1 //===-- XRefsTests.cpp ---------------------------*- C++ -*--------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
8 #include "Annotations.h"
10 #include "ParsedAST.h"
12 #include "SourceCode.h"
17 #include "index/MemIndex.h"
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"
35 using ::testing::AllOf
;
36 using ::testing::ElementsAre
;
38 using ::testing::IsEmpty
;
39 using ::testing::Matcher
;
40 using ::testing::UnorderedElementsAre
;
41 using ::testing::UnorderedElementsAreArray
;
42 using ::testing::UnorderedPointwise
;
44 std::string
guard(llvm::StringRef Code
) {
45 return "#pragma once\n" + Code
.str();
48 MATCHER_P2(FileRange
, File
, Range
, "") {
49 return Location
{URIForFile::canonicalize(File
, testRoot()), Range
} == arg
;
51 MATCHER(declRange
, "") {
52 const LocatedSymbol
&Sym
= ::testing::get
<0>(arg
);
53 const Range
&Range
= ::testing::get
<1>(arg
);
54 return Sym
.PreferredDeclaration
.range
== Range
;
57 // Extracts ranges from an annotated example, and constructs a matcher for a
58 // highlight set. Ranges should be named $read/$write as appropriate.
59 Matcher
<const std::vector
<DocumentHighlight
> &>
60 highlightsFrom(const Annotations
&Test
) {
61 std::vector
<DocumentHighlight
> Expected
;
62 auto Add
= [&](const Range
&R
, DocumentHighlightKind K
) {
63 Expected
.emplace_back();
64 Expected
.back().range
= R
;
65 Expected
.back().kind
= K
;
67 for (const auto &Range
: Test
.ranges())
68 Add(Range
, DocumentHighlightKind::Text
);
69 for (const auto &Range
: Test
.ranges("read"))
70 Add(Range
, DocumentHighlightKind::Read
);
71 for (const auto &Range
: Test
.ranges("write"))
72 Add(Range
, DocumentHighlightKind::Write
);
73 return UnorderedElementsAreArray(Expected
);
76 TEST(HighlightsTest
, All
) {
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
) {
138 auto TU
= TestTU::withCode(T
.code());
139 TU
.ExtraArgs
.push_back("-xobjective-c++");
140 auto AST
= TU
.build();
141 EXPECT_THAT(findDocumentHighlights(AST
, T
.point()), highlightsFrom(T
))
146 TEST(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
) {
275 auto TU
= TestTU::withCode(T
.code());
276 TU
.ExtraArgs
.push_back("-fexceptions"); // FIXME: stop testing on PS4.
277 auto AST
= TU
.build();
278 EXPECT_THAT(findDocumentHighlights(AST
, T
.point()), highlightsFrom(T
))
283 MATCHER_P3(sym
, Name
, Decl
, DefOrNone
, "") {
284 std::optional
<Range
> Def
= DefOrNone
;
285 if (Name
!= arg
.Name
) {
286 *result_listener
<< "Name is " << arg
.Name
;
289 if (Decl
!= arg
.PreferredDeclaration
.range
) {
290 *result_listener
<< "Declaration is "
291 << llvm::to_string(arg
.PreferredDeclaration
);
294 if (!Def
&& !arg
.Definition
)
296 if (Def
&& !arg
.Definition
) {
297 *result_listener
<< "Has no definition";
300 if (!Def
&& arg
.Definition
) {
301 *result_listener
<< "Definition is " << llvm::to_string(*arg
.Definition
);
304 if (arg
.Definition
->range
!= *Def
) {
305 *result_listener
<< "Definition is " << llvm::to_string(*arg
.Definition
);
311 MATCHER_P(sym
, Name
, "") { return arg
.Name
== Name
; }
313 MATCHER_P(rangeIs
, R
, "") { return arg
.Loc
.range
== R
; }
314 MATCHER_P(containerIs
, C
, "") {
315 return arg
.Loc
.containerName
.value_or("") == C
;
317 MATCHER_P(attrsAre
, A
, "") { return arg
.Attributes
== A
; }
318 MATCHER_P(hasID
, ID
, "") { return arg
.ID
== ID
; }
320 TEST(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
) {
339 auto AST
= TestTU::withCode(Main
.code()).build();
340 return clangd::locateSymbolAt(AST
, Main
.point(), Index
.get());
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())));
377 TEST(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.
389 TestTU TU
= TestTU::withCode(Code
.code());
390 auto AST
= TU
.build();
391 EXPECT_THAT(locateSymbolAt(AST
, Code
.point("1"), TU
.index().get()),
392 UnorderedElementsAre(sym("x", Code
.range("1"), Code
.range("1"))));
394 locateSymbolAt(AST
, Code
.point("2"), TU
.index().get()),
395 UnorderedElementsAre(sym("Foo", Code
.range("2"), Code
.range("2"))));
398 TEST(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;
407 TestTU TU
= TestTU::withCode(Code
.code());
408 auto AST
= TU
.build();
409 EXPECT_THAT(locateSymbolAt(AST
, Code
.point(), TU
.index().get()),
410 UnorderedElementsAre(sym("foo", Code
.range("1"), std::nullopt
),
411 sym("foo", Code
.range("2"), std::nullopt
)));
414 TEST(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"; // Prefer locations in codegen files.
422 auto Index
= TU
.index();
424 Annotations
Test(R
"cpp(// only declaration in AST.
425 // Shift to make range different.
434 auto AST
= TestTU::withCode(Test
.code()).build();
436 auto Locs
= clangd::locateSymbolAt(AST
, Test
.point("p"), Index
.get());
437 auto CodeGenLoc
= SymbolHeader
.range("p");
438 EXPECT_THAT(Locs
, ElementsAre(sym("Proto", CodeGenLoc
, CodeGenLoc
)));
441 auto Locs
= clangd::locateSymbolAt(AST
, Test
.point("f"), Index
.get());
442 auto CodeGenLoc
= SymbolHeader
.range("f");
443 EXPECT_THAT(Locs
, ElementsAre(sym("func", CodeGenLoc
, CodeGenLoc
)));
447 TEST(LocateSymbol
, All
) {
449 // $decl is the declaration location (if absent, no symbol is located)
450 // $def is the definition location (if absent, symbol has no definition)
451 // unnamed range becomes both $decl and $def.
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();
1040 auto Results
= locateSymbolAt(AST
, T
.point());
1043 EXPECT_THAT(Results
, IsEmpty()) << Test
;
1045 ASSERT_THAT(Results
, ::testing::SizeIs(1)) << Test
;
1046 EXPECT_EQ(Results
[0].PreferredDeclaration
.range
, *WantDecl
) << Test
;
1047 EXPECT_TRUE(Results
[0].ID
) << Test
;
1048 std::optional
<Range
> GotDef
;
1049 if (Results
[0].Definition
)
1050 GotDef
= Results
[0].Definition
->range
;
1051 EXPECT_EQ(WantDef
, GotDef
) << Test
;
1055 TEST(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);
1062 TestTU TU
= TestTU::withCode(T
.code());
1063 auto AST
= TU
.build();
1064 auto Index
= TU
.index();
1065 EXPECT_THAT(locateSymbolAt(AST
, T
.point("add"), Index
.get()),
1066 ElementsAre(AllOf(sym("add"),
1067 hasID(getSymbolID(&findDecl(AST
, "add"))))));
1069 locateSymbolAt(AST
, T
.point("MACRO"), Index
.get()),
1070 ElementsAre(AllOf(sym("MACRO"),
1071 hasID(findSymbol(TU
.headerSymbols(), "MACRO").ID
))));
1074 TEST(LocateSymbol
, AllMulti
) {
1076 // $declN is the declaration location
1077 // $defN is the definition location (if absent, symbol has no definition)
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();
1144 auto Results
= locateSymbolAt(AST
, T
.point());
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
;
1151 if (Results
[Idx
].Definition
)
1152 GotDef
= Results
[Idx
].Definition
->range
;
1153 EXPECT_EQ(GotDef
, Ranges
[Idx
].WantDef
) << "($def" << Idx
<< ")" << Test
;
1158 // LocateSymbol test cases that produce warnings.
1159 // These are separated out from All so that in All we can assert
1160 // that there are no diagnostics.
1161 TEST(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();
1194 auto Results
= locateSymbolAt(AST
, T
.point());
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
;
1202 if (Results
[0].Definition
)
1203 GotDef
= Results
[0].Definition
->range
;
1204 EXPECT_EQ(WantDef
, GotDef
) << Test
;
1209 TEST(LocateSymbol
, TextualSmoke
) {
1210 auto T
= Annotations(
1212 struct [[MyClass]] {};
1213 // Comment mentioning M^yClass
1216 auto TU
= TestTU::withCode(T
.code());
1217 auto AST
= TU
.build();
1218 auto Index
= TU
.index();
1220 locateSymbolAt(AST
, T
.point(), Index
.get()),
1221 ElementsAre(AllOf(sym("MyClass", T
.range(), T
.range()),
1222 hasID(getSymbolID(&findDecl(AST
, "MyClass"))))));
1225 TEST(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();
1259 auto TU
= TestTU::withCode(T
.code());
1261 auto AST
= TU
.build();
1262 auto Index
= TU
.index();
1263 auto Word
= SpelledWord::touching(
1264 cantFail(sourceLocationInMainFile(AST
.getSourceManager(), T
.point())),
1265 AST
.getTokens(), AST
.getLangOpts());
1267 ADD_FAILURE() << "No word touching point!" << Test
;
1270 auto Results
= locateSymbolTextually(*Word
, AST
, Index
.get(),
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
;
1282 TEST(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) {
1323 auto TU
= TestTU::withCode(T
.code());
1324 // FIXME: Go-to-definition in a template requires disabling delayed template
1326 TU
.ExtraArgs
.push_back("-fno-delayed-template-parsing");
1327 auto AST
= TU
.build();
1328 // Ordered assertions are deliberate: we expect a predictable order.
1329 EXPECT_THAT(locateSymbolAt(AST
, T
.point("1")), ElementsAre(sym("str")));
1330 EXPECT_THAT(locateSymbolAt(AST
, T
.point("2")), ElementsAre(sym("str")));
1331 EXPECT_THAT(locateSymbolAt(AST
, T
.point("3")), ElementsAre(sym("f")));
1332 EXPECT_THAT(locateSymbolAt(AST
, T
.point("4")), ElementsAre(sym("g")));
1333 EXPECT_THAT(locateSymbolAt(AST
, T
.point("5")), ElementsAre(sym("f")));
1334 EXPECT_THAT(locateSymbolAt(AST
, T
.point("6")), ElementsAre(sym("str")));
1335 // FIXME: Target the constructor as well.
1336 EXPECT_THAT(locateSymbolAt(AST
, T
.point("7")), ElementsAre(sym("abc")));
1337 // FIXME: Target the constructor as well.
1338 EXPECT_THAT(locateSymbolAt(AST
, T
.point("8")), ElementsAre(sym("abcd")));
1339 // FIXME: Target the constructor as well.
1340 EXPECT_THAT(locateSymbolAt(AST
, T
.point("9")), ElementsAre(sym("Foo")));
1341 EXPECT_THAT(locateSymbolAt(AST
, T
.point("10")),
1342 ElementsAre(sym("Foo", T
.range("ConstructorLoc"), std::nullopt
)));
1343 EXPECT_THAT(locateSymbolAt(AST
, T
.point("11")),
1344 ElementsAre(sym("Foo", T
.range("ConstructorLoc"), std::nullopt
)));
1345 // These assertions are unordered because the order comes from
1346 // CXXRecordDecl::lookupDependentName() which doesn't appear to provide
1347 // an order guarantee.
1348 EXPECT_THAT(locateSymbolAt(AST
, T
.point("12")),
1349 UnorderedElementsAre(
1350 sym("bar", T
.range("NonstaticOverload1"), std::nullopt
),
1351 sym("bar", T
.range("NonstaticOverload2"), std::nullopt
)));
1352 EXPECT_THAT(locateSymbolAt(AST
, T
.point("13")),
1353 UnorderedElementsAre(
1354 sym("baz", T
.range("StaticOverload1"), std::nullopt
),
1355 sym("baz", T
.range("StaticOverload2"), std::nullopt
)));
1358 TEST(LocateSymbol
, TextualDependent
) {
1359 // Put the declarations in the header to make sure we are
1360 // finding them via the index heuristic and not the
1361 // nearby-ident heuristic.
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();
1381 // Need to use locateSymbolAt() since we are testing an
1382 // interaction between locateASTReferent() and
1383 // locateSymbolNamedTextuallyAt().
1384 auto Results
= locateSymbolAt(AST
, Source
.point(), Index
.get());
1387 UnorderedElementsAre(
1388 sym("uniqueMethodName", Header
.range("FooLoc"), std::nullopt
),
1389 sym("uniqueMethodName", Header
.range("BarLoc"), std::nullopt
)));
1392 TEST(LocateSymbol
, Alias
) {
1393 const char *Tests
[] = {
1395 template <class T> struct function {};
1396 template <class T> using [[callback]] = function<T()>;
1401 // triggered on non-definition of a renaming alias: should not give any
1402 // underlying decls.
1405 typedef Foo [[Bar]];
1411 using [[Bar]] = Foo; // definition
1415 // triggered on the underlying decl of a renaming alias.
1421 // triggered on definition of a non-renaming alias: should give underlying
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]] {}; }
1445 // other cases that don't matter much.
1448 typedef Foo [[Ba^r]];
1452 using [[B^ar]] = Foo;
1455 // Member of dependent base
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
);
1471 auto AST
= TestTU::withCode(T
.code()).build();
1472 EXPECT_THAT(locateSymbolAt(AST
, T
.point()),
1473 UnorderedPointwise(declRange(), T
.ranges()));
1477 TEST(LocateSymbol
, RelPathsInCompileCommand
) {
1478 // The source is in "/clangd-test/src".
1479 // We build in "/clangd-test/build".
1481 Annotations
SourceAnnotations(R
"cpp(
1482 #include "header_in_preamble
.h
"
1484 #include "header_not_in_preamble
.h
"
1485 int baz = f$p1^oo + bar_pre$p2^amble + bar_not_pre$p3^amble;
1488 Annotations
HeaderInPreambleAnnotations(R
"cpp(
1489 int [[bar_preamble]];
1492 Annotations
HeaderNotInPreambleAnnotations(R
"cpp(
1493 int [[bar_not_preamble]];
1496 // Make the compilation paths appear as ../src/foo.cpp in the compile
1498 SmallString
<32> RelPathPrefix("..");
1499 llvm::sys::path::append(RelPathPrefix
, "src");
1500 std::string BuildDir
= testPath("build");
1501 MockCompilationDatabase
CDB(BuildDir
, RelPathPrefix
);
1504 ClangdServer
Server(CDB
, FS
, ClangdServer::optsForTest());
1506 // Fill the filesystem.
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());
1515 runAddDocument(Server
, FooCpp
, SourceAnnotations
.code());
1517 // Go to a definition in main source file.
1519 runLocateSymbolAt(Server
, FooCpp
, SourceAnnotations
.point("p1"));
1520 EXPECT_TRUE(bool(Locations
)) << "findDefinitions returned an error";
1521 EXPECT_THAT(*Locations
, ElementsAre(sym("foo", SourceAnnotations
.range(),
1522 SourceAnnotations
.range())));
1524 // Go to a definition in header_in_preamble.h.
1525 Locations
= runLocateSymbolAt(Server
, FooCpp
, SourceAnnotations
.point("p2"));
1526 EXPECT_TRUE(bool(Locations
)) << "findDefinitions returned an error";
1529 ElementsAre(sym("bar_preamble", HeaderInPreambleAnnotations
.range(),
1530 HeaderInPreambleAnnotations
.range())));
1532 // Go to a definition in header_not_in_preamble.h.
1533 Locations
= runLocateSymbolAt(Server
, FooCpp
, SourceAnnotations
.point("p3"));
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())));
1541 TEST(GoToInclude
, All
) {
1543 MockCompilationDatabase CDB
;
1544 ClangdServer
Server(CDB
, FS
, ClangdServer::optsForTest());
1546 auto FooCpp
= testPath("foo.cpp");
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());
1557 auto FooH
= testPath("foo.h");
1559 const char *HeaderContents
= R
"cpp([[]]#pragma once
1562 Annotations
HeaderAnnotations(HeaderContents
);
1563 FS
.Files
[FooH
] = std::string(HeaderAnnotations
.code());
1565 runAddDocument(Server
, FooH
, HeaderAnnotations
.code());
1566 runAddDocument(Server
, FooCpp
, SourceAnnotations
.code());
1568 // Test include in preamble.
1569 auto Locations
= runLocateSymbolAt(Server
, FooCpp
, SourceAnnotations
.point());
1570 ASSERT_TRUE(bool(Locations
)) << "locateSymbolAt returned an error";
1571 EXPECT_THAT(*Locations
, ElementsAre(sym("foo.h", HeaderAnnotations
.range(),
1572 HeaderAnnotations
.range())));
1574 // Test include in preamble, last char.
1575 Locations
= runLocateSymbolAt(Server
, FooCpp
, SourceAnnotations
.point("2"));
1576 ASSERT_TRUE(bool(Locations
)) << "locateSymbolAt returned an error";
1577 EXPECT_THAT(*Locations
, ElementsAre(sym("foo.h", HeaderAnnotations
.range(),
1578 HeaderAnnotations
.range())));
1580 Locations
= runLocateSymbolAt(Server
, FooCpp
, SourceAnnotations
.point("3"));
1581 ASSERT_TRUE(bool(Locations
)) << "locateSymbolAt returned an error";
1582 EXPECT_THAT(*Locations
, ElementsAre(sym("foo.h", HeaderAnnotations
.range(),
1583 HeaderAnnotations
.range())));
1585 // Test include outside of preamble.
1586 Locations
= runLocateSymbolAt(Server
, FooCpp
, SourceAnnotations
.point("6"));
1587 ASSERT_TRUE(bool(Locations
)) << "locateSymbolAt returned an error";
1588 EXPECT_THAT(*Locations
, ElementsAre(sym("foo.h", HeaderAnnotations
.range(),
1589 HeaderAnnotations
.range())));
1591 // Test a few positions that do not result in Locations.
1592 Locations
= runLocateSymbolAt(Server
, FooCpp
, SourceAnnotations
.point("4"));
1593 ASSERT_TRUE(bool(Locations
)) << "locateSymbolAt returned an error";
1594 EXPECT_THAT(*Locations
, IsEmpty());
1596 Locations
= runLocateSymbolAt(Server
, FooCpp
, SourceAnnotations
.point("5"));
1597 ASSERT_TRUE(bool(Locations
)) << "locateSymbolAt returned an error";
1598 EXPECT_THAT(*Locations
, ElementsAre(sym("foo.h", HeaderAnnotations
.range(),
1599 HeaderAnnotations
.range())));
1601 Locations
= runLocateSymbolAt(Server
, FooCpp
, SourceAnnotations
.point("7"));
1602 ASSERT_TRUE(bool(Locations
)) << "locateSymbolAt returned an error";
1603 EXPECT_THAT(*Locations
, ElementsAre(sym("foo.h", HeaderAnnotations
.range(),
1604 HeaderAnnotations
.range())));
1606 // Objective C #import directive.
1607 Annotations
ObjC(R
"objc(
1610 auto FooM
= testPath("foo.m");
1611 FS
.Files
[FooM
] = std::string(ObjC
.code());
1613 runAddDocument(Server
, FooM
, ObjC
.code());
1614 Locations
= runLocateSymbolAt(Server
, FooM
, ObjC
.point());
1615 ASSERT_TRUE(bool(Locations
)) << "locateSymbolAt returned an error";
1616 EXPECT_THAT(*Locations
, ElementsAre(sym("foo.h", HeaderAnnotations
.range(),
1617 HeaderAnnotations
.range())));
1620 TEST(LocateSymbol
, WithPreamble
) {
1621 // Test stragety: AST should always use the latest preamble instead of last
1624 MockCompilationDatabase CDB
;
1625 ClangdServer
Server(CDB
, FS
, ClangdServer::optsForTest());
1627 auto FooCpp
= testPath("foo.cpp");
1628 // The trigger locations must be the same.
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());
1634 auto FooH
= testPath("foo.h");
1635 Annotations
FooHeader(R
"cpp([[]])cpp");
1636 FS
.Files
[FooH
] = std::string(FooHeader
.code());
1638 runAddDocument(Server
, FooCpp
, FooWithHeader
.code());
1639 // LocateSymbol goes to a #include file: the result comes from the preamble.
1641 cantFail(runLocateSymbolAt(Server
, FooCpp
, FooWithHeader
.point())),
1642 ElementsAre(sym("foo.h", FooHeader
.range(), FooHeader
.range())));
1644 // Only preamble is built, and no AST is built in this request.
1645 Server
.addDocument(FooCpp
, FooWithoutHeader
.code(), "null",
1646 WantDiagnostics::No
);
1647 // We build AST here, and it should use the latest preamble rather than the
1650 cantFail(runLocateSymbolAt(Server
, FooCpp
, FooWithoutHeader
.point())),
1651 ElementsAre(sym("foo", FooWithoutHeader
.range(), std::nullopt
)));
1653 // Reset test environment.
1654 runAddDocument(Server
, FooCpp
, FooWithHeader
.code());
1655 // Both preamble and AST are built in this request.
1656 Server
.addDocument(FooCpp
, FooWithoutHeader
.code(), "null",
1657 WantDiagnostics::Yes
);
1658 // Use the AST being built in above request.
1660 cantFail(runLocateSymbolAt(Server
, FooCpp
, FooWithoutHeader
.point())),
1661 ElementsAre(sym("foo", FooWithoutHeader
.range(), std::nullopt
)));
1664 TEST(LocateSymbol
, NearbyTokenSmoke
) {
1665 auto T
= Annotations(R
"cpp(
1666 // prints e^rr and crashes
1667 void die(const char* [[err]]);
1669 auto AST
= TestTU::withCode(T
.code()).build();
1670 // We don't pass an index, so can't hit index-based fallback.
1671 EXPECT_THAT(locateSymbolAt(AST
, T
.point()),
1672 ElementsAre(sym("err", T
.range(), T
.range())));
1675 TEST(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
);
1751 auto AST
= TestTU::withCode(T
.code()).build();
1752 const auto &SM
= AST
.getSourceManager();
1753 std::optional
<Range
> Nearby
;
1755 SpelledWord::touching(cantFail(sourceLocationInMainFile(SM
, T
.point())),
1756 AST
.getTokens(), AST
.getLangOpts());
1758 ADD_FAILURE() << "No word at point! " << Test
;
1761 if (const auto *Tok
= findNearbyIdentifier(*Word
, AST
.getTokens()))
1762 Nearby
= halfOpenToRange(SM
, CharSourceRange::getCharRange(
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
;
1771 TEST(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
);
1815 auto TU
= TestTU::withCode(Code
.code());
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
)) {
1820 EXPECT_THAT(findImplementations(AST
, Point
, Index
.get()),
1821 UnorderedPointwise(declRange(), Code
.ranges(Label
)))
1822 << Code
.code() << " at " << Point
<< " for Label " << Label
;
1827 TEST(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
);
1841 auto TU
= TestTU::withCode(Code
.code());
1842 auto AST
= TU
.build();
1844 findImplementations(AST
, Code
.point(), TU
.index().get()),
1845 UnorderedElementsAre(sym("Foo", Code
.range("Decl"), Code
.range("Def")),
1846 sym("Foo", Code
.range("Child2"), std::nullopt
)))
1850 TEST(FindType
, All
) {
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]] {
1863 auto TU
= TestTU::withHeaderCode(HeaderA
.code());
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())
1897 EXPECT_THAT(findType(AST
, Pos
, nullptr),
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();
1910 EXPECT_THAT(findType(AST
, A
.point(), nullptr),
1911 UnorderedElementsAre(
1912 sym("Target", HeaderA
.range("Target"), HeaderA
.range("Target")),
1913 sym("smart_ptr", HeaderA
.range("smart_ptr"), HeaderA
.range("smart_ptr"))
1919 TEST(FindType
, Definition
) {
1920 Annotations
A(R
"cpp(
1925 auto TU
= TestTU::withCode(A
.code().str());
1926 ParsedAST AST
= TU
.build();
1928 EXPECT_THAT(findType(AST
, A
.point(), nullptr),
1929 ElementsAre(sym("X", A
.range("decl"), A
.range("def"))));
1932 TEST(FindType
, Index
) {
1933 Annotations
Def(R
"cpp(
1934 // This definition is only available through the index.
1937 TestTU DefTU
= TestTU::withHeaderCode(Def
.code());
1938 DefTU
.HeaderFilename
= "def.h";
1939 auto DefIdx
= DefTU
.index();
1941 Annotations
A(R
"cpp(
1945 auto TU
= TestTU::withCode(A
.code().str());
1946 ParsedAST AST
= TU
.build();
1948 EXPECT_THAT(findType(AST
, A
.point(), DefIdx
.get()),
1949 ElementsAre(sym("X", A
.range(), Def
.range())));
1952 void checkFindRefs(llvm::StringRef Test
, bool UseIndex
= false) {
1953 Annotations
T(Test
);
1954 auto TU
= TestTU::withCode(T
.code());
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)));
1962 // $def is actually shorthand for both definition and declaration.
1963 // If we have cases that are definition-only, we should change this.
1964 for (const auto &[R
, Context
] : T
.rangesWithPayload("def"))
1965 ExpectedLocations
.push_back(AllOf(rangeIs(R
), containerIs(Context
),
1966 attrsAre(ReferencesResult::Definition
|
1967 ReferencesResult::Declaration
)));
1968 for (const auto &[R
, Context
] : T
.rangesWithPayload("decl"))
1969 ExpectedLocations
.push_back(AllOf(rangeIs(R
), containerIs(Context
),
1970 attrsAre(ReferencesResult::Declaration
)));
1971 for (const auto &[R
, Context
] : T
.rangesWithPayload("overridedecl"))
1972 ExpectedLocations
.push_back(AllOf(
1973 rangeIs(R
), containerIs(Context
),
1974 attrsAre(ReferencesResult::Declaration
| ReferencesResult::Override
)));
1975 for (const auto &[R
, Context
] : T
.rangesWithPayload("overridedef"))
1976 ExpectedLocations
.push_back(AllOf(rangeIs(R
), containerIs(Context
),
1977 attrsAre(ReferencesResult::Declaration
|
1978 ReferencesResult::Definition
|
1979 ReferencesResult::Override
)));
1980 for (const auto &P
: T
.points()) {
1981 EXPECT_THAT(findReferences(AST
, P
, 0, UseIndex
? TU
.index().get() : nullptr,
1982 /*AddContext*/ true)
1984 UnorderedElementsAreArray(ExpectedLocations
))
1985 << "Failed for Refs at " << P
<< "\n"
1990 TEST(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
);
2186 TEST(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
);
2205 TEST(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
);
2218 TEST(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
);
2231 TEST(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
, /*UseIndex=*/true);
2253 TEST(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
, /*UseIndex=*/true);
2277 TEST(FindReferences
, MainFileReferencesOnly
) {
2278 llvm::StringRef Test
=
2282 // refs not from main file should not be included.
2286 Annotations
Code(Test
);
2287 auto TU
= TestTU::withCode(Code
.code());
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
));
2296 EXPECT_THAT(findReferences(AST
, Code
.point(), 0).References
,
2297 ElementsAreArray(ExpectedLocations
))
2301 TEST(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
);
2353 TEST(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
);
2375 auto TU
= TestTU::withCode(T
.code());
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())
2399 EXPECT_THAT(findReferences(AST
, P
, 0).References
,
2400 UnorderedElementsAreArray(ExpectedLocations
))
2401 << "Failed for Refs at " << P
<< "\n"
2406 TEST(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();
2414 // References in main file are returned without index.
2416 findReferences(AST
, Main
.point(), 0, /*Index=*/nullptr).References
,
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]](); } }
2425 // References from indexed files are included.
2427 IndexedTU
.Code
= std::string(IndexedMain
.code());
2428 IndexedTU
.Filename
= "Indexed.cpp";
2429 IndexedTU
.HeaderCode
= Header
;
2431 findReferences(AST
, Main
.point(), 0, IndexedTU
.index().get(),
2432 /*AddContext*/ true)
2435 rangeIs(Main
.range()),
2436 AllOf(rangeIs(IndexedMain
.range("decl")),
2437 attrsAre(ReferencesResult::Declaration
|
2438 ReferencesResult::Definition
)),
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"))));
2443 findReferences(AST
, Main
.point(), /*Limit*/ 1, IndexedTU
.index().get());
2444 EXPECT_EQ(1u, LimitRefs
.References
.size());
2445 EXPECT_TRUE(LimitRefs
.HasMore
);
2447 // Avoid indexed results for the main file. Use AST for the mainfile.
2448 TU
.Code
= ("\n\n" + Main
.code()).str();
2449 EXPECT_THAT(findReferences(AST
, Main
.point(), 0, TU
.index().get()).References
,
2450 ElementsAre(rangeIs(Main
.range())));
2453 TEST(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();
2465 // References in main file are returned without index.
2467 findReferences(AST
, Main
.point(), 0, /*Index=*/nullptr).References
,
2468 ElementsAre(rangeIs(Main
.range())));
2470 Annotations
IndexedMain(R
"cpp(
2471 int indexed_main() {
2472 int a = [[MACRO]](1);
2476 // References from indexed files are included.
2478 IndexedTU
.Code
= std::string(IndexedMain
.code());
2479 IndexedTU
.Filename
= "Indexed.cpp";
2480 IndexedTU
.HeaderCode
= Header
;
2482 findReferences(AST
, Main
.point(), 0, IndexedTU
.index().get()).References
,
2483 ElementsAre(rangeIs(Main
.range()), rangeIs(IndexedMain
.range())));
2485 findReferences(AST
, Main
.point(), /*Limit*/ 1, IndexedTU
.index().get());
2486 EXPECT_EQ(1u, LimitRefs
.References
.size());
2487 EXPECT_TRUE(LimitRefs
.HasMore
);
2490 TEST(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
{
2501 StringRef AnnotatedCode
;
2505 // For now we don't assume header structure which would allow skipping.
2506 {"namespace { int ^x; }", true},
2507 {"static int ^x;", true},
2508 // Anything in a function certainly can't be referenced though.
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
);
2516 auto AST
= TestTU::withCode(File
.code()).build();
2517 findReferences(AST
, File
.point(), 0, &Rec
);
2519 EXPECT_NE(Rec
.RefIDs
, std::nullopt
) << T
.AnnotatedCode
;
2521 EXPECT_EQ(Rec
.RefIDs
, std::nullopt
) << T
.AnnotatedCode
;
2525 TEST(GetNonLocalDeclRefs
, All
) {
2527 llvm::StringRef AnnotatedCode
;
2528 std::vector
<std::string
> ExpectedDecls
;
2531 // VarDecl and ParamVarDecl
2534 void ^foo(int baz) {
2541 // Method from class
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
);
2581 auto AST
= TestTU::withCode(File
.code()).build();
2582 SourceLocation SL
= llvm::cantFail(
2583 sourceLocationInMainFile(AST
.getSourceManager(), File
.point()));
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);
2591 auto NonLocalDeclRefs
= getNonLocalDeclRefs(AST
, FD
);
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
))
2602 TEST(DocumentLinks
, All
) {
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();
2616 clangd::getDocumentLinks(AST
),
2618 DocumentLink({MainCpp
.range("foo"),
2619 URIForFile::canonicalize(testPath("foo.h"), "")}),
2620 DocumentLink({MainCpp
.range("bar"),
2621 URIForFile::canonicalize(testPath("bar.h"), "")})));
2625 } // namespace clangd
2626 } // namespace clang