summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--clang-tools-extra/clangd/ClangdServer.cpp15
-rw-r--r--clang-tools-extra/clangd/ClangdUnit.cpp25
-rw-r--r--clang-tools-extra/clangd/ClangdUnit.h8
-rw-r--r--clang-tools-extra/clangd/TUScheduler.cpp6
-rw-r--r--clang-tools-extra/clangd/TUScheduler.h4
-rw-r--r--clang-tools-extra/clangd/index/FileIndex.cpp19
-rw-r--r--clang-tools-extra/clangd/index/FileIndex.h9
-rw-r--r--clang-tools-extra/unittests/clangd/FileIndexTests.cpp63
-rw-r--r--clang-tools-extra/unittests/clangd/TUSchedulerTests.cpp8
-rw-r--r--clang-tools-extra/unittests/clangd/TestTU.cpp2
10 files changed, 119 insertions, 40 deletions
diff --git a/clang-tools-extra/clangd/ClangdServer.cpp b/clang-tools-extra/clangd/ClangdServer.cpp
index 6d22bcdbeea..0512bca61de 100644
--- a/clang-tools-extra/clangd/ClangdServer.cpp
+++ b/clang-tools-extra/clangd/ClangdServer.cpp
@@ -17,6 +17,7 @@
#include "clang/Format/Format.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Lex/Preprocessor.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "clang/Tooling/Refactoring/RefactoringResultConsumer.h"
#include "clang/Tooling/Refactoring/Rename/RenamingAction.h"
@@ -92,12 +93,14 @@ ClangdServer::ClangdServer(GlobalCompilationDatabase &CDB,
// is parsed.
// FIXME(ioeric): this can be slow and we may be able to index on less
// critical paths.
- WorkScheduler(Opts.AsyncThreadsCount, Opts.StorePreamblesInMemory,
- FileIdx
- ? [this](PathRef Path,
- ParsedAST *AST) { FileIdx->update(Path, AST); }
- : ASTParsedCallback(),
- Opts.UpdateDebounce) {
+ WorkScheduler(
+ Opts.AsyncThreadsCount, Opts.StorePreamblesInMemory,
+ FileIdx
+ ? [this](PathRef Path, ASTContext &AST,
+ std::shared_ptr<Preprocessor>
+ PP) { FileIdx->update(Path, &AST, std::move(PP)); }
+ : PreambleParsedCallback(),
+ Opts.UpdateDebounce) {
if (FileIdx && Opts.StaticIndex) {
MergedIndex = mergeIndex(FileIdx.get(), Opts.StaticIndex);
Index = MergedIndex.get();
diff --git a/clang-tools-extra/clangd/ClangdUnit.cpp b/clang-tools-extra/clangd/ClangdUnit.cpp
index eb2fc184ccf..41f2df3669e 100644
--- a/clang-tools-extra/clangd/ClangdUnit.cpp
+++ b/clang-tools-extra/clangd/ClangdUnit.cpp
@@ -13,6 +13,8 @@
#include "Logger.h"
#include "SourceCode.h"
#include "Trace.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Basic/LangOptions.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendActions.h"
@@ -25,7 +27,6 @@
#include "clang/Sema/Sema.h"
#include "clang/Serialization/ASTWriter.h"
#include "clang/Tooling/CompilationDatabase.h"
-#include "clang/Basic/LangOptions.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/CrashRecoveryContext.h"
@@ -86,6 +87,9 @@ private:
class CppFilePreambleCallbacks : public PreambleCallbacks {
public:
+ CppFilePreambleCallbacks(PathRef File, PreambleParsedCallback ParsedCallback)
+ : File(File), ParsedCallback(ParsedCallback) {}
+
std::vector<serialization::DeclID> takeTopLevelDeclIDs() {
return std::move(TopLevelDeclIDs);
}
@@ -102,6 +106,13 @@ public:
}
}
+ void AfterExecute(CompilerInstance &CI) override {
+ if (!ParsedCallback)
+ return;
+ trace::Span Tracer("Running PreambleCallback");
+ ParsedCallback(File, CI.getASTContext(), CI.getPreprocessorPtr());
+ }
+
void HandleTopLevelDecl(DeclGroupRef DG) override {
for (Decl *D : DG) {
if (isa<ObjCMethodDecl>(D))
@@ -122,6 +133,8 @@ public:
}
private:
+ PathRef File;
+ PreambleParsedCallback ParsedCallback;
std::vector<Decl *> TopLevelDecls;
std::vector<serialization::DeclID> TopLevelDeclIDs;
std::vector<Inclusion> Inclusions;
@@ -277,9 +290,9 @@ ParsedAST::ParsedAST(std::shared_ptr<const PreambleData> Preamble,
CppFile::CppFile(PathRef FileName, bool StorePreamblesInMemory,
std::shared_ptr<PCHContainerOperations> PCHs,
- ASTParsedCallback ASTCallback)
+ PreambleParsedCallback PreambleCallback)
: FileName(FileName), StorePreamblesInMemory(StorePreamblesInMemory),
- PCHs(std::move(PCHs)), ASTCallback(std::move(ASTCallback)) {
+ PCHs(std::move(PCHs)), PreambleCallback(std::move(PreambleCallback)) {
log("Created CppFile for " + FileName);
}
@@ -346,10 +359,6 @@ llvm::Optional<std::vector<Diag>> CppFile::rebuild(ParseInputs &&Inputs) {
Diagnostics.insert(Diagnostics.end(), NewAST->getDiagnostics().begin(),
NewAST->getDiagnostics().end());
}
- if (ASTCallback && NewAST) {
- trace::Span Tracer("Running ASTCallback");
- ASTCallback(FileName, NewAST.getPointer());
- }
// Write the results of rebuild into class fields.
Command = std::move(Inputs.CompileCommand);
@@ -404,7 +413,7 @@ CppFile::rebuildPreamble(CompilerInvocation &CI,
assert(!CI.getFrontendOpts().SkipFunctionBodies);
CI.getFrontendOpts().SkipFunctionBodies = true;
- CppFilePreambleCallbacks SerializedDeclsCollector;
+ CppFilePreambleCallbacks SerializedDeclsCollector(FileName, PreambleCallback);
auto BuiltPreamble = PrecompiledPreamble::Build(
CI, &ContentsBuffer, Bounds, *PreambleDiagsEngine, FS, PCHs,
/*StoreInMemory=*/StorePreamblesInMemory, SerializedDeclsCollector);
diff --git a/clang-tools-extra/clangd/ClangdUnit.h b/clang-tools-extra/clangd/ClangdUnit.h
index 64a19c0e61a..3b3d891f1d1 100644
--- a/clang-tools-extra/clangd/ClangdUnit.h
+++ b/clang-tools-extra/clangd/ClangdUnit.h
@@ -17,6 +17,7 @@
#include "Protocol.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/PrecompiledPreamble.h"
+#include "clang/Lex/Preprocessor.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "clang/Tooling/Core/Replacement.h"
@@ -126,7 +127,8 @@ private:
std::vector<Inclusion> Inclusions;
};
-using ASTParsedCallback = std::function<void(PathRef Path, ParsedAST *)>;
+using PreambleParsedCallback = std::function<void(
+ PathRef Path, ASTContext &, std::shared_ptr<clang::Preprocessor>)>;
/// Manages resources, required by clangd. Allows to rebuild file with new
/// contents, and provides AST and Preamble for it.
@@ -134,7 +136,7 @@ class CppFile {
public:
CppFile(PathRef FileName, bool StorePreamblesInMemory,
std::shared_ptr<PCHContainerOperations> PCHs,
- ASTParsedCallback ASTCallback);
+ PreambleParsedCallback PreambleCallback);
/// Rebuild the AST and the preamble.
/// Returns a list of diagnostics or llvm::None, if an error occured.
@@ -170,7 +172,7 @@ private:
std::shared_ptr<PCHContainerOperations> PCHs;
/// This is called after the file is parsed. This can be nullptr if there is
/// no callback.
- ASTParsedCallback ASTCallback;
+ PreambleParsedCallback PreambleCallback;
};
/// Get the beginning SourceLocation at a specified \p Pos.
diff --git a/clang-tools-extra/clangd/TUScheduler.cpp b/clang-tools-extra/clangd/TUScheduler.cpp
index 51b13e2b7ba..588d257bfa0 100644
--- a/clang-tools-extra/clangd/TUScheduler.cpp
+++ b/clang-tools-extra/clangd/TUScheduler.cpp
@@ -414,11 +414,11 @@ struct TUScheduler::FileData {
TUScheduler::TUScheduler(unsigned AsyncThreadsCount,
bool StorePreamblesInMemory,
- ASTParsedCallback ASTCallback,
+ PreambleParsedCallback PreambleCallback,
steady_clock::duration UpdateDebounce)
: StorePreamblesInMemory(StorePreamblesInMemory),
PCHOps(std::make_shared<PCHContainerOperations>()),
- ASTCallback(std::move(ASTCallback)), Barrier(AsyncThreadsCount),
+ PreambleCallback(std::move(PreambleCallback)), Barrier(AsyncThreadsCount),
UpdateDebounce(UpdateDebounce) {
if (0 < AsyncThreadsCount) {
PreambleTasks.emplace();
@@ -455,7 +455,7 @@ void TUScheduler::update(PathRef File, ParseInputs Inputs,
// Create a new worker to process the AST-related tasks.
ASTWorkerHandle Worker = ASTWorker::Create(
File, WorkerThreads ? WorkerThreads.getPointer() : nullptr, Barrier,
- CppFile(File, StorePreamblesInMemory, PCHOps, ASTCallback),
+ CppFile(File, StorePreamblesInMemory, PCHOps, PreambleCallback),
UpdateDebounce);
FD = std::unique_ptr<FileData>(new FileData{
Inputs.Contents, Inputs.CompileCommand, std::move(Worker)});
diff --git a/clang-tools-extra/clangd/TUScheduler.h b/clang-tools-extra/clangd/TUScheduler.h
index aea669d9c73..99748427443 100644
--- a/clang-tools-extra/clangd/TUScheduler.h
+++ b/clang-tools-extra/clangd/TUScheduler.h
@@ -52,7 +52,7 @@ enum class WantDiagnostics {
class TUScheduler {
public:
TUScheduler(unsigned AsyncThreadsCount, bool StorePreamblesInMemory,
- ASTParsedCallback ASTCallback,
+ PreambleParsedCallback PreambleCallback,
std::chrono::steady_clock::duration UpdateDebounce);
~TUScheduler();
@@ -101,7 +101,7 @@ private:
const bool StorePreamblesInMemory;
const std::shared_ptr<PCHContainerOperations> PCHOps;
- const ASTParsedCallback ASTCallback;
+ const PreambleParsedCallback PreambleCallback;
Semaphore Barrier;
llvm::StringMap<std::unique_ptr<FileData>> Files;
// None when running tasks synchronously and non-None when running tasks
diff --git a/clang-tools-extra/clangd/index/FileIndex.cpp b/clang-tools-extra/clangd/index/FileIndex.cpp
index a6e80f83db8..7e19b00458f 100644
--- a/clang-tools-extra/clangd/index/FileIndex.cpp
+++ b/clang-tools-extra/clangd/index/FileIndex.cpp
@@ -10,12 +10,12 @@
#include "FileIndex.h"
#include "SymbolCollector.h"
#include "clang/Index/IndexingAction.h"
+#include "clang/Lex/Preprocessor.h"
namespace clang {
namespace clangd {
-SymbolSlab indexAST(ParsedAST *AST) {
- assert(AST && "AST must not be nullptr!");
+SymbolSlab indexAST(ASTContext &AST, std::shared_ptr<Preprocessor> PP) {
SymbolCollector::Options CollectorOpts;
// FIXME(ioeric): we might also want to collect include headers. We would need
// to make sure all includes are canonicalized (with CanonicalIncludes), which
@@ -26,15 +26,18 @@ SymbolSlab indexAST(ParsedAST *AST) {
CollectorOpts.CountReferences = false;
SymbolCollector Collector(std::move(CollectorOpts));
- Collector.setPreprocessor(AST->getPreprocessorPtr());
+ Collector.setPreprocessor(PP);
index::IndexingOptions IndexOpts;
// We only need declarations, because we don't count references.
IndexOpts.SystemSymbolFilter =
index::IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly;
IndexOpts.IndexFunctionLocals = false;
- index::indexTopLevelDecls(AST->getASTContext(), AST->getTopLevelDecls(),
- Collector, IndexOpts);
+ std::vector<const Decl *> TopLevelDecls(
+ AST.getTranslationUnitDecl()->decls().begin(),
+ AST.getTranslationUnitDecl()->decls().end());
+ index::indexTopLevelDecls(AST, TopLevelDecls, Collector, IndexOpts);
+
return Collector.takeSymbols();
}
@@ -69,12 +72,14 @@ std::shared_ptr<std::vector<const Symbol *>> FileSymbols::allSymbols() {
return {std::move(Snap), Pointers};
}
-void FileIndex::update(PathRef Path, ParsedAST *AST) {
+void FileIndex::update(PathRef Path, ASTContext *AST,
+ std::shared_ptr<Preprocessor> PP) {
if (!AST) {
FSymbols.update(Path, nullptr);
} else {
+ assert(PP);
auto Slab = llvm::make_unique<SymbolSlab>();
- *Slab = indexAST(AST);
+ *Slab = indexAST(*AST, PP);
FSymbols.update(Path, std::move(Slab));
}
auto Symbols = FSymbols.allSymbols();
diff --git a/clang-tools-extra/clangd/index/FileIndex.h b/clang-tools-extra/clangd/index/FileIndex.h
index a0afccea5be..f25ed1749bc 100644
--- a/clang-tools-extra/clangd/index/FileIndex.h
+++ b/clang-tools-extra/clangd/index/FileIndex.h
@@ -19,6 +19,7 @@
#include "../ClangdUnit.h"
#include "Index.h"
#include "MemIndex.h"
+#include "clang/Lex/Preprocessor.h"
namespace clang {
namespace clangd {
@@ -56,8 +57,10 @@ private:
class FileIndex : public SymbolIndex {
public:
/// \brief Update symbols in \p Path with symbols in \p AST. If \p AST is
- /// nullptr, this removes all symbols in the file
- void update(PathRef Path, ParsedAST *AST);
+ /// nullptr, this removes all symbols in the file.
+ /// If \p AST is not null, \p PP cannot be null and it should be the
+ /// preprocessor that was used to build \p AST.
+ void update(PathRef Path, ASTContext *AST, std::shared_ptr<Preprocessor> PP);
bool
fuzzyFind(const FuzzyFindRequest &Req,
@@ -73,7 +76,7 @@ private:
/// Retrieves namespace and class level symbols in \p AST.
/// Exposed to assist in unit tests.
-SymbolSlab indexAST(ParsedAST *AST);
+SymbolSlab indexAST(ASTContext &AST, std::shared_ptr<Preprocessor> PP);
} // namespace clangd
} // namespace clang
diff --git a/clang-tools-extra/unittests/clangd/FileIndexTests.cpp b/clang-tools-extra/unittests/clangd/FileIndexTests.cpp
index b1107b98d3f..1068a4b2f4d 100644
--- a/clang-tools-extra/unittests/clangd/FileIndexTests.cpp
+++ b/clang-tools-extra/unittests/clangd/FileIndexTests.cpp
@@ -7,8 +7,13 @@
//
//===----------------------------------------------------------------------===//
+#include "ClangdUnit.h"
+#include "TestFS.h"
#include "TestTU.h"
#include "index/FileIndex.h"
+#include "clang/Frontend/PCHContainerOperations.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Tooling/CompilationDatabase.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
@@ -87,7 +92,7 @@ void update(FileIndex &M, llvm::StringRef Basename, llvm::StringRef Code) {
File.HeaderFilename = (Basename + ".h").str();
File.HeaderCode = Code;
auto AST = File.build();
- M.update(File.Filename, &AST);
+ M.update(File.Filename, &AST.getASTContext(), AST.getPreprocessorPtr());
}
TEST(FileIndexTest, IndexAST) {
@@ -129,13 +134,13 @@ TEST(FileIndexTest, RemoveAST) {
Req.Scopes = {"ns::"};
EXPECT_THAT(match(M, Req), UnorderedElementsAre("ns::f", "ns::X"));
- M.update("f1.cpp", nullptr);
+ M.update("f1.cpp", nullptr, nullptr);
EXPECT_THAT(match(M, Req), UnorderedElementsAre());
}
TEST(FileIndexTest, RemoveNonExisting) {
FileIndex M;
- M.update("no.cpp", nullptr);
+ M.update("no.cpp", nullptr, nullptr);
EXPECT_THAT(match(M, FuzzyFindRequest()), UnorderedElementsAre());
}
@@ -200,6 +205,58 @@ vector<Ty> make_vector(Arg A) {}
EXPECT_TRUE(SeenMakeVector);
}
+TEST(FileIndexTest, RebuildWithPreamble) {
+ auto FooCpp = testPath("foo.cpp");
+ auto FooH = testPath("foo.h");
+ FileIndex Index;
+ bool IndexUpdated = false;
+ CppFile File("foo.cpp", /*StorePreambleInMemory=*/true,
+ std::make_shared<PCHContainerOperations>(),
+ [&Index, &IndexUpdated](PathRef FilePath, ASTContext &Ctx,
+ std::shared_ptr<Preprocessor> PP) {
+ EXPECT_FALSE(IndexUpdated)
+ << "Expected only a single index update";
+ IndexUpdated = true;
+ Index.update(FilePath, &Ctx, std::move(PP));
+ });
+
+ // Preparse ParseInputs.
+ ParseInputs PI;
+ PI.CompileCommand.Directory = testRoot();
+ PI.CompileCommand.Filename = FooCpp;
+ PI.CompileCommand.CommandLine = {"clang", "-xc++", FooCpp};
+
+ llvm::StringMap<std::string> Files;
+ Files[FooCpp] = "";
+ Files[FooH] = R"cpp(
+ namespace ns_in_header {
+ int func_in_header();
+ }
+ )cpp";
+ PI.FS = buildTestFS(std::move(Files));
+
+ PI.Contents = R"cpp(
+ #include "foo.h"
+ namespace ns_in_source {
+ int func_in_source();
+ }
+ )cpp";
+
+ // Rebuild the file.
+ File.rebuild(std::move(PI));
+ ASSERT_TRUE(IndexUpdated);
+
+ // Check the index contains symbols from the preamble, but not from the main
+ // file.
+ FuzzyFindRequest Req;
+ Req.Query = "";
+ Req.Scopes = {"", "ns_in_header::"};
+
+ EXPECT_THAT(
+ match(Index, Req),
+ UnorderedElementsAre("ns_in_header", "ns_in_header::func_in_header"));
+}
+
} // namespace
} // namespace clangd
} // namespace clang
diff --git a/clang-tools-extra/unittests/clangd/TUSchedulerTests.cpp b/clang-tools-extra/unittests/clangd/TUSchedulerTests.cpp
index 2235e8722c2..879bc5828a3 100644
--- a/clang-tools-extra/unittests/clangd/TUSchedulerTests.cpp
+++ b/clang-tools-extra/unittests/clangd/TUSchedulerTests.cpp
@@ -42,7 +42,7 @@ private:
TEST_F(TUSchedulerTests, MissingFiles) {
TUScheduler S(getDefaultAsyncThreadsCount(),
/*StorePreamblesInMemory=*/true,
- /*ASTParsedCallback=*/nullptr,
+ /*PreambleParsedCallback=*/nullptr,
/*UpdateDebounce=*/std::chrono::steady_clock::duration::zero());
auto Added = testPath("added.cpp");
@@ -98,7 +98,7 @@ TEST_F(TUSchedulerTests, WantDiagnostics) {
TUScheduler S(
getDefaultAsyncThreadsCount(),
/*StorePreamblesInMemory=*/true,
- /*ASTParsedCallback=*/nullptr,
+ /*PreambleParsedCallback=*/nullptr,
/*UpdateDebounce=*/std::chrono::steady_clock::duration::zero());
auto Path = testPath("foo.cpp");
S.update(Path, getInputs(Path, ""), WantDiagnostics::Yes,
@@ -126,7 +126,7 @@ TEST_F(TUSchedulerTests, Debounce) {
{
TUScheduler S(getDefaultAsyncThreadsCount(),
/*StorePreamblesInMemory=*/true,
- /*ASTParsedCallback=*/nullptr,
+ /*PreambleParsedCallback=*/nullptr,
/*UpdateDebounce=*/std::chrono::seconds(1));
// FIXME: we could probably use timeouts lower than 1 second here.
auto Path = testPath("foo.cpp");
@@ -157,7 +157,7 @@ TEST_F(TUSchedulerTests, ManyUpdates) {
{
TUScheduler S(getDefaultAsyncThreadsCount(),
/*StorePreamblesInMemory=*/true,
- /*ASTParsedCallback=*/nullptr,
+ /*PreambleParsedCallback=*/nullptr,
/*UpdateDebounce=*/std::chrono::milliseconds(50));
std::vector<std::string> Files;
diff --git a/clang-tools-extra/unittests/clangd/TestTU.cpp b/clang-tools-extra/unittests/clangd/TestTU.cpp
index 66a9ba1e72f..864a6906375 100644
--- a/clang-tools-extra/unittests/clangd/TestTU.cpp
+++ b/clang-tools-extra/unittests/clangd/TestTU.cpp
@@ -43,7 +43,7 @@ ParsedAST TestTU::build() const {
SymbolSlab TestTU::headerSymbols() const {
auto AST = build();
- return indexAST(&AST);
+ return indexAST(AST.getASTContext(), AST.getPreprocessorPtr());
}
std::unique_ptr<SymbolIndex> TestTU::index() const {