[clangd] Store preamble macros in dynamic index.
Summary:
Pros:
o Loading macros from preamble for every completion is slow (see profile).
o Calculating macro USR is also slow (see profile).
o Sema can provide a lot of macro completion results (e.g. when filter is empty,
60k for some large TUs!).
Cons:
o Slight memory increase in dynamic index (~1%).
o Some extra work during preamble build (should be fine as preamble build and
indexAST is way slower).
Before:
{F7195645}
After:
{F7195646}
Reviewers: ilya-biryukov, sammccall
Reviewed By: sammccall
Subscribers: MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D52078
git-svn-id: https://llvm.org/svn/llvm-project/clang-tools-extra/trunk@342529 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/clangd/index/FileIndex.cpp b/clangd/index/FileIndex.cpp
index 22a32cc..447a96c 100644
--- a/clangd/index/FileIndex.cpp
+++ b/clangd/index/FileIndex.cpp
@@ -14,6 +14,7 @@
#include "index/Index.h"
#include "index/Merge.h"
#include "clang/Index/IndexingAction.h"
+#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/Preprocessor.h"
#include <memory>
@@ -41,10 +42,13 @@
IndexOpts.SystemSymbolFilter =
index::IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly;
IndexOpts.IndexFunctionLocals = false;
-
- if (IsIndexMainAST)
+ if (IsIndexMainAST) {
// We only collect refs when indexing main AST.
CollectorOpts.RefFilter = RefKind::All;
+ }else {
+ IndexOpts.IndexMacrosInPreprocessor = true;
+ CollectorOpts.CollectMacro = true;
+ }
SymbolCollector Collector(std::move(CollectorOpts));
Collector.setPreprocessor(PP);
diff --git a/unittests/clangd/CodeCompleteTests.cpp b/unittests/clangd/CodeCompleteTests.cpp
index 2978142..c1e8404 100644
--- a/unittests/clangd/CodeCompleteTests.cpp
+++ b/unittests/clangd/CodeCompleteTests.cpp
@@ -223,12 +223,13 @@
void TestAfterDotCompletion(clangd::CodeCompleteOptions Opts) {
auto Results = completions(
R"cpp(
- #define MACRO X
-
int global_var;
int global_func();
+ // Make sure this is not in preamble.
+ #define MACRO X
+
struct GlobalClass {};
struct ClassWithMembers {
@@ -276,11 +277,12 @@
void TestGlobalScopeCompletion(clangd::CodeCompleteOptions Opts) {
auto Results = completions(
R"cpp(
- #define MACRO X
-
int global_var;
int global_func();
+ // Make sure this is not in preamble.
+ #define MACRO X
+
struct GlobalClass {};
struct ClassWithMembers {
@@ -430,10 +432,11 @@
TEST(CompletionTest, Kinds) {
auto Results = completions(
R"cpp(
- #define MACRO X
int variable;
struct Struct {};
int function();
+ // make sure MACRO is not included in preamble.
+ #define MACRO 10
int X = ^
)cpp",
{func("indexFunction"), var("indexVariable"), cls("indexClass")});
@@ -1921,6 +1924,21 @@
UnorderedElementsAre(Named("Clangd_Macro_Test")));
}
+TEST(CompletionTest, NoMacroFromPreambleIfIndexIsSet) {
+ auto Results = completions(
+ R"cpp(#define CLANGD_PREAMBLE x
+
+ int x = 0;
+ #define CLANGD_MAIN x
+ void f() { CLANGD_^ }
+ )cpp",
+ {func("CLANGD_INDEX")});
+ // Index is overriden in code completion options, so the preamble symbol is
+ // not seen.
+ EXPECT_THAT(Results.Completions, UnorderedElementsAre(Named("CLANGD_MAIN"),
+ Named("CLANGD_INDEX")));
+}
+
TEST(CompletionTest, DeprecatedResults) {
std::string Body = R"cpp(
void TestClangd();
diff --git a/unittests/clangd/FileIndexTests.cpp b/unittests/clangd/FileIndexTests.cpp
index f883551..d1858c5 100644
--- a/unittests/clangd/FileIndexTests.cpp
+++ b/unittests/clangd/FileIndexTests.cpp
@@ -15,6 +15,7 @@
#include "index/FileIndex.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/PCHContainerOperations.h"
+#include "clang/Index/IndexSymbol.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "gtest/gtest.h"
@@ -330,6 +331,21 @@
FileURI("unittest:///test2.cc"))}));
}
+TEST(FileIndexTest, CollectMacros) {
+ FileIndex M;
+ update(M, "f", "#define CLANGD 1");
+
+ FuzzyFindRequest Req;
+ Req.Query = "";
+ bool SeenSymbol = false;
+ M.index().fuzzyFind(Req, [&](const Symbol &Sym) {
+ EXPECT_EQ(Sym.Name, "CLANGD");
+ EXPECT_EQ(Sym.SymInfo.Kind, index::SymbolKind::Macro);
+ SeenSymbol = true;
+ });
+ EXPECT_TRUE(SeenSymbol);
+}
+
} // namespace
} // namespace clangd
} // namespace clang