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