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 |
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 Sema; |
42 | namespace clangd { |
43 | class HeuristicResolver; |
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 | /// Note that the returned ast will not contain decls from the preamble that |
63 | /// were not deserialized during parsing. Clients should expect only decls |
64 | /// from the main file to be in the AST. |
65 | ASTContext &getASTContext(); |
66 | const ASTContext &getASTContext() const; |
67 | |
68 | Sema &getSema(); |
69 | |
70 | Preprocessor &getPreprocessor(); |
71 | std::shared_ptr<Preprocessor> getPreprocessorPtr(); |
72 | const Preprocessor &getPreprocessor() const; |
73 | |
74 | SourceManager &getSourceManager() { |
75 | return getASTContext().getSourceManager(); |
76 | } |
77 | const SourceManager &getSourceManager() const { |
78 | return getASTContext().getSourceManager(); |
79 | } |
80 | |
81 | const LangOptions &getLangOpts() const { |
82 | return getASTContext().getLangOpts(); |
83 | } |
84 | |
85 | /// This function returns top-level decls present in the main file of the AST. |
86 | /// The result does not include the decls that come from the preamble. |
87 | /// (These should be const, but RecursiveASTVisitor requires Decl*). |
88 | ArrayRef<Decl *> getLocalTopLevelDecls(); |
89 | ArrayRef<const Decl *> getLocalTopLevelDecls() const; |
90 | |
91 | llvm::ArrayRef<Diag> getDiagnostics() const; |
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 | |
98 | /// Gets all macro references (definition, expansions) present in the main |
99 | /// file, including those in the preamble region. |
100 | const MainFileMacros &getMacros() const; |
101 | /// Gets all pragma marks in the main file. |
102 | const std::vector<PragmaMark> &getMarks() const; |
103 | /// Tokens recorded while parsing the main file. |
104 | /// (!) does not have tokens from the preamble. |
105 | const syntax::TokenBuffer &getTokens() const { return Tokens; } |
106 | /// Returns the PramaIncludes for preamble + main file includes. |
107 | const include_cleaner::PragmaIncludes &getPragmaIncludes() const; |
108 | |
109 | /// Returns the version of the ParseInputs this AST was built from. |
110 | llvm::StringRef version() const { return Version; } |
111 | |
112 | /// Returns the path passed by the caller when building this AST. |
113 | PathRef tuPath() const { return TUPath; } |
114 | |
115 | /// Returns the version of the ParseInputs used to build Preamble part of this |
116 | /// AST. Might be std::nullopt if no Preamble is used. |
117 | std::optional<llvm::StringRef> preambleVersion() const; |
118 | |
119 | const HeuristicResolver *getHeuristicResolver() const { |
120 | return Resolver.get(); |
121 | } |
122 | |
123 | private: |
124 | ParsedAST(PathRef TUPath, llvm::StringRef Version, |
125 | std::shared_ptr<const PreambleData> Preamble, |
126 | std::unique_ptr<CompilerInstance> Clang, |
127 | std::unique_ptr<FrontendAction> Action, syntax::TokenBuffer Tokens, |
128 | MainFileMacros Macros, std::vector<PragmaMark> Marks, |
129 | std::vector<Decl *> LocalTopLevelDecls, std::vector<Diag> Diags, |
130 | IncludeStructure Includes, include_cleaner::PragmaIncludes PI); |
131 | Path TUPath; |
132 | std::string Version; |
133 | // In-memory preambles must outlive the AST, it is important that this member |
134 | // goes before Clang and Action. |
135 | std::shared_ptr<const PreambleData> Preamble; |
136 | // We store an "incomplete" FrontendAction (i.e. no EndSourceFile was called |
137 | // on it) and CompilerInstance used to run it. That way we don't have to do |
138 | // complex memory management of all Clang structures on our own. (They are |
139 | // stored in CompilerInstance and cleaned up by |
140 | // FrontendAction.EndSourceFile). |
141 | std::unique_ptr<CompilerInstance> Clang; |
142 | std::unique_ptr<FrontendAction> Action; |
143 | /// Tokens recorded after the preamble finished. |
144 | /// - Includes all spelled tokens for the main file. |
145 | /// - Includes expanded tokens produced **after** preamble. |
146 | /// - Does not have spelled or expanded tokens for files from preamble. |
147 | syntax::TokenBuffer Tokens; |
148 | |
149 | /// All macro definitions and expansions in the main file. |
150 | MainFileMacros Macros; |
151 | // Pragma marks in the main file. |
152 | std::vector<PragmaMark> Marks; |
153 | // Diags emitted while parsing this AST (including preamble and compiler |
154 | // invocation). |
155 | std::vector<Diag> Diags; |
156 | // Top-level decls inside the current file. Not that this does not include |
157 | // top-level decls from the preamble. |
158 | std::vector<Decl *> LocalTopLevelDecls; |
159 | IncludeStructure Includes; |
160 | include_cleaner::PragmaIncludes PI; |
161 | std::unique_ptr<HeuristicResolver> Resolver; |
162 | }; |
163 | |
164 | } // namespace clangd |
165 | } // namespace clang |
166 | |
167 | #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_PARSEDAST_H |
168 | |