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 "Compiler.h"
10 #include "Matchers.h"
11 #include "ParsedAST.h"
12 #include "Protocol.h"
13 #include "SourceCode.h"
14 #include "SyncAPI.h"
15 #include "TestFS.h"
16 #include "TestIndex.h"
17 #include "TestTU.h"
18 #include "XRefs.h"
19 #include "index/FileIndex.h"
20 #include "index/MemIndex.h"
21 #include "index/SymbolCollector.h"
22 #include "clang/AST/Decl.h"
23 #include "clang/Basic/SourceLocation.h"
24 #include "clang/Index/IndexingAction.h"
25 #include "llvm/ADT/None.h"
26 #include "llvm/ADT/StringRef.h"
27 #include "llvm/Support/Casting.h"
28 #include "llvm/Support/Error.h"
29 #include "llvm/Support/Path.h"
30 #include "llvm/Support/ScopedPrinter.h"
31 #include "gmock/gmock.h"
32 #include "gtest/gtest.h"
33 #include <string>
34 #include <vector>
35
36 namespace clang {
37 namespace clangd {
38 namespace {
39
40 using ::testing::AllOf;
41 using ::testing::ElementsAre;
42 using ::testing::Eq;
43 using ::testing::IsEmpty;
44 using ::testing::Matcher;
45 using ::testing::UnorderedElementsAre;
46 using ::testing::UnorderedElementsAreArray;
47 using ::testing::UnorderedPointwise;
48
49 MATCHER_P2(FileRange, File, Range, "") {
50 return Location{URIForFile::canonicalize(File, testRoot()), Range} == arg;
51 }
52 MATCHER(DeclRange, "") {
53 const LocatedSymbol &Sym = ::testing::get<0>(arg);
54 const Range &Range = ::testing::get<1>(arg);
55 return Sym.PreferredDeclaration.range == Range;
56 }
57
58 // Extracts ranges from an annotated example, and constructs a matcher for a
59 // highlight set. Ranges should be named $read/$write as appropriate.
60 Matcher<const std::vector<DocumentHighlight> &>
HighlightsFrom(const Annotations & Test)61 HighlightsFrom(const Annotations &Test) {
62 std::vector<DocumentHighlight> Expected;
63 auto Add = [&](const Range &R, DocumentHighlightKind K) {
64 Expected.emplace_back();
65 Expected.back().range = R;
66 Expected.back().kind = K;
67 };
68 for (const auto &Range : Test.ranges())
69 Add(Range, DocumentHighlightKind::Text);
70 for (const auto &Range : Test.ranges("read"))
71 Add(Range, DocumentHighlightKind::Read);
72 for (const auto &Range : Test.ranges("write"))
73 Add(Range, DocumentHighlightKind::Write);
74 return UnorderedElementsAreArray(Expected);
75 }
76
TEST(HighlightsTest,All)77 TEST(HighlightsTest, All) {
78 const char *Tests[] = {
79 R"cpp(// Local variable
80 int main() {
81 int [[bonjour]];
82 $write[[^bonjour]] = 2;
83 int test1 = $read[[bonjour]];
84 }
85 )cpp",
86
87 R"cpp(// Struct
88 namespace ns1 {
89 struct [[MyClass]] {
90 static void foo([[MyClass]]*) {}
91 };
92 } // namespace ns1
93 int main() {
94 ns1::[[My^Class]]* Params;
95 }
96 )cpp",
97
98 R"cpp(// Function
99 int [[^foo]](int) {}
100 int main() {
101 [[foo]]([[foo]](42));
102 auto *X = &[[foo]];
103 }
104 )cpp",
105
106 R"cpp(// Function parameter in decl
107 void foo(int [[^bar]]);
108 )cpp",
109 R"cpp(// Not touching any identifiers.
110 struct Foo {
111 [[~]]Foo() {};
112 };
113 void foo() {
114 Foo f;
115 f.[[^~]]Foo();
116 }
117 )cpp",
118 R"cpp(// ObjC methods with split selectors.
119 @interface Foo
120 +(void) [[x]]:(int)a [[y]]:(int)b;
121 @end
122 @implementation Foo
123 +(void) [[x]]:(int)a [[y]]:(int)b {}
124 @end
125 void go() {
126 [Foo [[x]]:2 [[^y]]:4];
127 }
128 )cpp",
129 };
130 for (const char *Test : Tests) {
131 Annotations T(Test);
132 auto TU = TestTU::withCode(T.code());
133 TU.ExtraArgs.push_back("-xobjective-c++");
134 auto AST = TU.build();
135 EXPECT_THAT(findDocumentHighlights(AST, T.point()), HighlightsFrom(T))
136 << Test;
137 }
138 }
139
TEST(HighlightsTest,ControlFlow)140 TEST(HighlightsTest, ControlFlow) {
141 const char *Tests[] = {
142 R"cpp(
143 // Highlight same-function returns.
144 int fib(unsigned n) {
145 if (n <= 1) [[ret^urn]] 1;
146 [[return]] fib(n - 1) + fib(n - 2);
147
148 // Returns from other functions not highlighted.
149 auto Lambda = [] { return; };
150 class LocalClass { void x() { return; } };
151 }
152 )cpp",
153
154 R"cpp(
155 #define FAIL() return false
156 #define DO(x) { x; }
157 bool foo(int n) {
158 if (n < 0) [[FAIL]]();
159 DO([[re^turn]] true)
160 }
161 )cpp",
162
163 R"cpp(
164 // Highlight loop control flow
165 int magic() {
166 int counter = 0;
167 [[^for]] (char c : "fruit loops!") {
168 if (c == ' ') [[continue]];
169 counter += c;
170 if (c == '!') [[break]];
171 if (c == '?') [[return]] -1;
172 }
173 return counter;
174 }
175 )cpp",
176
177 R"cpp(
178 // Highlight loop and same-loop control flow
179 void nonsense() {
180 [[while]] (true) {
181 if (false) [[bre^ak]];
182 switch (1) break;
183 [[continue]];
184 }
185 }
186 )cpp",
187
188 R"cpp(
189 // Highlight switch for break (but not other breaks).
190 void describe(unsigned n) {
191 [[switch]](n) {
192 case 0:
193 break;
194 [[default]]:
195 [[^break]];
196 }
197 }
198 )cpp",
199
200 R"cpp(
201 // Highlight case and exits for switch-break (but not other cases).
202 void describe(unsigned n) {
203 [[switch]](n) {
204 case 0:
205 break;
206 [[case]] 1:
207 [[default]]:
208 [[return]];
209 [[^break]];
210 }
211 }
212 )cpp",
213
214 R"cpp(
215 // Highlight exits and switch for case
216 void describe(unsigned n) {
217 [[switch]](n) {
218 case 0:
219 break;
220 [[case]] 1:
221 [[d^efault]]:
222 [[return]];
223 [[break]];
224 }
225 }
226 )cpp",
227
228 R"cpp(
229 // Highlight nothing for switch.
230 void describe(unsigned n) {
231 s^witch(n) {
232 case 0:
233 break;
234 case 1:
235 default:
236 return;
237 break;
238 }
239 }
240 )cpp",
241
242 R"cpp(
243 // FIXME: match exception type against catch blocks
244 int catchy() {
245 try { // wrong: highlight try with matching catch
246 try { // correct: has no matching catch
247 [[thr^ow]] "oh no!";
248 } catch (int) { } // correct: catch doesn't match type
249 [[return]] -1; // correct: exits the matching catch
250 } catch (const char*) { } // wrong: highlight matching catch
251 [[return]] 42; // wrong: throw doesn't exit function
252 }
253 )cpp",
254
255 R"cpp(
256 // Loop highlights goto exiting the loop, but not jumping within it.
257 void jumpy() {
258 [[wh^ile]](1) {
259 up:
260 if (0) [[goto]] out;
261 goto up;
262 }
263 out: return;
264 }
265 )cpp",
266 };
267 for (const char *Test : Tests) {
268 Annotations T(Test);
269 auto TU = TestTU::withCode(T.code());
270 TU.ExtraArgs.push_back("-fexceptions"); // FIXME: stop testing on PS4.
271 auto AST = TU.build();
272 EXPECT_THAT(findDocumentHighlights(AST, T.point()), HighlightsFrom(T))
273 << Test;
274 }
275 }
276
277 MATCHER_P3(Sym, Name, Decl, DefOrNone, "") {
278 llvm::Optional<Range> Def = DefOrNone;
279 if (Name != arg.Name) {
280 *result_listener << "Name is " << arg.Name;
281 return false;
282 }
283 if (Decl != arg.PreferredDeclaration.range) {
284 *result_listener << "Declaration is "
285 << llvm::to_string(arg.PreferredDeclaration);
286 return false;
287 }
288 if (!Def && !arg.Definition)
289 return true;
290 if (Def && !arg.Definition) {
291 *result_listener << "Has no definition";
292 return false;
293 }
294 if (!Def && arg.Definition) {
295 *result_listener << "Definition is " << llvm::to_string(arg.Definition);
296 return false;
297 }
298 if (arg.Definition->range != *Def) {
299 *result_listener << "Definition is " << llvm::to_string(arg.Definition);
300 return false;
301 }
302 return true;
303 }
304
305 MATCHER_P(Sym, Name, "") { return arg.Name == Name; }
306
307 MATCHER_P(RangeIs, R, "") { return arg.Loc.range == R; }
308 MATCHER_P(AttrsAre, A, "") { return arg.Attributes == A; }
309 MATCHER_P(HasID, ID, "") { return arg.ID == ID; }
310
TEST(LocateSymbol,WithIndex)311 TEST(LocateSymbol, WithIndex) {
312 Annotations SymbolHeader(R"cpp(
313 class $forward[[Forward]];
314 class $foo[[Foo]] {};
315
316 void $f1[[f1]]();
317
318 inline void $f2[[f2]]() {}
319 )cpp");
320 Annotations SymbolCpp(R"cpp(
321 class $forward[[forward]] {};
322 void $f1[[f1]]() {}
323 )cpp");
324
325 TestTU TU;
326 TU.Code = std::string(SymbolCpp.code());
327 TU.HeaderCode = std::string(SymbolHeader.code());
328 auto Index = TU.index();
329 auto LocateWithIndex = [&Index](const Annotations &Main) {
330 auto AST = TestTU::withCode(Main.code()).build();
331 return clangd::locateSymbolAt(AST, Main.point(), Index.get());
332 };
333
334 Annotations Test(R"cpp(// only declaration in AST.
335 void [[f1]]();
336 int main() {
337 ^f1();
338 }
339 )cpp");
340 EXPECT_THAT(LocateWithIndex(Test),
341 ElementsAre(Sym("f1", Test.range(), SymbolCpp.range("f1"))));
342
343 Test = Annotations(R"cpp(// definition in AST.
344 void [[f1]]() {}
345 int main() {
346 ^f1();
347 }
348 )cpp");
349 EXPECT_THAT(LocateWithIndex(Test),
350 ElementsAre(Sym("f1", SymbolHeader.range("f1"), Test.range())));
351
352 Test = Annotations(R"cpp(// forward declaration in AST.
353 class [[Foo]];
354 F^oo* create();
355 )cpp");
356 EXPECT_THAT(LocateWithIndex(Test),
357 ElementsAre(Sym("Foo", Test.range(), SymbolHeader.range("foo"))));
358
359 Test = Annotations(R"cpp(// definition in AST.
360 class [[Forward]] {};
361 F^orward create();
362 )cpp");
363 EXPECT_THAT(
364 LocateWithIndex(Test),
365 ElementsAre(Sym("Forward", SymbolHeader.range("forward"), Test.range())));
366 }
367
TEST(LocateSymbol,FindOverrides)368 TEST(LocateSymbol, FindOverrides) {
369 auto Code = Annotations(R"cpp(
370 class Foo {
371 virtual void $1[[fo^o]]() = 0;
372 };
373 class Bar : public Foo {
374 void $2[[foo]]() override;
375 };
376 )cpp");
377 TestTU TU = TestTU::withCode(Code.code());
378 auto AST = TU.build();
379 EXPECT_THAT(locateSymbolAt(AST, Code.point(), TU.index().get()),
380 UnorderedElementsAre(Sym("foo", Code.range("1"), llvm::None),
381 Sym("foo", Code.range("2"), llvm::None)));
382 }
383
TEST(LocateSymbol,WithIndexPreferredLocation)384 TEST(LocateSymbol, WithIndexPreferredLocation) {
385 Annotations SymbolHeader(R"cpp(
386 class $p[[Proto]] {};
387 void $f[[func]]() {};
388 )cpp");
389 TestTU TU;
390 TU.HeaderCode = std::string(SymbolHeader.code());
391 TU.HeaderFilename = "x.proto"; // Prefer locations in codegen files.
392 auto Index = TU.index();
393
394 Annotations Test(R"cpp(// only declaration in AST.
395 // Shift to make range different.
396 class Proto;
397 void func() {}
398 P$p^roto* create() {
399 fu$f^nc();
400 return nullptr;
401 }
402 )cpp");
403
404 auto AST = TestTU::withCode(Test.code()).build();
405 {
406 auto Locs = clangd::locateSymbolAt(AST, Test.point("p"), Index.get());
407 auto CodeGenLoc = SymbolHeader.range("p");
408 EXPECT_THAT(Locs, ElementsAre(Sym("Proto", CodeGenLoc, CodeGenLoc)));
409 }
410 {
411 auto Locs = clangd::locateSymbolAt(AST, Test.point("f"), Index.get());
412 auto CodeGenLoc = SymbolHeader.range("f");
413 EXPECT_THAT(Locs, ElementsAre(Sym("func", CodeGenLoc, CodeGenLoc)));
414 }
415 }
416
TEST(LocateSymbol,All)417 TEST(LocateSymbol, All) {
418 // Ranges in tests:
419 // $decl is the declaration location (if absent, no symbol is located)
420 // $def is the definition location (if absent, symbol has no definition)
421 // unnamed range becomes both $decl and $def.
422 const char *Tests[] = {
423 R"cpp(
424 struct X {
425 union {
426 int [[a]];
427 float b;
428 };
429 };
430 int test(X &x) {
431 return x.^a;
432 }
433 )cpp",
434
435 R"cpp(// Local variable
436 int main() {
437 int [[bonjour]];
438 ^bonjour = 2;
439 int test1 = bonjour;
440 }
441 )cpp",
442
443 R"cpp(// Struct
444 namespace ns1 {
445 struct [[MyClass]] {};
446 } // namespace ns1
447 int main() {
448 ns1::My^Class* Params;
449 }
450 )cpp",
451
452 R"cpp(// Function definition via pointer
453 void [[foo]](int) {}
454 int main() {
455 auto *X = &^foo;
456 }
457 )cpp",
458
459 R"cpp(// Function declaration via call
460 int $decl[[foo]](int);
461 int main() {
462 return ^foo(42);
463 }
464 )cpp",
465
466 R"cpp(// Field
467 struct Foo { int [[x]]; };
468 int main() {
469 Foo bar;
470 (void)bar.^x;
471 }
472 )cpp",
473
474 R"cpp(// Field, member initializer
475 struct Foo {
476 int [[x]];
477 Foo() : ^x(0) {}
478 };
479 )cpp",
480
481 R"cpp(// Field, field designator
482 struct Foo { int [[x]]; };
483 int main() {
484 Foo bar = { .^x = 2 };
485 }
486 )cpp",
487
488 R"cpp(// Method call
489 struct Foo { int $decl[[x]](); };
490 int main() {
491 Foo bar;
492 bar.^x();
493 }
494 )cpp",
495
496 R"cpp(// Typedef
497 typedef int $decl[[Foo]];
498 int main() {
499 ^Foo bar;
500 }
501 )cpp",
502
503 R"cpp(// Template type parameter
504 template <typename [[T]]>
505 void foo() { ^T t; }
506 )cpp",
507
508 R"cpp(// Template template type parameter
509 template <template<typename> class [[T]]>
510 void foo() { ^T<int> t; }
511 )cpp",
512
513 R"cpp(// Namespace
514 namespace $decl[[ns]] {
515 struct Foo { static void bar(); };
516 } // namespace ns
517 int main() { ^ns::Foo::bar(); }
518 )cpp",
519
520 R"cpp(// Macro
521 class TTT { public: int a; };
522 #define [[FF]](S) if (int b = S.a) {}
523 void f() {
524 TTT t;
525 F^F(t);
526 }
527 )cpp",
528
529 R"cpp(// Macro argument
530 int [[i]];
531 #define ADDRESSOF(X) &X;
532 int *j = ADDRESSOF(^i);
533 )cpp",
534 R"cpp(// Macro argument appearing multiple times in expansion
535 #define VALIDATE_TYPE(x) (void)x;
536 #define ASSERT(expr) \
537 do { \
538 VALIDATE_TYPE(expr); \
539 if (!expr); \
540 } while (false)
541 bool [[waldo]]() { return true; }
542 void foo() {
543 ASSERT(wa^ldo());
544 }
545 )cpp",
546 R"cpp(// Symbol concatenated inside macro (not supported)
547 int *pi;
548 #define POINTER(X) p ## X;
549 int x = *POINTER(^i);
550 )cpp",
551
552 R"cpp(// Forward class declaration
553 class $decl[[Foo]];
554 class $def[[Foo]] {};
555 F^oo* foo();
556 )cpp",
557
558 R"cpp(// Function declaration
559 void $decl[[foo]]();
560 void g() { f^oo(); }
561 void $def[[foo]]() {}
562 )cpp",
563
564 R"cpp(
565 #define FF(name) class name##_Test {};
566 [[FF]](my);
567 void f() { my^_Test a; }
568 )cpp",
569
570 R"cpp(
571 #define FF() class [[Test]] {};
572 FF();
573 void f() { T^est a; }
574 )cpp",
575
576 R"cpp(// explicit template specialization
577 template <typename T>
578 struct Foo { void bar() {} };
579
580 template <>
581 struct [[Foo]]<int> { void bar() {} };
582
583 void foo() {
584 Foo<char> abc;
585 Fo^o<int> b;
586 }
587 )cpp",
588
589 R"cpp(// implicit template specialization
590 template <typename T>
591 struct [[Foo]] { void bar() {} };
592 template <>
593 struct Foo<int> { void bar() {} };
594 void foo() {
595 Fo^o<char> abc;
596 Foo<int> b;
597 }
598 )cpp",
599
600 R"cpp(// partial template specialization
601 template <typename T>
602 struct Foo { void bar() {} };
603 template <typename T>
604 struct [[Foo]]<T*> { void bar() {} };
605 ^Foo<int*> x;
606 )cpp",
607
608 R"cpp(// function template specializations
609 template <class T>
610 void foo(T) {}
611 template <>
612 void [[foo]](int) {}
613 void bar() {
614 fo^o(10);
615 }
616 )cpp",
617
618 R"cpp(// variable template decls
619 template <class T>
620 T var = T();
621
622 template <>
623 double [[var]]<int> = 10;
624
625 double y = va^r<int>;
626 )cpp",
627
628 R"cpp(// No implicit constructors
629 struct X {
630 X(X&& x) = default;
631 };
632 X $decl[[makeX]]();
633 void foo() {
634 auto x = m^akeX();
635 }
636 )cpp",
637
638 R"cpp(
639 struct X {
640 X& $decl[[operator]]++();
641 };
642 void foo(X& x) {
643 +^+x;
644 }
645 )cpp",
646
647 R"cpp(
648 struct S1 { void f(); };
649 struct S2 { S1 * $decl[[operator]]->(); };
650 void test(S2 s2) {
651 s2-^>f();
652 }
653 )cpp",
654
655 R"cpp(// Declaration of explicit template specialization
656 template <typename T>
657 struct $decl[[Foo]] {};
658
659 template <>
660 struct Fo^o<int> {};
661 )cpp",
662
663 R"cpp(// Declaration of partial template specialization
664 template <typename T>
665 struct $decl[[Foo]] {};
666
667 template <typename T>
668 struct Fo^o<T*> {};
669 )cpp",
670
671 R"cpp(// auto builtin type (not supported)
672 ^auto x = 42;
673 )cpp",
674
675 R"cpp(// auto on lambda
676 auto x = [[[]]]{};
677 ^auto y = x;
678 )cpp",
679
680 R"cpp(// auto on struct
681 namespace ns1 {
682 struct [[S1]] {};
683 } // namespace ns1
684
685 ^auto x = ns1::S1{};
686 )cpp",
687
688 R"cpp(// decltype on struct
689 namespace ns1 {
690 struct [[S1]] {};
691 } // namespace ns1
692
693 ns1::S1 i;
694 ^decltype(i) j;
695 )cpp",
696
697 R"cpp(// decltype(auto) on struct
698 namespace ns1 {
699 struct [[S1]] {};
700 } // namespace ns1
701
702 ns1::S1 i;
703 ns1::S1& j = i;
704 ^decltype(auto) k = j;
705 )cpp",
706
707 R"cpp(// auto on template class
708 template<typename T> class [[Foo]] {};
709
710 ^auto x = Foo<int>();
711 )cpp",
712
713 R"cpp(// auto on template class with forward declared class
714 template<typename T> class [[Foo]] {};
715 class X;
716
717 ^auto x = Foo<X>();
718 )cpp",
719
720 R"cpp(// auto on specialized template class
721 template<typename T> class Foo {};
722 template<> class [[Foo]]<int> {};
723
724 ^auto x = Foo<int>();
725 )cpp",
726
727 R"cpp(// auto on initializer list.
728 namespace std
729 {
730 template<class _E>
731 class [[initializer_list]] {};
732 }
733
734 ^auto i = {1,2};
735 )cpp",
736
737 R"cpp(// auto function return with trailing type
738 struct [[Bar]] {};
739 ^auto test() -> decltype(Bar()) {
740 return Bar();
741 }
742 )cpp",
743
744 R"cpp(// decltype in trailing return type
745 struct [[Bar]] {};
746 auto test() -> ^decltype(Bar()) {
747 return Bar();
748 }
749 )cpp",
750
751 R"cpp(// auto in function return
752 struct [[Bar]] {};
753 ^auto test() {
754 return Bar();
755 }
756 )cpp",
757
758 R"cpp(// auto& in function return
759 struct [[Bar]] {};
760 ^auto& test() {
761 static Bar x;
762 return x;
763 }
764 )cpp",
765
766 R"cpp(// auto* in function return
767 struct [[Bar]] {};
768 ^auto* test() {
769 Bar* x;
770 return x;
771 }
772 )cpp",
773
774 R"cpp(// const auto& in function return
775 struct [[Bar]] {};
776 const ^auto& test() {
777 static Bar x;
778 return x;
779 }
780 )cpp",
781
782 R"cpp(// decltype(auto) in function return
783 struct [[Bar]] {};
784 ^decltype(auto) test() {
785 return Bar();
786 }
787 )cpp",
788
789 R"cpp(// decltype of function with trailing return type.
790 struct [[Bar]] {};
791 auto test() -> decltype(Bar()) {
792 return Bar();
793 }
794 void foo() {
795 ^decltype(test()) i = test();
796 }
797 )cpp",
798
799 R"cpp(// Override specifier jumps to overridden method
800 class Y { virtual void $decl[[a]]() = 0; };
801 class X : Y { void a() ^override {} };
802 )cpp",
803
804 R"cpp(// Final specifier jumps to overridden method
805 class Y { virtual void $decl[[a]]() = 0; };
806 class X : Y { void a() ^final {} };
807 )cpp",
808
809 R"cpp(// Heuristic resolution of dependent method
810 template <typename T>
811 struct S {
812 void [[bar]]() {}
813 };
814
815 template <typename T>
816 void foo(S<T> arg) {
817 arg.ba^r();
818 }
819 )cpp",
820
821 R"cpp(// Heuristic resolution of dependent method via this->
822 template <typename T>
823 struct S {
824 void [[foo]]() {
825 this->fo^o();
826 }
827 };
828 )cpp",
829
830 R"cpp(// Heuristic resolution of dependent static method
831 template <typename T>
832 struct S {
833 static void [[bar]]() {}
834 };
835
836 template <typename T>
837 void foo() {
838 S<T>::ba^r();
839 }
840 )cpp",
841
842 R"cpp(// Heuristic resolution of dependent method
843 // invoked via smart pointer
844 template <typename> struct S { void [[foo]]() {} };
845 template <typename T> struct unique_ptr {
846 T* operator->();
847 };
848 template <typename T>
849 void test(unique_ptr<S<T>>& V) {
850 V->fo^o();
851 }
852 )cpp",
853
854 R"cpp(// Heuristic resolution of dependent enumerator
855 template <typename T>
856 struct Foo {
857 enum class E { [[A]], B };
858 E e = E::A^;
859 };
860 )cpp",
861
862 R"objc(
863 @protocol Dog;
864 @protocol $decl[[Dog]]
865 - (void)bark;
866 @end
867 id<Do^g> getDoggo() {
868 return 0;
869 }
870 )objc",
871
872 R"objc(
873 @interface Cat
874 @end
875 @implementation Cat
876 @end
877 @interface $decl[[Cat]] (Exte^nsion)
878 - (void)meow;
879 @end
880 @implementation $def[[Cat]] (Extension)
881 - (void)meow {}
882 @end
883 )objc",
884
885 R"objc(
886 @class $decl[[Foo]];
887 Fo^o * getFoo() {
888 return 0;
889 }
890 )objc",
891
892 R"objc(// Prefer interface definition over forward declaration
893 @class Foo;
894 @interface $decl[[Foo]]
895 @end
896 Fo^o * getFoo() {
897 return 0;
898 }
899 )objc",
900
901 R"objc(
902 @class Foo;
903 @interface $decl[[Foo]]
904 @end
905 @implementation $def[[Foo]]
906 @end
907 Fo^o * getFoo() {
908 return 0;
909 }
910 )objc"};
911 for (const char *Test : Tests) {
912 Annotations T(Test);
913 llvm::Optional<Range> WantDecl;
914 llvm::Optional<Range> WantDef;
915 if (!T.ranges().empty())
916 WantDecl = WantDef = T.range();
917 if (!T.ranges("decl").empty())
918 WantDecl = T.range("decl");
919 if (!T.ranges("def").empty())
920 WantDef = T.range("def");
921
922 TestTU TU;
923 TU.Code = std::string(T.code());
924
925 TU.ExtraArgs.push_back("-xobjective-c++");
926
927 auto AST = TU.build();
928 auto Results = locateSymbolAt(AST, T.point());
929
930 if (!WantDecl) {
931 EXPECT_THAT(Results, IsEmpty()) << Test;
932 } else {
933 ASSERT_THAT(Results, ::testing::SizeIs(1)) << Test;
934 EXPECT_EQ(Results[0].PreferredDeclaration.range, *WantDecl) << Test;
935 EXPECT_TRUE(Results[0].ID) << Test;
936 llvm::Optional<Range> GotDef;
937 if (Results[0].Definition)
938 GotDef = Results[0].Definition->range;
939 EXPECT_EQ(WantDef, GotDef) << Test;
940 }
941 }
942 }
TEST(LocateSymbol,ValidSymbolID)943 TEST(LocateSymbol, ValidSymbolID) {
944 auto T = Annotations(R"cpp(
945 #define MACRO(x, y) ((x) + (y))
946 int add(int x, int y) { return $MACRO^MACRO(x, y); }
947 int sum = $add^add(1, 2);
948 )cpp");
949
950 TestTU TU = TestTU::withCode(T.code());
951 auto AST = TU.build();
952 auto Index = TU.index();
953 EXPECT_THAT(locateSymbolAt(AST, T.point("add"), Index.get()),
954 ElementsAre(AllOf(Sym("add"),
955 HasID(getSymbolID(&findDecl(AST, "add"))))));
956 EXPECT_THAT(
957 locateSymbolAt(AST, T.point("MACRO"), Index.get()),
958 ElementsAre(AllOf(Sym("MACRO"),
959 HasID(findSymbol(TU.headerSymbols(), "MACRO").ID))));
960 }
961
TEST(LocateSymbol,AllMulti)962 TEST(LocateSymbol, AllMulti) {
963 // Ranges in tests:
964 // $declN is the declaration location
965 // $defN is the definition location (if absent, symbol has no definition)
966 //
967 // NOTE:
968 // N starts at 0.
969 struct ExpectedRanges {
970 Range WantDecl;
971 llvm::Optional<Range> WantDef;
972 };
973 const char *Tests[] = {
974 R"objc(
975 @interface $decl0[[Cat]]
976 @end
977 @implementation $def0[[Cat]]
978 @end
979 @interface $decl1[[Ca^t]] (Extension)
980 - (void)meow;
981 @end
982 @implementation $def1[[Cat]] (Extension)
983 - (void)meow {}
984 @end
985 )objc",
986
987 R"objc(
988 @interface $decl0[[Cat]]
989 @end
990 @implementation $def0[[Cat]]
991 @end
992 @interface $decl1[[Cat]] (Extension)
993 - (void)meow;
994 @end
995 @implementation $def1[[Ca^t]] (Extension)
996 - (void)meow {}
997 @end
998 )objc",
999
1000 R"objc(
1001 @interface $decl0[[Cat]]
1002 @end
1003 @interface $decl1[[Ca^t]] ()
1004 - (void)meow;
1005 @end
1006 @implementation $def0[[$def1[[Cat]]]]
1007 - (void)meow {}
1008 @end
1009 )objc",
1010 };
1011 for (const char *Test : Tests) {
1012 Annotations T(Test);
1013 std::vector<ExpectedRanges> Ranges;
1014 for (int Idx = 0; true; Idx++) {
1015 bool HasDecl = !T.ranges("decl" + std::to_string(Idx)).empty();
1016 bool HasDef = !T.ranges("def" + std::to_string(Idx)).empty();
1017 if (!HasDecl && !HasDef)
1018 break;
1019 ExpectedRanges Range;
1020 if (HasDecl)
1021 Range.WantDecl = T.range("decl" + std::to_string(Idx));
1022 if (HasDef)
1023 Range.WantDef = T.range("def" + std::to_string(Idx));
1024 Ranges.push_back(Range);
1025 }
1026
1027 TestTU TU;
1028 TU.Code = std::string(T.code());
1029 TU.ExtraArgs.push_back("-xobjective-c++");
1030
1031 auto AST = TU.build();
1032 auto Results = locateSymbolAt(AST, T.point());
1033
1034 ASSERT_THAT(Results, ::testing::SizeIs(Ranges.size())) << Test;
1035 for (size_t Idx = 0; Idx < Ranges.size(); Idx++) {
1036 EXPECT_EQ(Results[Idx].PreferredDeclaration.range, Ranges[Idx].WantDecl)
1037 << "($decl" << Idx << ")" << Test;
1038 llvm::Optional<Range> GotDef;
1039 if (Results[Idx].Definition)
1040 GotDef = Results[Idx].Definition->range;
1041 EXPECT_EQ(GotDef, Ranges[Idx].WantDef) << "($def" << Idx << ")" << Test;
1042 }
1043 }
1044 }
1045
1046 // LocateSymbol test cases that produce warnings.
1047 // These are separated out from All so that in All we can assert
1048 // that there are no diagnostics.
TEST(LocateSymbol,Warnings)1049 TEST(LocateSymbol, Warnings) {
1050 const char *Tests[] = {
1051 R"cpp(// Field, GNU old-style field designator
1052 struct Foo { int [[x]]; };
1053 int main() {
1054 Foo bar = { ^x : 1 };
1055 }
1056 )cpp",
1057
1058 R"cpp(// Macro
1059 #define MACRO 0
1060 #define [[MACRO]] 1
1061 int main() { return ^MACRO; }
1062 #define MACRO 2
1063 #undef macro
1064 )cpp",
1065 };
1066
1067 for (const char *Test : Tests) {
1068 Annotations T(Test);
1069 llvm::Optional<Range> WantDecl;
1070 llvm::Optional<Range> WantDef;
1071 if (!T.ranges().empty())
1072 WantDecl = WantDef = T.range();
1073 if (!T.ranges("decl").empty())
1074 WantDecl = T.range("decl");
1075 if (!T.ranges("def").empty())
1076 WantDef = T.range("def");
1077
1078 TestTU TU;
1079 TU.Code = std::string(T.code());
1080
1081 auto AST = TU.build();
1082 auto Results = locateSymbolAt(AST, T.point());
1083
1084 if (!WantDecl) {
1085 EXPECT_THAT(Results, IsEmpty()) << Test;
1086 } else {
1087 ASSERT_THAT(Results, ::testing::SizeIs(1)) << Test;
1088 EXPECT_EQ(Results[0].PreferredDeclaration.range, *WantDecl) << Test;
1089 llvm::Optional<Range> GotDef;
1090 if (Results[0].Definition)
1091 GotDef = Results[0].Definition->range;
1092 EXPECT_EQ(WantDef, GotDef) << Test;
1093 }
1094 }
1095 }
1096
TEST(LocateSymbol,TextualSmoke)1097 TEST(LocateSymbol, TextualSmoke) {
1098 auto T = Annotations(
1099 R"cpp(
1100 struct [[MyClass]] {};
1101 // Comment mentioning M^yClass
1102 )cpp");
1103
1104 auto TU = TestTU::withCode(T.code());
1105 auto AST = TU.build();
1106 auto Index = TU.index();
1107 EXPECT_THAT(
1108 locateSymbolAt(AST, T.point(), Index.get()),
1109 ElementsAre(AllOf(Sym("MyClass", T.range(), T.range()),
1110 HasID(getSymbolID(&findDecl(AST, "MyClass"))))));
1111 }
1112
TEST(LocateSymbol,Textual)1113 TEST(LocateSymbol, Textual) {
1114 const char *Tests[] = {
1115 R"cpp(// Comment
1116 struct [[MyClass]] {};
1117 // Comment mentioning M^yClass
1118 )cpp",
1119 R"cpp(// String
1120 struct MyClass {};
1121 // Not triggered for string literal tokens.
1122 const char* s = "String literal mentioning M^yClass";
1123 )cpp",
1124 R"cpp(// Ifdef'ed out code
1125 struct [[MyClass]] {};
1126 #ifdef WALDO
1127 M^yClass var;
1128 #endif
1129 )cpp",
1130 R"cpp(// Macro definition
1131 struct [[MyClass]] {};
1132 #define DECLARE_MYCLASS_OBJ(name) M^yClass name;
1133 )cpp",
1134 R"cpp(// Invalid code
1135 /*error-ok*/
1136 int myFunction(int);
1137 // Not triggered for token which survived preprocessing.
1138 int var = m^yFunction();
1139 )cpp"};
1140
1141 for (const char *Test : Tests) {
1142 Annotations T(Test);
1143 llvm::Optional<Range> WantDecl;
1144 if (!T.ranges().empty())
1145 WantDecl = T.range();
1146
1147 auto TU = TestTU::withCode(T.code());
1148
1149 auto AST = TU.build();
1150 auto Index = TU.index();
1151 auto Word = SpelledWord::touching(
1152 cantFail(sourceLocationInMainFile(AST.getSourceManager(), T.point())),
1153 AST.getTokens(), AST.getLangOpts());
1154 if (!Word) {
1155 ADD_FAILURE() << "No word touching point!" << Test;
1156 continue;
1157 }
1158 auto Results = locateSymbolTextually(*Word, AST, Index.get(),
1159 testPath(TU.Filename), ASTNodeKind());
1160
1161 if (!WantDecl) {
1162 EXPECT_THAT(Results, IsEmpty()) << Test;
1163 } else {
1164 ASSERT_THAT(Results, ::testing::SizeIs(1)) << Test;
1165 EXPECT_EQ(Results[0].PreferredDeclaration.range, *WantDecl) << Test;
1166 }
1167 }
1168 } // namespace
1169
TEST(LocateSymbol,Ambiguous)1170 TEST(LocateSymbol, Ambiguous) {
1171 auto T = Annotations(R"cpp(
1172 struct Foo {
1173 Foo();
1174 Foo(Foo&&);
1175 $ConstructorLoc[[Foo]](const char*);
1176 };
1177
1178 Foo f();
1179
1180 void g(Foo foo);
1181
1182 void call() {
1183 const char* str = "123";
1184 Foo a = $1^str;
1185 Foo b = Foo($2^str);
1186 Foo c = $3^f();
1187 $4^g($5^f());
1188 g($6^str);
1189 Foo ab$7^c;
1190 Foo ab$8^cd("asdf");
1191 Foo foox = Fo$9^o("asdf");
1192 Foo abcde$10^("asdf");
1193 Foo foox2 = Foo$11^("asdf");
1194 }
1195
1196 template <typename T>
1197 struct S {
1198 void $NonstaticOverload1[[bar]](int);
1199 void $NonstaticOverload2[[bar]](float);
1200
1201 static void $StaticOverload1[[baz]](int);
1202 static void $StaticOverload2[[baz]](float);
1203 };
1204
1205 template <typename T, typename U>
1206 void dependent_call(S<T> s, U u) {
1207 s.ba$12^r(u);
1208 S<T>::ba$13^z(u);
1209 }
1210 )cpp");
1211 auto TU = TestTU::withCode(T.code());
1212 // FIXME: Go-to-definition in a template requires disabling delayed template
1213 // parsing.
1214 TU.ExtraArgs.push_back("-fno-delayed-template-parsing");
1215 auto AST = TU.build();
1216 // Ordered assertions are deliberate: we expect a predictable order.
1217 EXPECT_THAT(locateSymbolAt(AST, T.point("1")), ElementsAre(Sym("str")));
1218 EXPECT_THAT(locateSymbolAt(AST, T.point("2")), ElementsAre(Sym("str")));
1219 EXPECT_THAT(locateSymbolAt(AST, T.point("3")), ElementsAre(Sym("f")));
1220 EXPECT_THAT(locateSymbolAt(AST, T.point("4")), ElementsAre(Sym("g")));
1221 EXPECT_THAT(locateSymbolAt(AST, T.point("5")), ElementsAre(Sym("f")));
1222 EXPECT_THAT(locateSymbolAt(AST, T.point("6")), ElementsAre(Sym("str")));
1223 // FIXME: Target the constructor as well.
1224 EXPECT_THAT(locateSymbolAt(AST, T.point("7")), ElementsAre(Sym("abc")));
1225 // FIXME: Target the constructor as well.
1226 EXPECT_THAT(locateSymbolAt(AST, T.point("8")), ElementsAre(Sym("abcd")));
1227 // FIXME: Target the constructor as well.
1228 EXPECT_THAT(locateSymbolAt(AST, T.point("9")), ElementsAre(Sym("Foo")));
1229 EXPECT_THAT(locateSymbolAt(AST, T.point("10")),
1230 ElementsAre(Sym("Foo", T.range("ConstructorLoc"), llvm::None)));
1231 EXPECT_THAT(locateSymbolAt(AST, T.point("11")),
1232 ElementsAre(Sym("Foo", T.range("ConstructorLoc"), llvm::None)));
1233 // These assertions are unordered because the order comes from
1234 // CXXRecordDecl::lookupDependentName() which doesn't appear to provide
1235 // an order guarantee.
1236 EXPECT_THAT(locateSymbolAt(AST, T.point("12")),
1237 UnorderedElementsAre(
1238 Sym("bar", T.range("NonstaticOverload1"), llvm::None),
1239 Sym("bar", T.range("NonstaticOverload2"), llvm::None)));
1240 EXPECT_THAT(
1241 locateSymbolAt(AST, T.point("13")),
1242 UnorderedElementsAre(Sym("baz", T.range("StaticOverload1"), llvm::None),
1243 Sym("baz", T.range("StaticOverload2"), llvm::None)));
1244 }
1245
TEST(LocateSymbol,TextualDependent)1246 TEST(LocateSymbol, TextualDependent) {
1247 // Put the declarations in the header to make sure we are
1248 // finding them via the index heuristic and not the
1249 // nearby-ident heuristic.
1250 Annotations Header(R"cpp(
1251 struct Foo {
1252 void $FooLoc[[uniqueMethodName]]();
1253 };
1254 struct Bar {
1255 void $BarLoc[[uniqueMethodName]]();
1256 };
1257 )cpp");
1258 Annotations Source(R"cpp(
1259 template <typename T>
1260 void f(T t) {
1261 t.u^niqueMethodName();
1262 }
1263 )cpp");
1264 TestTU TU;
1265 TU.Code = std::string(Source.code());
1266 TU.HeaderCode = std::string(Header.code());
1267 auto AST = TU.build();
1268 auto Index = TU.index();
1269 // Need to use locateSymbolAt() since we are testing an
1270 // interaction between locateASTReferent() and
1271 // locateSymbolNamedTextuallyAt().
1272 auto Results = locateSymbolAt(AST, Source.point(), Index.get());
1273 EXPECT_THAT(Results,
1274 UnorderedElementsAre(
1275 Sym("uniqueMethodName", Header.range("FooLoc"), llvm::None),
1276 Sym("uniqueMethodName", Header.range("BarLoc"), llvm::None)));
1277 }
1278
TEST(LocateSymbol,Alias)1279 TEST(LocateSymbol, Alias) {
1280 const char *Tests[] = {
1281 R"cpp(
1282 template <class T> struct function {};
1283 template <class T> using [[callback]] = function<T()>;
1284
1285 c^allback<int> foo;
1286 )cpp",
1287
1288 // triggered on non-definition of a renaming alias: should not give any
1289 // underlying decls.
1290 R"cpp(
1291 class Foo {};
1292 typedef Foo [[Bar]];
1293
1294 B^ar b;
1295 )cpp",
1296 R"cpp(
1297 class Foo {};
1298 using [[Bar]] = Foo; // definition
1299 Ba^r b;
1300 )cpp",
1301
1302 // triggered on the underlying decl of a renaming alias.
1303 R"cpp(
1304 class [[Foo]];
1305 using Bar = Fo^o;
1306 )cpp",
1307
1308 // triggered on definition of a non-renaming alias: should give underlying
1309 // decls.
1310 R"cpp(
1311 namespace ns { class [[Foo]] {}; }
1312 using ns::F^oo;
1313 )cpp",
1314
1315 R"cpp(
1316 namespace ns { int [[x]](char); int [[x]](double); }
1317 using ns::^x;
1318 )cpp",
1319
1320 R"cpp(
1321 namespace ns { int [[x]](char); int x(double); }
1322 using ns::[[x]];
1323 int y = ^x('a');
1324 )cpp",
1325
1326 R"cpp(
1327 namespace ns { class [[Foo]] {}; }
1328 using ns::Foo;
1329 F^oo f;
1330 )cpp",
1331
1332 // other cases that don't matter much.
1333 R"cpp(
1334 class Foo {};
1335 typedef Foo [[Ba^r]];
1336 )cpp",
1337 R"cpp(
1338 class Foo {};
1339 using [[B^ar]] = Foo;
1340 )cpp",
1341
1342 // Member of dependent base
1343 R"cpp(
1344 template <typename T>
1345 struct Base {
1346 void [[waldo]]() {}
1347 };
1348 template <typename T>
1349 struct Derived : Base<T> {
1350 using Base<T>::w^aldo;
1351 };
1352 )cpp",
1353 };
1354
1355 for (const auto *Case : Tests) {
1356 SCOPED_TRACE(Case);
1357 auto T = Annotations(Case);
1358 auto AST = TestTU::withCode(T.code()).build();
1359 EXPECT_THAT(locateSymbolAt(AST, T.point()),
1360 UnorderedPointwise(DeclRange(), T.ranges()));
1361 }
1362 }
1363
TEST(LocateSymbol,RelPathsInCompileCommand)1364 TEST(LocateSymbol, RelPathsInCompileCommand) {
1365 // The source is in "/clangd-test/src".
1366 // We build in "/clangd-test/build".
1367
1368 Annotations SourceAnnotations(R"cpp(
1369 #include "header_in_preamble.h"
1370 int [[foo]];
1371 #include "header_not_in_preamble.h"
1372 int baz = f$p1^oo + bar_pre$p2^amble + bar_not_pre$p3^amble;
1373 )cpp");
1374
1375 Annotations HeaderInPreambleAnnotations(R"cpp(
1376 int [[bar_preamble]];
1377 )cpp");
1378
1379 Annotations HeaderNotInPreambleAnnotations(R"cpp(
1380 int [[bar_not_preamble]];
1381 )cpp");
1382
1383 // Make the compilation paths appear as ../src/foo.cpp in the compile
1384 // commands.
1385 SmallString<32> RelPathPrefix("..");
1386 llvm::sys::path::append(RelPathPrefix, "src");
1387 std::string BuildDir = testPath("build");
1388 MockCompilationDatabase CDB(BuildDir, RelPathPrefix);
1389
1390 MockFS FS;
1391 ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
1392
1393 // Fill the filesystem.
1394 auto FooCpp = testPath("src/foo.cpp");
1395 FS.Files[FooCpp] = "";
1396 auto HeaderInPreambleH = testPath("src/header_in_preamble.h");
1397 FS.Files[HeaderInPreambleH] = std::string(HeaderInPreambleAnnotations.code());
1398 auto HeaderNotInPreambleH = testPath("src/header_not_in_preamble.h");
1399 FS.Files[HeaderNotInPreambleH] =
1400 std::string(HeaderNotInPreambleAnnotations.code());
1401
1402 runAddDocument(Server, FooCpp, SourceAnnotations.code());
1403
1404 // Go to a definition in main source file.
1405 auto Locations =
1406 runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("p1"));
1407 EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error";
1408 EXPECT_THAT(*Locations, ElementsAre(Sym("foo", SourceAnnotations.range(),
1409 SourceAnnotations.range())));
1410
1411 // Go to a definition in header_in_preamble.h.
1412 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("p2"));
1413 EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error";
1414 EXPECT_THAT(
1415 *Locations,
1416 ElementsAre(Sym("bar_preamble", HeaderInPreambleAnnotations.range(),
1417 HeaderInPreambleAnnotations.range())));
1418
1419 // Go to a definition in header_not_in_preamble.h.
1420 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("p3"));
1421 EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error";
1422 EXPECT_THAT(*Locations,
1423 ElementsAre(Sym("bar_not_preamble",
1424 HeaderNotInPreambleAnnotations.range(),
1425 HeaderNotInPreambleAnnotations.range())));
1426 }
1427
TEST(GoToInclude,All)1428 TEST(GoToInclude, All) {
1429 MockFS FS;
1430 MockCompilationDatabase CDB;
1431 ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
1432
1433 auto FooCpp = testPath("foo.cpp");
1434 const char *SourceContents = R"cpp(
1435 #include ^"$2^foo.h$3^"
1436 #include "$4^invalid.h"
1437 int b = a;
1438 // test
1439 int foo;
1440 #in$5^clude "$6^foo.h"$7^
1441 )cpp";
1442 Annotations SourceAnnotations(SourceContents);
1443 FS.Files[FooCpp] = std::string(SourceAnnotations.code());
1444 auto FooH = testPath("foo.h");
1445
1446 const char *HeaderContents = R"cpp([[]]#pragma once
1447 int a;
1448 )cpp";
1449 Annotations HeaderAnnotations(HeaderContents);
1450 FS.Files[FooH] = std::string(HeaderAnnotations.code());
1451
1452 runAddDocument(Server, FooH, HeaderAnnotations.code());
1453 runAddDocument(Server, FooCpp, SourceAnnotations.code());
1454
1455 // Test include in preamble.
1456 auto Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point());
1457 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1458 EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range(),
1459 HeaderAnnotations.range())));
1460
1461 // Test include in preamble, last char.
1462 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("2"));
1463 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1464 EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range(),
1465 HeaderAnnotations.range())));
1466
1467 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("3"));
1468 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1469 EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range(),
1470 HeaderAnnotations.range())));
1471
1472 // Test include outside of preamble.
1473 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("6"));
1474 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1475 EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range(),
1476 HeaderAnnotations.range())));
1477
1478 // Test a few positions that do not result in Locations.
1479 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("4"));
1480 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1481 EXPECT_THAT(*Locations, IsEmpty());
1482
1483 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("5"));
1484 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1485 EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range(),
1486 HeaderAnnotations.range())));
1487
1488 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("7"));
1489 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1490 EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range(),
1491 HeaderAnnotations.range())));
1492
1493 // Objective C #import directive.
1494 Annotations ObjC(R"objc(
1495 #import "^foo.h"
1496 )objc");
1497 auto FooM = testPath("foo.m");
1498 FS.Files[FooM] = std::string(ObjC.code());
1499
1500 runAddDocument(Server, FooM, ObjC.code());
1501 Locations = runLocateSymbolAt(Server, FooM, ObjC.point());
1502 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1503 EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range(),
1504 HeaderAnnotations.range())));
1505 }
1506
TEST(LocateSymbol,WithPreamble)1507 TEST(LocateSymbol, WithPreamble) {
1508 // Test stragety: AST should always use the latest preamble instead of last
1509 // good preamble.
1510 MockFS FS;
1511 MockCompilationDatabase CDB;
1512 ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
1513
1514 auto FooCpp = testPath("foo.cpp");
1515 // The trigger locations must be the same.
1516 Annotations FooWithHeader(R"cpp(#include "fo^o.h")cpp");
1517 Annotations FooWithoutHeader(R"cpp(double [[fo^o]]();)cpp");
1518
1519 FS.Files[FooCpp] = std::string(FooWithHeader.code());
1520
1521 auto FooH = testPath("foo.h");
1522 Annotations FooHeader(R"cpp([[]])cpp");
1523 FS.Files[FooH] = std::string(FooHeader.code());
1524
1525 runAddDocument(Server, FooCpp, FooWithHeader.code());
1526 // LocateSymbol goes to a #include file: the result comes from the preamble.
1527 EXPECT_THAT(
1528 cantFail(runLocateSymbolAt(Server, FooCpp, FooWithHeader.point())),
1529 ElementsAre(Sym("foo.h", FooHeader.range(), FooHeader.range())));
1530
1531 // Only preamble is built, and no AST is built in this request.
1532 Server.addDocument(FooCpp, FooWithoutHeader.code(), "null",
1533 WantDiagnostics::No);
1534 // We build AST here, and it should use the latest preamble rather than the
1535 // stale one.
1536 EXPECT_THAT(
1537 cantFail(runLocateSymbolAt(Server, FooCpp, FooWithoutHeader.point())),
1538 ElementsAre(Sym("foo", FooWithoutHeader.range(), llvm::None)));
1539
1540 // Reset test environment.
1541 runAddDocument(Server, FooCpp, FooWithHeader.code());
1542 // Both preamble and AST are built in this request.
1543 Server.addDocument(FooCpp, FooWithoutHeader.code(), "null",
1544 WantDiagnostics::Yes);
1545 // Use the AST being built in above request.
1546 EXPECT_THAT(
1547 cantFail(runLocateSymbolAt(Server, FooCpp, FooWithoutHeader.point())),
1548 ElementsAre(Sym("foo", FooWithoutHeader.range(), llvm::None)));
1549 }
1550
TEST(LocateSymbol,NearbyTokenSmoke)1551 TEST(LocateSymbol, NearbyTokenSmoke) {
1552 auto T = Annotations(R"cpp(
1553 // prints e^rr and crashes
1554 void die(const char* [[err]]);
1555 )cpp");
1556 auto AST = TestTU::withCode(T.code()).build();
1557 // We don't pass an index, so can't hit index-based fallback.
1558 EXPECT_THAT(locateSymbolAt(AST, T.point()),
1559 ElementsAre(Sym("err", T.range(), T.range())));
1560 }
1561
TEST(LocateSymbol,NearbyIdentifier)1562 TEST(LocateSymbol, NearbyIdentifier) {
1563 const char *Tests[] = {
1564 R"cpp(
1565 // regular identifiers (won't trigger)
1566 int hello;
1567 int y = he^llo;
1568 )cpp",
1569 R"cpp(
1570 // disabled preprocessor sections
1571 int [[hello]];
1572 #if 0
1573 int y = ^hello;
1574 #endif
1575 )cpp",
1576 R"cpp(
1577 // comments
1578 // he^llo, world
1579 int [[hello]];
1580 )cpp",
1581 R"cpp(
1582 // not triggered by string literals
1583 int hello;
1584 const char* greeting = "h^ello, world";
1585 )cpp",
1586
1587 R"cpp(
1588 // can refer to macro invocations
1589 #define INT int
1590 [[INT]] x;
1591 // I^NT
1592 )cpp",
1593
1594 R"cpp(
1595 // can refer to macro invocations (even if they expand to nothing)
1596 #define EMPTY
1597 [[EMPTY]] int x;
1598 // E^MPTY
1599 )cpp",
1600
1601 R"cpp(
1602 // prefer nearest occurrence, backwards is worse than forwards
1603 int hello;
1604 int x = hello;
1605 // h^ello
1606 int y = [[hello]];
1607 int z = hello;
1608 )cpp",
1609
1610 R"cpp(
1611 // short identifiers find near results
1612 int [[hi]];
1613 // h^i
1614 )cpp",
1615 R"cpp(
1616 // short identifiers don't find far results
1617 int hi;
1618
1619
1620
1621 // h^i
1622
1623
1624
1625
1626 int x = hi;
1627 )cpp",
1628 R"cpp(
1629 // prefer nearest occurrence even if several matched tokens
1630 // have the same value of `floor(log2(<token line> - <word line>))`.
1631 int hello;
1632 int x = hello, y = hello;
1633 int z = [[hello]];
1634 // h^ello
1635 )cpp"};
1636 for (const char *Test : Tests) {
1637 Annotations T(Test);
1638 auto AST = TestTU::withCode(T.code()).build();
1639 const auto &SM = AST.getSourceManager();
1640 llvm::Optional<Range> Nearby;
1641 auto Word =
1642 SpelledWord::touching(cantFail(sourceLocationInMainFile(SM, T.point())),
1643 AST.getTokens(), AST.getLangOpts());
1644 if (!Word) {
1645 ADD_FAILURE() << "No word at point! " << Test;
1646 continue;
1647 }
1648 if (const auto *Tok = findNearbyIdentifier(*Word, AST.getTokens()))
1649 Nearby = halfOpenToRange(SM, CharSourceRange::getCharRange(
1650 Tok->location(), Tok->endLocation()));
1651 if (T.ranges().empty())
1652 EXPECT_THAT(Nearby, Eq(llvm::None)) << Test;
1653 else
1654 EXPECT_EQ(Nearby, T.range()) << Test;
1655 }
1656 }
1657
TEST(FindImplementations,Inheritance)1658 TEST(FindImplementations, Inheritance) {
1659 llvm::StringRef Test = R"cpp(
1660 struct $0^Base {
1661 virtual void F$1^oo();
1662 void C$4^oncrete();
1663 };
1664 struct $0[[Child1]] : Base {
1665 void $1[[Fo$3^o]]() override;
1666 virtual void B$2^ar();
1667 void Concrete(); // No implementations for concrete methods.
1668 };
1669 struct Child2 : Child1 {
1670 void $3[[Foo]]() override;
1671 void $2[[Bar]]() override;
1672 };
1673 void FromReference() {
1674 $0^Base* B;
1675 B->Fo$1^o();
1676 B->C$4^oncrete();
1677 &Base::Fo$1^o;
1678 Child1 * C1;
1679 C1->B$2^ar();
1680 C1->Fo$3^o();
1681 }
1682 // CRTP should work.
1683 template<typename T>
1684 struct $5^TemplateBase {};
1685 struct $5[[Child3]] : public TemplateBase<Child3> {};
1686
1687 // Local classes.
1688 void LocationFunction() {
1689 struct $0[[LocalClass1]] : Base {
1690 void $1[[Foo]]() override;
1691 };
1692 struct $6^LocalBase {
1693 virtual void $7^Bar();
1694 };
1695 struct $6[[LocalClass2]]: LocalBase {
1696 void $7[[Bar]]() override;
1697 };
1698 }
1699 )cpp";
1700
1701 Annotations Code(Test);
1702 auto TU = TestTU::withCode(Code.code());
1703 auto AST = TU.build();
1704 auto Index = TU.index();
1705 for (StringRef Label : {"0", "1", "2", "3", "4", "5", "6", "7"}) {
1706 for (const auto &Point : Code.points(Label)) {
1707 EXPECT_THAT(findImplementations(AST, Point, Index.get()),
1708 UnorderedPointwise(DeclRange(), Code.ranges(Label)))
1709 << Code.code() << " at " << Point << " for Label " << Label;
1710 }
1711 }
1712 }
1713
TEST(FindImplementations,CaptureDefintion)1714 TEST(FindImplementations, CaptureDefintion) {
1715 llvm::StringRef Test = R"cpp(
1716 struct Base {
1717 virtual void F^oo();
1718 };
1719 struct Child1 : Base {
1720 void $Decl[[Foo]]() override;
1721 };
1722 struct Child2 : Base {
1723 void $Child2[[Foo]]() override;
1724 };
1725 void Child1::$Def[[Foo]]() { /* Definition */ }
1726 )cpp";
1727 Annotations Code(Test);
1728 auto TU = TestTU::withCode(Code.code());
1729 auto AST = TU.build();
1730 EXPECT_THAT(
1731 findImplementations(AST, Code.point(), TU.index().get()),
1732 UnorderedElementsAre(Sym("Foo", Code.range("Decl"), Code.range("Def")),
1733 Sym("Foo", Code.range("Child2"), llvm::None)))
1734 << Test;
1735 }
1736
checkFindRefs(llvm::StringRef Test,bool UseIndex=false)1737 void checkFindRefs(llvm::StringRef Test, bool UseIndex = false) {
1738 Annotations T(Test);
1739 auto TU = TestTU::withCode(T.code());
1740 auto AST = TU.build();
1741 std::vector<Matcher<ReferencesResult::Reference>> ExpectedLocations;
1742 for (const auto &R : T.ranges())
1743 ExpectedLocations.push_back(AllOf(RangeIs(R), AttrsAre(0u)));
1744 // $def is actually shorthand for both definition and declaration.
1745 // If we have cases that are definition-only, we should change this.
1746 for (const auto &R : T.ranges("def"))
1747 ExpectedLocations.push_back(
1748 AllOf(RangeIs(R), AttrsAre(ReferencesResult::Definition |
1749 ReferencesResult::Declaration)));
1750 for (const auto &R : T.ranges("decl"))
1751 ExpectedLocations.push_back(
1752 AllOf(RangeIs(R), AttrsAre(ReferencesResult::Declaration)));
1753 for (const auto &R : T.ranges("overridedecl"))
1754 ExpectedLocations.push_back(AllOf(
1755 RangeIs(R),
1756 AttrsAre(ReferencesResult::Declaration | ReferencesResult::Override)));
1757 for (const auto &R : T.ranges("overridedef"))
1758 ExpectedLocations.push_back(
1759 AllOf(RangeIs(R), AttrsAre(ReferencesResult::Declaration |
1760 ReferencesResult::Definition |
1761 ReferencesResult::Override)));
1762 EXPECT_THAT(
1763 findReferences(AST, T.point(), 0, UseIndex ? TU.index().get() : nullptr)
1764 .References,
1765 UnorderedElementsAreArray(ExpectedLocations))
1766 << Test;
1767 }
1768
TEST(FindReferences,WithinAST)1769 TEST(FindReferences, WithinAST) {
1770 const char *Tests[] = {
1771 R"cpp(// Local variable
1772 int main() {
1773 int $def[[foo]];
1774 [[^foo]] = 2;
1775 int test1 = [[foo]];
1776 }
1777 )cpp",
1778
1779 R"cpp(// Struct
1780 namespace ns1 {
1781 struct $def[[Foo]] {};
1782 } // namespace ns1
1783 int main() {
1784 ns1::[[Fo^o]]* Params;
1785 }
1786 )cpp",
1787
1788 R"cpp(// Forward declaration
1789 class $decl[[Foo]];
1790 class $def[[Foo]] {};
1791 int main() {
1792 [[Fo^o]] foo;
1793 }
1794 )cpp",
1795
1796 R"cpp(// Function
1797 int $def[[foo]](int) {}
1798 int main() {
1799 auto *X = &[[^foo]];
1800 [[foo]](42);
1801 }
1802 )cpp",
1803
1804 R"cpp(// Field
1805 struct Foo {
1806 int $def[[foo]];
1807 Foo() : [[foo]](0) {}
1808 };
1809 int main() {
1810 Foo f;
1811 f.[[f^oo]] = 1;
1812 }
1813 )cpp",
1814
1815 R"cpp(// Method call
1816 struct Foo { int $decl[[foo]](); };
1817 int Foo::$def[[foo]]() {}
1818 int main() {
1819 Foo f;
1820 f.[[^foo]]();
1821 }
1822 )cpp",
1823
1824 R"cpp(// Constructor
1825 struct Foo {
1826 $decl[[F^oo]](int);
1827 };
1828 void foo() {
1829 Foo f = [[Foo]](42);
1830 }
1831 )cpp",
1832
1833 R"cpp(// Typedef
1834 typedef int $def[[Foo]];
1835 int main() {
1836 [[^Foo]] bar;
1837 }
1838 )cpp",
1839
1840 R"cpp(// Namespace
1841 namespace $decl[[ns]] { // FIXME: def?
1842 struct Foo {};
1843 } // namespace ns
1844 int main() { [[^ns]]::Foo foo; }
1845 )cpp",
1846
1847 R"cpp(// Macros
1848 #define TYPE(X) X
1849 #define FOO Foo
1850 #define CAT(X, Y) X##Y
1851 class $def[[Fo^o]] {};
1852 void test() {
1853 TYPE([[Foo]]) foo;
1854 [[FOO]] foo2;
1855 TYPE(TYPE([[Foo]])) foo3;
1856 [[CAT]](Fo, o) foo4;
1857 }
1858 )cpp",
1859
1860 R"cpp(// Macros
1861 #define $def[[MA^CRO]](X) (X+1)
1862 void test() {
1863 int x = [[MACRO]]([[MACRO]](1));
1864 }
1865 )cpp",
1866
1867 R"cpp(// Macro outside preamble
1868 int breakPreamble;
1869 #define $def[[MA^CRO]](X) (X+1)
1870 void test() {
1871 int x = [[MACRO]]([[MACRO]](1));
1872 }
1873 )cpp",
1874
1875 R"cpp(
1876 int $def[[v^ar]] = 0;
1877 void foo(int s = [[var]]);
1878 )cpp",
1879
1880 R"cpp(
1881 template <typename T>
1882 class $def[[Fo^o]] {};
1883 void func([[Foo]]<int>);
1884 )cpp",
1885
1886 R"cpp(
1887 template <typename T>
1888 class $def[[Foo]] {};
1889 void func([[Fo^o]]<int>);
1890 )cpp",
1891 R"cpp(// Not touching any identifiers.
1892 struct Foo {
1893 $def[[~]]Foo() {};
1894 };
1895 void foo() {
1896 Foo f;
1897 f.[[^~]]Foo();
1898 }
1899 )cpp",
1900 R"cpp(// Lambda capture initializer
1901 void foo() {
1902 int $def[[w^aldo]] = 42;
1903 auto lambda = [x = [[waldo]]](){};
1904 }
1905 )cpp",
1906 R"cpp(// Renaming alias
1907 template <typename> class Vector {};
1908 using $def[[^X]] = Vector<int>;
1909 [[X]] x1;
1910 Vector<int> x2;
1911 Vector<double> y;
1912 )cpp",
1913 R"cpp(// Dependent code
1914 template <typename T> void $decl[[foo]](T t);
1915 template <typename T> void bar(T t) { [[foo]](t); } // foo in bar is uninstantiated.
1916 void baz(int x) { [[f^oo]](x); }
1917 )cpp",
1918 R"cpp(
1919 namespace ns {
1920 struct S{};
1921 void $decl[[foo]](S s);
1922 } // namespace ns
1923 template <typename T> void foo(T t);
1924 // FIXME: Maybe report this foo as a ref to ns::foo (because of ADL)
1925 // when bar<ns::S> is instantiated?
1926 template <typename T> void bar(T t) { foo(t); }
1927 void baz(int x) {
1928 ns::S s;
1929 bar<ns::S>(s);
1930 [[f^oo]](s);
1931 }
1932 )cpp",
1933 };
1934 for (const char *Test : Tests)
1935 checkFindRefs(Test);
1936 }
1937
TEST(FindReferences,IncludeOverrides)1938 TEST(FindReferences, IncludeOverrides) {
1939 llvm::StringRef Test =
1940 R"cpp(
1941 class Base {
1942 public:
1943 virtual void $decl[[f^unc]]() = 0;
1944 };
1945 class Derived : public Base {
1946 public:
1947 void $overridedecl[[func]]() override;
1948 };
1949 void Derived::$overridedef[[func]]() {}
1950 void test(Derived* D) {
1951 D->func(); // No references to the overrides.
1952 })cpp";
1953 checkFindRefs(Test, /*UseIndex=*/true);
1954 }
1955
TEST(FindReferences,RefsToBaseMethod)1956 TEST(FindReferences, RefsToBaseMethod) {
1957 llvm::StringRef Test =
1958 R"cpp(
1959 class BaseBase {
1960 public:
1961 virtual void [[func]]();
1962 };
1963 class Base : public BaseBase {
1964 public:
1965 void [[func]]() override;
1966 };
1967 class Derived : public Base {
1968 public:
1969 void $decl[[fu^nc]]() override;
1970 };
1971 void test(BaseBase* BB, Base* B, Derived* D) {
1972 // refs to overridden methods in complete type hierarchy are reported.
1973 BB->[[func]]();
1974 B->[[func]]();
1975 D->[[func]]();
1976 })cpp";
1977 checkFindRefs(Test, /*UseIndex=*/true);
1978 }
1979
TEST(FindReferences,MainFileReferencesOnly)1980 TEST(FindReferences, MainFileReferencesOnly) {
1981 llvm::StringRef Test =
1982 R"cpp(
1983 void test() {
1984 int [[fo^o]] = 1;
1985 // refs not from main file should not be included.
1986 #include "foo.inc"
1987 })cpp";
1988
1989 Annotations Code(Test);
1990 auto TU = TestTU::withCode(Code.code());
1991 TU.AdditionalFiles["foo.inc"] = R"cpp(
1992 foo = 3;
1993 )cpp";
1994 auto AST = TU.build();
1995
1996 std::vector<Matcher<ReferencesResult::Reference>> ExpectedLocations;
1997 for (const auto &R : Code.ranges())
1998 ExpectedLocations.push_back(RangeIs(R));
1999 EXPECT_THAT(findReferences(AST, Code.point(), 0).References,
2000 ElementsAreArray(ExpectedLocations))
2001 << Test;
2002 }
2003
TEST(FindReferences,ExplicitSymbols)2004 TEST(FindReferences, ExplicitSymbols) {
2005 const char *Tests[] = {
2006 R"cpp(
2007 struct Foo { Foo* $decl[[self]]() const; };
2008 void f() {
2009 Foo foo;
2010 if (Foo* T = foo.[[^self]]()) {} // Foo member call expr.
2011 }
2012 )cpp",
2013
2014 R"cpp(
2015 struct Foo { Foo(int); };
2016 Foo f() {
2017 int $def[[b]];
2018 return [[^b]]; // Foo constructor expr.
2019 }
2020 )cpp",
2021
2022 R"cpp(
2023 struct Foo {};
2024 void g(Foo);
2025 Foo $decl[[f]]();
2026 void call() {
2027 g([[^f]]()); // Foo constructor expr.
2028 }
2029 )cpp",
2030
2031 R"cpp(
2032 void $decl[[foo]](int);
2033 void $decl[[foo]](double);
2034
2035 namespace ns {
2036 using ::$decl[[fo^o]];
2037 }
2038 )cpp",
2039
2040 R"cpp(
2041 struct X {
2042 operator bool();
2043 };
2044
2045 int test() {
2046 X $def[[a]];
2047 [[a]].operator bool();
2048 if ([[a^]]) {} // ignore implicit conversion-operator AST node
2049 }
2050 )cpp",
2051 };
2052 for (const char *Test : Tests)
2053 checkFindRefs(Test);
2054 }
2055
TEST(FindReferences,NeedsIndexForSymbols)2056 TEST(FindReferences, NeedsIndexForSymbols) {
2057 const char *Header = "int foo();";
2058 Annotations Main("int main() { [[f^oo]](); }");
2059 TestTU TU;
2060 TU.Code = std::string(Main.code());
2061 TU.HeaderCode = Header;
2062 auto AST = TU.build();
2063
2064 // References in main file are returned without index.
2065 EXPECT_THAT(
2066 findReferences(AST, Main.point(), 0, /*Index=*/nullptr).References,
2067 ElementsAre(RangeIs(Main.range())));
2068 Annotations IndexedMain(R"cpp(
2069 int [[foo]]() { return 42; }
2070 )cpp");
2071
2072 // References from indexed files are included.
2073 TestTU IndexedTU;
2074 IndexedTU.Code = std::string(IndexedMain.code());
2075 IndexedTU.Filename = "Indexed.cpp";
2076 IndexedTU.HeaderCode = Header;
2077 EXPECT_THAT(
2078 findReferences(AST, Main.point(), 0, IndexedTU.index().get()).References,
2079 ElementsAre(RangeIs(Main.range()),
2080 AllOf(RangeIs(IndexedMain.range()),
2081 AttrsAre(ReferencesResult::Declaration |
2082 ReferencesResult::Definition))));
2083 auto LimitRefs =
2084 findReferences(AST, Main.point(), /*Limit*/ 1, IndexedTU.index().get());
2085 EXPECT_EQ(1u, LimitRefs.References.size());
2086 EXPECT_TRUE(LimitRefs.HasMore);
2087
2088 // Avoid indexed results for the main file. Use AST for the mainfile.
2089 TU.Code = ("\n\n" + Main.code()).str();
2090 EXPECT_THAT(findReferences(AST, Main.point(), 0, TU.index().get()).References,
2091 ElementsAre(RangeIs(Main.range())));
2092 }
2093
TEST(FindReferences,NeedsIndexForMacro)2094 TEST(FindReferences, NeedsIndexForMacro) {
2095 const char *Header = "#define MACRO(X) (X+1)";
2096 Annotations Main(R"cpp(
2097 int main() {
2098 int a = [[MA^CRO]](1);
2099 }
2100 )cpp");
2101 TestTU TU;
2102 TU.Code = std::string(Main.code());
2103 TU.HeaderCode = Header;
2104 auto AST = TU.build();
2105
2106 // References in main file are returned without index.
2107 EXPECT_THAT(
2108 findReferences(AST, Main.point(), 0, /*Index=*/nullptr).References,
2109 ElementsAre(RangeIs(Main.range())));
2110
2111 Annotations IndexedMain(R"cpp(
2112 int indexed_main() {
2113 int a = [[MACRO]](1);
2114 }
2115 )cpp");
2116
2117 // References from indexed files are included.
2118 TestTU IndexedTU;
2119 IndexedTU.Code = std::string(IndexedMain.code());
2120 IndexedTU.Filename = "Indexed.cpp";
2121 IndexedTU.HeaderCode = Header;
2122 EXPECT_THAT(
2123 findReferences(AST, Main.point(), 0, IndexedTU.index().get()).References,
2124 ElementsAre(RangeIs(Main.range()), RangeIs(IndexedMain.range())));
2125 auto LimitRefs =
2126 findReferences(AST, Main.point(), /*Limit*/ 1, IndexedTU.index().get());
2127 EXPECT_EQ(1u, LimitRefs.References.size());
2128 EXPECT_TRUE(LimitRefs.HasMore);
2129 }
2130
TEST(FindReferences,NoQueryForLocalSymbols)2131 TEST(FindReferences, NoQueryForLocalSymbols) {
2132 struct RecordingIndex : public MemIndex {
2133 mutable Optional<llvm::DenseSet<SymbolID>> RefIDs;
2134 bool refs(const RefsRequest &Req,
2135 llvm::function_ref<void(const Ref &)>) const override {
2136 RefIDs = Req.IDs;
2137 return false;
2138 }
2139 };
2140
2141 struct Test {
2142 StringRef AnnotatedCode;
2143 bool WantQuery;
2144 } Tests[] = {
2145 {"int ^x;", true},
2146 // For now we don't assume header structure which would allow skipping.
2147 {"namespace { int ^x; }", true},
2148 {"static int ^x;", true},
2149 // Anything in a function certainly can't be referenced though.
2150 {"void foo() { int ^x; }", false},
2151 {"void foo() { struct ^x{}; }", false},
2152 {"auto lambda = []{ int ^x; };", false},
2153 };
2154 for (Test T : Tests) {
2155 Annotations File(T.AnnotatedCode);
2156 RecordingIndex Rec;
2157 auto AST = TestTU::withCode(File.code()).build();
2158 findReferences(AST, File.point(), 0, &Rec);
2159 if (T.WantQuery)
2160 EXPECT_NE(Rec.RefIDs, None) << T.AnnotatedCode;
2161 else
2162 EXPECT_EQ(Rec.RefIDs, None) << T.AnnotatedCode;
2163 }
2164 }
2165
TEST(GetNonLocalDeclRefs,All)2166 TEST(GetNonLocalDeclRefs, All) {
2167 struct Case {
2168 llvm::StringRef AnnotatedCode;
2169 std::vector<std::string> ExpectedDecls;
2170 } Cases[] = {
2171 {
2172 // VarDecl and ParamVarDecl
2173 R"cpp(
2174 void bar();
2175 void ^foo(int baz) {
2176 int x = 10;
2177 bar();
2178 })cpp",
2179 {"bar"},
2180 },
2181 {
2182 // Method from class
2183 R"cpp(
2184 class Foo { public: void foo(); };
2185 class Bar {
2186 void foo();
2187 void bar();
2188 };
2189 void Bar::^foo() {
2190 Foo f;
2191 bar();
2192 f.foo();
2193 })cpp",
2194 {"Bar", "Bar::bar", "Foo", "Foo::foo"},
2195 },
2196 {
2197 // Local types
2198 R"cpp(
2199 void ^foo() {
2200 class Foo { public: void foo() {} };
2201 class Bar { public: void bar() {} };
2202 Foo f;
2203 Bar b;
2204 b.bar();
2205 f.foo();
2206 })cpp",
2207 {},
2208 },
2209 {
2210 // Template params
2211 R"cpp(
2212 template <typename T, template<typename> class Q>
2213 void ^foo() {
2214 T x;
2215 Q<T> y;
2216 })cpp",
2217 {},
2218 },
2219 };
2220 for (const Case &C : Cases) {
2221 Annotations File(C.AnnotatedCode);
2222 auto AST = TestTU::withCode(File.code()).build();
2223 SourceLocation SL = llvm::cantFail(
2224 sourceLocationInMainFile(AST.getSourceManager(), File.point()));
2225
2226 const FunctionDecl *FD =
2227 llvm::dyn_cast<FunctionDecl>(&findDecl(AST, [SL](const NamedDecl &ND) {
2228 return ND.getLocation() == SL && llvm::isa<FunctionDecl>(ND);
2229 }));
2230 ASSERT_NE(FD, nullptr);
2231
2232 auto NonLocalDeclRefs = getNonLocalDeclRefs(AST, FD);
2233 std::vector<std::string> Names;
2234 for (const Decl *D : NonLocalDeclRefs) {
2235 if (const auto *ND = llvm::dyn_cast<NamedDecl>(D))
2236 Names.push_back(ND->getQualifiedNameAsString());
2237 }
2238 EXPECT_THAT(Names, UnorderedElementsAreArray(C.ExpectedDecls))
2239 << File.code();
2240 }
2241 }
2242
TEST(DocumentLinks,All)2243 TEST(DocumentLinks, All) {
2244 Annotations MainCpp(R"cpp(
2245 #/*comments*/include /*comments*/ $foo[["foo.h"]] //more comments
2246 int end_of_preamble = 0;
2247 #include $bar[[<bar.h>]]
2248 )cpp");
2249
2250 TestTU TU;
2251 TU.Code = std::string(MainCpp.code());
2252 TU.AdditionalFiles = {{"foo.h", ""}, {"bar.h", ""}};
2253 TU.ExtraArgs = {"-isystem."};
2254 auto AST = TU.build();
2255
2256 EXPECT_THAT(
2257 clangd::getDocumentLinks(AST),
2258 ElementsAre(
2259 DocumentLink({MainCpp.range("foo"),
2260 URIForFile::canonicalize(testPath("foo.h"), "")}),
2261 DocumentLink({MainCpp.range("bar"),
2262 URIForFile::canonicalize(testPath("bar.h"), "")})));
2263 }
2264
2265 } // namespace
2266 } // namespace clangd
2267 } // namespace clang
2268