clang-tools 10.0.0

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 "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::IsEmpty;
42 using ::testing::Matcher;
43 using ::testing::UnorderedElementsAreArray;
44
45 class IgnoreDiagnostics : public DiagnosticsConsumer {
46 void onDiagnosticsReady(PathRef File,
47 std::vector<Diag> Diagnostics) override {}
48 };
49
50 MATCHER_P2(FileRange, File, Range, "") {
51 return Location{URIForFile::canonicalize(File, testRoot()), Range} == arg;
52 }
53
54 // Extracts ranges from an annotated example, and constructs a matcher for a
55 // highlight set. Ranges should be named $read/$write as appropriate.
56 Matcher<const std::vector<DocumentHighlight> &>
57 HighlightsFrom(const Annotations &Test) {
58 std::vector<DocumentHighlight> Expected;
59 auto Add = [&](const Range &R, DocumentHighlightKind K) {
60 Expected.emplace_back();
61 Expected.back().range = R;
62 Expected.back().kind = K;
63 };
64 for (const auto &Range : Test.ranges())
65 Add(Range, DocumentHighlightKind::Text);
66 for (const auto &Range : Test.ranges("read"))
67 Add(Range, DocumentHighlightKind::Read);
68 for (const auto &Range : Test.ranges("write"))
69 Add(Range, DocumentHighlightKind::Write);
70 return UnorderedElementsAreArray(Expected);
71 }
72
73 TEST(HighlightsTest, All) {
74 const char *Tests[] = {
75 R"cpp(// Local variable
76 int main() {
77 int [[bonjour]];
78 $write[[^bonjour]] = 2;
79 int test1 = $read[[bonjour]];
80 }
81 )cpp",
82
83 R"cpp(// Struct
84 namespace ns1 {
85 struct [[MyClass]] {
86 static void foo([[MyClass]]*) {}
87 };
88 } // namespace ns1
89 int main() {
90 ns1::[[My^Class]]* Params;
91 }
92 )cpp",
93
94 R"cpp(// Function
95 int [[^foo]](int) {}
96 int main() {
97 [[foo]]([[foo]](42));
98 auto *X = &[[foo]];
99 }
100 )cpp",
101
102 R"cpp(// Function parameter in decl
103 void foo(int [[^bar]]);
104 )cpp",
105 };
106 for (const char *Test : Tests) {
107 Annotations T(Test);
108 auto AST = TestTU::withCode(T.code()).build();
109 EXPECT_THAT(findDocumentHighlights(AST, T.point()), HighlightsFrom(T))
110 << Test;
111 }
112 }
113
114 MATCHER_P3(Sym, Name, Decl, DefOrNone, "") {
115 llvm::Optional<Range> Def = DefOrNone;
116 if (Name != arg.Name) {
117 *result_listener << "Name is " << arg.Name;
118 return false;
119 }
120 if (Decl != arg.PreferredDeclaration.range) {
121 *result_listener << "Declaration is "
122 << llvm::to_string(arg.PreferredDeclaration);
123 return false;
124 }
125 if (Def && !arg.Definition) {
126 *result_listener << "Has no definition";
127 return false;
128 }
129 if (Def && arg.Definition->range != *Def) {
130 *result_listener << "Definition is " << llvm::to_string(arg.Definition);
131 return false;
132 }
133 return true;
134 }
135 ::testing::Matcher<LocatedSymbol> Sym(std::string Name, Range Decl) {
136 return Sym(Name, Decl, llvm::None);
137 }
138 MATCHER_P(Sym, Name, "") { return arg.Name == Name; }
139
140 MATCHER_P(RangeIs, R, "") { return arg.range == R; }
141
142 TEST(LocateSymbol, WithIndex) {
143 Annotations SymbolHeader(R"cpp(
144 class $forward[[Forward]];
145 class $foo[[Foo]] {};
146
147 void $f1[[f1]]();
148
149 inline void $f2[[f2]]() {}
150 )cpp");
151 Annotations SymbolCpp(R"cpp(
152 class $forward[[forward]] {};
153 void $f1[[f1]]() {}
154 )cpp");
155
156 TestTU TU;
157 TU.Code = SymbolCpp.code();
158 TU.HeaderCode = SymbolHeader.code();
159 auto Index = TU.index();
160 auto LocateWithIndex = [&Index](const Annotations &Main) {
161 auto AST = TestTU::withCode(Main.code()).build();
162 return clangd::locateSymbolAt(AST, Main.point(), Index.get());
163 };
164
165 Annotations Test(R"cpp(// only declaration in AST.
166 void [[f1]]();
167 int main() {
168 ^f1();
169 }
170 )cpp");
171 EXPECT_THAT(LocateWithIndex(Test),
172 ElementsAre(Sym("f1", Test.range(), SymbolCpp.range("f1"))));
173
174 Test = Annotations(R"cpp(// definition in AST.
175 void [[f1]]() {}
176 int main() {
177 ^f1();
178 }
179 )cpp");
180 EXPECT_THAT(LocateWithIndex(Test),
181 ElementsAre(Sym("f1", SymbolHeader.range("f1"), Test.range())));
182
183 Test = Annotations(R"cpp(// forward declaration in AST.
184 class [[Foo]];
185 F^oo* create();
186 )cpp");
187 EXPECT_THAT(LocateWithIndex(Test),
188 ElementsAre(Sym("Foo", Test.range(), SymbolHeader.range("foo"))));
189
190 Test = Annotations(R"cpp(// definition in AST.
191 class [[Forward]] {};
192 F^orward create();
193 )cpp");
194 EXPECT_THAT(
195 LocateWithIndex(Test),
196 ElementsAre(Sym("Forward", SymbolHeader.range("forward"), Test.range())));
197 }
198
199 TEST(LocateSymbol, WithIndexPreferredLocation) {
200 Annotations SymbolHeader(R"cpp(
201 class $p[[Proto]] {};
202 void $f[[func]]() {};
203 )cpp");
204 TestTU TU;
205 TU.HeaderCode = SymbolHeader.code();
206 TU.HeaderFilename = "x.proto"; // Prefer locations in codegen files.
207 auto Index = TU.index();
208
209 Annotations Test(R"cpp(// only declaration in AST.
210 // Shift to make range different.
211 class Proto;
212 void func() {}
213 P$p^roto* create() {
214 fu$f^nc();
215 return nullptr;
216 }
217 )cpp");
218
219 auto AST = TestTU::withCode(Test.code()).build();
220 {
221 auto Locs = clangd::locateSymbolAt(AST, Test.point("p"), Index.get());
222 auto CodeGenLoc = SymbolHeader.range("p");
223 EXPECT_THAT(Locs, ElementsAre(Sym("Proto", CodeGenLoc, CodeGenLoc)));
224 }
225 {
226 auto Locs = clangd::locateSymbolAt(AST, Test.point("f"), Index.get());
227 auto CodeGenLoc = SymbolHeader.range("f");
228 EXPECT_THAT(Locs, ElementsAre(Sym("func", CodeGenLoc, CodeGenLoc)));
229 }
230 }
231
232 TEST(LocateSymbol, All) {
233 // Ranges in tests:
234 // $decl is the declaration location (if absent, no symbol is located)
235 // $def is the definition location (if absent, symbol has no definition)
236 // unnamed range becomes both $decl and $def.
237 const char *Tests[] = {
238 R"cpp(// Local variable
239 int main() {
240 int [[bonjour]];
241 ^bonjour = 2;
242 int test1 = bonjour;
243 }
244 )cpp",
245
246 R"cpp(// Struct
247 namespace ns1 {
248 struct [[MyClass]] {};
249 } // namespace ns1
250 int main() {
251 ns1::My^Class* Params;
252 }
253 )cpp",
254
255 R"cpp(// Function definition via pointer
256 void [[foo]](int) {}
257 int main() {
258 auto *X = &^foo;
259 }
260 )cpp",
261
262 R"cpp(// Function declaration via call
263 int $decl[[foo]](int);
264 int main() {
265 return ^foo(42);
266 }
267 )cpp",
268
269 R"cpp(// Field
270 struct Foo { int [[x]]; };
271 int main() {
272 Foo bar;
273 (void)bar.^x;
274 }
275 )cpp",
276
277 R"cpp(// Field, member initializer
278 struct Foo {
279 int [[x]];
280 Foo() : ^x(0) {}
281 };
282 )cpp",
283
284 R"cpp(// Field, field designator
285 struct Foo { int [[x]]; };
286 int main() {
287 Foo bar = { .^x = 2 };
288 }
289 )cpp",
290
291 R"cpp(// Method call
292 struct Foo { int $decl[[x]](); };
293 int main() {
294 Foo bar;
295 bar.^x();
296 }
297 )cpp",
298
299 R"cpp(// Typedef
300 typedef int $decl[[Foo]];
301 int main() {
302 ^Foo bar;
303 }
304 )cpp",
305
306 R"cpp(// Template type parameter
307 template <typename [[T]]>
308 void foo() { ^T t; }
309 )cpp",
310
311 R"cpp(// Template template type parameter
312 template <template<typename> class [[T]]>
313 void foo() { ^T<int> t; }
314 )cpp",
315
316 R"cpp(// Namespace
317 namespace $decl[[ns]] {
318 struct Foo { static void bar(); };
319 } // namespace ns
320 int main() { ^ns::Foo::bar(); }
321 )cpp",
322
323 R"cpp(// Macro
324 class TTT { public: int a; };
325 #define [[FF]](S) if (int b = S.a) {}
326 void f() {
327 TTT t;
328 F^F(t);
329 }
330 )cpp",
331
332 R"cpp(// Macro argument
333 int [[i]];
334 #define ADDRESSOF(X) &X;
335 int *j = ADDRESSOF(^i);
336 )cpp",
337
338 R"cpp(// Symbol concatenated inside macro (not supported)
339 int *pi;
340 #define POINTER(X) p ## X;
341 int i = *POINTER(^i);
342 )cpp",
343
344 R"cpp(// Forward class declaration
345 class Foo;
346 class [[Foo]] {};
347 F^oo* foo();
348 )cpp",
349
350 R"cpp(// Function declaration
351 void foo();
352 void g() { f^oo(); }
353 void [[foo]]() {}
354 )cpp",
355
356 R"cpp(
357 #define FF(name) class name##_Test {};
358 [[FF]](my);
359 void f() { my^_Test a; }
360 )cpp",
361
362 R"cpp(
363 #define FF() class [[Test]] {};
364 FF();
365 void f() { T^est a; }
366 )cpp",
367
368 R"cpp(// explicit template specialization
369 template <typename T>
370 struct Foo { void bar() {} };
371
372 template <>
373 struct [[Foo]]<int> { void bar() {} };
374
375 void foo() {
376 Foo<char> abc;
377 Fo^o<int> b;
378 }
379 )cpp",
380
381 R"cpp(// implicit template specialization
382 template <typename T>
383 struct [[Foo]] { void bar() {} };
384 template <>
385 struct Foo<int> { void bar() {} };
386 void foo() {
387 Fo^o<char> abc;
388 Foo<int> b;
389 }
390 )cpp",
391
392 R"cpp(// partial template specialization
393 template <typename T>
394 struct Foo { void bar() {} };
395 template <typename T>
396 struct [[Foo]]<T*> { void bar() {} };
397 ^Foo<int*> x;
398 )cpp",
399
400 R"cpp(// function template specializations
401 template <class T>
402 void foo(T) {}
403 template <>
404 void [[foo]](int) {}
405 void bar() {
406 fo^o(10);
407 }
408 )cpp",
409
410 R"cpp(// variable template decls
411 template <class T>
412 T var = T();
413
414 template <>
415 double [[var]]<int> = 10;
416
417 double y = va^r<int>;
418 )cpp",
419
420 R"cpp(// No implicit constructors
421 struct X {
422 X(X&& x) = default;
423 };
424 X $decl[[makeX]]();
425 void foo() {
426 auto x = m^akeX();
427 }
428 )cpp",
429
430 R"cpp(
431 struct X {
432 X& $decl[[operator]]++();
433 };
434 void foo(X& x) {
435 +^+x;
436 }
437 )cpp",
438
439 R"cpp(// Declaration of explicit template specialization
440 template <typename T>
441 struct $decl[[Foo]] {};
442
443 template <>
444 struct Fo^o<int> {};
445 )cpp",
446
447 R"cpp(// Declaration of partial template specialization
448 template <typename T>
449 struct $decl[[Foo]] {};
450
451 template <typename T>
452 struct Fo^o<T*> {};
453 )cpp",
454
455 R"cpp(// Heuristic resolution of dependent method
456 template <typename T>
457 struct S {
458 void [[bar]]() {}
459 };
460
461 template <typename T>
462 void foo(S<T> arg) {
463 arg.ba^r();
464 }
465 )cpp",
466
467 R"cpp(// Heuristic resolution of dependent method via this->
468 template <typename T>
469 struct S {
470 void [[foo]]() {
471 this->fo^o();
472 }
473 };
474 )cpp",
475
476 R"cpp(// Heuristic resolution of dependent static method
477 template <typename T>
478 struct S {
479 static void [[bar]]() {}
480 };
481
482 template <typename T>
483 void foo() {
484 S<T>::ba^r();
485 }
486 )cpp",
487
488 R"cpp(// Heuristic resolution of dependent method
489 // invoked via smart pointer
490 template <typename> struct S { void [[foo]]() {} };
491 template <typename T> struct unique_ptr {
492 T* operator->();
493 };
494 template <typename T>
495 void test(unique_ptr<S<T>>& V) {
496 V->fo^o();
497 }
498 )cpp"};
499 for (const char *Test : Tests) {
500 Annotations T(Test);
501 llvm::Optional<Range> WantDecl;
502 llvm::Optional<Range> WantDef;
503 if (!T.ranges().empty())
504 WantDecl = WantDef = T.range();
505 if (!T.ranges("decl").empty())
506 WantDecl = T.range("decl");
507 if (!T.ranges("def").empty())
508 WantDef = T.range("def");
509
510 TestTU TU;
511 TU.Code = T.code();
512
513 // FIXME: Auto-completion in a template requires disabling delayed template
514 // parsing.
515 TU.ExtraArgs.push_back("-fno-delayed-template-parsing");
516
517 auto AST = TU.build();
518 for (auto &D : AST.getDiagnostics())
519 ADD_FAILURE() << D;
520 ASSERT_TRUE(AST.getDiagnostics().empty()) << Test;
521
522 auto Results = locateSymbolAt(AST, T.point());
523
524 if (!WantDecl) {
525 EXPECT_THAT(Results, IsEmpty()) << Test;
526 } else {
527 ASSERT_THAT(Results, ::testing::SizeIs(1)) << Test;
528 EXPECT_EQ(Results[0].PreferredDeclaration.range, *WantDecl) << Test;
529 llvm::Optional<Range> GotDef;
530 if (Results[0].Definition)
531 GotDef = Results[0].Definition->range;
532 EXPECT_EQ(WantDef, GotDef) << Test;
533 }
534 }
535 }
536
537 // LocateSymbol test cases that produce warnings.
538 // These are separated out from All so that in All we can assert
539 // that there are no diagnostics.
540 TEST(LocateSymbol, Warnings) {
541 const char *Tests[] = {
542 R"cpp(// Field, GNU old-style field designator
543 struct Foo { int [[x]]; };
544 int main() {
545 Foo bar = { ^x : 1 };
546 }
547 )cpp",
548
549 R"cpp(// Macro
550 #define MACRO 0
551 #define [[MACRO]] 1
552 int main() { return ^MACRO; }
553 #define MACRO 2
554 #undef macro
555 )cpp",
556 };
557
558 for (const char *Test : Tests) {
559 Annotations T(Test);
560 llvm::Optional<Range> WantDecl;
561 llvm::Optional<Range> WantDef;
562 if (!T.ranges().empty())
563 WantDecl = WantDef = T.range();
564 if (!T.ranges("decl").empty())
565 WantDecl = T.range("decl");
566 if (!T.ranges("def").empty())
567 WantDef = T.range("def");
568
569 TestTU TU;
570 TU.Code = T.code();
571
572 auto AST = TU.build();
573 auto Results = locateSymbolAt(AST, T.point());
574
575 if (!WantDecl) {
576 EXPECT_THAT(Results, IsEmpty()) << Test;
577 } else {
578 ASSERT_THAT(Results, ::testing::SizeIs(1)) << Test;
579 EXPECT_EQ(Results[0].PreferredDeclaration.range, *WantDecl) << Test;
580 llvm::Optional<Range> GotDef;
581 if (Results[0].Definition)
582 GotDef = Results[0].Definition->range;
583 EXPECT_EQ(WantDef, GotDef) << Test;
584 }
585 }
586 }
587
588 TEST(LocateSymbol, Ambiguous) {
589 auto T = Annotations(R"cpp(
590 struct Foo {
591 Foo();
592 Foo(Foo&&);
593 $ConstructorLoc[[Foo]](const char*);
594 };
595
596 Foo f();
597
598 void g(Foo foo);
599
600 void call() {
601 const char* str = "123";
602 Foo a = $1^str;
603 Foo b = Foo($2^str);
604 Foo c = $3^f();
605 $4^g($5^f());
606 g($6^str);
607 Foo ab$7^c;
608 Foo ab$8^cd("asdf");
609 Foo foox = Fo$9^o("asdf");
610 Foo abcde$10^("asdf");
611 Foo foox2 = Foo$11^("asdf");
612 }
613
614 template <typename T>
615 struct S {
616 void $NonstaticOverload1[[bar]](int);
617 void $NonstaticOverload2[[bar]](float);
618
619 static void $StaticOverload1[[baz]](int);
620 static void $StaticOverload2[[baz]](float);
621 };
622
623 template <typename T, typename U>
624 void dependent_call(S<T> s, U u) {
625 s.ba$12^r(u);
626 S<T>::ba$13^z(u);
627 }
628 )cpp");
629 auto TU = TestTU::withCode(T.code());
630 // FIXME: Go-to-definition in a template requires disabling delayed template
631 // parsing.
632 TU.ExtraArgs.push_back("-fno-delayed-template-parsing");
633 auto AST = TU.build();
634 // Ordered assertions are deliberate: we expect a predictable order.
635 EXPECT_THAT(locateSymbolAt(AST, T.point("1")), ElementsAre(Sym("str")));
636 EXPECT_THAT(locateSymbolAt(AST, T.point("2")), ElementsAre(Sym("str")));
637 EXPECT_THAT(locateSymbolAt(AST, T.point("3")), ElementsAre(Sym("f")));
638 EXPECT_THAT(locateSymbolAt(AST, T.point("4")), ElementsAre(Sym("g")));
639 EXPECT_THAT(locateSymbolAt(AST, T.point("5")), ElementsAre(Sym("f")));
640 EXPECT_THAT(locateSymbolAt(AST, T.point("6")), ElementsAre(Sym("str")));
641 // FIXME: Target the constructor as well.
642 EXPECT_THAT(locateSymbolAt(AST, T.point("7")), ElementsAre(Sym("abc")));
643 // FIXME: Target the constructor as well.
644 EXPECT_THAT(locateSymbolAt(AST, T.point("8")), ElementsAre(Sym("abcd")));
645 // FIXME: Target the constructor as well.
646 EXPECT_THAT(locateSymbolAt(AST, T.point("9")), ElementsAre(Sym("Foo")));
647 EXPECT_THAT(locateSymbolAt(AST, T.point("10")),
648 ElementsAre(Sym("Foo", T.range("ConstructorLoc"))));
649 EXPECT_THAT(locateSymbolAt(AST, T.point("11")),
650 ElementsAre(Sym("Foo", T.range("ConstructorLoc"))));
651 // These assertions are unordered because the order comes from
652 // CXXRecordDecl::lookupDependentName() which doesn't appear to provide
653 // an order guarantee.
654 EXPECT_THAT(locateSymbolAt(AST, T.point("12")),
655 UnorderedElementsAre(Sym("bar", T.range("NonstaticOverload1")),
656 Sym("bar", T.range("NonstaticOverload2"))));
657 EXPECT_THAT(locateSymbolAt(AST, T.point("13")),
658 UnorderedElementsAre(Sym("baz", T.range("StaticOverload1")),
659 Sym("baz", T.range("StaticOverload2"))));
660 }
661
662 TEST(LocateSymbol, TemplateTypedefs) {
663 auto T = Annotations(R"cpp(
664 template <class T> struct function {};
665 template <class T> using callback = function<T()>;
666
667 c^allback<int> foo;
668 )cpp");
669 auto AST = TestTU::withCode(T.code()).build();
670 EXPECT_THAT(locateSymbolAt(AST, T.point()), ElementsAre(Sym("callback")));
671 }
672
673 TEST(LocateSymbol, RelPathsInCompileCommand) {
674 // The source is in "/clangd-test/src".
675 // We build in "/clangd-test/build".
676
677 Annotations SourceAnnotations(R"cpp(
678 #include "header_in_preamble.h"
679 int [[foo]];
680 #include "header_not_in_preamble.h"
681 int baz = f$p1^oo + bar_pre$p2^amble + bar_not_pre$p3^amble;
682 )cpp");
683
684 Annotations HeaderInPreambleAnnotations(R"cpp(
685 int [[bar_preamble]];
686 )cpp");
687
688 Annotations HeaderNotInPreambleAnnotations(R"cpp(
689 int [[bar_not_preamble]];
690 )cpp");
691
692 // Make the compilation paths appear as ../src/foo.cpp in the compile
693 // commands.
694 SmallString<32> RelPathPrefix("..");
695 llvm::sys::path::append(RelPathPrefix, "src");
696 std::string BuildDir = testPath("build");
697 MockCompilationDatabase CDB(BuildDir, RelPathPrefix);
698
699 IgnoreDiagnostics DiagConsumer;
700 MockFSProvider FS;
701 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
702
703 // Fill the filesystem.
704 auto FooCpp = testPath("src/foo.cpp");
705 FS.Files[FooCpp] = "";
706 auto HeaderInPreambleH = testPath("src/header_in_preamble.h");
707 FS.Files[HeaderInPreambleH] = HeaderInPreambleAnnotations.code();
708 auto HeaderNotInPreambleH = testPath("src/header_not_in_preamble.h");
709 FS.Files[HeaderNotInPreambleH] = HeaderNotInPreambleAnnotations.code();
710
711 runAddDocument(Server, FooCpp, SourceAnnotations.code());
712
713 // Go to a definition in main source file.
714 auto Locations =
715 runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("p1"));
716 EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error";
717 EXPECT_THAT(*Locations, ElementsAre(Sym("foo", SourceAnnotations.range())));
718
719 // Go to a definition in header_in_preamble.h.
720 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("p2"));
721 EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error";
722 EXPECT_THAT(
723 *Locations,
724 ElementsAre(Sym("bar_preamble", HeaderInPreambleAnnotations.range())));
725
726 // Go to a definition in header_not_in_preamble.h.
727 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("p3"));
728 EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error";
729 EXPECT_THAT(*Locations,
730 ElementsAre(Sym("bar_not_preamble",
731 HeaderNotInPreambleAnnotations.range())));
732 }
733
734 TEST(GoToInclude, All) {
735 MockFSProvider FS;
736 IgnoreDiagnostics DiagConsumer;
737 MockCompilationDatabase CDB;
738 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
739
740 auto FooCpp = testPath("foo.cpp");
741 const char *SourceContents = R"cpp(
742 #include ^"$2^foo.h$3^"
743 #include "$4^invalid.h"
744 int b = a;
745 // test
746 int foo;
747 #in$5^clude "$6^foo.h"$7^
748 )cpp";
749 Annotations SourceAnnotations(SourceContents);
750 FS.Files[FooCpp] = SourceAnnotations.code();
751 auto FooH = testPath("foo.h");
752
753 const char *HeaderContents = R"cpp([[]]#pragma once
754 int a;
755 )cpp";
756 Annotations HeaderAnnotations(HeaderContents);
757 FS.Files[FooH] = HeaderAnnotations.code();
758
759 Server.addDocument(FooH, HeaderAnnotations.code());
760 Server.addDocument(FooCpp, SourceAnnotations.code());
761
762 // Test include in preamble.
763 auto Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point());
764 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
765 EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range())));
766
767 // Test include in preamble, last char.
768 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("2"));
769 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
770 EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range())));
771
772 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("3"));
773 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
774 EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range())));
775
776 // Test include outside of preamble.
777 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("6"));
778 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
779 EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range())));
780
781 // Test a few positions that do not result in Locations.
782 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("4"));
783 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
784 EXPECT_THAT(*Locations, IsEmpty());
785
786 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("5"));
787 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
788 EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range())));
789
790 Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("7"));
791 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
792 EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range())));
793
794 // Objective C #import directive.
795 Annotations ObjC(R"objc(
796 #import "^foo.h"
797 )objc");
798 auto FooM = testPath("foo.m");
799 FS.Files[FooM] = ObjC.code();
800
801 Server.addDocument(FooM, ObjC.code());
802 Locations = runLocateSymbolAt(Server, FooM, ObjC.point());
803 ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
804 EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range())));
805 }
806
807 TEST(LocateSymbol, WithPreamble) {
808 // Test stragety: AST should always use the latest preamble instead of last
809 // good preamble.
810 MockFSProvider FS;
811 IgnoreDiagnostics DiagConsumer;
812 MockCompilationDatabase CDB;
813 ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
814
815 auto FooCpp = testPath("foo.cpp");
816 // The trigger locations must be the same.
817 Annotations FooWithHeader(R"cpp(#include "fo^o.h")cpp");
818 Annotations FooWithoutHeader(R"cpp(double [[fo^o]]();)cpp");
819
820 FS.Files[FooCpp] = FooWithHeader.code();
821
822 auto FooH = testPath("foo.h");
823 Annotations FooHeader(R"cpp([[]])cpp");
824 FS.Files[FooH] = FooHeader.code();
825
826 runAddDocument(Server, FooCpp, FooWithHeader.code());
827 // LocateSymbol goes to a #include file: the result comes from the preamble.
828 EXPECT_THAT(
829 cantFail(runLocateSymbolAt(Server, FooCpp, FooWithHeader.point())),
830 ElementsAre(Sym("foo.h", FooHeader.range())));
831
832 // Only preamble is built, and no AST is built in this request.
833 Server.addDocument(FooCpp, FooWithoutHeader.code(), WantDiagnostics::No);
834 // We build AST here, and it should use the latest preamble rather than the
835 // stale one.
836 EXPECT_THAT(
837 cantFail(runLocateSymbolAt(Server, FooCpp, FooWithoutHeader.point())),
838 ElementsAre(Sym("foo", FooWithoutHeader.range())));
839
840 // Reset test environment.
841 runAddDocument(Server, FooCpp, FooWithHeader.code());
842 // Both preamble and AST are built in this request.
843 Server.addDocument(FooCpp, FooWithoutHeader.code(), WantDiagnostics::Yes);
844 // Use the AST being built in above request.
845 EXPECT_THAT(
846 cantFail(runLocateSymbolAt(Server, FooCpp, FooWithoutHeader.point())),
847 ElementsAre(Sym("foo", FooWithoutHeader.range())));
848 }
849
850 TEST(FindReferences, WithinAST) {
851 const char *Tests[] = {
852 R"cpp(// Local variable
853 int main() {
854 int [[foo]];
855 [[^foo]] = 2;
856 int test1 = [[foo]];
857 }
858 )cpp",
859
860 R"cpp(// Struct
861 namespace ns1 {
862 struct [[Foo]] {};
863 } // namespace ns1
864 int main() {
865 ns1::[[Fo^o]]* Params;
866 }
867 )cpp",
868
869 R"cpp(// Forward declaration
870 class [[Foo]];
871 class [[Foo]] {}
872 int main() {
873 [[Fo^o]] foo;
874 }
875 )cpp",
876
877 R"cpp(// Function
878 int [[foo]](int) {}
879 int main() {
880 auto *X = &[[^foo]];
881 [[foo]](42)
882 }
883 )cpp",
884
885 R"cpp(// Field
886 struct Foo {
887 int [[foo]];
888 Foo() : [[foo]](0) {}
889 };
890 int main() {
891 Foo f;
892 f.[[f^oo]] = 1;
893 }
894 )cpp",
895
896 R"cpp(// Method call
897 struct Foo { int [[foo]](); };
898 int Foo::[[foo]]() {}
899 int main() {
900 Foo f;
901 f.[[^foo]]();
902 }
903 )cpp",
904
905 R"cpp(// Constructor
906 struct Foo {
907 [[F^oo]](int);
908 };
909 void foo() {
910 Foo f = [[Foo]](42);
911 }
912 )cpp",
913
914 R"cpp(// Typedef
915 typedef int [[Foo]];
916 int main() {
917 [[^Foo]] bar;
918 }
919 )cpp",
920
921 R"cpp(// Namespace
922 namespace [[ns]] {
923 struct Foo {};
924 } // namespace ns
925 int main() { [[^ns]]::Foo foo; }
926 )cpp",
927
928 R"cpp(// Macros
929 #define TYPE(X) X
930 #define FOO Foo
931 #define CAT(X, Y) X##Y
932 class [[Fo^o]] {};
933 void test() {
934 TYPE([[Foo]]) foo;
935 [[FOO]] foo2;
936 TYPE(TYPE([[Foo]])) foo3;
937 [[CAT]](Fo, o) foo4;
938 }
939 )cpp",
940
941 R"cpp(// Macros
942 #define [[MA^CRO]](X) (X+1)
943 void test() {
944 int x = [[MACRO]]([[MACRO]](1));
945 }
946 )cpp",
947 };
948 for (const char *Test : Tests) {
949 Annotations T(Test);
950 auto AST = TestTU::withCode(T.code()).build();
951 std::vector<Matcher<Location>> ExpectedLocations;
952 for (const auto &R : T.ranges())
953 ExpectedLocations.push_back(RangeIs(R));
954 EXPECT_THAT(findReferences(AST, T.point(), 0).References,
955 ElementsAreArray(ExpectedLocations))
956 << Test;
957 }
958 }
959
960 TEST(FindReferences, ExplicitSymbols) {
961 const char *Tests[] = {
962 R"cpp(
963 struct Foo { Foo* [[self]]() const; };
964 void f() {
965 Foo foo;
966 if (Foo* T = foo.[[^self]]()) {} // Foo member call expr.
967 }
968 )cpp",
969
970 R"cpp(
971 struct Foo { Foo(int); };
972 Foo f() {
973 int [[b]];
974 return [[^b]]; // Foo constructor expr.
975 }
976 )cpp",
977
978 R"cpp(
979 struct Foo {};
980 void g(Foo);
981 Foo [[f]]();
982 void call() {
983 g([[^f]]()); // Foo constructor expr.
984 }
985 )cpp",
986
987 R"cpp(
988 void [[foo]](int);
989 void [[foo]](double);
990
991 namespace ns {
992 using ::[[fo^o]];
993 }
994 )cpp",
995
996 R"cpp(
997 struct X {
998 operator bool();
999 };
1000
1001 int test() {
1002 X [[a]];
1003 [[a]].operator bool();
1004 if ([[a^]]) {} // ignore implicit conversion-operator AST node
1005 }
1006 )cpp",
1007 };
1008 for (const char *Test : Tests) {
1009 Annotations T(Test);
1010 auto AST = TestTU::withCode(T.code()).build();
1011 std::vector<Matcher<Location>> ExpectedLocations;
1012 for (const auto &R : T.ranges())
1013 ExpectedLocations.push_back(RangeIs(R));
1014 ASSERT_THAT(ExpectedLocations, Not(IsEmpty()));
1015 EXPECT_THAT(findReferences(AST, T.point(), 0).References,
1016 ElementsAreArray(ExpectedLocations))
1017 << Test;
1018 }
1019 }
1020
1021 TEST(FindReferences, NeedsIndexForSymbols) {
1022 const char *Header = "int foo();";
1023 Annotations Main("int main() { [[f^oo]](); }");
1024 TestTU TU;
1025 TU.Code = Main.code();
1026 TU.HeaderCode = Header;
1027 auto AST = TU.build();
1028
1029 // References in main file are returned without index.
1030 EXPECT_THAT(
1031 findReferences(AST, Main.point(), 0, /*Index=*/nullptr).References,
1032 ElementsAre(RangeIs(Main.range())));
1033 Annotations IndexedMain(R"cpp(
1034 int main() { [[f^oo]](); }
1035 )cpp");
1036
1037 // References from indexed files are included.
1038 TestTU IndexedTU;
1039 IndexedTU.Code = IndexedMain.code();
1040 IndexedTU.Filename = "Indexed.cpp";
1041 IndexedTU.HeaderCode = Header;
1042 EXPECT_THAT(
1043 findReferences(AST, Main.point(), 0, IndexedTU.index().get()).References,
1044 ElementsAre(RangeIs(Main.range()), RangeIs(IndexedMain.range())));
1045 auto LimitRefs =
1046 findReferences(AST, Main.point(), /*Limit*/ 1, IndexedTU.index().get());
1047 EXPECT_EQ(1u, LimitRefs.References.size());
1048 EXPECT_TRUE(LimitRefs.HasMore);
1049
1050 // Avoid indexed results for the main file. Use AST for the mainfile.
1051 TU.Code = ("\n\n" + Main.code()).str();
1052 EXPECT_THAT(findReferences(AST, Main.point(), 0, TU.index().get()).References,
1053 ElementsAre(RangeIs(Main.range())));
1054 }
1055
1056 TEST(FindReferences, NeedsIndexForMacro) {
1057 const char *Header = "#define MACRO(X) (X+1)";
1058 Annotations Main(R"cpp(
1059 int main() {
1060 int a = [[MA^CRO]](1);
1061 }
1062 )cpp");
1063 TestTU TU;
1064 TU.Code = Main.code();
1065 TU.HeaderCode = Header;
1066 auto AST = TU.build();
1067
1068 // References in main file are returned without index.
1069 EXPECT_THAT(
1070 findReferences(AST, Main.point(), 0, /*Index=*/nullptr).References,
1071 ElementsAre(RangeIs(Main.range())));
1072
1073 Annotations IndexedMain(R"cpp(
1074 int indexed_main() {
1075 int a = [[MACRO]](1);
1076 }
1077 )cpp");
1078
1079 // References from indexed files are included.
1080 TestTU IndexedTU;
1081 IndexedTU.Code = IndexedMain.code();
1082 IndexedTU.Filename = "Indexed.cpp";
1083 IndexedTU.HeaderCode = Header;
1084 EXPECT_THAT(
1085 findReferences(AST, Main.point(), 0, IndexedTU.index().get()).References,
1086 ElementsAre(RangeIs(Main.range()), RangeIs(IndexedMain.range())));
1087 auto LimitRefs =
1088 findReferences(AST, Main.point(), /*Limit*/ 1, IndexedTU.index().get());
1089 EXPECT_EQ(1u, LimitRefs.References.size());
1090 EXPECT_TRUE(LimitRefs.HasMore);
1091 }
1092
1093 TEST(FindReferences, NoQueryForLocalSymbols) {
1094 struct RecordingIndex : public MemIndex {
1095 mutable Optional<llvm::DenseSet<SymbolID>> RefIDs;
1096 bool refs(const RefsRequest &Req,
1097 llvm::function_ref<void(const Ref &)>) const override {
1098 RefIDs = Req.IDs;
1099 return false;
1100 }
1101 };
1102
1103 struct Test {
1104 StringRef AnnotatedCode;
1105 bool WantQuery;
1106 } Tests[] = {
1107 {"int ^x;", true},
1108 // For now we don't assume header structure which would allow skipping.
1109 {"namespace { int ^x; }", true},
1110 {"static int ^x;", true},
1111 // Anything in a function certainly can't be referenced though.
1112 {"void foo() { int ^x; }", false},
1113 {"void foo() { struct ^x{}; }", false},
1114 {"auto lambda = []{ int ^x; };", false},
1115 };
1116 for (Test T : Tests) {
1117 Annotations File(T.AnnotatedCode);
1118 RecordingIndex Rec;
1119 auto AST = TestTU::withCode(File.code()).build();
1120 findReferences(AST, File.point(), 0, &Rec);
1121 if (T.WantQuery)
1122 EXPECT_NE(Rec.RefIDs, None) << T.AnnotatedCode;
1123 else
1124 EXPECT_EQ(Rec.RefIDs, None) << T.AnnotatedCode;
1125 }
1126 }
1127
1128 TEST(GetNonLocalDeclRefs, All) {
1129 struct Case {
1130 llvm::StringRef AnnotatedCode;
1131 std::vector<llvm::StringRef> ExpectedDecls;
1132 } Cases[] = {
1133 {
1134 // VarDecl and ParamVarDecl
1135 R"cpp(
1136 void bar();
1137 void ^foo(int baz) {
1138 int x = 10;
1139 bar();
1140 })cpp",
1141 {"bar"},
1142 },
1143 {
1144 // Method from class
1145 R"cpp(
1146 class Foo { public: void foo(); };
1147 class Bar {
1148 void foo();
1149 void bar();
1150 };
1151 void Bar::^foo() {
1152 Foo f;
1153 bar();
1154 f.foo();
1155 })cpp",
1156 {"Bar", "Bar::bar", "Foo", "Foo::foo"},
1157 },
1158 {
1159 // Local types
1160 R"cpp(
1161 void ^foo() {
1162 class Foo { public: void foo() {} };
1163 class Bar { public: void bar() {} };
1164 Foo f;
1165 Bar b;
1166 b.bar();
1167 f.foo();
1168 })cpp",
1169 {},
1170 },
1171 {
1172 // Template params
1173 R"cpp(
1174 template <typename T, template<typename> class Q>
1175 void ^foo() {
1176 T x;
1177 Q<T> y;
1178 })cpp",
1179 {},
1180 },
1181 };
1182 for (const Case &C : Cases) {
1183 Annotations File(C.AnnotatedCode);
1184 auto AST = TestTU::withCode(File.code()).build();
1185 ASSERT_TRUE(AST.getDiagnostics().empty())
1186 << AST.getDiagnostics().begin()->Message;
1187 SourceLocation SL = llvm::cantFail(
1188 sourceLocationInMainFile(AST.getSourceManager(), File.point()));
1189
1190 const FunctionDecl *FD =
1191 llvm::dyn_cast<FunctionDecl>(&findDecl(AST, [SL](const NamedDecl &ND) {
1192 return ND.getLocation() == SL && llvm::isa<FunctionDecl>(ND);
1193 }));
1194 ASSERT_NE(FD, nullptr);
1195
1196 auto NonLocalDeclRefs = getNonLocalDeclRefs(AST, FD);
1197 std::vector<std::string> Names;
1198 for (const Decl *D : NonLocalDeclRefs) {
1199 if (const auto *ND = llvm::dyn_cast<NamedDecl>(D))
1200 Names.push_back(ND->getQualifiedNameAsString());
1201 }
1202 EXPECT_THAT(Names, UnorderedElementsAreArray(C.ExpectedDecls))
1203 << File.code();
1204 }
1205 }
1206
1207 TEST(DocumentLinks, All) {
1208 Annotations MainCpp(R"cpp(
1209 #include $foo[["foo.h"]]
1210 int end_of_preamble = 0;
1211 #include $bar[["bar.h"]]
1212 )cpp");
1213
1214 TestTU TU;
1215 TU.Code = MainCpp.code();
1216 TU.AdditionalFiles = {{"foo.h", ""}, {"bar.h", ""}};
1217 auto AST = TU.build();
1218
1219 EXPECT_THAT(
1220 clangd::getDocumentLinks(AST),
1221 ElementsAre(
1222 DocumentLink({MainCpp.range("foo"),
1223 URIForFile::canonicalize(testPath("foo.h"), "")}),
1224 DocumentLink({MainCpp.range("bar"),
1225 URIForFile::canonicalize(testPath("bar.h"), "")})));
1226 }
1227
1228 } // namespace
1229 } // namespace clangd
1230 } // namespace clang
clang::clangd::MATCHER_P
MATCHER_P(Named, N, "")
Definition: BackgroundIndexTests.cpp:26
Decl
const FunctionDecl * Decl
Definition: AvoidBindCheck.cpp:93
clang::clangd::WantDiagnostics::No
Diagnostics must be generated for this snapshot.
clang::clangd::getDocumentLinks
std::vector< DocumentLink > getDocumentLinks(ParsedAST &AST)
Get all document links.
Definition: XRefs.cpp:170
clang::clangd::runLocateSymbolAt
llvm::Expected< std::vector< LocatedSymbol > > runLocateSymbolAt(ClangdServer &Server, PathRef File, Position Pos)
Definition: SyncAPI.cpp:86
SourceCode.h
Matchers.h
Protocol.h
MemIndex.h
clang::clangd::PathRef
llvm::StringRef PathRef
A typedef to represent a ref to file path.
Definition: Path.h:23
clang::clangd::RefKind::All
Results
std::vector< CodeCompletionResult > Results
Definition: CodeComplete.cpp:689
FS
MockFSProvider FS
Definition: HeadersTests.cpp:119
clang::clangd::findReferences
ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit, const SymbolIndex *Index)
Returns references of the symbol at a specified Pos.
Definition: XRefs.cpp:423
clang::clangd::ClangdServer::optsForTest
static Options optsForTest()
Definition: ClangdServer.cpp:103
clang::clangd::TextDocumentSyncKind::None
Documents should not be synced at all.
TestFS.h
TestTU.h
clang::clangd::sourceLocationInMainFile
llvm::Expected< SourceLocation > sourceLocationInMainFile(const SourceManager &SM, Position P)
Return the file location, corresponding to P.
Definition: SourceCode.cpp:571
clang::clangd::TestTU::ExtraArgs
std::vector< const char * > ExtraArgs
Definition: TestTU.h:57
clang::clangd::WantDiagnostics::Yes
clang::clangd::DocumentHighlightKind::Read
clang::clangd::SymbolOrigin::AST
Annotations.h
clang::clangd::DocumentHighlightKind::Text
clang::clangd::TEST
TEST(BackgroundQueueTest, Priority)
Definition: BackgroundIndexTests.cpp:647
clang::clangd::testPath
std::string testPath(PathRef File)
Definition: TestFS.cpp:82
Compiler.h
clang::clangd::DiagnosticsConsumer::onDiagnosticsReady
virtual void onDiagnosticsReady(PathRef File, std::vector< Diag > Diagnostics)=0
Called by ClangdServer when Diagnostics for File are ready.
clang::clangd::RefKind::Definition
clang::clangd::URIForFile::canonicalize
static URIForFile canonicalize(llvm::StringRef AbsPath, llvm::StringRef TUPath)
Canonicalizes AbsPath via URI.
Definition: Protocol.cpp:32
Name
static constexpr llvm::StringLiteral Name
Definition: UppercaseLiteralSuffixCheck.cpp:27
clang::clangd::testRoot
const char * testRoot()
Definition: TestFS.cpp:74
clang::clangd::findDocumentHighlights
std::vector< DocumentHighlight > findDocumentHighlights(ParsedAST &AST, Position Pos)
Returns highlights for all usages of a symbol at Pos.
Definition: XRefs.cpp:390
clang::clangd::DocumentHighlightKind::Write
clang::clangd::TestTU::withCode
static TestTU withCode(llvm::StringRef Code)
Definition: TestTU.h:33
clang::clangd::DocumentHighlightKind
DocumentHighlightKind
Definition: Protocol.h:1093
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
SymbolCollector.h
References
unsigned References
Definition: CodeComplete.cpp:157
ParsedAST.h
Server
ClangdServer Server
Definition: FindSymbolsTests.cpp:70
Range
CharSourceRange Range
SourceRange for the file name.
Definition: IncludeOrderCheck.cpp:38
Expected
std::vector< const char * > Expected
Definition: PrintASTTests.cpp:27
SyncAPI.h
DiagConsumer
IgnoreDiagnostics DiagConsumer
Definition: FindSymbolsTests.cpp:69
TestIndex.h
clang::clangd::locateSymbolAt
std::vector< LocatedSymbol > locateSymbolAt(ParsedAST &AST, Position Pos, const SymbolIndex *Index)
Get definition of symbol at a specified Pos.
Definition: XRefs.cpp:190
FileIndex.h
HeaderContents
std::vector< HeaderEntry > HeaderContents
Definition: Modularize.cpp:483
AnnotatedCode
std::string AnnotatedCode
Definition: FindTargetTests.cpp:552
clang::clangd::CompletionItemKind::File
XRefs.h
clang::clangd::getNonLocalDeclRefs
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:826
clang::clangd::findDecl
const NamedDecl & findDecl(ParsedAST &AST, llvm::StringRef QName)
Definition: TestTU.cpp:118
clang::clangd::runAddDocument
void runAddDocument(ClangdServer &Server, PathRef File, llvm::StringRef Contents, WantDiagnostics WantDiags)
Definition: SyncAPI.cpp:15
Index
const SymbolIndex * Index
Definition: Dexp.cpp:84
Location
Definition: Modularize.cpp:383