| //===--- ParsedAST.h - Building translation units ----------------*- C++-*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file exposes building a file as if it were open in clangd, and defines |
| // the ParsedAST structure that holds the results. |
| // |
| // This is similar to a clang -fsyntax-only run that produces a clang AST, but |
| // we have several customizations: |
| // - preamble handling |
| // - capturing diagnostics for later access |
| // - running clang-tidy checks |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_PARSEDAST_H |
| #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_PARSEDAST_H |
| |
| #include "CollectMacros.h" |
| #include "Compiler.h" |
| #include "Diagnostics.h" |
| #include "Headers.h" |
| #include "Preamble.h" |
| #include "index/CanonicalIncludes.h" |
| #include "support/Path.h" |
| #include "clang/Frontend/FrontendAction.h" |
| #include "clang/Frontend/PrecompiledPreamble.h" |
| #include "clang/Lex/Preprocessor.h" |
| #include "clang/Tooling/CompilationDatabase.h" |
| #include "clang/Tooling/Syntax/Tokens.h" |
| #include "llvm/ADT/ArrayRef.h" |
| #include "llvm/ADT/None.h" |
| #include "llvm/ADT/Optional.h" |
| #include "llvm/ADT/StringRef.h" |
| #include <memory> |
| #include <string> |
| #include <vector> |
| |
| namespace clang { |
| namespace clangd { |
| class HeuristicResolver; |
| class SymbolIndex; |
| |
| /// Stores and provides access to parsed AST. |
| class ParsedAST { |
| public: |
| /// Attempts to run Clang and store the parsed AST. |
| /// If \p Preamble is non-null it is reused during parsing. |
| /// This function does not check if preamble is valid to reuse. |
| static llvm::Optional<ParsedAST> |
| build(llvm::StringRef Filename, const ParseInputs &Inputs, |
| std::unique_ptr<clang::CompilerInvocation> CI, |
| llvm::ArrayRef<Diag> CompilerInvocationDiags, |
| std::shared_ptr<const PreambleData> Preamble); |
| |
| ParsedAST(ParsedAST &&Other); |
| ParsedAST &operator=(ParsedAST &&Other); |
| |
| ~ParsedAST(); |
| |
| /// Note that the returned ast will not contain decls from the preamble that |
| /// were not deserialized during parsing. Clients should expect only decls |
| /// from the main file to be in the AST. |
| ASTContext &getASTContext(); |
| const ASTContext &getASTContext() const; |
| |
| Preprocessor &getPreprocessor(); |
| std::shared_ptr<Preprocessor> getPreprocessorPtr(); |
| const Preprocessor &getPreprocessor() const; |
| |
| SourceManager &getSourceManager() { |
| return getASTContext().getSourceManager(); |
| } |
| const SourceManager &getSourceManager() const { |
| return getASTContext().getSourceManager(); |
| } |
| |
| const LangOptions &getLangOpts() const { |
| return getASTContext().getLangOpts(); |
| } |
| |
| /// This function returns top-level decls present in the main file of the AST. |
| /// The result does not include the decls that come from the preamble. |
| /// (These should be const, but RecursiveASTVisitor requires Decl*). |
| ArrayRef<Decl *> getLocalTopLevelDecls(); |
| |
| const llvm::Optional<std::vector<Diag>> &getDiagnostics() const { |
| return Diags; |
| } |
| |
| /// Returns the estimated size of the AST and the accessory structures, in |
| /// bytes. Does not include the size of the preamble. |
| std::size_t getUsedBytes() const; |
| const IncludeStructure &getIncludeStructure() const; |
| const CanonicalIncludes &getCanonicalIncludes() const; |
| |
| /// Gets all macro references (definition, expansions) present in the main |
| /// file, including those in the preamble region. |
| const MainFileMacros &getMacros() const; |
| /// Gets all pragma marks in the main file. |
| const std::vector<PragmaMark> &getMarks() const; |
| /// Tokens recorded while parsing the main file. |
| /// (!) does not have tokens from the preamble. |
| const syntax::TokenBuffer &getTokens() const { return Tokens; } |
| |
| /// Returns the version of the ParseInputs this AST was built from. |
| llvm::StringRef version() const { return Version; } |
| |
| /// Returns the version of the ParseInputs used to build Preamble part of this |
| /// AST. Might be None if no Preamble is used. |
| llvm::Optional<llvm::StringRef> preambleVersion() const; |
| |
| const HeuristicResolver *getHeuristicResolver() const { |
| return Resolver.get(); |
| } |
| |
| private: |
| ParsedAST(llvm::StringRef Version, |
| std::shared_ptr<const PreambleData> Preamble, |
| std::unique_ptr<CompilerInstance> Clang, |
| std::unique_ptr<FrontendAction> Action, syntax::TokenBuffer Tokens, |
| MainFileMacros Macros, std::vector<PragmaMark> Marks, |
| std::vector<Decl *> LocalTopLevelDecls, |
| llvm::Optional<std::vector<Diag>> Diags, IncludeStructure Includes, |
| CanonicalIncludes CanonIncludes); |
| |
| std::string Version; |
| // In-memory preambles must outlive the AST, it is important that this member |
| // goes before Clang and Action. |
| std::shared_ptr<const PreambleData> Preamble; |
| // We store an "incomplete" FrontendAction (i.e. no EndSourceFile was called |
| // on it) and CompilerInstance used to run it. That way we don't have to do |
| // complex memory management of all Clang structures on our own. (They are |
| // stored in CompilerInstance and cleaned up by |
| // FrontendAction.EndSourceFile). |
| std::unique_ptr<CompilerInstance> Clang; |
| std::unique_ptr<FrontendAction> Action; |
| /// Tokens recorded after the preamble finished. |
| /// - Includes all spelled tokens for the main file. |
| /// - Includes expanded tokens produced **after** preamble. |
| /// - Does not have spelled or expanded tokens for files from preamble. |
| syntax::TokenBuffer Tokens; |
| |
| /// All macro definitions and expansions in the main file. |
| MainFileMacros Macros; |
| // Pragma marks in the main file. |
| std::vector<PragmaMark> Marks; |
| // Data, stored after parsing. None if AST was built with a stale preamble. |
| llvm::Optional<std::vector<Diag>> Diags; |
| // Top-level decls inside the current file. Not that this does not include |
| // top-level decls from the preamble. |
| std::vector<Decl *> LocalTopLevelDecls; |
| IncludeStructure Includes; |
| CanonicalIncludes CanonIncludes; |
| std::unique_ptr<HeuristicResolver> Resolver; |
| }; |
| |
| } // namespace clangd |
| } // namespace clang |
| |
| #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_PARSEDAST_H |