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 for (
const char *Test : Tests) {
1024 Annotations
T(Test);
1025 std::optional<Range> WantDecl;
1026 std::optional<Range> WantDef;
1027 if (!
T.ranges().empty())
1028 WantDecl = WantDef =
T.range();
1029 if (!
T.ranges(
"decl").empty())
1030 WantDecl =
T.range(
"decl");
1031 if (!
T.ranges(
"def").empty())
1032 WantDef =
T.range(
"def");
1035 TU.Code = std::string(
T.code());
1037 TU.ExtraArgs.push_back(
"-xobjective-c++");
1039 auto AST = TU.build();
1043 EXPECT_THAT(
Results, IsEmpty()) << Test;
1045 ASSERT_THAT(
Results, ::testing::SizeIs(1)) << Test;
1046 EXPECT_EQ(
Results[0].PreferredDeclaration.range, *WantDecl) << Test;
1048 std::optional<Range> GotDef;
1050 GotDef =
Results[0].Definition->range;
1051 EXPECT_EQ(WantDef, GotDef) << Test;
1055TEST(LocateSymbol, ValidSymbolID) {
1056 auto T = Annotations(R
"cpp(
1057 #define MACRO(x, y) ((x) + (y))
1058 int add(int x, int y) { return $MACRO^MACRO(x, y); }
1059 int sum = $add^add(1, 2);
1063 auto AST = TU.build();
1064 auto Index = TU.index();
1066 ElementsAre(AllOf(
sym(
"add"),
1070 ElementsAre(AllOf(
sym(
"MACRO"),
1074TEST(LocateSymbol, AllMulti) {
1081 struct ExpectedRanges {
1083 std::optional<Range> WantDef;
1085 const char *Tests[] = {
1087 @interface $decl0[[Cat]]
1089 @implementation $def0[[Cat]]
1091 @interface $decl1[[Ca^t]] (Extension)
1094 @implementation $def1[[Cat]] (Extension)
1100 @interface $decl0[[Cat]]
1102 @implementation $def0[[Cat]]
1104 @interface $decl1[[Cat]] (Extension)
1107 @implementation $def1[[Ca^t]] (Extension)
1113 @interface $decl0[[Cat]]
1115 @interface $decl1[[Ca^t]] ()
1118 @implementation $def0[[$def1[[Cat]]]]
1123 for (
const char *Test : Tests) {
1124 Annotations
T(Test);
1125 std::vector<ExpectedRanges> Ranges;
1126 for (
int Idx = 0;
true; Idx++) {
1127 bool HasDecl = !
T.ranges(
"decl" + std::to_string(Idx)).empty();
1128 bool HasDef = !
T.ranges(
"def" + std::to_string(Idx)).empty();
1129 if (!HasDecl && !HasDef)
1131 ExpectedRanges
Range;
1133 Range.WantDecl =
T.range(
"decl" + std::to_string(Idx));
1135 Range.WantDef =
T.range(
"def" + std::to_string(Idx));
1136 Ranges.push_back(Range);
1140 TU.Code = std::string(
T.code());
1141 TU.ExtraArgs.push_back(
"-xobjective-c++");
1143 auto AST = TU.build();
1146 ASSERT_THAT(
Results, ::testing::SizeIs(Ranges.size())) << Test;
1147 for (
size_t Idx = 0; Idx < Ranges.size(); Idx++) {
1148 EXPECT_EQ(
Results[Idx].PreferredDeclaration.range, Ranges[Idx].WantDecl)
1149 <<
"($decl" << Idx <<
")" << Test;
1150 std::optional<Range> GotDef;
1152 GotDef =
Results[Idx].Definition->range;
1153 EXPECT_EQ(GotDef, Ranges[Idx].WantDef) <<
"($def" << Idx <<
")" << Test;
1161TEST(LocateSymbol, Warnings) {
1162 const char *Tests[] = {
1163 R
"cpp(// Field, GNU old-style field designator
1164 struct Foo { int [[x]]; };
1166 Foo bar = { ^x : 1 };
1173 int main() { return ^MACRO; }
1179 for (
const char *Test : Tests) {
1180 Annotations
T(Test);
1181 std::optional<Range> WantDecl;
1182 std::optional<Range> WantDef;
1183 if (!
T.ranges().empty())
1184 WantDecl = WantDef =
T.range();
1185 if (!
T.ranges(
"decl").empty())
1186 WantDecl =
T.range(
"decl");
1187 if (!
T.ranges(
"def").empty())
1188 WantDef =
T.range(
"def");
1191 TU.Code = std::string(
T.code());
1193 auto AST = TU.build();
1197 EXPECT_THAT(
Results, IsEmpty()) << Test;
1199 ASSERT_THAT(
Results, ::testing::SizeIs(1)) << Test;
1200 EXPECT_EQ(
Results[0].PreferredDeclaration.range, *WantDecl) << Test;
1201 std::optional<Range> GotDef;
1203 GotDef =
Results[0].Definition->range;
1204 EXPECT_EQ(WantDef, GotDef) << Test;
1209TEST(LocateSymbol, TextualSmoke) {
1210 auto T = Annotations(
1212 struct [[MyClass]] {};
1213 // Comment mentioning M^yClass
1217 auto AST = TU.build();
1218 auto Index = TU.index();
1221 ElementsAre(AllOf(
sym(
"MyClass",
T.range(),
T.range()),
1225TEST(LocateSymbol, Textual) {
1226 const char *Tests[] = {
1228 struct [[MyClass]] {};
1229 // Comment mentioning M^yClass
1233 // Not triggered for string literal tokens.
1234 const char* s = "String literal mentioning M^yClass";
1236 R"cpp(// Ifdef'ed out code
1237 struct [[MyClass]] {};
1242 R"cpp(// Macro definition
1243 struct [[MyClass]] {};
1244 #define DECLARE_MYCLASS_OBJ(name) M^yClass name;
1246 R"cpp(// Invalid code
1248 int myFunction(int);
1249 // Not triggered for token which survived preprocessing.
1250 int var = m^yFunction();
1253 for (
const char *Test : Tests) {
1254 Annotations
T(Test);
1255 std::optional<Range> WantDecl;
1256 if (!
T.ranges().empty())
1257 WantDecl =
T.range();
1261 auto AST = TU.build();
1262 auto Index = TU.index();
1265 AST.getTokens(),
AST.getLangOpts());
1267 ADD_FAILURE() <<
"No word touching point!" << Test;
1271 testPath(TU.Filename), ASTNodeKind());
1274 EXPECT_THAT(
Results, IsEmpty()) << Test;
1276 ASSERT_THAT(
Results, ::testing::SizeIs(1)) << Test;
1277 EXPECT_EQ(
Results[0].PreferredDeclaration.range, *WantDecl) << Test;
1282TEST(LocateSymbol, Ambiguous) {
1283 auto T = Annotations(R
"cpp(
1287 $ConstructorLoc[[Foo]](const char*);
1295 const char* str = "123";
1297 Foo b = Foo($2^str);
1302 Foo ab$8^cd("asdf");
1303 Foo foox = Fo$9^o("asdf");
1304 Foo abcde$10^("asdf");
1305 Foo foox2 = Foo$11^("asdf");
1308 template <typename T>
1310 void $NonstaticOverload1[[bar]](int);
1311 void $NonstaticOverload2[[bar]](float);
1313 static void $StaticOverload1[[baz]](int);
1314 static void $StaticOverload2[[baz]](float);
1317 template <typename T, typename U>
1318 void dependent_call(S<T> s, U u) {
1326 TU.ExtraArgs.push_back(
"-fno-delayed-template-parsing");
1327 auto AST = TU.build();
1342 ElementsAre(
sym(
"Foo",
T.range(
"ConstructorLoc"), std::nullopt)));
1344 ElementsAre(
sym(
"Foo",
T.range(
"ConstructorLoc"), std::nullopt)));
1349 UnorderedElementsAre(
1350 sym(
"bar",
T.range(
"NonstaticOverload1"), std::nullopt),
1351 sym(
"bar",
T.range(
"NonstaticOverload2"), std::nullopt)));
1353 UnorderedElementsAre(
1354 sym(
"baz",
T.range(
"StaticOverload1"), std::nullopt),
1355 sym(
"baz",
T.range(
"StaticOverload2"), std::nullopt)));
1358TEST(LocateSymbol, TextualDependent) {
1362 Annotations Header(R
"cpp(
1364 void $FooLoc[[uniqueMethodName]]();
1367 void $BarLoc[[uniqueMethodName]]();
1370 Annotations Source(R"cpp(
1371 template <typename T>
1373 t.u^niqueMethodName();
1377 TU.Code = std::string(Source.code());
1378 TU.HeaderCode = std::string(Header.code());
1379 auto AST = TU.build();
1380 auto Index = TU.index();
1387 UnorderedElementsAre(
1388 sym(
"uniqueMethodName", Header.range(
"FooLoc"), std::nullopt),
1389 sym(
"uniqueMethodName", Header.range(
"BarLoc"), std::nullopt)));
1393 const char *Tests[] = {
1395 template <class T> struct function {};
1396 template <class T> using [[callback]] = function<T()>;
1405 typedef Foo [[Bar]];
1411 using [[Bar]] = Foo; // definition
1424 namespace ns { class [[Foo]] {}; }
1429 namespace ns { int [[x]](char); int [[x]](double); }
1434 namespace ns { int [[x]](char); int x(double); }
1440 namespace ns { class [[Foo]] {}; }
1448 typedef Foo [[Ba^r]];
1452 using [[B^ar]] = Foo;
1457 template <typename T>
1461 template <typename T>
1462 struct Derived : Base<T> {
1463 using Base<T>::w^aldo;
1468 for (
const auto *Case : Tests) {
1470 auto T = Annotations(Case);
1473 UnorderedPointwise(declRange(),
T.ranges()));
1477TEST(LocateSymbol, RelPathsInCompileCommand) {
1481 Annotations SourceAnnotations(R
"cpp(
1482#include "header_in_preamble.h"
1484#include "header_not_in_preamble.h"
1485int baz = f$p1^oo + bar_pre$p2^amble + bar_not_pre$p3^amble;
1488 Annotations HeaderInPreambleAnnotations(R"cpp(
1489int [[bar_preamble]];
1492 Annotations HeaderNotInPreambleAnnotations(R"cpp(
1493int [[bar_not_preamble]];
1498 SmallString<32> RelPathPrefix(
"..");
1499 llvm::sys::path::append(RelPathPrefix,
"src");
1501 MockCompilationDatabase CDB(
BuildDir, RelPathPrefix);
1507 auto FooCpp =
testPath(
"src/foo.cpp");
1508 FS.Files[FooCpp] =
"";
1509 auto HeaderInPreambleH =
testPath(
"src/header_in_preamble.h");
1510 FS.Files[HeaderInPreambleH] = std::string(HeaderInPreambleAnnotations.code());
1511 auto HeaderNotInPreambleH =
testPath(
"src/header_not_in_preamble.h");
1512 FS.Files[HeaderNotInPreambleH] =
1513 std::string(HeaderNotInPreambleAnnotations.code());
1520 EXPECT_TRUE(
bool(Locations)) <<
"findDefinitions returned an error";
1521 EXPECT_THAT(*Locations, ElementsAre(
sym(
"foo", SourceAnnotations.range(),
1522 SourceAnnotations.range())));
1526 EXPECT_TRUE(
bool(Locations)) <<
"findDefinitions returned an error";
1529 ElementsAre(
sym(
"bar_preamble", HeaderInPreambleAnnotations.range(),
1530 HeaderInPreambleAnnotations.range())));
1534 EXPECT_TRUE(
bool(Locations)) <<
"findDefinitions returned an error";
1535 EXPECT_THAT(*Locations,
1536 ElementsAre(
sym(
"bar_not_preamble",
1537 HeaderNotInPreambleAnnotations.range(),
1538 HeaderNotInPreambleAnnotations.range())));
1543 MockCompilationDatabase CDB;
1547 const char *SourceContents = R
"cpp(
1548 #include ^"$2^foo.h$3^"
1549 #include "$4^invalid.h"
1553 #in$5^clude "$6^foo.h"$7^
1555 Annotations SourceAnnotations(SourceContents);
1556 FS.Files[FooCpp] = std::string(SourceAnnotations.code());
1563 FS.Files[FooH] = std::string(HeaderAnnotations.code());
1570 ASSERT_TRUE(
bool(Locations)) <<
"locateSymbolAt returned an error";
1571 EXPECT_THAT(*Locations, ElementsAre(
sym(
"foo.h", HeaderAnnotations.range(),
1572 HeaderAnnotations.range())));
1576 ASSERT_TRUE(
bool(Locations)) <<
"locateSymbolAt returned an error";
1577 EXPECT_THAT(*Locations, ElementsAre(
sym(
"foo.h", HeaderAnnotations.range(),
1578 HeaderAnnotations.range())));
1581 ASSERT_TRUE(
bool(Locations)) <<
"locateSymbolAt returned an error";
1582 EXPECT_THAT(*Locations, ElementsAre(
sym(
"foo.h", HeaderAnnotations.range(),
1583 HeaderAnnotations.range())));
1587 ASSERT_TRUE(
bool(Locations)) <<
"locateSymbolAt returned an error";
1588 EXPECT_THAT(*Locations, ElementsAre(
sym(
"foo.h", HeaderAnnotations.range(),
1589 HeaderAnnotations.range())));
1593 ASSERT_TRUE(
bool(Locations)) <<
"locateSymbolAt returned an error";
1594 EXPECT_THAT(*Locations, IsEmpty());
1597 ASSERT_TRUE(
bool(Locations)) <<
"locateSymbolAt returned an error";
1598 EXPECT_THAT(*Locations, ElementsAre(
sym(
"foo.h", HeaderAnnotations.range(),
1599 HeaderAnnotations.range())));
1602 ASSERT_TRUE(
bool(Locations)) <<
"locateSymbolAt returned an error";
1603 EXPECT_THAT(*Locations, ElementsAre(
sym(
"foo.h", HeaderAnnotations.range(),
1604 HeaderAnnotations.range())));
1607 Annotations ObjC(R
"objc(
1611 FS.Files[FooM] = std::string(ObjC.code());
1615 ASSERT_TRUE(
bool(Locations)) <<
"locateSymbolAt returned an error";
1616 EXPECT_THAT(*Locations, ElementsAre(
sym(
"foo.h", HeaderAnnotations.range(),
1617 HeaderAnnotations.range())));
1620TEST(LocateSymbol, WithPreamble) {
1624 MockCompilationDatabase CDB;
1629 Annotations FooWithHeader(R
"cpp(#include "fo^o.h")cpp");
1630 Annotations FooWithoutHeader(R"cpp(double [[fo^o]]();)cpp");
1632 FS.Files[FooCpp] = std::string(FooWithHeader.code());
1635 Annotations FooHeader(R
"cpp([[]])cpp");
1636 FS.Files[FooH] = std::string(FooHeader.code());
1642 ElementsAre(
sym(
"foo.h", FooHeader.range(), FooHeader.range())));
1645 Server.addDocument(FooCpp, FooWithoutHeader.code(),
"null",
1651 ElementsAre(
sym(
"foo", FooWithoutHeader.range(), std::nullopt)));
1656 Server.addDocument(FooCpp, FooWithoutHeader.code(),
"null",
1661 ElementsAre(
sym(
"foo", FooWithoutHeader.range(), std::nullopt)));
1664TEST(LocateSymbol, NearbyTokenSmoke) {
1665 auto T = Annotations(R
"cpp(
1666 // prints e^rr and crashes
1667 void die(const char* [[err]]);
1672 ElementsAre(
sym(
"err",
T.range(),
T.range())));
1675TEST(LocateSymbol, NearbyIdentifier) {
1676 const char *Tests[] = {
1678 // regular identifiers (won't trigger)
1683 // disabled preprocessor sections
1695 // not triggered by string literals
1697 const char* greeting = "h^ello, world";
1701 // can refer to macro invocations
1708 // can refer to macro invocations (even if they expand to nothing)
1715 // prefer nearest occurrence, backwards is worse than forwards
1724 // short identifiers find near results
1729 // short identifiers don't find far results
1742 // prefer nearest occurrence even if several matched tokens
1743 // have the same value of `floor(log2(<token line> - <word line>))`.
1745 int x = hello, y = hello;
1749 for (
const char *Test : Tests) {
1750 Annotations
T(Test);
1752 const auto &SM =
AST.getSourceManager();
1753 std::optional<Range> Nearby;
1756 AST.getTokens(),
AST.getLangOpts());
1758 ADD_FAILURE() <<
"No word at point! " << Test;
1763 Tok->location(), Tok->endLocation()));
1764 if (
T.ranges().empty())
1765 EXPECT_THAT(Nearby, Eq(std::nullopt)) << Test;
1767 EXPECT_EQ(Nearby,
T.range()) << Test;
1771TEST(FindImplementations, Inheritance) {
1772 llvm::StringRef Test = R
"cpp(
1774 virtual void F$1^oo();
1777 struct $0[[Child1]] : Base {
1778 void $1[[Fo$3^o]]() override;
1779 virtual void B$2^ar();
1780 void Concrete(); // No implementations for concrete methods.
1782 struct Child2 : Child1 {
1783 void $3[[Foo]]() override;
1784 void $2[[Bar]]() override;
1786 void FromReference() {
1795 // CRTP should work.
1796 template<typename T>
1797 struct $5^TemplateBase {};
1798 struct $5[[Child3]] : public TemplateBase<Child3> {};
1801 void LocationFunction() {
1802 struct $0[[LocalClass1]] : Base {
1803 void $1[[Foo]]() override;
1805 struct $6^LocalBase {
1806 virtual void $7^Bar();
1808 struct $6[[LocalClass2]]: LocalBase {
1809 void $7[[Bar]]() override;
1814 Annotations Code(Test);
1816 auto AST = TU.build();
1817 auto Index = TU.index();
1818 for (StringRef
Label : {
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7"}) {
1819 for (
const auto &Point :
Code.points(
Label)) {
1821 UnorderedPointwise(declRange(),
Code.ranges(
Label)))
1822 <<
Code.code() <<
" at " << Point <<
" for Label " <<
Label;
1827TEST(FindImplementations, CaptureDefinition) {
1828 llvm::StringRef Test = R
"cpp(
1830 virtual void F^oo();
1832 struct Child1 : Base {
1833 void $Decl[[Foo]]() override;
1835 struct Child2 : Base {
1836 void $Child2[[Foo]]() override;
1838 void Child1::$Def[[Foo]]() { /* Definition */ }
1840 Annotations Code(Test);
1842 auto AST = TU.build();
1845 UnorderedElementsAre(
sym(
"Foo",
Code.range(
"Decl"),
Code.range(
"Def")),
1846 sym(
"Foo",
Code.range(
"Child2"), std::nullopt)))
1851 Annotations HeaderA(R
"cpp(
1852 struct $Target[[Target]] { operator int() const; };
1853 struct Aggregate { Target a, b; };
1857 template <typename T> struct $smart_ptr[[smart_ptr]] {
1864 for (
const llvm::StringRef Case : {
1868 "a^uto x = Target{};",
1869 "namespace m { Target tgt; } auto x = m^::tgt;",
1870 "Target funcCall(); auto x = ^funcCall();",
1871 "Aggregate a = { {}, ^{} };",
1872 "Aggregate a = { ^.a=t, };",
1873 "struct X { Target a; X() : ^a() {} };",
1874 "^using T = Target; ^T foo();",
1875 "^template <int> Target foo();",
1876 "void x() { try {} ^catch(Target e) {} }",
1877 "void x() { ^throw t; }",
1878 "int x() { ^return t; }",
1879 "void x() { ^switch(t) {} }",
1880 "void x() { ^delete (Target*)nullptr; }",
1881 "Target& ^tref = t;",
1882 "void x() { ^if (t) {} }",
1883 "void x() { ^while (t) {} }",
1884 "void x() { ^do { } while (t); }",
1885 "void x() { ^make(); }",
1886 "void x(smart_ptr<Target> &t) { t.^get(); }",
1887 "^auto x = []() { return t; };",
1888 "Target* ^tptr = &t;",
1889 "Target ^tarray[3];",
1891 Annotations
A(Case);
1892 TU.Code =
A.code().str();
1893 ParsedAST
AST = TU.build();
1895 ASSERT_GT(
A.points().size(), 0u) << Case;
1896 for (
auto Pos :
A.points())
1899 sym(
"Target", HeaderA.range(
"Target"), HeaderA.range(
"Target"))))
1903 for (
const llvm::StringRef Case : {
1904 "smart_ptr<Target> ^tsmart;",
1906 Annotations
A(Case);
1907 TU.Code =
A.code().str();
1908 ParsedAST
AST = TU.build();
1911 UnorderedElementsAre(
1912 sym(
"Target", HeaderA.range(
"Target"), HeaderA.range(
"Target")),
1913 sym(
"smart_ptr", HeaderA.range(
"smart_ptr"), HeaderA.range(
"smart_ptr"))
1920 Annotations
A(R
"cpp(
1926 ParsedAST
AST = TU.build();
1929 ElementsAre(
sym(
"X",
A.range(
"decl"),
A.range(
"def"))));
1932TEST(FindType, Index) {
1933 Annotations Def(R
"cpp(
1934 // This definition is only available through the index.
1938 DefTU.HeaderFilename = "def.h";
1939 auto DefIdx = DefTU.index();
1941 Annotations
A(R
"cpp(
1946 ParsedAST
AST = TU.build();
1949 ElementsAre(
sym(
"X",
A.range(), Def.range())));
1952void checkFindRefs(llvm::StringRef Test,
bool UseIndex =
false) {
1953 Annotations
T(Test);
1955 TU.ExtraArgs.push_back(
"-std=c++20");
1957 auto AST = TU.build();
1958 std::vector<Matcher<ReferencesResult::Reference>> ExpectedLocations;
1959 for (
const auto &[R, Context] :
T.rangesWithPayload())
1960 ExpectedLocations.push_back(
1961 AllOf(rangeIs(R), containerIs(Context), attrsAre(0u)));
1964 for (
const auto &[R, Context] :
T.rangesWithPayload(
"def"))
1965 ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(Context),
1968 for (
const auto &[R, Context] :
T.rangesWithPayload(
"decl"))
1969 ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(Context),
1971 for (
const auto &[R, Context] :
T.rangesWithPayload(
"overridedecl"))
1972 ExpectedLocations.push_back(AllOf(
1973 rangeIs(R), containerIs(Context),
1975 for (
const auto &[R, Context] :
T.rangesWithPayload(
"overridedef"))
1976 ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(Context),
1980 for (
const auto &P :
T.points()) {
1984 UnorderedElementsAreArray(ExpectedLocations))
1985 <<
"Failed for Refs at " << P <<
"\n"
1990TEST(FindReferences, WithinAST) {
1991 const char *Tests[] = {
1992 R
"cpp(// Local variable
1994 int $def(main)[[foo]];
1995 $(main)[[^foo]] = 2;
1996 int test1 = $(main)[[foo]];
2002 struct $def(ns1)[[Foo]] {};
2005 ns1::$(main)[[Fo^o]]* Params;
2009 R"cpp(// Forward declaration
2011 class $def[[Foo]] {};
2013 $(main)[[Fo^o]] foo;
2018 int $def[[foo]](int) {}
2020 auto *X = &$(main)[[^foo]];
2027 int $def(Foo)[[foo]];
2028 Foo() : $(Foo::Foo)[[foo]](0) {}
2032 f.$(main)[[f^oo]] = 1;
2036 R"cpp(// Method call
2037 struct Foo { int $decl(Foo)[[foo]](); };
2038 int Foo::$def(Foo)[[foo]]() {}
2041 f.$(main)[[^foo]]();
2045 R"cpp(// Constructor
2047 $decl(Foo)[[F^oo]](int);
2050 Foo f = $(foo)[[Foo]](42);
2055 typedef int $def[[Foo]];
2057 $(main)[[^Foo]] bar;
2062 namespace $decl[[ns]] { // FIXME: def?
2065 int main() { $(main)[[^ns]]::Foo foo; }
2071 #define CAT(X, Y) X##Y
2072 class $def[[Fo^o]] {};
2074 TYPE($(test)[[Foo]]) foo;
2075 $(test)[[FOO]] foo2;
2076 TYPE(TYPE($(test)[[Foo]])) foo3;
2077 $(test)[[CAT]](Fo, o) foo4;
2082 #define $def[[MA^CRO]](X) (X+1)
2084 int x = $[[MACRO]]($[[MACRO]](1));
2088 R"cpp(// Macro outside preamble
2090 #define $def[[MA^CRO]](X) (X+1)
2092 int x = $[[MACRO]]($[[MACRO]](1));
2097 int $def[[v^ar]] = 0;
2098 void foo(int s = $(foo)[[var]]);
2102 template <typename T>
2103 class $def[[Fo^o]] {};
2104 void func($(func)[[Foo]]<int>);
2108 template <typename T>
2109 class $def[[Foo]] {};
2110 void func($(func)[[Fo^o]]<int>);
2112 R"cpp(// Not touching any identifiers.
2114 $def(Foo)[[~]]Foo() {};
2118 f.$(foo)[[^~]]Foo();
2121 R"cpp(// Lambda capture initializer
2123 int $def(foo)[[w^aldo]] = 42;
2124 auto lambda = [x = $(foo)[[waldo]]](){};
2127 R"cpp(// Renaming alias
2128 template <typename> class Vector {};
2129 using $def[[^X]] = Vector<int>;
2134 R"cpp(// Dependent code
2135 template <typename T> void $decl[[foo]](T t);
2136 template <typename T> void bar(T t) { $(bar)[[foo]](t); } // foo in bar is uninstantiated.
2137 void baz(int x) { $(baz)[[f^oo]](x); }
2142 void $decl(ns)[[foo]](S s);
2144 template <typename T> void foo(T t);
2145 // FIXME: Maybe report this foo as a ref to ns::foo (because of ADL)
2146 // when bar<ns::S> is instantiated?
2147 template <typename T> void bar(T t) { foo(t); }
2154 R"cpp(// unresolved member expression
2156 template <typename T> void $decl(Foo)[[b^ar]](T t);
2158 template <typename T> void test(Foo F, T t) {
2159 F.$(test)[[bar]](t);
2165 typedef int $def[[MyTypeD^ef]];
2166 enum MyEnum : $(MyEnum)[[MyTy^peDef]] { };
2169 typedef int $def[[MyType^Def]];
2170 enum MyEnum : $(MyEnum)[[MyTypeD^ef]];
2173 using $def[[MyTypeD^ef]] = int;
2174 enum MyEnum : $(MyEnum)[[MyTy^peDef]] { };
2178 bool $decl[[operator]]"" _u^dl(unsigned long long value);
2179 bool x = $(x)[[1_udl]];
2182 for (
const char *Test : Tests)
2183 checkFindRefs(Test);
2186TEST(FindReferences, ConceptsWithinAST) {
2187 constexpr llvm::StringLiteral
Code = R
"cpp(
2189 concept $def[[IsSmal^l]] = sizeof(T) <= 8;
2192 concept IsSmallPtr = requires(T x) {
2193 { *x } -> $(IsSmallPtr)[[IsSmal^l]];
2196 $(i)[[IsSmall]] auto i = 'c';
2197 template<$(foo)[[IsSmal^l]] U> void foo();
2198 template<class U> void bar() requires $(bar)[[IsSmal^l]]<U>;
2199 template<class U> requires $(baz)[[IsSmal^l]]<U> void baz();
2200 static_assert([[IsSma^ll]]<char>);
2202 checkFindRefs(Code);
2205TEST(FindReferences, ConceptReq) {
2206 constexpr llvm::StringLiteral
Code = R
"cpp(
2208 concept $def[[IsSmal^l]] = sizeof(T) <= 8;
2211 concept IsSmallPtr = requires(T x) {
2212 { *x } -> $(IsSmallPtr)[[IsSmal^l]];
2215 checkFindRefs(Code);
2218TEST(FindReferences, RequiresExprParameters) {
2219 constexpr llvm::StringLiteral
Code = R
"cpp(
2221 concept IsSmall = sizeof(T) <= 8;
2224 concept IsSmallPtr = requires(T $def[[^x]]) {
2225 { *$(IsSmallPtr)[[^x]] } -> IsSmall;
2228 checkFindRefs(Code);
2231TEST(FindReferences, IncludeOverrides) {
2232 llvm::StringRef Test =
2236 virtu^al void $decl(Base)[[f^unc]]() ^= ^0;
2238 class Derived : public Base {
2240 void $overridedecl(Derived::func)[[func]]() override;
2242 void Derived::$overridedef[[func]]() {}
2243 class Derived2 : public Base {
2244 void $overridedef(Derived2::func)[[func]]() override {}
2246 void test(Derived* D, Base* B) {
2247 D->func(); // No references to the overrides.
2248 B->$(test)[[func]]();
2250 checkFindRefs(Test, true);
2253TEST(FindReferences, RefsToBaseMethod) {
2254 llvm::StringRef Test =
2258 virtual void $(BaseBase)[[func]]();
2260 class Base : public BaseBase {
2262 void $(Base)[[func]]() override;
2264 class Derived : public Base {
2266 void $decl(Derived)[[fu^nc]]() over^ride;
2268 void test(BaseBase* BB, Base* B, Derived* D) {
2269 // refs to overridden methods in complete type hierarchy are reported.
2270 BB->$(test)[[func]]();
2271 B->$(test)[[func]]();
2272 D->$(test)[[fu^nc]]();
2274 checkFindRefs(Test, true);
2277TEST(FindReferences, MainFileReferencesOnly) {
2278 llvm::StringRef Test =
2282 // refs not from main file should not be included.
2286 Annotations Code(Test);
2288 TU.AdditionalFiles[
"foo.inc"] = R
"cpp(
2291 auto AST = TU.build();
2293 std::vector<Matcher<ReferencesResult::Reference>> ExpectedLocations;
2294 for (
const auto &R :
Code.ranges())
2295 ExpectedLocations.push_back(rangeIs(R));
2297 ElementsAreArray(ExpectedLocations))
2301TEST(FindReferences, ExplicitSymbols) {
2302 const char *Tests[] = {
2304 struct Foo { Foo* $decl(Foo)[[self]]() const; };
2307 if (Foo* T = foo.$(f)[[^self]]()) {} // Foo member call expr.
2312 struct Foo { Foo(int); };
2315 return $(f)[[^b]]; // Foo constructor expr.
2324 g($(call)[[^f]]()); // Foo constructor expr.
2329 void $decl[[foo]](int);
2330 void $decl[[foo]](double);
2333 using ::$decl(ns)[[fo^o]];
2344 $(test)[[a]].operator bool();
2345 if ($(test)[[a^]]) {} // ignore implicit conversion-operator AST node
2349 for (
const char *Test : Tests)
2350 checkFindRefs(Test);
2353TEST(FindReferences, UsedSymbolsFromInclude) {
2354 const char *Tests[] = {
2355 R
"cpp( [[#include ^"bar.h"]]
2357 int fstBar = [[bar1]]();
2358 int sndBar = [[bar2]]();
2360 int macroBar = [[BAR]];
2361 std::vector<int> vec;
2364 R"cpp([[#in^clude <vector>]]
2365 std::[[vector]]<int> vec;
2369 [[#include ^"udl_header.h"]]
2373 for (
const char *Test : Tests) {
2374 Annotations
T(Test);
2376 TU.ExtraArgs.push_back(
"-std=c++20");
2377 TU.AdditionalFiles[
"bar.h"] = guard(R
"cpp(
2383 TU.AdditionalFiles["system/vector"] = guard(R
"cpp(
2389 TU.AdditionalFiles["udl_header.h"] = guard(R
"cpp(
2390 bool operator"" _b(unsigned long long value);
2392 TU.ExtraArgs.push_back("-isystem" +
testPath(
"system"));
2394 auto AST = TU.build();
2395 std::vector<Matcher<ReferencesResult::Reference>> ExpectedLocations;
2396 for (
const auto &R :
T.ranges())
2397 ExpectedLocations.push_back(AllOf(rangeIs(R), attrsAre(0u)));
2398 for (
const auto &P :
T.points())
2400 UnorderedElementsAreArray(ExpectedLocations))
2401 <<
"Failed for Refs at " << P <<
"\n"
2406TEST(FindReferences, NeedsIndexForSymbols) {
2407 const char *Header =
"int foo();";
2408 Annotations Main(
"int main() { [[f^oo]](); }");
2410 TU.Code = std::string(Main.code());
2411 TU.HeaderCode = Header;
2412 auto AST = TU.build();
2417 ElementsAre(rangeIs(Main.range())));
2418 Annotations IndexedMain(R
"cpp(
2419 int $decl[[foo]]() { return 42; }
2420 void bar() { $bar(bar)[[foo]](); }
2421 struct S { void bar() { $S(S::bar)[[foo]](); } };
2422 namespace N { void bar() { $N(N::bar)[[foo]](); } }
2427 IndexedTU.Code = std::string(IndexedMain.code());
2428 IndexedTU.Filename =
"Indexed.cpp";
2429 IndexedTU.HeaderCode = Header;
2435 rangeIs(Main.range()),
2436 AllOf(rangeIs(IndexedMain.range(
"decl")),
2439 AllOf(rangeIs(IndexedMain.range(
"bar")), containerIs(
"bar")),
2440 AllOf(rangeIs(IndexedMain.range(
"S")), containerIs(
"S::bar")),
2441 AllOf(rangeIs(IndexedMain.range(
"N")), containerIs(
"N::bar"))));
2444 EXPECT_EQ(1u, LimitRefs.References.size());
2445 EXPECT_TRUE(LimitRefs.HasMore);
2448 TU.Code = (
"\n\n" + Main.code()).str();
2450 ElementsAre(rangeIs(Main.range())));
2453TEST(FindReferences, NeedsIndexForMacro) {
2454 const char *Header =
"#define MACRO(X) (X+1)";
2455 Annotations Main(R
"cpp(
2457 int a = [[MA^CRO]](1);
2461 TU.Code = std::string(Main.code());
2462 TU.HeaderCode = Header;
2463 auto AST = TU.build();
2468 ElementsAre(rangeIs(Main.range())));
2470 Annotations IndexedMain(R
"cpp(
2471 int indexed_main() {
2472 int a = [[MACRO]](1);
2478 IndexedTU.Code = std::string(IndexedMain.code());
2479 IndexedTU.Filename =
"Indexed.cpp";
2480 IndexedTU.HeaderCode = Header;
2483 ElementsAre(rangeIs(Main.range()), rangeIs(IndexedMain.range())));
2486 EXPECT_EQ(1u, LimitRefs.References.size());
2487 EXPECT_TRUE(LimitRefs.HasMore);
2490TEST(FindReferences, NoQueryForLocalSymbols) {
2491 struct RecordingIndex :
public MemIndex {
2492 mutable std::optional<llvm::DenseSet<SymbolID>> RefIDs;
2493 bool refs(
const RefsRequest &Req,
2494 llvm::function_ref<
void(
const Ref &)>)
const override {
2506 {
"namespace { int ^x; }",
true},
2507 {
"static int ^x;",
true},
2509 {
"void foo() { int ^x; }",
false},
2510 {
"void foo() { struct ^x{}; }",
false},
2511 {
"auto lambda = []{ int ^x; };",
false},
2513 for (Test T : Tests) {
2514 Annotations
File(
T.AnnotatedCode);
2519 EXPECT_NE(Rec.RefIDs, std::nullopt) <<
T.AnnotatedCode;
2521 EXPECT_EQ(Rec.RefIDs, std::nullopt) <<
T.AnnotatedCode;
2525TEST(GetNonLocalDeclRefs,
All) {
2528 std::vector<std::string> ExpectedDecls;
2534 void ^foo(int baz) {
2543 class Foo { public: void foo(); };
2553 {"Bar",
"Bar::bar",
"Foo",
"Foo::foo"},
2559 class Foo { public: void foo() {} };
2560 class Bar { public: void bar() {} };
2571 template <typename T, template<typename> class Q>
2579 for (
const Case &
C : Cases) {
2580 Annotations
File(
C.AnnotatedCode);
2582 SourceLocation SL = llvm::cantFail(
2585 const FunctionDecl *FD =
2586 llvm::dyn_cast<FunctionDecl>(&
findDecl(
AST, [SL](
const NamedDecl &ND) {
2587 return ND.getLocation() == SL && llvm::isa<FunctionDecl>(ND);
2589 ASSERT_NE(FD,
nullptr);
2592 std::vector<std::string> Names;
2593 for (
const Decl *D : NonLocalDeclRefs) {
2594 if (
const auto *ND = llvm::dyn_cast<NamedDecl>(D))
2595 Names.push_back(ND->getQualifiedNameAsString());
2597 EXPECT_THAT(Names, UnorderedElementsAreArray(
C.ExpectedDecls))
2603 Annotations MainCpp(R
"cpp(
2604 #/*comments*/include /*comments*/ $foo[["foo.h"]] //more comments
2605 int end_of_preamble = 0;
2606 #include $bar[[<bar.h>]]
2610 TU.Code = std::string(MainCpp.code());
2611 TU.AdditionalFiles = {{"foo.h",
""}, {
"bar.h",
""}};
2612 TU.ExtraArgs = {
"-isystem."};
2613 auto AST = TU.build();
2618 DocumentLink({MainCpp.range(
"foo"),
2620 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()
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.