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 "index/CanonicalIncludes.h" 29 #include "clang/Frontend/FrontendAction.h" 30 #include "clang/Lex/Preprocessor.h" 31 #include "clang/Tooling/Syntax/Tokens.h" 32 #include "llvm/ADT/ArrayRef.h" 33 #include "llvm/ADT/Optional.h" 34 #include "llvm/ADT/StringRef.h" 35 #include <memory> 36 #include <string> 37 #include <vector> 38 39 namespace clang { 40 class Sema; 41 namespace clangd { 42 class HeuristicResolver; 43 44 /// Stores and provides access to parsed AST. 45 class ParsedAST { 46 public: 47 /// Attempts to run Clang and store the parsed AST. 48 /// If \p Preamble is non-null it is reused during parsing. 49 /// This function does not check if preamble is valid to reuse. 50 static llvm::Optional<ParsedAST> 51 build(llvm::StringRef Filename, const ParseInputs &Inputs, 52 std::unique_ptr<clang::CompilerInvocation> CI, 53 llvm::ArrayRef<Diag> CompilerInvocationDiags, 54 std::shared_ptr<const PreambleData> Preamble); 55 56 ParsedAST(ParsedAST &&Other); 57 ParsedAST &operator=(ParsedAST &&Other); 58 59 ~ParsedAST(); 60 61 /// Note that the returned ast will not contain decls from the preamble that 62 /// were not deserialized during parsing. Clients should expect only decls 63 /// from the main file to be in the AST. 64 ASTContext &getASTContext(); 65 const ASTContext &getASTContext() const; 66 67 Sema &getSema(); 68 69 Preprocessor &getPreprocessor(); 70 std::shared_ptr<Preprocessor> getPreprocessorPtr(); 71 const Preprocessor &getPreprocessor() const; 72 getSourceManager()73 SourceManager &getSourceManager() { 74 return getASTContext().getSourceManager(); 75 } getSourceManager()76 const SourceManager &getSourceManager() const { 77 return getASTContext().getSourceManager(); 78 } 79 getLangOpts()80 const LangOptions &getLangOpts() const { 81 return getASTContext().getLangOpts(); 82 } 83 84 /// This function returns top-level decls present in the main file of the AST. 85 /// The result does not include the decls that come from the preamble. 86 /// (These should be const, but RecursiveASTVisitor requires Decl*). 87 ArrayRef<Decl *> getLocalTopLevelDecls(); 88 getDiagnostics()89 const llvm::Optional<std::vector<Diag>> &getDiagnostics() const { 90 return Diags; 91 } 92 93 /// Returns the estimated size of the AST and the accessory structures, in 94 /// bytes. Does not include the size of the preamble. 95 std::size_t getUsedBytes() const; 96 const IncludeStructure &getIncludeStructure() const; 97 const CanonicalIncludes &getCanonicalIncludes() const; 98 99 /// Gets all macro references (definition, expansions) present in the main 100 /// file, including those in the preamble region. 101 const MainFileMacros &getMacros() const; 102 /// Gets all pragma marks in the main file. 103 const std::vector<PragmaMark> &getMarks() const; 104 /// Tokens recorded while parsing the main file. 105 /// (!) does not have tokens from the preamble. getTokens()106 const syntax::TokenBuffer &getTokens() const { return Tokens; } 107 108 /// Returns the version of the ParseInputs this AST was built from. version()109 llvm::StringRef version() const { return Version; } 110 111 /// Returns the version of the ParseInputs used to build Preamble part of this 112 /// AST. Might be None if no Preamble is used. 113 llvm::Optional<llvm::StringRef> preambleVersion() const; 114 getHeuristicResolver()115 const HeuristicResolver *getHeuristicResolver() const { 116 return Resolver.get(); 117 } 118 119 private: 120 ParsedAST(llvm::StringRef Version, 121 std::shared_ptr<const PreambleData> Preamble, 122 std::unique_ptr<CompilerInstance> Clang, 123 std::unique_ptr<FrontendAction> Action, syntax::TokenBuffer Tokens, 124 MainFileMacros Macros, std::vector<PragmaMark> Marks, 125 std::vector<Decl *> LocalTopLevelDecls, 126 llvm::Optional<std::vector<Diag>> Diags, IncludeStructure Includes, 127 CanonicalIncludes CanonIncludes); 128 129 std::string Version; 130 // In-memory preambles must outlive the AST, it is important that this member 131 // goes before Clang and Action. 132 std::shared_ptr<const PreambleData> Preamble; 133 // We store an "incomplete" FrontendAction (i.e. no EndSourceFile was called 134 // on it) and CompilerInstance used to run it. That way we don't have to do 135 // complex memory management of all Clang structures on our own. (They are 136 // stored in CompilerInstance and cleaned up by 137 // FrontendAction.EndSourceFile). 138 std::unique_ptr<CompilerInstance> Clang; 139 std::unique_ptr<FrontendAction> Action; 140 /// Tokens recorded after the preamble finished. 141 /// - Includes all spelled tokens for the main file. 142 /// - Includes expanded tokens produced **after** preamble. 143 /// - Does not have spelled or expanded tokens for files from preamble. 144 syntax::TokenBuffer Tokens; 145 146 /// All macro definitions and expansions in the main file. 147 MainFileMacros Macros; 148 // Pragma marks in the main file. 149 std::vector<PragmaMark> Marks; 150 // Data, stored after parsing. None if AST was built with a stale preamble. 151 llvm::Optional<std::vector<Diag>> Diags; 152 // Top-level decls inside the current file. Not that this does not include 153 // top-level decls from the preamble. 154 std::vector<Decl *> LocalTopLevelDecls; 155 IncludeStructure Includes; 156 CanonicalIncludes CanonIncludes; 157 std::unique_ptr<HeuristicResolver> Resolver; 158 }; 159 160 } // namespace clangd 161 } // namespace clang 162 163 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_PARSEDAST_H 164