1 //===--- ParsedAST.h - Building translation units ----------------*- C++-*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file exposes building a file as if it were open in clangd, and defines 10 // the ParsedAST structure that holds the results. 11 // 12 // This is similar to a clang -fsyntax-only run that produces a clang AST, but 13 // we have several customizations: 14 // - preamble handling 15 // - capturing diagnostics for later access 16 // - running clang-tidy checks 17 // 18 //===----------------------------------------------------------------------===// 19 20 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_PARSEDAST_H 21 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_PARSEDAST_H 22 23 #include "CollectMacros.h" 24 #include "Compiler.h" 25 #include "Diagnostics.h" 26 #include "Headers.h" 27 #include "Preamble.h" 28 #include "clang-include-cleaner/Record.h" 29 #include "support/Path.h" 30 #include "clang/Frontend/FrontendAction.h" 31 #include "clang/Lex/Preprocessor.h" 32 #include "clang/Tooling/Syntax/Tokens.h" 33 #include "llvm/ADT/ArrayRef.h" 34 #include "llvm/ADT/StringRef.h" 35 #include <memory> 36 #include <optional> 37 #include <string> 38 #include <vector> 39 40 namespace clang { 41 class HeuristicResolver; 42 class Sema; 43 namespace clangd { 44 45 /// Stores and provides access to parsed AST. 46 class ParsedAST { 47 public: 48 /// Attempts to run Clang and store the parsed AST. 49 /// If \p Preamble is non-null it is reused during parsing. 50 /// This function does not check if preamble is valid to reuse. 51 static std::optional<ParsedAST> 52 build(llvm::StringRef Filename, const ParseInputs &Inputs, 53 std::unique_ptr<clang::CompilerInvocation> CI, 54 llvm::ArrayRef<Diag> CompilerInvocationDiags, 55 std::shared_ptr<const PreambleData> Preamble); 56 57 ParsedAST(ParsedAST &&Other); 58 ParsedAST &operator=(ParsedAST &&Other); 59 60 ~ParsedAST(); 61 62 ParsedAST(const ParsedAST &Other) = delete; 63 ParsedAST &operator=(const ParsedAST &Other) = delete; 64 65 /// Note that the returned ast will not contain decls from the preamble that 66 /// were not deserialized during parsing. Clients should expect only decls 67 /// from the main file to be in the AST. 68 ASTContext &getASTContext(); 69 const ASTContext &getASTContext() const; 70 71 Sema &getSema(); 72 73 Preprocessor &getPreprocessor(); 74 std::shared_ptr<Preprocessor> getPreprocessorPtr(); 75 const Preprocessor &getPreprocessor() const; 76 77 SourceManager &getSourceManager() { 78 return getASTContext().getSourceManager(); 79 } 80 const SourceManager &getSourceManager() const { 81 return getASTContext().getSourceManager(); 82 } 83 84 const LangOptions &getLangOpts() const { 85 return getASTContext().getLangOpts(); 86 } 87 88 /// This function returns top-level decls present in the main file of the AST. 89 /// The result does not include the decls that come from the preamble. 90 /// (These should be const, but RecursiveASTVisitor requires Decl*). 91 ArrayRef<Decl *> getLocalTopLevelDecls(); 92 ArrayRef<const Decl *> getLocalTopLevelDecls() const; 93 94 llvm::ArrayRef<Diag> getDiagnostics() const; 95 96 /// Returns the estimated size of the AST and the accessory structures, in 97 /// bytes. Does not include the size of the preamble. 98 std::size_t getUsedBytes() const; 99 const IncludeStructure &getIncludeStructure() const; 100 101 /// Gets all macro references (definition, expansions) present in the main 102 /// file, including those in the preamble region. 103 const MainFileMacros &getMacros() const; 104 /// Gets all pragma marks in the main file. 105 const std::vector<PragmaMark> &getMarks() const; 106 /// Tokens recorded while parsing the main file. 107 /// (!) does not have tokens from the preamble. 108 const syntax::TokenBuffer &getTokens() const { return Tokens; } 109 /// Returns the PramaIncludes for preamble + main file includes. 110 const include_cleaner::PragmaIncludes &getPragmaIncludes() const; 111 112 /// Returns the version of the ParseInputs this AST was built from. 113 llvm::StringRef version() const { return Version; } 114 115 /// Returns the path passed by the caller when building this AST. 116 PathRef tuPath() const { return TUPath; } 117 118 /// Returns the version of the ParseInputs used to build Preamble part of this 119 /// AST. Might be std::nullopt if no Preamble is used. 120 std::optional<llvm::StringRef> preambleVersion() const; 121 122 const HeuristicResolver *getHeuristicResolver() const { 123 return Resolver.get(); 124 } 125 126 private: 127 ParsedAST(PathRef TUPath, llvm::StringRef Version, 128 std::shared_ptr<const PreambleData> Preamble, 129 std::unique_ptr<CompilerInstance> Clang, 130 std::unique_ptr<FrontendAction> Action, syntax::TokenBuffer Tokens, 131 MainFileMacros Macros, std::vector<PragmaMark> Marks, 132 std::vector<Decl *> LocalTopLevelDecls, std::vector<Diag> Diags, 133 IncludeStructure Includes, include_cleaner::PragmaIncludes PI); 134 Path TUPath; 135 std::string Version; 136 // In-memory preambles must outlive the AST, it is important that this member 137 // goes before Clang and Action. 138 std::shared_ptr<const PreambleData> Preamble; 139 // We store an "incomplete" FrontendAction (i.e. no EndSourceFile was called 140 // on it) and CompilerInstance used to run it. That way we don't have to do 141 // complex memory management of all Clang structures on our own. (They are 142 // stored in CompilerInstance and cleaned up by 143 // FrontendAction.EndSourceFile). 144 std::unique_ptr<CompilerInstance> Clang; 145 std::unique_ptr<FrontendAction> Action; 146 /// Tokens recorded after the preamble finished. 147 /// - Includes all spelled tokens for the main file. 148 /// - Includes expanded tokens produced **after** preamble. 149 /// - Does not have spelled or expanded tokens for files from preamble. 150 syntax::TokenBuffer Tokens; 151 152 /// All macro definitions and expansions in the main file. 153 MainFileMacros Macros; 154 // Pragma marks in the main file. 155 std::vector<PragmaMark> Marks; 156 // Diags emitted while parsing this AST (including preamble and compiler 157 // invocation). 158 std::vector<Diag> Diags; 159 // Top-level decls inside the current file. Not that this does not include 160 // top-level decls from the preamble. 161 std::vector<Decl *> LocalTopLevelDecls; 162 IncludeStructure Includes; 163 include_cleaner::PragmaIncludes PI; 164 std::unique_ptr<HeuristicResolver> Resolver; 165 }; 166 167 } // namespace clangd 168 } // namespace clang 169 170 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_PARSEDAST_H 171