[AMDGPU][AsmParser][NFC] Translate parsed MIMG instructions to MCInsts automatically.
[llvm-project.git] / clang-tools-extra / clangd / unittests / XRefsTests.cpp
blob1424e6aeefc4450fb6c7ecfe1340777624dee85a
1 //===-- XRefsTests.cpp ---------------------------*- C++ -*--------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 #include "Annotations.h"
9 #include "AST.h"
10 #include "ParsedAST.h"
11 #include "Protocol.h"
12 #include "SourceCode.h"
13 #include "SyncAPI.h"
14 #include "TestFS.h"
15 #include "TestTU.h"
16 #include "XRefs.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"
27 #include <optional>
28 #include <string>
29 #include <vector>
31 namespace clang {
32 namespace clangd {
33 namespace {
35 using ::testing::AllOf;
36 using ::testing::Contains;
37 using ::testing::ElementsAre;
38 using ::testing::Eq;
39 using ::testing::IsEmpty;
40 using ::testing::Matcher;
41 using ::testing::Not;
42 using ::testing::UnorderedElementsAre;
43 using ::testing::UnorderedElementsAreArray;
44 using ::testing::UnorderedPointwise;
46 std::string guard(llvm::StringRef Code) {
47 return "#pragma once\n" + Code.str();
50 MATCHER_P2(FileRange, File, Range, "") {
51 return Location{URIForFile::canonicalize(File, testRoot()), Range} == arg;
53 MATCHER(declRange, "") {
54 const LocatedSymbol &Sym = ::testing::get<0>(arg);
55 const Range &Range = ::testing::get<1>(arg);
56 return Sym.PreferredDeclaration.range == Range;
59 // Extracts ranges from an annotated example, and constructs a matcher for a
60 // highlight set. Ranges should be named $read/$write as appropriate.
61 Matcher<const std::vector<DocumentHighlight> &>
62 highlightsFrom(const Annotations &Test) {
63 std::vector<DocumentHighlight> Expected;
64 auto Add = [&](const Range &R, DocumentHighlightKind K) {
65 Expected.emplace_back();
66 Expected.back().range = R;
67 Expected.back().kind = K;
69 for (const auto &Range : Test.ranges())
70 Add(Range, DocumentHighlightKind::Text);
71 for (const auto &Range : Test.ranges("read"))
72 Add(Range, DocumentHighlightKind::Read);
73 for (const auto &Range : Test.ranges("write"))
74 Add(Range, DocumentHighlightKind::Write);
75 return UnorderedElementsAreArray(Expected);
78 TEST(HighlightsTest, All) {
79 const char *Tests[] = {
80 R"cpp(// Local variable
81 int main() {
82 int [[bonjour]];
83 $write[[^bonjour]] = 2;
84 int test1 = $read[[bonjour]];
86 )cpp",
88 R"cpp(// Struct
89 namespace ns1 {
90 struct [[MyClass]] {
91 static void foo([[MyClass]]*) {}
93 } // namespace ns1
94 int main() {
95 ns1::[[My^Class]]* Params;
97 )cpp",
99 R"cpp(// Function
100 int [[^foo]](int) {}
101 int main() {
102 [[foo]]([[foo]](42));
103 auto *X = &[[foo]];
105 )cpp",
107 R"cpp(// Function parameter in decl
108 void foo(int [[^bar]]);
109 )cpp",
110 R"cpp(// Not touching any identifiers.
111 struct Foo {
112 [[~]]Foo() {};
114 void foo() {
115 Foo f;
116 f.[[^~]]Foo();
118 )cpp",
119 R"cpp(// ObjC methods with split selectors.
120 @interface Foo
121 +(void) [[x]]:(int)a [[y]]:(int)b;
122 @end
123 @implementation Foo
124 +(void) [[x]]:(int)a [[y]]:(int)b {}
125 @end
126 void go() {
127 [Foo [[x]]:2 [[^y]]:4];
129 )cpp",
131 for (const char *Test : Tests) {
132 Annotations T(Test);
133 auto TU = TestTU::withCode(T.code());
134 TU.ExtraArgs.push_back("-xobjective-c++");
135 auto AST = TU.build();
136 EXPECT_THAT(findDocumentHighlights(AST, T.point()), highlightsFrom(T))
137 << Test;
141 TEST(HighlightsTest, ControlFlow) {
142 const char *Tests[] = {
143 R"cpp(
144 // Highlight same-function returns.
145 int fib(unsigned n) {
146 if (n <= 1) [[ret^urn]] 1;
147 [[return]] fib(n - 1) + fib(n - 2);
149 // Returns from other functions not highlighted.
150 auto Lambda = [] { return; };
151 class LocalClass { void x() { return; } };
153 )cpp",
155 R"cpp(
156 #define FAIL() return false
157 #define DO(x) { x; }
158 bool foo(int n) {
159 if (n < 0) [[FAIL]]();
160 DO([[re^turn]] true)
162 )cpp",
164 R"cpp(
165 // Highlight loop control flow
166 int magic() {
167 int counter = 0;
168 [[^for]] (char c : "fruit loops!") {
169 if (c == ' ') [[continue]];
170 counter += c;
171 if (c == '!') [[break]];
172 if (c == '?') [[return]] -1;
174 return counter;
176 )cpp",
178 R"cpp(
179 // Highlight loop and same-loop control flow
180 void nonsense() {
181 [[while]] (true) {
182 if (false) [[bre^ak]];
183 switch (1) break;
184 [[continue]];
187 )cpp",
189 R"cpp(
190 // Highlight switch for break (but not other breaks).
191 void describe(unsigned n) {
192 [[switch]](n) {
193 case 0:
194 break;
195 [[default]]:
196 [[^break]];
199 )cpp",
201 R"cpp(
202 // Highlight case and exits for switch-break (but not other cases).
203 void describe(unsigned n) {
204 [[switch]](n) {
205 case 0:
206 break;
207 [[case]] 1:
208 [[default]]:
209 [[return]];
210 [[^break]];
213 )cpp",
215 R"cpp(
216 // Highlight exits and switch for case
217 void describe(unsigned n) {
218 [[switch]](n) {
219 case 0:
220 break;
221 [[case]] 1:
222 [[d^efault]]:
223 [[return]];
224 [[break]];
227 )cpp",
229 R"cpp(
230 // Highlight nothing for switch.
231 void describe(unsigned n) {
232 s^witch(n) {
233 case 0:
234 break;
235 case 1:
236 default:
237 return;
238 break;
241 )cpp",
243 R"cpp(
244 // FIXME: match exception type against catch blocks
245 int catchy() {
246 try { // wrong: highlight try with matching catch
247 try { // correct: has no matching catch
248 [[thr^ow]] "oh no!";
249 } catch (int) { } // correct: catch doesn't match type
250 [[return]] -1; // correct: exits the matching catch
251 } catch (const char*) { } // wrong: highlight matching catch
252 [[return]] 42; // wrong: throw doesn't exit function
254 )cpp",
256 R"cpp(
257 // Loop highlights goto exiting the loop, but not jumping within it.
258 void jumpy() {
259 [[wh^ile]](1) {
261 if (0) [[goto]] out;
262 goto up;
264 out: return;
266 )cpp",
268 for (const char *Test : Tests) {
269 Annotations T(Test);
270 auto TU = TestTU::withCode(T.code());
271 TU.ExtraArgs.push_back("-fexceptions"); // FIXME: stop testing on PS4.
272 auto AST = TU.build();
273 EXPECT_THAT(findDocumentHighlights(AST, T.point()), highlightsFrom(T))
274 << Test;
278 MATCHER_P3(sym, Name, Decl, DefOrNone, "") {
279 std::optional<Range> Def = DefOrNone;
280 if (Name != arg.Name) {
281 *result_listener << "Name is " << arg.Name;
282 return false;
284 if (Decl != arg.PreferredDeclaration.range) {
285 *result_listener << "Declaration is "
286 << llvm::to_string(arg.PreferredDeclaration);
287 return false;
289 if (!Def && !arg.Definition)
290 return true;
291 if (Def && !arg.Definition) {
292 *result_listener << "Has no definition";
293 return false;
295 if (!Def && arg.Definition) {
296 *result_listener << "Definition is " << llvm::to_string(*arg.Definition);
297 return false;
299 if (arg.Definition->range != *Def) {
300 *result_listener << "Definition is " << llvm::to_string(*arg.Definition);
301 return false;
303 return true;
306 MATCHER_P(sym, Name, "") { return arg.Name == Name; }
308 MATCHER_P(rangeIs, R, "") { return arg.Loc.range == R; }
309 MATCHER_P(containerIs, C, "") {
310 return arg.Loc.containerName.value_or("") == C;
312 MATCHER_P(attrsAre, A, "") { return arg.Attributes == A; }
313 MATCHER_P(hasID, ID, "") { return arg.ID == ID; }
315 TEST(LocateSymbol, WithIndex) {
316 Annotations SymbolHeader(R"cpp(
317 class $forward[[Forward]];
318 class $foo[[Foo]] {};
320 void $f1[[f1]]();
322 inline void $f2[[f2]]() {}
323 )cpp");
324 Annotations SymbolCpp(R"cpp(
325 class $forward[[forward]] {};
326 void $f1[[f1]]() {}
327 )cpp");
329 TestTU TU;
330 TU.Code = std::string(SymbolCpp.code());
331 TU.HeaderCode = std::string(SymbolHeader.code());
332 auto Index = TU.index();
333 auto LocateWithIndex = [&Index](const Annotations &Main) {
334 auto AST = TestTU::withCode(Main.code()).build();
335 return clangd::locateSymbolAt(AST, Main.point(), Index.get());
338 Annotations Test(R"cpp(// only declaration in AST.
339 void [[f1]]();
340 int main() {
341 ^f1();
343 )cpp");
344 EXPECT_THAT(LocateWithIndex(Test),
345 ElementsAre(sym("f1", Test.range(), SymbolCpp.range("f1"))));
347 Test = Annotations(R"cpp(// definition in AST.
348 void [[f1]]() {}
349 int main() {
350 ^f1();
352 )cpp");
353 EXPECT_THAT(LocateWithIndex(Test),
354 ElementsAre(sym("f1", SymbolHeader.range("f1"), Test.range())));
356 Test = Annotations(R"cpp(// forward declaration in AST.
357 class [[Foo]];
358 F^oo* create();
359 )cpp");
360 EXPECT_THAT(LocateWithIndex(Test),
361 ElementsAre(sym("Foo", Test.range(), SymbolHeader.range("foo"))));
363 Test = Annotations(R"cpp(// definition in AST.
364 class [[Forward]] {};
365 F^orward create();
366 )cpp");
367 EXPECT_THAT(
368 LocateWithIndex(Test),
369 ElementsAre(sym("Forward", SymbolHeader.range("forward"), Test.range())));
372 TEST(LocateSymbol, AnonymousStructFields) {
373 auto Code = Annotations(R"cpp(
374 struct $2[[Foo]] {
375 struct { int $1[[x]]; };
376 void foo() {
377 // Make sure the implicit base is skipped.
378 $1^x = 42;
381 // Check that we don't skip explicit bases.
382 int a = $2^Foo{}.x;
383 )cpp");
384 TestTU TU = TestTU::withCode(Code.code());
385 auto AST = TU.build();
386 EXPECT_THAT(locateSymbolAt(AST, Code.point("1"), TU.index().get()),
387 UnorderedElementsAre(sym("x", Code.range("1"), Code.range("1"))));
388 EXPECT_THAT(
389 locateSymbolAt(AST, Code.point("2"), TU.index().get()),
390 UnorderedElementsAre(sym("Foo", Code.range("2"), Code.range("2"))));
393 TEST(LocateSymbol, FindOverrides) {
394 auto Code = Annotations(R"cpp(
395 class Foo {
396 virtual void $1[[fo^o]]() = 0;
398 class Bar : public Foo {
399 void $2[[foo]]() override;
401 )cpp");
402 TestTU TU = TestTU::withCode(Code.code());
403 auto AST = TU.build();
404 EXPECT_THAT(locateSymbolAt(AST, Code.point(), TU.index().get()),
405 UnorderedElementsAre(sym("foo", Code.range("1"), std::nullopt),
406 sym("foo", Code.range("2"), std::nullopt)));
409 TEST(LocateSymbol, WithIndexPreferredLocation) {
410 Annotations SymbolHeader(R"cpp(
411 class $p[[Proto]] {};
412 void $f[[func]]() {};
413 )cpp");
414 TestTU TU;
415 TU.HeaderCode = std::string(SymbolHeader.code());
416 TU.HeaderFilename = "x.proto"; // Prefer locations in codegen files.
417 auto Index = TU.index();
419 Annotations Test(R"cpp(// only declaration in AST.
420 // Shift to make range different.
421 class Proto;
422 void func() {}
423 P$p^roto* create() {
424 fu$f^nc();
425 return nullptr;
427 )cpp");
429 auto AST = TestTU::withCode(Test.code()).build();
431 auto Locs = clangd::locateSymbolAt(AST, Test.point("p"), Index.get());
432 auto CodeGenLoc = SymbolHeader.range("p");
433 EXPECT_THAT(Locs, ElementsAre(sym("Proto", CodeGenLoc, CodeGenLoc)));
436 auto Locs = clangd::locateSymbolAt(AST, Test.point("f"), Index.get());
437 auto CodeGenLoc = SymbolHeader.range("f");
438 EXPECT_THAT(Locs, ElementsAre(sym("func", CodeGenLoc, CodeGenLoc)));
442 TEST(LocateSymbol, All) {
443 // Ranges in tests:
444 // $decl is the declaration location (if absent, no symbol is located)
445 // $def is the definition location (if absent, symbol has no definition)
446 // unnamed range becomes both $decl and $def.
447 const char *Tests[] = {
448 R"cpp(
449 struct X {
450 union {
451 int [[a]];
452 float b;
455 int test(X &x) {
456 return x.^a;
458 )cpp",
460 R"cpp(// Local variable
461 int main() {
462 int [[bonjour]];
463 ^bonjour = 2;
464 int test1 = bonjour;
466 )cpp",
468 R"cpp(// Struct
469 namespace ns1 {
470 struct [[MyClass]] {};
471 } // namespace ns1
472 int main() {
473 ns1::My^Class* Params;
475 )cpp",
477 R"cpp(// Function definition via pointer
478 void [[foo]](int) {}
479 int main() {
480 auto *X = &^foo;
482 )cpp",
484 R"cpp(// Function declaration via call
485 int $decl[[foo]](int);
486 int main() {
487 return ^foo(42);
489 )cpp",
491 R"cpp(// Field
492 struct Foo { int [[x]]; };
493 int main() {
494 Foo bar;
495 (void)bar.^x;
497 )cpp",
499 R"cpp(// Field, member initializer
500 struct Foo {
501 int [[x]];
502 Foo() : ^x(0) {}
504 )cpp",
506 R"cpp(// Field, field designator
507 struct Foo { int [[x]]; };
508 int main() {
509 Foo bar = { .^x = 2 };
511 )cpp",
513 R"cpp(// Method call
514 struct Foo { int $decl[[x]](); };
515 int main() {
516 Foo bar;
517 bar.^x();
519 )cpp",
521 R"cpp(// Typedef
522 typedef int $decl[[Foo]];
523 int main() {
524 ^Foo bar;
526 )cpp",
528 R"cpp(// Template type parameter
529 template <typename [[T]]>
530 void foo() { ^T t; }
531 )cpp",
533 R"cpp(// Template template type parameter
534 template <template<typename> class [[T]]>
535 void foo() { ^T<int> t; }
536 )cpp",
538 R"cpp(// Namespace
539 namespace $decl[[ns]] {
540 struct Foo { static void bar(); };
541 } // namespace ns
542 int main() { ^ns::Foo::bar(); }
543 )cpp",
545 R"cpp(// Macro
546 class TTT { public: int a; };
547 #define [[FF]](S) if (int b = S.a) {}
548 void f() {
549 TTT t;
550 F^F(t);
552 )cpp",
554 R"cpp(// Macro argument
555 int [[i]];
556 #define ADDRESSOF(X) &X;
557 int *j = ADDRESSOF(^i);
558 )cpp",
559 R"cpp(// Macro argument appearing multiple times in expansion
560 #define VALIDATE_TYPE(x) (void)x;
561 #define ASSERT(expr) \
562 do { \
563 VALIDATE_TYPE(expr); \
564 if (!expr); \
565 } while (false)
566 bool [[waldo]]() { return true; }
567 void foo() {
568 ASSERT(wa^ldo());
570 )cpp",
571 R"cpp(// Symbol concatenated inside macro (not supported)
572 int *pi;
573 #define POINTER(X) p ## X;
574 int x = *POINTER(^i);
575 )cpp",
577 R"cpp(// Forward class declaration
578 class $decl[[Foo]];
579 class $def[[Foo]] {};
580 F^oo* foo();
581 )cpp",
583 R"cpp(// Function declaration
584 void $decl[[foo]]();
585 void g() { f^oo(); }
586 void $def[[foo]]() {}
587 )cpp",
589 R"cpp(
590 #define FF(name) class name##_Test {};
591 [[FF]](my);
592 void f() { my^_Test a; }
593 )cpp",
595 R"cpp(
596 #define FF() class [[Test]] {};
597 FF();
598 void f() { T^est a; }
599 )cpp",
601 R"cpp(// explicit template specialization
602 template <typename T>
603 struct Foo { void bar() {} };
605 template <>
606 struct [[Foo]]<int> { void bar() {} };
608 void foo() {
609 Foo<char> abc;
610 Fo^o<int> b;
612 )cpp",
614 R"cpp(// implicit template specialization
615 template <typename T>
616 struct [[Foo]] { void bar() {} };
617 template <>
618 struct Foo<int> { void bar() {} };
619 void foo() {
620 Fo^o<char> abc;
621 Foo<int> b;
623 )cpp",
625 R"cpp(// partial template specialization
626 template <typename T>
627 struct Foo { void bar() {} };
628 template <typename T>
629 struct [[Foo]]<T*> { void bar() {} };
630 ^Foo<int*> x;
631 )cpp",
633 R"cpp(// function template specializations
634 template <class T>
635 void foo(T) {}
636 template <>
637 void [[foo]](int) {}
638 void bar() {
639 fo^o(10);
641 )cpp",
643 R"cpp(// variable template decls
644 template <class T>
645 T var = T();
647 template <>
648 double [[var]]<int> = 10;
650 double y = va^r<int>;
651 )cpp",
653 R"cpp(// No implicit constructors
654 struct X {
655 X(X&& x) = default;
657 X $decl[[makeX]]();
658 void foo() {
659 auto x = m^akeX();
661 )cpp",
663 R"cpp(
664 struct X {
665 X& $decl[[operator]]++();
667 void foo(X& x) {
668 +^+x;
670 )cpp",
672 R"cpp(
673 struct S1 { void f(); };
674 struct S2 { S1 * $decl[[operator]]->(); };
675 void test(S2 s2) {
676 s2-^>f();
678 )cpp",
680 R"cpp(// Declaration of explicit template specialization
681 template <typename T>
682 struct $decl[[$def[[Foo]]]] {};
684 template <>
685 struct Fo^o<int> {};
686 )cpp",
688 R"cpp(// Declaration of partial template specialization
689 template <typename T>
690 struct $decl[[$def[[Foo]]]] {};
692 template <typename T>
693 struct Fo^o<T*> {};
694 )cpp",
696 R"cpp(// Definition on ClassTemplateDecl
697 namespace ns {
698 // Forward declaration.
699 template<typename T>
700 struct $decl[[Foo]];
702 template <typename T>
703 struct $def[[Foo]] {};
706 using ::ns::Fo^o;
707 )cpp",
709 R"cpp(// auto builtin type (not supported)
710 ^auto x = 42;
711 )cpp",
713 R"cpp(// auto on lambda
714 auto x = [[[]]]{};
715 ^auto y = x;
716 )cpp",
718 R"cpp(// auto on struct
719 namespace ns1 {
720 struct [[S1]] {};
721 } // namespace ns1
723 ^auto x = ns1::S1{};
724 )cpp",
726 R"cpp(// decltype on struct
727 namespace ns1 {
728 struct [[S1]] {};
729 } // namespace ns1
731 ns1::S1 i;
732 ^decltype(i) j;
733 )cpp",
735 R"cpp(// decltype(auto) on struct
736 namespace ns1 {
737 struct [[S1]] {};
738 } // namespace ns1
740 ns1::S1 i;
741 ns1::S1& j = i;
742 ^decltype(auto) k = j;
743 )cpp",
745 R"cpp(// auto on template class
746 template<typename T> class [[Foo]] {};
748 ^auto x = Foo<int>();
749 )cpp",
751 R"cpp(// auto on template class with forward declared class
752 template<typename T> class [[Foo]] {};
753 class X;
755 ^auto x = Foo<X>();
756 )cpp",
758 R"cpp(// auto on specialized template class
759 template<typename T> class Foo {};
760 template<> class [[Foo]]<int> {};
762 ^auto x = Foo<int>();
763 )cpp",
765 R"cpp(// auto on initializer list.
766 namespace std
768 template<class _E>
769 class [[initializer_list]] {};
772 ^auto i = {1,2};
773 )cpp",
775 R"cpp(// auto function return with trailing type
776 struct [[Bar]] {};
777 ^auto test() -> decltype(Bar()) {
778 return Bar();
780 )cpp",
782 R"cpp(// decltype in trailing return type
783 struct [[Bar]] {};
784 auto test() -> ^decltype(Bar()) {
785 return Bar();
787 )cpp",
789 R"cpp(// auto in function return
790 struct [[Bar]] {};
791 ^auto test() {
792 return Bar();
794 )cpp",
796 R"cpp(// auto& in function return
797 struct [[Bar]] {};
798 ^auto& test() {
799 static Bar x;
800 return x;
802 )cpp",
804 R"cpp(// auto* in function return
805 struct [[Bar]] {};
806 ^auto* test() {
807 Bar* x;
808 return x;
810 )cpp",
812 R"cpp(// const auto& in function return
813 struct [[Bar]] {};
814 const ^auto& test() {
815 static Bar x;
816 return x;
818 )cpp",
820 R"cpp(// auto lambda param where there's a single instantiation
821 struct [[Bar]] {};
822 auto Lambda = [](^auto){ return 0; };
823 int x = Lambda(Bar{});
824 )cpp",
826 R"cpp(// decltype(auto) in function return
827 struct [[Bar]] {};
828 ^decltype(auto) test() {
829 return Bar();
831 )cpp",
833 R"cpp(// decltype of function with trailing return type.
834 struct [[Bar]] {};
835 auto test() -> decltype(Bar()) {
836 return Bar();
838 void foo() {
839 ^decltype(test()) i = test();
841 )cpp",
843 R"cpp(// Override specifier jumps to overridden method
844 class Y { virtual void $decl[[a]]() = 0; };
845 class X : Y { void a() ^override {} };
846 )cpp",
848 R"cpp(// Final specifier jumps to overridden method
849 class Y { virtual void $decl[[a]]() = 0; };
850 class X : Y { void a() ^final {} };
851 )cpp",
853 R"cpp(// Heuristic resolution of dependent method
854 template <typename T>
855 struct S {
856 void [[bar]]() {}
859 template <typename T>
860 void foo(S<T> arg) {
861 arg.ba^r();
863 )cpp",
865 R"cpp(// Heuristic resolution of dependent method via this->
866 template <typename T>
867 struct S {
868 void [[foo]]() {
869 this->fo^o();
872 )cpp",
874 R"cpp(// Heuristic resolution of dependent static method
875 template <typename T>
876 struct S {
877 static void [[bar]]() {}
880 template <typename T>
881 void foo() {
882 S<T>::ba^r();
884 )cpp",
886 R"cpp(// Heuristic resolution of dependent method
887 // invoked via smart pointer
888 template <typename> struct S { void [[foo]]() {} };
889 template <typename T> struct unique_ptr {
890 T* operator->();
892 template <typename T>
893 void test(unique_ptr<S<T>>& V) {
894 V->fo^o();
896 )cpp",
898 R"cpp(// Heuristic resolution of dependent enumerator
899 template <typename T>
900 struct Foo {
901 enum class E { [[A]], B };
902 E e = E::A^;
904 )cpp",
906 R"cpp(// Enum base
907 typedef int $decl[[MyTypeDef]];
908 enum Foo : My^TypeDef {};
909 )cpp",
910 R"cpp(// Enum base
911 typedef int $decl[[MyTypeDef]];
912 enum Foo : My^TypeDef;
913 )cpp",
914 R"cpp(// Enum base
915 using $decl[[MyTypeDef]] = int;
916 enum Foo : My^TypeDef {};
917 )cpp",
919 R"objc(
920 @protocol Dog;
921 @protocol $decl[[Dog]]
922 - (void)bark;
923 @end
924 id<Do^g> getDoggo() {
925 return 0;
927 )objc",
929 R"objc(
930 @interface Cat
931 @end
932 @implementation Cat
933 @end
934 @interface $decl[[Cat]] (Exte^nsion)
935 - (void)meow;
936 @end
937 @implementation $def[[Cat]] (Extension)
938 - (void)meow {}
939 @end
940 )objc",
942 R"objc(
943 @class $decl[[Foo]];
944 Fo^o * getFoo() {
945 return 0;
947 )objc",
949 R"objc(// Prefer interface definition over forward declaration
950 @class Foo;
951 @interface $decl[[Foo]]
952 @end
953 Fo^o * getFoo() {
954 return 0;
956 )objc",
958 R"objc(
959 @class Foo;
960 @interface $decl[[Foo]]
961 @end
962 @implementation $def[[Foo]]
963 @end
964 Fo^o * getFoo() {
965 return 0;
967 )objc",
969 R"objc(// Method decl and definition for ObjC class.
970 @interface Cat
971 - (void)$decl[[meow]];
972 @end
973 @implementation Cat
974 - (void)$def[[meow]] {}
975 @end
976 void makeNoise(Cat *kitty) {
977 [kitty me^ow];
979 )objc",
981 R"objc(// Method decl and definition for ObjC category.
982 @interface Dog
983 @end
984 @interface Dog (Play)
985 - (void)$decl[[runAround]];
986 @end
987 @implementation Dog (Play)
988 - (void)$def[[runAround]] {}
989 @end
990 void play(Dog *dog) {
991 [dog run^Around];
993 )objc",
995 R"objc(// Method decl and definition for ObjC class extension.
996 @interface Dog
997 @end
998 @interface Dog ()
999 - (void)$decl[[howl]];
1000 @end
1001 @implementation Dog
1002 - (void)$def[[howl]] {}
1003 @end
1004 void play(Dog *dog) {
1005 [dog ho^wl];
1007 )objc"};
1008 for (const char *Test : Tests) {
1009 Annotations T(Test);
1010 std::optional<Range> WantDecl;
1011 std::optional<Range> WantDef;
1012 if (!T.ranges().empty())
1013 WantDecl = WantDef = T.range();
1014 if (!T.ranges("decl").empty())
1015 WantDecl = T.range("decl");
1016 if (!T.ranges("def").empty())
1017 WantDef = T.range("def");
1019 TestTU TU;
1020 TU.Code = std::string(T.code());
1022 TU.ExtraArgs.push_back("-xobjective-c++");
1024 auto AST = TU.build();
1025 auto Results = locateSymbolAt(AST, T.point());
1027 if (!WantDecl) {
1028 EXPECT_THAT(Results, IsEmpty()) << Test;
1029 } else {
1030 ASSERT_THAT(Results, ::testing::SizeIs(1)) << Test;
1031 EXPECT_EQ(Results[0].PreferredDeclaration.range, *WantDecl) << Test;
1032 EXPECT_TRUE(Results[0].ID) << Test;
1033 std::optional<Range> GotDef;
1034 if (Results[0].Definition)
1035 GotDef = Results[0].Definition->range;
1036 EXPECT_EQ(WantDef, GotDef) << Test;
1040 TEST(LocateSymbol, ValidSymbolID) {
1041 auto T = Annotations(R"cpp(
1042 #define MACRO(x, y) ((x) + (y))
1043 int add(int x, int y) { return $MACRO^MACRO(x, y); }
1044 int sum = $add^add(1, 2);
1045 )cpp");
1047 TestTU TU = TestTU::withCode(T.code());
1048 auto AST = TU.build();
1049 auto Index = TU.index();
1050 EXPECT_THAT(locateSymbolAt(AST, T.point("add"), Index.get()),
1051 ElementsAre(AllOf(sym("add"),
1052 hasID(getSymbolID(&findDecl(AST, "add"))))));
1053 EXPECT_THAT(
1054 locateSymbolAt(AST, T.point("MACRO"), Index.get()),
1055 ElementsAre(AllOf(sym("MACRO"),
1056 hasID(findSymbol(TU.headerSymbols(), "MACRO").ID))));
1059 TEST(LocateSymbol, AllMulti) {
1060 // Ranges in tests:
1061 // $declN is the declaration location
1062 // $defN is the definition location (if absent, symbol has no definition)
1064 // NOTE:
1065 // N starts at 0.
1066 struct ExpectedRanges {
1067 Range WantDecl;
1068 std::optional<Range> WantDef;
1070 const char *Tests[] = {
1071 R"objc(
1072 @interface $decl0[[Cat]]
1073 @end
1074 @implementation $def0[[Cat]]
1075 @end
1076 @interface $decl1[[Ca^t]] (Extension)
1077 - (void)meow;
1078 @end
1079 @implementation $def1[[Cat]] (Extension)
1080 - (void)meow {}
1081 @end
1082 )objc",
1084 R"objc(
1085 @interface $decl0[[Cat]]
1086 @end
1087 @implementation $def0[[Cat]]
1088 @end
1089 @interface $decl1[[Cat]] (Extension)
1090 - (void)meow;
1091 @end
1092 @implementation $def1[[Ca^t]] (Extension)
1093 - (void)meow {}
1094 @end
1095 )objc",
1097 R"objc(
1098 @interface $decl0[[Cat]]
1099 @end
1100 @interface $decl1[[Ca^t]] ()
1101 - (void)meow;
1102 @end
1103 @implementation $def0[[$def1[[Cat]]]]
1104 - (void)meow {}
1105 @end
1106 )objc",
1108 for (const char *Test : Tests) {
1109 Annotations T(Test);
1110 std::vector<ExpectedRanges> Ranges;
1111 for (int Idx = 0; true; Idx++) {
1112 bool HasDecl = !T.ranges("decl" + std::to_string(Idx)).empty();
1113 bool HasDef = !T.ranges("def" + std::to_string(Idx)).empty();
1114 if (!HasDecl && !HasDef)
1115 break;
1116 ExpectedRanges Range;
1117 if (HasDecl)
1118 Range.WantDecl = T.range("decl" + std::to_string(Idx));
1119 if (HasDef)
1120 Range.WantDef = T.range("def" + std::to_string(Idx));
1121 Ranges.push_back(Range);
1124 TestTU TU;
1125 TU.Code = std::string(T.code());
1126 TU.ExtraArgs.push_back("-xobjective-c++");
1128 auto AST = TU.build();
1129 auto Results = locateSymbolAt(AST, T.point());
1131 ASSERT_THAT(Results, ::testing::SizeIs(Ranges.size())) << Test;
1132 for (size_t Idx = 0; Idx < Ranges.size(); Idx++) {
1133 EXPECT_EQ(Results[Idx].PreferredDeclaration.range, Ranges[Idx].WantDecl)
1134 << "($decl" << Idx << ")" << Test;
1135 std::optional<Range> GotDef;
1136 if (Results[Idx].Definition)
1137 GotDef = Results[Idx].Definition->range;
1138 EXPECT_EQ(GotDef, Ranges[Idx].WantDef) << "($def" << Idx << ")" << Test;
1143 // LocateSymbol test cases that produce warnings.
1144 // These are separated out from All so that in All we can assert
1145 // that there are no diagnostics.
1146 TEST(LocateSymbol, Warnings) {
1147 const char *Tests[] = {
1148 R"cpp(// Field, GNU old-style field designator
1149 struct Foo { int [[x]]; };
1150 int main() {
1151 Foo bar = { ^x : 1 };
1153 )cpp",
1155 R"cpp(// Macro
1156 #define MACRO 0
1157 #define [[MACRO]] 1
1158 int main() { return ^MACRO; }
1159 #define MACRO 2
1160 #undef macro
1161 )cpp",
1164 for (const char *Test : Tests) {
1165 Annotations T(Test);
1166 std::optional<Range> WantDecl;
1167 std::optional<Range> WantDef;
1168 if (!T.ranges().empty())
1169 WantDecl = WantDef = T.range();
1170 if (!T.ranges("decl").empty())
1171 WantDecl = T.range("decl");
1172 if (!T.ranges("def").empty())
1173 WantDef = T.range("def");
1175 TestTU TU;
1176 TU.Code = std::string(T.code());
1178 auto AST = TU.build();
1179 auto Results = locateSymbolAt(AST, T.point());
1181 if (!WantDecl) {
1182 EXPECT_THAT(Results, IsEmpty()) << Test;
1183 } else {
1184 ASSERT_THAT(Results, ::testing::SizeIs(1)) << Test;
1185 EXPECT_EQ(Results[0].PreferredDeclaration.range, *WantDecl) << Test;
1186 std::optional<Range> GotDef;
1187 if (Results[0].Definition)
1188 GotDef = Results[0].Definition->range;
1189 EXPECT_EQ(WantDef, GotDef) << Test;
1194 TEST(LocateSymbol, TextualSmoke) {
1195 auto T = Annotations(
1196 R"cpp(
1197 struct [[MyClass]] {};
1198 // Comment mentioning M^yClass
1199 )cpp");
1201 auto TU = TestTU::withCode(T.code());
1202 auto AST = TU.build();
1203 auto Index = TU.index();
1204 EXPECT_THAT(
1205 locateSymbolAt(AST, T.point(), Index.get()),
1206 ElementsAre(AllOf(sym("MyClass", T.range(), T.range()),
1207 hasID(getSymbolID(&findDecl(AST, "MyClass"))))));
1210 TEST(LocateSymbol, Textual) {
1211 const char *Tests[] = {
1212 R"cpp(// Comment
1213 struct [[MyClass]] {};
1214 // Comment mentioning M^yClass
1215 )cpp",
1216 R"cpp(// String
1217 struct MyClass {};
1218 // Not triggered for string literal tokens.
1219 const char* s = "String literal mentioning M^yClass";
1220 )cpp",
1221 R"cpp(// Ifdef'ed out code
1222 struct [[MyClass]] {};
1223 #ifdef WALDO
1224 M^yClass var;
1225 #endif
1226 )cpp",
1227 R"cpp(// Macro definition
1228 struct [[MyClass]] {};
1229 #define DECLARE_MYCLASS_OBJ(name) M^yClass name;
1230 )cpp",
1231 R"cpp(// Invalid code
1232 /*error-ok*/
1233 int myFunction(int);
1234 // Not triggered for token which survived preprocessing.
1235 int var = m^yFunction();
1236 )cpp"};
1238 for (const char *Test : Tests) {
1239 Annotations T(Test);
1240 std::optional<Range> WantDecl;
1241 if (!T.ranges().empty())
1242 WantDecl = T.range();
1244 auto TU = TestTU::withCode(T.code());
1246 auto AST = TU.build();
1247 auto Index = TU.index();
1248 auto Word = SpelledWord::touching(
1249 cantFail(sourceLocationInMainFile(AST.getSourceManager(), T.point())),
1250 AST.getTokens(), AST.getLangOpts());
1251 if (!Word) {
1252 ADD_FAILURE() << "No word touching point!" << Test;
1253 continue;
1255 auto Results = locateSymbolTextually(*Word, AST, Index.get(),
1256 testPath(TU.Filename), ASTNodeKind());
1258 if (!WantDecl) {
1259 EXPECT_THAT(Results, IsEmpty()) << Test;
1260 } else {
1261 ASSERT_THAT(Results, ::testing::SizeIs(1)) << Test;
1262 EXPECT_EQ(Results[0].PreferredDeclaration.range, *WantDecl) << Test;
1265 } // namespace
1267 TEST(LocateSymbol, Ambiguous) {
1268 auto T = Annotations(R"cpp(
1269 struct Foo {
1270 Foo();
1271 Foo(Foo&&);
1272 $ConstructorLoc[[Foo]](const char*);
1275 Foo f();
1277 void g(Foo foo);
1279 void call() {
1280 const char* str = "123";
1281 Foo a = $1^str;
1282 Foo b = Foo($2^str);
1283 Foo c = $3^f();
1284 $4^g($5^f());
1285 g($6^str);
1286 Foo ab$7^c;
1287 Foo ab$8^cd("asdf");
1288 Foo foox = Fo$9^o("asdf");
1289 Foo abcde$10^("asdf");
1290 Foo foox2 = Foo$11^("asdf");
1293 template <typename T>
1294 struct S {
1295 void $NonstaticOverload1[[bar]](int);
1296 void $NonstaticOverload2[[bar]](float);
1298 static void $StaticOverload1[[baz]](int);
1299 static void $StaticOverload2[[baz]](float);
1302 template <typename T, typename U>
1303 void dependent_call(S<T> s, U u) {
1304 s.ba$12^r(u);
1305 S<T>::ba$13^z(u);
1307 )cpp");
1308 auto TU = TestTU::withCode(T.code());
1309 // FIXME: Go-to-definition in a template requires disabling delayed template
1310 // parsing.
1311 TU.ExtraArgs.push_back("-fno-delayed-template-parsing");
1312 auto AST = TU.build();
1313 // Ordered assertions are deliberate: we expect a predictable order.
1314 EXPECT_THAT(locateSymbolAt(AST, T.point("1")), ElementsAre(sym("str")));
1315 EXPECT_THAT(locateSymbolAt(AST, T.point("2")), ElementsAre(sym("str")));
1316 EXPECT_THAT(locateSymbolAt(AST, T.point("3")), ElementsAre(sym("f")));
1317 EXPECT_THAT(locateSymbolAt(AST, T.point("4")), ElementsAre(sym("g")));
1318 EXPECT_THAT(locateSymbolAt(AST, T.point("5")), ElementsAre(sym("f")));
1319 EXPECT_THAT(locateSymbolAt(AST, T.point("6")), ElementsAre(sym("str")));
1320 // FIXME: Target the constructor as well.
1321 EXPECT_THAT(locateSymbolAt(AST, T.point("7")), ElementsAre(sym("abc")));
1322 // FIXME: Target the constructor as well.
1323 EXPECT_THAT(locateSymbolAt(AST, T.point("8")), ElementsAre(sym("abcd")));
1324 // FIXME: Target the constructor as well.
1325 EXPECT_THAT(locateSymbolAt(AST, T.point("9")), ElementsAre(sym("Foo")));
1326 EXPECT_THAT(locateSymbolAt(AST, T.point("10")),
1327 ElementsAre(sym("Foo", T.range("ConstructorLoc"), std::nullopt)));
1328 EXPECT_THAT(locateSymbolAt(AST, T.point("11")),
1329 ElementsAre(sym("Foo", T.range("ConstructorLoc"), std::nullopt)));
1330 // These assertions are unordered because the order comes from
1331 // CXXRecordDecl::lookupDependentName() which doesn't appear to provide
1332 // an order guarantee.
1333 EXPECT_THAT(locateSymbolAt(AST, T.point("12")),
1334 UnorderedElementsAre(
1335 sym("bar", T.range("NonstaticOverload1"), std::nullopt),
1336 sym("bar", T.range("NonstaticOverload2"), std::nullopt)));
1337 EXPECT_THAT(locateSymbolAt(AST, T.point("13")),
1338 UnorderedElementsAre(
1339 sym("baz", T.range("StaticOverload1"), std::nullopt),
1340 sym("baz", T.range("StaticOverload2"), std::nullopt)));
1343 TEST(LocateSymbol, TextualDependent) {
1344 // Put the declarations in the header to make sure we are
1345 // finding them via the index heuristic and not the
1346 // nearby-ident heuristic.
1347 Annotations Header(R"cpp(
1348 struct Foo {
1349 void $FooLoc[[uniqueMethodName]]();
1351 struct Bar {
1352 void $BarLoc[[uniqueMethodName]]();
1354 )cpp");
1355 Annotations Source(R"cpp(
1356 template <typename T>
1357 void f(T t) {
1358 t.u^niqueMethodName();
1360 )cpp");
1361 TestTU TU;
1362 TU.Code = std::string(Source.code());
1363 TU.HeaderCode = std::string(Header.code());
1364 auto AST = TU.build();
1365 auto Index = TU.index();
1366 // Need to use locateSymbolAt() since we are testing an
1367 // interaction between locateASTReferent() and
1368 // locateSymbolNamedTextuallyAt().
1369 auto Results = locateSymbolAt(AST, Source.point(), Index.get());
1370 EXPECT_THAT(
1371 Results,
1372 UnorderedElementsAre(
1373 sym("uniqueMethodName", Header.range("FooLoc"), std::nullopt),
1374 sym("uniqueMethodName", Header.range("BarLoc"), std::nullopt)));
1377 TEST(LocateSymbol, Alias) {
1378 const char *Tests[] = {
1379 R"cpp(
1380 template <class T> struct function {};
1381 template <class T> using [[callback]] = function<T()>;
1383 c^allback<int> foo;
1384 )cpp",
1386 // triggered on non-definition of a renaming alias: should not give any
1387 // underlying decls.
1388 R"cpp(
1389 class Foo {};
1390 typedef Foo [[Bar]];
1392 B^ar b;
1393 )cpp",
1394 R"cpp(
1395 class Foo {};
1396 using [[Bar]] = Foo; // definition
1397 Ba^r b;
1398 )cpp",
1400 // triggered on the underlying decl of a renaming alias.
1401 R"cpp(
1402 class [[Foo]];
1403 using Bar = Fo^o;
1404 )cpp",
1406 // triggered on definition of a non-renaming alias: should give underlying
1407 // decls.
1408 R"cpp(
1409 namespace ns { class [[Foo]] {}; }
1410 using ns::F^oo;
1411 )cpp",
1413 R"cpp(
1414 namespace ns { int [[x]](char); int [[x]](double); }
1415 using ns::^x;
1416 )cpp",
1418 R"cpp(
1419 namespace ns { int [[x]](char); int x(double); }
1420 using ns::[[x]];
1421 int y = ^x('a');
1422 )cpp",
1424 R"cpp(
1425 namespace ns { class [[Foo]] {}; }
1426 using ns::[[Foo]];
1427 F^oo f;
1428 )cpp",
1430 // other cases that don't matter much.
1431 R"cpp(
1432 class Foo {};
1433 typedef Foo [[Ba^r]];
1434 )cpp",
1435 R"cpp(
1436 class Foo {};
1437 using [[B^ar]] = Foo;
1438 )cpp",
1440 // Member of dependent base
1441 R"cpp(
1442 template <typename T>
1443 struct Base {
1444 void [[waldo]]() {}
1446 template <typename T>
1447 struct Derived : Base<T> {
1448 using Base<T>::w^aldo;
1450 )cpp",
1453 for (const auto *Case : Tests) {
1454 SCOPED_TRACE(Case);
1455 auto T = Annotations(Case);
1456 auto AST = TestTU::withCode(T.code()).build();
1457 EXPECT_THAT(locateSymbolAt(AST, T.point()),
1458 UnorderedPointwise(declRange(), T.ranges()));
1462 TEST(LocateSymbol, RelPathsInCompileCommand) {
1463 // The source is in "/clangd-test/src".
1464 // We build in "/clangd-test/build".
1466 Annotations SourceAnnotations(R"cpp(
1467 #include "header_in_preamble.h"
1468 int [[foo]];
1469 #include "header_not_in_preamble.h"
1470 int baz = f$p1^oo + bar_pre$p2^amble + bar_not_pre$p3^amble;
1471 )cpp");
1473 Annotations HeaderInPreambleAnnotations(R"cpp(
1474 int [[bar_preamble]];
1475 )cpp");
1477 Annotations HeaderNotInPreambleAnnotations(R"cpp(
1478 int [[bar_not_preamble]];
1479 )cpp");
1481 // Make the compilation paths appear as ../src/foo.cpp in the compile
1482 // commands.
1483 SmallString<32> RelPathPrefix("..");
1484 llvm::sys::path::append(RelPathPrefix, "src");
1485 std::string BuildDir = testPath("build");
1486 MockCompilationDatabase CDB(BuildDir, RelPathPrefix);
1488 MockFS FS;
1489 ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
1491 // Fill the filesystem.
1492 auto FooCpp = testPath("src/foo.cpp");
1493 FS.Files[FooCpp] = "";
1494 auto HeaderInPreambleH = testPath("src/header_in_preamble.h");
1495 FS.Files[HeaderInPreambleH] = std::string(HeaderInPreambleAnnotations.code());
1496 auto HeaderNotInPreambleH = testPath("src/header_not_in_preamble.h");
1497 FS.Files[HeaderNotInPreambleH] =
1498 std::string(HeaderNotInPreambleAnnotations.code());
1500 runAddDocument(Server, FooCpp, SourceAnnotations.code());
1502 // Go to a definition in main source file.
1503 auto Locations =
1504 runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("p1"));
1505 EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error";
1506 EXPECT_THAT(*Locations, ElementsAre(sym("foo", SourceAnnotations.range(),
1507 SourceAnnotations.range())));
1509 // Go to a definition in header_in_preamble.h.
1510 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("p2"));
1511 EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error";
1512 EXPECT_THAT(
1513 *Locations,
1514 ElementsAre(sym("bar_preamble", HeaderInPreambleAnnotations.range(),
1515 HeaderInPreambleAnnotations.range())));
1517 // Go to a definition in header_not_in_preamble.h.
1518 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("p3"));
1519 EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error";
1520 EXPECT_THAT(*Locations,
1521 ElementsAre(sym("bar_not_preamble",
1522 HeaderNotInPreambleAnnotations.range(),
1523 HeaderNotInPreambleAnnotations.range())));
1526 TEST(GoToInclude, All) {
1527 MockFS FS;
1528 MockCompilationDatabase CDB;
1529 ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
1531 auto FooCpp = testPath("foo.cpp");
1532 const char *SourceContents = R"cpp(
1533 #include ^"$2^foo.h$3^"
1534 #include "$4^invalid.h"
1535 int b = a;
1536 // test
1537 int foo;
1538 #in$5^clude "$6^foo.h"$7^
1539 )cpp";
1540 Annotations SourceAnnotations(SourceContents);
1541 FS.Files[FooCpp] = std::string(SourceAnnotations.code());
1542 auto FooH = testPath("foo.h");
1544 const char *HeaderContents = R"cpp([[]]#pragma once
1545 int a;
1546 )cpp";
1547 Annotations HeaderAnnotations(HeaderContents);
1548 FS.Files[FooH] = std::string(HeaderAnnotations.code());
1550 runAddDocument(Server, FooH, HeaderAnnotations.code());
1551 runAddDocument(Server, FooCpp, SourceAnnotations.code());
1553 // Test include in preamble.
1554 auto Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point());
1555 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1556 EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(),
1557 HeaderAnnotations.range())));
1559 // Test include in preamble, last char.
1560 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("2"));
1561 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1562 EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(),
1563 HeaderAnnotations.range())));
1565 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("3"));
1566 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1567 EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(),
1568 HeaderAnnotations.range())));
1570 // Test include outside of preamble.
1571 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("6"));
1572 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1573 EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(),
1574 HeaderAnnotations.range())));
1576 // Test a few positions that do not result in Locations.
1577 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("4"));
1578 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1579 EXPECT_THAT(*Locations, IsEmpty());
1581 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("5"));
1582 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1583 EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(),
1584 HeaderAnnotations.range())));
1586 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("7"));
1587 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1588 EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(),
1589 HeaderAnnotations.range())));
1591 // Objective C #import directive.
1592 Annotations ObjC(R"objc(
1593 #import "^foo.h"
1594 )objc");
1595 auto FooM = testPath("foo.m");
1596 FS.Files[FooM] = std::string(ObjC.code());
1598 runAddDocument(Server, FooM, ObjC.code());
1599 Locations = runLocateSymbolAt(Server, FooM, ObjC.point());
1600 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1601 EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(),
1602 HeaderAnnotations.range())));
1605 TEST(LocateSymbol, WithPreamble) {
1606 // Test stragety: AST should always use the latest preamble instead of last
1607 // good preamble.
1608 MockFS FS;
1609 MockCompilationDatabase CDB;
1610 ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
1612 auto FooCpp = testPath("foo.cpp");
1613 // The trigger locations must be the same.
1614 Annotations FooWithHeader(R"cpp(#include "fo^o.h")cpp");
1615 Annotations FooWithoutHeader(R"cpp(double [[fo^o]]();)cpp");
1617 FS.Files[FooCpp] = std::string(FooWithHeader.code());
1619 auto FooH = testPath("foo.h");
1620 Annotations FooHeader(R"cpp([[]])cpp");
1621 FS.Files[FooH] = std::string(FooHeader.code());
1623 runAddDocument(Server, FooCpp, FooWithHeader.code());
1624 // LocateSymbol goes to a #include file: the result comes from the preamble.
1625 EXPECT_THAT(
1626 cantFail(runLocateSymbolAt(Server, FooCpp, FooWithHeader.point())),
1627 ElementsAre(sym("foo.h", FooHeader.range(), FooHeader.range())));
1629 // Only preamble is built, and no AST is built in this request.
1630 Server.addDocument(FooCpp, FooWithoutHeader.code(), "null",
1631 WantDiagnostics::No);
1632 // We build AST here, and it should use the latest preamble rather than the
1633 // stale one.
1634 EXPECT_THAT(
1635 cantFail(runLocateSymbolAt(Server, FooCpp, FooWithoutHeader.point())),
1636 ElementsAre(sym("foo", FooWithoutHeader.range(), std::nullopt)));
1638 // Reset test environment.
1639 runAddDocument(Server, FooCpp, FooWithHeader.code());
1640 // Both preamble and AST are built in this request.
1641 Server.addDocument(FooCpp, FooWithoutHeader.code(), "null",
1642 WantDiagnostics::Yes);
1643 // Use the AST being built in above request.
1644 EXPECT_THAT(
1645 cantFail(runLocateSymbolAt(Server, FooCpp, FooWithoutHeader.point())),
1646 ElementsAre(sym("foo", FooWithoutHeader.range(), std::nullopt)));
1649 TEST(LocateSymbol, NearbyTokenSmoke) {
1650 auto T = Annotations(R"cpp(
1651 // prints e^rr and crashes
1652 void die(const char* [[err]]);
1653 )cpp");
1654 auto AST = TestTU::withCode(T.code()).build();
1655 // We don't pass an index, so can't hit index-based fallback.
1656 EXPECT_THAT(locateSymbolAt(AST, T.point()),
1657 ElementsAre(sym("err", T.range(), T.range())));
1660 TEST(LocateSymbol, NearbyIdentifier) {
1661 const char *Tests[] = {
1662 R"cpp(
1663 // regular identifiers (won't trigger)
1664 int hello;
1665 int y = he^llo;
1666 )cpp",
1667 R"cpp(
1668 // disabled preprocessor sections
1669 int [[hello]];
1670 #if 0
1671 int y = ^hello;
1672 #endif
1673 )cpp",
1674 R"cpp(
1675 // comments
1676 // he^llo, world
1677 int [[hello]];
1678 )cpp",
1679 R"cpp(
1680 // not triggered by string literals
1681 int hello;
1682 const char* greeting = "h^ello, world";
1683 )cpp",
1685 R"cpp(
1686 // can refer to macro invocations
1687 #define INT int
1688 [[INT]] x;
1689 // I^NT
1690 )cpp",
1692 R"cpp(
1693 // can refer to macro invocations (even if they expand to nothing)
1694 #define EMPTY
1695 [[EMPTY]] int x;
1696 // E^MPTY
1697 )cpp",
1699 R"cpp(
1700 // prefer nearest occurrence, backwards is worse than forwards
1701 int hello;
1702 int x = hello;
1703 // h^ello
1704 int y = [[hello]];
1705 int z = hello;
1706 )cpp",
1708 R"cpp(
1709 // short identifiers find near results
1710 int [[hi]];
1711 // h^i
1712 )cpp",
1713 R"cpp(
1714 // short identifiers don't find far results
1715 int hi;
1719 // h^i
1724 int x = hi;
1725 )cpp",
1726 R"cpp(
1727 // prefer nearest occurrence even if several matched tokens
1728 // have the same value of `floor(log2(<token line> - <word line>))`.
1729 int hello;
1730 int x = hello, y = hello;
1731 int z = [[hello]];
1732 // h^ello
1733 )cpp"};
1734 for (const char *Test : Tests) {
1735 Annotations T(Test);
1736 auto AST = TestTU::withCode(T.code()).build();
1737 const auto &SM = AST.getSourceManager();
1738 std::optional<Range> Nearby;
1739 auto Word =
1740 SpelledWord::touching(cantFail(sourceLocationInMainFile(SM, T.point())),
1741 AST.getTokens(), AST.getLangOpts());
1742 if (!Word) {
1743 ADD_FAILURE() << "No word at point! " << Test;
1744 continue;
1746 if (const auto *Tok = findNearbyIdentifier(*Word, AST.getTokens()))
1747 Nearby = halfOpenToRange(SM, CharSourceRange::getCharRange(
1748 Tok->location(), Tok->endLocation()));
1749 if (T.ranges().empty())
1750 EXPECT_THAT(Nearby, Eq(std::nullopt)) << Test;
1751 else
1752 EXPECT_EQ(Nearby, T.range()) << Test;
1756 TEST(FindImplementations, Inheritance) {
1757 llvm::StringRef Test = R"cpp(
1758 struct $0^Base {
1759 virtual void F$1^oo();
1760 void C$4^oncrete();
1762 struct $0[[Child1]] : Base {
1763 void $1[[Fo$3^o]]() override;
1764 virtual void B$2^ar();
1765 void Concrete(); // No implementations for concrete methods.
1767 struct Child2 : Child1 {
1768 void $3[[Foo]]() override;
1769 void $2[[Bar]]() override;
1771 void FromReference() {
1772 $0^Base* B;
1773 B->Fo$1^o();
1774 B->C$4^oncrete();
1775 &Base::Fo$1^o;
1776 Child1 * C1;
1777 C1->B$2^ar();
1778 C1->Fo$3^o();
1780 // CRTP should work.
1781 template<typename T>
1782 struct $5^TemplateBase {};
1783 struct $5[[Child3]] : public TemplateBase<Child3> {};
1785 // Local classes.
1786 void LocationFunction() {
1787 struct $0[[LocalClass1]] : Base {
1788 void $1[[Foo]]() override;
1790 struct $6^LocalBase {
1791 virtual void $7^Bar();
1793 struct $6[[LocalClass2]]: LocalBase {
1794 void $7[[Bar]]() override;
1797 )cpp";
1799 Annotations Code(Test);
1800 auto TU = TestTU::withCode(Code.code());
1801 auto AST = TU.build();
1802 auto Index = TU.index();
1803 for (StringRef Label : {"0", "1", "2", "3", "4", "5", "6", "7"}) {
1804 for (const auto &Point : Code.points(Label)) {
1805 EXPECT_THAT(findImplementations(AST, Point, Index.get()),
1806 UnorderedPointwise(declRange(), Code.ranges(Label)))
1807 << Code.code() << " at " << Point << " for Label " << Label;
1812 TEST(FindImplementations, CaptureDefinition) {
1813 llvm::StringRef Test = R"cpp(
1814 struct Base {
1815 virtual void F^oo();
1817 struct Child1 : Base {
1818 void $Decl[[Foo]]() override;
1820 struct Child2 : Base {
1821 void $Child2[[Foo]]() override;
1823 void Child1::$Def[[Foo]]() { /* Definition */ }
1824 )cpp";
1825 Annotations Code(Test);
1826 auto TU = TestTU::withCode(Code.code());
1827 auto AST = TU.build();
1828 EXPECT_THAT(
1829 findImplementations(AST, Code.point(), TU.index().get()),
1830 UnorderedElementsAre(sym("Foo", Code.range("Decl"), Code.range("Def")),
1831 sym("Foo", Code.range("Child2"), std::nullopt)))
1832 << Test;
1835 TEST(FindType, All) {
1836 Annotations HeaderA(R"cpp(
1837 struct $Target[[Target]] { operator int() const; };
1838 struct Aggregate { Target a, b; };
1839 Target t;
1840 Target make();
1842 template <typename T> struct $smart_ptr[[smart_ptr]] {
1843 T& operator*();
1844 T* operator->();
1845 T* get();
1847 )cpp");
1848 auto TU = TestTU::withHeaderCode(HeaderA.code());
1849 for (const llvm::StringRef Case : {
1850 "str^uct Target;",
1851 "T^arget x;",
1852 "Target ^x;",
1853 "a^uto x = Target{};",
1854 "namespace m { Target tgt; } auto x = m^::tgt;",
1855 "Target funcCall(); auto x = ^funcCall();",
1856 "Aggregate a = { {}, ^{} };",
1857 "Aggregate a = { ^.a=t, };",
1858 "struct X { Target a; X() : ^a() {} };",
1859 "^using T = Target; ^T foo();",
1860 "^template <int> Target foo();",
1861 "void x() { try {} ^catch(Target e) {} }",
1862 "void x() { ^throw t; }",
1863 "int x() { ^return t; }",
1864 "void x() { ^switch(t) {} }",
1865 "void x() { ^delete (Target*)nullptr; }",
1866 "Target& ^tref = t;",
1867 "void x() { ^if (t) {} }",
1868 "void x() { ^while (t) {} }",
1869 "void x() { ^do { } while (t); }",
1870 "void x() { ^make(); }",
1871 "void x(smart_ptr<Target> &t) { t.^get(); }",
1872 "^auto x = []() { return t; };",
1873 "Target* ^tptr = &t;",
1874 "Target ^tarray[3];",
1875 }) {
1876 Annotations A(Case);
1877 TU.Code = A.code().str();
1878 ParsedAST AST = TU.build();
1880 ASSERT_GT(A.points().size(), 0u) << Case;
1881 for (auto Pos : A.points())
1882 EXPECT_THAT(findType(AST, Pos),
1883 ElementsAre(
1884 sym("Target", HeaderA.range("Target"), HeaderA.range("Target"))))
1885 << Case;
1888 for (const llvm::StringRef Case : {
1889 "smart_ptr<Target> ^tsmart;",
1890 }) {
1891 Annotations A(Case);
1892 TU.Code = A.code().str();
1893 ParsedAST AST = TU.build();
1895 EXPECT_THAT(findType(AST, A.point()),
1896 UnorderedElementsAre(
1897 sym("Target", HeaderA.range("Target"), HeaderA.range("Target")),
1898 sym("smart_ptr", HeaderA.range("smart_ptr"), HeaderA.range("smart_ptr"))
1900 << Case;
1904 void checkFindRefs(llvm::StringRef Test, bool UseIndex = false) {
1905 Annotations T(Test);
1906 auto TU = TestTU::withCode(T.code());
1907 TU.ExtraArgs.push_back("-std=c++20");
1909 auto AST = TU.build();
1910 std::vector<Matcher<ReferencesResult::Reference>> ExpectedLocations;
1911 for (const auto &[R, Context] : T.rangesWithPayload())
1912 ExpectedLocations.push_back(
1913 AllOf(rangeIs(R), containerIs(Context), attrsAre(0u)));
1914 // $def is actually shorthand for both definition and declaration.
1915 // If we have cases that are definition-only, we should change this.
1916 for (const auto &[R, Context] : T.rangesWithPayload("def"))
1917 ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(Context),
1918 attrsAre(ReferencesResult::Definition |
1919 ReferencesResult::Declaration)));
1920 for (const auto &[R, Context] : T.rangesWithPayload("decl"))
1921 ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(Context),
1922 attrsAre(ReferencesResult::Declaration)));
1923 for (const auto &[R, Context] : T.rangesWithPayload("overridedecl"))
1924 ExpectedLocations.push_back(AllOf(
1925 rangeIs(R), containerIs(Context),
1926 attrsAre(ReferencesResult::Declaration | ReferencesResult::Override)));
1927 for (const auto &[R, Context] : T.rangesWithPayload("overridedef"))
1928 ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(Context),
1929 attrsAre(ReferencesResult::Declaration |
1930 ReferencesResult::Definition |
1931 ReferencesResult::Override)));
1932 for (const auto &P : T.points()) {
1933 EXPECT_THAT(findReferences(AST, P, 0, UseIndex ? TU.index().get() : nullptr,
1934 /*AddContext*/ true)
1935 .References,
1936 UnorderedElementsAreArray(ExpectedLocations))
1937 << "Failed for Refs at " << P << "\n"
1938 << Test;
1942 TEST(FindReferences, WithinAST) {
1943 const char *Tests[] = {
1944 R"cpp(// Local variable
1945 int main() {
1946 int $def(main)[[foo]];
1947 $(main)[[^foo]] = 2;
1948 int test1 = $(main)[[foo]];
1950 )cpp",
1952 R"cpp(// Struct
1953 namespace ns1 {
1954 struct $def(ns1)[[Foo]] {};
1955 } // namespace ns1
1956 int main() {
1957 ns1::$(main)[[Fo^o]]* Params;
1959 )cpp",
1961 R"cpp(// Forward declaration
1962 class $decl[[Foo]];
1963 class $def[[Foo]] {};
1964 int main() {
1965 $(main)[[Fo^o]] foo;
1967 )cpp",
1969 R"cpp(// Function
1970 int $def[[foo]](int) {}
1971 int main() {
1972 auto *X = &$(main)[[^foo]];
1973 $(main)[[foo]](42);
1975 )cpp",
1977 R"cpp(// Field
1978 struct Foo {
1979 int $def(Foo)[[foo]];
1980 Foo() : $(Foo::Foo)[[foo]](0) {}
1982 int main() {
1983 Foo f;
1984 f.$(main)[[f^oo]] = 1;
1986 )cpp",
1988 R"cpp(// Method call
1989 struct Foo { int $decl(Foo)[[foo]](); };
1990 int Foo::$def(Foo)[[foo]]() {}
1991 int main() {
1992 Foo f;
1993 f.$(main)[[^foo]]();
1995 )cpp",
1997 R"cpp(// Constructor
1998 struct Foo {
1999 $decl(Foo)[[F^oo]](int);
2001 void foo() {
2002 Foo f = $(foo)[[Foo]](42);
2004 )cpp",
2006 R"cpp(// Typedef
2007 typedef int $def[[Foo]];
2008 int main() {
2009 $(main)[[^Foo]] bar;
2011 )cpp",
2013 R"cpp(// Namespace
2014 namespace $decl[[ns]] { // FIXME: def?
2015 struct Foo {};
2016 } // namespace ns
2017 int main() { $(main)[[^ns]]::Foo foo; }
2018 )cpp",
2020 R"cpp(// Macros
2021 #define TYPE(X) X
2022 #define FOO Foo
2023 #define CAT(X, Y) X##Y
2024 class $def[[Fo^o]] {};
2025 void test() {
2026 TYPE($(test)[[Foo]]) foo;
2027 $(test)[[FOO]] foo2;
2028 TYPE(TYPE($(test)[[Foo]])) foo3;
2029 $(test)[[CAT]](Fo, o) foo4;
2031 )cpp",
2033 R"cpp(// Macros
2034 #define $def[[MA^CRO]](X) (X+1)
2035 void test() {
2036 int x = $[[MACRO]]($[[MACRO]](1));
2038 )cpp",
2040 R"cpp(// Macro outside preamble
2041 int breakPreamble;
2042 #define $def[[MA^CRO]](X) (X+1)
2043 void test() {
2044 int x = $[[MACRO]]($[[MACRO]](1));
2046 )cpp",
2048 R"cpp(
2049 int $def[[v^ar]] = 0;
2050 void foo(int s = $(foo)[[var]]);
2051 )cpp",
2053 R"cpp(
2054 template <typename T>
2055 class $def[[Fo^o]] {};
2056 void func($(func)[[Foo]]<int>);
2057 )cpp",
2059 R"cpp(
2060 template <typename T>
2061 class $def[[Foo]] {};
2062 void func($(func)[[Fo^o]]<int>);
2063 )cpp",
2064 R"cpp(// Not touching any identifiers.
2065 struct Foo {
2066 $def(Foo)[[~]]Foo() {};
2068 void foo() {
2069 Foo f;
2070 f.$(foo)[[^~]]Foo();
2072 )cpp",
2073 R"cpp(// Lambda capture initializer
2074 void foo() {
2075 int $def(foo)[[w^aldo]] = 42;
2076 auto lambda = [x = $(foo)[[waldo]]](){};
2078 )cpp",
2079 R"cpp(// Renaming alias
2080 template <typename> class Vector {};
2081 using $def[[^X]] = Vector<int>;
2082 $(x1)[[X]] x1;
2083 Vector<int> x2;
2084 Vector<double> y;
2085 )cpp",
2086 R"cpp(// Dependent code
2087 template <typename T> void $decl[[foo]](T t);
2088 template <typename T> void bar(T t) { $(bar)[[foo]](t); } // foo in bar is uninstantiated.
2089 void baz(int x) { $(baz)[[f^oo]](x); }
2090 )cpp",
2091 R"cpp(
2092 namespace ns {
2093 struct S{};
2094 void $decl(ns)[[foo]](S s);
2095 } // namespace ns
2096 template <typename T> void foo(T t);
2097 // FIXME: Maybe report this foo as a ref to ns::foo (because of ADL)
2098 // when bar<ns::S> is instantiated?
2099 template <typename T> void bar(T t) { foo(t); }
2100 void baz(int x) {
2101 ns::S s;
2102 bar<ns::S>(s);
2103 $(baz)[[f^oo]](s);
2105 )cpp",
2106 R"cpp(// unresolved member expression
2107 struct Foo {
2108 template <typename T> void $decl(Foo)[[b^ar]](T t);
2110 template <typename T> void test(Foo F, T t) {
2111 F.$(test)[[bar]](t);
2113 )cpp",
2115 // Enum base
2116 R"cpp(
2117 typedef int $def[[MyTypeD^ef]];
2118 enum MyEnum : $(MyEnum)[[MyTy^peDef]] { };
2119 )cpp",
2120 R"cpp(
2121 typedef int $def[[MyType^Def]];
2122 enum MyEnum : $(MyEnum)[[MyTypeD^ef]];
2123 )cpp",
2124 R"cpp(
2125 using $def[[MyTypeD^ef]] = int;
2126 enum MyEnum : $(MyEnum)[[MyTy^peDef]] { };
2127 )cpp",
2129 for (const char *Test : Tests)
2130 checkFindRefs(Test);
2133 TEST(FindReferences, ConceptsWithinAST) {
2134 constexpr llvm::StringLiteral Code = R"cpp(
2135 template <class T>
2136 concept $def[[IsSmal^l]] = sizeof(T) <= 8;
2138 template <class T>
2139 concept IsSmallPtr = requires(T x) {
2140 { *x } -> $(IsSmallPtr)[[IsSmal^l]];
2143 $(i)[[IsSmall]] auto i = 'c';
2144 template<$(foo)[[IsSmal^l]] U> void foo();
2145 template<class U> void bar() requires $(bar)[[IsSmal^l]]<U>;
2146 template<class U> requires $(baz)[[IsSmal^l]]<U> void baz();
2147 static_assert([[IsSma^ll]]<char>);
2148 )cpp";
2149 checkFindRefs(Code);
2152 TEST(FindReferences, ConceptReq) {
2153 constexpr llvm::StringLiteral Code = R"cpp(
2154 template <class T>
2155 concept $def[[IsSmal^l]] = sizeof(T) <= 8;
2157 template <class T>
2158 concept IsSmallPtr = requires(T x) {
2159 { *x } -> $(IsSmallPtr)[[IsSmal^l]];
2161 )cpp";
2162 checkFindRefs(Code);
2165 TEST(FindReferences, RequiresExprParameters) {
2166 constexpr llvm::StringLiteral Code = R"cpp(
2167 template <class T>
2168 concept IsSmall = sizeof(T) <= 8;
2170 template <class T>
2171 concept IsSmallPtr = requires(T $def[[^x]]) {
2172 { *$(IsSmallPtr)[[^x]] } -> IsSmall;
2174 )cpp";
2175 checkFindRefs(Code);
2178 TEST(FindReferences, IncludeOverrides) {
2179 llvm::StringRef Test =
2180 R"cpp(
2181 class Base {
2182 public:
2183 virtu^al void $decl(Base)[[f^unc]]() ^= ^0;
2185 class Derived : public Base {
2186 public:
2187 void $overridedecl(Derived::func)[[func]]() override;
2189 void Derived::$overridedef[[func]]() {}
2190 class Derived2 : public Base {
2191 void $overridedef(Derived2::func)[[func]]() override {}
2193 void test(Derived* D, Base* B) {
2194 D->func(); // No references to the overrides.
2195 B->$(test)[[func]]();
2196 })cpp";
2197 checkFindRefs(Test, /*UseIndex=*/true);
2200 TEST(FindReferences, RefsToBaseMethod) {
2201 llvm::StringRef Test =
2202 R"cpp(
2203 class BaseBase {
2204 public:
2205 virtual void $(BaseBase)[[func]]();
2207 class Base : public BaseBase {
2208 public:
2209 void $(Base)[[func]]() override;
2211 class Derived : public Base {
2212 public:
2213 void $decl(Derived)[[fu^nc]]() over^ride;
2215 void test(BaseBase* BB, Base* B, Derived* D) {
2216 // refs to overridden methods in complete type hierarchy are reported.
2217 BB->$(test)[[func]]();
2218 B->$(test)[[func]]();
2219 D->$(test)[[fu^nc]]();
2220 })cpp";
2221 checkFindRefs(Test, /*UseIndex=*/true);
2224 TEST(FindReferences, MainFileReferencesOnly) {
2225 llvm::StringRef Test =
2226 R"cpp(
2227 void test() {
2228 int [[fo^o]] = 1;
2229 // refs not from main file should not be included.
2230 #include "foo.inc"
2231 })cpp";
2233 Annotations Code(Test);
2234 auto TU = TestTU::withCode(Code.code());
2235 TU.AdditionalFiles["foo.inc"] = R"cpp(
2236 foo = 3;
2237 )cpp";
2238 auto AST = TU.build();
2240 std::vector<Matcher<ReferencesResult::Reference>> ExpectedLocations;
2241 for (const auto &R : Code.ranges())
2242 ExpectedLocations.push_back(rangeIs(R));
2243 EXPECT_THAT(findReferences(AST, Code.point(), 0).References,
2244 ElementsAreArray(ExpectedLocations))
2245 << Test;
2248 TEST(FindReferences, ExplicitSymbols) {
2249 const char *Tests[] = {
2250 R"cpp(
2251 struct Foo { Foo* $decl(Foo)[[self]]() const; };
2252 void f() {
2253 Foo foo;
2254 if (Foo* T = foo.$(f)[[^self]]()) {} // Foo member call expr.
2256 )cpp",
2258 R"cpp(
2259 struct Foo { Foo(int); };
2260 Foo f() {
2261 int $def(f)[[b]];
2262 return $(f)[[^b]]; // Foo constructor expr.
2264 )cpp",
2266 R"cpp(
2267 struct Foo {};
2268 void g(Foo);
2269 Foo $decl[[f]]();
2270 void call() {
2271 g($(call)[[^f]]()); // Foo constructor expr.
2273 )cpp",
2275 R"cpp(
2276 void $decl[[foo]](int);
2277 void $decl[[foo]](double);
2279 namespace ns {
2280 using ::$decl(ns)[[fo^o]];
2282 )cpp",
2284 R"cpp(
2285 struct X {
2286 operator bool();
2289 int test() {
2290 X $def(test)[[a]];
2291 $(test)[[a]].operator bool();
2292 if ($(test)[[a^]]) {} // ignore implicit conversion-operator AST node
2294 )cpp",
2296 for (const char *Test : Tests)
2297 checkFindRefs(Test);
2300 TEST(FindReferences, UsedSymbolsFromInclude) {
2301 const char *Tests[] = {
2302 R"cpp([[#include ^"bar.h"]]
2303 #include <vector>
2304 int fstBar = [[bar1]]();
2305 int sndBar = [[bar2]]();
2306 [[Bar]] bar;
2307 int macroBar = [[BAR]];
2308 std::vector<int> vec;
2309 )cpp",
2311 R"cpp([[#in^clude <vector>]]
2312 std::[[vector]]<int> vec;
2313 )cpp"};
2314 for (const char *Test : Tests) {
2315 Annotations T(Test);
2316 auto TU = TestTU::withCode(T.code());
2317 TU.ExtraArgs.push_back("-std=c++20");
2318 TU.AdditionalFiles["bar.h"] = guard(R"cpp(
2319 #define BAR 5
2320 int bar1();
2321 int bar2();
2322 class Bar {};
2323 )cpp");
2324 TU.AdditionalFiles["system/vector"] = guard(R"cpp(
2325 namespace std {
2326 template<typename>
2327 class vector{};
2329 )cpp");
2330 TU.ExtraArgs.push_back("-isystem" + testPath("system"));
2332 auto AST = TU.build();
2333 std::vector<Matcher<ReferencesResult::Reference>> ExpectedLocations;
2334 for (const auto &R : T.ranges())
2335 ExpectedLocations.push_back(AllOf(rangeIs(R), attrsAre(0u)));
2336 for (const auto &P : T.points())
2337 EXPECT_THAT(findReferences(AST, P, 0).References,
2338 UnorderedElementsAreArray(ExpectedLocations))
2339 << "Failed for Refs at " << P << "\n"
2340 << Test;
2344 TEST(FindReferences, NeedsIndexForSymbols) {
2345 const char *Header = "int foo();";
2346 Annotations Main("int main() { [[f^oo]](); }");
2347 TestTU TU;
2348 TU.Code = std::string(Main.code());
2349 TU.HeaderCode = Header;
2350 auto AST = TU.build();
2352 // References in main file are returned without index.
2353 EXPECT_THAT(
2354 findReferences(AST, Main.point(), 0, /*Index=*/nullptr).References,
2355 ElementsAre(rangeIs(Main.range())));
2356 Annotations IndexedMain(R"cpp(
2357 int $decl[[foo]]() { return 42; }
2358 void bar() { $bar(bar)[[foo]](); }
2359 struct S { void bar() { $S(S::bar)[[foo]](); } };
2360 namespace N { void bar() { $N(N::bar)[[foo]](); } }
2361 )cpp");
2363 // References from indexed files are included.
2364 TestTU IndexedTU;
2365 IndexedTU.Code = std::string(IndexedMain.code());
2366 IndexedTU.Filename = "Indexed.cpp";
2367 IndexedTU.HeaderCode = Header;
2368 EXPECT_THAT(
2369 findReferences(AST, Main.point(), 0, IndexedTU.index().get(),
2370 /*AddContext*/ true)
2371 .References,
2372 ElementsAre(
2373 rangeIs(Main.range()),
2374 AllOf(rangeIs(IndexedMain.range("decl")),
2375 attrsAre(ReferencesResult::Declaration |
2376 ReferencesResult::Definition)),
2377 AllOf(rangeIs(IndexedMain.range("bar")), containerIs("bar")),
2378 AllOf(rangeIs(IndexedMain.range("S")), containerIs("S::bar")),
2379 AllOf(rangeIs(IndexedMain.range("N")), containerIs("N::bar"))));
2380 auto LimitRefs =
2381 findReferences(AST, Main.point(), /*Limit*/ 1, IndexedTU.index().get());
2382 EXPECT_EQ(1u, LimitRefs.References.size());
2383 EXPECT_TRUE(LimitRefs.HasMore);
2385 // Avoid indexed results for the main file. Use AST for the mainfile.
2386 TU.Code = ("\n\n" + Main.code()).str();
2387 EXPECT_THAT(findReferences(AST, Main.point(), 0, TU.index().get()).References,
2388 ElementsAre(rangeIs(Main.range())));
2391 TEST(FindReferences, NeedsIndexForMacro) {
2392 const char *Header = "#define MACRO(X) (X+1)";
2393 Annotations Main(R"cpp(
2394 int main() {
2395 int a = [[MA^CRO]](1);
2397 )cpp");
2398 TestTU TU;
2399 TU.Code = std::string(Main.code());
2400 TU.HeaderCode = Header;
2401 auto AST = TU.build();
2403 // References in main file are returned without index.
2404 EXPECT_THAT(
2405 findReferences(AST, Main.point(), 0, /*Index=*/nullptr).References,
2406 ElementsAre(rangeIs(Main.range())));
2408 Annotations IndexedMain(R"cpp(
2409 int indexed_main() {
2410 int a = [[MACRO]](1);
2412 )cpp");
2414 // References from indexed files are included.
2415 TestTU IndexedTU;
2416 IndexedTU.Code = std::string(IndexedMain.code());
2417 IndexedTU.Filename = "Indexed.cpp";
2418 IndexedTU.HeaderCode = Header;
2419 EXPECT_THAT(
2420 findReferences(AST, Main.point(), 0, IndexedTU.index().get()).References,
2421 ElementsAre(rangeIs(Main.range()), rangeIs(IndexedMain.range())));
2422 auto LimitRefs =
2423 findReferences(AST, Main.point(), /*Limit*/ 1, IndexedTU.index().get());
2424 EXPECT_EQ(1u, LimitRefs.References.size());
2425 EXPECT_TRUE(LimitRefs.HasMore);
2428 TEST(FindReferences, NoQueryForLocalSymbols) {
2429 struct RecordingIndex : public MemIndex {
2430 mutable std::optional<llvm::DenseSet<SymbolID>> RefIDs;
2431 bool refs(const RefsRequest &Req,
2432 llvm::function_ref<void(const Ref &)>) const override {
2433 RefIDs = Req.IDs;
2434 return false;
2438 struct Test {
2439 StringRef AnnotatedCode;
2440 bool WantQuery;
2441 } Tests[] = {
2442 {"int ^x;", true},
2443 // For now we don't assume header structure which would allow skipping.
2444 {"namespace { int ^x; }", true},
2445 {"static int ^x;", true},
2446 // Anything in a function certainly can't be referenced though.
2447 {"void foo() { int ^x; }", false},
2448 {"void foo() { struct ^x{}; }", false},
2449 {"auto lambda = []{ int ^x; };", false},
2451 for (Test T : Tests) {
2452 Annotations File(T.AnnotatedCode);
2453 RecordingIndex Rec;
2454 auto AST = TestTU::withCode(File.code()).build();
2455 findReferences(AST, File.point(), 0, &Rec);
2456 if (T.WantQuery)
2457 EXPECT_NE(Rec.RefIDs, std::nullopt) << T.AnnotatedCode;
2458 else
2459 EXPECT_EQ(Rec.RefIDs, std::nullopt) << T.AnnotatedCode;
2463 TEST(GetNonLocalDeclRefs, All) {
2464 struct Case {
2465 llvm::StringRef AnnotatedCode;
2466 std::vector<std::string> ExpectedDecls;
2467 } Cases[] = {
2469 // VarDecl and ParamVarDecl
2470 R"cpp(
2471 void bar();
2472 void ^foo(int baz) {
2473 int x = 10;
2474 bar();
2475 })cpp",
2476 {"bar"},
2479 // Method from class
2480 R"cpp(
2481 class Foo { public: void foo(); };
2482 class Bar {
2483 void foo();
2484 void bar();
2486 void Bar::^foo() {
2487 Foo f;
2488 bar();
2489 f.foo();
2490 })cpp",
2491 {"Bar", "Bar::bar", "Foo", "Foo::foo"},
2494 // Local types
2495 R"cpp(
2496 void ^foo() {
2497 class Foo { public: void foo() {} };
2498 class Bar { public: void bar() {} };
2499 Foo f;
2500 Bar b;
2501 b.bar();
2502 f.foo();
2503 })cpp",
2507 // Template params
2508 R"cpp(
2509 template <typename T, template<typename> class Q>
2510 void ^foo() {
2511 T x;
2512 Q<T> y;
2513 })cpp",
2517 for (const Case &C : Cases) {
2518 Annotations File(C.AnnotatedCode);
2519 auto AST = TestTU::withCode(File.code()).build();
2520 SourceLocation SL = llvm::cantFail(
2521 sourceLocationInMainFile(AST.getSourceManager(), File.point()));
2523 const FunctionDecl *FD =
2524 llvm::dyn_cast<FunctionDecl>(&findDecl(AST, [SL](const NamedDecl &ND) {
2525 return ND.getLocation() == SL && llvm::isa<FunctionDecl>(ND);
2526 }));
2527 ASSERT_NE(FD, nullptr);
2529 auto NonLocalDeclRefs = getNonLocalDeclRefs(AST, FD);
2530 std::vector<std::string> Names;
2531 for (const Decl *D : NonLocalDeclRefs) {
2532 if (const auto *ND = llvm::dyn_cast<NamedDecl>(D))
2533 Names.push_back(ND->getQualifiedNameAsString());
2535 EXPECT_THAT(Names, UnorderedElementsAreArray(C.ExpectedDecls))
2536 << File.code();
2540 TEST(DocumentLinks, All) {
2541 Annotations MainCpp(R"cpp(
2542 #/*comments*/include /*comments*/ $foo[["foo.h"]] //more comments
2543 int end_of_preamble = 0;
2544 #include $bar[[<bar.h>]]
2545 )cpp");
2547 TestTU TU;
2548 TU.Code = std::string(MainCpp.code());
2549 TU.AdditionalFiles = {{"foo.h", ""}, {"bar.h", ""}};
2550 TU.ExtraArgs = {"-isystem."};
2551 auto AST = TU.build();
2553 EXPECT_THAT(
2554 clangd::getDocumentLinks(AST),
2555 ElementsAre(
2556 DocumentLink({MainCpp.range("foo"),
2557 URIForFile::canonicalize(testPath("foo.h"), "")}),
2558 DocumentLink({MainCpp.range("bar"),
2559 URIForFile::canonicalize(testPath("bar.h"), "")})));
2562 } // namespace
2563 } // namespace clangd
2564 } // namespace clang