18#include "clang/AST/Decl.h"
19#include "clang/Basic/SourceLocation.h"
20#include "llvm/ADT/StringRef.h"
21#include "llvm/Support/Casting.h"
22#include "llvm/Support/Error.h"
23#include "llvm/Support/Path.h"
24#include "llvm/Support/ScopedPrinter.h"
25#include "gmock/gmock.h"
26#include "gtest/gtest.h"
35using ::testing::AllOf;
36using ::testing::ElementsAre;
38using ::testing::IsEmpty;
39using ::testing::Matcher;
40using ::testing::UnorderedElementsAre;
41using ::testing::UnorderedElementsAreArray;
42using ::testing::UnorderedPointwise;
44std::string guard(llvm::StringRef Code) {
45 return "#pragma once\n" + Code.str();
54 return Sym.PreferredDeclaration.range ==
Range;
59Matcher<const std::vector<DocumentHighlight> &>
61 std::vector<DocumentHighlight> Expected;
63 Expected.emplace_back();
64 Expected.back().range = R;
65 Expected.back().kind = K;
67 for (
const auto &
Range : Test.ranges())
69 for (
const auto &
Range : Test.ranges(
"read"))
71 for (
const auto &
Range : Test.ranges(
"write"))
73 return UnorderedElementsAreArray(Expected);
77 const char *Tests[] = {
78 R
"cpp(// Local variable
81 $write[[^bonjour]] = 2;
82 int test1 = $read[[bonjour]];
89 static void foo([[MyClass]]*) {}
93 ns1::[[My^Class]]* Params;
98 int [[^foo]](int) { return 0; }
100 [[foo]]([[foo]](42));
105 R"cpp(// Function parameter in decl
106 void foo(int [[^bar]]);
108 R"cpp(// Not touching any identifiers.
117 R"cpp(// ObjC methods with split selectors.
119 +(void) [[x]]:(int)a [[y]]:(int)b;
122 +(void) [[x]]:(int)a [[y]]:(int)b {}
125 [Foo [[x]]:2 [[^y]]:4];
136 for (
const char *Test : Tests) {
139 TU.ExtraArgs.push_back(
"-xobjective-c++");
140 auto AST = TU.build();
146TEST(HighlightsTest, ControlFlow) {
147 const char *Tests[] = {
149 // Highlight same-function returns.
150 int fib(unsigned n) {
151 if (n <= 1) [[ret^urn]] 1;
152 [[return]] fib(n - 1) + fib(n - 2);
154 // Returns from other functions not highlighted.
155 auto Lambda = [] { return; };
156 class LocalClass { void x() { return; } };
161 #define FAIL() return false
164 if (n < 0) [[FAIL]]();
170 // Highlight loop control flow
173 [[^for]] (char c : "fruit loops!") {
174 if (c == ' ') [[continue]];
176 if (c == '!') [[break]];
177 if (c == '?') [[return]] -1;
184 // Highlight loop and same-loop control flow
187 if (false) [[bre^ak]];
195 // Highlight switch for break (but not other breaks).
196 void describe(unsigned n) {
207 // Highlight case and exits for switch-break (but not other cases).
208 void describe(unsigned n) {
221 // Highlight exits and switch for case
222 void describe(unsigned n) {
235 // Highlight nothing for switch.
236 void describe(unsigned n) {
249 // FIXME: match exception type against catch blocks
251 try { // wrong: highlight try with matching catch
252 try { // correct: has no matching catch
254 } catch (int) { } // correct: catch doesn't match type
255 [[return]] -1; // correct: exits the matching catch
256 } catch (const char*) { } // wrong: highlight matching catch
257 [[return]] 42; // wrong: throw doesn't exit function
262 // Loop highlights goto exiting the loop, but not jumping within it.
273 for (
const char *Test : Tests) {
276 TU.ExtraArgs.push_back(
"-fexceptions");
277 auto AST = TU.build();
283MATCHER_P3(
sym, Name, Decl, DefOrNone,
"") {
284 std::optional<Range> Def = DefOrNone;
285 if (Name != arg.Name) {
286 *result_listener <<
"Name is " << arg.Name;
289 if (Decl != arg.PreferredDeclaration.range) {
290 *result_listener <<
"Declaration is "
291 << llvm::to_string(arg.PreferredDeclaration);
294 if (!Def && !arg.Definition)
296 if (Def && !arg.Definition) {
297 *result_listener <<
"Has no definition";
300 if (!Def && arg.Definition) {
301 *result_listener <<
"Definition is " << llvm::to_string(*arg.Definition);
304 if (arg.Definition->range != *Def) {
305 *result_listener <<
"Definition is " << llvm::to_string(*arg.Definition);
313MATCHER_P(rangeIs, R,
"") {
return arg.Loc.range == R; }
315 return arg.Loc.containerName.value_or(
"") ==
C;
317MATCHER_P(attrsAre, A,
"") {
return arg.Attributes ==
A; }
318MATCHER_P(hasID, ID,
"") {
return arg.ID == ID; }
320TEST(LocateSymbol, WithIndex) {
322 class $forward[[Forward]];
323 class $foo[[Foo]] {};
327 inline void $f2[[f2]]() {}
330 class $forward[[forward]] {};
335 TU.Code = std::string(SymbolCpp.code());
336 TU.HeaderCode = std::string(SymbolHeader.code());
337 auto Index = TU.index();
338 auto LocateWithIndex = [&Index](
const Annotations &Main) {
349 EXPECT_THAT(LocateWithIndex(Test),
350 ElementsAre(sym("f1", Test.range(), SymbolCpp.range(
"f1"))));
358 EXPECT_THAT(LocateWithIndex(Test),
359 ElementsAre(sym("f1", SymbolHeader.range(
"f1"), Test.range())));
361 Test =
Annotations(R
"cpp(// forward declaration in AST.
365 EXPECT_THAT(LocateWithIndex(Test),
366 ElementsAre(sym("Foo", Test.range(), SymbolHeader.range(
"foo"))));
369 class [[Forward]] {};
373 LocateWithIndex(Test),
374 ElementsAre(sym("Forward", SymbolHeader.range(
"forward"), Test.range())));
377TEST(LocateSymbol, AnonymousStructFields) {
380 struct { int $1[[x]]; };
382 // Make sure the implicit base is skipped.
386 // Check that we don't skip explicit bases.
390 auto AST = TU.build();
392 UnorderedElementsAre(
sym(
"x", Code.range(
"1"), Code.range(
"1"))));
395 UnorderedElementsAre(
sym(
"Foo", Code.range(
"2"), Code.range(
"2"))));
398TEST(LocateSymbol, FindOverrides) {
401 virtual void $1[[fo^o]]() = 0;
403 class Bar : public Foo {
404 void $2[[foo]]() override;
408 auto AST = TU.build();
410 UnorderedElementsAre(
sym(
"foo", Code.range(
"1"), std::nullopt),
411 sym(
"foo", Code.range(
"2"), std::nullopt)));
414TEST(LocateSymbol, FindOverridesFromDefObjC) {
422 @interface Foo : Base<Fooey>
430 - (void)$3[[fo^o]] {}
434 TU.ExtraArgs.push_back("-xobjective-c++");
435 auto AST = TU.build();
438 UnorderedElementsAre(
sym(
"foo", Code.range(
"1"), std::nullopt),
439 sym(
"foo", Code.range(
"2"), Code.range(
"3"))));
442TEST(LocateSymbol, NoOverridesFromDeclObjC) {
450 @interface Foo : Base<Fooey>
462 TU.ExtraArgs.push_back("-xobjective-c++");
463 auto AST = TU.build();
466 UnorderedElementsAre(
sym(
"foo", Code.range(
"2"), Code.range(
"3"))));
469TEST(LocateSymbol, ObjCNoOverridesOnUsage) {
481 void doSomething(Bar *bar) {
486 TU.ExtraArgs.push_back("-xobjective-c++");
487 auto AST = TU.build();
490 UnorderedElementsAre(
sym(
"foo", Code.range(
"1"), Code.range(
"2"))));
493TEST(LocateSymbol, WithIndexPreferredLocation) {
495 class $p[[Proto]] {};
496 void $f[[func]]() {};
499 TU.HeaderCode = std::string(SymbolHeader.code());
500 TU.HeaderFilename = "x.proto";
501 auto Index = TU.index();
504 // Shift to make range different.
516 auto CodeGenLoc = SymbolHeader.range(
"p");
517 EXPECT_THAT(Locs, ElementsAre(
sym(
"Proto", CodeGenLoc, CodeGenLoc)));
521 auto CodeGenLoc = SymbolHeader.range(
"f");
522 EXPECT_THAT(Locs, ElementsAre(
sym(
"func", CodeGenLoc, CodeGenLoc)));
531 const char *Tests[] = {
544 R"cpp(// Local variable
554 struct [[MyClass]] {};
557 ns1::My^Class* Params;
561 R"cpp(// Function definition via pointer
568 R"cpp(// Function declaration via call
569 int $decl[[foo]](int);
576 struct Foo { int [[x]]; };
583 R"cpp(// Field, member initializer
590 R"cpp(// Field, field designator
591 struct Foo { int [[x]]; };
593 Foo bar = { .^x = 2 };
598 struct Foo { int $decl[[x]](); };
606 typedef int $decl[[Foo]];
612 R"cpp(// Template type parameter
613 template <typename [[T]]>
617 R"cpp(// Template template type parameter
618 template <template<typename> class [[T]]>
619 void foo() { ^T<int> t; }
623 namespace $decl[[ns]] {
624 struct Foo { static void bar(); };
626 int main() { ^ns::Foo::bar(); }
630 class TTT { public: int a; };
631 #define [[FF]](S) if (int b = S.a) {}
638 R"cpp(// Macro argument
640 #define ADDRESSOF(X) &X;
641 int *j = ADDRESSOF(^i);
643 R"cpp(// Macro argument appearing multiple times in expansion
644 #define VALIDATE_TYPE(x) (void)x;
645 #define ASSERT(expr) \
647 VALIDATE_TYPE(expr); \
650 bool [[waldo]]() { return true; }
655 R"cpp(// Symbol concatenated inside macro (not supported)
657 #define POINTER(X) p ## X;
658 int x = *POINTER(^i);
661 R"cpp(// Forward class declaration
663 class $def[[Foo]] {};
667 R"cpp(// Function declaration
670 void $def[[foo]]() {}
674 #define FF(name) class name##_Test {};
676 void f() { my^_Test a; }
680 #define FF() class [[Test]] {};
682 void f() { T^est a; }
685 R"cpp(// explicit template specialization
686 template <typename T>
687 struct Foo { void bar() {} };
690 struct [[Foo]]<int> { void bar() {} };
698 R"cpp(// implicit template specialization
699 template <typename T>
700 struct [[Foo]] { void bar() {} };
702 struct Foo<int> { void bar() {} };
709 R"cpp(// partial template specialization
710 template <typename T>
711 struct Foo { void bar() {} };
712 template <typename T>
713 struct [[Foo]]<T*> { void bar() {} };
717 R"cpp(// function template specializations
727 R"cpp(// variable template decls
732 double [[var]]<int> = 10;
734 double y = va^r<int>;
737 R"cpp(// No implicit constructors
749 X& $decl[[operator]]++();
757 struct S1 { void f(); };
758 struct S2 { S1 * $decl[[operator]]->(); };
764 R"cpp(// Declaration of explicit template specialization
765 template <typename T>
766 struct $decl[[$def[[Foo]]]] {};
772 R"cpp(// Declaration of partial template specialization
773 template <typename T>
774 struct $decl[[$def[[Foo]]]] {};
776 template <typename T>
780 R"cpp(// Definition on ClassTemplateDecl
782 // Forward declaration.
786 template <typename T>
787 struct $def[[Foo]] {};
793 R"cpp(// auto builtin type (not supported)
797 R"cpp(// auto on lambda
802 R"cpp(// auto on struct
810 R"cpp(// decltype on struct
819 R"cpp(// decltype(auto) on struct
826 ^decltype(auto) k = j;
829 R"cpp(// auto on template class
830 template<typename T> class [[Foo]] {};
832 ^auto x = Foo<int>();
835 R"cpp(// auto on template class with forward declared class
836 template<typename T> class [[Foo]] {};
842 R"cpp(// auto on specialized template class
843 template<typename T> class Foo {};
844 template<> class [[Foo]]<int> {};
846 ^auto x = Foo<int>();
849 R"cpp(// auto on initializer list.
853 class [[initializer_list]] { const _E *a, *b; };
859 R"cpp(// auto function return with trailing type
861 ^auto test() -> decltype(Bar()) {
866 R"cpp(// decltype in trailing return type
868 auto test() -> ^decltype(Bar()) {
873 R"cpp(// auto in function return
880 R"cpp(// auto& in function return
888 R"cpp(// auto* in function return
896 R"cpp(// const auto& in function return
898 const ^auto& test() {
904 R"cpp(// auto lambda param where there's a single instantiation
906 auto Lambda = [](^auto){ return 0; };
907 int x = Lambda(Bar{});
910 R"cpp(// decltype(auto) in function return
912 ^decltype(auto) test() {
917 R"cpp(// decltype of function with trailing return type.
919 auto test() -> decltype(Bar()) {
923 ^decltype(test()) i = test();
927 R"cpp(// auto with dependent type
930 template <typename T>
936 R"cpp(// Override specifier jumps to overridden method
937 class Y { virtual void $decl[[a]]() = 0; };
938 class X : Y { void a() ^override {} };
940 R"cpp(// Final specifier jumps to overridden method
941 class Y { virtual void $decl[[a]]() = 0; };
942 class X : Y { void a() ^final {} };
945 R"cpp(// Heuristic resolution of dependent method
946 template <typename T>
951 template <typename T>
957 R"cpp(// Heuristic resolution of dependent method via this->
958 template <typename T>
966 R"cpp(// Heuristic resolution of dependent static method
967 template <typename T>
969 static void [[bar]]() {}
972 template <typename T>
978 R"cpp(// Heuristic resolution of dependent method
979 // invoked via smart pointer
980 template <typename> struct S { void [[foo]]() {} };
981 template <typename T> struct unique_ptr {
984 template <typename T>
985 void test(unique_ptr<S<T>>& V) {
990 R"cpp(// Heuristic resolution of dependent enumerator
991 template <typename T>
993 enum class E { [[A]], B };
999 typedef int $decl[[MyTypeDef]];
1000 enum Foo : My^TypeDef {};
1003 typedef int $decl[[MyTypeDef]];
1004 enum Foo : My^TypeDef;
1007 using $decl[[MyTypeDef]] = int;
1008 enum Foo : My^TypeDef {};
1013 @protocol $decl[[Dog]]
1016 id<Do^g> getDoggo() {
1026 @interface $decl[[Cat]] (Exte^nsion)
1029 @implementation $def[[Cat]] (Extension)
1035 @class $decl[[Foo]];
1041 R"objc(// Prefer interface definition over forward declaration
1043 @interface $decl[[Foo]]
1052 @interface $decl[[Foo]]
1054 @implementation $def[[Foo]]
1061 R"objc(// Method decl and definition for ObjC class.
1063 - (void)$decl[[meow]];
1066 - (void)$def[[meow]] {}
1068 void makeNoise(Cat *kitty) {
1073 R"objc(// Method decl and definition for ObjC category.
1076 @interface Dog (Play)
1077 - (void)$decl[[runAround]];
1079 @implementation Dog (Play)
1080 - (void)$def[[runAround]] {}
1082 void play(Dog *dog) {
1087 R"objc(// Method decl and definition for ObjC class extension.
1091 - (void)$decl[[howl]];
1094 - (void)$def[[howl]] {}
1096 void play(Dog *dog) {
1101 struct PointerIntPairInfo {
1102 static void *$decl[[getPointer]](void *Value);
1105 template <typename Info = PointerIntPairInfo> struct PointerIntPair {
1107 void *getPointer() const { return Info::get^Pointer(Value); }
1110 R"cpp(// Deducing this
1116 int x = wa^ldo.bar();
1119 for (
const char *Test : Tests) {
1121 std::optional<Range> WantDecl;
1122 std::optional<Range> WantDef;
1123 if (!
T.ranges().empty())
1124 WantDecl = WantDef =
T.range();
1125 if (!
T.ranges(
"decl").empty())
1126 WantDecl =
T.range(
"decl");
1127 if (!
T.ranges(
"def").empty())
1128 WantDef =
T.range(
"def");
1131 TU.
Code = std::string(
T.code());
1133 TU.ExtraArgs.push_back(
"-xobjective-c++");
1134 TU.ExtraArgs.push_back(
"-std=c++23");
1136 auto AST = TU.build();
1140 EXPECT_THAT(Results, IsEmpty()) << Test;
1142 ASSERT_THAT(Results, ::testing::SizeIs(1)) << Test;
1143 EXPECT_EQ(Results[0].PreferredDeclaration.range, *WantDecl) << Test;
1144 EXPECT_TRUE(Results[0].ID) << Test;
1145 std::optional<Range> GotDef;
1147 GotDef = Results[0].Definition->range;
1148 EXPECT_EQ(WantDef, GotDef) << Test;
1152TEST(LocateSymbol, ValidSymbolID) {
1154 #define MACRO(x, y) ((x) + (y))
1155 int add(int x, int y) { return $MACRO^MACRO(x, y); }
1156 int sum = $add^add(1, 2);
1160 auto AST = TU.build();
1161 auto Index = TU.index();
1163 ElementsAre(AllOf(
sym(
"add"),
1167 ElementsAre(AllOf(
sym(
"MACRO"),
1171TEST(LocateSymbol, AllMulti) {
1178 struct ExpectedRanges {
1180 std::optional<Range> WantDef;
1182 const char *Tests[] = {
1184 @interface $decl0[[Cat]]
1186 @implementation $def0[[Cat]]
1188 @interface $decl1[[Ca^t]] (Extension)
1191 @implementation $def1[[Cat]] (Extension)
1197 @interface $decl0[[Cat]]
1199 @implementation $def0[[Cat]]
1201 @interface $decl1[[Cat]] (Extension)
1204 @implementation $def1[[Ca^t]] (Extension)
1210 @interface $decl0[[Cat]]
1212 @interface $decl1[[Ca^t]] ()
1215 @implementation $def0[[$def1[[Cat]]]]
1220 for (
const char *Test : Tests) {
1222 std::vector<ExpectedRanges> Ranges;
1223 for (
int Idx = 0;
true; Idx++) {
1224 bool HasDecl = !
T.ranges(
"decl" + std::to_string(Idx)).empty();
1225 bool HasDef = !
T.ranges(
"def" + std::to_string(Idx)).empty();
1226 if (!HasDecl && !HasDef)
1228 ExpectedRanges
Range;
1230 Range.WantDecl =
T.range(
"decl" + std::to_string(Idx));
1232 Range.WantDef =
T.range(
"def" + std::to_string(Idx));
1233 Ranges.push_back(
Range);
1237 TU.
Code = std::string(
T.code());
1238 TU.ExtraArgs.push_back(
"-xobjective-c++");
1240 auto AST = TU.build();
1243 ASSERT_THAT(Results, ::testing::SizeIs(Ranges.size())) << Test;
1244 for (
size_t Idx = 0; Idx < Ranges.size(); Idx++) {
1245 EXPECT_EQ(Results[Idx].PreferredDeclaration.range, Ranges[Idx].WantDecl)
1246 <<
"($decl" << Idx <<
")" << Test;
1247 std::optional<Range> GotDef;
1249 GotDef = Results[Idx].Definition->range;
1250 EXPECT_EQ(GotDef, Ranges[Idx].WantDef) <<
"($def" << Idx <<
")" << Test;
1258TEST(LocateSymbol, Warnings) {
1259 const char *Tests[] = {
1260 R
"cpp(// Field, GNU old-style field designator
1261 struct Foo { int [[x]]; };
1263 Foo bar = { ^x : 1 };
1270 int main() { return ^MACRO; }
1276 for (
const char *Test : Tests) {
1278 std::optional<Range> WantDecl;
1279 std::optional<Range> WantDef;
1280 if (!
T.ranges().empty())
1281 WantDecl = WantDef =
T.range();
1282 if (!
T.ranges(
"decl").empty())
1283 WantDecl =
T.range(
"decl");
1284 if (!
T.ranges(
"def").empty())
1285 WantDef =
T.range(
"def");
1288 TU.
Code = std::string(
T.code());
1290 auto AST = TU.build();
1294 EXPECT_THAT(Results, IsEmpty()) << Test;
1296 ASSERT_THAT(Results, ::testing::SizeIs(1)) << Test;
1297 EXPECT_EQ(Results[0].PreferredDeclaration.range, *WantDecl) << Test;
1298 std::optional<Range> GotDef;
1300 GotDef = Results[0].Definition->range;
1301 EXPECT_EQ(WantDef, GotDef) << Test;
1306TEST(LocateSymbol, TextualSmoke) {
1309 struct [[MyClass]] {};
1310 // Comment mentioning M^yClass
1314 auto AST = TU.build();
1315 auto Index = TU.index();
1318 ElementsAre(AllOf(
sym(
"MyClass",
T.range(),
T.range()),
1322TEST(LocateSymbol, Textual) {
1323 const char *Tests[] = {
1325 struct [[MyClass]] {};
1326 // Comment mentioning M^yClass
1330 // Not triggered for string literal tokens.
1331 const char* s = "String literal mentioning M^yClass";
1333 R"cpp(// Ifdef'ed out code
1334 struct [[MyClass]] {};
1339 R"cpp(// Macro definition
1340 struct [[MyClass]] {};
1341 #define DECLARE_MYCLASS_OBJ(name) M^yClass name;
1343 R"cpp(// Invalid code
1345 int myFunction(int);
1346 // Not triggered for token which survived preprocessing.
1347 int var = m^yFunction();
1350 for (
const char *Test : Tests) {
1352 std::optional<Range> WantDecl;
1353 if (!
T.ranges().empty())
1354 WantDecl =
T.range();
1358 auto AST = TU.build();
1359 auto Index = TU.index();
1362 AST.getTokens(),
AST.getLangOpts());
1364 ADD_FAILURE() <<
"No word touching point!" << Test;
1368 testPath(TU.Filename), ASTNodeKind());
1371 EXPECT_THAT(Results, IsEmpty()) << Test;
1373 ASSERT_THAT(Results, ::testing::SizeIs(1)) << Test;
1374 EXPECT_EQ(Results[0].PreferredDeclaration.range, *WantDecl) << Test;
1379TEST(LocateSymbol, Ambiguous) {
1384 $ConstructorLoc[[Foo]](const char*);
1392 const char* str = "123";
1394 Foo b = Foo($2^str);
1399 Foo ab$8^cd("asdf");
1400 Foo foox = Fo$9^o("asdf");
1401 Foo abcde$10^("asdf");
1402 Foo foox2 = Foo$11^("asdf");
1405 template <typename T>
1407 void $NonstaticOverload1[[bar]](int);
1408 void $NonstaticOverload2[[bar]](float);
1410 static void $StaticOverload1[[baz]](int);
1411 static void $StaticOverload2[[baz]](float);
1414 template <typename T, typename U>
1415 void dependent_call(S<T> s, U u) {
1423 TU.ExtraArgs.push_back(
"-fno-delayed-template-parsing");
1424 auto AST = TU.build();
1439 ElementsAre(
sym(
"Foo",
T.range(
"ConstructorLoc"), std::nullopt)));
1441 ElementsAre(
sym(
"Foo",
T.range(
"ConstructorLoc"), std::nullopt)));
1446 UnorderedElementsAre(
1447 sym(
"bar",
T.range(
"NonstaticOverload1"), std::nullopt),
1448 sym(
"bar",
T.range(
"NonstaticOverload2"), std::nullopt)));
1450 UnorderedElementsAre(
1451 sym(
"baz",
T.range(
"StaticOverload1"), std::nullopt),
1452 sym(
"baz",
T.range(
"StaticOverload2"), std::nullopt)));
1455TEST(LocateSymbol, TextualDependent) {
1461 void $FooLoc[[uniqueMethodName]]();
1464 void $BarLoc[[uniqueMethodName]]();
1468 template <typename T>
1470 t.u^niqueMethodName();
1474 TU.Code = std::string(Source.code());
1475 TU.HeaderCode = std::string(Header.code());
1476 auto AST = TU.build();
1477 auto Index = TU.index();
1484 UnorderedElementsAre(
1485 sym(
"uniqueMethodName", Header.range(
"FooLoc"), std::nullopt),
1486 sym(
"uniqueMethodName", Header.range(
"BarLoc"), std::nullopt)));
1490 const char *Tests[] = {
1492 template <class T> struct function {};
1493 template <class T> using [[callback]] = function<T()>;
1502 typedef Foo [[Bar]];
1508 using [[Bar]] = Foo; // definition
1521 namespace ns { class [[Foo]] {}; }
1526 namespace ns { int [[x]](char); int [[x]](double); }
1531 namespace ns { int [[x]](char); int x(double); }
1537 namespace ns { class [[Foo]] {}; }
1545 typedef Foo [[Ba^r]];
1549 using [[B^ar]] = Foo;
1554 template <typename T>
1558 template <typename T>
1559 struct Derived : Base<T> {
1560 using Base<T>::w^aldo;
1565 for (
const auto *Case : Tests) {
1570 UnorderedPointwise(declRange(),
T.ranges()));
1574TEST(LocateSymbol, RelPathsInCompileCommand) {
1579#include "header_in_preamble.h"
1581#include "header_not_in_preamble.h"
1582int baz = f$p1^oo + bar_pre$p2^amble + bar_not_pre$p3^amble;
1586int [[bar_preamble]];
1590int [[bar_not_preamble]];
1595 SmallString<32> RelPathPrefix(
"..");
1596 llvm::sys::path::append(RelPathPrefix,
"src");
1597 std::string BuildDir =
testPath(
"build");
1604 auto FooCpp =
testPath(
"src/foo.cpp");
1605 FS.Files[FooCpp] =
"";
1606 auto HeaderInPreambleH =
testPath(
"src/header_in_preamble.h");
1607 FS.Files[HeaderInPreambleH] = std::string(HeaderInPreambleAnnotations.code());
1608 auto HeaderNotInPreambleH =
testPath(
"src/header_not_in_preamble.h");
1609 FS.Files[HeaderNotInPreambleH] =
1610 std::string(HeaderNotInPreambleAnnotations.code());
1617 EXPECT_TRUE(
bool(Locations)) <<
"findDefinitions returned an error";
1618 EXPECT_THAT(*Locations, ElementsAre(
sym(
"foo", SourceAnnotations.range(),
1619 SourceAnnotations.range())));
1623 EXPECT_TRUE(
bool(Locations)) <<
"findDefinitions returned an error";
1626 ElementsAre(
sym(
"bar_preamble", HeaderInPreambleAnnotations.range(),
1627 HeaderInPreambleAnnotations.range())));
1631 EXPECT_TRUE(
bool(Locations)) <<
"findDefinitions returned an error";
1632 EXPECT_THAT(*Locations,
1633 ElementsAre(
sym(
"bar_not_preamble",
1634 HeaderNotInPreambleAnnotations.range(),
1635 HeaderNotInPreambleAnnotations.range())));
1644 const char *SourceContents = R
"cpp(
1645 #include ^"$2^foo.h$3^"
1646 #include "$4^invalid.h"
1650 #in$5^clude "$6^foo.h"$7^
1653 FS.Files[FooCpp] = std::string(SourceAnnotations.code());
1660 FS.Files[FooH] = std::string(HeaderAnnotations.code());
1667 ASSERT_TRUE(
bool(Locations)) <<
"locateSymbolAt returned an error";
1668 EXPECT_THAT(*Locations, ElementsAre(
sym(
"foo.h", HeaderAnnotations.range(),
1669 HeaderAnnotations.range())));
1673 ASSERT_TRUE(
bool(Locations)) <<
"locateSymbolAt returned an error";
1674 EXPECT_THAT(*Locations, ElementsAre(
sym(
"foo.h", HeaderAnnotations.range(),
1675 HeaderAnnotations.range())));
1678 ASSERT_TRUE(
bool(Locations)) <<
"locateSymbolAt returned an error";
1679 EXPECT_THAT(*Locations, ElementsAre(
sym(
"foo.h", HeaderAnnotations.range(),
1680 HeaderAnnotations.range())));
1684 ASSERT_TRUE(
bool(Locations)) <<
"locateSymbolAt returned an error";
1685 EXPECT_THAT(*Locations, ElementsAre(
sym(
"foo.h", HeaderAnnotations.range(),
1686 HeaderAnnotations.range())));
1690 ASSERT_TRUE(
bool(Locations)) <<
"locateSymbolAt returned an error";
1691 EXPECT_THAT(*Locations, IsEmpty());
1694 ASSERT_TRUE(
bool(Locations)) <<
"locateSymbolAt returned an error";
1695 EXPECT_THAT(*Locations, ElementsAre(
sym(
"foo.h", HeaderAnnotations.range(),
1696 HeaderAnnotations.range())));
1699 ASSERT_TRUE(
bool(Locations)) <<
"locateSymbolAt returned an error";
1700 EXPECT_THAT(*Locations, ElementsAre(
sym(
"foo.h", HeaderAnnotations.range(),
1701 HeaderAnnotations.range())));
1708 FS.Files[FooM] = std::string(ObjC.code());
1712 ASSERT_TRUE(
bool(Locations)) <<
"locateSymbolAt returned an error";
1713 EXPECT_THAT(*Locations, ElementsAre(
sym(
"foo.h", HeaderAnnotations.range(),
1714 HeaderAnnotations.range())));
1717TEST(LocateSymbol, WithPreamble) {
1726 Annotations FooWithHeader(R
"cpp(#include "fo^o.h")cpp");
1727 Annotations FooWithoutHeader(R"cpp(double [[fo^o]]();)cpp");
1729 FS.Files[FooCpp] = std::string(FooWithHeader.code());
1733 FS.Files[FooH] = std::string(FooHeader.code());
1739 ElementsAre(
sym(
"foo.h", FooHeader.range(), FooHeader.range())));
1742 Server.addDocument(FooCpp, FooWithoutHeader.code(),
"null",
1748 ElementsAre(
sym(
"foo", FooWithoutHeader.range(), std::nullopt)));
1753 Server.addDocument(FooCpp, FooWithoutHeader.code(),
"null",
1758 ElementsAre(
sym(
"foo", FooWithoutHeader.range(), std::nullopt)));
1761TEST(LocateSymbol, NearbyTokenSmoke) {
1763 // prints e^rr and crashes
1764 void die(const char* [[err]]);
1769 ElementsAre(
sym(
"err",
T.range(),
T.range())));
1772TEST(LocateSymbol, NearbyIdentifier) {
1773 const char *Tests[] = {
1775 // regular identifiers (won't trigger)
1780 // disabled preprocessor sections
1792 // not triggered by string literals
1794 const char* greeting = "h^ello, world";
1798 // can refer to macro invocations
1805 // can refer to macro invocations (even if they expand to nothing)
1812 // prefer nearest occurrence, backwards is worse than forwards
1821 // short identifiers find near results
1826 // short identifiers don't find far results
1839 // prefer nearest occurrence even if several matched tokens
1840 // have the same value of `floor(log2(<token line> - <word line>))`.
1842 int x = hello, y = hello;
1846 for (
const char *Test : Tests) {
1849 const auto &SM =
AST.getSourceManager();
1850 std::optional<Range> Nearby;
1853 AST.getTokens(),
AST.getLangOpts());
1855 ADD_FAILURE() <<
"No word at point! " << Test;
1860 Tok->location(), Tok->endLocation()));
1861 if (
T.ranges().empty())
1862 EXPECT_THAT(Nearby, Eq(std::nullopt)) << Test;
1864 EXPECT_EQ(Nearby,
T.range()) << Test;
1868TEST(FindImplementations, Inheritance) {
1869 llvm::StringRef Test = R
"cpp(
1871 virtual void F$1^oo();
1874 struct $0[[Child1]] : Base {
1875 void $1[[Fo$3^o]]() override;
1876 virtual void B$2^ar();
1877 void Concrete(); // No implementations for concrete methods.
1879 struct Child2 : Child1 {
1880 void $3[[Foo]]() override;
1881 void $2[[Bar]]() override;
1883 void FromReference() {
1892 // CRTP should work.
1893 template<typename T>
1894 struct $5^TemplateBase {};
1895 struct $5[[Child3]] : public TemplateBase<Child3> {};
1898 void LocationFunction() {
1899 struct $0[[LocalClass1]] : Base {
1900 void $1[[Foo]]() override;
1902 struct $6^LocalBase {
1903 virtual void $7^Bar();
1905 struct $6[[LocalClass2]]: LocalBase {
1906 void $7[[Bar]]() override;
1913 auto AST = TU.build();
1914 auto Index = TU.index();
1915 for (StringRef
Label : {
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7"}) {
1916 for (
const auto &Point : Code.points(
Label)) {
1918 UnorderedPointwise(declRange(), Code.ranges(
Label)))
1919 << Code.code() <<
" at " << Point <<
" for Label " <<
Label;
1924TEST(FindImplementations, InheritanceObjC) {
1925 llvm::StringRef Test = R
"objc(
1926 @interface $base^Base
1930 - (void)$protocol^protocol;
1932 @interface $ChildDecl[[Child]] : Base <Protocol>
1934 - (void)$fooDecl[[foo]];
1936 @implementation $ChildDef[[Child]]
1938 - (void)$fooDef[[foo]] {}
1939 - (void)$protocolDef[[protocol]] {}
1945 TU.ExtraArgs.push_back(
"-xobjective-c++");
1946 auto AST = TU.build();
1947 auto Index = TU.index();
1949 UnorderedElementsAre(
sym(
"Child", Code.range(
"ChildDecl"),
1950 Code.range(
"ChildDef"))));
1952 UnorderedElementsAre(
1953 sym(
"foo", Code.range(
"fooDecl"), Code.range(
"fooDef"))));
1955 UnorderedElementsAre(
sym(
"protocol", Code.range(
"protocolDef"),
1956 Code.range(
"protocolDef"))));
1959TEST(FindImplementations, CaptureDefinition) {
1960 llvm::StringRef Test = R
"cpp(
1962 virtual void F^oo();
1964 struct Child1 : Base {
1965 void $Decl[[Foo]]() override;
1967 struct Child2 : Base {
1968 void $Child2[[Foo]]() override;
1970 void Child1::$Def[[Foo]]() { /* Definition */ }
1974 auto AST = TU.build();
1977 UnorderedElementsAre(
sym(
"Foo", Code.range(
"Decl"), Code.range(
"Def")),
1978 sym(
"Foo", Code.range(
"Child2"), std::nullopt)))
1984 struct $Target[[Target]] { operator int() const; };
1985 struct Aggregate { Target a, b; };
1989 template <typename T> struct $smart_ptr[[smart_ptr]] {
1996 for (
const llvm::StringRef Case : {
2000 "a^uto x = Target{};",
2001 "namespace m { Target tgt; } auto x = m^::tgt;",
2002 "Target funcCall(); auto x = ^funcCall();",
2003 "Aggregate a = { {}, ^{} };",
2004 "Aggregate a = { ^.a=t, };",
2005 "struct X { Target a; X() : ^a() {} };",
2006 "^using T = Target; ^T foo();",
2007 "^template <int> Target foo();",
2008 "void x() { try {} ^catch(Target e) {} }",
2009 "void x() { ^throw t; }",
2010 "int x() { ^return t; }",
2011 "void x() { ^switch(t) {} }",
2012 "void x() { ^delete (Target*)nullptr; }",
2013 "Target& ^tref = t;",
2014 "void x() { ^if (t) {} }",
2015 "void x() { ^while (t) {} }",
2016 "void x() { ^do { } while (t); }",
2017 "void x() { ^make(); }",
2018 "void x(smart_ptr<Target> &t) { t.^get(); }",
2019 "^auto x = []() { return t; };",
2020 "Target* ^tptr = &t;",
2021 "Target ^tarray[3];",
2024 TU.Code =
A.code().str();
2027 ASSERT_GT(
A.points().size(), 0u) << Case;
2028 for (
auto Pos :
A.points())
2031 sym(
"Target", HeaderA.range(
"Target"), HeaderA.range(
"Target"))))
2035 for (
const llvm::StringRef Case : {
2036 "smart_ptr<Target> ^tsmart;",
2039 TU.Code =
A.code().str();
2043 UnorderedElementsAre(
2044 sym(
"Target", HeaderA.range(
"Target"), HeaderA.range(
"Target")),
2045 sym(
"smart_ptr", HeaderA.range(
"smart_ptr"), HeaderA.range(
"smart_ptr"))
2061 ElementsAre(
sym(
"X",
A.range(
"decl"),
A.range(
"def"))));
2064TEST(FindType, Index) {
2066 // This definition is only available through the index.
2070 DefTU.HeaderFilename = "def.h";
2071 auto DefIdx = DefTU.index();
2081 ElementsAre(
sym(
"X",
A.range(), Def.range())));
2084void checkFindRefs(llvm::StringRef Test,
bool UseIndex =
false) {
2087 TU.ExtraArgs.push_back(
"-std=c++20");
2088 TU.ExtraArgs.push_back(
"-xobjective-c++");
2090 auto AST = TU.build();
2091 std::vector<Matcher<ReferencesResult::Reference>> ExpectedLocations;
2092 for (
const auto &[R,
Context] :
T.rangesWithPayload())
2093 ExpectedLocations.push_back(
2094 AllOf(rangeIs(R), containerIs(
Context), attrsAre(0u)));
2097 for (
const auto &[R,
Context] :
T.rangesWithPayload(
"def"))
2098 ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(
Context),
2101 for (
const auto &[R,
Context] :
T.rangesWithPayload(
"decl"))
2102 ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(
Context),
2104 for (
const auto &[R,
Context] :
T.rangesWithPayload(
"overridedecl"))
2105 ExpectedLocations.push_back(AllOf(
2106 rangeIs(R), containerIs(
Context),
2108 for (
const auto &[R,
Context] :
T.rangesWithPayload(
"overridedef"))
2109 ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(
Context),
2113 for (
const auto &P :
T.points()) {
2117 UnorderedElementsAreArray(ExpectedLocations))
2118 <<
"Failed for Refs at " <<
P <<
"\n"
2123TEST(FindReferences, WithinAST) {
2124 const char *Tests[] = {
2125 R
"cpp(// Local variable
2127 int $def(main)[[foo]];
2128 $(main)[[^foo]] = 2;
2129 int test1 = $(main)[[foo]];
2135 struct $def(ns1)[[Foo]] {};
2138 ns1::$(main)[[Fo^o]]* Params;
2142 R"cpp(// Forward declaration
2144 class $def[[Foo]] {};
2146 $(main)[[Fo^o]] foo;
2151 int $def[[foo]](int) { return 0; }
2153 auto *X = &$(main)[[^foo]];
2160 int $def(Foo)[[foo]];
2161 Foo() : $(Foo::Foo)[[foo]](0) {}
2165 f.$(main)[[f^oo]] = 1;
2169 R"cpp(// Method call
2170 struct Foo { int $decl(Foo)[[foo]](); };
2171 int Foo::$def(Foo)[[foo]]() { return 0; }
2174 f.$(main)[[^foo]]();
2178 R"cpp(// Constructor
2180 $decl(Foo)[[F^oo]](int);
2183 Foo f = $(foo)[[Foo]](42);
2188 typedef int $def[[Foo]];
2190 $(main)[[^Foo]] bar;
2195 namespace $decl[[ns]] { // FIXME: def?
2198 int main() { $(main)[[^ns]]::Foo foo; }
2204 #define CAT(X, Y) X##Y
2205 class $def[[Fo^o]] {};
2207 TYPE($(test)[[Foo]]) foo;
2208 $(test)[[FOO]] foo2;
2209 TYPE(TYPE($(test)[[Foo]])) foo3;
2210 $(test)[[CAT]](Fo, o) foo4;
2215 #define $def[[MA^CRO]](X) (X+1)
2217 int x = $[[MACRO]]($[[MACRO]](1));
2221 R"cpp(// Macro outside preamble
2223 #define $def[[MA^CRO]](X) (X+1)
2225 int x = $[[MACRO]]($[[MACRO]](1));
2230 int $def[[v^ar]] = 0;
2231 void foo(int s = $(foo)[[var]]);
2235 template <typename T>
2236 class $def[[Fo^o]] {};
2237 void func($(func)[[Foo]]<int>);
2241 template <typename T>
2242 class $def[[Foo]] {};
2243 void func($(func)[[Fo^o]]<int>);
2245 R"cpp(// Not touching any identifiers.
2247 $def(Foo)[[~]]Foo() {};
2251 f.$(foo)[[^~]]Foo();
2254 R"cpp(// Lambda capture initializer
2256 int $def(foo)[[w^aldo]] = 42;
2257 auto lambda = [x = $(foo)[[waldo]]](){};
2260 R"cpp(// Renaming alias
2261 template <typename> class Vector {};
2262 using $def[[^X]] = Vector<int>;
2267 R"cpp(// Dependent code
2268 template <typename T> void $decl[[foo]](T t);
2269 template <typename T> void bar(T t) { $(bar)[[foo]](t); } // foo in bar is uninstantiated.
2270 void baz(int x) { $(baz)[[f^oo]](x); }
2275 void $decl(ns)[[foo]](S s);
2277 template <typename T> void foo(T t);
2278 // FIXME: Maybe report this foo as a ref to ns::foo (because of ADL)
2279 // when bar<ns::S> is instantiated?
2280 template <typename T> void bar(T t) { foo(t); }
2287 R"cpp(// unresolved member expression
2289 template <typename T> void $decl(Foo)[[b^ar]](T t);
2291 template <typename T> void test(Foo F, T t) {
2292 F.$(test)[[bar]](t);
2298 typedef int $def[[MyTypeD^ef]];
2299 enum MyEnum : $(MyEnum)[[MyTy^peDef]] { };
2302 typedef int $def[[MyType^Def]];
2303 enum MyEnum : $(MyEnum)[[MyTypeD^ef]];
2306 using $def[[MyTypeD^ef]] = int;
2307 enum MyEnum : $(MyEnum)[[MyTy^peDef]] { };
2311 bool $decl[[operator]]"" _u^dl(unsigned long long value);
2312 bool x = $(x)[[1_udl]];
2317 static void $decl(S)[[operator]] delete(void *);
2318 static void deleteObject(S *S) {
2319 $(S::deleteObject)[[de^lete]] S;
2325 const int $def[[F^oo]] = 0;
2327 [$(Bar)[[F^oo]]...$(Bar)[[Fo^o]] + 1] = 0,
2328 [$(Bar)[[^Foo]] + 2] = 1
2331 for (
const char *Test : Tests)
2332 checkFindRefs(Test);
2335TEST(FindReferences, ConceptsWithinAST) {
2336 constexpr llvm::StringLiteral Code = R
"cpp(
2338 concept $def[[IsSmal^l]] = sizeof(T) <= 8;
2341 concept IsSmallPtr = requires(T x) {
2342 { *x } -> $(IsSmallPtr)[[IsSmal^l]];
2345 $(i)[[IsSmall]] auto i = 'c';
2346 template<$(foo)[[IsSmal^l]] U> void foo();
2347 template<class U> void bar() requires $(bar)[[IsSmal^l]]<U>;
2348 template<class U> requires $(baz)[[IsSmal^l]]<U> void baz();
2349 static_assert([[IsSma^ll]]<char>);
2351 checkFindRefs(Code);
2354TEST(FindReferences, ConceptReq) {
2355 constexpr llvm::StringLiteral Code = R
"cpp(
2357 concept $def[[IsSmal^l]] = sizeof(T) <= 8;
2360 concept IsSmallPtr = requires(T x) {
2361 { *x } -> $(IsSmallPtr)[[IsSmal^l]];
2364 checkFindRefs(Code);
2367TEST(FindReferences, RequiresExprParameters) {
2368 constexpr llvm::StringLiteral Code = R
"cpp(
2370 concept IsSmall = sizeof(T) <= 8;
2373 concept IsSmallPtr = requires(T $def[[^x]]) {
2374 { *$(IsSmallPtr)[[^x]] } -> IsSmall;
2377 checkFindRefs(Code);
2380TEST(FindReferences, IncludeOverrides) {
2381 llvm::StringRef Test =
2385 virtu^al void $decl(Base)[[f^unc]]() ^= ^0;
2387 class Derived : public Base {
2389 void $overridedecl(Derived::func)[[func]]() override;
2391 void Derived::$overridedef[[func]]() {}
2392 class Derived2 : public Base {
2393 void $overridedef(Derived2::func)[[func]]() override {}
2395 void test(Derived* D, Base* B) {
2396 D->func(); // No references to the overrides.
2397 B->$(test)[[func]]();
2399 checkFindRefs(Test, true);
2402TEST(FindReferences, IncludeOverridesObjC) {
2403 llvm::StringRef Test =
2406 - (void)$decl(Base)[[f^unc]];
2408 @interface Derived : Base
2409 - (void)$overridedecl(Derived::func)[[func]];
2411 @implementation Derived
2412 - (void)$overridedef[[func]] {}
2414 void test(Derived *derived, Base *base) {
2415 [derived func]; // No references to the overrides.
2416 [base $(test)[[func]]];
2418 checkFindRefs(Test, true);
2421TEST(FindReferences, RefsToBaseMethod) {
2422 llvm::StringRef Test =
2426 virtual void $(BaseBase)[[func]]();
2428 class Base : public BaseBase {
2430 void $(Base)[[func]]() override;
2432 class Derived : public Base {
2434 void $decl(Derived)[[fu^nc]]() over^ride;
2436 void test(BaseBase* BB, Base* B, Derived* D) {
2437 // refs to overridden methods in complete type hierarchy are reported.
2438 BB->$(test)[[func]]();
2439 B->$(test)[[func]]();
2440 D->$(test)[[fu^nc]]();
2442 checkFindRefs(Test, true);
2445TEST(FindReferences, RefsToBaseMethodObjC) {
2446 llvm::StringRef Test =
2449 - (void)$(BaseBase)[[func]];
2451 @interface Base : BaseBase
2452 - (void)$(Base)[[func]];
2454 @interface Derived : Base
2455 - (void)$decl(Derived)[[fu^nc]];
2457 void test(BaseBase *bb, Base *b, Derived *d) {
2458 // refs to overridden methods in complete type hierarchy are reported.
2459 [bb $(test)[[func]]];
2460 [b $(test)[[func]]];
2461 [d $(test)[[fu^nc]]];
2463 checkFindRefs(Test, true);
2466TEST(FindReferences, MainFileReferencesOnly) {
2467 llvm::StringRef Test =
2471 // refs not from main file should not be included.
2477 TU.AdditionalFiles[
"foo.inc"] = R
"cpp(
2480 auto AST = TU.build();
2482 std::vector<Matcher<ReferencesResult::Reference>> ExpectedLocations;
2483 for (
const auto &R : Code.ranges())
2484 ExpectedLocations.push_back(rangeIs(R));
2486 ElementsAreArray(ExpectedLocations))
2490TEST(FindReferences, ExplicitSymbols) {
2491 const char *Tests[] = {
2493 struct Foo { Foo* $decl(Foo)[[self]]() const; };
2496 if (Foo* T = foo.$(f)[[^self]]()) {} // Foo member call expr.
2501 struct Foo { Foo(int); };
2504 return $(f)[[^b]]; // Foo constructor expr.
2513 g($(call)[[^f]]()); // Foo constructor expr.
2518 void $decl[[foo]](int);
2519 void $decl[[foo]](double);
2522 using ::$decl(ns)[[fo^o]];
2533 $(test)[[a]].operator bool();
2534 if ($(test)[[a^]]) {} // ignore implicit conversion-operator AST node
2539 for (
const char *Test : Tests)
2540 checkFindRefs(Test);
2543TEST(FindReferences, UsedSymbolsFromInclude) {
2544 const char *Tests[] = {
2545 R
"cpp( [[#include ^"bar.h"]]
2547 int fstBar = [[bar1]]();
2548 int sndBar = [[bar2]]();
2550 int macroBar = [[BAR]];
2551 std::vector<int> vec;
2554 R"cpp([[#in^clude <vector>]]
2555 std::[[vector]]<int> vec;
2559 [[#include ^"udl_header.h"]]
2563 for (
const char *Test : Tests) {
2566 TU.ExtraArgs.push_back(
"-std=c++20");
2567 TU.AdditionalFiles[
"bar.h"] = guard(R
"cpp(
2573 TU.AdditionalFiles["system/vector"] = guard(R
"cpp(
2579 TU.AdditionalFiles["udl_header.h"] = guard(R
"cpp(
2580 bool operator"" _b(unsigned long long value);
2582 TU.ExtraArgs.push_back("-isystem" +
testPath(
"system"));
2584 auto AST = TU.build();
2585 std::vector<Matcher<ReferencesResult::Reference>> ExpectedLocations;
2586 for (
const auto &R :
T.ranges())
2587 ExpectedLocations.push_back(AllOf(rangeIs(R), attrsAre(0u)));
2588 for (
const auto &P :
T.points())
2590 UnorderedElementsAreArray(ExpectedLocations))
2591 <<
"Failed for Refs at " <<
P <<
"\n"
2596TEST(FindReferences, NeedsIndexForSymbols) {
2597 const char *Header =
"int foo();";
2600 TU.
Code = std::string(Main.code());
2601 TU.HeaderCode = Header;
2602 auto AST = TU.build();
2607 ElementsAre(rangeIs(Main.range())));
2609 int $decl[[foo]]() { return 42; }
2610 void bar() { $bar(bar)[[foo]](); }
2611 struct S { void bar() { $S(S::bar)[[foo]](); } };
2612 namespace N { void bar() { $N(N::bar)[[foo]](); } }
2617 IndexedTU.
Code = std::string(IndexedMain.code());
2618 IndexedTU.Filename =
"Indexed.cpp";
2619 IndexedTU.HeaderCode = Header;
2625 rangeIs(Main.range()),
2626 AllOf(rangeIs(IndexedMain.range(
"decl")),
2629 AllOf(rangeIs(IndexedMain.range(
"bar")), containerIs(
"bar")),
2630 AllOf(rangeIs(IndexedMain.range(
"S")), containerIs(
"S::bar")),
2631 AllOf(rangeIs(IndexedMain.range(
"N")), containerIs(
"N::bar"))));
2634 EXPECT_EQ(1u, LimitRefs.References.size());
2635 EXPECT_TRUE(LimitRefs.HasMore);
2638 TU.Code = (
"\n\n" + Main.code()).str();
2640 ElementsAre(rangeIs(Main.range())));
2643TEST(FindReferences, NeedsIndexForMacro) {
2644 const char *Header =
"#define MACRO(X) (X+1)";
2647 int a = [[MA^CRO]](1);
2651 TU.Code = std::string(Main.code());
2652 TU.HeaderCode = Header;
2653 auto AST = TU.build();
2658 ElementsAre(rangeIs(Main.range())));
2661 int indexed_main() {
2662 int a = [[MACRO]](1);
2669 IndexedTU.
Code = std::string(IndexedMain.code());
2670 IndexedTU.Filename =
"Indexed.cpp";
2671 IndexedTU.HeaderCode = Header;
2674 ElementsAre(rangeIs(Main.range()), rangeIs(IndexedMain.range())));
2677 EXPECT_EQ(1u, LimitRefs.References.size());
2678 EXPECT_TRUE(LimitRefs.HasMore);
2681TEST(FindReferences, NoQueryForLocalSymbols) {
2682 struct RecordingIndex :
public MemIndex {
2683 mutable std::optional<llvm::DenseSet<SymbolID>> RefIDs;
2684 bool refs(
const RefsRequest &Req,
2685 llvm::function_ref<
void(
const Ref &)>)
const override {
2692 StringRef AnnotatedCode;
2697 {
"namespace { int ^x; }",
true},
2698 {
"static int ^x;",
true},
2700 {
"void foo() { int ^x; }",
false},
2701 {
"void foo() { struct ^x{}; }",
false},
2702 {
"auto lambda = []{ int ^x; };",
false},
2704 for (Test T : Tests) {
2710 EXPECT_NE(Rec.RefIDs, std::nullopt) <<
T.AnnotatedCode;
2712 EXPECT_EQ(Rec.RefIDs, std::nullopt) <<
T.AnnotatedCode;
2716TEST(GetNonLocalDeclRefs,
All) {
2718 llvm::StringRef AnnotatedCode;
2719 std::vector<std::string> ExpectedDecls;
2725 void ^foo(int baz) {
2734 class Foo { public: void foo(); };
2744 {"Bar",
"Bar::bar",
"Foo",
"Foo::foo"},
2750 class Foo { public: void foo() {} };
2751 class Bar { public: void bar() {} };
2762 template <typename T, template<typename> class Q>
2770 for (
const Case &C : Cases) {
2773 SourceLocation SL = llvm::cantFail(
2776 const FunctionDecl *FD =
2777 llvm::dyn_cast<FunctionDecl>(&
findDecl(
AST, [SL](
const NamedDecl &ND) {
2778 return ND.getLocation() == SL && llvm::isa<FunctionDecl>(ND);
2780 ASSERT_NE(FD,
nullptr);
2783 std::vector<std::string> Names;
2784 for (
const Decl *D : NonLocalDeclRefs) {
2785 if (
const auto *ND = llvm::dyn_cast<NamedDecl>(D))
2786 Names.push_back(ND->getQualifiedNameAsString());
2788 EXPECT_THAT(Names, UnorderedElementsAreArray(
C.ExpectedDecls))
2795 #define HEADER_AA "faa.h"
2796 #define HEADER_BB "fbb.h"
2797 #define GET_HEADER(X) HEADER_ ## X
2799 #/*comments*/include /*comments*/ $foo[["foo.h"]] //more comments
2800 int end_of_preamble = 0;
2801 #include $bar[[<bar.h>]]
2802 #include $AA[[GET_HEADER]](AA) // Some comment !
2803 # /* What about */ \
2804 include /* multiple line */ \
2805 $BB[[GET_HEADER]]( /* statements ? */ \
2810 TU.Code = std::string(MainCpp.code());
2811 TU.AdditionalFiles = {
2812 {"faa.h",
""}, {
"fbb.h",
""}, {
"foo.h",
""}, {
"bar.h",
""}};
2813 TU.ExtraArgs = {
"-isystem."};
2814 auto AST = TU.build();
std::vector< HeaderEntry > HeaderContents
Same as llvm::Annotations, but adjusts functions to LSP-specific types for positions and ranges.
Manages a collection of source files and derived data (ASTs, indexes), and provides language-aware fe...
static Options optsForTest()
A context is an immutable container for per-request data that must be propagated through layers that ...
MemIndex is a naive in-memory index suitable for a small set of symbols.
Stores and provides access to parsed AST.
FIXME: Skip testing on windows temporarily due to the different escaping code mode.
SymbolID getSymbolID(const Decl *D)
Gets the symbol ID for a declaration. Returned SymbolID might be null.
const NamedDecl & findDecl(ParsedAST &AST, llvm::StringRef QName)
Range halfOpenToRange(const SourceManager &SM, CharSourceRange R)
std::vector< DocumentHighlight > findDocumentHighlights(ParsedAST &AST, Position Pos)
Returns highlights for all usages of a symbol at Pos.
Symbol sym(llvm::StringRef QName, index::SymbolKind Kind, llvm::StringRef USRFormat, llvm::StringRef Signature)
std::vector< LocatedSymbol > locateSymbolTextually(const SpelledWord &Word, ParsedAST &AST, const SymbolIndex *Index, llvm::StringRef MainFilePath, ASTNodeKind NodeKind)
std::vector< DocumentLink > getDocumentLinks(ParsedAST &AST)
Get all document links.
MATCHER_P2(hasFlag, Flag, Path, "")
std::vector< LocatedSymbol > findType(ParsedAST &AST, Position Pos, const SymbolIndex *Index)
Returns symbols for types referenced at Pos.
ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit, const SymbolIndex *Index, bool AddContext)
Returns references of the symbol at a specified Pos.
std::string testPath(PathRef File, llvm::sys::path::Style Style)
std::vector< LocatedSymbol > locateSymbolAt(ParsedAST &AST, Position Pos, const SymbolIndex *Index)
Get definition of symbol at a specified Pos.
TEST(BackgroundQueueTest, Priority)
const syntax::Token * findNearbyIdentifier(const SpelledWord &Word, const syntax::TokenBuffer &TB)
void runAddDocument(ClangdServer &Server, PathRef File, llvm::StringRef Contents, llvm::StringRef Version, WantDiagnostics WantDiags, bool ForceRebuild)
llvm::Expected< std::vector< LocatedSymbol > > runLocateSymbolAt(ClangdServer &Server, PathRef File, Position Pos)
const Symbol & findSymbol(const SymbolSlab &Slab, llvm::StringRef QName)
llvm::Expected< SourceLocation > sourceLocationInMainFile(const SourceManager &SM, Position P)
Return the file location, corresponding to P.
@ No
Diagnostics must be generated for this snapshot.
std::vector< LocatedSymbol > findImplementations(ParsedAST &AST, Position Pos, const SymbolIndex *Index)
Returns implementations at a specified Pos:
llvm::DenseSet< const Decl * > getNonLocalDeclRefs(ParsedAST &AST, const FunctionDecl *FD)
Returns all decls that are referenced in the FD except local symbols.
@ Alias
This declaration is an alias that was referred to.
cppcoreguidelines::ProBoundsAvoidUncheckedContainerAccess P
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
A range in a text document that links to an internal or external resource, like another text document...
std::vector< Reference > References
static std::optional< SpelledWord > touching(SourceLocation SpelledLoc, const syntax::TokenBuffer &TB, const LangOptions &LangOpts)
SymbolID ID
The ID of the symbol.
static TestTU withHeaderCode(llvm::StringRef HeaderCode)
static TestTU withCode(llvm::StringRef Code)
static URIForFile canonicalize(llvm::StringRef AbsPath, llvm::StringRef TUPath)
Canonicalizes AbsPath via URI.