aboutsummaryrefslogtreecommitdiff
path: root/unittests/clangd/SymbolCollectorTests.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'unittests/clangd/SymbolCollectorTests.cpp')
-rw-r--r--unittests/clangd/SymbolCollectorTests.cpp402
1 files changed, 304 insertions, 98 deletions
diff --git a/unittests/clangd/SymbolCollectorTests.cpp b/unittests/clangd/SymbolCollectorTests.cpp
index 06a087cb..666d0bb0 100644
--- a/unittests/clangd/SymbolCollectorTests.cpp
+++ b/unittests/clangd/SymbolCollectorTests.cpp
@@ -9,6 +9,7 @@
#include "Annotations.h"
#include "TestFS.h"
+#include "TestTU.h"
#include "index/SymbolCollector.h"
#include "index/SymbolYAML.h"
#include "clang/Basic/FileManager.h"
@@ -35,15 +36,18 @@ using testing::UnorderedElementsAre;
using testing::UnorderedElementsAreArray;
// GMock helpers for matching Symbol.
-MATCHER_P(Labeled, Label, "") { return arg.CompletionLabel == Label; }
-MATCHER(HasDetail, "") { return arg.Detail; }
-MATCHER_P(Detail, D, "") {
- return arg.Detail && arg.Detail->CompletionDetail == D;
+MATCHER_P(Labeled, Label, "") {
+ return (arg.Name + arg.Signature).str() == Label;
+}
+MATCHER(HasReturnType, "") {
+ return arg.Detail && !arg.Detail->ReturnType.empty();
+}
+MATCHER_P(ReturnType, D, "") {
+ return arg.Detail && arg.Detail->ReturnType == D;
}
MATCHER_P(Doc, D, "") { return arg.Detail && arg.Detail->Documentation == D; }
-MATCHER_P(Plain, Text, "") { return arg.CompletionPlainInsertText == Text; }
MATCHER_P(Snippet, S, "") {
- return arg.CompletionSnippetInsertText == S;
+ return (arg.Name + arg.CompletionSnippetSuffix).str() == S;
}
MATCHER_P(QName, Name, "") { return (arg.Scope + arg.Name).str() == Name; }
MATCHER_P(DeclURI, P, "") { return arg.CanonicalDeclaration.FileURI == P; }
@@ -67,11 +71,94 @@ MATCHER_P(DefRange, Pos, "") {
Pos.end.character);
}
MATCHER_P(Refs, R, "") { return int(arg.References) == R; }
+MATCHER_P(ForCodeCompletion, IsIndexedForCodeCompletion, "") {
+ return arg.IsIndexedForCodeCompletion == IsIndexedForCodeCompletion;
+}
namespace clang {
namespace clangd {
namespace {
+
+class ShouldCollectSymbolTest : public ::testing::Test {
+public:
+ void build(StringRef HeaderCode, StringRef Code = "") {
+ File.HeaderFilename = HeaderName;
+ File.Filename = FileName;
+ File.HeaderCode = HeaderCode;
+ File.Code = Code;
+ AST = File.build();
+ }
+
+ // build() must have been called.
+ bool shouldCollect(StringRef Name, bool Qualified = true) {
+ assert(AST.hasValue());
+ return SymbolCollector::shouldCollectSymbol(
+ Qualified ? findDecl(*AST, Name) : findAnyDecl(*AST, Name),
+ AST->getASTContext(), SymbolCollector::Options());
+ }
+
+protected:
+ std::string HeaderName = "f.h";
+ std::string FileName = "f.cpp";
+ TestTU File;
+ Optional<ParsedAST> AST; // Initialized after build.
+};
+
+TEST_F(ShouldCollectSymbolTest, ShouldCollectSymbol) {
+ build(R"(
+ namespace nx {
+ class X{}
+ void f() { int Local; }
+ struct { int x } var;
+ namespace { class InAnonymous {}; }
+ }
+ )",
+ "class InMain {};");
+ auto AST = File.build();
+ EXPECT_TRUE(shouldCollect("nx"));
+ EXPECT_TRUE(shouldCollect("nx::X"));
+ EXPECT_TRUE(shouldCollect("nx::f"));
+
+ EXPECT_FALSE(shouldCollect("InMain"));
+ EXPECT_FALSE(shouldCollect("Local", /*Qualified=*/false));
+ EXPECT_FALSE(shouldCollect("InAnonymous", /*Qualified=*/false));
+}
+
+TEST_F(ShouldCollectSymbolTest, NoPrivateProtoSymbol) {
+ HeaderName = "f.proto.h";
+ build(
+ R"(// Generated by the protocol buffer compiler. DO NOT EDIT!
+ namespace nx {
+ class Top_Level {};
+ class TopLevel {};
+ enum Kind {
+ KIND_OK,
+ Kind_Not_Ok,
+ };
+ })");
+ EXPECT_TRUE(shouldCollect("nx::TopLevel"));
+ EXPECT_TRUE(shouldCollect("nx::Kind::KIND_OK"));
+ EXPECT_TRUE(shouldCollect("nx::Kind"));
+
+ EXPECT_FALSE(shouldCollect("nx::Top_Level"));
+ EXPECT_FALSE(shouldCollect("nx::Kind::Kind_Not_Ok"));
+}
+
+TEST_F(ShouldCollectSymbolTest, DoubleCheckProtoHeaderComment) {
+ HeaderName = "f.proto.h";
+ build(R"(
+ namespace nx {
+ class Top_Level {};
+ enum Kind {
+ Kind_Fine
+ };
+ }
+ )");
+ EXPECT_TRUE(shouldCollect("nx::Top_Level"));
+ EXPECT_TRUE(shouldCollect("nx::Kind_Fine"));
+}
+
class SymbolIndexActionFactory : public tooling::FrontendActionFactory {
public:
SymbolIndexActionFactory(SymbolCollector::Options COpts,
@@ -132,9 +219,13 @@ public:
CollectorOpts, PragmaHandler.get());
std::vector<std::string> Args = {
- "symbol_collector", "-fsyntax-only", "-xc++", "-std=c++11",
- "-include", TestHeaderName, TestFileName};
+ "symbol_collector", "-fsyntax-only", "-xc++",
+ "-std=c++11", "-include", TestHeaderName};
Args.insert(Args.end(), ExtraArgs.begin(), ExtraArgs.end());
+ // This allows to override the "-xc++" with something else, i.e.
+ // -xobjective-c++.
+ Args.push_back(TestFileName);
+
tooling::ToolInvocation Invocation(
Args,
Factory->create(), Files.get(),
@@ -163,8 +254,20 @@ protected:
TEST_F(SymbolCollectorTest, CollectSymbols) {
const std::string Header = R"(
class Foo {
+ Foo() {}
+ Foo(int a) {}
+ void f();
+ friend void f1();
+ friend class Friend;
+ Foo& operator=(const Foo&);
+ ~Foo();
+ class Nested {
void f();
+ };
};
+ class Friend {
+ };
+
void f1();
inline void f2() {}
static const int KInt = 2;
@@ -200,23 +303,78 @@ TEST_F(SymbolCollectorTest, CollectSymbols) {
runSymbolCollector(Header, /*Main=*/"");
EXPECT_THAT(Symbols,
UnorderedElementsAreArray(
- {QName("Foo"), QName("f1"), QName("f2"), QName("KInt"),
- QName("kStr"), QName("foo"), QName("foo::bar"),
- QName("foo::int32"), QName("foo::int32_t"), QName("foo::v1"),
- QName("foo::bar::v2"), QName("foo::baz")}));
+ {AllOf(QName("Foo"), ForCodeCompletion(true)),
+ AllOf(QName("Foo::Foo"), ForCodeCompletion(false)),
+ AllOf(QName("Foo::Foo"), ForCodeCompletion(false)),
+ AllOf(QName("Foo::f"), ForCodeCompletion(false)),
+ AllOf(QName("Foo::~Foo"), ForCodeCompletion(false)),
+ AllOf(QName("Foo::operator="), ForCodeCompletion(false)),
+ AllOf(QName("Foo::Nested"), ForCodeCompletion(false)),
+ AllOf(QName("Foo::Nested::f"), ForCodeCompletion(false)),
+
+ AllOf(QName("Friend"), ForCodeCompletion(true)),
+ AllOf(QName("f1"), ForCodeCompletion(true)),
+ AllOf(QName("f2"), ForCodeCompletion(true)),
+ AllOf(QName("KInt"), ForCodeCompletion(true)),
+ AllOf(QName("kStr"), ForCodeCompletion(true)),
+ AllOf(QName("foo"), ForCodeCompletion(true)),
+ AllOf(QName("foo::bar"), ForCodeCompletion(true)),
+ AllOf(QName("foo::int32"), ForCodeCompletion(true)),
+ AllOf(QName("foo::int32_t"), ForCodeCompletion(true)),
+ AllOf(QName("foo::v1"), ForCodeCompletion(true)),
+ AllOf(QName("foo::bar::v2"), ForCodeCompletion(true)),
+ AllOf(QName("foo::baz"), ForCodeCompletion(true))}));
}
TEST_F(SymbolCollectorTest, Template) {
Annotations Header(R"(
// Template is indexed, specialization and instantiation is not.
- template <class T> struct [[Tmpl]] {T x = 0;};
+ template <class T> struct [[Tmpl]] {T $xdecl[[x]] = 0;};
template <> struct Tmpl<int> {};
extern template struct Tmpl<float>;
template struct Tmpl<double>;
)");
runSymbolCollector(Header.code(), /*Main=*/"");
- EXPECT_THAT(Symbols, UnorderedElementsAreArray({AllOf(
- QName("Tmpl"), DeclRange(Header.range()))}));
+ EXPECT_THAT(Symbols,
+ UnorderedElementsAreArray(
+ {AllOf(QName("Tmpl"), DeclRange(Header.range())),
+ AllOf(QName("Tmpl::x"), DeclRange(Header.range("xdecl")))}));
+}
+
+TEST_F(SymbolCollectorTest, ObjCSymbols) {
+ const std::string Header = R"(
+ @interface Person
+ - (void)someMethodName:(void*)name1 lastName:(void*)lName;
+ @end
+
+ @implementation Person
+ - (void)someMethodName:(void*)name1 lastName:(void*)lName{
+ int foo;
+ ^(int param){ int bar; };
+ }
+ @end
+
+ @interface Person (MyCategory)
+ - (void)someMethodName2:(void*)name2;
+ @end
+
+ @implementation Person (MyCategory)
+ - (void)someMethodName2:(void*)name2 {
+ int foo2;
+ }
+ @end
+
+ @protocol MyProtocol
+ - (void)someMethodName3:(void*)name3;
+ @end
+ )";
+ TestFileName = "test.m";
+ runSymbolCollector(Header, /*Main=*/"", {"-fblocks", "-xobjective-c++"});
+ EXPECT_THAT(Symbols,
+ UnorderedElementsAre(
+ QName("Person"), QName("Person::someMethodName:lastName:"),
+ QName("MyCategory"), QName("Person::someMethodName2:"),
+ QName("MyProtocol"), QName("MyProtocol::someMethodName3:")));
}
TEST_F(SymbolCollectorTest, Locations) {
@@ -298,17 +456,15 @@ TEST_F(SymbolCollectorTest, SymbolRelativeWithFallback) {
UnorderedElementsAre(AllOf(QName("Foo"), DeclURI(TestHeaderURI))));
}
-#ifndef _WIN32
TEST_F(SymbolCollectorTest, CustomURIScheme) {
// Use test URI scheme from URITests.cpp
CollectorOpts.URISchemes.insert(CollectorOpts.URISchemes.begin(), "unittest");
- TestHeaderName = testPath("test-root/x.h");
- TestFileName = testPath("test-root/x.cpp");
+ TestHeaderName = testPath("x.h");
+ TestFileName = testPath("x.cpp");
runSymbolCollector("class Foo {};", /*Main=*/"");
- EXPECT_THAT(Symbols,
- UnorderedElementsAre(AllOf(QName("Foo"), DeclURI("unittest:x.h"))));
+ EXPECT_THAT(Symbols, UnorderedElementsAre(
+ AllOf(QName("Foo"), DeclURI("unittest:///x.h"))));
}
-#endif
TEST_F(SymbolCollectorTest, InvalidURIScheme) {
// Use test URI scheme from URITests.cpp
@@ -334,7 +490,7 @@ TEST_F(SymbolCollectorTest, IncludeEnums) {
Green
};
enum class Color2 {
- Yellow // ignore
+ Yellow
};
namespace ns {
enum {
@@ -343,20 +499,26 @@ TEST_F(SymbolCollectorTest, IncludeEnums) {
}
)";
runSymbolCollector(Header, /*Main=*/"");
- EXPECT_THAT(Symbols, UnorderedElementsAre(QName("Red"), QName("Color"),
- QName("Green"), QName("Color2"),
- QName("ns"), QName("ns::Black")));
+ EXPECT_THAT(Symbols,
+ UnorderedElementsAre(
+ AllOf(QName("Red"), ForCodeCompletion(true)),
+ AllOf(QName("Color"), ForCodeCompletion(true)),
+ AllOf(QName("Green"), ForCodeCompletion(true)),
+ AllOf(QName("Color2"), ForCodeCompletion(true)),
+ AllOf(QName("Color2::Yellow"), ForCodeCompletion(false)),
+ AllOf(QName("ns"), ForCodeCompletion(true)),
+ AllOf(QName("ns::Black"), ForCodeCompletion(true))));
}
-TEST_F(SymbolCollectorTest, IgnoreNamelessSymbols) {
+TEST_F(SymbolCollectorTest, NamelessSymbols) {
const std::string Header = R"(
struct {
int a;
} Foo;
)";
runSymbolCollector(Header, /*Main=*/"");
- EXPECT_THAT(Symbols,
- UnorderedElementsAre(QName("Foo")));
+ EXPECT_THAT(Symbols, UnorderedElementsAre(QName("Foo"),
+ QName("(anonymous struct)::a")));
}
TEST_F(SymbolCollectorTest, SymbolFormedFromMacro) {
@@ -417,7 +579,7 @@ TEST_F(SymbolCollectorTest, IgnoreSymbolsInMainFile) {
UnorderedElementsAre(QName("Foo"), QName("f1"), QName("f2")));
}
-TEST_F(SymbolCollectorTest, IgnoreClassMembers) {
+TEST_F(SymbolCollectorTest, ClassMembers) {
const std::string Header = R"(
class Foo {
void f() {}
@@ -432,7 +594,10 @@ TEST_F(SymbolCollectorTest, IgnoreClassMembers) {
void Foo::ssf() {}
)";
runSymbolCollector(Header, Main);
- EXPECT_THAT(Symbols, UnorderedElementsAre(QName("Foo")));
+ EXPECT_THAT(Symbols,
+ UnorderedElementsAre(QName("Foo"), QName("Foo::f"),
+ QName("Foo::g"), QName("Foo::sf"),
+ QName("Foo::ssf"), QName("Foo::x")));
}
TEST_F(SymbolCollectorTest, Scopes) {
@@ -494,10 +659,10 @@ TEST_F(SymbolCollectorTest, SymbolWithDocumentation) {
Symbols,
UnorderedElementsAre(
QName("nx"), AllOf(QName("nx::ff"), Labeled("ff(int x, double y)"),
- Detail("int"), Doc("Foo comment."))));
+ ReturnType("int"), Doc("Foo comment."))));
}
-TEST_F(SymbolCollectorTest, PlainAndSnippet) {
+TEST_F(SymbolCollectorTest, Snippet) {
const std::string Header = R"(
namespace nx {
void f() {}
@@ -505,13 +670,12 @@ TEST_F(SymbolCollectorTest, PlainAndSnippet) {
}
)";
runSymbolCollector(Header, /*Main=*/"");
- EXPECT_THAT(
- Symbols,
- UnorderedElementsAre(
- QName("nx"),
- AllOf(QName("nx::f"), Labeled("f()"), Plain("f"), Snippet("f()")),
- AllOf(QName("nx::ff"), Labeled("ff(int x, double y)"), Plain("ff"),
- Snippet("ff(${1:int x}, ${2:double y})"))));
+ EXPECT_THAT(Symbols,
+ UnorderedElementsAre(
+ QName("nx"),
+ AllOf(QName("nx::f"), Labeled("f()"), Snippet("f()")),
+ AllOf(QName("nx::ff"), Labeled("ff(int x, double y)"),
+ Snippet("ff(${1:int x}, ${2:double y})"))));
}
TEST_F(SymbolCollectorTest, YAMLConversions) {
@@ -531,12 +695,10 @@ CanonicalDeclaration:
End:
Line: 1
Column: 1
-CompletionLabel: 'Foo1-label'
-CompletionFilterText: 'filter'
-CompletionPlainInsertText: 'plain'
+IsIndexedForCodeCompletion: true
Detail:
Documentation: 'Foo doc'
- CompletionDetail: 'int'
+ ReturnType: 'int'
...
)";
const std::string YAML2 = R"(
@@ -555,23 +717,24 @@ CanonicalDeclaration:
End:
Line: 1
Column: 1
-CompletionLabel: 'Foo2-label'
-CompletionFilterText: 'filter'
-CompletionPlainInsertText: 'plain'
-CompletionSnippetInsertText: 'snippet'
+IsIndexedForCodeCompletion: false
+Signature: '-sig'
+CompletionSnippetSuffix: '-snippet'
...
)";
- auto Symbols1 = SymbolsFromYAML(YAML1);
+ auto Symbols1 = symbolsFromYAML(YAML1);
EXPECT_THAT(Symbols1,
- UnorderedElementsAre(AllOf(
- QName("clang::Foo1"), Labeled("Foo1-label"), Doc("Foo doc"),
- Detail("int"), DeclURI("file:///path/foo.h"))));
- auto Symbols2 = SymbolsFromYAML(YAML2);
+ UnorderedElementsAre(AllOf(QName("clang::Foo1"), Labeled("Foo1"),
+ Doc("Foo doc"), ReturnType("int"),
+ DeclURI("file:///path/foo.h"),
+ ForCodeCompletion(true))));
+ auto Symbols2 = symbolsFromYAML(YAML2);
EXPECT_THAT(Symbols2, UnorderedElementsAre(AllOf(
- QName("clang::Foo2"), Labeled("Foo2-label"),
- Not(HasDetail()), DeclURI("file:///path/bar.h"))));
+ QName("clang::Foo2"), Labeled("Foo2-sig"),
+ Not(HasReturnType()), DeclURI("file:///path/bar.h"),
+ ForCodeCompletion(false))));
std::string ConcatenatedYAML;
{
@@ -579,7 +742,7 @@ CompletionSnippetInsertText: 'snippet'
SymbolsToYAML(Symbols1, OS);
SymbolsToYAML(Symbols2, OS);
}
- auto ConcatenatedSymbols = SymbolsFromYAML(ConcatenatedYAML);
+ auto ConcatenatedSymbols = symbolsFromYAML(ConcatenatedYAML);
EXPECT_THAT(ConcatenatedSymbols,
UnorderedElementsAre(QName("clang::Foo1"),
QName("clang::Foo2")));
@@ -741,23 +904,27 @@ TEST_F(SymbolCollectorTest, AvoidUsingFwdDeclsAsCanonicalDecls) {
// Canonical declarations.
class $cdecl[[C]] {};
struct $sdecl[[S]] {};
- union $udecl[[U]] {int x; bool y;};
+ union $udecl[[U]] {int $xdecl[[x]]; bool $ydecl[[y]];};
)");
runSymbolCollector(Header.code(), /*Main=*/"");
- EXPECT_THAT(Symbols,
- UnorderedElementsAre(
- AllOf(QName("C"), DeclURI(TestHeaderURI),
- DeclRange(Header.range("cdecl")),
- IncludeHeader(TestHeaderURI), DefURI(TestHeaderURI),
- DefRange(Header.range("cdecl"))),
- AllOf(QName("S"), DeclURI(TestHeaderURI),
- DeclRange(Header.range("sdecl")),
- IncludeHeader(TestHeaderURI), DefURI(TestHeaderURI),
- DefRange(Header.range("sdecl"))),
- AllOf(QName("U"), DeclURI(TestHeaderURI),
- DeclRange(Header.range("udecl")),
- IncludeHeader(TestHeaderURI), DefURI(TestHeaderURI),
- DefRange(Header.range("udecl")))));
+ EXPECT_THAT(
+ Symbols,
+ UnorderedElementsAre(
+ AllOf(QName("C"), DeclURI(TestHeaderURI),
+ DeclRange(Header.range("cdecl")), IncludeHeader(TestHeaderURI),
+ DefURI(TestHeaderURI), DefRange(Header.range("cdecl"))),
+ AllOf(QName("S"), DeclURI(TestHeaderURI),
+ DeclRange(Header.range("sdecl")), IncludeHeader(TestHeaderURI),
+ DefURI(TestHeaderURI), DefRange(Header.range("sdecl"))),
+ AllOf(QName("U"), DeclURI(TestHeaderURI),
+ DeclRange(Header.range("udecl")), IncludeHeader(TestHeaderURI),
+ DefURI(TestHeaderURI), DefRange(Header.range("udecl"))),
+ AllOf(QName("U::x"), DeclURI(TestHeaderURI),
+ DeclRange(Header.range("xdecl")), DefURI(TestHeaderURI),
+ DefRange(Header.range("xdecl"))),
+ AllOf(QName("U::y"), DeclURI(TestHeaderURI),
+ DeclRange(Header.range("ydecl")), DefURI(TestHeaderURI),
+ DefRange(Header.range("ydecl")))));
}
TEST_F(SymbolCollectorTest, ClassForwardDeclarationIsCanonical) {
@@ -776,40 +943,79 @@ TEST_F(SymbolCollectorTest, UTF16Character) {
AllOf(QName("pörk"), DeclRange(Header.range()))));
}
-TEST_F(SymbolCollectorTest, FilterPrivateProtoSymbols) {
- TestHeaderName = testPath("x.proto.h");
- const std::string Header =
- R"(// Generated by the protocol buffer compiler. DO NOT EDIT!
- namespace nx {
- class Top_Level {};
- class TopLevel {};
- enum Kind {
- KIND_OK,
- Kind_Not_Ok,
- };
- bool operator<(const TopLevel &, const TopLevel &);
- })";
- runSymbolCollector(Header, /*Main=*/"");
+TEST_F(SymbolCollectorTest, DoNotIndexSymbolsInFriendDecl) {
+ Annotations Header(R"(
+ namespace nx {
+ class $z[[Z]] {};
+ class X {
+ friend class Y;
+ friend class Z;
+ friend void foo();
+ friend void $bar[[bar]]() {}
+ };
+ class $y[[Y]] {};
+ void $foo[[foo]]();
+ }
+ )");
+ runSymbolCollector(Header.code(), /*Main=*/"");
+
EXPECT_THAT(Symbols,
- UnorderedElementsAre(QName("nx"), QName("nx::TopLevel"),
- QName("nx::Kind"), QName("nx::KIND_OK"),
- QName("nx::operator<")));
+ UnorderedElementsAre(
+ QName("nx"), QName("nx::X"),
+ AllOf(QName("nx::Y"), DeclRange(Header.range("y"))),
+ AllOf(QName("nx::Z"), DeclRange(Header.range("z"))),
+ AllOf(QName("nx::foo"), DeclRange(Header.range("foo"))),
+ AllOf(QName("nx::bar"), DeclRange(Header.range("bar")))));
}
-TEST_F(SymbolCollectorTest, DoubleCheckProtoHeaderComment) {
- TestHeaderName = testPath("x.proto.h");
+TEST_F(SymbolCollectorTest, ReferencesInFriendDecl) {
const std::string Header = R"(
- namespace nx {
- class Top_Level {};
- enum Kind {
- Kind_Fine
+ class X;
+ class Y;
+ )";
+ const std::string Main = R"(
+ class C {
+ friend ::X;
+ friend class Y;
};
- }
)";
- runSymbolCollector(Header, /*Main=*/"");
- EXPECT_THAT(Symbols,
- UnorderedElementsAre(QName("nx"), QName("nx::Top_Level"),
- QName("nx::Kind"), QName("nx::Kind_Fine")));
+ CollectorOpts.CountReferences = true;
+ runSymbolCollector(Header, Main);
+ EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(QName("X"), Refs(1)),
+ AllOf(QName("Y"), Refs(1))));
+}
+
+TEST_F(SymbolCollectorTest, Origin) {
+ CollectorOpts.Origin = SymbolOrigin::Static;
+ runSymbolCollector("class Foo {};", /*Main=*/"");
+ EXPECT_THAT(Symbols, UnorderedElementsAre(
+ Field(&Symbol::Origin, SymbolOrigin::Static)));
+}
+
+TEST_F(SymbolCollectorTest, CollectMacros) {
+ CollectorOpts.CollectIncludePath = true;
+ Annotations Header(R"(
+ #define X 1
+ #define $mac[[MAC]](x) int x
+ #define $used[[USED]](y) float y;
+
+ MAC(p);
+ )");
+ const std::string Main = R"(
+ #define MAIN 1 // not indexed
+ USED(t);
+ )";
+ CollectorOpts.CountReferences = true;
+ CollectorOpts.CollectMacro = true;
+ runSymbolCollector(Header.code(), Main);
+ EXPECT_THAT(
+ Symbols,
+ UnorderedElementsAre(
+ QName("p"),
+ AllOf(QName("X"), DeclURI(TestHeaderURI),
+ IncludeHeader(TestHeaderURI)),
+ AllOf(Labeled("MAC(x)"), Refs(0), DeclRange(Header.range("mac"))),
+ AllOf(Labeled("USED(y)"), Refs(1), DeclRange(Header.range("used")))));
}
} // namespace