22 #include "clang/AST/Decl.h"
23 #include "clang/Basic/SourceLocation.h"
24 #include "clang/Index/IndexingAction.h"
25 #include "llvm/ADT/None.h"
26 #include "llvm/ADT/StringRef.h"
27 #include "llvm/Support/Casting.h"
28 #include "llvm/Support/Error.h"
29 #include "llvm/Support/Path.h"
30 #include "llvm/Support/ScopedPrinter.h"
31 #include "gmock/gmock.h"
32 #include "gtest/gtest.h"
40 using ::testing::ElementsAre;
42 using ::testing::IsEmpty;
43 using ::testing::Matcher;
44 using ::testing::UnorderedElementsAreArray;
46 MATCHER_P2(FileRange, File,
Range,
"") {
52 Matcher<const std::vector<DocumentHighlight> &>
53 HighlightsFrom(
const Annotations &Test) {
54 std::vector<DocumentHighlight>
Expected;
60 for (
const auto &
Range : Test.ranges())
62 for (
const auto &
Range : Test.ranges(
"read"))
64 for (
const auto &
Range : Test.ranges(
"write"))
66 return UnorderedElementsAreArray(
Expected);
69 TEST(HighlightsTest, All) {
70 const char *Tests[] = {
71 R
"cpp(// Local variable
74 $write[[^bonjour]] = 2;
75 int test1 = $read[[bonjour]];
82 static void foo([[MyClass]]*) {}
86 ns1::[[My^Class]]* Params;
98 R"cpp(// Function parameter in decl
99 void foo(int [[^bar]]);
101 R"cpp(// Not touching any identifiers.
111 for (
const char *Test : Tests) {
119 TEST(HighlightsTest, ControlFlow) {
120 const char *Tests[] = {
122 // Highlight same-function returns.
123 int fib(unsigned n) {
124 if (n <= 1) [[ret^urn]] 1;
125 [[return]] fib(n - 1) + fib(n - 2);
127 // Returns from other functions not highlighted.
128 auto Lambda = [] { return; };
129 class LocalClass { void x() { return; } };
134 #define FAIL() return false
137 if (n < 0) [[FAIL]]();
143 // Highlight loop control flow
146 [[^for]] (char c : "fruit loops!") {
147 if (c == ' ') [[continue]];
149 if (c == '!') [[break]];
150 if (c == '?') [[return]] -1;
157 // Highlight loop and same-loop control flow
160 if (false) [[bre^ak]];
168 // Highlight switch for break (but not other breaks).
169 void describe(unsigned n) {
180 // Highlight case and exits for switch-break (but not other cases).
181 void describe(unsigned n) {
194 // Highlight exits and switch for case
195 void describe(unsigned n) {
208 // Highlight nothing for switch.
209 void describe(unsigned n) {
222 // FIXME: match exception type against catch blocks
224 try { // wrong: highlight try with matching catch
225 try { // correct: has no matching catch
227 } catch (int) { } // correct: catch doesn't match type
228 [[return]] -1; // correct: exits the matching catch
229 } catch (const char*) { } // wrong: highlight matching catch
230 [[return]] 42; // wrong: throw doesn't exit function
235 // Loop highlights goto exiting the loop, but not jumping within it.
246 for (
const char *Test : Tests) {
250 auto AST = TU.
build();
256 MATCHER_P3(Sym,
Name,
Decl, DefOrNone,
"") {
257 llvm::Optional<Range> Def = DefOrNone;
258 if (
Name != arg.Name) {
259 *result_listener <<
"Name is " << arg.Name;
262 if (
Decl != arg.PreferredDeclaration.range) {
263 *result_listener <<
"Declaration is "
264 << llvm::to_string(arg.PreferredDeclaration);
267 if (Def && !arg.Definition) {
268 *result_listener <<
"Has no definition";
271 if (Def && arg.Definition->range != *Def) {
272 *result_listener <<
"Definition is " << llvm::to_string(arg.Definition);
277 ::testing::Matcher<LocatedSymbol> Sym(std::string
Name,
Range Decl) {
282 MATCHER_P(RangeIs, R,
"") {
return arg.range == R; }
284 TEST(LocateSymbol, WithIndex) {
285 Annotations SymbolHeader(R
"cpp(
286 class $forward[[Forward]];
287 class $foo[[Foo]] {};
291 inline void $f2[[f2]]() {}
293 Annotations SymbolCpp(R"cpp(
294 class $forward[[forward]] {};
299 TU.Code = std::string(SymbolCpp.code());
300 TU.HeaderCode = std::string(SymbolHeader.code());
301 auto Index = TU.index();
302 auto LocateWithIndex = [&
Index](
const Annotations &Main) {
307 Annotations Test(R
"cpp(// only declaration in AST.
313 EXPECT_THAT(LocateWithIndex(Test),
314 ElementsAre(Sym("f1", Test.range(), SymbolCpp.range(
"f1"))));
316 Test = Annotations(R
"cpp(// definition in AST.
322 EXPECT_THAT(LocateWithIndex(Test),
323 ElementsAre(Sym("f1", SymbolHeader.range(
"f1"), Test.range())));
325 Test = Annotations(R
"cpp(// forward declaration in AST.
329 EXPECT_THAT(LocateWithIndex(Test),
330 ElementsAre(Sym("Foo", Test.range(), SymbolHeader.range(
"foo"))));
332 Test = Annotations(R
"cpp(// definition in AST.
333 class [[Forward]] {};
337 LocateWithIndex(Test),
338 ElementsAre(Sym("Forward", SymbolHeader.range(
"forward"), Test.range())));
341 TEST(LocateSymbol, WithIndexPreferredLocation) {
342 Annotations SymbolHeader(R
"cpp(
343 class $p[[Proto]] {};
344 void $f[[func]]() {};
347 TU.HeaderCode = std::string(SymbolHeader.code());
348 TU.HeaderFilename = "x.proto";
349 auto Index = TU.index();
351 Annotations Test(R
"cpp(// only declaration in AST.
352 // Shift to make range different.
364 auto CodeGenLoc = SymbolHeader.range(
"p");
365 EXPECT_THAT(Locs, ElementsAre(Sym(
"Proto", CodeGenLoc, CodeGenLoc)));
369 auto CodeGenLoc = SymbolHeader.range(
"f");
370 EXPECT_THAT(Locs, ElementsAre(Sym(
"func", CodeGenLoc, CodeGenLoc)));
374 TEST(LocateSymbol, All) {
379 const char *Tests[] = {
380 R
"cpp(// Local variable
390 struct [[MyClass]] {};
393 ns1::My^Class* Params;
397 R"cpp(// Function definition via pointer
404 R"cpp(// Function declaration via call
405 int $decl[[foo]](int);
412 struct Foo { int [[x]]; };
419 R"cpp(// Field, member initializer
426 R"cpp(// Field, field designator
427 struct Foo { int [[x]]; };
429 Foo bar = { .^x = 2 };
434 struct Foo { int $decl[[x]](); };
442 typedef int $decl[[Foo]];
448 R"cpp(// Template type parameter
449 template <typename [[T]]>
453 R"cpp(// Template template type parameter
454 template <template<typename> class [[T]]>
455 void foo() { ^T<int> t; }
459 namespace $decl[[ns]] {
460 struct Foo { static void bar(); };
462 int main() { ^ns::Foo::bar(); }
466 class TTT { public: int a; };
467 #define [[FF]](S) if (int b = S.a) {}
474 R"cpp(// Macro argument
476 #define ADDRESSOF(X) &X;
477 int *j = ADDRESSOF(^i);
479 R"cpp(// Macro argument appearing multiple times in expansion
480 #define VALIDATE_TYPE(x) (void)x;
481 #define ASSERT(expr) \
483 VALIDATE_TYPE(expr); \
486 bool [[waldo]]() { return true; }
491 R"cpp(// Symbol concatenated inside macro (not supported)
493 #define POINTER(X) p ## X;
494 int x = *POINTER(^i);
497 R"cpp(// Forward class declaration
499 class $def[[Foo]] {};
503 R"cpp(// Function declaration
506 void $def[[foo]]() {}
510 #define FF(name) class name##_Test {};
512 void f() { my^_Test a; }
516 #define FF() class [[Test]] {};
518 void f() { T^est a; }
521 R"cpp(// explicit template specialization
522 template <typename T>
523 struct Foo { void bar() {} };
526 struct [[Foo]]<int> { void bar() {} };
534 R"cpp(// implicit template specialization
535 template <typename T>
536 struct [[Foo]] { void bar() {} };
538 struct Foo<int> { void bar() {} };
545 R"cpp(// partial template specialization
546 template <typename T>
547 struct Foo { void bar() {} };
548 template <typename T>
549 struct [[Foo]]<T*> { void bar() {} };
553 R"cpp(// function template specializations
563 R"cpp(// variable template decls
568 double [[var]]<int> = 10;
570 double y = va^r<int>;
573 R"cpp(// No implicit constructors
585 X& $decl[[operator]]++();
593 struct S1 { void f(); };
594 struct S2 { S1 * $decl[[operator]]->(); };
600 R"cpp(// Declaration of explicit template specialization
601 template <typename T>
602 struct $decl[[Foo]] {};
608 R"cpp(// Declaration of partial template specialization
609 template <typename T>
610 struct $decl[[Foo]] {};
612 template <typename T>
616 R"cpp(// Override specifier jumps to overridden method
617 class Y { virtual void $decl[[a]]() = 0; };
618 class X : Y { void a() ^override {} };
621 R"cpp(// Final specifier jumps to overridden method
622 class Y { virtual void $decl[[a]]() = 0; };
623 class X : Y { void a() ^final {} };
626 R"cpp(// Heuristic resolution of dependent method
627 template <typename T>
632 template <typename T>
638 R"cpp(// Heuristic resolution of dependent method via this->
639 template <typename T>
647 R"cpp(// Heuristic resolution of dependent static method
648 template <typename T>
650 static void [[bar]]() {}
653 template <typename T>
659 R"cpp(// Heuristic resolution of dependent method
660 // invoked via smart pointer
661 template <typename> struct S { void [[foo]]() {} };
662 template <typename T> struct unique_ptr {
665 template <typename T>
666 void test(unique_ptr<S<T>>& V) {
671 R"cpp(// Heuristic resolution of dependent enumerator
672 template <typename T>
674 enum class E { [[A]], B };
678 for (
const char *Test : Tests) {
680 llvm::Optional<Range> WantDecl;
681 llvm::Optional<Range> WantDef;
682 if (!T.ranges().empty())
683 WantDecl = WantDef = T.range();
684 if (!T.ranges(
"decl").empty())
685 WantDecl = T.range(
"decl");
686 if (!T.ranges(
"def").empty())
687 WantDef = T.range(
"def");
690 TU.Code = std::string(T.code());
694 TU.ExtraArgs.push_back(
"-fno-delayed-template-parsing");
696 auto AST = TU.
build();
700 EXPECT_THAT(
Results, IsEmpty()) << Test;
702 ASSERT_THAT(
Results, ::testing::SizeIs(1)) << Test;
703 EXPECT_EQ(
Results[0].PreferredDeclaration.range, *WantDecl) << Test;
704 llvm::Optional<Range> GotDef;
706 GotDef =
Results[0].Definition->range;
707 EXPECT_EQ(WantDef, GotDef) << Test;
715 TEST(LocateSymbol, Warnings) {
716 const char *Tests[] = {
717 R
"cpp(// Field, GNU old-style field designator
718 struct Foo { int [[x]]; };
720 Foo bar = { ^x : 1 };
727 int main() { return ^MACRO; }
733 for (
const char *Test : Tests) {
735 llvm::Optional<Range> WantDecl;
736 llvm::Optional<Range> WantDef;
737 if (!T.ranges().empty())
738 WantDecl = WantDef = T.range();
739 if (!T.ranges(
"decl").empty())
740 WantDecl = T.range(
"decl");
741 if (!T.ranges(
"def").empty())
742 WantDef = T.range(
"def");
745 TU.Code = std::string(T.code());
747 auto AST = TU.
build();
751 EXPECT_THAT(
Results, IsEmpty()) << Test;
753 ASSERT_THAT(
Results, ::testing::SizeIs(1)) << Test;
754 EXPECT_EQ(
Results[0].PreferredDeclaration.range, *WantDecl) << Test;
755 llvm::Optional<Range> GotDef;
757 GotDef =
Results[0].Definition->range;
758 EXPECT_EQ(WantDef, GotDef) << Test;
763 TEST(LocateSymbol, TextualSmoke) {
764 auto T = Annotations(
766 struct [[MyClass]] {};
767 // Comment mentioning M^yClass
771 auto AST = TU.
build();
772 auto Index = TU.index();
774 ElementsAre(Sym(
"MyClass", T.range())));
777 TEST(LocateSymbol, Textual) {
778 const char *Tests[] = {
780 struct [[MyClass]] {};
781 // Comment mentioning M^yClass
785 // Not triggered for string literal tokens.
786 const char* s = "String literal mentioning M^yClass";
788 R"cpp(// Ifdef'ed out code
789 struct [[MyClass]] {};
794 R"cpp(// Macro definition
795 struct [[MyClass]] {};
796 #define DECLARE_MYCLASS_OBJ(name) M^yClass name;
798 R"cpp(// Invalid code
801 // Not triggered for token which survived preprocessing.
802 int var = m^yFunction();
805 for (
const char *Test : Tests) {
807 llvm::Optional<Range> WantDecl;
808 if (!T.ranges().empty())
809 WantDecl = T.range();
813 auto AST = TU.
build();
814 auto Index = TU.index();
819 ADD_FAILURE() <<
"No word touching point!" << Test;
823 testPath(TU.Filename), ASTNodeKind());
826 EXPECT_THAT(
Results, IsEmpty()) << Test;
828 ASSERT_THAT(
Results, ::testing::SizeIs(1)) << Test;
829 EXPECT_EQ(
Results[0].PreferredDeclaration.range, *WantDecl) << Test;
834 TEST(LocateSymbol, Ambiguous) {
835 auto T = Annotations(R
"cpp(
839 $ConstructorLoc[[Foo]](const char*);
847 const char* str = "123";
855 Foo foox = Fo$9^o("asdf");
856 Foo abcde$10^("asdf");
857 Foo foox2 = Foo$11^("asdf");
860 template <typename T>
862 void $NonstaticOverload1[[bar]](int);
863 void $NonstaticOverload2[[bar]](float);
865 static void $StaticOverload1[[baz]](int);
866 static void $StaticOverload2[[baz]](float);
869 template <typename T, typename U>
870 void dependent_call(S<T> s, U u) {
878 TU.
ExtraArgs.push_back(
"-fno-delayed-template-parsing");
879 auto AST = TU.
build();
881 EXPECT_THAT(
locateSymbolAt(AST, T.point(
"1")), ElementsAre(Sym(
"str")));
882 EXPECT_THAT(
locateSymbolAt(AST, T.point(
"2")), ElementsAre(Sym(
"str")));
883 EXPECT_THAT(
locateSymbolAt(AST, T.point(
"3")), ElementsAre(Sym(
"f")));
884 EXPECT_THAT(
locateSymbolAt(AST, T.point(
"4")), ElementsAre(Sym(
"g")));
885 EXPECT_THAT(
locateSymbolAt(AST, T.point(
"5")), ElementsAre(Sym(
"f")));
886 EXPECT_THAT(
locateSymbolAt(AST, T.point(
"6")), ElementsAre(Sym(
"str")));
888 EXPECT_THAT(
locateSymbolAt(AST, T.point(
"7")), ElementsAre(Sym(
"abc")));
890 EXPECT_THAT(
locateSymbolAt(AST, T.point(
"8")), ElementsAre(Sym(
"abcd")));
892 EXPECT_THAT(
locateSymbolAt(AST, T.point(
"9")), ElementsAre(Sym(
"Foo")));
894 ElementsAre(Sym(
"Foo", T.range(
"ConstructorLoc"))));
896 ElementsAre(Sym(
"Foo", T.range(
"ConstructorLoc"))));
901 UnorderedElementsAre(Sym(
"bar", T.range(
"NonstaticOverload1")),
902 Sym(
"bar", T.range(
"NonstaticOverload2"))));
904 UnorderedElementsAre(Sym(
"baz", T.range(
"StaticOverload1")),
905 Sym(
"baz", T.range(
"StaticOverload2"))));
908 TEST(LocateSymbol, TextualDependent) {
912 Annotations Header(R
"cpp(
914 void $FooLoc[[uniqueMethodName]]();
917 void $BarLoc[[uniqueMethodName]]();
920 Annotations Source(R"cpp(
921 template <typename T>
923 t.u^niqueMethodName();
927 TU.Code = std::string(Source.code());
928 TU.HeaderCode = std::string(Header.code());
929 auto AST = TU.
build();
930 auto Index = TU.index();
935 EXPECT_THAT(
Results, UnorderedElementsAre(
936 Sym(
"uniqueMethodName", Header.range(
"FooLoc")),
937 Sym(
"uniqueMethodName", Header.range(
"BarLoc"))));
940 TEST(LocateSymbol, TemplateTypedefs) {
941 auto T = Annotations(R
"cpp(
942 template <class T> struct function {};
943 template <class T> using callback = function<T()>;
948 EXPECT_THAT(
locateSymbolAt(AST, T.point()), ElementsAre(Sym(
"callback")));
951 TEST(LocateSymbol, RelPathsInCompileCommand) {
955 Annotations SourceAnnotations(R
"cpp(
956 #include "header_in_preamble.h"
958 #include "header_not_in_preamble.h"
959 int baz = f$p1^oo + bar_pre$p2^amble + bar_not_pre$p3^amble;
962 Annotations HeaderInPreambleAnnotations(R"cpp(
963 int [[bar_preamble]];
966 Annotations HeaderNotInPreambleAnnotations(R"cpp(
967 int [[bar_not_preamble]];
972 SmallString<32> RelPathPrefix(
"..");
973 llvm::sys::path::append(RelPathPrefix,
"src");
974 std::string BuildDir =
testPath(
"build");
975 MockCompilationDatabase CDB(BuildDir, RelPathPrefix);
981 auto FooCpp =
testPath(
"src/foo.cpp");
983 auto HeaderInPreambleH =
testPath(
"src/header_in_preamble.h");
984 FS.
Files[HeaderInPreambleH] = std::string(HeaderInPreambleAnnotations.code());
985 auto HeaderNotInPreambleH =
testPath(
"src/header_not_in_preamble.h");
986 FS.
Files[HeaderNotInPreambleH] =
987 std::string(HeaderNotInPreambleAnnotations.code());
994 EXPECT_TRUE(
bool(Locations)) <<
"findDefinitions returned an error";
995 EXPECT_THAT(*Locations, ElementsAre(Sym(
"foo", SourceAnnotations.range())));
999 EXPECT_TRUE(
bool(Locations)) <<
"findDefinitions returned an error";
1002 ElementsAre(Sym(
"bar_preamble", HeaderInPreambleAnnotations.range())));
1006 EXPECT_TRUE(
bool(Locations)) <<
"findDefinitions returned an error";
1007 EXPECT_THAT(*Locations,
1008 ElementsAre(Sym(
"bar_not_preamble",
1009 HeaderNotInPreambleAnnotations.range())));
1012 TEST(GoToInclude, All) {
1014 MockCompilationDatabase CDB;
1018 const char *SourceContents = R
"cpp(
1019 #include ^"$2^foo.h$3^"
1020 #include "$4^invalid.h"
1024 #in$5^clude "$6^foo.h"$7^
1026 Annotations SourceAnnotations(SourceContents);
1027 FS.Files[FooCpp] = std::string(SourceAnnotations.code());
1034 FS.Files[FooH] = std::string(HeaderAnnotations.code());
1036 Server.addDocument(FooH, HeaderAnnotations.code());
1037 Server.addDocument(FooCpp, SourceAnnotations.code());
1041 ASSERT_TRUE(
bool(Locations)) <<
"locateSymbolAt returned an error";
1042 EXPECT_THAT(*Locations, ElementsAre(Sym(
"foo.h", HeaderAnnotations.range())));
1046 ASSERT_TRUE(
bool(Locations)) <<
"locateSymbolAt returned an error";
1047 EXPECT_THAT(*Locations, ElementsAre(Sym(
"foo.h", HeaderAnnotations.range())));
1050 ASSERT_TRUE(
bool(Locations)) <<
"locateSymbolAt returned an error";
1051 EXPECT_THAT(*Locations, ElementsAre(Sym(
"foo.h", HeaderAnnotations.range())));
1055 ASSERT_TRUE(
bool(Locations)) <<
"locateSymbolAt returned an error";
1056 EXPECT_THAT(*Locations, ElementsAre(Sym(
"foo.h", HeaderAnnotations.range())));
1060 ASSERT_TRUE(
bool(Locations)) <<
"locateSymbolAt returned an error";
1061 EXPECT_THAT(*Locations, IsEmpty());
1064 ASSERT_TRUE(
bool(Locations)) <<
"locateSymbolAt returned an error";
1065 EXPECT_THAT(*Locations, ElementsAre(Sym(
"foo.h", HeaderAnnotations.range())));
1068 ASSERT_TRUE(
bool(Locations)) <<
"locateSymbolAt returned an error";
1069 EXPECT_THAT(*Locations, ElementsAre(Sym(
"foo.h", HeaderAnnotations.range())));
1072 Annotations ObjC(R
"objc(
1076 FS.
Files[FooM] = std::string(ObjC.code());
1078 Server.addDocument(FooM, ObjC.code());
1080 ASSERT_TRUE(
bool(Locations)) <<
"locateSymbolAt returned an error";
1081 EXPECT_THAT(*Locations, ElementsAre(Sym(
"foo.h", HeaderAnnotations.range())));
1084 TEST(LocateSymbol, WithPreamble) {
1088 MockCompilationDatabase CDB;
1093 Annotations FooWithHeader(R
"cpp(#include "fo^o.h")cpp");
1094 Annotations FooWithoutHeader(R"cpp(double [[fo^o]]();)cpp");
1096 FS.Files[FooCpp] = std::string(FooWithHeader.code());
1099 Annotations FooHeader(R
"cpp([[]])cpp");
1100 FS.Files[FooH] = std::string(FooHeader.code());
1106 ElementsAre(Sym(
"foo.h", FooHeader.range())));
1109 Server.addDocument(FooCpp, FooWithoutHeader.code(),
"null",
1115 ElementsAre(Sym(
"foo", FooWithoutHeader.range())));
1120 Server.addDocument(FooCpp, FooWithoutHeader.code(),
"null",
1125 ElementsAre(Sym(
"foo", FooWithoutHeader.range())));
1128 TEST(LocateSymbol, NearbyTokenSmoke) {
1129 auto T = Annotations(R
"cpp(
1130 // prints e^rr and crashes
1131 void die(const char* [[err]]);
1136 ElementsAre(Sym(
"err", T.range())));
1139 TEST(LocateSymbol, NearbyIdentifier) {
1140 const char *Tests[] = {
1142 // regular identifiers (won't trigger)
1147 // disabled preprocessor sections
1159 // not triggered by string literals
1161 const char* greeting = "h^ello, world";
1165 // can refer to macro invocations
1172 // can refer to macro invocations (even if they expand to nothing)
1179 // prefer nearest occurrence, backwards is worse than forwards
1188 // short identifiers find near results
1193 // short identifiers don't find far results
1201 for (
const char *Test : Tests) {
1202 Annotations T(Test);
1205 llvm::Optional<Range> Nearby;
1210 ADD_FAILURE() <<
"No word at point! " << Test;
1215 Tok->location(), Tok->endLocation()));
1216 if (T.ranges().empty())
1219 EXPECT_EQ(Nearby, T.range()) << Test;
1223 TEST(FindReferences, WithinAST) {
1224 const char *Tests[] = {
1225 R
"cpp(// Local variable
1229 int test1 = [[foo]];
1238 ns1::[[Fo^o]]* Params;
1242 R"cpp(// Forward declaration
1253 auto *X = &[[^foo]];
1261 Foo() : [[foo]](0) {}
1269 R"cpp(// Method call
1270 struct Foo { int [[foo]](); };
1271 int Foo::[[foo]]() {}
1278 R"cpp(// Constructor
1283 Foo f = [[Foo]](42);
1288 typedef int [[Foo]];
1298 int main() { [[^ns]]::Foo foo; }
1304 #define CAT(X, Y) X##Y
1309 TYPE(TYPE([[Foo]])) foo3;
1310 [[CAT]](Fo, o) foo4;
1315 #define [[MA^CRO]](X) (X+1)
1317 int x = [[MACRO]]([[MACRO]](1));
1323 void foo(int s = [[var]]);
1327 template <typename T>
1329 void func([[Foo]]<int>);
1333 template <typename T>
1335 void func([[Fo^o]]<int>);
1337 R"cpp(// Not touching any identifiers.
1347 for (
const char *Test : Tests) {
1348 Annotations T(Test);
1350 std::vector<Matcher<Location>> ExpectedLocations;
1351 for (
const auto &R : T.ranges())
1352 ExpectedLocations.push_back(RangeIs(R));
1354 ElementsAreArray(ExpectedLocations))
1359 TEST(FindReferences, MainFileReferencesOnly) {
1360 llvm::StringRef Test =
1364 // refs not from main file should not be included.
1368 Annotations Code(Test);
1373 auto AST = TU.
build();
1375 std::vector<Matcher<Location>> ExpectedLocations;
1376 for (
const auto &R :
Code.ranges())
1377 ExpectedLocations.push_back(RangeIs(R));
1379 ElementsAreArray(ExpectedLocations))
1383 TEST(FindReferences, ExplicitSymbols) {
1384 const char *Tests[] = {
1386 struct Foo { Foo* [[self]]() const; };
1389 if (Foo* T = foo.[[^self]]()) {} // Foo member call expr.
1394 struct Foo { Foo(int); };
1397 return [[^b]]; // Foo constructor expr.
1406 g([[^f]]()); // Foo constructor expr.
1412 void [[foo]](double);
1426 [[a]].operator bool();
1427 if ([[a^]]) {} // ignore implicit conversion-operator AST node
1431 for (
const char *Test : Tests) {
1432 Annotations T(Test);
1434 std::vector<Matcher<Location>> ExpectedLocations;
1435 for (
const auto &R : T.ranges())
1436 ExpectedLocations.push_back(RangeIs(R));
1437 ASSERT_THAT(ExpectedLocations, Not(IsEmpty()));
1439 ElementsAreArray(ExpectedLocations))
1444 TEST(FindReferences, NeedsIndexForSymbols) {
1445 const char *Header =
"int foo();";
1446 Annotations Main(
"int main() { [[f^oo]](); }");
1448 TU.Code = std::string(Main.code());
1449 TU.HeaderCode = Header;
1450 auto AST = TU.
build();
1455 ElementsAre(RangeIs(Main.range())));
1456 Annotations IndexedMain(R
"cpp(
1457 int main() { [[f^oo]](); }
1462 IndexedTU.Code = std::string(IndexedMain.code());
1463 IndexedTU.Filename =
"Indexed.cpp";
1464 IndexedTU.HeaderCode = Header;
1467 ElementsAre(RangeIs(Main.range()), RangeIs(IndexedMain.range())));
1470 EXPECT_EQ(1u, LimitRefs.References.size());
1471 EXPECT_TRUE(LimitRefs.HasMore);
1474 TU.Code = (
"\n\n" + Main.code()).str();
1476 ElementsAre(RangeIs(Main.range())));
1479 TEST(FindReferences, NeedsIndexForMacro) {
1480 const char *Header =
"#define MACRO(X) (X+1)";
1481 Annotations Main(R
"cpp(
1483 int a = [[MA^CRO]](1);
1487 TU.Code = std::string(Main.code());
1488 TU.HeaderCode = Header;
1489 auto AST = TU.
build();
1494 ElementsAre(RangeIs(Main.range())));
1496 Annotations IndexedMain(R
"cpp(
1497 int indexed_main() {
1498 int a = [[MACRO]](1);
1504 IndexedTU.Code = std::string(IndexedMain.code());
1505 IndexedTU.Filename =
"Indexed.cpp";
1506 IndexedTU.HeaderCode = Header;
1509 ElementsAre(RangeIs(Main.range()), RangeIs(IndexedMain.range())));
1512 EXPECT_EQ(1u, LimitRefs.References.size());
1513 EXPECT_TRUE(LimitRefs.HasMore);
1516 TEST(FindReferences, NoQueryForLocalSymbols) {
1517 struct RecordingIndex :
public MemIndex {
1518 mutable Optional<llvm::DenseSet<SymbolID>> RefIDs;
1519 bool refs(
const RefsRequest &Req,
1520 llvm::function_ref<
void(
const Ref &)>)
const override {
1532 {
"namespace { int ^x; }",
true},
1533 {
"static int ^x;",
true},
1535 {
"void foo() { int ^x; }",
false},
1536 {
"void foo() { struct ^x{}; }",
false},
1537 {
"auto lambda = []{ int ^x; };",
false},
1539 for (Test T : Tests) {
1540 Annotations File(T.AnnotatedCode);
1545 EXPECT_NE(Rec.RefIDs, None) << T.AnnotatedCode;
1547 EXPECT_EQ(Rec.RefIDs, None) << T.AnnotatedCode;
1551 TEST(GetNonLocalDeclRefs, All) {
1554 std::vector<std::string> ExpectedDecls;
1560 void ^foo(int baz) {
1569 class Foo { public: void foo(); };
1579 {"Bar",
"Bar::bar",
"Foo",
"Foo::foo"},
1585 class Foo { public: void foo() {} };
1586 class Bar { public: void bar() {} };
1597 template <typename T, template<typename> class Q>
1605 for (
const Case &C : Cases) {
1606 Annotations File(C.AnnotatedCode);
1608 SourceLocation SL = llvm::cantFail(
1611 const FunctionDecl *FD =
1612 llvm::dyn_cast<FunctionDecl>(&
findDecl(AST, [SL](
const NamedDecl &ND) {
1613 return ND.getLocation() == SL && llvm::isa<FunctionDecl>(ND);
1615 ASSERT_NE(FD,
nullptr);
1618 std::vector<std::string> Names;
1619 for (
const Decl *D : NonLocalDeclRefs) {
1620 if (
const auto *ND = llvm::dyn_cast<NamedDecl>(D))
1621 Names.push_back(ND->getQualifiedNameAsString());
1623 EXPECT_THAT(Names, UnorderedElementsAreArray(C.ExpectedDecls))
1628 TEST(DocumentLinks, All) {
1629 Annotations MainCpp(R
"cpp(
1630 #/*comments*/include /*comments*/ $foo[["foo.h"]] //more comments
1631 int end_of_preamble = 0;
1632 #include $bar[[<bar.h>]]
1636 TU.Code = std::string(MainCpp.code());
1637 TU.AdditionalFiles = {{"foo.h",
""}, {
"bar.h",
""}};
1638 TU.ExtraArgs = {
"-isystem."};
1639 auto AST = TU.
build();
1644 DocumentLink({MainCpp.range(
"foo"),
1646 DocumentLink({MainCpp.range(
"bar"),