clang-tools  11.0.0git
FindSymbolsTests.cpp
Go to the documentation of this file.
1 //===-- FindSymbolsTests.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 "ClangdServer.h"
10 #include "FindSymbols.h"
11 #include "SyncAPI.h"
12 #include "TestFS.h"
13 #include "TestTU.h"
14 #include "llvm/ADT/StringRef.h"
15 #include "gmock/gmock.h"
16 #include "gtest/gtest.h"
17 
18 namespace clang {
19 namespace clangd {
20 
21 namespace {
22 
23 using ::testing::AllOf;
24 using ::testing::ElementsAre;
25 using ::testing::ElementsAreArray;
26 using ::testing::Field;
27 using ::testing::IsEmpty;
28 using ::testing::UnorderedElementsAre;
29 
30 // GMock helpers for matching SymbolInfos items.
31 MATCHER_P(QName, Name, "") {
32  if (arg.containerName.empty())
33  return arg.name == Name;
34  return (arg.containerName + "::" + arg.name) == Name;
35 }
36 MATCHER_P(WithName, N, "") { return arg.name == N; }
37 MATCHER_P(WithKind, Kind, "") { return arg.kind == Kind; }
38 MATCHER_P(SymRange, Range, "") { return arg.location.range == Range; }
39 
40 // GMock helpers for matching DocumentSymbol.
41 MATCHER_P(SymNameRange, Range, "") { return arg.selectionRange == Range; }
42 template <class... ChildMatchers>
43 ::testing::Matcher<DocumentSymbol> Children(ChildMatchers... ChildrenM) {
44  return Field(&DocumentSymbol::children, ElementsAre(ChildrenM...));
45 }
46 
47 std::vector<SymbolInformation> getSymbols(TestTU &TU, llvm::StringRef Query,
48  int Limit = 0) {
49  auto SymbolInfos = getWorkspaceSymbols(Query, Limit, TU.index().get(),
50  testPath(TU.Filename));
51  EXPECT_TRUE(bool(SymbolInfos)) << "workspaceSymbols returned an error";
52  return *SymbolInfos;
53 }
54 
55 TEST(WorkspaceSymbols, Macros) {
56  TestTU TU;
57  TU.Code = R"cpp(
58  #define MACRO X
59  )cpp";
60 
61  // LSP's SymbolKind doesn't have a "Macro" kind, and
62  // indexSymbolKindToSymbolKind() currently maps macros
63  // to SymbolKind::String.
64  EXPECT_THAT(getSymbols(TU, "macro"),
65  ElementsAre(AllOf(QName("MACRO"), WithKind(SymbolKind::String))));
66 }
67 
68 TEST(WorkspaceSymbols, NoLocals) {
69  TestTU TU;
70  TU.Code = R"cpp(
71  void test(int FirstParam, int SecondParam) {
72  struct LocalClass {};
73  int local_var;
74  })cpp";
75  EXPECT_THAT(getSymbols(TU, "l"), IsEmpty());
76  EXPECT_THAT(getSymbols(TU, "p"), IsEmpty());
77 }
78 
79 TEST(WorkspaceSymbols, Globals) {
80  TestTU TU;
81  TU.AdditionalFiles["foo.h"] = R"cpp(
82  int global_var;
83 
84  int global_func();
85 
86  struct GlobalStruct {};)cpp";
87  TU.Code = R"cpp(
88  #include "foo.h"
89  )cpp";
90  EXPECT_THAT(getSymbols(TU, "global"),
91  UnorderedElementsAre(
92  AllOf(QName("GlobalStruct"), WithKind(SymbolKind::Struct)),
93  AllOf(QName("global_func"), WithKind(SymbolKind::Function)),
94  AllOf(QName("global_var"), WithKind(SymbolKind::Variable))));
95 }
96 
97 TEST(WorkspaceSymbols, Unnamed) {
98  TestTU TU;
99  TU.AdditionalFiles["foo.h"] = R"cpp(
100  struct {
101  int InUnnamed;
102  } UnnamedStruct;)cpp";
103  TU.Code = R"cpp(
104  #include "foo.h"
105  )cpp";
106  EXPECT_THAT(getSymbols(TU, "UnnamedStruct"),
107  ElementsAre(AllOf(QName("UnnamedStruct"),
108  WithKind(SymbolKind::Variable))));
109  EXPECT_THAT(getSymbols(TU, "InUnnamed"),
110  ElementsAre(AllOf(QName("(anonymous struct)::InUnnamed"),
111  WithKind(SymbolKind::Field))));
112 }
113 
114 TEST(WorkspaceSymbols, InMainFile) {
115  TestTU TU;
116  TU.Code = R"cpp(
117  int test() {}
118  static void test2() {}
119  )cpp";
120  EXPECT_THAT(getSymbols(TU, "test"),
121  ElementsAre(QName("test"), QName("test2")));
122 }
123 
124 TEST(WorkspaceSymbols, Namespaces) {
125  TestTU TU;
126  TU.AdditionalFiles["foo.h"] = R"cpp(
127  namespace ans1 {
128  int ai1;
129  namespace ans2 {
130  int ai2;
131  }
132  }
133  )cpp";
134  TU.Code = R"cpp(
135  #include "foo.h"
136  )cpp";
137  EXPECT_THAT(getSymbols(TU, "a"),
138  UnorderedElementsAre(QName("ans1"), QName("ans1::ai1"),
139  QName("ans1::ans2"),
140  QName("ans1::ans2::ai2")));
141  EXPECT_THAT(getSymbols(TU, "::"), ElementsAre(QName("ans1")));
142  EXPECT_THAT(getSymbols(TU, "::a"), ElementsAre(QName("ans1")));
143  EXPECT_THAT(getSymbols(TU, "ans1::"),
144  UnorderedElementsAre(QName("ans1::ai1"), QName("ans1::ans2")));
145  EXPECT_THAT(getSymbols(TU, "::ans1"), ElementsAre(QName("ans1")));
146  EXPECT_THAT(getSymbols(TU, "::ans1::"),
147  UnorderedElementsAre(QName("ans1::ai1"), QName("ans1::ans2")));
148  EXPECT_THAT(getSymbols(TU, "::ans1::ans2"), ElementsAre(QName("ans1::ans2")));
149  EXPECT_THAT(getSymbols(TU, "::ans1::ans2::"),
150  ElementsAre(QName("ans1::ans2::ai2")));
151 }
152 
153 TEST(WorkspaceSymbols, AnonymousNamespace) {
154  TestTU TU;
155  TU.Code = R"cpp(
156  namespace {
157  void test() {}
158  }
159  )cpp";
160  EXPECT_THAT(getSymbols(TU, "test"), ElementsAre(QName("test")));
161 }
162 
163 TEST(WorkspaceSymbols, MultiFile) {
164  TestTU TU;
165  TU.AdditionalFiles["foo.h"] = R"cpp(
166  int foo() {
167  }
168  )cpp";
169  TU.AdditionalFiles["foo2.h"] = R"cpp(
170  int foo2() {
171  }
172  )cpp";
173  TU.Code = R"cpp(
174  #include "foo.h"
175  #include "foo2.h"
176  )cpp";
177  EXPECT_THAT(getSymbols(TU, "foo"),
178  UnorderedElementsAre(QName("foo"), QName("foo2")));
179 }
180 
181 TEST(WorkspaceSymbols, GlobalNamespaceQueries) {
182  TestTU TU;
183  TU.AdditionalFiles["foo.h"] = R"cpp(
184  int foo() {
185  }
186  class Foo {
187  int a;
188  };
189  namespace ns {
190  int foo2() {
191  }
192  }
193  )cpp";
194  TU.Code = R"cpp(
195  #include "foo.h"
196  )cpp";
197  EXPECT_THAT(getSymbols(TU, "::"),
198  UnorderedElementsAre(
199  AllOf(QName("Foo"), WithKind(SymbolKind::Class)),
200  AllOf(QName("foo"), WithKind(SymbolKind::Function)),
201  AllOf(QName("ns"), WithKind(SymbolKind::Namespace))));
202  EXPECT_THAT(getSymbols(TU, ":"), IsEmpty());
203  EXPECT_THAT(getSymbols(TU, ""), IsEmpty());
204 }
205 
206 TEST(WorkspaceSymbols, Enums) {
207  TestTU TU;
208  TU.AdditionalFiles["foo.h"] = R"cpp(
209  enum {
210  Red
211  };
212  enum Color {
213  Green
214  };
215  enum class Color2 {
216  Yellow
217  };
218  namespace ns {
219  enum {
220  Black
221  };
222  enum Color3 {
223  Blue
224  };
225  enum class Color4 {
226  White
227  };
228  }
229  )cpp";
230  TU.Code = R"cpp(
231  #include "foo.h"
232  )cpp";
233  EXPECT_THAT(getSymbols(TU, "Red"), ElementsAre(QName("Red")));
234  EXPECT_THAT(getSymbols(TU, "::Red"), ElementsAre(QName("Red")));
235  EXPECT_THAT(getSymbols(TU, "Green"), ElementsAre(QName("Green")));
236  EXPECT_THAT(getSymbols(TU, "Green"), ElementsAre(QName("Green")));
237  EXPECT_THAT(getSymbols(TU, "Color2::Yellow"),
238  ElementsAre(QName("Color2::Yellow")));
239  EXPECT_THAT(getSymbols(TU, "Yellow"), ElementsAre(QName("Color2::Yellow")));
240 
241  EXPECT_THAT(getSymbols(TU, "ns::Black"), ElementsAre(QName("ns::Black")));
242  EXPECT_THAT(getSymbols(TU, "ns::Blue"), ElementsAre(QName("ns::Blue")));
243  EXPECT_THAT(getSymbols(TU, "ns::Color4::White"),
244  ElementsAre(QName("ns::Color4::White")));
245 }
246 
247 TEST(WorkspaceSymbols, Ranking) {
248  TestTU TU;
249  TU.AdditionalFiles["foo.h"] = R"cpp(
250  namespace ns{}
251  void func();
252  )cpp";
253  TU.Code = R"cpp(
254  #include "foo.h"
255  )cpp";
256  EXPECT_THAT(getSymbols(TU, "::"), ElementsAre(QName("func"), QName("ns")));
257 }
258 
259 TEST(WorkspaceSymbols, WithLimit) {
260  TestTU TU;
261  TU.AdditionalFiles["foo.h"] = R"cpp(
262  int foo;
263  int foo2;
264  )cpp";
265  TU.Code = R"cpp(
266  #include "foo.h"
267  )cpp";
268  // Foo is higher ranked because of exact name match.
269  EXPECT_THAT(getSymbols(TU, "foo"),
270  UnorderedElementsAre(
271  AllOf(QName("foo"), WithKind(SymbolKind::Variable)),
272  AllOf(QName("foo2"), WithKind(SymbolKind::Variable))));
273 
274  EXPECT_THAT(getSymbols(TU, "foo", 1), ElementsAre(QName("foo")));
275 }
276 
277 TEST(WorkspaceSymbols, TempSpecs) {
278  TestTU TU;
279  TU.ExtraArgs = {"-xc++"};
280  TU.Code = R"cpp(
281  template <typename T, typename U, int X = 5> class Foo {};
282  template <typename T> class Foo<int, T> {};
283  template <> class Foo<bool, int> {};
284  template <> class Foo<bool, int, 3> {};
285  )cpp";
286  // Foo is higher ranked because of exact name match.
287  EXPECT_THAT(
288  getSymbols(TU, "Foo"),
289  UnorderedElementsAre(
290  AllOf(QName("Foo"), WithKind(SymbolKind::Class)),
291  AllOf(QName("Foo<int, T>"), WithKind(SymbolKind::Class)),
292  AllOf(QName("Foo<bool, int>"), WithKind(SymbolKind::Class)),
293  AllOf(QName("Foo<bool, int, 3>"), WithKind(SymbolKind::Class))));
294 }
295 
296 std::vector<DocumentSymbol> getSymbols(ParsedAST AST) {
297  auto SymbolInfos = getDocumentSymbols(AST);
298  EXPECT_TRUE(bool(SymbolInfos)) << "documentSymbols returned an error";
299  return *SymbolInfos;
300 }
301 
302 TEST(DocumentSymbols, BasicSymbols) {
303  TestTU TU;
304  Annotations Main(R"(
305  class Foo;
306  class Foo {
307  Foo() {}
308  Foo(int a) {}
309  void $decl[[f]]();
310  friend void f1();
311  friend class Friend;
312  Foo& operator=(const Foo&);
313  ~Foo();
314  class Nested {
315  void f();
316  };
317  };
318  class Friend {
319  };
320 
321  void f1();
322  inline void f2() {}
323  static const int KInt = 2;
324  const char* kStr = "123";
325 
326  void f1() {}
327 
328  namespace foo {
329  // Type alias
330  typedef int int32;
331  using int32_t = int32;
332 
333  // Variable
334  int v1;
335 
336  // Namespace
337  namespace bar {
338  int v2;
339  }
340  // Namespace alias
341  namespace baz = bar;
342 
343  using bar::v2;
344  } // namespace foo
345  )");
346 
347  TU.Code = Main.code().str();
348  EXPECT_THAT(
349  getSymbols(TU.build()),
350  ElementsAreArray(
351  {AllOf(WithName("Foo"), WithKind(SymbolKind::Class), Children()),
352  AllOf(WithName("Foo"), WithKind(SymbolKind::Class),
353  Children(AllOf(WithName("Foo"),
354  WithKind(SymbolKind::Constructor), Children()),
355  AllOf(WithName("Foo"),
356  WithKind(SymbolKind::Constructor), Children()),
357  AllOf(WithName("f"), WithKind(SymbolKind::Method),
358  Children()),
359  AllOf(WithName("operator="),
360  WithKind(SymbolKind::Method), Children()),
361  AllOf(WithName("~Foo"),
362  WithKind(SymbolKind::Constructor), Children()),
363  AllOf(WithName("Nested"), WithKind(SymbolKind::Class),
364  Children(AllOf(WithName("f"),
365  WithKind(SymbolKind::Method),
366  Children()))))),
367  AllOf(WithName("Friend"), WithKind(SymbolKind::Class), Children()),
368  AllOf(WithName("f1"), WithKind(SymbolKind::Function), Children()),
369  AllOf(WithName("f2"), WithKind(SymbolKind::Function), Children()),
370  AllOf(WithName("KInt"), WithKind(SymbolKind::Variable), Children()),
371  AllOf(WithName("kStr"), WithKind(SymbolKind::Variable), Children()),
372  AllOf(WithName("f1"), WithKind(SymbolKind::Function), Children()),
373  AllOf(
374  WithName("foo"), WithKind(SymbolKind::Namespace),
375  Children(
376  AllOf(WithName("int32"), WithKind(SymbolKind::Class),
377  Children()),
378  AllOf(WithName("int32_t"), WithKind(SymbolKind::Class),
379  Children()),
380  AllOf(WithName("v1"), WithKind(SymbolKind::Variable),
381  Children()),
382  AllOf(WithName("bar"), WithKind(SymbolKind::Namespace),
383  Children(AllOf(WithName("v2"),
384  WithKind(SymbolKind::Variable),
385  Children()))),
386  AllOf(WithName("baz"), WithKind(SymbolKind::Namespace),
387  Children()),
388  AllOf(WithName("v2"), WithKind(SymbolKind::Namespace))))}));
389 }
390 
391 TEST(DocumentSymbols, DeclarationDefinition) {
392  TestTU TU;
393  Annotations Main(R"(
394  class Foo {
395  void $decl[[f]]();
396  };
397  void Foo::$def[[f]]() {
398  }
399  )");
400 
401  TU.Code = Main.code().str();
402  EXPECT_THAT(
403  getSymbols(TU.build()),
404  ElementsAre(
405  AllOf(WithName("Foo"), WithKind(SymbolKind::Class),
406  Children(AllOf(WithName("f"), WithKind(SymbolKind::Method),
407  SymNameRange(Main.range("decl"))))),
408  AllOf(WithName("Foo::f"), WithKind(SymbolKind::Method),
409  SymNameRange(Main.range("def")))));
410 }
411 
412 TEST(DocumentSymbols, Concepts) {
413  TestTU TU;
414  TU.ExtraArgs = {"-std=c++20"};
415  TU.Code = "template <typename T> concept C = requires(T t) { t.foo(); };";
416 
417  EXPECT_THAT(getSymbols(TU.build()), ElementsAre(WithName("C")));
418 }
419 
420 TEST(DocumentSymbols, ExternSymbol) {
421  TestTU TU;
422  TU.AdditionalFiles["foo.h"] = R"cpp(
423  extern int var;
424  )cpp";
425  TU.Code = R"cpp(
426  #include "foo.h"
427  )cpp";
428 
429  EXPECT_THAT(getSymbols(TU.build()), IsEmpty());
430 }
431 
432 TEST(DocumentSymbols, NoLocals) {
433  TestTU TU;
434  TU.Code = R"cpp(
435  void test(int FirstParam, int SecondParam) {
436  struct LocalClass {};
437  int local_var;
438  })cpp";
439  EXPECT_THAT(getSymbols(TU.build()), ElementsAre(WithName("test")));
440 }
441 
442 TEST(DocumentSymbols, Unnamed) {
443  TestTU TU;
444  TU.Code = R"cpp(
445  struct {
446  int InUnnamed;
447  } UnnamedStruct;
448  )cpp";
449  EXPECT_THAT(
450  getSymbols(TU.build()),
451  ElementsAre(
452  AllOf(WithName("(anonymous struct)"), WithKind(SymbolKind::Struct),
453  Children(AllOf(WithName("InUnnamed"),
454  WithKind(SymbolKind::Field), Children()))),
455  AllOf(WithName("UnnamedStruct"), WithKind(SymbolKind::Variable),
456  Children())));
457 }
458 
459 TEST(DocumentSymbols, InHeaderFile) {
460  TestTU TU;
461  TU.AdditionalFiles["bar.h"] = R"cpp(
462  int foo() {
463  }
464  )cpp";
465  TU.Code = R"cpp(
466  #include "bar.h"
467  int test() {
468  }
469  )cpp";
470  EXPECT_THAT(getSymbols(TU.build()), ElementsAre(WithName("test")));
471 }
472 
473 TEST(DocumentSymbols, Template) {
474  TestTU TU;
475  TU.Code = R"(
476  template <class T> struct Tmpl {T x = 0;};
477  template <> struct Tmpl<int> {
478  int y = 0;
479  };
480  extern template struct Tmpl<float>;
481  template struct Tmpl<double>;
482 
483  template <class T, class U, class Z = float>
484  int funcTmpl(U a);
485  template <>
486  int funcTmpl<int>(double a);
487 
488  template <class T, class U = double>
489  int varTmpl = T();
490  template <>
491  double varTmpl<int> = 10.0;
492  )";
493  EXPECT_THAT(
494  getSymbols(TU.build()),
495  ElementsAre(
496  AllOf(WithName("Tmpl"), WithKind(SymbolKind::Struct),
497  Children(AllOf(WithName("x"), WithKind(SymbolKind::Field)))),
498  AllOf(WithName("Tmpl<int>"), WithKind(SymbolKind::Struct),
499  Children(WithName("y"))),
500  AllOf(WithName("Tmpl<float>"), WithKind(SymbolKind::Struct),
501  Children()),
502  AllOf(WithName("Tmpl<double>"), WithKind(SymbolKind::Struct),
503  Children()),
504  AllOf(WithName("funcTmpl"), Children()),
505  AllOf(WithName("funcTmpl<int>"), Children()),
506  AllOf(WithName("varTmpl"), Children()),
507  AllOf(WithName("varTmpl<int>"), Children())));
508 }
509 
510 TEST(DocumentSymbols, Namespaces) {
511  TestTU TU;
512  TU.Code = R"cpp(
513  namespace ans1 {
514  int ai1;
515  namespace ans2 {
516  int ai2;
517  }
518  }
519  namespace {
520  void test() {}
521  }
522 
523  namespace na {
524  inline namespace nb {
525  class Foo {};
526  }
527  }
528  namespace na {
529  // This is still inlined.
530  namespace nb {
531  class Bar {};
532  }
533  }
534  )cpp";
535  EXPECT_THAT(
536  getSymbols(TU.build()),
537  ElementsAreArray<::testing::Matcher<DocumentSymbol>>(
538  {AllOf(WithName("ans1"),
539  Children(AllOf(WithName("ai1"), Children()),
540  AllOf(WithName("ans2"), Children(WithName("ai2"))))),
541  AllOf(WithName("(anonymous namespace)"), Children(WithName("test"))),
542  AllOf(WithName("na"),
543  Children(AllOf(WithName("nb"), Children(WithName("Foo"))))),
544  AllOf(WithName("na"),
545  Children(AllOf(WithName("nb"), Children(WithName("Bar")))))}));
546 }
547 
548 TEST(DocumentSymbols, Enums) {
549  TestTU TU;
550  TU.Code = R"(
551  enum {
552  Red
553  };
554  enum Color {
555  Green
556  };
557  enum class Color2 {
558  Yellow
559  };
560  namespace ns {
561  enum {
562  Black
563  };
564  }
565  )";
566  EXPECT_THAT(
567  getSymbols(TU.build()),
568  ElementsAre(
569  AllOf(WithName("(anonymous enum)"), Children(WithName("Red"))),
570  AllOf(WithName("Color"), Children(WithName("Green"))),
571  AllOf(WithName("Color2"), Children(WithName("Yellow"))),
572  AllOf(WithName("ns"), Children(AllOf(WithName("(anonymous enum)"),
573  Children(WithName("Black")))))));
574 }
575 
576 TEST(DocumentSymbols, FromMacro) {
577  TestTU TU;
578  Annotations Main(R"(
579  #define FF(name) \
580  class name##_Test {};
581 
582  $expansion[[FF]](abc);
583 
584  #define FF2() \
585  class $spelling[[Test]] {};
586 
587  FF2();
588  )");
589  TU.Code = Main.code().str();
590  EXPECT_THAT(
591  getSymbols(TU.build()),
592  ElementsAre(
593  AllOf(WithName("abc_Test"), SymNameRange(Main.range("expansion"))),
594  AllOf(WithName("Test"), SymNameRange(Main.range("spelling")))));
595 }
596 
597 TEST(DocumentSymbols, FuncTemplates) {
598  TestTU TU;
599  Annotations Source(R"cpp(
600  template <class T>
601  T foo() {}
602 
603  auto x = foo<int>();
604  auto y = foo<double>();
605  )cpp");
606  TU.Code = Source.code().str();
607  // Make sure we only see the template declaration, not instantiations.
608  EXPECT_THAT(getSymbols(TU.build()),
609  ElementsAre(WithName("foo"), WithName("x"), WithName("y")));
610 }
611 
612 TEST(DocumentSymbols, UsingDirectives) {
613  TestTU TU;
614  Annotations Source(R"cpp(
615  namespace ns {
616  int foo;
617  }
618 
619  namespace ns_alias = ns;
620 
621  using namespace ::ns; // check we don't loose qualifiers.
622  using namespace ns_alias; // and namespace aliases.
623  )cpp");
624  TU.Code = Source.code().str();
625  EXPECT_THAT(getSymbols(TU.build()),
626  ElementsAre(WithName("ns"), WithName("ns_alias"),
627  WithName("using namespace ::ns"),
628  WithName("using namespace ns_alias")));
629 }
630 
631 TEST(DocumentSymbols, TempSpecs) {
632  TestTU TU;
633  TU.Code = R"cpp(
634  template <typename T, typename U, int X = 5> class Foo {};
635  template <typename T> class Foo<int, T> {};
636  template <> class Foo<bool, int> {};
637  template <> class Foo<bool, int, 3> {};
638  )cpp";
639  // Foo is higher ranked because of exact name match.
640  EXPECT_THAT(
641  getSymbols(TU.build()),
642  UnorderedElementsAre(
643  AllOf(WithName("Foo"), WithKind(SymbolKind::Class)),
644  AllOf(WithName("Foo<int, T>"), WithKind(SymbolKind::Class)),
645  AllOf(WithName("Foo<bool, int>"), WithKind(SymbolKind::Class)),
646  AllOf(WithName("Foo<bool, int, 3>"), WithKind(SymbolKind::Class))));
647 }
648 
649 TEST(DocumentSymbols, Qualifiers) {
650  TestTU TU;
651  TU.Code = R"cpp(
652  namespace foo { namespace bar {
653  struct Cls;
654 
655  int func1();
656  int func2();
657  int func3();
658  int func4();
659  }}
660 
661  struct foo::bar::Cls { };
662 
663  int foo::bar::func1() { return 10; }
664  int ::foo::bar::func2() { return 20; }
665 
666  using namespace foo;
667  int bar::func3() { return 30; }
668 
669  namespace alias = foo::bar;
670  int ::alias::func4() { return 40; }
671  )cpp";
672 
673  // All the qualifiers should be preserved exactly as written.
674  EXPECT_THAT(getSymbols(TU.build()),
675  UnorderedElementsAre(
676  WithName("foo"), WithName("foo::bar::Cls"),
677  WithName("foo::bar::func1"), WithName("::foo::bar::func2"),
678  WithName("using namespace foo"), WithName("bar::func3"),
679  WithName("alias"), WithName("::alias::func4")));
680 }
681 
682 TEST(DocumentSymbols, QualifiersWithTemplateArgs) {
683  TestTU TU;
684  TU.Code = R"cpp(
685  template <typename T, typename U = double> class Foo;
686 
687  template <>
688  class Foo<int, double> {
689  int method1();
690  int method2();
691  int method3();
692  };
693 
694  using int_type = int;
695 
696  // Typedefs should be preserved!
697  int Foo<int_type, double>::method1() { return 10; }
698 
699  // Default arguments should not be shown!
700  int Foo<int>::method2() { return 20; }
701 
702  using Foo_type = Foo<int>;
703  // If the whole type is aliased, this should be preserved too!
704  int Foo_type::method3() { return 30; }
705  )cpp";
706  EXPECT_THAT(
707  getSymbols(TU.build()),
708  UnorderedElementsAre(WithName("Foo"), WithName("Foo<int, double>"),
709  WithName("int_type"),
710  WithName("Foo<int_type, double>::method1"),
711  WithName("Foo<int>::method2"), WithName("Foo_type"),
712  WithName("Foo_type::method3")));
713 }
714 
715 } // namespace
716 } // namespace clangd
717 } // namespace clang
MATCHER_P(Named, N, "")
llvm::Expected< std::vector< SymbolInformation > > getWorkspaceSymbols(llvm::StringRef Query, int Limit, const SymbolIndex *const Index, llvm::StringRef HintPath)
Searches for the symbols matching Query.
Definition: FindSymbols.cpp:71
BindArgumentKind Kind
std::string QName
TEST(BackgroundQueueTest, Priority)
std::string testPath(PathRef File, llvm::sys::path::Style Style)
Definition: TestFS.cpp:82
static constexpr llvm::StringLiteral Name
std::vector< DocumentSymbol > children
Children of this symbol, e.g. properties of a class.
Definition: Protocol.h:969
std::vector< std::unique_ptr< HTMLNode > > Children
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
llvm::Expected< std::vector< DocumentSymbol > > getDocumentSymbols(ParsedAST &AST)
Retrieves the symbols contained in the "main file" section of an AST in the same order that they appe...
CharSourceRange Range
SourceRange for the file name.