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;
139 bool ErrorOk = [&,
this] {
140 llvm::StringLiteral Marker =
"error-ok";
141 if (llvm::StringRef(
Code).contains(Marker) ||
145 if (llvm::StringRef(KV.second).contains(Marker))
151 for (
const auto &D :
AST->getDiagnostics())
152 if (D.Severity >= DiagnosticsEngine::Error) {
154 <<
"TestTU failed to build (suppress with /*error-ok*/): \n"
155 << D <<
"\n\nFor code:\n"
160 return std::move(*
AST);
166 "null",
AST.getASTContext(),
AST.getPreprocessor(),
167 AST.getPragmaIncludes()));
177 auto Idx = std::make_unique<FileIndex>();
179 AST.getASTContext(),
AST.getPreprocessor(),
180 AST.getPragmaIncludes());
182 return std::move(Idx);
186 const Symbol *Result =
nullptr;
187 for (
const Symbol &S : Slab) {
188 if (QName != (S.Scope + S.Name).str())
191 llvm::errs() <<
"Multiple symbols named " << QName <<
":\n"
192 << *Result <<
"\n---\n"
194 assert(
false &&
"QName is not unique");
199 llvm::errs() <<
"No symbol named " << QName <<
" in "
200 << llvm::to_string(Slab);
201 assert(
false &&
"No symbol with QName");
209 std::vector<Decl *> ScopeToRestore;
213 : Ctx(
AST.getASTContext()), ScopeToRestore(Ctx.getTraversalScope()) {
214 Ctx.setTraversalScope({Ctx.getTranslationUnitDecl()});
220 auto &Ctx =
AST.getASTContext();
221 auto LookupDecl = [&Ctx](
const DeclContext &Scope,
222 llvm::StringRef
Name) ->
const NamedDecl & {
223 auto LookupRes = Scope.lookup(DeclarationName(&Ctx.Idents.get(
Name)));
224 assert(!LookupRes.empty() &&
"Lookup failed");
225 assert(LookupRes.isSingleResult() &&
"Lookup returned multiple results");
226 return *LookupRes.front();
229 const DeclContext *Scope = Ctx.getTranslationUnitDecl();
232 for (std::tie(Cur, Rest) = QName.split(
"::"); !Rest.empty();
233 std::tie(Cur, Rest) = Rest.split(
"::")) {
234 Scope = &cast<DeclContext>(LookupDecl(*Scope, Cur));
236 return LookupDecl(*Scope, Cur);
240 std::function<
bool(
const NamedDecl &)> Filter) {
242 struct Visitor : RecursiveASTVisitor<Visitor> {
244 llvm::SmallVector<const NamedDecl *, 1> Decls;
245 bool VisitNamedDecl(
const NamedDecl *ND) {
252 Visitor.TraverseDecl(
AST.getASTContext().getTranslationUnitDecl());
253 if (Visitor.Decls.size() != 1) {
254 llvm::errs() << Visitor.Decls.size() <<
" symbols matched.\n";
255 assert(Visitor.Decls.size() == 1);
257 return *Visitor.Decls.front();
262 if (
auto *
ID = ND.getIdentifier())
263 if (
ID->getName() ==
Name)
llvm::SmallString< 256U > 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.
std::function< void(CapturedASTCtx ASTCtx, std::shared_ptr< const include_cleaner::PragmaIncludes >)> PreambleParsedCallback
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.
SlabTuple indexHeaderSymbols(llvm::StringRef Version, ASTContext &AST, Preprocessor &PP, const include_cleaner::PragmaIncludes &PI)
Index declarations from AST and macros from PP that are declared in included headers.
const NamedDecl & findUnqualifiedDecl(ParsedAST &AST, llvm::StringRef Name)
void initializeModuleCache(CompilerInvocation &CI)
const Symbol & findSymbol(const SymbolSlab &Slab, llvm::StringRef QName)
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