clang-tools  10.0.0git
HoverTests.cpp
Go to the documentation of this file.
1 //===-- HoverTests.cpp ----------------------------------------------------===//
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 
9 #include "AST.h"
10 #include "Annotations.h"
11 #include "Hover.h"
12 #include "TestIndex.h"
13 #include "TestTU.h"
14 #include "index/MemIndex.h"
15 #include "clang/Index/IndexSymbol.h"
16 #include "llvm/ADT/None.h"
17 #include "llvm/ADT/StringRef.h"
18 
19 #include "gmock/gmock.h"
20 #include "gtest/gtest.h"
21 #include <string>
22 #include <vector>
23 
24 namespace clang {
25 namespace clangd {
26 namespace {
27 
28 TEST(Hover, Structured) {
29  struct {
30  const char *const Code;
31  const std::function<void(HoverInfo &)> ExpectedBuilder;
32  } Cases[] = {
33  // Global scope.
34  {R"cpp(
35  // Best foo ever.
36  void [[fo^o]]() {}
37  )cpp",
38  [](HoverInfo &HI) {
39  HI.NamespaceScope = "";
40  HI.Name = "foo";
41  HI.Kind = index::SymbolKind::Function;
42  HI.Documentation = "Best foo ever.";
43  HI.Definition = "void foo()";
44  HI.ReturnType = "void";
45  HI.Type = "void ()";
46  HI.Parameters.emplace();
47  }},
48  // Inside namespace
49  {R"cpp(
50  namespace ns1 { namespace ns2 {
51  /// Best foo ever.
52  void [[fo^o]]() {}
53  }}
54  )cpp",
55  [](HoverInfo &HI) {
56  HI.NamespaceScope = "ns1::ns2::";
57  HI.Name = "foo";
58  HI.Kind = index::SymbolKind::Function;
59  HI.Documentation = "Best foo ever.";
60  HI.Definition = "void foo()";
61  HI.ReturnType = "void";
62  HI.Type = "void ()";
63  HI.Parameters.emplace();
64  }},
65  // Field
66  {R"cpp(
67  namespace ns1 { namespace ns2 {
68  struct Foo {
69  int [[b^ar]];
70  };
71  }}
72  )cpp",
73  [](HoverInfo &HI) {
74  HI.NamespaceScope = "ns1::ns2::";
75  HI.LocalScope = "Foo::";
76  HI.Name = "bar";
77  HI.Kind = index::SymbolKind::Field;
78  HI.Definition = "int bar";
79  HI.Type = "int";
80  }},
81  // Local to class method.
82  {R"cpp(
83  namespace ns1 { namespace ns2 {
84  struct Foo {
85  void foo() {
86  int [[b^ar]];
87  }
88  };
89  }}
90  )cpp",
91  [](HoverInfo &HI) {
92  HI.NamespaceScope = "ns1::ns2::";
93  HI.LocalScope = "Foo::foo::";
94  HI.Name = "bar";
95  HI.Kind = index::SymbolKind::Variable;
96  HI.Definition = "int bar";
97  HI.Type = "int";
98  }},
99  // Anon namespace and local scope.
100  {R"cpp(
101  namespace ns1 { namespace {
102  struct {
103  int [[b^ar]];
104  } T;
105  }}
106  )cpp",
107  [](HoverInfo &HI) {
108  HI.NamespaceScope = "ns1::";
109  HI.LocalScope = "(anonymous struct)::";
110  HI.Name = "bar";
111  HI.Kind = index::SymbolKind::Field;
112  HI.Definition = "int bar";
113  HI.Type = "int";
114  }},
115  // Variable with template type
116  {R"cpp(
117  template <typename T, class... Ts> class Foo { public: Foo(int); };
118  Foo<int, char, bool> [[fo^o]] = Foo<int, char, bool>(5);
119  )cpp",
120  [](HoverInfo &HI) {
121  HI.NamespaceScope = "";
122  HI.Name = "foo";
123  HI.Kind = index::SymbolKind::Variable;
124  HI.Definition = "Foo<int, char, bool> foo = Foo<int, char, bool>(5)";
125  HI.Type = "Foo<int, char, bool>";
126  }},
127  // Implicit template instantiation
128  {R"cpp(
129  template <typename T> class vector{};
130  [[vec^tor]]<int> foo;
131  )cpp",
132  [](HoverInfo &HI) {
133  HI.NamespaceScope = "";
134  HI.Name = "vector<int>";
135  HI.Kind = index::SymbolKind::Class;
136  HI.Definition = "template <> class vector<int> {}";
137  }},
138  // Class template
139  {R"cpp(
140  template <template<typename, bool...> class C,
141  typename = char,
142  int = 0,
143  bool Q = false,
144  class... Ts> class Foo {};
145  template <template<typename, bool...> class T>
146  [[F^oo]]<T> foo;
147  )cpp",
148  [](HoverInfo &HI) {
149  HI.NamespaceScope = "";
150  HI.Name = "Foo";
151  HI.Kind = index::SymbolKind::Class;
152  HI.Definition =
153  R"cpp(template <template <typename, bool...> class C, typename = char, int = 0,
154  bool Q = false, class... Ts>
155 class Foo {})cpp";
156  HI.TemplateParameters = {
157  {std::string("template <typename, bool...> class"),
158  std::string("C"), llvm::None},
159  {std::string("typename"), llvm::None, std::string("char")},
160  {std::string("int"), llvm::None, std::string("0")},
161  {std::string("bool"), std::string("Q"), std::string("false")},
162  {std::string("class..."), std::string("Ts"), llvm::None},
163  };
164  }},
165  // Function template
166  {R"cpp(
167  template <template<typename, bool...> class C,
168  typename = char,
169  int = 0,
170  bool Q = false,
171  class... Ts> void foo();
172  template<typename, bool...> class Foo;
173 
174  void bar() {
175  [[fo^o]]<Foo>();
176  }
177  )cpp",
178  [](HoverInfo &HI) {
179  HI.NamespaceScope = "";
180  HI.Name = "foo";
181  HI.Kind = index::SymbolKind::Function;
182  HI.Definition = "template <> void foo<Foo, char, 0, false, <>>()";
183  HI.ReturnType = "void";
184  HI.Type = "void ()";
185  HI.Parameters.emplace();
186  }},
187  // Function decl
188  {R"cpp(
189  template<typename, bool...> class Foo {};
190  Foo<bool, true, false> foo(int, bool T = false);
191 
192  void bar() {
193  [[fo^o]](3);
194  }
195  )cpp",
196  [](HoverInfo &HI) {
197  HI.NamespaceScope = "";
198  HI.Name = "foo";
199  HI.Kind = index::SymbolKind::Function;
200  HI.Definition = "Foo<bool, true, false> foo(int, bool T = false)";
201  HI.ReturnType = "Foo<bool, true, false>";
202  HI.Type = "Foo<bool, true, false> (int, bool)";
203  HI.Parameters = {
204  {std::string("int"), llvm::None, llvm::None},
205  {std::string("bool"), std::string("T"), std::string("false")},
206  };
207  }},
208  // Pointers to lambdas
209  {R"cpp(
210  void foo() {
211  auto lamb = [](int T, bool B) -> bool { return T && B; };
212  auto *b = &lamb;
213  auto *[[^c]] = &b;
214  }
215  )cpp",
216  [](HoverInfo &HI) {
217  HI.NamespaceScope = "";
218  HI.LocalScope = "foo::";
219  HI.Name = "c";
220  HI.Kind = index::SymbolKind::Variable;
221  HI.Definition = "auto *c = &b";
222  HI.Type = "class (lambda) **";
223  HI.ReturnType = "bool";
224  HI.Parameters = {
225  {std::string("int"), std::string("T"), llvm::None},
226  {std::string("bool"), std::string("B"), llvm::None},
227  };
228  return HI;
229  }},
230  // Lambda parameter with decltype reference
231  {R"cpp(
232  auto lamb = [](int T, bool B) -> bool { return T && B; };
233  void foo(decltype(lamb)& bar) {
234  [[ba^r]](0, false);
235  }
236  )cpp",
237  [](HoverInfo &HI) {
238  HI.NamespaceScope = "";
239  HI.LocalScope = "foo::";
240  HI.Name = "bar";
241  HI.Kind = index::SymbolKind::Parameter;
242  HI.Definition = "decltype(lamb) &bar";
243  HI.Type = "decltype(lamb) &";
244  HI.ReturnType = "bool";
245  HI.Parameters = {
246  {std::string("int"), std::string("T"), llvm::None},
247  {std::string("bool"), std::string("B"), llvm::None},
248  };
249  return HI;
250  }},
251  // Lambda parameter with decltype
252  {R"cpp(
253  auto lamb = [](int T, bool B) -> bool { return T && B; };
254  void foo(decltype(lamb) bar) {
255  [[ba^r]](0, false);
256  }
257  )cpp",
258  [](HoverInfo &HI) {
259  HI.NamespaceScope = "";
260  HI.LocalScope = "foo::";
261  HI.Name = "bar";
262  HI.Kind = index::SymbolKind::Parameter;
263  HI.Definition = "decltype(lamb) bar";
264  HI.Type = "class (lambda)";
265  HI.ReturnType = "bool";
266  HI.Parameters = {
267  {std::string("int"), std::string("T"), llvm::None},
268  {std::string("bool"), std::string("B"), llvm::None},
269  };
270  HI.Value = "false";
271  return HI;
272  }},
273  // Lambda variable
274  {R"cpp(
275  void foo() {
276  int bar = 5;
277  auto lamb = [&bar](int T, bool B) -> bool { return T && B && bar; };
278  bool res = [[lam^b]](bar, false);
279  }
280  )cpp",
281  [](HoverInfo &HI) {
282  HI.NamespaceScope = "";
283  HI.LocalScope = "foo::";
284  HI.Name = "lamb";
285  HI.Kind = index::SymbolKind::Variable;
286  HI.Definition = "auto lamb = [&bar](int T, bool B) -> bool {}";
287  HI.Type = "class (lambda)";
288  HI.ReturnType = "bool";
289  HI.Parameters = {
290  {std::string("int"), std::string("T"), llvm::None},
291  {std::string("bool"), std::string("B"), llvm::None},
292  };
293  return HI;
294  }},
295  // Local variable in lambda
296  {R"cpp(
297  void foo() {
298  auto lamb = []{int [[te^st]];};
299  }
300  )cpp",
301  [](HoverInfo &HI) {
302  HI.NamespaceScope = "";
303  HI.LocalScope = "foo::(anonymous class)::operator()::";
304  HI.Name = "test";
305  HI.Kind = index::SymbolKind::Variable;
306  HI.Definition = "int test";
307  HI.Type = "int";
308  }},
309  // Partially-specialized class template. (formerly type-parameter-0-0)
310  {R"cpp(
311  template <typename T> class X;
312  template <typename T> class [[^X]]<T*> {};
313  )cpp",
314  [](HoverInfo &HI) {
315  HI.Name = "X<T *>";
316  HI.NamespaceScope = "";
317  HI.Kind = index::SymbolKind::Class;
318  HI.Definition = "template <typename T> class X<T *> {}";
319  }},
320  // Constructor of partially-specialized class template
321  {R"cpp(
322  template<typename, typename=void> struct X;
323  template<typename T> struct X<T*>{ [[^X]](); };
324  )cpp",
325  [](HoverInfo &HI) {
326  HI.NamespaceScope = "";
327  HI.Name = "X";
328  HI.LocalScope = "X<T *>::"; // FIXME: X<T *, void>::
329  HI.Kind = index::SymbolKind::Constructor;
330  HI.Definition = "X()";
331  HI.Parameters.emplace();
332  }},
333  {"class X { [[^~]]X(); };", // FIXME: Should be [[~X]]()
334  [](HoverInfo &HI) {
335  HI.NamespaceScope = "";
336  HI.Name = "~X";
337  HI.LocalScope = "X::";
338  HI.Kind = index::SymbolKind::Destructor;
339  HI.Definition = "~X()";
340  HI.Parameters.emplace();
341  }},
342  {"class X { operator [[in^t]](); };",
343  [](HoverInfo &HI) {
344  HI.NamespaceScope = "";
345  HI.Name = "operator int";
346  HI.LocalScope = "X::";
347  HI.Kind = index::SymbolKind::ConversionFunction;
348  HI.Definition = "operator int()";
349  HI.Parameters.emplace();
350  }},
351 
352  // auto on lambda
353  {R"cpp(
354  void foo() {
355  [[au^to]] lamb = []{};
356  }
357  )cpp",
358  [](HoverInfo &HI) {
359  HI.Name = "(lambda)";
360  HI.Kind = index::SymbolKind::Class;
361  }},
362  // auto on template instantiation
363  {R"cpp(
364  template<typename T> class Foo{};
365  void foo() {
366  [[au^to]] x = Foo<int>();
367  }
368  )cpp",
369  [](HoverInfo &HI) {
370  HI.Name = "Foo<int>";
371  HI.Kind = index::SymbolKind::Class;
372  }},
373  // auto on specialized template
374  {R"cpp(
375  template<typename T> class Foo{};
376  template<> class Foo<int>{};
377  void foo() {
378  [[au^to]] x = Foo<int>();
379  }
380  )cpp",
381  [](HoverInfo &HI) {
382  HI.Name = "Foo<int>";
383  HI.Kind = index::SymbolKind::Class;
384  }},
385 
386  // macro
387  {R"cpp(
388  // Best MACRO ever.
389  #define MACRO(x,y,z) void foo(x, y, z);
390  [[MAC^RO]](int, double d, bool z = false);
391  )cpp",
392  [](HoverInfo &HI) {
393  HI.Name = "MACRO", HI.Kind = index::SymbolKind::Macro,
394  HI.Definition = "#define MACRO(x, y, z) void foo(x, y, z);";
395  }},
396 
397  // constexprs
398  {R"cpp(
399  constexpr int add(int a, int b) { return a + b; }
400  int [[b^ar]] = add(1, 2);
401  )cpp",
402  [](HoverInfo &HI) {
403  HI.Name = "bar";
404  HI.Definition = "int bar = add(1, 2)";
405  HI.Kind = index::SymbolKind::Variable;
406  HI.Type = "int";
407  HI.NamespaceScope = "";
408  HI.Value = "3";
409  }},
410  {R"cpp(
411  int [[b^ar]] = sizeof(char);
412  )cpp",
413  [](HoverInfo &HI) {
414  HI.Name = "bar";
415  HI.Definition = "int bar = sizeof(char)";
416  HI.Kind = index::SymbolKind::Variable;
417  HI.Type = "int";
418  HI.NamespaceScope = "";
419  HI.Value = "1";
420  }},
421  {R"cpp(
422  template<int a, int b> struct Add {
423  static constexpr int result = a + b;
424  };
425  int [[ba^r]] = Add<1, 2>::result;
426  )cpp",
427  [](HoverInfo &HI) {
428  HI.Name = "bar";
429  HI.Definition = "int bar = Add<1, 2>::result";
430  HI.Kind = index::SymbolKind::Variable;
431  HI.Type = "int";
432  HI.NamespaceScope = "";
433  HI.Value = "3";
434  }},
435  {R"cpp(
436  enum Color { RED, GREEN, };
437  Color x = [[GR^EEN]];
438  )cpp",
439  [](HoverInfo &HI) {
440  HI.Name = "GREEN";
441  HI.NamespaceScope = "";
442  HI.LocalScope = "Color::";
443  HI.Definition = "GREEN";
444  HI.Kind = index::SymbolKind::EnumConstant;
445  HI.Type = "enum Color";
446  HI.Value = "1"; // Numeric when hovering on the enumerator name.
447  }},
448  {R"cpp(
449  enum Color { RED, GREEN, };
450  Color x = GREEN;
451  Color y = [[^x]];
452  )cpp",
453  [](HoverInfo &HI) {
454  HI.Name = "x";
455  HI.NamespaceScope = "";
456  HI.Definition = "Color x = GREEN";
457  HI.Kind = index::SymbolKind::Variable;
458  HI.Type = "enum Color";
459  HI.Value = "GREEN (1)"; // Symbolic when hovering on an expression.
460  }},
461  {R"cpp(
462  template<int a, int b> struct Add {
463  static constexpr int result = a + b;
464  };
465  int bar = Add<1, 2>::[[resu^lt]];
466  )cpp",
467  [](HoverInfo &HI) {
468  HI.Name = "result";
469  HI.Definition = "static constexpr int result = 1 + 2";
470  HI.Kind = index::SymbolKind::StaticProperty;
471  HI.Type = "const int";
472  HI.NamespaceScope = "";
473  HI.LocalScope = "Add<1, 2>::";
474  HI.Value = "3";
475  }},
476  {R"cpp(
477  constexpr int answer() { return 40 + 2; }
478  int x = [[ans^wer]]();
479  )cpp",
480  [](HoverInfo &HI) {
481  HI.Name = "answer";
482  HI.Definition = "constexpr int answer()";
483  HI.Kind = index::SymbolKind::Function;
484  HI.Type = "int ()";
485  HI.ReturnType = "int";
486  HI.Parameters.emplace();
487  HI.NamespaceScope = "";
488  HI.Value = "42";
489  }},
490  {R"cpp(
491  const char *[[ba^r]] = "1234";
492  )cpp",
493  [](HoverInfo &HI) {
494  HI.Name = "bar";
495  HI.Definition = "const char *bar = \"1234\"";
496  HI.Kind = index::SymbolKind::Variable;
497  HI.Type = "const char *";
498  HI.NamespaceScope = "";
499  HI.Value = "&\"1234\"[0]";
500  }},
501  {R"cpp(// Should not crash
502  template <typename T>
503  struct Tmpl {
504  Tmpl(int name);
505  };
506 
507  template <typename A>
508  void boom(int name) {
509  new Tmpl<A>([[na^me]]);
510  })cpp",
511  [](HoverInfo &HI) {
512  HI.Name = "name";
513  HI.Definition = "int name";
514  HI.Kind = index::SymbolKind::Parameter;
515  HI.Type = "int";
516  HI.NamespaceScope = "";
517  HI.LocalScope = "boom::";
518  }},
519  {
520  R"cpp(// Should not print inline or anon namespaces.
521  namespace ns {
522  inline namespace in_ns {
523  namespace a {
524  namespace {
525  namespace b {
526  inline namespace in_ns2 {
527  class Foo {};
528  } // in_ns2
529  } // b
530  } // anon
531  } // a
532  } // in_ns
533  } // ns
534  void foo() {
535  ns::a::b::[[F^oo]] x;
536  (void)x;
537  }
538  )cpp",
539  [](HoverInfo &HI) {
540  HI.Name = "Foo";
541  HI.Kind = index::SymbolKind::Class;
542  HI.NamespaceScope = "ns::a::b::";
543  HI.Definition = "class Foo {}";
544  }},
545  {
546  R"cpp(
547  template <typename T> class Foo {};
548  class X;
549  void foo() {
550  [[^auto]] x = Foo<X>();
551  }
552  )cpp",
553  [](HoverInfo &HI) {
554  HI.Name = "Foo<X>";
555  HI.Kind = index::SymbolKind::Class;
556  }},
557  {// Falls back to primary template, when the type is not instantiated.
558  R"cpp(
559  // comment from primary
560  template <typename T> class Foo {};
561  // comment from specialization
562  template <typename T> class Foo<T*> {};
563  void foo() {
564  [[Fo^o]]<int*> *x = nullptr;
565  }
566  )cpp",
567  [](HoverInfo &HI) {
568  HI.Name = "Foo<int *>";
569  HI.Kind = index::SymbolKind::Class;
570  HI.NamespaceScope = "";
571  HI.Definition = "template <> class Foo<int *>";
572  // FIXME: Maybe force instantiation to make use of real template
573  // pattern.
574  HI.Documentation = "comment from primary";
575  }},
576  };
577  for (const auto &Case : Cases) {
578  SCOPED_TRACE(Case.Code);
579 
580  Annotations T(Case.Code);
581  TestTU TU = TestTU::withCode(T.code());
582  TU.ExtraArgs.push_back("-std=c++17");
583  // FIXME: This is no longer necessary, as the default behavior is no delayed
584  // parsing in the triplet below.
585  TU.ExtraArgs.push_back("-fno-delayed-template-parsing");
586  // Types might be different depending on the target triplet, we chose a
587  // fixed one to make sure tests passes on different platform.
588  TU.ExtraArgs.push_back("--target=x86_64-pc-linux-gnu");
589  auto AST = TU.build();
590  ASSERT_TRUE(AST.getDiagnostics().empty());
591 
592  auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);
593  ASSERT_TRUE(H);
594  HoverInfo Expected;
595  Expected.SymRange = T.range();
596  Case.ExpectedBuilder(Expected);
597 
598  EXPECT_EQ(H->NamespaceScope, Expected.NamespaceScope);
599  EXPECT_EQ(H->LocalScope, Expected.LocalScope);
600  EXPECT_EQ(H->Name, Expected.Name);
601  EXPECT_EQ(H->Kind, Expected.Kind);
602  EXPECT_EQ(H->Documentation, Expected.Documentation);
603  EXPECT_EQ(H->Definition, Expected.Definition);
604  EXPECT_EQ(H->Type, Expected.Type);
605  EXPECT_EQ(H->ReturnType, Expected.ReturnType);
606  EXPECT_EQ(H->Parameters, Expected.Parameters);
607  EXPECT_EQ(H->TemplateParameters, Expected.TemplateParameters);
608  EXPECT_EQ(H->SymRange, Expected.SymRange);
609  EXPECT_EQ(H->Value, Expected.Value);
610  }
611 }
612 
613 TEST(Hover, NoHover) {
614  llvm::StringRef Tests[] = {
615  "^int main() {}",
616  "void foo() {^}",
617  R"cpp(// structured binding. Not supported yet
618  struct Bar {};
619  void foo() {
620  Bar a[2];
621  ^auto [x,y] = a;
622  }
623  )cpp",
624  R"cpp(// Template auto parameter. Nothing (Not useful).
625  template<^auto T>
626  void func() {
627  }
628  void foo() {
629  func<1>();
630  }
631  )cpp",
632  R"cpp(// non-named decls don't get hover. Don't crash!
633  ^static_assert(1, "");
634  )cpp",
635  R"cpp(// non-evaluatable expr
636  template <typename T> void foo() {
637  (void)[[size^of]](T);
638  })cpp",
639  // literals
640  "auto x = t^rue;",
641  "auto x = '^A';",
642  "auto x = ^(int){42};",
643  "auto x = ^42.;",
644  "auto x = ^42.0i;",
645  "auto x = ^42;",
646  "auto x = ^nullptr;",
647  "auto x = ^\"asdf\";",
648  };
649 
650  for (const auto &Test : Tests) {
651  SCOPED_TRACE(Test);
652 
653  Annotations T(Test);
654  TestTU TU = TestTU::withCode(T.code());
655  TU.ExtraArgs.push_back("-std=c++17");
656  auto AST = TU.build();
657  ASSERT_TRUE(AST.getDiagnostics().empty());
658 
659  auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);
660  ASSERT_FALSE(H);
661  }
662 }
663 
664 TEST(Hover, All) {
665  struct {
666  const char *const Code;
667  const std::function<void(HoverInfo &)> ExpectedBuilder;
668  } Cases[] = {
669  {
670  R"cpp(// Local variable
671  int main() {
672  int bonjour;
673  ^[[bonjour]] = 2;
674  int test1 = bonjour;
675  }
676  )cpp",
677  [](HoverInfo &HI) {
678  HI.Name = "bonjour";
679  HI.Kind = index::SymbolKind::Variable;
680  HI.NamespaceScope = "";
681  HI.LocalScope = "main::";
682  HI.Type = "int";
683  HI.Definition = "int bonjour";
684  }},
685  {
686  R"cpp(// Local variable in method
687  struct s {
688  void method() {
689  int bonjour;
690  ^[[bonjour]] = 2;
691  }
692  };
693  )cpp",
694  [](HoverInfo &HI) {
695  HI.Name = "bonjour";
696  HI.Kind = index::SymbolKind::Variable;
697  HI.NamespaceScope = "";
698  HI.LocalScope = "s::method::";
699  HI.Type = "int";
700  HI.Definition = "int bonjour";
701  }},
702  {
703  R"cpp(// Struct
704  namespace ns1 {
705  struct MyClass {};
706  } // namespace ns1
707  int main() {
708  ns1::[[My^Class]]* Params;
709  }
710  )cpp",
711  [](HoverInfo &HI) {
712  HI.Name = "MyClass";
713  HI.Kind = index::SymbolKind::Struct;
714  HI.NamespaceScope = "ns1::";
715  HI.Definition = "struct MyClass {}";
716  }},
717  {
718  R"cpp(// Class
719  namespace ns1 {
720  class MyClass {};
721  } // namespace ns1
722  int main() {
723  ns1::[[My^Class]]* Params;
724  }
725  )cpp",
726  [](HoverInfo &HI) {
727  HI.Name = "MyClass";
728  HI.Kind = index::SymbolKind::Class;
729  HI.NamespaceScope = "ns1::";
730  HI.Definition = "class MyClass {}";
731  }},
732  {
733  R"cpp(// Union
734  namespace ns1 {
735  union MyUnion { int x; int y; };
736  } // namespace ns1
737  int main() {
738  ns1::[[My^Union]] Params;
739  }
740  )cpp",
741  [](HoverInfo &HI) {
742  HI.Name = "MyUnion";
743  HI.Kind = index::SymbolKind::Union;
744  HI.NamespaceScope = "ns1::";
745  HI.Definition = "union MyUnion {}";
746  }},
747  {
748  R"cpp(// Function definition via pointer
749  void foo(int) {}
750  int main() {
751  auto *X = &^[[foo]];
752  }
753  )cpp",
754  [](HoverInfo &HI) {
755  HI.Name = "foo";
756  HI.Kind = index::SymbolKind::Function;
757  HI.NamespaceScope = "";
758  HI.Type = "void (int)";
759  HI.Definition = "void foo(int)";
760  HI.Documentation = "Function definition via pointer";
761  HI.ReturnType = "void";
762  HI.Parameters = {
763  {std::string("int"), llvm::None, llvm::None},
764  };
765  }},
766  {
767  R"cpp(// Function declaration via call
768  int foo(int);
769  int main() {
770  return ^[[foo]](42);
771  }
772  )cpp",
773  [](HoverInfo &HI) {
774  HI.Name = "foo";
775  HI.Kind = index::SymbolKind::Function;
776  HI.NamespaceScope = "";
777  HI.Type = "int (int)";
778  HI.Definition = "int foo(int)";
779  HI.Documentation = "Function declaration via call";
780  HI.ReturnType = "int";
781  HI.Parameters = {
782  {std::string("int"), llvm::None, llvm::None},
783  };
784  }},
785  {
786  R"cpp(// Field
787  struct Foo { int x; };
788  int main() {
789  Foo bar;
790  (void)bar.^[[x]];
791  }
792  )cpp",
793  [](HoverInfo &HI) {
794  HI.Name = "x";
795  HI.Kind = index::SymbolKind::Field;
796  HI.NamespaceScope = "";
797  HI.LocalScope = "Foo::";
798  HI.Type = "int";
799  HI.Definition = "int x";
800  }},
801  {
802  R"cpp(// Field with initialization
803  struct Foo { int x = 5; };
804  int main() {
805  Foo bar;
806  (void)bar.^[[x]];
807  }
808  )cpp",
809  [](HoverInfo &HI) {
810  HI.Name = "x";
811  HI.Kind = index::SymbolKind::Field;
812  HI.NamespaceScope = "";
813  HI.LocalScope = "Foo::";
814  HI.Type = "int";
815  HI.Definition = "int x = 5";
816  }},
817  {
818  R"cpp(// Static field
819  struct Foo { static int x; };
820  int main() {
821  (void)Foo::^[[x]];
822  }
823  )cpp",
824  [](HoverInfo &HI) {
825  HI.Name = "x";
826  HI.Kind = index::SymbolKind::StaticProperty;
827  HI.NamespaceScope = "";
828  HI.LocalScope = "Foo::";
829  HI.Type = "int";
830  HI.Definition = "static int x";
831  }},
832  {
833  R"cpp(// Field, member initializer
834  struct Foo {
835  int x;
836  Foo() : ^[[x]](0) {}
837  };
838  )cpp",
839  [](HoverInfo &HI) {
840  HI.Name = "x";
841  HI.Kind = index::SymbolKind::Field;
842  HI.NamespaceScope = "";
843  HI.LocalScope = "Foo::";
844  HI.Type = "int";
845  HI.Definition = "int x";
846  }},
847  {
848  R"cpp(// Field, GNU old-style field designator
849  struct Foo { int x; };
850  int main() {
851  Foo bar = { ^[[x]] : 1 };
852  }
853  )cpp",
854  [](HoverInfo &HI) {
855  HI.Name = "x";
856  HI.Kind = index::SymbolKind::Field;
857  HI.NamespaceScope = "";
858  HI.LocalScope = "Foo::";
859  HI.Type = "int";
860  HI.Definition = "int x";
861  HI.Value = "{1}";
862  }},
863  {
864  R"cpp(// Field, field designator
865  struct Foo { int x; };
866  int main() {
867  Foo bar = { .^[[x]] = 2 };
868  }
869  )cpp",
870  [](HoverInfo &HI) {
871  HI.Name = "x";
872  HI.Kind = index::SymbolKind::Field;
873  HI.NamespaceScope = "";
874  HI.LocalScope = "Foo::";
875  HI.Type = "int";
876  HI.Definition = "int x";
877  HI.Value = "{2}";
878  }},
879  {
880  R"cpp(// Method call
881  struct Foo { int x(); };
882  int main() {
883  Foo bar;
884  bar.^[[x]]();
885  }
886  )cpp",
887  [](HoverInfo &HI) {
888  HI.Name = "x";
889  HI.Kind = index::SymbolKind::InstanceMethod;
890  HI.NamespaceScope = "";
891  HI.LocalScope = "Foo::";
892  HI.Type = "int ()";
893  HI.Definition = "int x()";
894  HI.ReturnType = "int";
895  HI.Parameters = std::vector<HoverInfo::Param>{};
896  }},
897  {
898  R"cpp(// Static method call
899  struct Foo { static int x(); };
900  int main() {
901  Foo::^[[x]]();
902  }
903  )cpp",
904  [](HoverInfo &HI) {
905  HI.Name = "x";
906  HI.Kind = index::SymbolKind::StaticMethod;
907  HI.NamespaceScope = "";
908  HI.LocalScope = "Foo::";
909  HI.Type = "int ()";
910  HI.Definition = "static int x()";
911  HI.ReturnType = "int";
912  HI.Parameters = std::vector<HoverInfo::Param>{};
913  }},
914  {
915  R"cpp(// Typedef
916  typedef int Foo;
917  int main() {
918  ^[[Foo]] bar;
919  }
920  )cpp",
921  [](HoverInfo &HI) {
922  HI.Name = "Foo";
923  HI.Kind = index::SymbolKind::TypeAlias;
924  HI.NamespaceScope = "";
925  HI.Definition = "typedef int Foo";
926  HI.Documentation = "Typedef";
927  // FIXME: Maybe put underlying type into HI.Type for aliases?
928  }},
929  {
930  R"cpp(// Typedef with embedded definition
931  typedef struct Bar {} Foo;
932  int main() {
933  ^[[Foo]] bar;
934  }
935  )cpp",
936  [](HoverInfo &HI) {
937  HI.Name = "Foo";
938  HI.Kind = index::SymbolKind::TypeAlias;
939  HI.NamespaceScope = "";
940  HI.Definition = "typedef struct Bar Foo";
941  HI.Documentation = "Typedef with embedded definition";
942  }},
943  {
944  R"cpp(// Namespace
945  namespace ns {
946  struct Foo { static void bar(); };
947  } // namespace ns
948  int main() { ^[[ns]]::Foo::bar(); }
949  )cpp",
950  [](HoverInfo &HI) {
951  HI.Name = "ns";
952  HI.Kind = index::SymbolKind::Namespace;
953  HI.NamespaceScope = "";
954  HI.Definition = "namespace ns {}";
955  }},
956  {
957  R"cpp(// Anonymous namespace
958  namespace ns {
959  namespace {
960  int foo;
961  } // anonymous namespace
962  } // namespace ns
963  int main() { ns::[[f^oo]]++; }
964  )cpp",
965  [](HoverInfo &HI) {
966  HI.Name = "foo";
967  HI.Kind = index::SymbolKind::Variable;
968  HI.NamespaceScope = "ns::";
969  HI.Type = "int";
970  HI.Definition = "int foo";
971  }},
972  {
973  R"cpp(// Macro
974  #define MACRO 0
975  int main() { return ^[[MACRO]]; }
976  )cpp",
977  [](HoverInfo &HI) {
978  HI.Name = "MACRO";
979  HI.Kind = index::SymbolKind::Macro;
980  HI.Definition = "#define MACRO 0";
981  }},
982  {
983  R"cpp(// Macro
984  #define MACRO 0
985  #define MACRO2 ^[[MACRO]]
986  )cpp",
987  [](HoverInfo &HI) {
988  HI.Name = "MACRO";
989  HI.Kind = index::SymbolKind::Macro;
990  HI.Definition = "#define MACRO 0";
991  }},
992  {
993  R"cpp(// Macro
994  #define MACRO {\
995  return 0;\
996  }
997  int main() ^[[MACRO]]
998  )cpp",
999  [](HoverInfo &HI) {
1000  HI.Name = "MACRO";
1001  HI.Kind = index::SymbolKind::Macro;
1002  HI.Definition =
1003  R"cpp(#define MACRO \
1004  { return 0; })cpp";
1005  }},
1006  {
1007  R"cpp(// Forward class declaration
1008  class Foo;
1009  class Foo {};
1010  [[F^oo]]* foo();
1011  )cpp",
1012  [](HoverInfo &HI) {
1013  HI.Name = "Foo";
1014  HI.Kind = index::SymbolKind::Class;
1015  HI.NamespaceScope = "";
1016  HI.Definition = "class Foo {}";
1017  HI.Documentation = "Forward class declaration";
1018  }},
1019  {
1020  R"cpp(// Function declaration
1021  void foo();
1022  void g() { [[f^oo]](); }
1023  void foo() {}
1024  )cpp",
1025  [](HoverInfo &HI) {
1026  HI.Name = "foo";
1027  HI.Kind = index::SymbolKind::Function;
1028  HI.NamespaceScope = "";
1029  HI.Type = "void ()";
1030  HI.Definition = "void foo()";
1031  HI.Documentation = "Function declaration";
1032  HI.ReturnType = "void";
1033  HI.Parameters = std::vector<HoverInfo::Param>{};
1034  }},
1035  {
1036  R"cpp(// Enum declaration
1037  enum Hello {
1038  ONE, TWO, THREE,
1039  };
1040  void foo() {
1041  [[Hel^lo]] hello = ONE;
1042  }
1043  )cpp",
1044  [](HoverInfo &HI) {
1045  HI.Name = "Hello";
1046  HI.Kind = index::SymbolKind::Enum;
1047  HI.NamespaceScope = "";
1048  HI.Definition = "enum Hello {}";
1049  HI.Documentation = "Enum declaration";
1050  }},
1051  {
1052  R"cpp(// Enumerator
1053  enum Hello {
1054  ONE, TWO, THREE,
1055  };
1056  void foo() {
1057  Hello hello = [[O^NE]];
1058  }
1059  )cpp",
1060  [](HoverInfo &HI) {
1061  HI.Name = "ONE";
1062  HI.Kind = index::SymbolKind::EnumConstant;
1063  HI.NamespaceScope = "";
1064  HI.LocalScope = "Hello::";
1065  HI.Type = "enum Hello";
1066  HI.Definition = "ONE";
1067  HI.Value = "0";
1068  }},
1069  {
1070  R"cpp(// Enumerator in anonymous enum
1071  enum {
1072  ONE, TWO, THREE,
1073  };
1074  void foo() {
1075  int hello = [[O^NE]];
1076  }
1077  )cpp",
1078  [](HoverInfo &HI) {
1079  HI.Name = "ONE";
1080  HI.Kind = index::SymbolKind::EnumConstant;
1081  HI.NamespaceScope = "";
1082  // FIXME: This should be `(anon enum)::`
1083  HI.LocalScope = "";
1084  HI.Type = "enum (anonymous)";
1085  HI.Definition = "ONE";
1086  HI.Value = "0";
1087  }},
1088  {
1089  R"cpp(// Global variable
1090  static int hey = 10;
1091  void foo() {
1092  [[he^y]]++;
1093  }
1094  )cpp",
1095  [](HoverInfo &HI) {
1096  HI.Name = "hey";
1097  HI.Kind = index::SymbolKind::Variable;
1098  HI.NamespaceScope = "";
1099  HI.Type = "int";
1100  HI.Definition = "static int hey = 10";
1101  HI.Documentation = "Global variable";
1102  // FIXME: Value shouldn't be set in this case
1103  HI.Value = "10";
1104  }},
1105  {
1106  R"cpp(// Global variable in namespace
1107  namespace ns1 {
1108  static int hey = 10;
1109  }
1110  void foo() {
1111  ns1::[[he^y]]++;
1112  }
1113  )cpp",
1114  [](HoverInfo &HI) {
1115  HI.Name = "hey";
1116  HI.Kind = index::SymbolKind::Variable;
1117  HI.NamespaceScope = "ns1::";
1118  HI.Type = "int";
1119  HI.Definition = "static int hey = 10";
1120  HI.Value = "10";
1121  }},
1122  {
1123  R"cpp(// Field in anonymous struct
1124  static struct {
1125  int hello;
1126  } s;
1127  void foo() {
1128  s.[[he^llo]]++;
1129  }
1130  )cpp",
1131  [](HoverInfo &HI) {
1132  HI.Name = "hello";
1133  HI.Kind = index::SymbolKind::Field;
1134  HI.NamespaceScope = "";
1135  HI.LocalScope = "(anonymous struct)::";
1136  HI.Type = "int";
1137  HI.Definition = "int hello";
1138  }},
1139  {
1140  R"cpp(// Templated function
1141  template <typename T>
1142  T foo() {
1143  return 17;
1144  }
1145  void g() { auto x = [[f^oo]]<int>(); }
1146  )cpp",
1147  [](HoverInfo &HI) {
1148  HI.Name = "foo";
1149  HI.Kind = index::SymbolKind::Function;
1150  HI.NamespaceScope = "";
1151  HI.Type = "int ()";
1152  HI.Definition = "template <> int foo<int>()";
1153  HI.Documentation = "Templated function";
1154  HI.ReturnType = "int";
1155  HI.Parameters = std::vector<HoverInfo::Param>{};
1156  // FIXME: We should populate template parameters with arguments in
1157  // case of instantiations.
1158  }},
1159  {
1160  R"cpp(// Anonymous union
1161  struct outer {
1162  union {
1163  int abc, def;
1164  } v;
1165  };
1166  void g() { struct outer o; o.v.[[d^ef]]++; }
1167  )cpp",
1168  [](HoverInfo &HI) {
1169  HI.Name = "def";
1170  HI.Kind = index::SymbolKind::Field;
1171  HI.NamespaceScope = "";
1172  HI.LocalScope = "outer::(anonymous union)::";
1173  HI.Type = "int";
1174  HI.Definition = "int def";
1175  }},
1176  {
1177  R"cpp(// documentation from index
1178  int nextSymbolIsAForwardDeclFromIndexWithNoLocalDocs;
1179  void indexSymbol();
1180  void g() { [[ind^exSymbol]](); }
1181  )cpp",
1182  [](HoverInfo &HI) {
1183  HI.Name = "indexSymbol";
1184  HI.Kind = index::SymbolKind::Function;
1185  HI.NamespaceScope = "";
1186  HI.Type = "void ()";
1187  HI.Definition = "void indexSymbol()";
1188  HI.ReturnType = "void";
1189  HI.Parameters = std::vector<HoverInfo::Param>{};
1190  HI.Documentation = "comment from index";
1191  }},
1192  {
1193  R"cpp(// Simple initialization with auto
1194  void foo() {
1195  ^[[auto]] i = 1;
1196  }
1197  )cpp",
1198  [](HoverInfo &HI) {
1199  HI.Name = "int";
1200  // FIXME: Should be Builtin/Integral.
1201  HI.Kind = index::SymbolKind::Unknown;
1202  }},
1203  {
1204  R"cpp(// Simple initialization with const auto
1205  void foo() {
1206  const ^[[auto]] i = 1;
1207  }
1208  )cpp",
1209  [](HoverInfo &HI) { HI.Name = "int"; }},
1210  {
1211  R"cpp(// Simple initialization with const auto&
1212  void foo() {
1213  const ^[[auto]]& i = 1;
1214  }
1215  )cpp",
1216  [](HoverInfo &HI) { HI.Name = "int"; }},
1217  {
1218  R"cpp(// Simple initialization with auto&
1219  void foo() {
1220  int x;
1221  ^[[auto]]& i = x;
1222  }
1223  )cpp",
1224  [](HoverInfo &HI) { HI.Name = "int"; }},
1225  {
1226  R"cpp(// Simple initialization with auto*
1227  void foo() {
1228  int a = 1;
1229  ^[[auto]]* i = &a;
1230  }
1231  )cpp",
1232  [](HoverInfo &HI) { HI.Name = "int"; }},
1233  {
1234  R"cpp(// Auto with initializer list.
1235  namespace std
1236  {
1237  template<class _E>
1238  class initializer_list {};
1239  }
1240  void foo() {
1241  ^[[auto]] i = {1,2};
1242  }
1243  )cpp",
1244  [](HoverInfo &HI) {
1245  HI.Name = "initializer_list<int>";
1246  HI.Kind = index::SymbolKind::Class;
1247  }},
1248  {
1249  R"cpp(// User defined conversion to auto
1250  struct Bar {
1251  operator ^[[auto]]() const { return 10; }
1252  };
1253  )cpp",
1254  [](HoverInfo &HI) { HI.Name = "int"; }},
1255  {
1256  R"cpp(// Simple initialization with decltype(auto)
1257  void foo() {
1258  ^[[decltype]](auto) i = 1;
1259  }
1260  )cpp",
1261  [](HoverInfo &HI) { HI.Name = "int"; }},
1262  {
1263  R"cpp(// Simple initialization with const decltype(auto)
1264  void foo() {
1265  const int j = 0;
1266  ^[[decltype]](auto) i = j;
1267  }
1268  )cpp",
1269  [](HoverInfo &HI) { HI.Name = "const int"; }},
1270  {
1271  R"cpp(// Simple initialization with const& decltype(auto)
1272  void foo() {
1273  int k = 0;
1274  const int& j = k;
1275  ^[[decltype]](auto) i = j;
1276  }
1277  )cpp",
1278  [](HoverInfo &HI) { HI.Name = "const int &"; }},
1279  {
1280  R"cpp(// Simple initialization with & decltype(auto)
1281  void foo() {
1282  int k = 0;
1283  int& j = k;
1284  ^[[decltype]](auto) i = j;
1285  }
1286  )cpp",
1287  [](HoverInfo &HI) { HI.Name = "int &"; }},
1288  {
1289  R"cpp(// simple trailing return type
1290  ^[[auto]] main() -> int {
1291  return 0;
1292  }
1293  )cpp",
1294  [](HoverInfo &HI) { HI.Name = "int"; }},
1295  {
1296  R"cpp(// auto function return with trailing type
1297  struct Bar {};
1298  ^[[auto]] test() -> decltype(Bar()) {
1299  return Bar();
1300  }
1301  )cpp",
1302  [](HoverInfo &HI) {
1303  HI.Name = "Bar";
1304  HI.Kind = index::SymbolKind::Struct;
1305  HI.Documentation = "auto function return with trailing type";
1306  }},
1307  {
1308  R"cpp(// trailing return type
1309  struct Bar {};
1310  auto test() -> ^[[decltype]](Bar()) {
1311  return Bar();
1312  }
1313  )cpp",
1314  [](HoverInfo &HI) {
1315  HI.Name = "Bar";
1316  HI.Kind = index::SymbolKind::Struct;
1317  HI.Documentation = "trailing return type";
1318  }},
1319  {
1320  R"cpp(// auto in function return
1321  struct Bar {};
1322  ^[[auto]] test() {
1323  return Bar();
1324  }
1325  )cpp",
1326  [](HoverInfo &HI) {
1327  HI.Name = "Bar";
1328  HI.Kind = index::SymbolKind::Struct;
1329  HI.Documentation = "auto in function return";
1330  }},
1331  {
1332  R"cpp(// auto& in function return
1333  struct Bar {};
1334  ^[[auto]]& test() {
1335  static Bar x;
1336  return x;
1337  }
1338  )cpp",
1339  [](HoverInfo &HI) {
1340  HI.Name = "Bar";
1341  HI.Kind = index::SymbolKind::Struct;
1342  HI.Documentation = "auto& in function return";
1343  }},
1344  {
1345  R"cpp(// auto* in function return
1346  struct Bar {};
1347  ^[[auto]]* test() {
1348  Bar* bar;
1349  return bar;
1350  }
1351  )cpp",
1352  [](HoverInfo &HI) {
1353  HI.Name = "Bar";
1354  HI.Kind = index::SymbolKind::Struct;
1355  HI.Documentation = "auto* in function return";
1356  }},
1357  {
1358  R"cpp(// const auto& in function return
1359  struct Bar {};
1360  const ^[[auto]]& test() {
1361  static Bar x;
1362  return x;
1363  }
1364  )cpp",
1365  [](HoverInfo &HI) {
1366  HI.Name = "Bar";
1367  HI.Kind = index::SymbolKind::Struct;
1368  HI.Documentation = "const auto& in function return";
1369  }},
1370  {
1371  R"cpp(// decltype(auto) in function return
1372  struct Bar {};
1373  ^[[decltype]](auto) test() {
1374  return Bar();
1375  }
1376  )cpp",
1377  [](HoverInfo &HI) {
1378  HI.Name = "Bar";
1379  HI.Kind = index::SymbolKind::Struct;
1380  HI.Documentation = "decltype(auto) in function return";
1381  }},
1382  {
1383  R"cpp(// decltype(auto) reference in function return
1384  ^[[decltype]](auto) test() {
1385  static int a;
1386  return (a);
1387  }
1388  )cpp",
1389  [](HoverInfo &HI) { HI.Name = "int &"; }},
1390  {
1391  R"cpp(// decltype lvalue reference
1392  void foo() {
1393  int I = 0;
1394  ^[[decltype]](I) J = I;
1395  }
1396  )cpp",
1397  [](HoverInfo &HI) { HI.Name = "int"; }},
1398  {
1399  R"cpp(// decltype lvalue reference
1400  void foo() {
1401  int I= 0;
1402  int &K = I;
1403  ^[[decltype]](K) J = I;
1404  }
1405  )cpp",
1406  [](HoverInfo &HI) { HI.Name = "int &"; }},
1407  {
1408  R"cpp(// decltype lvalue reference parenthesis
1409  void foo() {
1410  int I = 0;
1411  ^[[decltype]]((I)) J = I;
1412  }
1413  )cpp",
1414  [](HoverInfo &HI) { HI.Name = "int &"; }},
1415  {
1416  R"cpp(// decltype rvalue reference
1417  void foo() {
1418  int I = 0;
1419  ^[[decltype]](static_cast<int&&>(I)) J = static_cast<int&&>(I);
1420  }
1421  )cpp",
1422  [](HoverInfo &HI) { HI.Name = "int &&"; }},
1423  {
1424  R"cpp(// decltype rvalue reference function call
1425  int && bar();
1426  void foo() {
1427  int I = 0;
1428  ^[[decltype]](bar()) J = bar();
1429  }
1430  )cpp",
1431  [](HoverInfo &HI) { HI.Name = "int &&"; }},
1432  {
1433  R"cpp(// decltype of function with trailing return type.
1434  struct Bar {};
1435  auto test() -> decltype(Bar()) {
1436  return Bar();
1437  }
1438  void foo() {
1439  ^[[decltype]](test()) i = test();
1440  }
1441  )cpp",
1442  [](HoverInfo &HI) {
1443  HI.Name = "Bar";
1444  HI.Kind = index::SymbolKind::Struct;
1445  HI.Documentation =
1446  "decltype of function with trailing return type.";
1447  }},
1448  {
1449  R"cpp(// decltype of var with decltype.
1450  void foo() {
1451  int I = 0;
1452  decltype(I) J = I;
1453  ^[[decltype]](J) K = J;
1454  }
1455  )cpp",
1456  [](HoverInfo &HI) { HI.Name = "int"; }},
1457  {
1458  R"cpp(// More complicated structured types.
1459  int bar();
1460  ^[[auto]] (*foo)() = bar;
1461  )cpp",
1462  [](HoverInfo &HI) { HI.Name = "int"; }},
1463  {
1464  R"cpp(// Should not crash when evaluating the initializer.
1465  struct Test {};
1466  void test() { Test && [[te^st]] = {}; }
1467  )cpp",
1468  [](HoverInfo &HI) {
1469  HI.Name = "test";
1470  HI.Kind = index::SymbolKind::Variable;
1471  HI.NamespaceScope = "";
1472  HI.LocalScope = "test::";
1473  HI.Type = "struct Test &&";
1474  HI.Definition = "Test &&test = {}";
1475  HI.Value = "{}";
1476  }},
1477  {
1478  R"cpp(// auto on alias
1479  typedef int int_type;
1480  ^[[auto]] x = int_type();
1481  )cpp",
1482  [](HoverInfo &HI) { HI.Name = "int"; }},
1483  {
1484  R"cpp(// auto on alias
1485  struct cls {};
1486  typedef cls cls_type;
1487  ^[[auto]] y = cls_type();
1488  )cpp",
1489  [](HoverInfo &HI) {
1490  HI.Name = "cls";
1491  HI.Kind = index::SymbolKind::Struct;
1492  HI.Documentation = "auto on alias";
1493  }},
1494  {
1495  R"cpp(// auto on alias
1496  template <class>
1497  struct templ {};
1498  ^[[auto]] z = templ<int>();
1499  )cpp",
1500  [](HoverInfo &HI) {
1501  HI.Name = "templ<int>";
1502  HI.Kind = index::SymbolKind::Struct;
1503  HI.Documentation = "auto on alias";
1504  }},
1505  {
1506  R"cpp(// should not crash.
1507  template <class T> struct cls {
1508  int method();
1509  };
1510 
1511  auto test = cls<int>().[[m^ethod]]();
1512  )cpp",
1513  [](HoverInfo &HI) {
1514  HI.Definition = "int method()";
1515  HI.Kind = index::SymbolKind::InstanceMethod;
1516  HI.NamespaceScope = "";
1517  HI.LocalScope = "cls<int>::";
1518  HI.Name = "method";
1519  HI.Parameters.emplace();
1520  HI.ReturnType = "int";
1521  HI.Type = "int ()";
1522  }},
1523  {
1524  R"cpp(// type of nested templates.
1525  template <class T> struct cls {};
1526  cls<cls<cls<int>>> [[fo^o]];
1527  )cpp",
1528  [](HoverInfo &HI) {
1529  HI.Definition = "cls<cls<cls<int>>> foo";
1530  HI.Kind = index::SymbolKind::Variable;
1531  HI.NamespaceScope = "";
1532  HI.Name = "foo";
1533  HI.Type = "cls<cls<cls<int> > >";
1534  HI.Value = "{}";
1535  }},
1536  {
1537  R"cpp(// type of nested templates.
1538  template <class T> struct cls {};
1539  [[cl^s]]<cls<cls<int>>> foo;
1540  )cpp",
1541  [](HoverInfo &HI) {
1542  HI.Definition = "template <> struct cls<cls<cls<int>>> {}";
1543  HI.Kind = index::SymbolKind::Struct;
1544  HI.NamespaceScope = "";
1545  HI.Name = "cls<cls<cls<int> > >";
1546  HI.Documentation = "type of nested templates.";
1547  }},
1548  {
1549  R"cpp(// type with decltype
1550  int a;
1551  decltype(a) [[b^]] = a;)cpp",
1552  [](HoverInfo &HI) {
1553  HI.Definition = "decltype(a) b = a";
1554  HI.Kind = index::SymbolKind::Variable;
1555  HI.NamespaceScope = "";
1556  HI.Name = "b";
1557  HI.Type = "int";
1558  }},
1559  {
1560  R"cpp(// type with decltype
1561  int a;
1562  decltype(a) c;
1563  decltype(c) [[b^]] = a;)cpp",
1564  [](HoverInfo &HI) {
1565  HI.Definition = "decltype(c) b = a";
1566  HI.Kind = index::SymbolKind::Variable;
1567  HI.NamespaceScope = "";
1568  HI.Name = "b";
1569  HI.Type = "int";
1570  }},
1571  {
1572  R"cpp(// type with decltype
1573  int a;
1574  const decltype(a) [[b^]] = a;)cpp",
1575  [](HoverInfo &HI) {
1576  HI.Definition = "const decltype(a) b = a";
1577  HI.Kind = index::SymbolKind::Variable;
1578  HI.NamespaceScope = "";
1579  HI.Name = "b";
1580  HI.Type = "int";
1581  }},
1582  {
1583  R"cpp(// type with decltype
1584  int a;
1585  auto [[f^oo]](decltype(a) x) -> decltype(a) { return 0; })cpp",
1586  [](HoverInfo &HI) {
1587  HI.Definition = "auto foo(decltype(a) x) -> decltype(a)";
1588  HI.Kind = index::SymbolKind::Function;
1589  HI.NamespaceScope = "";
1590  HI.Name = "foo";
1591  // FIXME: Handle composite types with decltype with a printing
1592  // policy.
1593  HI.Type = "auto (decltype(a)) -> decltype(a)";
1594  HI.ReturnType = "int";
1595  HI.Parameters = {
1596  {std::string("int"), std::string("x"), llvm::None}};
1597  }},
1598  {
1599  R"cpp(// sizeof expr
1600  void foo() {
1601  (void)[[size^of]](char);
1602  })cpp",
1603  [](HoverInfo &HI) {
1604  HI.Name = "expression";
1605  HI.Type = "unsigned long";
1606  HI.Value = "1";
1607  }},
1608  {
1609  R"cpp(// alignof expr
1610  void foo() {
1611  (void)[[align^of]](char);
1612  })cpp",
1613  [](HoverInfo &HI) {
1614  HI.Name = "expression";
1615  HI.Type = "unsigned long";
1616  HI.Value = "1";
1617  }},
1618  };
1619 
1620  // Create a tiny index, so tests above can verify documentation is fetched.
1621  Symbol IndexSym = func("indexSymbol");
1622  IndexSym.Documentation = "comment from index";
1624  Symbols.insert(IndexSym);
1625  auto Index =
1626  MemIndex::build(std::move(Symbols).build(), RefSlab(), RelationSlab());
1627 
1628  for (const auto &Case : Cases) {
1629  SCOPED_TRACE(Case.Code);
1630 
1631  Annotations T(Case.Code);
1632  TestTU TU = TestTU::withCode(T.code());
1633  TU.ExtraArgs.push_back("-std=c++17");
1634  TU.ExtraArgs.push_back("-Wno-gnu-designator");
1635  // Types might be different depending on the target triplet, we chose a
1636  // fixed one to make sure tests passes on different platform.
1637  TU.ExtraArgs.push_back("--target=x86_64-pc-linux-gnu");
1638  auto AST = TU.build();
1639  for (const auto &D : AST.getDiagnostics())
1640  ADD_FAILURE() << D;
1641  ASSERT_TRUE(AST.getDiagnostics().empty());
1642 
1643  auto H = getHover(AST, T.point(), format::getLLVMStyle(), Index.get());
1644  ASSERT_TRUE(H);
1645  HoverInfo Expected;
1646  Expected.SymRange = T.range();
1647  Case.ExpectedBuilder(Expected);
1648 
1649  SCOPED_TRACE(H->present().asPlainText());
1650  EXPECT_EQ(H->NamespaceScope, Expected.NamespaceScope);
1651  EXPECT_EQ(H->LocalScope, Expected.LocalScope);
1652  EXPECT_EQ(H->Name, Expected.Name);
1653  EXPECT_EQ(H->Kind, Expected.Kind);
1654  EXPECT_EQ(H->Documentation, Expected.Documentation);
1655  EXPECT_EQ(H->Definition, Expected.Definition);
1656  EXPECT_EQ(H->Type, Expected.Type);
1657  EXPECT_EQ(H->ReturnType, Expected.ReturnType);
1658  EXPECT_EQ(H->Parameters, Expected.Parameters);
1659  EXPECT_EQ(H->TemplateParameters, Expected.TemplateParameters);
1660  EXPECT_EQ(H->SymRange, Expected.SymRange);
1661  EXPECT_EQ(H->Value, Expected.Value);
1662  }
1663 }
1664 
1665 TEST(Hover, DocsFromIndex) {
1666  Annotations T(R"cpp(
1667  template <typename T> class X {};
1668  void foo() {
1669  au^to t = X<int>();
1670  X^<int> w;
1671  (void)w;
1672  })cpp");
1673 
1674  TestTU TU = TestTU::withCode(T.code());
1675  auto AST = TU.build();
1676  for (const auto &D : AST.getDiagnostics())
1677  ADD_FAILURE() << D;
1678  ASSERT_TRUE(AST.getDiagnostics().empty());
1679 
1680  Symbol IndexSym;
1681  IndexSym.ID = *getSymbolID(&findDecl(AST, "X"));
1682  IndexSym.Documentation = "comment from index";
1684  Symbols.insert(IndexSym);
1685  auto Index =
1686  MemIndex::build(std::move(Symbols).build(), RefSlab(), RelationSlab());
1687 
1688  for (const auto &P : T.points()) {
1689  auto H = getHover(AST, P, format::getLLVMStyle(), Index.get());
1690  ASSERT_TRUE(H);
1691  EXPECT_EQ(H->Documentation, IndexSym.Documentation);
1692  }
1693 }
1694 
1695 TEST(Hover, DocsFromAST) {
1696  Annotations T(R"cpp(
1697  // doc
1698  template <typename T> class X {};
1699  // doc
1700  template <typename T> void bar() {}
1701  // doc
1702  template <typename T> T baz;
1703  void foo() {
1704  au^to t = X<int>();
1705  X^<int>();
1706  b^ar<int>();
1707  au^to T = ba^z<X<int>>;
1708  ba^z<int> = 0;
1709  })cpp");
1710 
1711  TestTU TU = TestTU::withCode(T.code());
1712  auto AST = TU.build();
1713  for (const auto &D : AST.getDiagnostics())
1714  ADD_FAILURE() << D;
1715  ASSERT_TRUE(AST.getDiagnostics().empty());
1716 
1717  for (const auto &P : T.points()) {
1718  auto H = getHover(AST, P, format::getLLVMStyle(), nullptr);
1719  ASSERT_TRUE(H);
1720  EXPECT_EQ(H->Documentation, "doc");
1721  }
1722 }
1723 
1724 TEST(Hover, DocsFromMostSpecial) {
1725  Annotations T(R"cpp(
1726  // doc1
1727  template <typename T> class $doc1^X {};
1728  // doc2
1729  template <> class $doc2^X<int> {};
1730  // doc3
1731  template <typename T> class $doc3^X<T*> {};
1732  void foo() {
1733  X$doc1^<char>();
1734  X$doc2^<int>();
1735  X$doc3^<int*>();
1736  })cpp");
1737 
1738  TestTU TU = TestTU::withCode(T.code());
1739  auto AST = TU.build();
1740  for (const auto &D : AST.getDiagnostics())
1741  ADD_FAILURE() << D;
1742  ASSERT_TRUE(AST.getDiagnostics().empty());
1743 
1744  for (auto Comment : {"doc1", "doc2", "doc3"}) {
1745  for (const auto &P : T.points(Comment)) {
1746  auto H = getHover(AST, P, format::getLLVMStyle(), nullptr);
1747  ASSERT_TRUE(H);
1748  EXPECT_EQ(H->Documentation, Comment);
1749  }
1750  }
1751 }
1752 
1753 TEST(Hover, Present) {
1754  struct {
1755  const std::function<void(HoverInfo &)> Builder;
1756  llvm::StringRef ExpectedRender;
1757  } Cases[] = {
1758  {
1759  [](HoverInfo &HI) {
1760  HI.Kind = index::SymbolKind::Unknown;
1761  HI.Name = "X";
1762  },
1763  R"(X)",
1764  },
1765  {
1766  [](HoverInfo &HI) {
1767  HI.Kind = index::SymbolKind::NamespaceAlias;
1768  HI.Name = "foo";
1769  },
1770  R"(namespace-alias foo)",
1771  },
1772  {
1773  [](HoverInfo &HI) {
1774  HI.Kind = index::SymbolKind::Class;
1775  HI.TemplateParameters = {
1776  {std::string("typename"), std::string("T"), llvm::None},
1777  {std::string("typename"), std::string("C"),
1778  std::string("bool")},
1779  };
1780  HI.Documentation = "documentation";
1781  HI.Definition =
1782  "template <typename T, typename C = bool> class Foo {}";
1783  HI.Name = "foo";
1784  HI.NamespaceScope.emplace();
1785  },
1786  R"(class foo
1787 
1788 documentation
1789 
1790 template <typename T, typename C = bool> class Foo {})",
1791  },
1792  {
1793  [](HoverInfo &HI) {
1794  HI.Kind = index::SymbolKind::Function;
1795  HI.Name = "foo";
1796  HI.Type = "type";
1797  HI.ReturnType = "ret_type";
1798  HI.Parameters.emplace();
1799  HoverInfo::Param P;
1800  HI.Parameters->push_back(P);
1801  P.Type = "type";
1802  HI.Parameters->push_back(P);
1803  P.Name = "foo";
1804  HI.Parameters->push_back(P);
1805  P.Default = "default";
1806  HI.Parameters->push_back(P);
1807  HI.NamespaceScope = "ns::";
1808  HI.Definition = "ret_type foo(params) {}";
1809  },
1810  R"(function foo
1811 
1812 → ret_type
1813 Parameters:
1814 -
1815 - type
1816 - type foo
1817 - type foo = default
1818 
1819 // In namespace ns
1820 ret_type foo(params) {})",
1821  },
1822  {
1823  [](HoverInfo &HI) {
1824  HI.Kind = index::SymbolKind::Variable;
1825  HI.LocalScope = "test::bar::";
1826  HI.Value = "value";
1827  HI.Name = "foo";
1828  HI.Type = "type";
1829  HI.Definition = "def";
1830  },
1831  R"(variable foo
1832 
1833 Type: type
1834 Value = value
1835 
1836 // In test::bar
1837 def)",
1838  },
1839  };
1840 
1841  for (const auto &C : Cases) {
1842  HoverInfo HI;
1843  C.Builder(HI);
1844  EXPECT_EQ(HI.present().asPlainText(), C.ExpectedRender);
1845  }
1846 }
1847 
1848 // This is a separate test as headings don't create any differences in plaintext
1849 // mode.
1850 TEST(Hover, PresentHeadings) {
1851  HoverInfo HI;
1852  HI.Kind = index::SymbolKind::Variable;
1853  HI.Name = "foo";
1854 
1855  EXPECT_EQ(HI.present().asMarkdown(), "### variable `foo`");
1856 }
1857 
1858 // This is a separate test as rulers behave differently in markdown vs
1859 // plaintext.
1860 TEST(Hover, PresentRulers) {
1861  HoverInfo HI;
1862  HI.Kind = index::SymbolKind::Variable;
1863  HI.Name = "foo";
1864  HI.Value = "val";
1865  HI.Definition = "def";
1866 
1867  llvm::StringRef ExpectedMarkdown = R"md(### variable `foo`
1868 
1869 ---
1870 Value \= `val`
1871 
1872 ---
1873 ```cpp
1874 def
1875 ```)md";
1876  EXPECT_EQ(HI.present().asMarkdown(), ExpectedMarkdown);
1877 
1878  llvm::StringRef ExpectedPlaintext = R"pt(variable foo
1879 
1880 Value = val
1881 
1882 def)pt";
1883  EXPECT_EQ(HI.present().asPlainText(), ExpectedPlaintext);
1884 }
1885 } // namespace
1886 } // namespace clangd
1887 } // namespace clang
ParsedAST build() const
Definition: TestTU.cpp:22
std::string Code
llvm::Optional< SymbolID > getSymbolID(const Decl *D)
Gets the symbol ID for a declaration, if possible.
Definition: AST.cpp:286
Documents should not be synced at all.
std::vector< const char * > ExtraArgs
Definition: TestTU.h:57
static std::unique_ptr< SymbolIndex > build(SymbolSlab Symbols, RefSlab Refs, RelationSlab Relations)
Builds an index from slabs. The index takes ownership of the data.
Definition: MemIndex.cpp:19
llvm::Optional< HoverInfo > getHover(ParsedAST &AST, Position Pos, format::FormatStyle Style, const SymbolIndex *Index)
Get the hover information when hovering at Pos.
Definition: Hover.cpp:483
TEST(BackgroundQueueTest, Priority)
SymbolSlab Symbols
static TestTU withCode(llvm::StringRef Code)
Definition: TestTU.h:33
CodeCompletionBuilder Builder
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
std::vector< const char * > Expected
static llvm::Optional< ParsedAST > build(std::unique_ptr< clang::CompilerInvocation > CI, llvm::ArrayRef< Diag > CompilerInvocationDiags, std::shared_ptr< const PreambleData > Preamble, std::unique_ptr< llvm::MemoryBuffer > Buffer, llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > VFS, const SymbolIndex *Index, const ParseOptions &Opts)
Attempts to run Clang and store parsed AST.
Definition: ParsedAST.cpp:218
const std::vector< Diag > & getDiagnostics() const
Definition: ParsedAST.cpp:446
const NamedDecl & findDecl(ParsedAST &AST, llvm::StringRef QName)
Definition: TestTU.cpp:118
const SymbolIndex * Index
Definition: Dexp.cpp:84
Symbol func(llvm::StringRef Name)
Definition: TestIndex.cpp:60