}
llvm::Optional<ParsedAST>
-ParsedAST::build(llvm::StringRef Version,
+ParsedAST::build(llvm::StringRef Filename, const ParseInputs &Inputs,
std::unique_ptr<clang::CompilerInvocation> CI,
llvm::ArrayRef<Diag> CompilerInvocationDiags,
- std::shared_ptr<const PreambleData> Preamble,
- std::unique_ptr<llvm::MemoryBuffer> Buffer,
- llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
- const SymbolIndex *Index, const ParseOptions &Opts) {
+ std::shared_ptr<const PreambleData> Preamble) {
+ trace::Span Tracer("BuildAST");
+ SPAN_ATTACH(Tracer, "File", Filename);
+
+ auto VFS = Inputs.FS;
+ if (Preamble && Preamble->StatCache)
+ VFS = Preamble->StatCache->getConsumingFS(std::move(VFS));
+ if (VFS->setCurrentWorkingDirectory(Inputs.CompileCommand.Directory)) {
+ log("Couldn't set working directory when building the preamble.");
+ // We proceed anyway, our lit-tests rely on results for non-existing working
+ // dirs.
+ }
+
assert(CI);
// Command-line parsing sets DisableFree to true by default, but we don't want
// to leak memory in clangd.
// Recovery expression currently only works for C++.
if (CI->getLangOpts()->CPlusPlus)
- CI->getLangOpts()->RecoveryAST = Opts.BuildRecoveryAST;
+ CI->getLangOpts()->RecoveryAST = Inputs.Opts.BuildRecoveryAST;
// This is on-by-default in windows to allow parsing SDK headers, but it
// breaks many features. Disable it for the main-file (not preamble).
CI->getLangOpts()->DelayedTemplateParsing = false;
StoreDiags ASTDiags;
- std::string Content = std::string(Buffer->getBuffer());
- std::string Filename =
- std::string(Buffer->getBufferIdentifier()); // Absolute.
- auto Clang = prepareCompilerInstance(std::move(CI), PreamblePCH,
- std::move(Buffer), VFS, ASTDiags);
+ auto Clang = prepareCompilerInstance(
+ std::move(CI), PreamblePCH,
+ llvm::MemoryBuffer::getMemBufferCopy(Inputs.Contents, Filename), VFS,
+ ASTDiags);
if (!Clang)
return None;
{
trace::Span Tracer("ClangTidyInit");
dlog("ClangTidy configuration for file {0}: {1}", Filename,
- tidy::configurationAsText(Opts.ClangTidyOpts));
+ tidy::configurationAsText(Inputs.Opts.ClangTidyOpts));
tidy::ClangTidyCheckFactories CTFactories;
for (const auto &E : tidy::ClangTidyModuleRegistry::entries())
E.instantiate()->addCheckFactories(CTFactories);
CTContext.emplace(std::make_unique<tidy::DefaultOptionsProvider>(
- tidy::ClangTidyGlobalOptions(), Opts.ClangTidyOpts));
+ tidy::ClangTidyGlobalOptions(), Inputs.Opts.ClangTidyOpts));
CTContext->setDiagnosticsEngine(&Clang->getDiagnostics());
CTContext->setASTContext(&Clang->getASTContext());
CTContext->setCurrentFile(Filename);
// (e.g. incomplete type) and attach include insertion fixes to diagnostics.
llvm::Optional<IncludeFixer> FixIncludes;
auto BuildDir = VFS->getCurrentWorkingDirectory();
- if (Opts.SuggestMissingIncludes && Index && !BuildDir.getError()) {
- auto Style = getFormatStyleForFile(Filename, Content, VFS.get());
+ if (Inputs.Opts.SuggestMissingIncludes && Inputs.Index &&
+ !BuildDir.getError()) {
+ auto Style = getFormatStyleForFile(Filename, Inputs.Contents, VFS.get());
auto Inserter = std::make_shared<IncludeInserter>(
- Filename, Content, Style, BuildDir.get(),
+ Filename, Inputs.Contents, Style, BuildDir.get(),
&Clang->getPreprocessor().getHeaderSearchInfo());
if (Preamble) {
for (const auto &Inc : Preamble->Includes.MainFileIncludes)
Inserter->addExisting(Inc);
}
- FixIncludes.emplace(Filename, Inserter, *Index,
+ FixIncludes.emplace(Filename, Inserter, *Inputs.Index,
/*IndexRequestLimit=*/5);
ASTDiags.contributeFixes([&FixIncludes](DiagnosticsEngine::Level DiagLevl,
const clang::Diagnostic &Info) {
std::vector<Diag> D = ASTDiags.take(CTContext.getPointer());
Diags.insert(Diags.end(), D.begin(), D.end());
}
- return ParsedAST(Version, std::move(Preamble), std::move(Clang),
+ return ParsedAST(Inputs.Version, std::move(Preamble), std::move(Clang),
std::move(Action), std::move(Tokens), std::move(Macros),
std::move(ParsedDecls), std::move(Diags),
std::move(Includes), std::move(CanonIncludes));
assert(this->Action);
}
-llvm::Optional<ParsedAST>
-buildAST(PathRef FileName, std::unique_ptr<CompilerInvocation> Invocation,
- llvm::ArrayRef<Diag> CompilerInvocationDiags,
- const ParseInputs &Inputs,
- std::shared_ptr<const PreambleData> Preamble) {
- trace::Span Tracer("BuildAST");
- SPAN_ATTACH(Tracer, "File", FileName);
-
- auto VFS = Inputs.FS;
- if (Preamble && Preamble->StatCache)
- VFS = Preamble->StatCache->getConsumingFS(std::move(VFS));
- if (VFS->setCurrentWorkingDirectory(Inputs.CompileCommand.Directory)) {
- log("Couldn't set working directory when building the preamble.");
- // We proceed anyway, our lit-tests rely on results for non-existing working
- // dirs.
- }
-
- return ParsedAST::build(
- Inputs.Version, std::move(Invocation), CompilerInvocationDiags, Preamble,
- llvm::MemoryBuffer::getMemBufferCopy(Inputs.Contents, FileName),
- std::move(VFS), Inputs.Index, Inputs.Opts);
-}
-
} // namespace clangd
} // namespace clang
// - capturing diagnostics for later access
// - running clang-tidy checks checks
//
-//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_PARSEDAST_H
/// Stores and provides access to parsed AST.
class ParsedAST {
public:
- /// Attempts to run Clang and store parsed AST. If \p Preamble is non-null
- /// it is reused during parsing.
+ /// 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 Version, std::unique_ptr<clang::CompilerInvocation> CI,
+ build(llvm::StringRef Filename, const ParseInputs &Inputs,
+ std::unique_ptr<clang::CompilerInvocation> CI,
llvm::ArrayRef<Diag> CompilerInvocationDiags,
- std::shared_ptr<const PreambleData> Preamble,
- std::unique_ptr<llvm::MemoryBuffer> Buffer,
- llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
- const SymbolIndex *Index, const ParseOptions &Opts);
+ std::shared_ptr<const PreambleData> Preamble);
ParsedAST(ParsedAST &&Other);
ParsedAST &operator=(ParsedAST &&Other);
CanonicalIncludes CanonIncludes;
};
-/// Build an AST from provided user inputs. This function does not check if
-/// preamble can be reused, as this function expects that \p Preamble is the
-/// result of calling buildPreamble.
-llvm::Optional<ParsedAST>
-buildAST(PathRef FileName, std::unique_ptr<CompilerInvocation> Invocation,
- llvm::ArrayRef<Diag> CompilerInvocationDiags,
- const ParseInputs &Inputs,
- std::shared_ptr<const PreambleData> Preamble);
-
/// For testing/debugging purposes. Note that this method deserializes all
/// unserialized Decls, so use with care.
void dumpAST(ParsedAST &AST, llvm::raw_ostream &OS);
// return a compatible preamble as ASTWorker::update blocks.
llvm::Optional<ParsedAST> NewAST;
if (Invocation) {
- NewAST = buildAST(FileName, std::move(Invocation),
- CompilerInvocationDiagConsumer.take(), FileInputs,
- getPossiblyStalePreamble());
+ NewAST = ParsedAST::build(FileName, FileInputs, std::move(Invocation),
+ CompilerInvocationDiagConsumer.take(),
+ getPossiblyStalePreamble());
++ASTBuildCount;
}
AST = NewAST ? std::make_unique<ParsedAST>(std::move(*NewAST)) : nullptr;
llvm::Optional<std::unique_ptr<ParsedAST>> AST = IdleASTs.take(this);
if (!AST || !InputsAreLatest) {
auto RebuildStartTime = DebouncePolicy::clock::now();
- llvm::Optional<ParsedAST> NewAST = buildAST(
- FileName, std::move(Invocation), CIDiags, Inputs, LatestPreamble);
+ llvm::Optional<ParsedAST> NewAST = ParsedAST::build(
+ FileName, Inputs, std::move(Invocation), CIDiags, LatestPreamble);
auto RebuildDuration = DebouncePolicy::clock::now() - RebuildStartTime;
++ASTBuildCount;
// Try to record the AST-build time, to inform future update debouncing.