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