15#include "clang/AST/RecursiveASTVisitor.h"
16#include "clang/Basic/Diagnostic.h"
17#include "clang/Frontend/CompilerInvocation.h"
18#include "llvm/ADT/ScopeExit.h"
19#include "llvm/Support/ScopedPrinter.h"
20#include "llvm/Support/raw_ostream.h"
29 ImportThunk =
testPath(
"import_thunk.h");
33 std::string ThunkContents =
"#import \"" + FullHeaderName +
"\"\n";
36 FS.Files[FullFilename] =
Code;
38 FS.Files[ImportThunk] = ThunkContents;
42 auto &Argv = Inputs.CompileCommand.CommandLine;
48 Argv.push_back(
"-Xclang");
49 Argv.push_back(
"-undef");
54 Argv.push_back(
"-include");
59 Inputs.CompileCommand.CommandLine.push_back(
"-fno-ms-compatibility");
64 Argv.push_back(FullFilename);
67 Mangler(Inputs.CompileCommand, FullFilename);
68 Inputs.CompileCommand.Filename = FullFilename;
69 Inputs.CompileCommand.Directory =
testRoot();
70 Inputs.Contents =
Code;
72 FS.OverlayRealFileSystemForModules =
true;
82 llvm::SmallString<128> ModuleCachePath;
83 if (llvm::sys::fs::createUniqueDirectory(
"module-cache", ModuleCachePath)) {
84 llvm::errs() <<
"Failed to create temp directory for module-cache";
87 CI.getHeaderSearchOpts().ModuleCachePath = ModuleCachePath.c_str();
91 if (!ModuleCachePath.empty()) {
92 if (llvm::sys::fs::remove_directories(ModuleCachePath)) {
93 llvm::errs() <<
"Failed to delete temp directory for module-cache";
99std::shared_ptr<const PreambleData>
105 assert(
CI &&
"Failed to build compilation invocation.");
108 auto ModuleCacheDeleter = llvm::make_scope_exit(
111 true, PreambleCallback);
120 assert(
CI &&
"Failed to build compilation invocation.");
123 auto ModuleCacheDeleter = llvm::make_scope_exit(
132 llvm::errs() <<
"Failed to build code:\n" <<
Code;
135 assert(
AST->getDiagnostics() &&
136 "TestTU should always build an AST with a fresh Preamble");
141 bool ErrorOk = [&,
this] {
142 llvm::StringLiteral Marker =
"error-ok";
143 if (llvm::StringRef(
Code).contains(Marker) ||
147 if (llvm::StringRef(KV.second).contains(Marker))
153 for (
const auto &D : *
AST->getDiagnostics())
154 if (D.Severity >= DiagnosticsEngine::Error) {
156 <<
"TestTU failed to build (suppress with /*error-ok*/): \n"
157 << D <<
"\n\nFor code:\n"
162 return std::move(*
AST);
168 AST.getPreprocessor(),
169 AST.getCanonicalIncludes()));
179 auto Idx = std::make_unique<FileIndex>();
181 AST.getASTContext(),
AST.getPreprocessor(),
182 AST.getCanonicalIncludes());
184 return std::move(Idx);
188 const Symbol *Result =
nullptr;
189 for (
const Symbol &S : Slab) {
190 if (QName != (S.Scope + S.Name).str())
193 llvm::errs() <<
"Multiple symbols named " << QName <<
":\n"
194 << *Result <<
"\n---\n"
196 assert(
false &&
"QName is not unique");
201 llvm::errs() <<
"No symbol named " << QName <<
" in "
202 << llvm::to_string(Slab);
203 assert(
false &&
"No symbol with QName");
211 std::vector<Decl *> ScopeToRestore;
215 : Ctx(
AST.getASTContext()), ScopeToRestore(Ctx.getTraversalScope()) {
216 Ctx.setTraversalScope({Ctx.getTranslationUnitDecl()});
222 auto &Ctx =
AST.getASTContext();
223 auto LookupDecl = [&Ctx](
const DeclContext &Scope,
224 llvm::StringRef
Name) ->
const NamedDecl & {
225 auto LookupRes = Scope.lookup(DeclarationName(&Ctx.Idents.get(
Name)));
226 assert(!LookupRes.empty() &&
"Lookup failed");
227 assert(LookupRes.isSingleResult() &&
"Lookup returned multiple results");
228 return *LookupRes.front();
231 const DeclContext *Scope = Ctx.getTranslationUnitDecl();
234 for (std::tie(Cur, Rest) = QName.split(
"::"); !Rest.empty();
235 std::tie(Cur, Rest) = Rest.split(
"::")) {
236 Scope = &cast<DeclContext>(LookupDecl(*Scope, Cur));
238 return LookupDecl(*Scope, Cur);
242 std::function<
bool(
const NamedDecl &)> Filter) {
244 struct Visitor : RecursiveASTVisitor<Visitor> {
246 llvm::SmallVector<const NamedDecl *, 1> Decls;
247 bool VisitNamedDecl(
const NamedDecl *ND) {
254 Visitor.TraverseDecl(
AST.getASTContext().getTranslationUnitDecl());
255 if (Visitor.Decls.size() != 1) {
256 llvm::errs() << Visitor.Decls.size() <<
" symbols matched.\n";
257 assert(Visitor.Decls.size() == 1);
259 return *Visitor.Decls.front();
264 if (
auto *ID = ND.getIdentifier())
265 if (ID->getName() ==
Name)
std::unique_ptr< CompilerInvocation > CI
Stores and provides access to parsed AST.
static std::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)
Attempts to run Clang and store the parsed AST.
An efficient structure of storing large set of symbol references in memory.
StoreDiags collects the diagnostics that can later be reported by clangd.
An immutable symbol container that stores a set of symbols.
const NamedDecl & findDecl(ParsedAST &AST, llvm::StringRef QName)
std::unique_ptr< CompilerInvocation > buildCompilerInvocation(const ParseInputs &Inputs, clang::DiagnosticConsumer &D, std::vector< std::string > *CC1Args)
Builds compiler invocation that could be used to build AST or preamble.
SlabTuple indexMainDecls(ParsedAST &AST)
Retrieves symbols and refs of local top level decls in AST (i.e.
std::string testPath(PathRef File, llvm::sys::path::Style Style)
std::shared_ptr< const PreambleData > buildPreamble(PathRef FileName, CompilerInvocation CI, const ParseInputs &Inputs, bool StoreInMemory, PreambleParsedCallback PreambleCallback, PreambleBuildStats *Stats)
Build a preamble for the new inputs unless an old one can be reused.
const NamedDecl & findUnqualifiedDecl(ParsedAST &AST, llvm::StringRef Name)
void initializeModuleCache(CompilerInvocation &CI)
std::function< void(ASTContext &, Preprocessor &, const CanonicalIncludes &)> PreambleParsedCallback
const Symbol & findSymbol(const SymbolSlab &Slab, llvm::StringRef QName)
SlabTuple indexHeaderSymbols(llvm::StringRef Version, ASTContext &AST, Preprocessor &PP, const CanonicalIncludes &Includes)
Index declarations from AST and macros from PP that are declared in included headers.
void deleteModuleCache(const std::string ModuleCachePath)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
static CommandMangler forTests()
The class presents a C++ symbol, e.g.
std::vector< std::string > ExtraArgs
TidyProvider ClangTidyProvider
ParseInputs inputs(MockFS &FS) const
RefSlab headerRefs() const
std::string HeaderFilename
SymbolSlab headerSymbols() const
std::shared_ptr< const PreambleData > preamble(PreambleParsedCallback PreambleCallback=nullptr) const
bool OverlayRealFileSystemForModules
const SymbolIndex * ExternalIndex
llvm::StringMap< std::string > AdditionalFiles
FeatureModuleSet * FeatureModules
std::unique_ptr< SymbolIndex > index() const