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();
52 const LocatedSymbol &Sym = ::testing::get<0>(arg);
54 return Sym.PreferredDeclaration.range ==
Range;
59Matcher<const std::vector<DocumentHighlight> &>
60highlightsFrom(
const Annotations &Test) {
61 std::vector<DocumentHighlight>
Expected;
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;
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();
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; }
320TEST(LocateSymbol, WithIndex) {
321 Annotations SymbolHeader(R
"cpp(
322 class $forward[[Forward]];
323 class $foo[[Foo]] {};
327 inline void $f2[[f2]]() {}
329 Annotations SymbolCpp(R"cpp(
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) {
343 Annotations Test(R
"cpp(// only declaration in AST.
349 EXPECT_THAT(LocateWithIndex(Test),
350 ElementsAre(sym("f1", Test.range(), SymbolCpp.range(
"f1"))));
352 Test = Annotations(R
"cpp(// definition in AST.
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"))));
368 Test = Annotations(R
"cpp(// definition in AST.
369 class [[Forward]] {};
373 LocateWithIndex(Test),
374 ElementsAre(sym("Forward", SymbolHeader.range(
"forward"), Test.range())));
377TEST(LocateSymbol, AnonymousStructFields) {
378 auto Code = Annotations(R
"cpp(
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) {
399 auto Code = Annotations(R
"cpp(
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, WithIndexPreferredLocation) {
415 Annotations SymbolHeader(R
"cpp(
416 class $p[[Proto]] {};
417 void $f[[func]]() {};
420 TU.HeaderCode = std::string(SymbolHeader.code());
421 TU.HeaderFilename = "x.proto";
422 auto Index = TU.index();
424 Annotations Test(R
"cpp(// only declaration in AST.
425 // Shift to make range different.
437 auto CodeGenLoc = SymbolHeader.range(
"p");
438 EXPECT_THAT(Locs, ElementsAre(
sym(
"Proto", CodeGenLoc, CodeGenLoc)));
442 auto CodeGenLoc = SymbolHeader.range(
"f");
443 EXPECT_THAT(Locs, ElementsAre(
sym(
"func", CodeGenLoc, CodeGenLoc)));
452 const char *Tests[] = {
465 R"cpp(// Local variable
475 struct [[MyClass]] {};
478 ns1::My^Class* Params;
482 R"cpp(// Function definition via pointer
489 R"cpp(// Function declaration via call
490 int $decl[[foo]](int);
497 struct Foo { int [[x]]; };
504 R"cpp(// Field, member initializer
511 R"cpp(// Field, field designator
512 struct Foo { int [[x]]; };
514 Foo bar = { .^x = 2 };
519 struct Foo { int $decl[[x]](); };
527 typedef int $decl[[Foo]];
533 R"cpp(// Template type parameter
534 template <typename [[T]]>
538 R"cpp(// Template template type parameter
539 template <template<typename> class [[T]]>
540 void foo() { ^T<int> t; }
544 namespace $decl[[ns]] {
545 struct Foo { static void bar(); };
547 int main() { ^ns::Foo::bar(); }
551 class TTT { public: int a; };
552 #define [[FF]](S) if (int b = S.a) {}
559 R"cpp(// Macro argument
561 #define ADDRESSOF(X) &X;
562 int *j = ADDRESSOF(^i);
564 R"cpp(// Macro argument appearing multiple times in expansion
565 #define VALIDATE_TYPE(x) (void)x;
566 #define ASSERT(expr) \
568 VALIDATE_TYPE(expr); \
571 bool [[waldo]]() { return true; }
576 R"cpp(// Symbol concatenated inside macro (not supported)
578 #define POINTER(X) p ## X;
579 int x = *POINTER(^i);
582 R"cpp(// Forward class declaration
584 class $def[[Foo]] {};
588 R"cpp(// Function declaration
591 void $def[[foo]]() {}
595 #define FF(name) class name##_Test {};
597 void f() { my^_Test a; }
601 #define FF() class [[Test]] {};
603 void f() { T^est a; }
606 R"cpp(// explicit template specialization
607 template <typename T>
608 struct Foo { void bar() {} };
611 struct [[Foo]]<int> { void bar() {} };
619 R"cpp(// implicit template specialization
620 template <typename T>
621 struct [[Foo]] { void bar() {} };
623 struct Foo<int> { void bar() {} };
630 R"cpp(// partial template specialization
631 template <typename T>
632 struct Foo { void bar() {} };
633 template <typename T>
634 struct [[Foo]]<T*> { void bar() {} };
638 R"cpp(// function template specializations
648 R"cpp(// variable template decls
653 double [[var]]<int> = 10;
655 double y = va^r<int>;
658 R"cpp(// No implicit constructors
670 X& $decl[[operator]]++();
678 struct S1 { void f(); };
679 struct S2 { S1 * $decl[[operator]]->(); };
685 R"cpp(// Declaration of explicit template specialization
686 template <typename T>
687 struct $decl[[$def[[Foo]]]] {};
693 R"cpp(// Declaration of partial template specialization
694 template <typename T>
695 struct $decl[[$def[[Foo]]]] {};
697 template <typename T>
701 R"cpp(// Definition on ClassTemplateDecl
703 // Forward declaration.
707 template <typename T>
708 struct $def[[Foo]] {};
714 R"cpp(// auto builtin type (not supported)
718 R"cpp(// auto on lambda
723 R"cpp(// auto on struct
731 R"cpp(// decltype on struct
740 R"cpp(// decltype(auto) on struct
747 ^decltype(auto) k = j;
750 R"cpp(// auto on template class
751 template<typename T> class [[Foo]] {};
753 ^auto x = Foo<int>();
756 R"cpp(// auto on template class with forward declared class
757 template<typename T> class [[Foo]] {};
763 R"cpp(// auto on specialized template class
764 template<typename T> class Foo {};
765 template<> class [[Foo]]<int> {};
767 ^auto x = Foo<int>();
770 R"cpp(// auto on initializer list.
774 class [[initializer_list]] { const _E *a, *b; };
780 R"cpp(// auto function return with trailing type
782 ^auto test() -> decltype(Bar()) {
787 R"cpp(// decltype in trailing return type
789 auto test() -> ^decltype(Bar()) {
794 R"cpp(// auto in function return
801 R"cpp(// auto& in function return
809 R"cpp(// auto* in function return
817 R"cpp(// const auto& in function return
819 const ^auto& test() {
825 R"cpp(// auto lambda param where there's a single instantiation
827 auto Lambda = [](^auto){ return 0; };
828 int x = Lambda(Bar{});
831 R"cpp(// decltype(auto) in function return
833 ^decltype(auto) test() {
838 R"cpp(// decltype of function with trailing return type.
840 auto test() -> decltype(Bar()) {
844 ^decltype(test()) i = test();
848 R"cpp(// Override specifier jumps to overridden method
849 class Y { virtual void $decl[[a]]() = 0; };
850 class X : Y { void a() ^override {} };
853 R"cpp(// Final specifier jumps to overridden method
854 class Y { virtual void $decl[[a]]() = 0; };
855 class X : Y { void a() ^final {} };
858 R"cpp(// Heuristic resolution of dependent method
859 template <typename T>
864 template <typename T>
870 R"cpp(// Heuristic resolution of dependent method via this->
871 template <typename T>
879 R"cpp(// Heuristic resolution of dependent static method
880 template <typename T>
882 static void [[bar]]() {}
885 template <typename T>
891 R"cpp(// Heuristic resolution of dependent method
892 // invoked via smart pointer
893 template <typename> struct S { void [[foo]]() {} };
894 template <typename T> struct unique_ptr {
897 template <typename T>
898 void test(unique_ptr<S<T>>& V) {
903 R"cpp(// Heuristic resolution of dependent enumerator
904 template <typename T>
906 enum class E { [[A]], B };
912 typedef int $decl[[MyTypeDef]];
913 enum Foo : My^TypeDef {};
916 typedef int $decl[[MyTypeDef]];
917 enum Foo : My^TypeDef;
920 using $decl[[MyTypeDef]] = int;
921 enum Foo : My^TypeDef {};
926 @protocol $decl[[Dog]]
929 id<Do^g> getDoggo() {
939 @interface $decl[[Cat]] (Exte^nsion)
942 @implementation $def[[Cat]] (Extension)
954 R"objc(// Prefer interface definition over forward declaration
956 @interface $decl[[Foo]]
965 @interface $decl[[Foo]]
967 @implementation $def[[Foo]]
974 R"objc(// Method decl and definition for ObjC class.
976 - (void)$decl[[meow]];
979 - (void)$def[[meow]] {}
981 void makeNoise(Cat *kitty) {
986 R"objc(// Method decl and definition for ObjC category.
989 @interface Dog (Play)
990 - (void)$decl[[runAround]];
992 @implementation Dog (Play)
993 - (void)$def[[runAround]] {}
995 void play(Dog *dog) {
1000 R"objc(// Method decl and definition for ObjC class extension.
1004 - (void)$decl[[howl]];
1007 - (void)$def[[howl]] {}
1009 void play(Dog *dog) {
1014 struct PointerIntPairInfo {
1015 static void *getPointer(void *Value);
1018 template <typename Info = PointerIntPairInfo> struct PointerIntPair {
1020 void *getPointer() const { return Info::get^Pointer(Value); }
1023 R"cpp(// Deducing this
1029 int x = wa^ldo.bar();
1032 for (
const char *Test : Tests) {
1033 Annotations
T(Test);
1034 std::optional<Range> WantDecl;
1035 std::optional<Range> WantDef;
1036 if (!
T.ranges().empty())
1037 WantDecl = WantDef =
T.range();
1038 if (!
T.ranges(
"decl").empty())
1039 WantDecl =
T.range(
"decl");
1040 if (!
T.ranges(
"def").empty())
1041 WantDef =
T.range(
"def");
1044 TU.Code = std::string(
T.code());
1046 TU.ExtraArgs.push_back(
"-xobjective-c++");
1047 TU.ExtraArgs.push_back(
"-std=c++23");
1049 auto AST = TU.build();
1053 EXPECT_THAT(
Results, IsEmpty()) << Test;
1055 ASSERT_THAT(
Results, ::testing::SizeIs(1)) << Test;
1056 EXPECT_EQ(
Results[0].PreferredDeclaration.range, *WantDecl) << Test;
1058 std::optional<Range> GotDef;
1060 GotDef =
Results[0].Definition->range;
1061 EXPECT_EQ(WantDef, GotDef) << Test;
1065TEST(LocateSymbol, ValidSymbolID) {
1066 auto T = Annotations(R
"cpp(
1067 #define MACRO(x, y) ((x) + (y))
1068 int add(int x, int y) { return $MACRO^MACRO(x, y); }
1069 int sum = $add^add(1, 2);
1073 auto AST = TU.build();
1074 auto Index = TU.index();
1076 ElementsAre(AllOf(
sym(
"add"),
1080 ElementsAre(AllOf(
sym(
"MACRO"),
1084TEST(LocateSymbol, AllMulti) {
1091 struct ExpectedRanges {
1093 std::optional<Range> WantDef;
1095 const char *Tests[] = {
1097 @interface $decl0[[Cat]]
1099 @implementation $def0[[Cat]]
1101 @interface $decl1[[Ca^t]] (Extension)
1104 @implementation $def1[[Cat]] (Extension)
1110 @interface $decl0[[Cat]]
1112 @implementation $def0[[Cat]]
1114 @interface $decl1[[Cat]] (Extension)
1117 @implementation $def1[[Ca^t]] (Extension)
1123 @interface $decl0[[Cat]]
1125 @interface $decl1[[Ca^t]] ()
1128 @implementation $def0[[$def1[[Cat]]]]
1133 for (
const char *Test : Tests) {
1134 Annotations
T(Test);
1135 std::vector<ExpectedRanges> Ranges;
1136 for (
int Idx = 0;
true; Idx++) {
1137 bool HasDecl = !
T.ranges(
"decl" + std::to_string(Idx)).empty();
1138 bool HasDef = !
T.ranges(
"def" + std::to_string(Idx)).empty();
1139 if (!HasDecl && !HasDef)
1141 ExpectedRanges
Range;
1143 Range.WantDecl =
T.range(
"decl" + std::to_string(Idx));
1145 Range.WantDef =
T.range(
"def" + std::to_string(Idx));
1146 Ranges.push_back(Range);
1150 TU.Code = std::string(
T.code());
1151 TU.ExtraArgs.push_back(
"-xobjective-c++");
1153 auto AST = TU.build();
1156 ASSERT_THAT(
Results, ::testing::SizeIs(Ranges.size())) << Test;
1157 for (
size_t Idx = 0; Idx < Ranges.size(); Idx++) {
1158 EXPECT_EQ(
Results[Idx].PreferredDeclaration.range, Ranges[Idx].WantDecl)
1159 <<
"($decl" << Idx <<
")" << Test;
1160 std::optional<Range> GotDef;
1162 GotDef =
Results[Idx].Definition->range;
1163 EXPECT_EQ(GotDef, Ranges[Idx].WantDef) <<
"($def" << Idx <<
")" << Test;
1171TEST(LocateSymbol, Warnings) {
1172 const char *Tests[] = {
1173 R
"cpp(// Field, GNU old-style field designator
1174 struct Foo { int [[x]]; };
1176 Foo bar = { ^x : 1 };
1183 int main() { return ^MACRO; }
1189 for (
const char *Test : Tests) {
1190 Annotations
T(Test);
1191 std::optional<Range> WantDecl;
1192 std::optional<Range> WantDef;
1193 if (!
T.ranges().empty())
1194 WantDecl = WantDef =
T.range();
1195 if (!
T.ranges(
"decl").empty())
1196 WantDecl =
T.range(
"decl");
1197 if (!
T.ranges(
"def").empty())
1198 WantDef =
T.range(
"def");
1201 TU.Code = std::string(
T.code());
1203 auto AST = TU.build();
1207 EXPECT_THAT(
Results, IsEmpty()) << Test;
1209 ASSERT_THAT(
Results, ::testing::SizeIs(1)) << Test;
1210 EXPECT_EQ(
Results[0].PreferredDeclaration.range, *WantDecl) << Test;
1211 std::optional<Range> GotDef;
1213 GotDef =
Results[0].Definition->range;
1214 EXPECT_EQ(WantDef, GotDef) << Test;
1219TEST(LocateSymbol, TextualSmoke) {
1220 auto T = Annotations(
1222 struct [[MyClass]] {};
1223 // Comment mentioning M^yClass
1227 auto AST = TU.build();
1228 auto Index = TU.index();
1231 ElementsAre(AllOf(
sym(
"MyClass",
T.range(),
T.range()),
1235TEST(LocateSymbol, Textual) {
1236 const char *Tests[] = {
1238 struct [[MyClass]] {};
1239 // Comment mentioning M^yClass
1243 // Not triggered for string literal tokens.
1244 const char* s = "String literal mentioning M^yClass";
1246 R"cpp(// Ifdef'ed out code
1247 struct [[MyClass]] {};
1252 R"cpp(// Macro definition
1253 struct [[MyClass]] {};
1254 #define DECLARE_MYCLASS_OBJ(name) M^yClass name;
1256 R"cpp(// Invalid code
1258 int myFunction(int);
1259 // Not triggered for token which survived preprocessing.
1260 int var = m^yFunction();
1263 for (
const char *Test : Tests) {
1264 Annotations
T(Test);
1265 std::optional<Range> WantDecl;
1266 if (!
T.ranges().empty())
1267 WantDecl =
T.range();
1271 auto AST = TU.build();
1272 auto Index = TU.index();
1275 AST.getTokens(),
AST.getLangOpts());
1277 ADD_FAILURE() <<
"No word touching point!" << Test;
1281 testPath(TU.Filename), ASTNodeKind());
1284 EXPECT_THAT(
Results, IsEmpty()) << Test;
1286 ASSERT_THAT(
Results, ::testing::SizeIs(1)) << Test;
1287 EXPECT_EQ(
Results[0].PreferredDeclaration.range, *WantDecl) << Test;
1292TEST(LocateSymbol, Ambiguous) {
1293 auto T = Annotations(R
"cpp(
1297 $ConstructorLoc[[Foo]](const char*);
1305 const char* str = "123";
1307 Foo b = Foo($2^str);
1312 Foo ab$8^cd("asdf");
1313 Foo foox = Fo$9^o("asdf");
1314 Foo abcde$10^("asdf");
1315 Foo foox2 = Foo$11^("asdf");
1318 template <typename T>
1320 void $NonstaticOverload1[[bar]](int);
1321 void $NonstaticOverload2[[bar]](float);
1323 static void $StaticOverload1[[baz]](int);
1324 static void $StaticOverload2[[baz]](float);
1327 template <typename T, typename U>
1328 void dependent_call(S<T> s, U u) {
1336 TU.ExtraArgs.push_back(
"-fno-delayed-template-parsing");
1337 auto AST = TU.build();
1352 ElementsAre(
sym(
"Foo",
T.range(
"ConstructorLoc"), std::nullopt)));
1354 ElementsAre(
sym(
"Foo",
T.range(
"ConstructorLoc"), std::nullopt)));
1359 UnorderedElementsAre(
1360 sym(
"bar",
T.range(
"NonstaticOverload1"), std::nullopt),
1361 sym(
"bar",
T.range(
"NonstaticOverload2"), std::nullopt)));
1363 UnorderedElementsAre(
1364 sym(
"baz",
T.range(
"StaticOverload1"), std::nullopt),
1365 sym(
"baz",
T.range(
"StaticOverload2"), std::nullopt)));
1368TEST(LocateSymbol, TextualDependent) {
1372 Annotations Header(R
"cpp(
1374 void $FooLoc[[uniqueMethodName]]();
1377 void $BarLoc[[uniqueMethodName]]();
1380 Annotations Source(R"cpp(
1381 template <typename T>
1383 t.u^niqueMethodName();
1387 TU.Code = std::string(Source.code());
1388 TU.HeaderCode = std::string(Header.code());
1389 auto AST = TU.build();
1390 auto Index = TU.index();
1397 UnorderedElementsAre(
1398 sym(
"uniqueMethodName", Header.range(
"FooLoc"), std::nullopt),
1399 sym(
"uniqueMethodName", Header.range(
"BarLoc"), std::nullopt)));
1403 const char *Tests[] = {
1405 template <class T> struct function {};
1406 template <class T> using [[callback]] = function<T()>;
1415 typedef Foo [[Bar]];
1421 using [[Bar]] = Foo; // definition
1434 namespace ns { class [[Foo]] {}; }
1439 namespace ns { int [[x]](char); int [[x]](double); }
1444 namespace ns { int [[x]](char); int x(double); }
1450 namespace ns { class [[Foo]] {}; }
1458 typedef Foo [[Ba^r]];
1462 using [[B^ar]] = Foo;
1467 template <typename T>
1471 template <typename T>
1472 struct Derived : Base<T> {
1473 using Base<T>::w^aldo;
1478 for (
const auto *Case : Tests) {
1480 auto T = Annotations(Case);
1483 UnorderedPointwise(declRange(),
T.ranges()));
1487TEST(LocateSymbol, RelPathsInCompileCommand) {
1491 Annotations SourceAnnotations(R
"cpp(
1492#include "header_in_preamble.h"
1494#include "header_not_in_preamble.h"
1495int baz = f$p1^oo + bar_pre$p2^amble + bar_not_pre$p3^amble;
1498 Annotations HeaderInPreambleAnnotations(R"cpp(
1499int [[bar_preamble]];
1502 Annotations HeaderNotInPreambleAnnotations(R"cpp(
1503int [[bar_not_preamble]];
1508 SmallString<32> RelPathPrefix(
"..");
1509 llvm::sys::path::append(RelPathPrefix,
"src");
1511 MockCompilationDatabase CDB(
BuildDir, RelPathPrefix);
1517 auto FooCpp =
testPath(
"src/foo.cpp");
1518 FS.Files[FooCpp] =
"";
1519 auto HeaderInPreambleH =
testPath(
"src/header_in_preamble.h");
1520 FS.Files[HeaderInPreambleH] = std::string(HeaderInPreambleAnnotations.code());
1521 auto HeaderNotInPreambleH =
testPath(
"src/header_not_in_preamble.h");
1522 FS.Files[HeaderNotInPreambleH] =
1523 std::string(HeaderNotInPreambleAnnotations.code());
1530 EXPECT_TRUE(
bool(Locations)) <<
"findDefinitions returned an error";
1531 EXPECT_THAT(*Locations, ElementsAre(
sym(
"foo", SourceAnnotations.range(),
1532 SourceAnnotations.range())));
1536 EXPECT_TRUE(
bool(Locations)) <<
"findDefinitions returned an error";
1539 ElementsAre(
sym(
"bar_preamble", HeaderInPreambleAnnotations.range(),
1540 HeaderInPreambleAnnotations.range())));
1544 EXPECT_TRUE(
bool(Locations)) <<
"findDefinitions returned an error";
1545 EXPECT_THAT(*Locations,
1546 ElementsAre(
sym(
"bar_not_preamble",
1547 HeaderNotInPreambleAnnotations.range(),
1548 HeaderNotInPreambleAnnotations.range())));
1553 MockCompilationDatabase CDB;
1557 const char *SourceContents = R
"cpp(
1558 #include ^"$2^foo.h$3^"
1559 #include "$4^invalid.h"
1563 #in$5^clude "$6^foo.h"$7^
1565 Annotations SourceAnnotations(SourceContents);
1566 FS.Files[FooCpp] = std::string(SourceAnnotations.code());
1573 FS.Files[FooH] = std::string(HeaderAnnotations.code());
1580 ASSERT_TRUE(
bool(Locations)) <<
"locateSymbolAt returned an error";
1581 EXPECT_THAT(*Locations, ElementsAre(
sym(
"foo.h", HeaderAnnotations.range(),
1582 HeaderAnnotations.range())));
1586 ASSERT_TRUE(
bool(Locations)) <<
"locateSymbolAt returned an error";
1587 EXPECT_THAT(*Locations, ElementsAre(
sym(
"foo.h", HeaderAnnotations.range(),
1588 HeaderAnnotations.range())));
1591 ASSERT_TRUE(
bool(Locations)) <<
"locateSymbolAt returned an error";
1592 EXPECT_THAT(*Locations, ElementsAre(
sym(
"foo.h", HeaderAnnotations.range(),
1593 HeaderAnnotations.range())));
1597 ASSERT_TRUE(
bool(Locations)) <<
"locateSymbolAt returned an error";
1598 EXPECT_THAT(*Locations, ElementsAre(
sym(
"foo.h", HeaderAnnotations.range(),
1599 HeaderAnnotations.range())));
1603 ASSERT_TRUE(
bool(Locations)) <<
"locateSymbolAt returned an error";
1604 EXPECT_THAT(*Locations, IsEmpty());
1607 ASSERT_TRUE(
bool(Locations)) <<
"locateSymbolAt returned an error";
1608 EXPECT_THAT(*Locations, ElementsAre(
sym(
"foo.h", HeaderAnnotations.range(),
1609 HeaderAnnotations.range())));
1612 ASSERT_TRUE(
bool(Locations)) <<
"locateSymbolAt returned an error";
1613 EXPECT_THAT(*Locations, ElementsAre(
sym(
"foo.h", HeaderAnnotations.range(),
1614 HeaderAnnotations.range())));
1617 Annotations ObjC(R
"objc(
1621 FS.Files[FooM] = std::string(ObjC.code());
1625 ASSERT_TRUE(
bool(Locations)) <<
"locateSymbolAt returned an error";
1626 EXPECT_THAT(*Locations, ElementsAre(
sym(
"foo.h", HeaderAnnotations.range(),
1627 HeaderAnnotations.range())));
1630TEST(LocateSymbol, WithPreamble) {
1634 MockCompilationDatabase CDB;
1639 Annotations FooWithHeader(R
"cpp(#include "fo^o.h")cpp");
1640 Annotations FooWithoutHeader(R"cpp(double [[fo^o]]();)cpp");
1642 FS.Files[FooCpp] = std::string(FooWithHeader.code());
1645 Annotations FooHeader(R
"cpp([[]])cpp");
1646 FS.Files[FooH] = std::string(FooHeader.code());
1652 ElementsAre(
sym(
"foo.h", FooHeader.range(), FooHeader.range())));
1655 Server.addDocument(FooCpp, FooWithoutHeader.code(),
"null",
1661 ElementsAre(
sym(
"foo", FooWithoutHeader.range(), std::nullopt)));
1666 Server.addDocument(FooCpp, FooWithoutHeader.code(),
"null",
1671 ElementsAre(
sym(
"foo", FooWithoutHeader.range(), std::nullopt)));
1674TEST(LocateSymbol, NearbyTokenSmoke) {
1675 auto T = Annotations(R
"cpp(
1676 // prints e^rr and crashes
1677 void die(const char* [[err]]);
1682 ElementsAre(
sym(
"err",
T.range(),
T.range())));
1685TEST(LocateSymbol, NearbyIdentifier) {
1686 const char *Tests[] = {
1688 // regular identifiers (won't trigger)
1693 // disabled preprocessor sections
1705 // not triggered by string literals
1707 const char* greeting = "h^ello, world";
1711 // can refer to macro invocations
1718 // can refer to macro invocations (even if they expand to nothing)
1725 // prefer nearest occurrence, backwards is worse than forwards
1734 // short identifiers find near results
1739 // short identifiers don't find far results
1752 // prefer nearest occurrence even if several matched tokens
1753 // have the same value of `floor(log2(<token line> - <word line>))`.
1755 int x = hello, y = hello;
1759 for (
const char *Test : Tests) {
1760 Annotations
T(Test);
1762 const auto &SM =
AST.getSourceManager();
1763 std::optional<Range> Nearby;
1766 AST.getTokens(),
AST.getLangOpts());
1768 ADD_FAILURE() <<
"No word at point! " << Test;
1773 Tok->location(), Tok->endLocation()));
1774 if (
T.ranges().empty())
1775 EXPECT_THAT(Nearby, Eq(std::nullopt)) << Test;
1777 EXPECT_EQ(Nearby,
T.range()) << Test;
1781TEST(FindImplementations, Inheritance) {
1782 llvm::StringRef Test = R
"cpp(
1784 virtual void F$1^oo();
1787 struct $0[[Child1]] : Base {
1788 void $1[[Fo$3^o]]() override;
1789 virtual void B$2^ar();
1790 void Concrete(); // No implementations for concrete methods.
1792 struct Child2 : Child1 {
1793 void $3[[Foo]]() override;
1794 void $2[[Bar]]() override;
1796 void FromReference() {
1805 // CRTP should work.
1806 template<typename T>
1807 struct $5^TemplateBase {};
1808 struct $5[[Child3]] : public TemplateBase<Child3> {};
1811 void LocationFunction() {
1812 struct $0[[LocalClass1]] : Base {
1813 void $1[[Foo]]() override;
1815 struct $6^LocalBase {
1816 virtual void $7^Bar();
1818 struct $6[[LocalClass2]]: LocalBase {
1819 void $7[[Bar]]() override;
1824 Annotations Code(Test);
1826 auto AST = TU.build();
1827 auto Index = TU.index();
1828 for (StringRef
Label : {
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7"}) {
1829 for (
const auto &Point : Code.points(
Label)) {
1831 UnorderedPointwise(declRange(), Code.ranges(
Label)))
1832 << Code.code() <<
" at " << Point <<
" for Label " <<
Label;
1837TEST(FindImplementations, CaptureDefinition) {
1838 llvm::StringRef Test = R
"cpp(
1840 virtual void F^oo();
1842 struct Child1 : Base {
1843 void $Decl[[Foo]]() override;
1845 struct Child2 : Base {
1846 void $Child2[[Foo]]() override;
1848 void Child1::$Def[[Foo]]() { /* Definition */ }
1850 Annotations Code(Test);
1852 auto AST = TU.build();
1855 UnorderedElementsAre(
sym(
"Foo", Code.range(
"Decl"), Code.range(
"Def")),
1856 sym(
"Foo", Code.range(
"Child2"), std::nullopt)))
1861 Annotations HeaderA(R
"cpp(
1862 struct $Target[[Target]] { operator int() const; };
1863 struct Aggregate { Target a, b; };
1867 template <typename T> struct $smart_ptr[[smart_ptr]] {
1874 for (
const llvm::StringRef Case : {
1878 "a^uto x = Target{};",
1879 "namespace m { Target tgt; } auto x = m^::tgt;",
1880 "Target funcCall(); auto x = ^funcCall();",
1881 "Aggregate a = { {}, ^{} };",
1882 "Aggregate a = { ^.a=t, };",
1883 "struct X { Target a; X() : ^a() {} };",
1884 "^using T = Target; ^T foo();",
1885 "^template <int> Target foo();",
1886 "void x() { try {} ^catch(Target e) {} }",
1887 "void x() { ^throw t; }",
1888 "int x() { ^return t; }",
1889 "void x() { ^switch(t) {} }",
1890 "void x() { ^delete (Target*)nullptr; }",
1891 "Target& ^tref = t;",
1892 "void x() { ^if (t) {} }",
1893 "void x() { ^while (t) {} }",
1894 "void x() { ^do { } while (t); }",
1895 "void x() { ^make(); }",
1896 "void x(smart_ptr<Target> &t) { t.^get(); }",
1897 "^auto x = []() { return t; };",
1898 "Target* ^tptr = &t;",
1899 "Target ^tarray[3];",
1901 Annotations
A(Case);
1902 TU.Code =
A.code().str();
1903 ParsedAST
AST = TU.build();
1905 ASSERT_GT(
A.points().size(), 0u) << Case;
1906 for (
auto Pos :
A.points())
1909 sym(
"Target", HeaderA.range(
"Target"), HeaderA.range(
"Target"))))
1913 for (
const llvm::StringRef Case : {
1914 "smart_ptr<Target> ^tsmart;",
1916 Annotations
A(Case);
1917 TU.Code =
A.code().str();
1918 ParsedAST
AST = TU.build();
1921 UnorderedElementsAre(
1922 sym(
"Target", HeaderA.range(
"Target"), HeaderA.range(
"Target")),
1923 sym(
"smart_ptr", HeaderA.range(
"smart_ptr"), HeaderA.range(
"smart_ptr"))
1930 Annotations
A(R
"cpp(
1936 ParsedAST
AST = TU.build();
1939 ElementsAre(
sym(
"X",
A.range(
"decl"),
A.range(
"def"))));
1942TEST(FindType, Index) {
1943 Annotations Def(R
"cpp(
1944 // This definition is only available through the index.
1948 DefTU.HeaderFilename = "def.h";
1949 auto DefIdx = DefTU.index();
1951 Annotations
A(R
"cpp(
1956 ParsedAST
AST = TU.build();
1959 ElementsAre(
sym(
"X",
A.range(), Def.range())));
1962void checkFindRefs(llvm::StringRef Test,
bool UseIndex =
false) {
1963 Annotations
T(Test);
1965 TU.ExtraArgs.push_back(
"-std=c++20");
1967 auto AST = TU.build();
1968 std::vector<Matcher<ReferencesResult::Reference>> ExpectedLocations;
1969 for (
const auto &[R, Context] :
T.rangesWithPayload())
1970 ExpectedLocations.push_back(
1971 AllOf(rangeIs(R), containerIs(Context), attrsAre(0u)));
1974 for (
const auto &[R, Context] :
T.rangesWithPayload(
"def"))
1975 ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(Context),
1978 for (
const auto &[R, Context] :
T.rangesWithPayload(
"decl"))
1979 ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(Context),
1981 for (
const auto &[R, Context] :
T.rangesWithPayload(
"overridedecl"))
1982 ExpectedLocations.push_back(AllOf(
1983 rangeIs(R), containerIs(Context),
1985 for (
const auto &[R, Context] :
T.rangesWithPayload(
"overridedef"))
1986 ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(Context),
1990 for (
const auto &P :
T.points()) {
1994 UnorderedElementsAreArray(ExpectedLocations))
1995 <<
"Failed for Refs at " << P <<
"\n"
2000TEST(FindReferences, WithinAST) {
2001 const char *Tests[] = {
2002 R
"cpp(// Local variable
2004 int $def(main)[[foo]];
2005 $(main)[[^foo]] = 2;
2006 int test1 = $(main)[[foo]];
2012 struct $def(ns1)[[Foo]] {};
2015 ns1::$(main)[[Fo^o]]* Params;
2019 R"cpp(// Forward declaration
2021 class $def[[Foo]] {};
2023 $(main)[[Fo^o]] foo;
2028 int $def[[foo]](int) {}
2030 auto *X = &$(main)[[^foo]];
2037 int $def(Foo)[[foo]];
2038 Foo() : $(Foo::Foo)[[foo]](0) {}
2042 f.$(main)[[f^oo]] = 1;
2046 R"cpp(// Method call
2047 struct Foo { int $decl(Foo)[[foo]](); };
2048 int Foo::$def(Foo)[[foo]]() {}
2051 f.$(main)[[^foo]]();
2055 R"cpp(// Constructor
2057 $decl(Foo)[[F^oo]](int);
2060 Foo f = $(foo)[[Foo]](42);
2065 typedef int $def[[Foo]];
2067 $(main)[[^Foo]] bar;
2072 namespace $decl[[ns]] { // FIXME: def?
2075 int main() { $(main)[[^ns]]::Foo foo; }
2081 #define CAT(X, Y) X##Y
2082 class $def[[Fo^o]] {};
2084 TYPE($(test)[[Foo]]) foo;
2085 $(test)[[FOO]] foo2;
2086 TYPE(TYPE($(test)[[Foo]])) foo3;
2087 $(test)[[CAT]](Fo, o) foo4;
2092 #define $def[[MA^CRO]](X) (X+1)
2094 int x = $[[MACRO]]($[[MACRO]](1));
2098 R"cpp(// Macro outside preamble
2100 #define $def[[MA^CRO]](X) (X+1)
2102 int x = $[[MACRO]]($[[MACRO]](1));
2107 int $def[[v^ar]] = 0;
2108 void foo(int s = $(foo)[[var]]);
2112 template <typename T>
2113 class $def[[Fo^o]] {};
2114 void func($(func)[[Foo]]<int>);
2118 template <typename T>
2119 class $def[[Foo]] {};
2120 void func($(func)[[Fo^o]]<int>);
2122 R"cpp(// Not touching any identifiers.
2124 $def(Foo)[[~]]Foo() {};
2128 f.$(foo)[[^~]]Foo();
2131 R"cpp(// Lambda capture initializer
2133 int $def(foo)[[w^aldo]] = 42;
2134 auto lambda = [x = $(foo)[[waldo]]](){};
2137 R"cpp(// Renaming alias
2138 template <typename> class Vector {};
2139 using $def[[^X]] = Vector<int>;
2144 R"cpp(// Dependent code
2145 template <typename T> void $decl[[foo]](T t);
2146 template <typename T> void bar(T t) { $(bar)[[foo]](t); } // foo in bar is uninstantiated.
2147 void baz(int x) { $(baz)[[f^oo]](x); }
2152 void $decl(ns)[[foo]](S s);
2154 template <typename T> void foo(T t);
2155 // FIXME: Maybe report this foo as a ref to ns::foo (because of ADL)
2156 // when bar<ns::S> is instantiated?
2157 template <typename T> void bar(T t) { foo(t); }
2164 R"cpp(// unresolved member expression
2166 template <typename T> void $decl(Foo)[[b^ar]](T t);
2168 template <typename T> void test(Foo F, T t) {
2169 F.$(test)[[bar]](t);
2175 typedef int $def[[MyTypeD^ef]];
2176 enum MyEnum : $(MyEnum)[[MyTy^peDef]] { };
2179 typedef int $def[[MyType^Def]];
2180 enum MyEnum : $(MyEnum)[[MyTypeD^ef]];
2183 using $def[[MyTypeD^ef]] = int;
2184 enum MyEnum : $(MyEnum)[[MyTy^peDef]] { };
2188 bool $decl[[operator]]"" _u^dl(unsigned long long value);
2189 bool x = $(x)[[1_udl]];
2192 for (
const char *Test : Tests)
2193 checkFindRefs(Test);
2196TEST(FindReferences, ConceptsWithinAST) {
2197 constexpr llvm::StringLiteral Code = R
"cpp(
2199 concept $def[[IsSmal^l]] = sizeof(T) <= 8;
2202 concept IsSmallPtr = requires(T x) {
2203 { *x } -> $(IsSmallPtr)[[IsSmal^l]];
2206 $(i)[[IsSmall]] auto i = 'c';
2207 template<$(foo)[[IsSmal^l]] U> void foo();
2208 template<class U> void bar() requires $(bar)[[IsSmal^l]]<U>;
2209 template<class U> requires $(baz)[[IsSmal^l]]<U> void baz();
2210 static_assert([[IsSma^ll]]<char>);
2212 checkFindRefs(Code);
2215TEST(FindReferences, ConceptReq) {
2216 constexpr llvm::StringLiteral Code = R
"cpp(
2218 concept $def[[IsSmal^l]] = sizeof(T) <= 8;
2221 concept IsSmallPtr = requires(T x) {
2222 { *x } -> $(IsSmallPtr)[[IsSmal^l]];
2225 checkFindRefs(Code);
2228TEST(FindReferences, RequiresExprParameters) {
2229 constexpr llvm::StringLiteral Code = R
"cpp(
2231 concept IsSmall = sizeof(T) <= 8;
2234 concept IsSmallPtr = requires(T $def[[^x]]) {
2235 { *$(IsSmallPtr)[[^x]] } -> IsSmall;
2238 checkFindRefs(Code);
2241TEST(FindReferences, IncludeOverrides) {
2242 llvm::StringRef Test =
2246 virtu^al void $decl(Base)[[f^unc]]() ^= ^0;
2248 class Derived : public Base {
2250 void $overridedecl(Derived::func)[[func]]() override;
2252 void Derived::$overridedef[[func]]() {}
2253 class Derived2 : public Base {
2254 void $overridedef(Derived2::func)[[func]]() override {}
2256 void test(Derived* D, Base* B) {
2257 D->func(); // No references to the overrides.
2258 B->$(test)[[func]]();
2260 checkFindRefs(Test, true);
2263TEST(FindReferences, RefsToBaseMethod) {
2264 llvm::StringRef Test =
2268 virtual void $(BaseBase)[[func]]();
2270 class Base : public BaseBase {
2272 void $(Base)[[func]]() override;
2274 class Derived : public Base {
2276 void $decl(Derived)[[fu^nc]]() over^ride;
2278 void test(BaseBase* BB, Base* B, Derived* D) {
2279 // refs to overridden methods in complete type hierarchy are reported.
2280 BB->$(test)[[func]]();
2281 B->$(test)[[func]]();
2282 D->$(test)[[fu^nc]]();
2284 checkFindRefs(Test, true);
2287TEST(FindReferences, MainFileReferencesOnly) {
2288 llvm::StringRef Test =
2292 // refs not from main file should not be included.
2296 Annotations Code(Test);
2298 TU.AdditionalFiles[
"foo.inc"] = R
"cpp(
2301 auto AST = TU.build();
2303 std::vector<Matcher<ReferencesResult::Reference>> ExpectedLocations;
2304 for (
const auto &R : Code.ranges())
2305 ExpectedLocations.push_back(rangeIs(R));
2307 ElementsAreArray(ExpectedLocations))
2311TEST(FindReferences, ExplicitSymbols) {
2312 const char *Tests[] = {
2314 struct Foo { Foo* $decl(Foo)[[self]]() const; };
2317 if (Foo* T = foo.$(f)[[^self]]()) {} // Foo member call expr.
2322 struct Foo { Foo(int); };
2325 return $(f)[[^b]]; // Foo constructor expr.
2334 g($(call)[[^f]]()); // Foo constructor expr.
2339 void $decl[[foo]](int);
2340 void $decl[[foo]](double);
2343 using ::$decl(ns)[[fo^o]];
2354 $(test)[[a]].operator bool();
2355 if ($(test)[[a^]]) {} // ignore implicit conversion-operator AST node
2359 for (
const char *Test : Tests)
2360 checkFindRefs(Test);
2363TEST(FindReferences, UsedSymbolsFromInclude) {
2364 const char *Tests[] = {
2365 R
"cpp( [[#include ^"bar.h"]]
2367 int fstBar = [[bar1]]();
2368 int sndBar = [[bar2]]();
2370 int macroBar = [[BAR]];
2371 std::vector<int> vec;
2374 R"cpp([[#in^clude <vector>]]
2375 std::[[vector]]<int> vec;
2379 [[#include ^"udl_header.h"]]
2383 for (
const char *Test : Tests) {
2384 Annotations
T(Test);
2386 TU.ExtraArgs.push_back(
"-std=c++20");
2387 TU.AdditionalFiles[
"bar.h"] = guard(R
"cpp(
2393 TU.AdditionalFiles["system/vector"] = guard(R
"cpp(
2399 TU.AdditionalFiles["udl_header.h"] = guard(R
"cpp(
2400 bool operator"" _b(unsigned long long value);
2402 TU.ExtraArgs.push_back("-isystem" +
testPath(
"system"));
2404 auto AST = TU.build();
2405 std::vector<Matcher<ReferencesResult::Reference>> ExpectedLocations;
2406 for (
const auto &R :
T.ranges())
2407 ExpectedLocations.push_back(AllOf(rangeIs(R), attrsAre(0u)));
2408 for (
const auto &P :
T.points())
2410 UnorderedElementsAreArray(ExpectedLocations))
2411 <<
"Failed for Refs at " << P <<
"\n"
2416TEST(FindReferences, NeedsIndexForSymbols) {
2417 const char *Header =
"int foo();";
2418 Annotations Main(
"int main() { [[f^oo]](); }");
2420 TU.Code = std::string(Main.code());
2421 TU.HeaderCode = Header;
2422 auto AST = TU.build();
2427 ElementsAre(rangeIs(Main.range())));
2428 Annotations IndexedMain(R
"cpp(
2429 int $decl[[foo]]() { return 42; }
2430 void bar() { $bar(bar)[[foo]](); }
2431 struct S { void bar() { $S(S::bar)[[foo]](); } };
2432 namespace N { void bar() { $N(N::bar)[[foo]](); } }
2437 IndexedTU.Code = std::string(IndexedMain.code());
2438 IndexedTU.Filename =
"Indexed.cpp";
2439 IndexedTU.HeaderCode = Header;
2445 rangeIs(Main.range()),
2446 AllOf(rangeIs(IndexedMain.range(
"decl")),
2449 AllOf(rangeIs(IndexedMain.range(
"bar")), containerIs(
"bar")),
2450 AllOf(rangeIs(IndexedMain.range(
"S")), containerIs(
"S::bar")),
2451 AllOf(rangeIs(IndexedMain.range(
"N")), containerIs(
"N::bar"))));
2454 EXPECT_EQ(1u, LimitRefs.References.size());
2455 EXPECT_TRUE(LimitRefs.HasMore);
2458 TU.Code = (
"\n\n" + Main.code()).str();
2460 ElementsAre(rangeIs(Main.range())));
2463TEST(FindReferences, NeedsIndexForMacro) {
2464 const char *Header =
"#define MACRO(X) (X+1)";
2465 Annotations Main(R
"cpp(
2467 int a = [[MA^CRO]](1);
2471 TU.Code = std::string(Main.code());
2472 TU.HeaderCode = Header;
2473 auto AST = TU.build();
2478 ElementsAre(rangeIs(Main.range())));
2480 Annotations IndexedMain(R
"cpp(
2481 int indexed_main() {
2482 int a = [[MACRO]](1);
2488 IndexedTU.Code = std::string(IndexedMain.code());
2489 IndexedTU.Filename =
"Indexed.cpp";
2490 IndexedTU.HeaderCode = Header;
2493 ElementsAre(rangeIs(Main.range()), rangeIs(IndexedMain.range())));
2496 EXPECT_EQ(1u, LimitRefs.References.size());
2497 EXPECT_TRUE(LimitRefs.HasMore);
2500TEST(FindReferences, NoQueryForLocalSymbols) {
2501 struct RecordingIndex :
public MemIndex {
2502 mutable std::optional<llvm::DenseSet<SymbolID>> RefIDs;
2503 bool refs(
const RefsRequest &Req,
2504 llvm::function_ref<
void(
const Ref &)>)
const override {
2516 {
"namespace { int ^x; }",
true},
2517 {
"static int ^x;",
true},
2519 {
"void foo() { int ^x; }",
false},
2520 {
"void foo() { struct ^x{}; }",
false},
2521 {
"auto lambda = []{ int ^x; };",
false},
2523 for (Test T : Tests) {
2524 Annotations
File(
T.AnnotatedCode);
2529 EXPECT_NE(Rec.RefIDs, std::nullopt) <<
T.AnnotatedCode;
2531 EXPECT_EQ(Rec.RefIDs, std::nullopt) <<
T.AnnotatedCode;
2535TEST(GetNonLocalDeclRefs,
All) {
2538 std::vector<std::string> ExpectedDecls;
2544 void ^foo(int baz) {
2553 class Foo { public: void foo(); };
2563 {"Bar",
"Bar::bar",
"Foo",
"Foo::foo"},
2569 class Foo { public: void foo() {} };
2570 class Bar { public: void bar() {} };
2581 template <typename T, template<typename> class Q>
2589 for (
const Case &
C : Cases) {
2590 Annotations
File(
C.AnnotatedCode);
2592 SourceLocation SL = llvm::cantFail(
2595 const FunctionDecl *FD =
2596 llvm::dyn_cast<FunctionDecl>(&
findDecl(
AST, [SL](
const NamedDecl &ND) {
2597 return ND.getLocation() == SL && llvm::isa<FunctionDecl>(ND);
2599 ASSERT_NE(FD,
nullptr);
2602 std::vector<std::string> Names;
2603 for (
const Decl *D : NonLocalDeclRefs) {
2604 if (
const auto *ND = llvm::dyn_cast<NamedDecl>(D))
2605 Names.push_back(ND->getQualifiedNameAsString());
2607 EXPECT_THAT(Names, UnorderedElementsAreArray(
C.ExpectedDecls))
2613 Annotations MainCpp(R
"cpp(
2614 #/*comments*/include /*comments*/ $foo[["foo.h"]] //more comments
2615 int end_of_preamble = 0;
2616 #include $bar[[<bar.h>]]
2620 TU.Code = std::string(MainCpp.code());
2621 TU.AdditionalFiles = {{"foo.h",
""}, {
"bar.h",
""}};
2622 TU.ExtraArgs = {
"-isystem."};
2623 auto AST = TU.build();
2628 DocumentLink({MainCpp.range(
"foo"),
2630 DocumentLink({MainCpp.range(
"bar"),
const FunctionDecl * Decl
llvm::SmallString< 256U > Name
std::vector< CodeCompletionResult > Results
std::string AnnotatedCode
CharSourceRange Range
SourceRange for the file name.
std::vector< HeaderEntry > HeaderContents
std::vector< const char * > Expected
static Options optsForTest()
Token::Index index(const Token &T) const
Returns the index of T within the stream.
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.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
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.