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::ElementsAre;
41 using ::testing::Eq;
42 using ::testing::IsEmpty;
43 using ::testing::Matcher;
44 using ::testing::UnorderedElementsAreArray;
45
46 MATCHER_P2(FileRange, File, Range, "") {
47 return Location{URIForFile::canonicalize(File, testRoot()), Range} == arg;
48 }
49
50 // Extracts ranges from an annotated example, and constructs a matcher for a
51 // highlight set. Ranges should be named $read/$write as appropriate.
52 Matcher<const std::vector<DocumentHighlight> &>
HighlightsFrom(const Annotations & Test)53 HighlightsFrom(const Annotations &Test) {
54 std::vector<DocumentHighlight> Expected;
55 auto Add = [&](const Range &R, DocumentHighlightKind K) {
56 Expected.emplace_back();
57 Expected.back().range = R;
58 Expected.back().kind = K;
59 };
60 for (const auto &Range : Test.ranges())
61 Add(Range, DocumentHighlightKind::Text);
62 for (const auto &Range : Test.ranges("read"))
63 Add(Range, DocumentHighlightKind::Read);
64 for (const auto &Range : Test.ranges("write"))
65 Add(Range, DocumentHighlightKind::Write);
66 return UnorderedElementsAreArray(Expected);
67 }
68
TEST(HighlightsTest,All)69 TEST(HighlightsTest, All) {
70 const char *Tests[] = {
71 R"cpp(// Local variable
72 int main() {
73 int [[bonjour]];
74 $write[[^bonjour]] = 2;
75 int test1 = $read[[bonjour]];
76 }
77 )cpp",
78
79 R"cpp(// Struct
80 namespace ns1 {
81 struct [[MyClass]] {
82 static void foo([[MyClass]]*) {}
83 };
84 } // namespace ns1
85 int main() {
86 ns1::[[My^Class]]* Params;
87 }
88 )cpp",
89
90 R"cpp(// Function
91 int [[^foo]](int) {}
92 int main() {
93 [[foo]]([[foo]](42));
94 auto *X = &[[foo]];
95 }
96 )cpp",
97
98 R"cpp(// Function parameter in decl
99 void foo(int [[^bar]]);
100 )cpp",
101 R"cpp(// Not touching any identifiers.
102 struct Foo {
103 [[~]]Foo() {};
104 };
105 void foo() {
106 Foo f;
107 f.[[^~]]Foo();
108 }
109 )cpp",
110 };
111 for (const char *Test : Tests) {
112 Annotations T(Test);
113 auto AST = TestTU::withCode(T.code()).build();
114 EXPECT_THAT(findDocumentHighlights(AST, T.point()), HighlightsFrom(T))
115 << Test;
116 }
117 }
118
TEST(HighlightsTest,ControlFlow)119 TEST(HighlightsTest, ControlFlow) {
120 const char *Tests[] = {
121 R"cpp(
122 // Highlight same-function returns.
123 int fib(unsigned n) {
124 if (n <= 1) [[ret^urn]] 1;
125 [[return]] fib(n - 1) + fib(n - 2);
126
127 // Returns from other functions not highlighted.
128 auto Lambda = [] { return; };
129 class LocalClass { void x() { return; } };
130 }
131 )cpp",
132
133 R"cpp(
134 #define FAIL() return false
135 #define DO(x) { x; }
136 bool foo(int n) {
137 if (n < 0) [[FAIL]]();
138 DO([[re^turn]] true)
139 }
140 )cpp",
141
142 R"cpp(
143 // Highlight loop control flow
144 int magic() {
145 int counter = 0;
146 [[^for]] (char c : "fruit loops!") {
147 if (c == ' ') [[continue]];
148 counter += c;
149 if (c == '!') [[break]];
150 if (c == '?') [[return]] -1;
151 }
152 return counter;
153 }
154 )cpp",
155
156 R"cpp(
157 // Highlight loop and same-loop control flow
158 void nonsense() {
159 [[while]] (true) {
160 if (false) [[bre^ak]];
161 switch (1) break;
162 [[continue]];
163 }
164 }
165 )cpp",
166
167 R"cpp(
168 // Highlight switch for break (but not other breaks).
169 void describe(unsigned n) {
170 [[switch]](n) {
171 case 0:
172 break;
173 [[default]]:
174 [[^break]];
175 }
176 }
177 )cpp",
178
179 R"cpp(
180 // Highlight case and exits for switch-break (but not other cases).
181 void describe(unsigned n) {
182 [[switch]](n) {
183 case 0:
184 break;
185 [[case]] 1:
186 [[default]]:
187 [[return]];
188 [[^break]];
189 }
190 }
191 )cpp",
192
193 R"cpp(
194 // Highlight exits and switch for case
195 void describe(unsigned n) {
196 [[switch]](n) {
197 case 0:
198 break;
199 [[case]] 1:
200 [[d^efault]]:
201 [[return]];
202 [[break]];
203 }
204 }
205 )cpp",
206
207 R"cpp(
208 // Highlight nothing for switch.
209 void describe(unsigned n) {
210 s^witch(n) {
211 case 0:
212 break;
213 case 1:
214 default:
215 return;
216 break;
217 }
218 }
219 )cpp",
220
221 R"cpp(
222 // FIXME: match exception type against catch blocks
223 int catchy() {
224 try { // wrong: highlight try with matching catch
225 try { // correct: has no matching catch
226 [[thr^ow]] "oh no!";
227 } catch (int) { } // correct: catch doesn't match type
228 [[return]] -1; // correct: exits the matching catch
229 } catch (const char*) { } // wrong: highlight matching catch
230 [[return]] 42; // wrong: throw doesn't exit function
231 }
232 )cpp",
233
234 R"cpp(
235 // Loop highlights goto exiting the loop, but not jumping within it.
236 void jumpy() {
237 [[wh^ile]](1) {
238 up:
239 if (0) [[goto]] out;
240 goto up;
241 }
242 out: return;
243 }
244 )cpp",
245 };
246 for (const char *Test : Tests) {
247 Annotations T(Test);
248 auto TU = TestTU::withCode(T.code());
249 TU.ExtraArgs.push_back("-fexceptions"); // FIXME: stop testing on PS4.
250 auto AST = TU.build();
251 EXPECT_THAT(findDocumentHighlights(AST, T.point()), HighlightsFrom(T))
252 << Test;
253 }
254 }
255
256 MATCHER_P3(Sym, Name, Decl, DefOrNone, "") {
257 llvm::Optional<Range> Def = DefOrNone;
258 if (Name != arg.Name) {
259 *result_listener << "Name is " << arg.Name;
260 return false;
261 }
262 if (Decl != arg.PreferredDeclaration.range) {
263 *result_listener << "Declaration is "
264 << llvm::to_string(arg.PreferredDeclaration);
265 return false;
266 }
267 if (Def && !arg.Definition) {
268 *result_listener << "Has no definition";
269 return false;
270 }
271 if (Def && arg.Definition->range != *Def) {
272 *result_listener << "Definition is " << llvm::to_string(arg.Definition);
273 return false;
274 }
275 return true;
276 }
Sym(std::string Name,Range Decl)277 ::testing::Matcher<LocatedSymbol> Sym(std::string Name, Range Decl) {
278 return Sym(Name, Decl, llvm::None);
279 }
280 MATCHER_P(Sym, Name, "") { return arg.Name == Name; }
281
282 MATCHER_P(RangeIs, R, "") { return arg.range == R; }
283
TEST(LocateSymbol,WithIndex)284 TEST(LocateSymbol, WithIndex) {
285 Annotations SymbolHeader(R"cpp(
286 class $forward[[Forward]];
287 class $foo[[Foo]] {};
288
289 void $f1[[f1]]();
290
291 inline void $f2[[f2]]() {}
292 )cpp");
293 Annotations SymbolCpp(R"cpp(
294 class $forward[[forward]] {};
295 void $f1[[f1]]() {}
296 )cpp");
297
298 TestTU TU;
299 TU.Code = std::string(SymbolCpp.code());
300 TU.HeaderCode = std::string(SymbolHeader.code());
301 auto Index = TU.index();
302 auto LocateWithIndex = [&Index](const Annotations &Main) {
303 auto AST = TestTU::withCode(Main.code()).build();
304 return clangd::locateSymbolAt(AST, Main.point(), Index.get());
305 };
306
307 Annotations Test(R"cpp(// only declaration in AST.
308 void [[f1]]();
309 int main() {
310 ^f1();
311 }
312 )cpp");
313 EXPECT_THAT(LocateWithIndex(Test),
314 ElementsAre(Sym("f1", Test.range(), SymbolCpp.range("f1"))));
315
316 Test = Annotations(R"cpp(// definition in AST.
317 void [[f1]]() {}
318 int main() {
319 ^f1();
320 }
321 )cpp");
322 EXPECT_THAT(LocateWithIndex(Test),
323 ElementsAre(Sym("f1", SymbolHeader.range("f1"), Test.range())));
324
325 Test = Annotations(R"cpp(// forward declaration in AST.
326 class [[Foo]];
327 F^oo* create();
328 )cpp");
329 EXPECT_THAT(LocateWithIndex(Test),
330 ElementsAre(Sym("Foo", Test.range(), SymbolHeader.range("foo"))));
331
332 Test = Annotations(R"cpp(// definition in AST.
333 class [[Forward]] {};
334 F^orward create();
335 )cpp");
336 EXPECT_THAT(
337 LocateWithIndex(Test),
338 ElementsAre(Sym("Forward", SymbolHeader.range("forward"), Test.range())));
339 }
340
TEST(LocateSymbol,WithIndexPreferredLocation)341 TEST(LocateSymbol, WithIndexPreferredLocation) {
342 Annotations SymbolHeader(R"cpp(
343 class $p[[Proto]] {};
344 void $f[[func]]() {};
345 )cpp");
346 TestTU TU;
347 TU.HeaderCode = std::string(SymbolHeader.code());
348 TU.HeaderFilename = "x.proto"; // Prefer locations in codegen files.
349 auto Index = TU.index();
350
351 Annotations Test(R"cpp(// only declaration in AST.
352 // Shift to make range different.
353 class Proto;
354 void func() {}
355 P$p^roto* create() {
356 fu$f^nc();
357 return nullptr;
358 }
359 )cpp");
360
361 auto AST = TestTU::withCode(Test.code()).build();
362 {
363 auto Locs = clangd::locateSymbolAt(AST, Test.point("p"), Index.get());
364 auto CodeGenLoc = SymbolHeader.range("p");
365 EXPECT_THAT(Locs, ElementsAre(Sym("Proto", CodeGenLoc, CodeGenLoc)));
366 }
367 {
368 auto Locs = clangd::locateSymbolAt(AST, Test.point("f"), Index.get());
369 auto CodeGenLoc = SymbolHeader.range("f");
370 EXPECT_THAT(Locs, ElementsAre(Sym("func", CodeGenLoc, CodeGenLoc)));
371 }
372 }
373
TEST(LocateSymbol,All)374 TEST(LocateSymbol, All) {
375 // Ranges in tests:
376 // $decl is the declaration location (if absent, no symbol is located)
377 // $def is the definition location (if absent, symbol has no definition)
378 // unnamed range becomes both $decl and $def.
379 const char *Tests[] = {
380 R"cpp(// Local variable
381 int main() {
382 int [[bonjour]];
383 ^bonjour = 2;
384 int test1 = bonjour;
385 }
386 )cpp",
387
388 R"cpp(// Struct
389 namespace ns1 {
390 struct [[MyClass]] {};
391 } // namespace ns1
392 int main() {
393 ns1::My^Class* Params;
394 }
395 )cpp",
396
397 R"cpp(// Function definition via pointer
398 void [[foo]](int) {}
399 int main() {
400 auto *X = &^foo;
401 }
402 )cpp",
403
404 R"cpp(// Function declaration via call
405 int $decl[[foo]](int);
406 int main() {
407 return ^foo(42);
408 }
409 )cpp",
410
411 R"cpp(// Field
412 struct Foo { int [[x]]; };
413 int main() {
414 Foo bar;
415 (void)bar.^x;
416 }
417 )cpp",
418
419 R"cpp(// Field, member initializer
420 struct Foo {
421 int [[x]];
422 Foo() : ^x(0) {}
423 };
424 )cpp",
425
426 R"cpp(// Field, field designator
427 struct Foo { int [[x]]; };
428 int main() {
429 Foo bar = { .^x = 2 };
430 }
431 )cpp",
432
433 R"cpp(// Method call
434 struct Foo { int $decl[[x]](); };
435 int main() {
436 Foo bar;
437 bar.^x();
438 }
439 )cpp",
440
441 R"cpp(// Typedef
442 typedef int $decl[[Foo]];
443 int main() {
444 ^Foo bar;
445 }
446 )cpp",
447
448 R"cpp(// Template type parameter
449 template <typename [[T]]>
450 void foo() { ^T t; }
451 )cpp",
452
453 R"cpp(// Template template type parameter
454 template <template<typename> class [[T]]>
455 void foo() { ^T<int> t; }
456 )cpp",
457
458 R"cpp(// Namespace
459 namespace $decl[[ns]] {
460 struct Foo { static void bar(); };
461 } // namespace ns
462 int main() { ^ns::Foo::bar(); }
463 )cpp",
464
465 R"cpp(// Macro
466 class TTT { public: int a; };
467 #define [[FF]](S) if (int b = S.a) {}
468 void f() {
469 TTT t;
470 F^F(t);
471 }
472 )cpp",
473
474 R"cpp(// Macro argument
475 int [[i]];
476 #define ADDRESSOF(X) &X;
477 int *j = ADDRESSOF(^i);
478 )cpp",
479 R"cpp(// Macro argument appearing multiple times in expansion
480 #define VALIDATE_TYPE(x) (void)x;
481 #define ASSERT(expr) \
482 do { \
483 VALIDATE_TYPE(expr); \
484 if (!expr); \
485 } while (false)
486 bool [[waldo]]() { return true; }
487 void foo() {
488 ASSERT(wa^ldo());
489 }
490 )cpp",
491 R"cpp(// Symbol concatenated inside macro (not supported)
492 int *pi;
493 #define POINTER(X) p ## X;
494 int x = *POINTER(^i);
495 )cpp",
496
497 R"cpp(// Forward class declaration
498 class $decl[[Foo]];
499 class $def[[Foo]] {};
500 F^oo* foo();
501 )cpp",
502
503 R"cpp(// Function declaration
504 void $decl[[foo]]();
505 void g() { f^oo(); }
506 void $def[[foo]]() {}
507 )cpp",
508
509 R"cpp(
510 #define FF(name) class name##_Test {};
511 [[FF]](my);
512 void f() { my^_Test a; }
513 )cpp",
514
515 R"cpp(
516 #define FF() class [[Test]] {};
517 FF();
518 void f() { T^est a; }
519 )cpp",
520
521 R"cpp(// explicit template specialization
522 template <typename T>
523 struct Foo { void bar() {} };
524
525 template <>
526 struct [[Foo]]<int> { void bar() {} };
527
528 void foo() {
529 Foo<char> abc;
530 Fo^o<int> b;
531 }
532 )cpp",
533
534 R"cpp(// implicit template specialization
535 template <typename T>
536 struct [[Foo]] { void bar() {} };
537 template <>
538 struct Foo<int> { void bar() {} };
539 void foo() {
540 Fo^o<char> abc;
541 Foo<int> b;
542 }
543 )cpp",
544
545 R"cpp(// partial template specialization
546 template <typename T>
547 struct Foo { void bar() {} };
548 template <typename T>
549 struct [[Foo]]<T*> { void bar() {} };
550 ^Foo<int*> x;
551 )cpp",
552
553 R"cpp(// function template specializations
554 template <class T>
555 void foo(T) {}
556 template <>
557 void [[foo]](int) {}
558 void bar() {
559 fo^o(10);
560 }
561 )cpp",
562
563 R"cpp(// variable template decls
564 template <class T>
565 T var = T();
566
567 template <>
568 double [[var]]<int> = 10;
569
570 double y = va^r<int>;
571 )cpp",
572
573 R"cpp(// No implicit constructors
574 struct X {
575 X(X&& x) = default;
576 };
577 X $decl[[makeX]]();
578 void foo() {
579 auto x = m^akeX();
580 }
581 )cpp",
582
583 R"cpp(
584 struct X {
585 X& $decl[[operator]]++();
586 };
587 void foo(X& x) {
588 +^+x;
589 }
590 )cpp",
591
592 R"cpp(
593 struct S1 { void f(); };
594 struct S2 { S1 * $decl[[operator]]->(); };
595 void test(S2 s2) {
596 s2-^>f();
597 }
598 )cpp",
599
600 R"cpp(// Declaration of explicit template specialization
601 template <typename T>
602 struct $decl[[Foo]] {};
603
604 template <>
605 struct Fo^o<int> {};
606 )cpp",
607
608 R"cpp(// Declaration of partial template specialization
609 template <typename T>
610 struct $decl[[Foo]] {};
611
612 template <typename T>
613 struct Fo^o<T*> {};
614 )cpp",
615
616 R"cpp(// Override specifier jumps to overridden method
617 class Y { virtual void $decl[[a]]() = 0; };
618 class X : Y { void a() ^override {} };
619 )cpp",
620
621 R"cpp(// Final specifier jumps to overridden method
622 class Y { virtual void $decl[[a]]() = 0; };
623 class X : Y { void a() ^final {} };
624 )cpp",
625
626 R"cpp(// Heuristic resolution of dependent method
627 template <typename T>
628 struct S {
629 void [[bar]]() {}
630 };
631
632 template <typename T>
633 void foo(S<T> arg) {
634 arg.ba^r();
635 }
636 )cpp",
637
638 R"cpp(// Heuristic resolution of dependent method via this->
639 template <typename T>
640 struct S {
641 void [[foo]]() {
642 this->fo^o();
643 }
644 };
645 )cpp",
646
647 R"cpp(// Heuristic resolution of dependent static method
648 template <typename T>
649 struct S {
650 static void [[bar]]() {}
651 };
652
653 template <typename T>
654 void foo() {
655 S<T>::ba^r();
656 }
657 )cpp",
658
659 R"cpp(// Heuristic resolution of dependent method
660 // invoked via smart pointer
661 template <typename> struct S { void [[foo]]() {} };
662 template <typename T> struct unique_ptr {
663 T* operator->();
664 };
665 template <typename T>
666 void test(unique_ptr<S<T>>& V) {
667 V->fo^o();
668 }
669 )cpp",
670
671 R"cpp(// Heuristic resolution of dependent enumerator
672 template <typename T>
673 struct Foo {
674 enum class E { [[A]], B };
675 E e = E::A^;
676 };
677 )cpp"};
678 for (const char *Test : Tests) {
679 Annotations T(Test);
680 llvm::Optional<Range> WantDecl;
681 llvm::Optional<Range> WantDef;
682 if (!T.ranges().empty())
683 WantDecl = WantDef = T.range();
684 if (!T.ranges("decl").empty())
685 WantDecl = T.range("decl");
686 if (!T.ranges("def").empty())
687 WantDef = T.range("def");
688
689 TestTU TU;
690 TU.Code = std::string(T.code());
691
692 // FIXME: Auto-completion in a template requires disabling delayed template
693 // parsing.
694 TU.ExtraArgs.push_back("-fno-delayed-template-parsing");
695
696 auto AST = TU.build();
697 auto Results = locateSymbolAt(AST, T.point());
698
699 if (!WantDecl) {
700 EXPECT_THAT(Results, IsEmpty()) << Test;
701 } else {
702 ASSERT_THAT(Results, ::testing::SizeIs(1)) << Test;
703 EXPECT_EQ(Results[0].PreferredDeclaration.range, *WantDecl) << Test;
704 llvm::Optional<Range> GotDef;
705 if (Results[0].Definition)
706 GotDef = Results[0].Definition->range;
707 EXPECT_EQ(WantDef, GotDef) << Test;
708 }
709 }
710 }
711
712 // LocateSymbol test cases that produce warnings.
713 // These are separated out from All so that in All we can assert
714 // that there are no diagnostics.
TEST(LocateSymbol,Warnings)715 TEST(LocateSymbol, Warnings) {
716 const char *Tests[] = {
717 R"cpp(// Field, GNU old-style field designator
718 struct Foo { int [[x]]; };
719 int main() {
720 Foo bar = { ^x : 1 };
721 }
722 )cpp",
723
724 R"cpp(// Macro
725 #define MACRO 0
726 #define [[MACRO]] 1
727 int main() { return ^MACRO; }
728 #define MACRO 2
729 #undef macro
730 )cpp",
731 };
732
733 for (const char *Test : Tests) {
734 Annotations T(Test);
735 llvm::Optional<Range> WantDecl;
736 llvm::Optional<Range> WantDef;
737 if (!T.ranges().empty())
738 WantDecl = WantDef = T.range();
739 if (!T.ranges("decl").empty())
740 WantDecl = T.range("decl");
741 if (!T.ranges("def").empty())
742 WantDef = T.range("def");
743
744 TestTU TU;
745 TU.Code = std::string(T.code());
746
747 auto AST = TU.build();
748 auto Results = locateSymbolAt(AST, T.point());
749
750 if (!WantDecl) {
751 EXPECT_THAT(Results, IsEmpty()) << Test;
752 } else {
753 ASSERT_THAT(Results, ::testing::SizeIs(1)) << Test;
754 EXPECT_EQ(Results[0].PreferredDeclaration.range, *WantDecl) << Test;
755 llvm::Optional<Range> GotDef;
756 if (Results[0].Definition)
757 GotDef = Results[0].Definition->range;
758 EXPECT_EQ(WantDef, GotDef) << Test;
759 }
760 }
761 }
762
TEST(LocateSymbol,TextualSmoke)763 TEST(LocateSymbol, TextualSmoke) {
764 auto T = Annotations(
765 R"cpp(
766 struct [[MyClass]] {};
767 // Comment mentioning M^yClass
768 )cpp");
769
770 auto TU = TestTU::withCode(T.code());
771 auto AST = TU.build();
772 auto Index = TU.index();
773 EXPECT_THAT(locateSymbolAt(AST, T.point(), Index.get()),
774 ElementsAre(Sym("MyClass", T.range())));
775 }
776
TEST(LocateSymbol,Textual)777 TEST(LocateSymbol, Textual) {
778 const char *Tests[] = {
779 R"cpp(// Comment
780 struct [[MyClass]] {};
781 // Comment mentioning M^yClass
782 )cpp",
783 R"cpp(// String
784 struct MyClass {};
785 // Not triggered for string literal tokens.
786 const char* s = "String literal mentioning M^yClass";
787 )cpp",
788 R"cpp(// Ifdef'ed out code
789 struct [[MyClass]] {};
790 #ifdef WALDO
791 M^yClass var;
792 #endif
793 )cpp",
794 R"cpp(// Macro definition
795 struct [[MyClass]] {};
796 #define DECLARE_MYCLASS_OBJ(name) M^yClass name;
797 )cpp",
798 R"cpp(// Invalid code
799 /*error-ok*/
800 int myFunction(int);
801 // Not triggered for token which survived preprocessing.
802 int var = m^yFunction();
803 )cpp"};
804
805 for (const char *Test : Tests) {
806 Annotations T(Test);
807 llvm::Optional<Range> WantDecl;
808 if (!T.ranges().empty())
809 WantDecl = T.range();
810
811 auto TU = TestTU::withCode(T.code());
812
813 auto AST = TU.build();
814 auto Index = TU.index();
815 auto Word = SpelledWord::touching(
816 cantFail(sourceLocationInMainFile(AST.getSourceManager(), T.point())),
817 AST.getTokens(), AST.getLangOpts());
818 if (!Word) {
819 ADD_FAILURE() << "No word touching point!" << Test;
820 continue;
821 }
822 auto Results = locateSymbolTextually(*Word, AST, Index.get(),
823 testPath(TU.Filename), ASTNodeKind());
824
825 if (!WantDecl) {
826 EXPECT_THAT(Results, IsEmpty()) << Test;
827 } else {
828 ASSERT_THAT(Results, ::testing::SizeIs(1)) << Test;
829 EXPECT_EQ(Results[0].PreferredDeclaration.range, *WantDecl) << Test;
830 }
831 }
832 } // namespace
833
TEST(LocateSymbol,Ambiguous)834 TEST(LocateSymbol, Ambiguous) {
835 auto T = Annotations(R"cpp(
836 struct Foo {
837 Foo();
838 Foo(Foo&&);
839 $ConstructorLoc[[Foo]](const char*);
840 };
841
842 Foo f();
843
844 void g(Foo foo);
845
846 void call() {
847 const char* str = "123";
848 Foo a = $1^str;
849 Foo b = Foo($2^str);
850 Foo c = $3^f();
851 $4^g($5^f());
852 g($6^str);
853 Foo ab$7^c;
854 Foo ab$8^cd("asdf");
855 Foo foox = Fo$9^o("asdf");
856 Foo abcde$10^("asdf");
857 Foo foox2 = Foo$11^("asdf");
858 }
859
860 template <typename T>
861 struct S {
862 void $NonstaticOverload1[[bar]](int);
863 void $NonstaticOverload2[[bar]](float);
864
865 static void $StaticOverload1[[baz]](int);
866 static void $StaticOverload2[[baz]](float);
867 };
868
869 template <typename T, typename U>
870 void dependent_call(S<T> s, U u) {
871 s.ba$12^r(u);
872 S<T>::ba$13^z(u);
873 }
874 )cpp");
875 auto TU = TestTU::withCode(T.code());
876 // FIXME: Go-to-definition in a template requires disabling delayed template
877 // parsing.
878 TU.ExtraArgs.push_back("-fno-delayed-template-parsing");
879 auto AST = TU.build();
880 // Ordered assertions are deliberate: we expect a predictable order.
881 EXPECT_THAT(locateSymbolAt(AST, T.point("1")), ElementsAre(Sym("str")));
882 EXPECT_THAT(locateSymbolAt(AST, T.point("2")), ElementsAre(Sym("str")));
883 EXPECT_THAT(locateSymbolAt(AST, T.point("3")), ElementsAre(Sym("f")));
884 EXPECT_THAT(locateSymbolAt(AST, T.point("4")), ElementsAre(Sym("g")));
885 EXPECT_THAT(locateSymbolAt(AST, T.point("5")), ElementsAre(Sym("f")));
886 EXPECT_THAT(locateSymbolAt(AST, T.point("6")), ElementsAre(Sym("str")));
887 // FIXME: Target the constructor as well.
888 EXPECT_THAT(locateSymbolAt(AST, T.point("7")), ElementsAre(Sym("abc")));
889 // FIXME: Target the constructor as well.
890 EXPECT_THAT(locateSymbolAt(AST, T.point("8")), ElementsAre(Sym("abcd")));
891 // FIXME: Target the constructor as well.
892 EXPECT_THAT(locateSymbolAt(AST, T.point("9")), ElementsAre(Sym("Foo")));
893 EXPECT_THAT(locateSymbolAt(AST, T.point("10")),
894 ElementsAre(Sym("Foo", T.range("ConstructorLoc"))));
895 EXPECT_THAT(locateSymbolAt(AST, T.point("11")),
896 ElementsAre(Sym("Foo", T.range("ConstructorLoc"))));
897 // These assertions are unordered because the order comes from
898 // CXXRecordDecl::lookupDependentName() which doesn't appear to provide
899 // an order guarantee.
900 EXPECT_THAT(locateSymbolAt(AST, T.point("12")),
901 UnorderedElementsAre(Sym("bar", T.range("NonstaticOverload1")),
902 Sym("bar", T.range("NonstaticOverload2"))));
903 EXPECT_THAT(locateSymbolAt(AST, T.point("13")),
904 UnorderedElementsAre(Sym("baz", T.range("StaticOverload1")),
905 Sym("baz", T.range("StaticOverload2"))));
906 }
907
TEST(LocateSymbol,TextualDependent)908 TEST(LocateSymbol, TextualDependent) {
909 // Put the declarations in the header to make sure we are
910 // finding them via the index heuristic and not the
911 // nearby-ident heuristic.
912 Annotations Header(R"cpp(
913 struct Foo {
914 void $FooLoc[[uniqueMethodName]]();
915 };
916 struct Bar {
917 void $BarLoc[[uniqueMethodName]]();
918 };
919 )cpp");
920 Annotations Source(R"cpp(
921 template <typename T>
922 void f(T t) {
923 t.u^niqueMethodName();
924 }
925 )cpp");
926 TestTU TU;
927 TU.Code = std::string(Source.code());
928 TU.HeaderCode = std::string(Header.code());
929 auto AST = TU.build();
930 auto Index = TU.index();
931 // Need to use locateSymbolAt() since we are testing an
932 // interaction between locateASTReferent() and
933 // locateSymbolNamedTextuallyAt().
934 auto Results = locateSymbolAt(AST, Source.point(), Index.get());
935 EXPECT_THAT(Results, UnorderedElementsAre(
936 Sym("uniqueMethodName", Header.range("FooLoc")),
937 Sym("uniqueMethodName", Header.range("BarLoc"))));
938 }
939
TEST(LocateSymbol,TemplateTypedefs)940 TEST(LocateSymbol, TemplateTypedefs) {
941 auto T = Annotations(R"cpp(
942 template <class T> struct function {};
943 template <class T> using callback = function<T()>;
944
945 c^allback<int> foo;
946 )cpp");
947 auto AST = TestTU::withCode(T.code()).build();
948 EXPECT_THAT(locateSymbolAt(AST, T.point()), ElementsAre(Sym("callback")));
949 }
950
TEST(LocateSymbol,RelPathsInCompileCommand)951 TEST(LocateSymbol, RelPathsInCompileCommand) {
952 // The source is in "/clangd-test/src".
953 // We build in "/clangd-test/build".
954
955 Annotations SourceAnnotations(R"cpp(
956 #include "header_in_preamble.h"
957 int [[foo]];
958 #include "header_not_in_preamble.h"
959 int baz = f$p1^oo + bar_pre$p2^amble + bar_not_pre$p3^amble;
960 )cpp");
961
962 Annotations HeaderInPreambleAnnotations(R"cpp(
963 int [[bar_preamble]];
964 )cpp");
965
966 Annotations HeaderNotInPreambleAnnotations(R"cpp(
967 int [[bar_not_preamble]];
968 )cpp");
969
970 // Make the compilation paths appear as ../src/foo.cpp in the compile
971 // commands.
972 SmallString<32> RelPathPrefix("..");
973 llvm::sys::path::append(RelPathPrefix, "src");
974 std::string BuildDir = testPath("build");
975 MockCompilationDatabase CDB(BuildDir, RelPathPrefix);
976
977 MockFS FS;
978 ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
979
980 // Fill the filesystem.
981 auto FooCpp = testPath("src/foo.cpp");
982 FS.Files[FooCpp] = "";
983 auto HeaderInPreambleH = testPath("src/header_in_preamble.h");
984 FS.Files[HeaderInPreambleH] = std::string(HeaderInPreambleAnnotations.code());
985 auto HeaderNotInPreambleH = testPath("src/header_not_in_preamble.h");
986 FS.Files[HeaderNotInPreambleH] =
987 std::string(HeaderNotInPreambleAnnotations.code());
988
989 runAddDocument(Server, FooCpp, SourceAnnotations.code());
990
991 // Go to a definition in main source file.
992 auto Locations =
993 runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("p1"));
994 EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error";
995 EXPECT_THAT(*Locations, ElementsAre(Sym("foo", SourceAnnotations.range())));
996
997 // Go to a definition in header_in_preamble.h.
998 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("p2"));
999 EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error";
1000 EXPECT_THAT(
1001 *Locations,
1002 ElementsAre(Sym("bar_preamble", HeaderInPreambleAnnotations.range())));
1003
1004 // Go to a definition in header_not_in_preamble.h.
1005 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("p3"));
1006 EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error";
1007 EXPECT_THAT(*Locations,
1008 ElementsAre(Sym("bar_not_preamble",
1009 HeaderNotInPreambleAnnotations.range())));
1010 }
1011
TEST(GoToInclude,All)1012 TEST(GoToInclude, All) {
1013 MockFS FS;
1014 MockCompilationDatabase CDB;
1015 ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
1016
1017 auto FooCpp = testPath("foo.cpp");
1018 const char *SourceContents = R"cpp(
1019 #include ^"$2^foo.h$3^"
1020 #include "$4^invalid.h"
1021 int b = a;
1022 // test
1023 int foo;
1024 #in$5^clude "$6^foo.h"$7^
1025 )cpp";
1026 Annotations SourceAnnotations(SourceContents);
1027 FS.Files[FooCpp] = std::string(SourceAnnotations.code());
1028 auto FooH = testPath("foo.h");
1029
1030 const char *HeaderContents = R"cpp([[]]#pragma once
1031 int a;
1032 )cpp";
1033 Annotations HeaderAnnotations(HeaderContents);
1034 FS.Files[FooH] = std::string(HeaderAnnotations.code());
1035
1036 Server.addDocument(FooH, HeaderAnnotations.code());
1037 Server.addDocument(FooCpp, SourceAnnotations.code());
1038
1039 // Test include in preamble.
1040 auto Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point());
1041 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1042 EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range())));
1043
1044 // Test include in preamble, last char.
1045 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("2"));
1046 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1047 EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range())));
1048
1049 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("3"));
1050 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1051 EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range())));
1052
1053 // Test include outside of preamble.
1054 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("6"));
1055 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1056 EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range())));
1057
1058 // Test a few positions that do not result in Locations.
1059 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("4"));
1060 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1061 EXPECT_THAT(*Locations, IsEmpty());
1062
1063 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("5"));
1064 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1065 EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range())));
1066
1067 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("7"));
1068 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1069 EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range())));
1070
1071 // Objective C #import directive.
1072 Annotations ObjC(R"objc(
1073 #import "^foo.h"
1074 )objc");
1075 auto FooM = testPath("foo.m");
1076 FS.Files[FooM] = std::string(ObjC.code());
1077
1078 Server.addDocument(FooM, ObjC.code());
1079 Locations = runLocateSymbolAt(Server, FooM, ObjC.point());
1080 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1081 EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range())));
1082 }
1083
TEST(LocateSymbol,WithPreamble)1084 TEST(LocateSymbol, WithPreamble) {
1085 // Test stragety: AST should always use the latest preamble instead of last
1086 // good preamble.
1087 MockFS FS;
1088 MockCompilationDatabase CDB;
1089 ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
1090
1091 auto FooCpp = testPath("foo.cpp");
1092 // The trigger locations must be the same.
1093 Annotations FooWithHeader(R"cpp(#include "fo^o.h")cpp");
1094 Annotations FooWithoutHeader(R"cpp(double [[fo^o]]();)cpp");
1095
1096 FS.Files[FooCpp] = std::string(FooWithHeader.code());
1097
1098 auto FooH = testPath("foo.h");
1099 Annotations FooHeader(R"cpp([[]])cpp");
1100 FS.Files[FooH] = std::string(FooHeader.code());
1101
1102 runAddDocument(Server, FooCpp, FooWithHeader.code());
1103 // LocateSymbol goes to a #include file: the result comes from the preamble.
1104 EXPECT_THAT(
1105 cantFail(runLocateSymbolAt(Server, FooCpp, FooWithHeader.point())),
1106 ElementsAre(Sym("foo.h", FooHeader.range())));
1107
1108 // Only preamble is built, and no AST is built in this request.
1109 Server.addDocument(FooCpp, FooWithoutHeader.code(), "null",
1110 WantDiagnostics::No);
1111 // We build AST here, and it should use the latest preamble rather than the
1112 // stale one.
1113 EXPECT_THAT(
1114 cantFail(runLocateSymbolAt(Server, FooCpp, FooWithoutHeader.point())),
1115 ElementsAre(Sym("foo", FooWithoutHeader.range())));
1116
1117 // Reset test environment.
1118 runAddDocument(Server, FooCpp, FooWithHeader.code());
1119 // Both preamble and AST are built in this request.
1120 Server.addDocument(FooCpp, FooWithoutHeader.code(), "null",
1121 WantDiagnostics::Yes);
1122 // Use the AST being built in above request.
1123 EXPECT_THAT(
1124 cantFail(runLocateSymbolAt(Server, FooCpp, FooWithoutHeader.point())),
1125 ElementsAre(Sym("foo", FooWithoutHeader.range())));
1126 }
1127
TEST(LocateSymbol,NearbyTokenSmoke)1128 TEST(LocateSymbol, NearbyTokenSmoke) {
1129 auto T = Annotations(R"cpp(
1130 // prints e^rr and crashes
1131 void die(const char* [[err]]);
1132 )cpp");
1133 auto AST = TestTU::withCode(T.code()).build();
1134 // We don't pass an index, so can't hit index-based fallback.
1135 EXPECT_THAT(locateSymbolAt(AST, T.point()),
1136 ElementsAre(Sym("err", T.range())));
1137 }
1138
TEST(LocateSymbol,NearbyIdentifier)1139 TEST(LocateSymbol, NearbyIdentifier) {
1140 const char *Tests[] = {
1141 R"cpp(
1142 // regular identifiers (won't trigger)
1143 int hello;
1144 int y = he^llo;
1145 )cpp",
1146 R"cpp(
1147 // disabled preprocessor sections
1148 int [[hello]];
1149 #if 0
1150 int y = ^hello;
1151 #endif
1152 )cpp",
1153 R"cpp(
1154 // comments
1155 // he^llo, world
1156 int [[hello]];
1157 )cpp",
1158 R"cpp(
1159 // not triggered by string literals
1160 int hello;
1161 const char* greeting = "h^ello, world";
1162 )cpp",
1163
1164 R"cpp(
1165 // can refer to macro invocations
1166 #define INT int
1167 [[INT]] x;
1168 // I^NT
1169 )cpp",
1170
1171 R"cpp(
1172 // can refer to macro invocations (even if they expand to nothing)
1173 #define EMPTY
1174 [[EMPTY]] int x;
1175 // E^MPTY
1176 )cpp",
1177
1178 R"cpp(
1179 // prefer nearest occurrence, backwards is worse than forwards
1180 int hello;
1181 int x = hello;
1182 // h^ello
1183 int y = [[hello]];
1184 int z = hello;
1185 )cpp",
1186
1187 R"cpp(
1188 // short identifiers find near results
1189 int [[hi]];
1190 // h^i
1191 )cpp",
1192 R"cpp(
1193 // short identifiers don't find far results
1194 int hi;
1195
1196
1197
1198 // h^i
1199 )cpp",
1200 };
1201 for (const char *Test : Tests) {
1202 Annotations T(Test);
1203 auto AST = TestTU::withCode(T.code()).build();
1204 const auto &SM = AST.getSourceManager();
1205 llvm::Optional<Range> Nearby;
1206 auto Word =
1207 SpelledWord::touching(cantFail(sourceLocationInMainFile(SM, T.point())),
1208 AST.getTokens(), AST.getLangOpts());
1209 if (!Word) {
1210 ADD_FAILURE() << "No word at point! " << Test;
1211 continue;
1212 }
1213 if (const auto *Tok = findNearbyIdentifier(*Word, AST.getTokens()))
1214 Nearby = halfOpenToRange(SM, CharSourceRange::getCharRange(
1215 Tok->location(), Tok->endLocation()));
1216 if (T.ranges().empty())
1217 EXPECT_THAT(Nearby, Eq(llvm::None)) << Test;
1218 else
1219 EXPECT_EQ(Nearby, T.range()) << Test;
1220 }
1221 }
1222
TEST(FindReferences,WithinAST)1223 TEST(FindReferences, WithinAST) {
1224 const char *Tests[] = {
1225 R"cpp(// Local variable
1226 int main() {
1227 int [[foo]];
1228 [[^foo]] = 2;
1229 int test1 = [[foo]];
1230 }
1231 )cpp",
1232
1233 R"cpp(// Struct
1234 namespace ns1 {
1235 struct [[Foo]] {};
1236 } // namespace ns1
1237 int main() {
1238 ns1::[[Fo^o]]* Params;
1239 }
1240 )cpp",
1241
1242 R"cpp(// Forward declaration
1243 class [[Foo]];
1244 class [[Foo]] {};
1245 int main() {
1246 [[Fo^o]] foo;
1247 }
1248 )cpp",
1249
1250 R"cpp(// Function
1251 int [[foo]](int) {}
1252 int main() {
1253 auto *X = &[[^foo]];
1254 [[foo]](42);
1255 }
1256 )cpp",
1257
1258 R"cpp(// Field
1259 struct Foo {
1260 int [[foo]];
1261 Foo() : [[foo]](0) {}
1262 };
1263 int main() {
1264 Foo f;
1265 f.[[f^oo]] = 1;
1266 }
1267 )cpp",
1268
1269 R"cpp(// Method call
1270 struct Foo { int [[foo]](); };
1271 int Foo::[[foo]]() {}
1272 int main() {
1273 Foo f;
1274 f.[[^foo]]();
1275 }
1276 )cpp",
1277
1278 R"cpp(// Constructor
1279 struct Foo {
1280 [[F^oo]](int);
1281 };
1282 void foo() {
1283 Foo f = [[Foo]](42);
1284 }
1285 )cpp",
1286
1287 R"cpp(// Typedef
1288 typedef int [[Foo]];
1289 int main() {
1290 [[^Foo]] bar;
1291 }
1292 )cpp",
1293
1294 R"cpp(// Namespace
1295 namespace [[ns]] {
1296 struct Foo {};
1297 } // namespace ns
1298 int main() { [[^ns]]::Foo foo; }
1299 )cpp",
1300
1301 R"cpp(// Macros
1302 #define TYPE(X) X
1303 #define FOO Foo
1304 #define CAT(X, Y) X##Y
1305 class [[Fo^o]] {};
1306 void test() {
1307 TYPE([[Foo]]) foo;
1308 [[FOO]] foo2;
1309 TYPE(TYPE([[Foo]])) foo3;
1310 [[CAT]](Fo, o) foo4;
1311 }
1312 )cpp",
1313
1314 R"cpp(// Macros
1315 #define [[MA^CRO]](X) (X+1)
1316 void test() {
1317 int x = [[MACRO]]([[MACRO]](1));
1318 }
1319 )cpp",
1320
1321 R"cpp(
1322 int [[v^ar]] = 0;
1323 void foo(int s = [[var]]);
1324 )cpp",
1325
1326 R"cpp(
1327 template <typename T>
1328 class [[Fo^o]] {};
1329 void func([[Foo]]<int>);
1330 )cpp",
1331
1332 R"cpp(
1333 template <typename T>
1334 class [[Foo]] {};
1335 void func([[Fo^o]]<int>);
1336 )cpp",
1337 R"cpp(// Not touching any identifiers.
1338 struct Foo {
1339 [[~]]Foo() {};
1340 };
1341 void foo() {
1342 Foo f;
1343 f.[[^~]]Foo();
1344 }
1345 )cpp",
1346 };
1347 for (const char *Test : Tests) {
1348 Annotations T(Test);
1349 auto AST = TestTU::withCode(T.code()).build();
1350 std::vector<Matcher<Location>> ExpectedLocations;
1351 for (const auto &R : T.ranges())
1352 ExpectedLocations.push_back(RangeIs(R));
1353 EXPECT_THAT(findReferences(AST, T.point(), 0).References,
1354 ElementsAreArray(ExpectedLocations))
1355 << Test;
1356 }
1357 }
1358
TEST(FindReferences,MainFileReferencesOnly)1359 TEST(FindReferences, MainFileReferencesOnly) {
1360 llvm::StringRef Test =
1361 R"cpp(
1362 void test() {
1363 int [[fo^o]] = 1;
1364 // refs not from main file should not be included.
1365 #include "foo.inc"
1366 })cpp";
1367
1368 Annotations Code(Test);
1369 auto TU = TestTU::withCode(Code.code());
1370 TU.AdditionalFiles["foo.inc"] = R"cpp(
1371 foo = 3;
1372 )cpp";
1373 auto AST = TU.build();
1374
1375 std::vector<Matcher<Location>> ExpectedLocations;
1376 for (const auto &R : Code.ranges())
1377 ExpectedLocations.push_back(RangeIs(R));
1378 EXPECT_THAT(findReferences(AST, Code.point(), 0).References,
1379 ElementsAreArray(ExpectedLocations))
1380 << Test;
1381 }
1382
TEST(FindReferences,ExplicitSymbols)1383 TEST(FindReferences, ExplicitSymbols) {
1384 const char *Tests[] = {
1385 R"cpp(
1386 struct Foo { Foo* [[self]]() const; };
1387 void f() {
1388 Foo foo;
1389 if (Foo* T = foo.[[^self]]()) {} // Foo member call expr.
1390 }
1391 )cpp",
1392
1393 R"cpp(
1394 struct Foo { Foo(int); };
1395 Foo f() {
1396 int [[b]];
1397 return [[^b]]; // Foo constructor expr.
1398 }
1399 )cpp",
1400
1401 R"cpp(
1402 struct Foo {};
1403 void g(Foo);
1404 Foo [[f]]();
1405 void call() {
1406 g([[^f]]()); // Foo constructor expr.
1407 }
1408 )cpp",
1409
1410 R"cpp(
1411 void [[foo]](int);
1412 void [[foo]](double);
1413
1414 namespace ns {
1415 using ::[[fo^o]];
1416 }
1417 )cpp",
1418
1419 R"cpp(
1420 struct X {
1421 operator bool();
1422 };
1423
1424 int test() {
1425 X [[a]];
1426 [[a]].operator bool();
1427 if ([[a^]]) {} // ignore implicit conversion-operator AST node
1428 }
1429 )cpp",
1430 };
1431 for (const char *Test : Tests) {
1432 Annotations T(Test);
1433 auto AST = TestTU::withCode(T.code()).build();
1434 std::vector<Matcher<Location>> ExpectedLocations;
1435 for (const auto &R : T.ranges())
1436 ExpectedLocations.push_back(RangeIs(R));
1437 ASSERT_THAT(ExpectedLocations, Not(IsEmpty()));
1438 EXPECT_THAT(findReferences(AST, T.point(), 0).References,
1439 ElementsAreArray(ExpectedLocations))
1440 << Test;
1441 }
1442 }
1443
TEST(FindReferences,NeedsIndexForSymbols)1444 TEST(FindReferences, NeedsIndexForSymbols) {
1445 const char *Header = "int foo();";
1446 Annotations Main("int main() { [[f^oo]](); }");
1447 TestTU TU;
1448 TU.Code = std::string(Main.code());
1449 TU.HeaderCode = Header;
1450 auto AST = TU.build();
1451
1452 // References in main file are returned without index.
1453 EXPECT_THAT(
1454 findReferences(AST, Main.point(), 0, /*Index=*/nullptr).References,
1455 ElementsAre(RangeIs(Main.range())));
1456 Annotations IndexedMain(R"cpp(
1457 int main() { [[f^oo]](); }
1458 )cpp");
1459
1460 // References from indexed files are included.
1461 TestTU IndexedTU;
1462 IndexedTU.Code = std::string(IndexedMain.code());
1463 IndexedTU.Filename = "Indexed.cpp";
1464 IndexedTU.HeaderCode = Header;
1465 EXPECT_THAT(
1466 findReferences(AST, Main.point(), 0, IndexedTU.index().get()).References,
1467 ElementsAre(RangeIs(Main.range()), RangeIs(IndexedMain.range())));
1468 auto LimitRefs =
1469 findReferences(AST, Main.point(), /*Limit*/ 1, IndexedTU.index().get());
1470 EXPECT_EQ(1u, LimitRefs.References.size());
1471 EXPECT_TRUE(LimitRefs.HasMore);
1472
1473 // Avoid indexed results for the main file. Use AST for the mainfile.
1474 TU.Code = ("\n\n" + Main.code()).str();
1475 EXPECT_THAT(findReferences(AST, Main.point(), 0, TU.index().get()).References,
1476 ElementsAre(RangeIs(Main.range())));
1477 }
1478
TEST(FindReferences,NeedsIndexForMacro)1479 TEST(FindReferences, NeedsIndexForMacro) {
1480 const char *Header = "#define MACRO(X) (X+1)";
1481 Annotations Main(R"cpp(
1482 int main() {
1483 int a = [[MA^CRO]](1);
1484 }
1485 )cpp");
1486 TestTU TU;
1487 TU.Code = std::string(Main.code());
1488 TU.HeaderCode = Header;
1489 auto AST = TU.build();
1490
1491 // References in main file are returned without index.
1492 EXPECT_THAT(
1493 findReferences(AST, Main.point(), 0, /*Index=*/nullptr).References,
1494 ElementsAre(RangeIs(Main.range())));
1495
1496 Annotations IndexedMain(R"cpp(
1497 int indexed_main() {
1498 int a = [[MACRO]](1);
1499 }
1500 )cpp");
1501
1502 // References from indexed files are included.
1503 TestTU IndexedTU;
1504 IndexedTU.Code = std::string(IndexedMain.code());
1505 IndexedTU.Filename = "Indexed.cpp";
1506 IndexedTU.HeaderCode = Header;
1507 EXPECT_THAT(
1508 findReferences(AST, Main.point(), 0, IndexedTU.index().get()).References,
1509 ElementsAre(RangeIs(Main.range()), RangeIs(IndexedMain.range())));
1510 auto LimitRefs =
1511 findReferences(AST, Main.point(), /*Limit*/ 1, IndexedTU.index().get());
1512 EXPECT_EQ(1u, LimitRefs.References.size());
1513 EXPECT_TRUE(LimitRefs.HasMore);
1514 }
1515
TEST(FindReferences,NoQueryForLocalSymbols)1516 TEST(FindReferences, NoQueryForLocalSymbols) {
1517 struct RecordingIndex : public MemIndex {
1518 mutable Optional<llvm::DenseSet<SymbolID>> RefIDs;
1519 bool refs(const RefsRequest &Req,
1520 llvm::function_ref<void(const Ref &)>) const override {
1521 RefIDs = Req.IDs;
1522 return false;
1523 }
1524 };
1525
1526 struct Test {
1527 StringRef AnnotatedCode;
1528 bool WantQuery;
1529 } Tests[] = {
1530 {"int ^x;", true},
1531 // For now we don't assume header structure which would allow skipping.
1532 {"namespace { int ^x; }", true},
1533 {"static int ^x;", true},
1534 // Anything in a function certainly can't be referenced though.
1535 {"void foo() { int ^x; }", false},
1536 {"void foo() { struct ^x{}; }", false},
1537 {"auto lambda = []{ int ^x; };", false},
1538 };
1539 for (Test T : Tests) {
1540 Annotations File(T.AnnotatedCode);
1541 RecordingIndex Rec;
1542 auto AST = TestTU::withCode(File.code()).build();
1543 findReferences(AST, File.point(), 0, &Rec);
1544 if (T.WantQuery)
1545 EXPECT_NE(Rec.RefIDs, None) << T.AnnotatedCode;
1546 else
1547 EXPECT_EQ(Rec.RefIDs, None) << T.AnnotatedCode;
1548 }
1549 }
1550
TEST(GetNonLocalDeclRefs,All)1551 TEST(GetNonLocalDeclRefs, All) {
1552 struct Case {
1553 llvm::StringRef AnnotatedCode;
1554 std::vector<std::string> ExpectedDecls;
1555 } Cases[] = {
1556 {
1557 // VarDecl and ParamVarDecl
1558 R"cpp(
1559 void bar();
1560 void ^foo(int baz) {
1561 int x = 10;
1562 bar();
1563 })cpp",
1564 {"bar"},
1565 },
1566 {
1567 // Method from class
1568 R"cpp(
1569 class Foo { public: void foo(); };
1570 class Bar {
1571 void foo();
1572 void bar();
1573 };
1574 void Bar::^foo() {
1575 Foo f;
1576 bar();
1577 f.foo();
1578 })cpp",
1579 {"Bar", "Bar::bar", "Foo", "Foo::foo"},
1580 },
1581 {
1582 // Local types
1583 R"cpp(
1584 void ^foo() {
1585 class Foo { public: void foo() {} };
1586 class Bar { public: void bar() {} };
1587 Foo f;
1588 Bar b;
1589 b.bar();
1590 f.foo();
1591 })cpp",
1592 {},
1593 },
1594 {
1595 // Template params
1596 R"cpp(
1597 template <typename T, template<typename> class Q>
1598 void ^foo() {
1599 T x;
1600 Q<T> y;
1601 })cpp",
1602 {},
1603 },
1604 };
1605 for (const Case &C : Cases) {
1606 Annotations File(C.AnnotatedCode);
1607 auto AST = TestTU::withCode(File.code()).build();
1608 SourceLocation SL = llvm::cantFail(
1609 sourceLocationInMainFile(AST.getSourceManager(), File.point()));
1610
1611 const FunctionDecl *FD =
1612 llvm::dyn_cast<FunctionDecl>(&findDecl(AST, [SL](const NamedDecl &ND) {
1613 return ND.getLocation() == SL && llvm::isa<FunctionDecl>(ND);
1614 }));
1615 ASSERT_NE(FD, nullptr);
1616
1617 auto NonLocalDeclRefs = getNonLocalDeclRefs(AST, FD);
1618 std::vector<std::string> Names;
1619 for (const Decl *D : NonLocalDeclRefs) {
1620 if (const auto *ND = llvm::dyn_cast<NamedDecl>(D))
1621 Names.push_back(ND->getQualifiedNameAsString());
1622 }
1623 EXPECT_THAT(Names, UnorderedElementsAreArray(C.ExpectedDecls))
1624 << File.code();
1625 }
1626 }
1627
TEST(DocumentLinks,All)1628 TEST(DocumentLinks, All) {
1629 Annotations MainCpp(R"cpp(
1630 #/*comments*/include /*comments*/ $foo[["foo.h"]] //more comments
1631 int end_of_preamble = 0;
1632 #include $bar[[<bar.h>]]
1633 )cpp");
1634
1635 TestTU TU;
1636 TU.Code = std::string(MainCpp.code());
1637 TU.AdditionalFiles = {{"foo.h", ""}, {"bar.h", ""}};
1638 TU.ExtraArgs = {"-isystem."};
1639 auto AST = TU.build();
1640
1641 EXPECT_THAT(
1642 clangd::getDocumentLinks(AST),
1643 ElementsAre(
1644 DocumentLink({MainCpp.range("foo"),
1645 URIForFile::canonicalize(testPath("foo.h"), "")}),
1646 DocumentLink({MainCpp.range("bar"),
1647 URIForFile::canonicalize(testPath("bar.h"), "")})));
1648 }
1649
1650 } // namespace
1651 } // namespace clangd
1652 } // namespace clang
1653