clang-tools  10.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 "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 {
47  std::vector<Diag> Diagnostics) override {}
48 };
49 
50 MATCHER_P2(FileRange, File, Range, "") {
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())
66  for (const auto &Range : Test.ranges("read"))
68  for (const auto &Range : Test.ranges("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(
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
MATCHER_P(Named, N, "")
const FunctionDecl * Decl
Diagnostics must be generated for this snapshot.
std::vector< DocumentLink > getDocumentLinks(ParsedAST &AST)
Get all document links.
Definition: XRefs.cpp:170
llvm::Expected< std::vector< LocatedSymbol > > runLocateSymbolAt(ClangdServer &Server, PathRef File, Position Pos)
Definition: SyncAPI.cpp:86
llvm::StringRef PathRef
A typedef to represent a ref to file path.
Definition: Path.h:23
std::vector< CodeCompletionResult > Results
MockFSProvider FS
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
static Options optsForTest()
Documents should not be synced at all.
llvm::Expected< SourceLocation > sourceLocationInMainFile(const SourceManager &SM, Position P)
Return the file location, corresponding to P.
Definition: SourceCode.cpp:571
std::vector< const char * > ExtraArgs
Definition: TestTU.h:57
TEST(BackgroundQueueTest, Priority)
std::string testPath(PathRef File)
Definition: TestFS.cpp:82
virtual void onDiagnosticsReady(PathRef File, std::vector< Diag > Diagnostics)=0
Called by ClangdServer when Diagnostics for File are ready.
static URIForFile canonicalize(llvm::StringRef AbsPath, llvm::StringRef TUPath)
Canonicalizes AbsPath via URI.
Definition: Protocol.cpp:32
static constexpr llvm::StringLiteral Name
const char * testRoot()
Definition: TestFS.cpp:74
std::vector< DocumentHighlight > findDocumentHighlights(ParsedAST &AST, Position Pos)
Returns highlights for all usages of a symbol at Pos.
Definition: XRefs.cpp:390
static TestTU withCode(llvm::StringRef Code)
Definition: TestTU.h:33
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
unsigned References
ClangdServer Server
CharSourceRange Range
SourceRange for the file name.
std::vector< const char * > Expected
IgnoreDiagnostics DiagConsumer
std::vector< LocatedSymbol > locateSymbolAt(ParsedAST &AST, Position Pos, const SymbolIndex *Index)
Get definition of symbol at a specified Pos.
Definition: XRefs.cpp:190
std::vector< HeaderEntry > HeaderContents
Definition: Modularize.cpp:483
std::string AnnotatedCode
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
const NamedDecl & findDecl(ParsedAST &AST, llvm::StringRef QName)
Definition: TestTU.cpp:118
void runAddDocument(ClangdServer &Server, PathRef File, llvm::StringRef Contents, WantDiagnostics WantDiags)
Definition: SyncAPI.cpp:15
const SymbolIndex * Index
Definition: Dexp.cpp:84