clang-tools 22.0.0git
XRefsTests.cpp
Go to the documentation of this file.
1//===-- XRefsTests.cpp ---------------------------*- C++ -*--------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8#include "Annotations.h"
9#include "AST.h"
10#include "ParsedAST.h"
11#include "Protocol.h"
12#include "SourceCode.h"
13#include "SyncAPI.h"
14#include "TestFS.h"
15#include "TestTU.h"
16#include "XRefs.h"
17#include "index/MemIndex.h"
18#include "clang/AST/Decl.h"
19#include "clang/Basic/SourceLocation.h"
20#include "llvm/ADT/StringRef.h"
21#include "llvm/Support/Casting.h"
22#include "llvm/Support/Error.h"
23#include "llvm/Support/Path.h"
24#include "llvm/Support/ScopedPrinter.h"
25#include "gmock/gmock.h"
26#include "gtest/gtest.h"
27#include <optional>
28#include <string>
29#include <vector>
30
31namespace clang {
32namespace clangd {
33namespace {
34
35using ::testing::AllOf;
36using ::testing::ElementsAre;
37using ::testing::Eq;
38using ::testing::IsEmpty;
39using ::testing::Matcher;
40using ::testing::UnorderedElementsAre;
41using ::testing::UnorderedElementsAreArray;
42using ::testing::UnorderedPointwise;
43
44std::string guard(llvm::StringRef Code) {
45 return "#pragma once\n" + Code.str();
46}
47
48MATCHER_P2(FileRange, File, Range, "") {
50}
51MATCHER(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.
59Matcher<const std::vector<DocumentHighlight> &>
60highlightsFrom(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())
69 for (const auto &Range : Test.ranges("read"))
71 for (const auto &Range : Test.ranges("write"))
73 return UnorderedElementsAreArray(Expected);
74}
75
76TEST(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) { return 0; }
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 R"cpp(// ObjC methods with split selectors.
118 @interface Foo
119 +(void) [[x]]:(int)a [[y]]:(int)b;
120 @end
121 @implementation Foo
122 +(void) [[x]]:(int)a [[y]]:(int)b {}
123 @end
124 void go() {
125 [Foo [[x]]:2 [[^y]]:4];
126 }
127 )cpp",
128 R"cpp( // Label
129 int main() {
130 goto [[^theLabel]];
131 [[theLabel]]:
132 return 1;
133 }
134 )cpp",
135 };
136 for (const char *Test : Tests) {
137 Annotations T(Test);
138 auto TU = TestTU::withCode(T.code());
139 TU.ExtraArgs.push_back("-xobjective-c++");
140 auto AST = TU.build();
141 EXPECT_THAT(findDocumentHighlights(AST, T.point()), highlightsFrom(T))
142 << Test;
143 }
144}
145
146TEST(HighlightsTest, ControlFlow) {
147 const char *Tests[] = {
148 R"cpp(
149 // Highlight same-function returns.
150 int fib(unsigned n) {
151 if (n <= 1) [[ret^urn]] 1;
152 [[return]] fib(n - 1) + fib(n - 2);
153
154 // Returns from other functions not highlighted.
155 auto Lambda = [] { return; };
156 class LocalClass { void x() { return; } };
157 }
158 )cpp",
159
160 R"cpp(
161 #define FAIL() return false
162 #define DO(x) { x; }
163 bool foo(int n) {
164 if (n < 0) [[FAIL]]();
165 DO([[re^turn]] true)
166 }
167 )cpp",
168
169 R"cpp(
170 // Highlight loop control flow
171 int magic() {
172 int counter = 0;
173 [[^for]] (char c : "fruit loops!") {
174 if (c == ' ') [[continue]];
175 counter += c;
176 if (c == '!') [[break]];
177 if (c == '?') [[return]] -1;
178 }
179 return counter;
180 }
181 )cpp",
182
183 R"cpp(
184 // Highlight loop and same-loop control flow
185 void nonsense() {
186 [[while]] (true) {
187 if (false) [[bre^ak]];
188 switch (1) break;
189 [[continue]];
190 }
191 }
192 )cpp",
193
194 R"cpp(
195 // Highlight switch for break (but not other breaks).
196 void describe(unsigned n) {
197 [[switch]](n) {
198 case 0:
199 break;
200 [[default]]:
201 [[^break]];
202 }
203 }
204 )cpp",
205
206 R"cpp(
207 // Highlight case and exits for switch-break (but not other cases).
208 void describe(unsigned n) {
209 [[switch]](n) {
210 case 0:
211 break;
212 [[case]] 1:
213 [[default]]:
214 [[return]];
215 [[^break]];
216 }
217 }
218 )cpp",
219
220 R"cpp(
221 // Highlight exits and switch for case
222 void describe(unsigned n) {
223 [[switch]](n) {
224 case 0:
225 break;
226 [[case]] 1:
227 [[d^efault]]:
228 [[return]];
229 [[break]];
230 }
231 }
232 )cpp",
233
234 R"cpp(
235 // Highlight nothing for switch.
236 void describe(unsigned n) {
237 s^witch(n) {
238 case 0:
239 break;
240 case 1:
241 default:
242 return;
243 break;
244 }
245 }
246 )cpp",
247
248 R"cpp(
249 // FIXME: match exception type against catch blocks
250 int catchy() {
251 try { // wrong: highlight try with matching catch
252 try { // correct: has no matching catch
253 [[thr^ow]] "oh no!";
254 } catch (int) { } // correct: catch doesn't match type
255 [[return]] -1; // correct: exits the matching catch
256 } catch (const char*) { } // wrong: highlight matching catch
257 [[return]] 42; // wrong: throw doesn't exit function
258 }
259 )cpp",
260
261 R"cpp(
262 // Loop highlights goto exiting the loop, but not jumping within it.
263 void jumpy() {
264 [[wh^ile]](1) {
265 up:
266 if (0) [[goto]] out;
267 goto up;
268 }
269 out: return;
270 }
271 )cpp",
272 };
273 for (const char *Test : Tests) {
274 Annotations T(Test);
275 auto TU = TestTU::withCode(T.code());
276 TU.ExtraArgs.push_back("-fexceptions"); // FIXME: stop testing on PS4.
277 auto AST = TU.build();
278 EXPECT_THAT(findDocumentHighlights(AST, T.point()), highlightsFrom(T))
279 << Test;
280 }
281}
282
283MATCHER_P3(sym, Name, Decl, DefOrNone, "") {
284 std::optional<Range> Def = DefOrNone;
285 if (Name != arg.Name) {
286 *result_listener << "Name is " << arg.Name;
287 return false;
288 }
289 if (Decl != arg.PreferredDeclaration.range) {
290 *result_listener << "Declaration is "
291 << llvm::to_string(arg.PreferredDeclaration);
292 return false;
293 }
294 if (!Def && !arg.Definition)
295 return true;
296 if (Def && !arg.Definition) {
297 *result_listener << "Has no definition";
298 return false;
299 }
300 if (!Def && arg.Definition) {
301 *result_listener << "Definition is " << llvm::to_string(*arg.Definition);
302 return false;
303 }
304 if (arg.Definition->range != *Def) {
305 *result_listener << "Definition is " << llvm::to_string(*arg.Definition);
306 return false;
307 }
308 return true;
309}
310
311MATCHER_P(sym, Name, "") { return arg.Name == Name; }
312
313MATCHER_P(rangeIs, R, "") { return arg.Loc.range == R; }
314MATCHER_P(containerIs, C, "") {
315 return arg.Loc.containerName.value_or("") == C;
316}
317MATCHER_P(attrsAre, A, "") { return arg.Attributes == A; }
318MATCHER_P(hasID, ID, "") { return arg.ID == ID; }
319
320TEST(LocateSymbol, WithIndex) {
321 Annotations SymbolHeader(R"cpp(
322 class $forward[[Forward]];
323 class $foo[[Foo]] {};
324
325 void $f1[[f1]]();
326
327 inline void $f2[[f2]]() {}
328 )cpp");
329 Annotations SymbolCpp(R"cpp(
330 class $forward[[forward]] {};
331 void $f1[[f1]]() {}
332 )cpp");
333
334 TestTU TU;
335 TU.Code = std::string(SymbolCpp.code());
336 TU.HeaderCode = std::string(SymbolHeader.code());
337 auto Index = TU.index();
338 auto LocateWithIndex = [&Index](const Annotations &Main) {
339 auto AST = TestTU::withCode(Main.code()).build();
340 return clangd::locateSymbolAt(AST, Main.point(), Index.get());
341 };
342
343 Annotations Test(R"cpp(// only declaration in AST.
344 void [[f1]]();
345 int main() {
346 ^f1();
347 }
348 )cpp");
349 EXPECT_THAT(LocateWithIndex(Test),
350 ElementsAre(sym("f1", Test.range(), SymbolCpp.range("f1"))));
351
352 Test = Annotations(R"cpp(// definition in AST.
353 void [[f1]]() {}
354 int main() {
355 ^f1();
356 }
357 )cpp");
358 EXPECT_THAT(LocateWithIndex(Test),
359 ElementsAre(sym("f1", SymbolHeader.range("f1"), Test.range())));
360
361 Test = Annotations(R"cpp(// forward declaration in AST.
362 class [[Foo]];
363 F^oo* create();
364 )cpp");
365 EXPECT_THAT(LocateWithIndex(Test),
366 ElementsAre(sym("Foo", Test.range(), SymbolHeader.range("foo"))));
367
368 Test = Annotations(R"cpp(// definition in AST.
369 class [[Forward]] {};
370 F^orward create();
371 )cpp");
372 EXPECT_THAT(
373 LocateWithIndex(Test),
374 ElementsAre(sym("Forward", SymbolHeader.range("forward"), Test.range())));
375}
376
377TEST(LocateSymbol, AnonymousStructFields) {
378 auto Code = Annotations(R"cpp(
379 struct $2[[Foo]] {
380 struct { int $1[[x]]; };
381 void foo() {
382 // Make sure the implicit base is skipped.
383 $1^x = 42;
384 }
385 };
386 // Check that we don't skip explicit bases.
387 int a = $2^Foo{}.x;
388 )cpp");
389 TestTU TU = TestTU::withCode(Code.code());
390 auto AST = TU.build();
391 EXPECT_THAT(locateSymbolAt(AST, Code.point("1"), TU.index().get()),
392 UnorderedElementsAre(sym("x", Code.range("1"), Code.range("1"))));
393 EXPECT_THAT(
394 locateSymbolAt(AST, Code.point("2"), TU.index().get()),
395 UnorderedElementsAre(sym("Foo", Code.range("2"), Code.range("2"))));
396}
397
398TEST(LocateSymbol, FindOverrides) {
399 auto Code = Annotations(R"cpp(
400 class Foo {
401 virtual void $1[[fo^o]]() = 0;
402 };
403 class Bar : public Foo {
404 void $2[[foo]]() override;
405 };
406 )cpp");
407 TestTU TU = TestTU::withCode(Code.code());
408 auto AST = TU.build();
409 EXPECT_THAT(locateSymbolAt(AST, Code.point(), TU.index().get()),
410 UnorderedElementsAre(sym("foo", Code.range("1"), std::nullopt),
411 sym("foo", Code.range("2"), std::nullopt)));
412}
413
414TEST(LocateSymbol, FindOverridesFromDefObjC) {
415 auto Code = Annotations(R"objc(
416 @protocol Fooey
417 - (void)foo;
418 @end
419 @interface Base
420 - (void)foo;
421 @end
422 @interface Foo : Base<Fooey>
423 - (void)$1[[foo]];
424 @end
425
426 @interface Bar : Foo
427 - (void)$2[[foo]];
428 @end
429 @implementation Bar
430 - (void)$3[[fo^o]] {}
431 @end
432 )objc");
433 TestTU TU = TestTU::withCode(Code.code());
434 TU.ExtraArgs.push_back("-xobjective-c++");
435 auto AST = TU.build();
436 EXPECT_THAT(
437 locateSymbolAt(AST, Code.point(), TU.index().get()),
438 UnorderedElementsAre(sym("foo", Code.range("1"), std::nullopt),
439 sym("foo", Code.range("2"), Code.range("3"))));
440}
441
442TEST(LocateSymbol, NoOverridesFromDeclObjC) {
443 auto Code = Annotations(R"objc(
444 @protocol Fooey
445 - (void)foo;
446 @end
447 @interface Base
448 - (void)foo;
449 @end
450 @interface Foo : Base<Fooey>
451 - (void)foo;
452 @end
453
454 @interface Bar : Foo
455 - (void)$2[[fo^o]];
456 @end
457 @implementation Bar
458 - (void)$3[[foo]] {}
459 @end
460 )objc");
461 TestTU TU = TestTU::withCode(Code.code());
462 TU.ExtraArgs.push_back("-xobjective-c++");
463 auto AST = TU.build();
464 EXPECT_THAT(
465 locateSymbolAt(AST, Code.point(), TU.index().get()),
466 UnorderedElementsAre(sym("foo", Code.range("2"), Code.range("3"))));
467}
468
469TEST(LocateSymbol, ObjCNoOverridesOnUsage) {
470 auto Code = Annotations(R"objc(
471 @interface Foo
472 - (void)foo;
473 @end
474
475 @interface Bar : Foo
476 - (void)$1[[foo]];
477 @end
478 @implementation Bar
479 - (void)$2[[foo]] {}
480 @end
481 void doSomething(Bar *bar) {
482 [bar fo^o];
483 }
484 )objc");
485 TestTU TU = TestTU::withCode(Code.code());
486 TU.ExtraArgs.push_back("-xobjective-c++");
487 auto AST = TU.build();
488 EXPECT_THAT(
489 locateSymbolAt(AST, Code.point(), TU.index().get()),
490 UnorderedElementsAre(sym("foo", Code.range("1"), Code.range("2"))));
491}
492
493TEST(LocateSymbol, WithIndexPreferredLocation) {
494 Annotations SymbolHeader(R"cpp(
495 class $p[[Proto]] {};
496 void $f[[func]]() {};
497 )cpp");
498 TestTU TU;
499 TU.HeaderCode = std::string(SymbolHeader.code());
500 TU.HeaderFilename = "x.proto"; // Prefer locations in codegen files.
501 auto Index = TU.index();
502
503 Annotations Test(R"cpp(// only declaration in AST.
504 // Shift to make range different.
505 class Proto;
506 void func() {}
507 P$p^roto* create() {
508 fu$f^nc();
509 return nullptr;
510 }
511 )cpp");
512
513 auto AST = TestTU::withCode(Test.code()).build();
514 {
515 auto Locs = clangd::locateSymbolAt(AST, Test.point("p"), Index.get());
516 auto CodeGenLoc = SymbolHeader.range("p");
517 EXPECT_THAT(Locs, ElementsAre(sym("Proto", CodeGenLoc, CodeGenLoc)));
518 }
519 {
520 auto Locs = clangd::locateSymbolAt(AST, Test.point("f"), Index.get());
521 auto CodeGenLoc = SymbolHeader.range("f");
522 EXPECT_THAT(Locs, ElementsAre(sym("func", CodeGenLoc, CodeGenLoc)));
523 }
524}
525
526TEST(LocateSymbol, All) {
527 // Ranges in tests:
528 // $decl is the declaration location (if absent, no symbol is located)
529 // $def is the definition location (if absent, symbol has no definition)
530 // unnamed range becomes both $decl and $def.
531 const char *Tests[] = {
532 R"cpp(
533 struct X {
534 union {
535 int [[a]];
536 float b;
537 };
538 };
539 int test(X &x) {
540 return x.^a;
541 }
542 )cpp",
543
544 R"cpp(// Local variable
545 int main() {
546 int [[bonjour]];
547 ^bonjour = 2;
548 int test1 = bonjour;
549 }
550 )cpp",
551
552 R"cpp(// Struct
553 namespace ns1 {
554 struct [[MyClass]] {};
555 } // namespace ns1
556 int main() {
557 ns1::My^Class* Params;
558 }
559 )cpp",
560
561 R"cpp(// Function definition via pointer
562 void [[foo]](int) {}
563 int main() {
564 auto *X = &^foo;
565 }
566 )cpp",
567
568 R"cpp(// Function declaration via call
569 int $decl[[foo]](int);
570 int main() {
571 return ^foo(42);
572 }
573 )cpp",
574
575 R"cpp(// Field
576 struct Foo { int [[x]]; };
577 int main() {
578 Foo bar;
579 (void)bar.^x;
580 }
581 )cpp",
582
583 R"cpp(// Field, member initializer
584 struct Foo {
585 int [[x]];
586 Foo() : ^x(0) {}
587 };
588 )cpp",
589
590 R"cpp(// Field, field designator
591 struct Foo { int [[x]]; };
592 int main() {
593 Foo bar = { .^x = 2 };
594 }
595 )cpp",
596
597 R"cpp(// Method call
598 struct Foo { int $decl[[x]](); };
599 int main() {
600 Foo bar;
601 bar.^x();
602 }
603 )cpp",
604
605 R"cpp(// Typedef
606 typedef int $decl[[Foo]];
607 int main() {
608 ^Foo bar;
609 }
610 )cpp",
611
612 R"cpp(// Template type parameter
613 template <typename [[T]]>
614 void foo() { ^T t; }
615 )cpp",
616
617 R"cpp(// Template template type parameter
618 template <template<typename> class [[T]]>
619 void foo() { ^T<int> t; }
620 )cpp",
621
622 R"cpp(// Namespace
623 namespace $decl[[ns]] {
624 struct Foo { static void bar(); };
625 } // namespace ns
626 int main() { ^ns::Foo::bar(); }
627 )cpp",
628
629 R"cpp(// Macro
630 class TTT { public: int a; };
631 #define [[FF]](S) if (int b = S.a) {}
632 void f() {
633 TTT t;
634 F^F(t);
635 }
636 )cpp",
637
638 R"cpp(// Macro argument
639 int [[i]];
640 #define ADDRESSOF(X) &X;
641 int *j = ADDRESSOF(^i);
642 )cpp",
643 R"cpp(// Macro argument appearing multiple times in expansion
644 #define VALIDATE_TYPE(x) (void)x;
645 #define ASSERT(expr) \
646 do { \
647 VALIDATE_TYPE(expr); \
648 if (!expr); \
649 } while (false)
650 bool [[waldo]]() { return true; }
651 void foo() {
652 ASSERT(wa^ldo());
653 }
654 )cpp",
655 R"cpp(// Symbol concatenated inside macro (not supported)
656 int *pi;
657 #define POINTER(X) p ## X;
658 int x = *POINTER(^i);
659 )cpp",
660
661 R"cpp(// Forward class declaration
662 class $decl[[Foo]];
663 class $def[[Foo]] {};
664 F^oo* foo();
665 )cpp",
666
667 R"cpp(// Function declaration
668 void $decl[[foo]]();
669 void g() { f^oo(); }
670 void $def[[foo]]() {}
671 )cpp",
672
673 R"cpp(
674 #define FF(name) class name##_Test {};
675 [[FF]](my);
676 void f() { my^_Test a; }
677 )cpp",
678
679 R"cpp(
680 #define FF() class [[Test]] {};
681 FF();
682 void f() { T^est a; }
683 )cpp",
684
685 R"cpp(// explicit template specialization
686 template <typename T>
687 struct Foo { void bar() {} };
688
689 template <>
690 struct [[Foo]]<int> { void bar() {} };
691
692 void foo() {
693 Foo<char> abc;
694 Fo^o<int> b;
695 }
696 )cpp",
697
698 R"cpp(// implicit template specialization
699 template <typename T>
700 struct [[Foo]] { void bar() {} };
701 template <>
702 struct Foo<int> { void bar() {} };
703 void foo() {
704 Fo^o<char> abc;
705 Foo<int> b;
706 }
707 )cpp",
708
709 R"cpp(// partial template specialization
710 template <typename T>
711 struct Foo { void bar() {} };
712 template <typename T>
713 struct [[Foo]]<T*> { void bar() {} };
714 ^Foo<int*> x;
715 )cpp",
716
717 R"cpp(// function template specializations
718 template <class T>
719 void foo(T) {}
720 template <>
721 void [[foo]](int) {}
722 void bar() {
723 fo^o(10);
724 }
725 )cpp",
726
727 R"cpp(// variable template decls
728 template <class T>
729 T var = T();
730
731 template <>
732 double [[var]]<int> = 10;
733
734 double y = va^r<int>;
735 )cpp",
736
737 R"cpp(// No implicit constructors
738 struct X {
739 X(X&& x) = default;
740 };
741 X $decl[[makeX]]();
742 void foo() {
743 auto x = m^akeX();
744 }
745 )cpp",
746
747 R"cpp(
748 struct X {
749 X& $decl[[operator]]++();
750 };
751 void foo(X& x) {
752 +^+x;
753 }
754 )cpp",
755
756 R"cpp(
757 struct S1 { void f(); };
758 struct S2 { S1 * $decl[[operator]]->(); };
759 void test(S2 s2) {
760 s2-^>f();
761 }
762 )cpp",
763
764 R"cpp(// Declaration of explicit template specialization
765 template <typename T>
766 struct $decl[[$def[[Foo]]]] {};
767
768 template <>
769 struct Fo^o<int> {};
770 )cpp",
771
772 R"cpp(// Declaration of partial template specialization
773 template <typename T>
774 struct $decl[[$def[[Foo]]]] {};
775
776 template <typename T>
777 struct Fo^o<T*> {};
778 )cpp",
779
780 R"cpp(// Definition on ClassTemplateDecl
781 namespace ns {
782 // Forward declaration.
783 template<typename T>
784 struct $decl[[Foo]];
785
786 template <typename T>
787 struct $def[[Foo]] {};
788 }
789
790 using ::ns::Fo^o;
791 )cpp",
792
793 R"cpp(// auto builtin type (not supported)
794 ^auto x = 42;
795 )cpp",
796
797 R"cpp(// auto on lambda
798 auto x = [[[]]]{};
799 ^auto y = x;
800 )cpp",
801
802 R"cpp(// auto on struct
803 namespace ns1 {
804 struct [[S1]] {};
805 } // namespace ns1
806
807 ^auto x = ns1::S1{};
808 )cpp",
809
810 R"cpp(// decltype on struct
811 namespace ns1 {
812 struct [[S1]] {};
813 } // namespace ns1
814
815 ns1::S1 i;
816 ^decltype(i) j;
817 )cpp",
818
819 R"cpp(// decltype(auto) on struct
820 namespace ns1 {
821 struct [[S1]] {};
822 } // namespace ns1
823
824 ns1::S1 i;
825 ns1::S1& j = i;
826 ^decltype(auto) k = j;
827 )cpp",
828
829 R"cpp(// auto on template class
830 template<typename T> class [[Foo]] {};
831
832 ^auto x = Foo<int>();
833 )cpp",
834
835 R"cpp(// auto on template class with forward declared class
836 template<typename T> class [[Foo]] {};
837 class X;
838
839 ^auto x = Foo<X>();
840 )cpp",
841
842 R"cpp(// auto on specialized template class
843 template<typename T> class Foo {};
844 template<> class [[Foo]]<int> {};
845
846 ^auto x = Foo<int>();
847 )cpp",
848
849 R"cpp(// auto on initializer list.
850 namespace std
851 {
852 template<class _E>
853 class [[initializer_list]] { const _E *a, *b; };
854 }
855
856 ^auto i = {1,2};
857 )cpp",
858
859 R"cpp(// auto function return with trailing type
860 struct [[Bar]] {};
861 ^auto test() -> decltype(Bar()) {
862 return Bar();
863 }
864 )cpp",
865
866 R"cpp(// decltype in trailing return type
867 struct [[Bar]] {};
868 auto test() -> ^decltype(Bar()) {
869 return Bar();
870 }
871 )cpp",
872
873 R"cpp(// auto in function return
874 struct [[Bar]] {};
875 ^auto test() {
876 return Bar();
877 }
878 )cpp",
879
880 R"cpp(// auto& in function return
881 struct [[Bar]] {};
882 ^auto& test() {
883 static Bar x;
884 return x;
885 }
886 )cpp",
887
888 R"cpp(// auto* in function return
889 struct [[Bar]] {};
890 ^auto* test() {
891 Bar* x;
892 return x;
893 }
894 )cpp",
895
896 R"cpp(// const auto& in function return
897 struct [[Bar]] {};
898 const ^auto& test() {
899 static Bar x;
900 return x;
901 }
902 )cpp",
903
904 R"cpp(// auto lambda param where there's a single instantiation
905 struct [[Bar]] {};
906 auto Lambda = [](^auto){ return 0; };
907 int x = Lambda(Bar{});
908 )cpp",
909
910 R"cpp(// decltype(auto) in function return
911 struct [[Bar]] {};
912 ^decltype(auto) test() {
913 return Bar();
914 }
915 )cpp",
916
917 R"cpp(// decltype of function with trailing return type.
918 struct [[Bar]] {};
919 auto test() -> decltype(Bar()) {
920 return Bar();
921 }
922 void foo() {
923 ^decltype(test()) i = test();
924 }
925 )cpp",
926
927 R"cpp(// auto with dependent type
928 template <typename>
929 struct [[A]] {};
930 template <typename T>
931 void foo(A<T> a) {
932 ^auto copy = a;
933 }
934 )cpp",
935
936 R"cpp(// Override specifier jumps to overridden method
937 class Y { virtual void $decl[[a]]() = 0; };
938 class X : Y { void a() ^override {} };
939 )cpp",
940 R"cpp(// Final specifier jumps to overridden method
941 class Y { virtual void $decl[[a]]() = 0; };
942 class X : Y { void a() ^final {} };
943 )cpp",
944
945 R"cpp(// Heuristic resolution of dependent method
946 template <typename T>
947 struct S {
948 void [[bar]]() {}
949 };
950
951 template <typename T>
952 void foo(S<T> arg) {
953 arg.ba^r();
954 }
955 )cpp",
956
957 R"cpp(// Heuristic resolution of dependent method via this->
958 template <typename T>
959 struct S {
960 void [[foo]]() {
961 this->fo^o();
962 }
963 };
964 )cpp",
965
966 R"cpp(// Heuristic resolution of dependent static method
967 template <typename T>
968 struct S {
969 static void [[bar]]() {}
970 };
971
972 template <typename T>
973 void foo() {
974 S<T>::ba^r();
975 }
976 )cpp",
977
978 R"cpp(// Heuristic resolution of dependent method
979 // invoked via smart pointer
980 template <typename> struct S { void [[foo]]() {} };
981 template <typename T> struct unique_ptr {
982 T* operator->();
983 };
984 template <typename T>
985 void test(unique_ptr<S<T>>& V) {
986 V->fo^o();
987 }
988 )cpp",
989
990 R"cpp(// Heuristic resolution of dependent enumerator
991 template <typename T>
992 struct Foo {
993 enum class E { [[A]], B };
994 E e = E::A^;
995 };
996 )cpp",
997
998 R"cpp(// Enum base
999 typedef int $decl[[MyTypeDef]];
1000 enum Foo : My^TypeDef {};
1001 )cpp",
1002 R"cpp(// Enum base
1003 typedef int $decl[[MyTypeDef]];
1004 enum Foo : My^TypeDef;
1005 )cpp",
1006 R"cpp(// Enum base
1007 using $decl[[MyTypeDef]] = int;
1008 enum Foo : My^TypeDef {};
1009 )cpp",
1010
1011 R"objc(
1012 @protocol Dog;
1013 @protocol $decl[[Dog]]
1014 - (void)bark;
1015 @end
1016 id<Do^g> getDoggo() {
1017 return 0;
1018 }
1019 )objc",
1020
1021 R"objc(
1022 @interface Cat
1023 @end
1024 @implementation Cat
1025 @end
1026 @interface $decl[[Cat]] (Exte^nsion)
1027 - (void)meow;
1028 @end
1029 @implementation $def[[Cat]] (Extension)
1030 - (void)meow {}
1031 @end
1032 )objc",
1033
1034 R"objc(
1035 @class $decl[[Foo]];
1036 Fo^o * getFoo() {
1037 return 0;
1038 }
1039 )objc",
1040
1041 R"objc(// Prefer interface definition over forward declaration
1042 @class Foo;
1043 @interface $decl[[Foo]]
1044 @end
1045 Fo^o * getFoo() {
1046 return 0;
1047 }
1048 )objc",
1049
1050 R"objc(
1051 @class Foo;
1052 @interface $decl[[Foo]]
1053 @end
1054 @implementation $def[[Foo]]
1055 @end
1056 Fo^o * getFoo() {
1057 return 0;
1058 }
1059 )objc",
1060
1061 R"objc(// Method decl and definition for ObjC class.
1062 @interface Cat
1063 - (void)$decl[[meow]];
1064 @end
1065 @implementation Cat
1066 - (void)$def[[meow]] {}
1067 @end
1068 void makeNoise(Cat *kitty) {
1069 [kitty me^ow];
1070 }
1071 )objc",
1072
1073 R"objc(// Method decl and definition for ObjC category.
1074 @interface Dog
1075 @end
1076 @interface Dog (Play)
1077 - (void)$decl[[runAround]];
1078 @end
1079 @implementation Dog (Play)
1080 - (void)$def[[runAround]] {}
1081 @end
1082 void play(Dog *dog) {
1083 [dog run^Around];
1084 }
1085 )objc",
1086
1087 R"objc(// Method decl and definition for ObjC class extension.
1088 @interface Dog
1089 @end
1090 @interface Dog ()
1091 - (void)$decl[[howl]];
1092 @end
1093 @implementation Dog
1094 - (void)$def[[howl]] {}
1095 @end
1096 void play(Dog *dog) {
1097 [dog ho^wl];
1098 }
1099 )objc",
1100 R"cpp(
1101 struct PointerIntPairInfo {
1102 static void *$decl[[getPointer]](void *Value);
1103 };
1104
1105 template <typename Info = PointerIntPairInfo> struct PointerIntPair {
1106 void *Value;
1107 void *getPointer() const { return Info::get^Pointer(Value); }
1108 };
1109 )cpp",
1110 R"cpp(// Deducing this
1111 struct S {
1112 int bar(this S&);
1113 };
1114 void foo() {
1115 S [[waldo]];
1116 int x = wa^ldo.bar();
1117 }
1118 )cpp"};
1119 for (const char *Test : Tests) {
1120 Annotations T(Test);
1121 std::optional<Range> WantDecl;
1122 std::optional<Range> WantDef;
1123 if (!T.ranges().empty())
1124 WantDecl = WantDef = T.range();
1125 if (!T.ranges("decl").empty())
1126 WantDecl = T.range("decl");
1127 if (!T.ranges("def").empty())
1128 WantDef = T.range("def");
1129
1130 TestTU TU;
1131 TU.Code = std::string(T.code());
1132
1133 TU.ExtraArgs.push_back("-xobjective-c++");
1134 TU.ExtraArgs.push_back("-std=c++23");
1135
1136 auto AST = TU.build();
1137 auto Results = locateSymbolAt(AST, T.point());
1138
1139 if (!WantDecl) {
1140 EXPECT_THAT(Results, IsEmpty()) << Test;
1141 } else {
1142 ASSERT_THAT(Results, ::testing::SizeIs(1)) << Test;
1143 EXPECT_EQ(Results[0].PreferredDeclaration.range, *WantDecl) << Test;
1144 EXPECT_TRUE(Results[0].ID) << Test;
1145 std::optional<Range> GotDef;
1146 if (Results[0].Definition)
1147 GotDef = Results[0].Definition->range;
1148 EXPECT_EQ(WantDef, GotDef) << Test;
1149 }
1150 }
1151}
1152TEST(LocateSymbol, ValidSymbolID) {
1153 auto T = Annotations(R"cpp(
1154 #define MACRO(x, y) ((x) + (y))
1155 int add(int x, int y) { return $MACRO^MACRO(x, y); }
1156 int sum = $add^add(1, 2);
1157 )cpp");
1158
1159 TestTU TU = TestTU::withCode(T.code());
1160 auto AST = TU.build();
1161 auto Index = TU.index();
1162 EXPECT_THAT(locateSymbolAt(AST, T.point("add"), Index.get()),
1163 ElementsAre(AllOf(sym("add"),
1164 hasID(getSymbolID(&findDecl(AST, "add"))))));
1165 EXPECT_THAT(
1166 locateSymbolAt(AST, T.point("MACRO"), Index.get()),
1167 ElementsAre(AllOf(sym("MACRO"),
1168 hasID(findSymbol(TU.headerSymbols(), "MACRO").ID))));
1169}
1170
1171TEST(LocateSymbol, AllMulti) {
1172 // Ranges in tests:
1173 // $declN is the declaration location
1174 // $defN is the definition location (if absent, symbol has no definition)
1175 //
1176 // NOTE:
1177 // N starts at 0.
1178 struct ExpectedRanges {
1179 Range WantDecl;
1180 std::optional<Range> WantDef;
1181 };
1182 const char *Tests[] = {
1183 R"objc(
1184 @interface $decl0[[Cat]]
1185 @end
1186 @implementation $def0[[Cat]]
1187 @end
1188 @interface $decl1[[Ca^t]] (Extension)
1189 - (void)meow;
1190 @end
1191 @implementation $def1[[Cat]] (Extension)
1192 - (void)meow {}
1193 @end
1194 )objc",
1195
1196 R"objc(
1197 @interface $decl0[[Cat]]
1198 @end
1199 @implementation $def0[[Cat]]
1200 @end
1201 @interface $decl1[[Cat]] (Extension)
1202 - (void)meow;
1203 @end
1204 @implementation $def1[[Ca^t]] (Extension)
1205 - (void)meow {}
1206 @end
1207 )objc",
1208
1209 R"objc(
1210 @interface $decl0[[Cat]]
1211 @end
1212 @interface $decl1[[Ca^t]] ()
1213 - (void)meow;
1214 @end
1215 @implementation $def0[[$def1[[Cat]]]]
1216 - (void)meow {}
1217 @end
1218 )objc",
1219 };
1220 for (const char *Test : Tests) {
1221 Annotations T(Test);
1222 std::vector<ExpectedRanges> Ranges;
1223 for (int Idx = 0; true; Idx++) {
1224 bool HasDecl = !T.ranges("decl" + std::to_string(Idx)).empty();
1225 bool HasDef = !T.ranges("def" + std::to_string(Idx)).empty();
1226 if (!HasDecl && !HasDef)
1227 break;
1228 ExpectedRanges Range;
1229 if (HasDecl)
1230 Range.WantDecl = T.range("decl" + std::to_string(Idx));
1231 if (HasDef)
1232 Range.WantDef = T.range("def" + std::to_string(Idx));
1233 Ranges.push_back(Range);
1234 }
1235
1236 TestTU TU;
1237 TU.Code = std::string(T.code());
1238 TU.ExtraArgs.push_back("-xobjective-c++");
1239
1240 auto AST = TU.build();
1241 auto Results = locateSymbolAt(AST, T.point());
1242
1243 ASSERT_THAT(Results, ::testing::SizeIs(Ranges.size())) << Test;
1244 for (size_t Idx = 0; Idx < Ranges.size(); Idx++) {
1245 EXPECT_EQ(Results[Idx].PreferredDeclaration.range, Ranges[Idx].WantDecl)
1246 << "($decl" << Idx << ")" << Test;
1247 std::optional<Range> GotDef;
1248 if (Results[Idx].Definition)
1249 GotDef = Results[Idx].Definition->range;
1250 EXPECT_EQ(GotDef, Ranges[Idx].WantDef) << "($def" << Idx << ")" << Test;
1251 }
1252 }
1253}
1254
1255// LocateSymbol test cases that produce warnings.
1256// These are separated out from All so that in All we can assert
1257// that there are no diagnostics.
1258TEST(LocateSymbol, Warnings) {
1259 const char *Tests[] = {
1260 R"cpp(// Field, GNU old-style field designator
1261 struct Foo { int [[x]]; };
1262 int main() {
1263 Foo bar = { ^x : 1 };
1264 }
1265 )cpp",
1266
1267 R"cpp(// Macro
1268 #define MACRO 0
1269 #define [[MACRO]] 1
1270 int main() { return ^MACRO; }
1271 #define MACRO 2
1272 #undef macro
1273 )cpp",
1274 };
1275
1276 for (const char *Test : Tests) {
1277 Annotations T(Test);
1278 std::optional<Range> WantDecl;
1279 std::optional<Range> WantDef;
1280 if (!T.ranges().empty())
1281 WantDecl = WantDef = T.range();
1282 if (!T.ranges("decl").empty())
1283 WantDecl = T.range("decl");
1284 if (!T.ranges("def").empty())
1285 WantDef = T.range("def");
1286
1287 TestTU TU;
1288 TU.Code = std::string(T.code());
1289
1290 auto AST = TU.build();
1291 auto Results = locateSymbolAt(AST, T.point());
1292
1293 if (!WantDecl) {
1294 EXPECT_THAT(Results, IsEmpty()) << Test;
1295 } else {
1296 ASSERT_THAT(Results, ::testing::SizeIs(1)) << Test;
1297 EXPECT_EQ(Results[0].PreferredDeclaration.range, *WantDecl) << Test;
1298 std::optional<Range> GotDef;
1299 if (Results[0].Definition)
1300 GotDef = Results[0].Definition->range;
1301 EXPECT_EQ(WantDef, GotDef) << Test;
1302 }
1303 }
1304}
1305
1306TEST(LocateSymbol, TextualSmoke) {
1307 auto T = Annotations(
1308 R"cpp(
1309 struct [[MyClass]] {};
1310 // Comment mentioning M^yClass
1311 )cpp");
1312
1313 auto TU = TestTU::withCode(T.code());
1314 auto AST = TU.build();
1315 auto Index = TU.index();
1316 EXPECT_THAT(
1317 locateSymbolAt(AST, T.point(), Index.get()),
1318 ElementsAre(AllOf(sym("MyClass", T.range(), T.range()),
1319 hasID(getSymbolID(&findDecl(AST, "MyClass"))))));
1320}
1321
1322TEST(LocateSymbol, Textual) {
1323 const char *Tests[] = {
1324 R"cpp(// Comment
1325 struct [[MyClass]] {};
1326 // Comment mentioning M^yClass
1327 )cpp",
1328 R"cpp(// String
1329 struct MyClass {};
1330 // Not triggered for string literal tokens.
1331 const char* s = "String literal mentioning M^yClass";
1332 )cpp",
1333 R"cpp(// Ifdef'ed out code
1334 struct [[MyClass]] {};
1335 #ifdef WALDO
1336 M^yClass var;
1337 #endif
1338 )cpp",
1339 R"cpp(// Macro definition
1340 struct [[MyClass]] {};
1341 #define DECLARE_MYCLASS_OBJ(name) M^yClass name;
1342 )cpp",
1343 R"cpp(// Invalid code
1344 /*error-ok*/
1345 int myFunction(int);
1346 // Not triggered for token which survived preprocessing.
1347 int var = m^yFunction();
1348 )cpp"};
1349
1350 for (const char *Test : Tests) {
1351 Annotations T(Test);
1352 std::optional<Range> WantDecl;
1353 if (!T.ranges().empty())
1354 WantDecl = T.range();
1355
1356 auto TU = TestTU::withCode(T.code());
1357
1358 auto AST = TU.build();
1359 auto Index = TU.index();
1360 auto Word = SpelledWord::touching(
1361 cantFail(sourceLocationInMainFile(AST.getSourceManager(), T.point())),
1362 AST.getTokens(), AST.getLangOpts());
1363 if (!Word) {
1364 ADD_FAILURE() << "No word touching point!" << Test;
1365 continue;
1366 }
1367 auto Results = locateSymbolTextually(*Word, AST, Index.get(),
1368 testPath(TU.Filename), ASTNodeKind());
1369
1370 if (!WantDecl) {
1371 EXPECT_THAT(Results, IsEmpty()) << Test;
1372 } else {
1373 ASSERT_THAT(Results, ::testing::SizeIs(1)) << Test;
1374 EXPECT_EQ(Results[0].PreferredDeclaration.range, *WantDecl) << Test;
1375 }
1376 }
1377} // namespace
1378
1379TEST(LocateSymbol, Ambiguous) {
1380 auto T = Annotations(R"cpp(
1381 struct Foo {
1382 Foo();
1383 Foo(Foo&&);
1384 $ConstructorLoc[[Foo]](const char*);
1385 };
1386
1387 Foo f();
1388
1389 void g(Foo foo);
1390
1391 void call() {
1392 const char* str = "123";
1393 Foo a = $1^str;
1394 Foo b = Foo($2^str);
1395 Foo c = $3^f();
1396 $4^g($5^f());
1397 g($6^str);
1398 Foo ab$7^c;
1399 Foo ab$8^cd("asdf");
1400 Foo foox = Fo$9^o("asdf");
1401 Foo abcde$10^("asdf");
1402 Foo foox2 = Foo$11^("asdf");
1403 }
1404
1405 template <typename T>
1406 struct S {
1407 void $NonstaticOverload1[[bar]](int);
1408 void $NonstaticOverload2[[bar]](float);
1409
1410 static void $StaticOverload1[[baz]](int);
1411 static void $StaticOverload2[[baz]](float);
1412 };
1413
1414 template <typename T, typename U>
1415 void dependent_call(S<T> s, U u) {
1416 s.ba$12^r(u);
1417 S<T>::ba$13^z(u);
1418 }
1419 )cpp");
1420 auto TU = TestTU::withCode(T.code());
1421 // FIXME: Go-to-definition in a template requires disabling delayed template
1422 // parsing.
1423 TU.ExtraArgs.push_back("-fno-delayed-template-parsing");
1424 auto AST = TU.build();
1425 // Ordered assertions are deliberate: we expect a predictable order.
1426 EXPECT_THAT(locateSymbolAt(AST, T.point("1")), ElementsAre(sym("str")));
1427 EXPECT_THAT(locateSymbolAt(AST, T.point("2")), ElementsAre(sym("str")));
1428 EXPECT_THAT(locateSymbolAt(AST, T.point("3")), ElementsAre(sym("f")));
1429 EXPECT_THAT(locateSymbolAt(AST, T.point("4")), ElementsAre(sym("g")));
1430 EXPECT_THAT(locateSymbolAt(AST, T.point("5")), ElementsAre(sym("f")));
1431 EXPECT_THAT(locateSymbolAt(AST, T.point("6")), ElementsAre(sym("str")));
1432 // FIXME: Target the constructor as well.
1433 EXPECT_THAT(locateSymbolAt(AST, T.point("7")), ElementsAre(sym("abc")));
1434 // FIXME: Target the constructor as well.
1435 EXPECT_THAT(locateSymbolAt(AST, T.point("8")), ElementsAre(sym("abcd")));
1436 // FIXME: Target the constructor as well.
1437 EXPECT_THAT(locateSymbolAt(AST, T.point("9")), ElementsAre(sym("Foo")));
1438 EXPECT_THAT(locateSymbolAt(AST, T.point("10")),
1439 ElementsAre(sym("Foo", T.range("ConstructorLoc"), std::nullopt)));
1440 EXPECT_THAT(locateSymbolAt(AST, T.point("11")),
1441 ElementsAre(sym("Foo", T.range("ConstructorLoc"), std::nullopt)));
1442 // These assertions are unordered because the order comes from
1443 // CXXRecordDecl::lookupDependentName() which doesn't appear to provide
1444 // an order guarantee.
1445 EXPECT_THAT(locateSymbolAt(AST, T.point("12")),
1446 UnorderedElementsAre(
1447 sym("bar", T.range("NonstaticOverload1"), std::nullopt),
1448 sym("bar", T.range("NonstaticOverload2"), std::nullopt)));
1449 EXPECT_THAT(locateSymbolAt(AST, T.point("13")),
1450 UnorderedElementsAre(
1451 sym("baz", T.range("StaticOverload1"), std::nullopt),
1452 sym("baz", T.range("StaticOverload2"), std::nullopt)));
1453}
1454
1455TEST(LocateSymbol, TextualDependent) {
1456 // Put the declarations in the header to make sure we are
1457 // finding them via the index heuristic and not the
1458 // nearby-ident heuristic.
1459 Annotations Header(R"cpp(
1460 struct Foo {
1461 void $FooLoc[[uniqueMethodName]]();
1462 };
1463 struct Bar {
1464 void $BarLoc[[uniqueMethodName]]();
1465 };
1466 )cpp");
1467 Annotations Source(R"cpp(
1468 template <typename T>
1469 void f(T t) {
1470 t.u^niqueMethodName();
1471 }
1472 )cpp");
1473 TestTU TU;
1474 TU.Code = std::string(Source.code());
1475 TU.HeaderCode = std::string(Header.code());
1476 auto AST = TU.build();
1477 auto Index = TU.index();
1478 // Need to use locateSymbolAt() since we are testing an
1479 // interaction between locateASTReferent() and
1480 // locateSymbolNamedTextuallyAt().
1481 auto Results = locateSymbolAt(AST, Source.point(), Index.get());
1482 EXPECT_THAT(
1483 Results,
1484 UnorderedElementsAre(
1485 sym("uniqueMethodName", Header.range("FooLoc"), std::nullopt),
1486 sym("uniqueMethodName", Header.range("BarLoc"), std::nullopt)));
1487}
1488
1489TEST(LocateSymbol, Alias) {
1490 const char *Tests[] = {
1491 R"cpp(
1492 template <class T> struct function {};
1493 template <class T> using [[callback]] = function<T()>;
1494
1495 c^allback<int> foo;
1496 )cpp",
1497
1498 // triggered on non-definition of a renaming alias: should not give any
1499 // underlying decls.
1500 R"cpp(
1501 class Foo {};
1502 typedef Foo [[Bar]];
1503
1504 B^ar b;
1505 )cpp",
1506 R"cpp(
1507 class Foo {};
1508 using [[Bar]] = Foo; // definition
1509 Ba^r b;
1510 )cpp",
1511
1512 // triggered on the underlying decl of a renaming alias.
1513 R"cpp(
1514 class [[Foo]];
1515 using Bar = Fo^o;
1516 )cpp",
1517
1518 // triggered on definition of a non-renaming alias: should give underlying
1519 // decls.
1520 R"cpp(
1521 namespace ns { class [[Foo]] {}; }
1522 using ns::F^oo;
1523 )cpp",
1524
1525 R"cpp(
1526 namespace ns { int [[x]](char); int [[x]](double); }
1527 using ns::^x;
1528 )cpp",
1529
1530 R"cpp(
1531 namespace ns { int [[x]](char); int x(double); }
1532 using ns::[[x]];
1533 int y = ^x('a');
1534 )cpp",
1535
1536 R"cpp(
1537 namespace ns { class [[Foo]] {}; }
1538 using ns::[[Foo]];
1539 F^oo f;
1540 )cpp",
1541
1542 // other cases that don't matter much.
1543 R"cpp(
1544 class Foo {};
1545 typedef Foo [[Ba^r]];
1546 )cpp",
1547 R"cpp(
1548 class Foo {};
1549 using [[B^ar]] = Foo;
1550 )cpp",
1551
1552 // Member of dependent base
1553 R"cpp(
1554 template <typename T>
1555 struct Base {
1556 void [[waldo]]() {}
1557 };
1558 template <typename T>
1559 struct Derived : Base<T> {
1560 using Base<T>::w^aldo;
1561 };
1562 )cpp",
1563 };
1564
1565 for (const auto *Case : Tests) {
1566 SCOPED_TRACE(Case);
1567 auto T = Annotations(Case);
1568 auto AST = TestTU::withCode(T.code()).build();
1569 EXPECT_THAT(locateSymbolAt(AST, T.point()),
1570 UnorderedPointwise(declRange(), T.ranges()));
1571 }
1572}
1573
1574TEST(LocateSymbol, RelPathsInCompileCommand) {
1575 // The source is in "/clangd-test/src".
1576 // We build in "/clangd-test/build".
1577
1578 Annotations SourceAnnotations(R"cpp(
1579#include "header_in_preamble.h"
1580int [[foo]];
1581#include "header_not_in_preamble.h"
1582int baz = f$p1^oo + bar_pre$p2^amble + bar_not_pre$p3^amble;
1583)cpp");
1584
1585 Annotations HeaderInPreambleAnnotations(R"cpp(
1586int [[bar_preamble]];
1587)cpp");
1588
1589 Annotations HeaderNotInPreambleAnnotations(R"cpp(
1590int [[bar_not_preamble]];
1591)cpp");
1592
1593 // Make the compilation paths appear as ../src/foo.cpp in the compile
1594 // commands.
1595 SmallString<32> RelPathPrefix("..");
1596 llvm::sys::path::append(RelPathPrefix, "src");
1597 std::string BuildDir = testPath("build");
1598 MockCompilationDatabase CDB(BuildDir, RelPathPrefix);
1599
1600 MockFS FS;
1601 ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
1602
1603 // Fill the filesystem.
1604 auto FooCpp = testPath("src/foo.cpp");
1605 FS.Files[FooCpp] = "";
1606 auto HeaderInPreambleH = testPath("src/header_in_preamble.h");
1607 FS.Files[HeaderInPreambleH] = std::string(HeaderInPreambleAnnotations.code());
1608 auto HeaderNotInPreambleH = testPath("src/header_not_in_preamble.h");
1609 FS.Files[HeaderNotInPreambleH] =
1610 std::string(HeaderNotInPreambleAnnotations.code());
1611
1612 runAddDocument(Server, FooCpp, SourceAnnotations.code());
1613
1614 // Go to a definition in main source file.
1615 auto Locations =
1616 runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("p1"));
1617 EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error";
1618 EXPECT_THAT(*Locations, ElementsAre(sym("foo", SourceAnnotations.range(),
1619 SourceAnnotations.range())));
1620
1621 // Go to a definition in header_in_preamble.h.
1622 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("p2"));
1623 EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error";
1624 EXPECT_THAT(
1625 *Locations,
1626 ElementsAre(sym("bar_preamble", HeaderInPreambleAnnotations.range(),
1627 HeaderInPreambleAnnotations.range())));
1628
1629 // Go to a definition in header_not_in_preamble.h.
1630 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("p3"));
1631 EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error";
1632 EXPECT_THAT(*Locations,
1633 ElementsAre(sym("bar_not_preamble",
1634 HeaderNotInPreambleAnnotations.range(),
1635 HeaderNotInPreambleAnnotations.range())));
1636}
1637
1638TEST(GoToInclude, All) {
1639 MockFS FS;
1641 ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
1642
1643 auto FooCpp = testPath("foo.cpp");
1644 const char *SourceContents = R"cpp(
1645 #include ^"$2^foo.h$3^"
1646 #include "$4^invalid.h"
1647 int b = a;
1648 // test
1649 int foo;
1650 #in$5^clude "$6^foo.h"$7^
1651 )cpp";
1652 Annotations SourceAnnotations(SourceContents);
1653 FS.Files[FooCpp] = std::string(SourceAnnotations.code());
1654 auto FooH = testPath("foo.h");
1655
1656 const char *HeaderContents = R"cpp([[]]#pragma once
1657 int a;
1658 )cpp";
1659 Annotations HeaderAnnotations(HeaderContents);
1660 FS.Files[FooH] = std::string(HeaderAnnotations.code());
1661
1662 runAddDocument(Server, FooH, HeaderAnnotations.code());
1663 runAddDocument(Server, FooCpp, SourceAnnotations.code());
1664
1665 // Test include in preamble.
1666 auto Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point());
1667 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1668 EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(),
1669 HeaderAnnotations.range())));
1670
1671 // Test include in preamble, last char.
1672 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("2"));
1673 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1674 EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(),
1675 HeaderAnnotations.range())));
1676
1677 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("3"));
1678 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1679 EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(),
1680 HeaderAnnotations.range())));
1681
1682 // Test include outside of preamble.
1683 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("6"));
1684 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1685 EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(),
1686 HeaderAnnotations.range())));
1687
1688 // Test a few positions that do not result in Locations.
1689 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("4"));
1690 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1691 EXPECT_THAT(*Locations, IsEmpty());
1692
1693 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("5"));
1694 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1695 EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(),
1696 HeaderAnnotations.range())));
1697
1698 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("7"));
1699 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1700 EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(),
1701 HeaderAnnotations.range())));
1702
1703 // Objective C #import directive.
1704 Annotations ObjC(R"objc(
1705 #import "^foo.h"
1706 )objc");
1707 auto FooM = testPath("foo.m");
1708 FS.Files[FooM] = std::string(ObjC.code());
1709
1710 runAddDocument(Server, FooM, ObjC.code());
1711 Locations = runLocateSymbolAt(Server, FooM, ObjC.point());
1712 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
1713 EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(),
1714 HeaderAnnotations.range())));
1715}
1716
1717TEST(LocateSymbol, WithPreamble) {
1718 // Test stragety: AST should always use the latest preamble instead of last
1719 // good preamble.
1720 MockFS FS;
1722 ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
1723
1724 auto FooCpp = testPath("foo.cpp");
1725 // The trigger locations must be the same.
1726 Annotations FooWithHeader(R"cpp(#include "fo^o.h")cpp");
1727 Annotations FooWithoutHeader(R"cpp(double [[fo^o]]();)cpp");
1728
1729 FS.Files[FooCpp] = std::string(FooWithHeader.code());
1730
1731 auto FooH = testPath("foo.h");
1732 Annotations FooHeader(R"cpp([[]])cpp");
1733 FS.Files[FooH] = std::string(FooHeader.code());
1734
1735 runAddDocument(Server, FooCpp, FooWithHeader.code());
1736 // LocateSymbol goes to a #include file: the result comes from the preamble.
1737 EXPECT_THAT(
1738 cantFail(runLocateSymbolAt(Server, FooCpp, FooWithHeader.point())),
1739 ElementsAre(sym("foo.h", FooHeader.range(), FooHeader.range())));
1740
1741 // Only preamble is built, and no AST is built in this request.
1742 Server.addDocument(FooCpp, FooWithoutHeader.code(), "null",
1744 // We build AST here, and it should use the latest preamble rather than the
1745 // stale one.
1746 EXPECT_THAT(
1747 cantFail(runLocateSymbolAt(Server, FooCpp, FooWithoutHeader.point())),
1748 ElementsAre(sym("foo", FooWithoutHeader.range(), std::nullopt)));
1749
1750 // Reset test environment.
1751 runAddDocument(Server, FooCpp, FooWithHeader.code());
1752 // Both preamble and AST are built in this request.
1753 Server.addDocument(FooCpp, FooWithoutHeader.code(), "null",
1755 // Use the AST being built in above request.
1756 EXPECT_THAT(
1757 cantFail(runLocateSymbolAt(Server, FooCpp, FooWithoutHeader.point())),
1758 ElementsAre(sym("foo", FooWithoutHeader.range(), std::nullopt)));
1759}
1760
1761TEST(LocateSymbol, NearbyTokenSmoke) {
1762 auto T = Annotations(R"cpp(
1763 // prints e^rr and crashes
1764 void die(const char* [[err]]);
1765 )cpp");
1766 auto AST = TestTU::withCode(T.code()).build();
1767 // We don't pass an index, so can't hit index-based fallback.
1768 EXPECT_THAT(locateSymbolAt(AST, T.point()),
1769 ElementsAre(sym("err", T.range(), T.range())));
1770}
1771
1772TEST(LocateSymbol, NearbyIdentifier) {
1773 const char *Tests[] = {
1774 R"cpp(
1775 // regular identifiers (won't trigger)
1776 int hello;
1777 int y = he^llo;
1778 )cpp",
1779 R"cpp(
1780 // disabled preprocessor sections
1781 int [[hello]];
1782 #if 0
1783 int y = ^hello;
1784 #endif
1785 )cpp",
1786 R"cpp(
1787 // comments
1788 // he^llo, world
1789 int [[hello]];
1790 )cpp",
1791 R"cpp(
1792 // not triggered by string literals
1793 int hello;
1794 const char* greeting = "h^ello, world";
1795 )cpp",
1796
1797 R"cpp(
1798 // can refer to macro invocations
1799 #define INT int
1800 [[INT]] x;
1801 // I^NT
1802 )cpp",
1803
1804 R"cpp(
1805 // can refer to macro invocations (even if they expand to nothing)
1806 #define EMPTY
1807 [[EMPTY]] int x;
1808 // E^MPTY
1809 )cpp",
1810
1811 R"cpp(
1812 // prefer nearest occurrence, backwards is worse than forwards
1813 int hello;
1814 int x = hello;
1815 // h^ello
1816 int y = [[hello]];
1817 int z = hello;
1818 )cpp",
1819
1820 R"cpp(
1821 // short identifiers find near results
1822 int [[hi]];
1823 // h^i
1824 )cpp",
1825 R"cpp(
1826 // short identifiers don't find far results
1827 int hi;
1828
1829
1830
1831 // h^i
1832
1833
1834
1835
1836 int x = hi;
1837 )cpp",
1838 R"cpp(
1839 // prefer nearest occurrence even if several matched tokens
1840 // have the same value of `floor(log2(<token line> - <word line>))`.
1841 int hello;
1842 int x = hello, y = hello;
1843 int z = [[hello]];
1844 // h^ello
1845 )cpp"};
1846 for (const char *Test : Tests) {
1847 Annotations T(Test);
1848 auto AST = TestTU::withCode(T.code()).build();
1849 const auto &SM = AST.getSourceManager();
1850 std::optional<Range> Nearby;
1851 auto Word =
1852 SpelledWord::touching(cantFail(sourceLocationInMainFile(SM, T.point())),
1853 AST.getTokens(), AST.getLangOpts());
1854 if (!Word) {
1855 ADD_FAILURE() << "No word at point! " << Test;
1856 continue;
1857 }
1858 if (const auto *Tok = findNearbyIdentifier(*Word, AST.getTokens()))
1859 Nearby = halfOpenToRange(SM, CharSourceRange::getCharRange(
1860 Tok->location(), Tok->endLocation()));
1861 if (T.ranges().empty())
1862 EXPECT_THAT(Nearby, Eq(std::nullopt)) << Test;
1863 else
1864 EXPECT_EQ(Nearby, T.range()) << Test;
1865 }
1866}
1867
1868TEST(FindImplementations, Inheritance) {
1869 llvm::StringRef Test = R"cpp(
1870 struct $0^Base {
1871 virtual void F$1^oo();
1872 void C$4^oncrete();
1873 };
1874 struct $0[[Child1]] : Base {
1875 void $1[[Fo$3^o]]() override;
1876 virtual void B$2^ar();
1877 void Concrete(); // No implementations for concrete methods.
1878 };
1879 struct Child2 : Child1 {
1880 void $3[[Foo]]() override;
1881 void $2[[Bar]]() override;
1882 };
1883 void FromReference() {
1884 $0^Base* B;
1885 B->Fo$1^o();
1886 B->C$4^oncrete();
1887 &Base::Fo$1^o;
1888 Child1 * C1;
1889 C1->B$2^ar();
1890 C1->Fo$3^o();
1891 }
1892 // CRTP should work.
1893 template<typename T>
1894 struct $5^TemplateBase {};
1895 struct $5[[Child3]] : public TemplateBase<Child3> {};
1896
1897 // Local classes.
1898 void LocationFunction() {
1899 struct $0[[LocalClass1]] : Base {
1900 void $1[[Foo]]() override;
1901 };
1902 struct $6^LocalBase {
1903 virtual void $7^Bar();
1904 };
1905 struct $6[[LocalClass2]]: LocalBase {
1906 void $7[[Bar]]() override;
1907 };
1908 }
1909 )cpp";
1910
1911 Annotations Code(Test);
1912 auto TU = TestTU::withCode(Code.code());
1913 auto AST = TU.build();
1914 auto Index = TU.index();
1915 for (StringRef Label : {"0", "1", "2", "3", "4", "5", "6", "7"}) {
1916 for (const auto &Point : Code.points(Label)) {
1917 EXPECT_THAT(findImplementations(AST, Point, Index.get()),
1918 UnorderedPointwise(declRange(), Code.ranges(Label)))
1919 << Code.code() << " at " << Point << " for Label " << Label;
1920 }
1921 }
1922}
1923
1924TEST(FindImplementations, InheritanceObjC) {
1925 llvm::StringRef Test = R"objc(
1926 @interface $base^Base
1927 - (void)fo$foo^o;
1928 @end
1929 @protocol Protocol
1930 - (void)$protocol^protocol;
1931 @end
1932 @interface $ChildDecl[[Child]] : Base <Protocol>
1933 - (void)concrete;
1934 - (void)$fooDecl[[foo]];
1935 @end
1936 @implementation $ChildDef[[Child]]
1937 - (void)concrete {}
1938 - (void)$fooDef[[foo]] {}
1939 - (void)$protocolDef[[protocol]] {}
1940 @end
1941 )objc";
1942
1943 Annotations Code(Test);
1944 auto TU = TestTU::withCode(Code.code());
1945 TU.ExtraArgs.push_back("-xobjective-c++");
1946 auto AST = TU.build();
1947 auto Index = TU.index();
1948 EXPECT_THAT(findImplementations(AST, Code.point("base"), Index.get()),
1949 UnorderedElementsAre(sym("Child", Code.range("ChildDecl"),
1950 Code.range("ChildDef"))));
1951 EXPECT_THAT(findImplementations(AST, Code.point("foo"), Index.get()),
1952 UnorderedElementsAre(
1953 sym("foo", Code.range("fooDecl"), Code.range("fooDef"))));
1954 EXPECT_THAT(findImplementations(AST, Code.point("protocol"), Index.get()),
1955 UnorderedElementsAre(sym("protocol", Code.range("protocolDef"),
1956 Code.range("protocolDef"))));
1957}
1958
1959TEST(FindImplementations, CaptureDefinition) {
1960 llvm::StringRef Test = R"cpp(
1961 struct Base {
1962 virtual void F^oo();
1963 };
1964 struct Child1 : Base {
1965 void $Decl[[Foo]]() override;
1966 };
1967 struct Child2 : Base {
1968 void $Child2[[Foo]]() override;
1969 };
1970 void Child1::$Def[[Foo]]() { /* Definition */ }
1971 )cpp";
1972 Annotations Code(Test);
1973 auto TU = TestTU::withCode(Code.code());
1974 auto AST = TU.build();
1975 EXPECT_THAT(
1976 findImplementations(AST, Code.point(), TU.index().get()),
1977 UnorderedElementsAre(sym("Foo", Code.range("Decl"), Code.range("Def")),
1978 sym("Foo", Code.range("Child2"), std::nullopt)))
1979 << Test;
1980}
1981
1982TEST(FindType, All) {
1983 Annotations HeaderA(R"cpp(
1984 struct $Target[[Target]] { operator int() const; };
1985 struct Aggregate { Target a, b; };
1986 Target t;
1987 Target make();
1988
1989 template <typename T> struct $smart_ptr[[smart_ptr]] {
1990 T& operator*();
1991 T* operator->();
1992 T* get();
1993 };
1994 )cpp");
1995 auto TU = TestTU::withHeaderCode(HeaderA.code());
1996 for (const llvm::StringRef Case : {
1997 "str^uct Target;",
1998 "T^arget x;",
1999 "Target ^x;",
2000 "a^uto x = Target{};",
2001 "namespace m { Target tgt; } auto x = m^::tgt;",
2002 "Target funcCall(); auto x = ^funcCall();",
2003 "Aggregate a = { {}, ^{} };",
2004 "Aggregate a = { ^.a=t, };",
2005 "struct X { Target a; X() : ^a() {} };",
2006 "^using T = Target; ^T foo();",
2007 "^template <int> Target foo();",
2008 "void x() { try {} ^catch(Target e) {} }",
2009 "void x() { ^throw t; }",
2010 "int x() { ^return t; }",
2011 "void x() { ^switch(t) {} }",
2012 "void x() { ^delete (Target*)nullptr; }",
2013 "Target& ^tref = t;",
2014 "void x() { ^if (t) {} }",
2015 "void x() { ^while (t) {} }",
2016 "void x() { ^do { } while (t); }",
2017 "void x() { ^make(); }",
2018 "void x(smart_ptr<Target> &t) { t.^get(); }",
2019 "^auto x = []() { return t; };",
2020 "Target* ^tptr = &t;",
2021 "Target ^tarray[3];",
2022 }) {
2023 Annotations A(Case);
2024 TU.Code = A.code().str();
2025 ParsedAST AST = TU.build();
2026
2027 ASSERT_GT(A.points().size(), 0u) << Case;
2028 for (auto Pos : A.points())
2029 EXPECT_THAT(findType(AST, Pos, nullptr),
2030 ElementsAre(
2031 sym("Target", HeaderA.range("Target"), HeaderA.range("Target"))))
2032 << Case;
2033 }
2034
2035 for (const llvm::StringRef Case : {
2036 "smart_ptr<Target> ^tsmart;",
2037 }) {
2038 Annotations A(Case);
2039 TU.Code = A.code().str();
2040 ParsedAST AST = TU.build();
2041
2042 EXPECT_THAT(findType(AST, A.point(), nullptr),
2043 UnorderedElementsAre(
2044 sym("Target", HeaderA.range("Target"), HeaderA.range("Target")),
2045 sym("smart_ptr", HeaderA.range("smart_ptr"), HeaderA.range("smart_ptr"))
2046 ))
2047 << Case;
2048 }
2049}
2050
2051TEST(FindType, Definition) {
2052 Annotations A(R"cpp(
2053 class $decl[[X]];
2054 X *^x;
2055 class $def[[X]] {};
2056 )cpp");
2057 auto TU = TestTU::withCode(A.code().str());
2058 ParsedAST AST = TU.build();
2059
2060 EXPECT_THAT(findType(AST, A.point(), nullptr),
2061 ElementsAre(sym("X", A.range("decl"), A.range("def"))));
2062}
2063
2064TEST(FindType, Index) {
2065 Annotations Def(R"cpp(
2066 // This definition is only available through the index.
2067 class [[X]] {};
2068 )cpp");
2069 TestTU DefTU = TestTU::withHeaderCode(Def.code());
2070 DefTU.HeaderFilename = "def.h";
2071 auto DefIdx = DefTU.index();
2072
2073 Annotations A(R"cpp(
2074 class [[X]];
2075 X *^x;
2076 )cpp");
2077 auto TU = TestTU::withCode(A.code().str());
2078 ParsedAST AST = TU.build();
2079
2080 EXPECT_THAT(findType(AST, A.point(), DefIdx.get()),
2081 ElementsAre(sym("X", A.range(), Def.range())));
2082}
2083
2084void checkFindRefs(llvm::StringRef Test, bool UseIndex = false) {
2085 Annotations T(Test);
2086 auto TU = TestTU::withCode(T.code());
2087 TU.ExtraArgs.push_back("-std=c++20");
2088 TU.ExtraArgs.push_back("-xobjective-c++");
2089
2090 auto AST = TU.build();
2091 std::vector<Matcher<ReferencesResult::Reference>> ExpectedLocations;
2092 for (const auto &[R, Context] : T.rangesWithPayload())
2093 ExpectedLocations.push_back(
2094 AllOf(rangeIs(R), containerIs(Context), attrsAre(0u)));
2095 // $def is actually shorthand for both definition and declaration.
2096 // If we have cases that are definition-only, we should change this.
2097 for (const auto &[R, Context] : T.rangesWithPayload("def"))
2098 ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(Context),
2101 for (const auto &[R, Context] : T.rangesWithPayload("decl"))
2102 ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(Context),
2104 for (const auto &[R, Context] : T.rangesWithPayload("overridedecl"))
2105 ExpectedLocations.push_back(AllOf(
2106 rangeIs(R), containerIs(Context),
2108 for (const auto &[R, Context] : T.rangesWithPayload("overridedef"))
2109 ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(Context),
2113 for (const auto &P : T.points()) {
2114 EXPECT_THAT(findReferences(AST, P, 0, UseIndex ? TU.index().get() : nullptr,
2115 /*AddContext*/ true)
2116 .References,
2117 UnorderedElementsAreArray(ExpectedLocations))
2118 << "Failed for Refs at " << P << "\n"
2119 << Test;
2120 }
2121}
2122
2123TEST(FindReferences, WithinAST) {
2124 const char *Tests[] = {
2125 R"cpp(// Local variable
2126 int main() {
2127 int $def(main)[[foo]];
2128 $(main)[[^foo]] = 2;
2129 int test1 = $(main)[[foo]];
2130 }
2131 )cpp",
2132
2133 R"cpp(// Struct
2134 namespace ns1 {
2135 struct $def(ns1)[[Foo]] {};
2136 } // namespace ns1
2137 int main() {
2138 ns1::$(main)[[Fo^o]]* Params;
2139 }
2140 )cpp",
2141
2142 R"cpp(// Forward declaration
2143 class $decl[[Foo]];
2144 class $def[[Foo]] {};
2145 int main() {
2146 $(main)[[Fo^o]] foo;
2147 }
2148 )cpp",
2149
2150 R"cpp(// Function
2151 int $def[[foo]](int) { return 0; }
2152 int main() {
2153 auto *X = &$(main)[[^foo]];
2154 $(main)[[foo]](42);
2155 }
2156 )cpp",
2157
2158 R"cpp(// Field
2159 struct Foo {
2160 int $def(Foo)[[foo]];
2161 Foo() : $(Foo::Foo)[[foo]](0) {}
2162 };
2163 int main() {
2164 Foo f;
2165 f.$(main)[[f^oo]] = 1;
2166 }
2167 )cpp",
2168
2169 R"cpp(// Method call
2170 struct Foo { int $decl(Foo)[[foo]](); };
2171 int Foo::$def(Foo)[[foo]]() { return 0; }
2172 int main() {
2173 Foo f;
2174 f.$(main)[[^foo]]();
2175 }
2176 )cpp",
2177
2178 R"cpp(// Constructor
2179 struct Foo {
2180 $decl(Foo)[[F^oo]](int);
2181 };
2182 void foo() {
2183 Foo f = $(foo)[[Foo]](42);
2184 }
2185 )cpp",
2186
2187 R"cpp(// Typedef
2188 typedef int $def[[Foo]];
2189 int main() {
2190 $(main)[[^Foo]] bar;
2191 }
2192 )cpp",
2193
2194 R"cpp(// Namespace
2195 namespace $decl[[ns]] { // FIXME: def?
2196 struct Foo {};
2197 } // namespace ns
2198 int main() { $(main)[[^ns]]::Foo foo; }
2199 )cpp",
2200
2201 R"cpp(// Macros
2202 #define TYPE(X) X
2203 #define FOO Foo
2204 #define CAT(X, Y) X##Y
2205 class $def[[Fo^o]] {};
2206 void test() {
2207 TYPE($(test)[[Foo]]) foo;
2208 $(test)[[FOO]] foo2;
2209 TYPE(TYPE($(test)[[Foo]])) foo3;
2210 $(test)[[CAT]](Fo, o) foo4;
2211 }
2212 )cpp",
2213
2214 R"cpp(// Macros
2215 #define $def[[MA^CRO]](X) (X+1)
2216 void test() {
2217 int x = $[[MACRO]]($[[MACRO]](1));
2218 }
2219 )cpp",
2220
2221 R"cpp(// Macro outside preamble
2222 int breakPreamble;
2223 #define $def[[MA^CRO]](X) (X+1)
2224 void test() {
2225 int x = $[[MACRO]]($[[MACRO]](1));
2226 }
2227 )cpp",
2228
2229 R"cpp(
2230 int $def[[v^ar]] = 0;
2231 void foo(int s = $(foo)[[var]]);
2232 )cpp",
2233
2234 R"cpp(
2235 template <typename T>
2236 class $def[[Fo^o]] {};
2237 void func($(func)[[Foo]]<int>);
2238 )cpp",
2239
2240 R"cpp(
2241 template <typename T>
2242 class $def[[Foo]] {};
2243 void func($(func)[[Fo^o]]<int>);
2244 )cpp",
2245 R"cpp(// Not touching any identifiers.
2246 struct Foo {
2247 $def(Foo)[[~]]Foo() {};
2248 };
2249 void foo() {
2250 Foo f;
2251 f.$(foo)[[^~]]Foo();
2252 }
2253 )cpp",
2254 R"cpp(// Lambda capture initializer
2255 void foo() {
2256 int $def(foo)[[w^aldo]] = 42;
2257 auto lambda = [x = $(foo)[[waldo]]](){};
2258 }
2259 )cpp",
2260 R"cpp(// Renaming alias
2261 template <typename> class Vector {};
2262 using $def[[^X]] = Vector<int>;
2263 $(x1)[[X]] x1;
2264 Vector<int> x2;
2265 Vector<double> y;
2266 )cpp",
2267 R"cpp(// Dependent code
2268 template <typename T> void $decl[[foo]](T t);
2269 template <typename T> void bar(T t) { $(bar)[[foo]](t); } // foo in bar is uninstantiated.
2270 void baz(int x) { $(baz)[[f^oo]](x); }
2271 )cpp",
2272 R"cpp(
2273 namespace ns {
2274 struct S{};
2275 void $decl(ns)[[foo]](S s);
2276 } // namespace ns
2277 template <typename T> void foo(T t);
2278 // FIXME: Maybe report this foo as a ref to ns::foo (because of ADL)
2279 // when bar<ns::S> is instantiated?
2280 template <typename T> void bar(T t) { foo(t); }
2281 void baz(int x) {
2282 ns::S s;
2283 bar<ns::S>(s);
2284 $(baz)[[f^oo]](s);
2285 }
2286 )cpp",
2287 R"cpp(// unresolved member expression
2288 struct Foo {
2289 template <typename T> void $decl(Foo)[[b^ar]](T t);
2290 };
2291 template <typename T> void test(Foo F, T t) {
2292 F.$(test)[[bar]](t);
2293 }
2294 )cpp",
2295
2296 // Enum base
2297 R"cpp(
2298 typedef int $def[[MyTypeD^ef]];
2299 enum MyEnum : $(MyEnum)[[MyTy^peDef]] { };
2300 )cpp",
2301 R"cpp(
2302 typedef int $def[[MyType^Def]];
2303 enum MyEnum : $(MyEnum)[[MyTypeD^ef]];
2304 )cpp",
2305 R"cpp(
2306 using $def[[MyTypeD^ef]] = int;
2307 enum MyEnum : $(MyEnum)[[MyTy^peDef]] { };
2308 )cpp",
2309 // UDL
2310 R"cpp(
2311 bool $decl[[operator]]"" _u^dl(unsigned long long value);
2312 bool x = $(x)[[1_udl]];
2313 )cpp",
2314 R"cpp(
2315 struct S {
2316 public:
2317 static void $decl(S)[[operator]] delete(void *);
2318 static void deleteObject(S *S) {
2319 $(S::deleteObject)[[de^lete]] S;
2320 }
2321 };
2322 )cpp",
2323 // Array designators
2324 R"cpp(
2325 const int $def[[F^oo]] = 0;
2326 int Bar[] = {
2327 [$(Bar)[[F^oo]]...$(Bar)[[Fo^o]] + 1] = 0,
2328 [$(Bar)[[^Foo]] + 2] = 1
2329 };
2330 )cpp"};
2331 for (const char *Test : Tests)
2332 checkFindRefs(Test);
2333}
2334
2335TEST(FindReferences, ConceptsWithinAST) {
2336 constexpr llvm::StringLiteral Code = R"cpp(
2337 template <class T>
2338 concept $def[[IsSmal^l]] = sizeof(T) <= 8;
2339
2340 template <class T>
2341 concept IsSmallPtr = requires(T x) {
2342 { *x } -> $(IsSmallPtr)[[IsSmal^l]];
2343 };
2344
2345 $(i)[[IsSmall]] auto i = 'c';
2346 template<$(foo)[[IsSmal^l]] U> void foo();
2347 template<class U> void bar() requires $(bar)[[IsSmal^l]]<U>;
2348 template<class U> requires $(baz)[[IsSmal^l]]<U> void baz();
2349 static_assert([[IsSma^ll]]<char>);
2350 )cpp";
2351 checkFindRefs(Code);
2352}
2353
2354TEST(FindReferences, ConceptReq) {
2355 constexpr llvm::StringLiteral Code = R"cpp(
2356 template <class T>
2357 concept $def[[IsSmal^l]] = sizeof(T) <= 8;
2358
2359 template <class T>
2360 concept IsSmallPtr = requires(T x) {
2361 { *x } -> $(IsSmallPtr)[[IsSmal^l]];
2362 };
2363 )cpp";
2364 checkFindRefs(Code);
2365}
2366
2367TEST(FindReferences, RequiresExprParameters) {
2368 constexpr llvm::StringLiteral Code = R"cpp(
2369 template <class T>
2370 concept IsSmall = sizeof(T) <= 8;
2371
2372 template <class T>
2373 concept IsSmallPtr = requires(T $def[[^x]]) {
2374 { *$(IsSmallPtr)[[^x]] } -> IsSmall;
2375 };
2376 )cpp";
2377 checkFindRefs(Code);
2378}
2379
2380TEST(FindReferences, IncludeOverrides) {
2381 llvm::StringRef Test =
2382 R"cpp(
2383 class Base {
2384 public:
2385 virtu^al void $decl(Base)[[f^unc]]() ^= ^0;
2386 };
2387 class Derived : public Base {
2388 public:
2389 void $overridedecl(Derived::func)[[func]]() override;
2390 };
2391 void Derived::$overridedef[[func]]() {}
2392 class Derived2 : public Base {
2393 void $overridedef(Derived2::func)[[func]]() override {}
2394 };
2395 void test(Derived* D, Base* B) {
2396 D->func(); // No references to the overrides.
2397 B->$(test)[[func]]();
2398 })cpp";
2399 checkFindRefs(Test, /*UseIndex=*/true);
2400}
2401
2402TEST(FindReferences, IncludeOverridesObjC) {
2403 llvm::StringRef Test =
2404 R"objc(
2405 @interface Base
2406 - (void)$decl(Base)[[f^unc]];
2407 @end
2408 @interface Derived : Base
2409 - (void)$overridedecl(Derived::func)[[func]];
2410 @end
2411 @implementation Derived
2412 - (void)$overridedef[[func]] {}
2413 @end
2414 void test(Derived *derived, Base *base) {
2415 [derived func]; // No references to the overrides.
2416 [base $(test)[[func]]];
2417 })objc";
2418 checkFindRefs(Test, /*UseIndex=*/true);
2419}
2420
2421TEST(FindReferences, RefsToBaseMethod) {
2422 llvm::StringRef Test =
2423 R"cpp(
2424 class BaseBase {
2425 public:
2426 virtual void $(BaseBase)[[func]]();
2427 };
2428 class Base : public BaseBase {
2429 public:
2430 void $(Base)[[func]]() override;
2431 };
2432 class Derived : public Base {
2433 public:
2434 void $decl(Derived)[[fu^nc]]() over^ride;
2435 };
2436 void test(BaseBase* BB, Base* B, Derived* D) {
2437 // refs to overridden methods in complete type hierarchy are reported.
2438 BB->$(test)[[func]]();
2439 B->$(test)[[func]]();
2440 D->$(test)[[fu^nc]]();
2441 })cpp";
2442 checkFindRefs(Test, /*UseIndex=*/true);
2443}
2444
2445TEST(FindReferences, RefsToBaseMethodObjC) {
2446 llvm::StringRef Test =
2447 R"objc(
2448 @interface BaseBase
2449 - (void)$(BaseBase)[[func]];
2450 @end
2451 @interface Base : BaseBase
2452 - (void)$(Base)[[func]];
2453 @end
2454 @interface Derived : Base
2455 - (void)$decl(Derived)[[fu^nc]];
2456 @end
2457 void test(BaseBase *bb, Base *b, Derived *d) {
2458 // refs to overridden methods in complete type hierarchy are reported.
2459 [bb $(test)[[func]]];
2460 [b $(test)[[func]]];
2461 [d $(test)[[fu^nc]]];
2462 })objc";
2463 checkFindRefs(Test, /*UseIndex=*/true);
2464}
2465
2466TEST(FindReferences, MainFileReferencesOnly) {
2467 llvm::StringRef Test =
2468 R"cpp(
2469 void test() {
2470 int [[fo^o]] = 1;
2471 // refs not from main file should not be included.
2472 #include "foo.inc"
2473 })cpp";
2474
2475 Annotations Code(Test);
2476 auto TU = TestTU::withCode(Code.code());
2477 TU.AdditionalFiles["foo.inc"] = R"cpp(
2478 foo = 3;
2479 )cpp";
2480 auto AST = TU.build();
2481
2482 std::vector<Matcher<ReferencesResult::Reference>> ExpectedLocations;
2483 for (const auto &R : Code.ranges())
2484 ExpectedLocations.push_back(rangeIs(R));
2485 EXPECT_THAT(findReferences(AST, Code.point(), 0).References,
2486 ElementsAreArray(ExpectedLocations))
2487 << Test;
2488}
2489
2490TEST(FindReferences, ExplicitSymbols) {
2491 const char *Tests[] = {
2492 R"cpp(
2493 struct Foo { Foo* $decl(Foo)[[self]]() const; };
2494 void f() {
2495 Foo foo;
2496 if (Foo* T = foo.$(f)[[^self]]()) {} // Foo member call expr.
2497 }
2498 )cpp",
2499
2500 R"cpp(
2501 struct Foo { Foo(int); };
2502 Foo f() {
2503 int $def(f)[[b]];
2504 return $(f)[[^b]]; // Foo constructor expr.
2505 }
2506 )cpp",
2507
2508 R"cpp(
2509 struct Foo {};
2510 void g(Foo);
2511 Foo $decl[[f]]();
2512 void call() {
2513 g($(call)[[^f]]()); // Foo constructor expr.
2514 }
2515 )cpp",
2516
2517 R"cpp(
2518 void $decl[[foo]](int);
2519 void $decl[[foo]](double);
2520
2521 namespace ns {
2522 using ::$decl(ns)[[fo^o]];
2523 }
2524 )cpp",
2525
2526 R"cpp(
2527 struct X {
2528 operator bool();
2529 };
2530
2531 int test() {
2532 X $def(test)[[a]];
2533 $(test)[[a]].operator bool();
2534 if ($(test)[[a^]]) {} // ignore implicit conversion-operator AST node
2535 return 0;
2536 }
2537 )cpp",
2538 };
2539 for (const char *Test : Tests)
2540 checkFindRefs(Test);
2541}
2542
2543TEST(FindReferences, UsedSymbolsFromInclude) {
2544 const char *Tests[] = {
2545 R"cpp( [[#include ^"bar.h"]]
2546 #include <vector>
2547 int fstBar = [[bar1]]();
2548 int sndBar = [[bar2]]();
2549 [[Bar]] bar;
2550 int macroBar = [[BAR]];
2551 std::vector<int> vec;
2552 )cpp",
2553
2554 R"cpp([[#in^clude <vector>]]
2555 std::[[vector]]<int> vec;
2556 )cpp",
2557
2558 R"cpp(
2559 [[#include ^"udl_header.h"]]
2560 auto x = [[1_b]];
2561 )cpp",
2562 };
2563 for (const char *Test : Tests) {
2564 Annotations T(Test);
2565 auto TU = TestTU::withCode(T.code());
2566 TU.ExtraArgs.push_back("-std=c++20");
2567 TU.AdditionalFiles["bar.h"] = guard(R"cpp(
2568 #define BAR 5
2569 int bar1();
2570 int bar2();
2571 class Bar {};
2572 )cpp");
2573 TU.AdditionalFiles["system/vector"] = guard(R"cpp(
2574 namespace std {
2575 template<typename>
2576 class vector{};
2577 }
2578 )cpp");
2579 TU.AdditionalFiles["udl_header.h"] = guard(R"cpp(
2580 bool operator"" _b(unsigned long long value);
2581 )cpp");
2582 TU.ExtraArgs.push_back("-isystem" + testPath("system"));
2583
2584 auto AST = TU.build();
2585 std::vector<Matcher<ReferencesResult::Reference>> ExpectedLocations;
2586 for (const auto &R : T.ranges())
2587 ExpectedLocations.push_back(AllOf(rangeIs(R), attrsAre(0u)));
2588 for (const auto &P : T.points())
2589 EXPECT_THAT(findReferences(AST, P, 0).References,
2590 UnorderedElementsAreArray(ExpectedLocations))
2591 << "Failed for Refs at " << P << "\n"
2592 << Test;
2593 }
2594}
2595
2596TEST(FindReferences, NeedsIndexForSymbols) {
2597 const char *Header = "int foo();";
2598 Annotations Main("int main() { [[f^oo]](); }");
2599 TestTU TU;
2600 TU.Code = std::string(Main.code());
2601 TU.HeaderCode = Header;
2602 auto AST = TU.build();
2603
2604 // References in main file are returned without index.
2605 EXPECT_THAT(
2606 findReferences(AST, Main.point(), 0, /*Index=*/nullptr).References,
2607 ElementsAre(rangeIs(Main.range())));
2608 Annotations IndexedMain(R"cpp(
2609 int $decl[[foo]]() { return 42; }
2610 void bar() { $bar(bar)[[foo]](); }
2611 struct S { void bar() { $S(S::bar)[[foo]](); } };
2612 namespace N { void bar() { $N(N::bar)[[foo]](); } }
2613 )cpp");
2614
2615 // References from indexed files are included.
2616 TestTU IndexedTU;
2617 IndexedTU.Code = std::string(IndexedMain.code());
2618 IndexedTU.Filename = "Indexed.cpp";
2619 IndexedTU.HeaderCode = Header;
2620 EXPECT_THAT(
2621 findReferences(AST, Main.point(), 0, IndexedTU.index().get(),
2622 /*AddContext*/ true)
2623 .References,
2624 ElementsAre(
2625 rangeIs(Main.range()),
2626 AllOf(rangeIs(IndexedMain.range("decl")),
2629 AllOf(rangeIs(IndexedMain.range("bar")), containerIs("bar")),
2630 AllOf(rangeIs(IndexedMain.range("S")), containerIs("S::bar")),
2631 AllOf(rangeIs(IndexedMain.range("N")), containerIs("N::bar"))));
2632 auto LimitRefs =
2633 findReferences(AST, Main.point(), /*Limit*/ 1, IndexedTU.index().get());
2634 EXPECT_EQ(1u, LimitRefs.References.size());
2635 EXPECT_TRUE(LimitRefs.HasMore);
2636
2637 // Avoid indexed results for the main file. Use AST for the mainfile.
2638 TU.Code = ("\n\n" + Main.code()).str();
2639 EXPECT_THAT(findReferences(AST, Main.point(), 0, TU.index().get()).References,
2640 ElementsAre(rangeIs(Main.range())));
2641}
2642
2643TEST(FindReferences, NeedsIndexForMacro) {
2644 const char *Header = "#define MACRO(X) (X+1)";
2645 Annotations Main(R"cpp(
2646 int main() {
2647 int a = [[MA^CRO]](1);
2648 }
2649 )cpp");
2650 TestTU TU;
2651 TU.Code = std::string(Main.code());
2652 TU.HeaderCode = Header;
2653 auto AST = TU.build();
2654
2655 // References in main file are returned without index.
2656 EXPECT_THAT(
2657 findReferences(AST, Main.point(), 0, /*Index=*/nullptr).References,
2658 ElementsAre(rangeIs(Main.range())));
2659
2660 Annotations IndexedMain(R"cpp(
2661 int indexed_main() {
2662 int a = [[MACRO]](1);
2663 return 0;
2664 }
2665 )cpp");
2666
2667 // References from indexed files are included.
2668 TestTU IndexedTU;
2669 IndexedTU.Code = std::string(IndexedMain.code());
2670 IndexedTU.Filename = "Indexed.cpp";
2671 IndexedTU.HeaderCode = Header;
2672 EXPECT_THAT(
2673 findReferences(AST, Main.point(), 0, IndexedTU.index().get()).References,
2674 ElementsAre(rangeIs(Main.range()), rangeIs(IndexedMain.range())));
2675 auto LimitRefs =
2676 findReferences(AST, Main.point(), /*Limit*/ 1, IndexedTU.index().get());
2677 EXPECT_EQ(1u, LimitRefs.References.size());
2678 EXPECT_TRUE(LimitRefs.HasMore);
2679}
2680
2681TEST(FindReferences, NoQueryForLocalSymbols) {
2682 struct RecordingIndex : public MemIndex {
2683 mutable std::optional<llvm::DenseSet<SymbolID>> RefIDs;
2684 bool refs(const RefsRequest &Req,
2685 llvm::function_ref<void(const Ref &)>) const override {
2686 RefIDs = Req.IDs;
2687 return false;
2688 }
2689 };
2690
2691 struct Test {
2692 StringRef AnnotatedCode;
2693 bool WantQuery;
2694 } Tests[] = {
2695 {"int ^x;", true},
2696 // For now we don't assume header structure which would allow skipping.
2697 {"namespace { int ^x; }", true},
2698 {"static int ^x;", true},
2699 // Anything in a function certainly can't be referenced though.
2700 {"void foo() { int ^x; }", false},
2701 {"void foo() { struct ^x{}; }", false},
2702 {"auto lambda = []{ int ^x; };", false},
2703 };
2704 for (Test T : Tests) {
2705 Annotations File(T.AnnotatedCode);
2706 RecordingIndex Rec;
2707 auto AST = TestTU::withCode(File.code()).build();
2708 findReferences(AST, File.point(), 0, &Rec);
2709 if (T.WantQuery)
2710 EXPECT_NE(Rec.RefIDs, std::nullopt) << T.AnnotatedCode;
2711 else
2712 EXPECT_EQ(Rec.RefIDs, std::nullopt) << T.AnnotatedCode;
2713 }
2714}
2715
2716TEST(GetNonLocalDeclRefs, All) {
2717 struct Case {
2718 llvm::StringRef AnnotatedCode;
2719 std::vector<std::string> ExpectedDecls;
2720 } Cases[] = {
2721 {
2722 // VarDecl and ParamVarDecl
2723 R"cpp(
2724 void bar();
2725 void ^foo(int baz) {
2726 int x = 10;
2727 bar();
2728 })cpp",
2729 {"bar"},
2730 },
2731 {
2732 // Method from class
2733 R"cpp(
2734 class Foo { public: void foo(); };
2735 class Bar {
2736 void foo();
2737 void bar();
2738 };
2739 void Bar::^foo() {
2740 Foo f;
2741 bar();
2742 f.foo();
2743 })cpp",
2744 {"Bar", "Bar::bar", "Foo", "Foo::foo"},
2745 },
2746 {
2747 // Local types
2748 R"cpp(
2749 void ^foo() {
2750 class Foo { public: void foo() {} };
2751 class Bar { public: void bar() {} };
2752 Foo f;
2753 Bar b;
2754 b.bar();
2755 f.foo();
2756 })cpp",
2757 {},
2758 },
2759 {
2760 // Template params
2761 R"cpp(
2762 template <typename T, template<typename> class Q>
2763 void ^foo() {
2764 T x;
2765 Q<T> y;
2766 })cpp",
2767 {},
2768 },
2769 };
2770 for (const Case &C : Cases) {
2771 Annotations File(C.AnnotatedCode);
2772 auto AST = TestTU::withCode(File.code()).build();
2773 SourceLocation SL = llvm::cantFail(
2774 sourceLocationInMainFile(AST.getSourceManager(), File.point()));
2775
2776 const FunctionDecl *FD =
2777 llvm::dyn_cast<FunctionDecl>(&findDecl(AST, [SL](const NamedDecl &ND) {
2778 return ND.getLocation() == SL && llvm::isa<FunctionDecl>(ND);
2779 }));
2780 ASSERT_NE(FD, nullptr);
2781
2782 auto NonLocalDeclRefs = getNonLocalDeclRefs(AST, FD);
2783 std::vector<std::string> Names;
2784 for (const Decl *D : NonLocalDeclRefs) {
2785 if (const auto *ND = llvm::dyn_cast<NamedDecl>(D))
2786 Names.push_back(ND->getQualifiedNameAsString());
2787 }
2788 EXPECT_THAT(Names, UnorderedElementsAreArray(C.ExpectedDecls))
2789 << File.code();
2790 }
2791}
2792
2793TEST(DocumentLinks, All) {
2794 Annotations MainCpp(R"cpp(
2795 #define HEADER_AA "faa.h"
2796 #define HEADER_BB "fbb.h"
2797 #define GET_HEADER(X) HEADER_ ## X
2798
2799 #/*comments*/include /*comments*/ $foo[["foo.h"]] //more comments
2800 int end_of_preamble = 0;
2801 #include $bar[[<bar.h>]]
2802 #include $AA[[GET_HEADER]](AA) // Some comment !
2803 # /* What about */ \
2804 include /* multiple line */ \
2805 $BB[[GET_HEADER]]( /* statements ? */ \
2806 BB /* :) */ )
2807 )cpp");
2808
2809 TestTU TU;
2810 TU.Code = std::string(MainCpp.code());
2811 TU.AdditionalFiles = {
2812 {"faa.h", ""}, {"fbb.h", ""}, {"foo.h", ""}, {"bar.h", ""}};
2813 TU.ExtraArgs = {"-isystem."};
2814 auto AST = TU.build();
2815
2816 EXPECT_THAT(
2818 ElementsAre(
2819 DocumentLink({MainCpp.range("foo"),
2820 URIForFile::canonicalize(testPath("foo.h"), "")}),
2821 DocumentLink({MainCpp.range("bar"),
2822 URIForFile::canonicalize(testPath("bar.h"), "")}),
2823 DocumentLink({MainCpp.range("AA"),
2824 URIForFile::canonicalize(testPath("faa.h"), "")}),
2825 DocumentLink({MainCpp.range("BB"),
2826 URIForFile::canonicalize(testPath("fbb.h"), "")})));
2827}
2828
2829} // namespace
2830} // namespace clangd
2831} // namespace clang
std::vector< HeaderEntry > HeaderContents
Same as llvm::Annotations, but adjusts functions to LSP-specific types for positions and ranges.
Definition Annotations.h:23
Manages a collection of source files and derived data (ASTs, indexes), and provides language-aware fe...
A context is an immutable container for per-request data that must be propagated through layers that ...
Definition Context.h:69
MemIndex is a naive in-memory index suitable for a small set of symbols.
Definition MemIndex.h:20
Stores and provides access to parsed AST.
Definition ParsedAST.h:46
FIXME: Skip testing on windows temporarily due to the different escaping code mode.
Definition AST.cpp:45
SymbolID getSymbolID(const Decl *D)
Gets the symbol ID for a declaration. Returned SymbolID might be null.
Definition AST.cpp:354
const NamedDecl & findDecl(ParsedAST &AST, llvm::StringRef QName)
Definition TestTU.cpp:220
Range halfOpenToRange(const SourceManager &SM, CharSourceRange R)
std::vector< DocumentHighlight > findDocumentHighlights(ParsedAST &AST, Position Pos)
Returns highlights for all usages of a symbol at Pos.
Definition XRefs.cpp:1279
Symbol sym(llvm::StringRef QName, index::SymbolKind Kind, llvm::StringRef USRFormat, llvm::StringRef Signature)
Definition TestIndex.cpp:40
std::vector< LocatedSymbol > locateSymbolTextually(const SpelledWord &Word, ParsedAST &AST, const SymbolIndex *Index, llvm::StringRef MainFilePath, ASTNodeKind NodeKind)
Definition XRefs.cpp:575
std::vector< DocumentLink > getDocumentLinks(ParsedAST &AST)
Get all document links.
Definition XRefs.cpp:857
MATCHER_P2(hasFlag, Flag, Path, "")
std::vector< LocatedSymbol > findType(ParsedAST &AST, Position Pos, const SymbolIndex *Index)
Returns symbols for types referenced at Pos.
Definition XRefs.cpp:2146
MATCHER_P(named, N, "")
ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit, const SymbolIndex *Index, bool AddContext)
Returns references of the symbol at a specified Pos.
Definition XRefs.cpp:1445
std::string testPath(PathRef File, llvm::sys::path::Style Style)
Definition TestFS.cpp:93
std::vector< LocatedSymbol > locateSymbolAt(ParsedAST &AST, Position Pos, const SymbolIndex *Index)
Get definition of symbol at a specified Pos.
Definition XRefs.cpp:776
TEST(BackgroundQueueTest, Priority)
const syntax::Token * findNearbyIdentifier(const SpelledWord &Word, const syntax::TokenBuffer &TB)
Definition XRefs.cpp:685
void runAddDocument(ClangdServer &Server, PathRef File, llvm::StringRef Contents, llvm::StringRef Version, WantDiagnostics WantDiags, bool ForceRebuild)
Definition SyncAPI.cpp:17
llvm::Expected< std::vector< LocatedSymbol > > runLocateSymbolAt(ClangdServer &Server, PathRef File, Position Pos)
Definition SyncAPI.cpp:88
const Symbol & findSymbol(const SymbolSlab &Slab, llvm::StringRef QName)
Definition TestTU.cpp:186
llvm::Expected< SourceLocation > sourceLocationInMainFile(const SourceManager &SM, Position P)
Return the file location, corresponding to P.
@ No
Diagnostics must be generated for this snapshot.
Definition TUScheduler.h:55
std::vector< LocatedSymbol > findImplementations(ParsedAST &AST, Position Pos, const SymbolIndex *Index)
Returns implementations at a specified Pos:
Definition XRefs.cpp:1320
llvm::DenseSet< const Decl * > getNonLocalDeclRefs(ParsedAST &AST, const FunctionDecl *FD)
Returns all decls that are referenced in the FD except local symbols.
Definition XRefs.cpp:2478
const char * testRoot()
Definition TestFS.cpp:85
@ Alias
This declaration is an alias that was referred to.
Definition FindTarget.h:112
cppcoreguidelines::ProBoundsAvoidUncheckedContainerAccess P
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
std::vector< Reference > References
Definition XRefs.h:94
static std::optional< SpelledWord > touching(SourceLocation SpelledLoc, const syntax::TokenBuffer &TB, const LangOptions &LangOpts)
SymbolID ID
The ID of the symbol.
Definition Symbol.h:41
std::string Code
Definition TestTU.h:49
ParsedAST build() const
Definition TestTU.cpp:115
static TestTU withHeaderCode(llvm::StringRef HeaderCode)
Definition TestTU.h:42
static TestTU withCode(llvm::StringRef Code)
Definition TestTU.h:36
std::string HeaderCode
Definition TestTU.h:53
static URIForFile canonicalize(llvm::StringRef AbsPath, llvm::StringRef TUPath)
Canonicalizes AbsPath via URI.
Definition Protocol.cpp:46