summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang-tools-extra/clangd/TUScheduler.cpp3
-rw-r--r--clang-tools-extra/unittests/clangd/XRefsTests.cpp45
2 files changed, 46 insertions, 2 deletions
diff --git a/clang-tools-extra/clangd/TUScheduler.cpp b/clang-tools-extra/clangd/TUScheduler.cpp
index f985e7d7fa3..4d65886e65f 100644
--- a/clang-tools-extra/clangd/TUScheduler.cpp
+++ b/clang-tools-extra/clangd/TUScheduler.cpp
@@ -370,8 +370,7 @@ void ASTWorker::update(
bool CanReuseAST = InputsAreTheSame && (OldPreamble == NewPreamble);
{
std::lock_guard<std::mutex> Lock(Mutex);
- if (NewPreamble)
- LastBuiltPreamble = NewPreamble;
+ LastBuiltPreamble = NewPreamble;
}
// Before doing the expensive AST reparse, we want to release our reference
// to the old preamble, so it can be freed if there are no other references
diff --git a/clang-tools-extra/unittests/clangd/XRefsTests.cpp b/clang-tools-extra/unittests/clangd/XRefsTests.cpp
index b08af32df21..2558cdefaaa 100644
--- a/clang-tools-extra/unittests/clangd/XRefsTests.cpp
+++ b/clang-tools-extra/unittests/clangd/XRefsTests.cpp
@@ -1021,6 +1021,51 @@ TEST(GoToInclude, All) {
EXPECT_THAT(*Locations, IsEmpty());
}
+TEST(GoToDefinition, WithPreamble) {
+ // Test stragety: AST should always use the latest preamble instead of last
+ // good preamble.
+ MockFSProvider FS;
+ IgnoreDiagnostics DiagConsumer;
+ MockCompilationDatabase CDB;
+ ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+ auto FooCpp = testPath("foo.cpp");
+ auto FooCppUri = URIForFile{FooCpp};
+ // The trigger locations must be the same.
+ Annotations FooWithHeader(R"cpp(#include "fo^o.h")cpp");
+ Annotations FooWithoutHeader(R"cpp(double [[fo^o]]();)cpp");
+
+ FS.Files[FooCpp] = FooWithHeader.code();
+
+ auto FooH = testPath("foo.h");
+ auto FooHUri = URIForFile{FooH};
+ Annotations FooHeader(R"cpp([[]])cpp");
+ FS.Files[FooH] = FooHeader.code();
+
+ runAddDocument(Server, FooCpp, FooWithHeader.code());
+ // GoToDefinition goes to a #include file: the result comes from the preamble.
+ EXPECT_THAT(
+ cantFail(runFindDefinitions(Server, FooCpp, FooWithHeader.point())),
+ ElementsAre(Location{FooHUri, FooHeader.range()}));
+
+ // Only preamble is built, and no AST is built in this request.
+ Server.addDocument(FooCpp, FooWithoutHeader.code(), WantDiagnostics::No);
+ // We build AST here, and it should use the latest preamble rather than the
+ // stale one.
+ EXPECT_THAT(
+ cantFail(runFindDefinitions(Server, FooCpp, FooWithoutHeader.point())),
+ ElementsAre(Location{FooCppUri, FooWithoutHeader.range()}));
+
+ // Reset test environment.
+ runAddDocument(Server, FooCpp, FooWithHeader.code());
+ // Both preamble and AST are built in this request.
+ Server.addDocument(FooCpp, FooWithoutHeader.code(), WantDiagnostics::Yes);
+ // Use the AST being built in above request.
+ EXPECT_THAT(
+ cantFail(runFindDefinitions(Server, FooCpp, FooWithoutHeader.point())),
+ ElementsAre(Location{FooCppUri, FooWithoutHeader.range()}));
+}
+
} // namespace
} // namespace clangd
} // namespace clang
OpenPOWER on IntegriCloud