16#include "clang/AST/RecursiveASTVisitor.h"
17#include "clang/Basic/Diagnostic.h"
18#include "clang/Frontend/CompilerInvocation.h"
19#include "llvm/ADT/ScopeExit.h"
20#include "llvm/Support/ScopedPrinter.h"
21#include "llvm/Support/raw_ostream.h"
30 ImportThunk =
testPath(
"import_thunk.h");
34 std::string ThunkContents =
"#import \"" + FullHeaderName +
"\"\n";
39 FS.
Files[ImportThunk] = ThunkContents;
49 Argv.push_back(
"-Xclang");
50 Argv.push_back(
"-undef");
55 Argv.push_back(
"-include");
60 Inputs.
CompileCommand.CommandLine.push_back(
"-fno-ms-compatibility");
65 Argv.push_back(FullFilename);
83 llvm::SmallString<128> ModuleCachePath;
84 if (llvm::sys::fs::createUniqueDirectory(
"module-cache", ModuleCachePath)) {
85 llvm::errs() <<
"Failed to create temp directory for module-cache";
88 CI.getHeaderSearchOpts().ModuleCachePath = ModuleCachePath.c_str();
92 if (!ModuleCachePath.empty()) {
93 if (llvm::sys::fs::remove_directories(ModuleCachePath)) {
94 llvm::errs() <<
"Failed to delete temp directory for module-cache";
100std::shared_ptr<const PreambleData>
106 assert(CI &&
"Failed to build compilation invocation.");
109 auto ModuleCacheDeleter = llvm::make_scope_exit(
112 true, PreambleCallback);
121 assert(CI &&
"Failed to build compilation invocation.");
124 auto ModuleCacheDeleter = llvm::make_scope_exit(
133 llvm::errs() <<
"Failed to build code:\n" <<
Code;
140 bool ErrorOk = [&,
this] {
141 llvm::StringLiteral Marker =
"error-ok";
142 if (llvm::StringRef(
Code).contains(Marker) ||
146 if (llvm::StringRef(KV.second).contains(Marker))
152 for (
const auto &D :
AST->getDiagnostics())
153 if (D.Severity >= DiagnosticsEngine::Error) {
155 <<
"TestTU failed to build (suppress with /*error-ok*/): \n"
156 << D <<
"\n\nFor code:\n"
161 return std::move(*
AST);
167 "null",
AST.getASTContext(),
AST.getPreprocessor(),
178 auto Idx = std::make_unique<FileIndex>(
true);
180 AST.getASTContext(),
AST.getPreprocessor(),
181 AST.getPragmaIncludes());
183 return std::move(Idx);
187 const Symbol *Result =
nullptr;
188 for (
const Symbol &S : Slab) {
189 if (QName != (S.Scope + S.Name).str())
192 llvm::errs() <<
"Multiple symbols named " << QName <<
":\n"
193 << *Result <<
"\n---\n"
195 assert(
false &&
"QName is not unique");
200 llvm::errs() <<
"No symbol named " << QName <<
" in "
201 << llvm::to_string(Slab);
202 assert(
false &&
"No symbol with QName");
210 std::vector<Decl *> ScopeToRestore;
214 : Ctx(
AST.getASTContext()), ScopeToRestore(Ctx.getTraversalScope()) {
215 Ctx.setTraversalScope({Ctx.getTranslationUnitDecl()});
221 auto &Ctx =
AST.getASTContext();
222 auto LookupDecl = [&Ctx](
const DeclContext &Scope,
223 llvm::StringRef Name) ->
const NamedDecl & {
224 auto LookupRes = Scope.lookup(DeclarationName(&Ctx.Idents.get(Name)));
225 assert(!LookupRes.empty() &&
"Lookup failed");
226 assert(LookupRes.isSingleResult() &&
"Lookup returned multiple results");
227 return *LookupRes.front();
230 const DeclContext *Scope = Ctx.getTranslationUnitDecl();
233 for (std::tie(Cur, Rest) = QName.split(
"::"); !Rest.empty();
234 std::tie(Cur, Rest) = Rest.split(
"::")) {
235 Scope = &cast<DeclContext>(LookupDecl(*Scope, Cur));
237 return LookupDecl(*Scope, Cur);
241 std::function<
bool(
const NamedDecl &)> Filter) {
243 struct Visitor : RecursiveASTVisitor<Visitor> {
245 llvm::SmallVector<const NamedDecl *, 1> Decls;
246 bool VisitNamedDecl(
const NamedDecl *ND) {
253 Visitor.TraverseDecl(
AST.getASTContext().getTranslationUnitDecl());
254 if (Visitor.Decls.size() != 1) {
255 llvm::errs() << Visitor.Decls.size() <<
" symbols matched.\n";
256 assert(Visitor.Decls.size() == 1);
258 return *Visitor.Decls.front();
263 if (
auto *ID = ND.getIdentifier())
264 if (ID->getName() == Name)
llvm::StringMap< std::string > Files
bool OverlayRealFileSystemForModules
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.
std::vector< Diag > take(const clang::tidy::ClangTidyContext *Tidy=nullptr)
An immutable symbol container that stores a set of symbols.
FIXME: Skip testing on windows temporarily due to the different escaping code mode.
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, SymbolOrigin Origin)
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)
std::function< void(CapturedASTCtx ASTCtx, std::shared_ptr< const include_cleaner::PragmaIncludes >)> PreambleParsedCallback
===– 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