clang-tools  11.0.0
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/Basic/Specifiers.h"
16 #include "clang/Index/IndexSymbol.h"
17 #include "llvm/ADT/None.h"
18 #include "llvm/ADT/StringRef.h"
19 
20 #include "gmock/gmock.h"
21 #include "gtest/gtest.h"
22 #include <string>
23 #include <vector>
24 
25 namespace clang {
26 namespace clangd {
27 namespace {
28 
29 using PassMode = HoverInfo::PassType::PassMode;
30 
31 TEST(Hover, Structured) {
32  struct {
33  const char *const Code;
34  const std::function<void(HoverInfo &)> ExpectedBuilder;
35  } Cases[] = {
36  // Global scope.
37  {R"cpp(
38  // Best foo ever.
39  void [[fo^o]]() {}
40  )cpp",
41  [](HoverInfo &HI) {
42  HI.NamespaceScope = "";
43  HI.Name = "foo";
44  HI.Kind = index::SymbolKind::Function;
45  HI.Documentation = "Best foo ever.";
46  HI.Definition = "void foo()";
47  HI.ReturnType = "void";
48  HI.Type = "void ()";
49  HI.Parameters.emplace();
50  }},
51  // Inside namespace
52  {R"cpp(
53  namespace ns1 { namespace ns2 {
54  /// Best foo ever.
55  void [[fo^o]]() {}
56  }}
57  )cpp",
58  [](HoverInfo &HI) {
59  HI.NamespaceScope = "ns1::ns2::";
60  HI.Name = "foo";
61  HI.Kind = index::SymbolKind::Function;
62  HI.Documentation = "Best foo ever.";
63  HI.Definition = "void foo()";
64  HI.ReturnType = "void";
65  HI.Type = "void ()";
66  HI.Parameters.emplace();
67  }},
68  // Field
69  {R"cpp(
70  namespace ns1 { namespace ns2 {
71  struct Foo {
72  char [[b^ar]];
73  };
74  }}
75  )cpp",
76  [](HoverInfo &HI) {
77  HI.NamespaceScope = "ns1::ns2::";
78  HI.LocalScope = "Foo::";
79  HI.Name = "bar";
80  HI.Kind = index::SymbolKind::Field;
81  HI.Definition = "char bar";
82  HI.Type = "char";
83  HI.Offset = 0;
84  HI.Size = 1;
85  HI.AccessSpecifier = "public";
86  }},
87  // Local to class method.
88  {R"cpp(
89  namespace ns1 { namespace ns2 {
90  struct Foo {
91  void foo() {
92  int [[b^ar]];
93  }
94  };
95  }}
96  )cpp",
97  [](HoverInfo &HI) {
98  HI.NamespaceScope = "ns1::ns2::";
99  HI.LocalScope = "Foo::foo::";
100  HI.Name = "bar";
101  HI.Kind = index::SymbolKind::Variable;
102  HI.Definition = "int bar";
103  HI.Type = "int";
104  }},
105  // Anon namespace and local scope.
106  {R"cpp(
107  namespace ns1 { namespace {
108  struct {
109  char [[b^ar]];
110  } T;
111  }}
112  )cpp",
113  [](HoverInfo &HI) {
114  HI.NamespaceScope = "ns1::";
115  HI.LocalScope = "(anonymous struct)::";
116  HI.Name = "bar";
117  HI.Kind = index::SymbolKind::Field;
118  HI.Definition = "char bar";
119  HI.Type = "char";
120  HI.Offset = 0;
121  HI.Size = 1;
122  HI.AccessSpecifier = "public";
123  }},
124  // Struct definition shows size.
125  {R"cpp(
126  struct [[^X]]{};
127  )cpp",
128  [](HoverInfo &HI) {
129  HI.NamespaceScope = "";
130  HI.Name = "X";
131  HI.Kind = index::SymbolKind::Struct;
132  HI.Definition = "struct X {}";
133  HI.Size = 1;
134  }},
135  // Variable with template type
136  {R"cpp(
137  template <typename T, class... Ts> class Foo { public: Foo(int); };
138  Foo<int, char, bool> [[fo^o]] = Foo<int, char, bool>(5);
139  )cpp",
140  [](HoverInfo &HI) {
141  HI.NamespaceScope = "";
142  HI.Name = "foo";
143  HI.Kind = index::SymbolKind::Variable;
144  HI.Definition = "Foo<int, char, bool> foo = Foo<int, char, bool>(5)";
145  HI.Type = "Foo<int, char, bool>";
146  }},
147  // Implicit template instantiation
148  {R"cpp(
149  template <typename T> class vector{};
150  [[vec^tor]]<int> foo;
151  )cpp",
152  [](HoverInfo &HI) {
153  HI.NamespaceScope = "";
154  HI.Name = "vector<int>";
155  HI.Kind = index::SymbolKind::Class;
156  HI.Definition = "template <> class vector<int> {}";
157  }},
158  // Class template
159  {R"cpp(
160  template <template<typename, bool...> class C,
161  typename = char,
162  int = 0,
163  bool Q = false,
164  class... Ts> class Foo {};
165  template <template<typename, bool...> class T>
166  [[F^oo]]<T> foo;
167  )cpp",
168  [](HoverInfo &HI) {
169  HI.NamespaceScope = "";
170  HI.Name = "Foo";
171  HI.Kind = index::SymbolKind::Class;
172  HI.Definition =
173  R"cpp(template <template <typename, bool...> class C, typename = char, int = 0,
174  bool Q = false, class... Ts>
175 class Foo {})cpp";
176  HI.TemplateParameters = {
177  {std::string("template <typename, bool...> class"),
178  std::string("C"), llvm::None},
179  {std::string("typename"), llvm::None, std::string("char")},
180  {std::string("int"), llvm::None, std::string("0")},
181  {std::string("bool"), std::string("Q"), std::string("false")},
182  {std::string("class..."), std::string("Ts"), llvm::None},
183  };
184  }},
185  // Function template
186  {R"cpp(
187  template <template<typename, bool...> class C,
188  typename = char,
189  int = 0,
190  bool Q = false,
191  class... Ts> void foo();
192  template<typename, bool...> class Foo;
193 
194  void bar() {
195  [[fo^o]]<Foo>();
196  }
197  )cpp",
198  [](HoverInfo &HI) {
199  HI.NamespaceScope = "";
200  HI.Name = "foo";
201  HI.Kind = index::SymbolKind::Function;
202  HI.Definition = "template <> void foo<Foo, char, 0, false, <>>()";
203  HI.ReturnType = "void";
204  HI.Type = "void ()";
205  HI.Parameters.emplace();
206  }},
207  // Function decl
208  {R"cpp(
209  template<typename, bool...> class Foo {};
210  Foo<bool, true, false> foo(int, bool T = false);
211 
212  void bar() {
213  [[fo^o]](3);
214  }
215  )cpp",
216  [](HoverInfo &HI) {
217  HI.NamespaceScope = "";
218  HI.Name = "foo";
219  HI.Kind = index::SymbolKind::Function;
220  HI.Definition = "Foo<bool, true, false> foo(int, bool T = false)";
221  HI.ReturnType = "Foo<bool, true, false>";
222  HI.Type = "Foo<bool, true, false> (int, bool)";
223  HI.Parameters = {
224  {std::string("int"), llvm::None, llvm::None},
225  {std::string("bool"), std::string("T"), std::string("false")},
226  };
227  }},
228  // Pointers to lambdas
229  {R"cpp(
230  void foo() {
231  auto lamb = [](int T, bool B) -> bool { return T && B; };
232  auto *b = &lamb;
233  auto *[[^c]] = &b;
234  }
235  )cpp",
236  [](HoverInfo &HI) {
237  HI.NamespaceScope = "";
238  HI.LocalScope = "foo::";
239  HI.Name = "c";
240  HI.Kind = index::SymbolKind::Variable;
241  HI.Definition = "auto *c = &b";
242  HI.Type = "class (lambda) **";
243  HI.ReturnType = "bool";
244  HI.Parameters = {
245  {std::string("int"), std::string("T"), llvm::None},
246  {std::string("bool"), std::string("B"), llvm::None},
247  };
248  return HI;
249  }},
250  // Lambda parameter with decltype reference
251  {R"cpp(
252  auto lamb = [](int T, bool B) -> bool { return T && B; };
253  void foo(decltype(lamb)& bar) {
254  [[ba^r]](0, false);
255  }
256  )cpp",
257  [](HoverInfo &HI) {
258  HI.NamespaceScope = "";
259  HI.LocalScope = "foo::";
260  HI.Name = "bar";
261  HI.Kind = index::SymbolKind::Parameter;
262  HI.Definition = "decltype(lamb) &bar";
263  HI.Type = "decltype(lamb) &";
264  HI.ReturnType = "bool";
265  HI.Parameters = {
266  {std::string("int"), std::string("T"), llvm::None},
267  {std::string("bool"), std::string("B"), llvm::None},
268  };
269  return HI;
270  }},
271  // Lambda parameter with decltype
272  {R"cpp(
273  auto lamb = [](int T, bool B) -> bool { return T && B; };
274  void foo(decltype(lamb) bar) {
275  [[ba^r]](0, false);
276  }
277  )cpp",
278  [](HoverInfo &HI) {
279  HI.NamespaceScope = "";
280  HI.LocalScope = "foo::";
281  HI.Name = "bar";
282  HI.Kind = index::SymbolKind::Parameter;
283  HI.Definition = "decltype(lamb) bar";
284  HI.Type = "class (lambda)";
285  HI.ReturnType = "bool";
286  HI.Parameters = {
287  {std::string("int"), std::string("T"), llvm::None},
288  {std::string("bool"), std::string("B"), llvm::None},
289  };
290  HI.Value = "false";
291  return HI;
292  }},
293  // Lambda variable
294  {R"cpp(
295  void foo() {
296  int bar = 5;
297  auto lamb = [&bar](int T, bool B) -> bool { return T && B && bar; };
298  bool res = [[lam^b]](bar, false);
299  }
300  )cpp",
301  [](HoverInfo &HI) {
302  HI.NamespaceScope = "";
303  HI.LocalScope = "foo::";
304  HI.Name = "lamb";
305  HI.Kind = index::SymbolKind::Variable;
306  HI.Definition = "auto lamb = [&bar](int T, bool B) -> bool {}";
307  HI.Type = "class (lambda)";
308  HI.ReturnType = "bool";
309  HI.Parameters = {
310  {std::string("int"), std::string("T"), llvm::None},
311  {std::string("bool"), std::string("B"), llvm::None},
312  };
313  return HI;
314  }},
315  // Local variable in lambda
316  {R"cpp(
317  void foo() {
318  auto lamb = []{int [[te^st]];};
319  }
320  )cpp",
321  [](HoverInfo &HI) {
322  HI.NamespaceScope = "";
323  HI.LocalScope = "foo::(anonymous class)::operator()::";
324  HI.Name = "test";
325  HI.Kind = index::SymbolKind::Variable;
326  HI.Definition = "int test";
327  HI.Type = "int";
328  }},
329  // Partially-specialized class template. (formerly type-parameter-0-0)
330  {R"cpp(
331  template <typename T> class X;
332  template <typename T> class [[^X]]<T*> {};
333  )cpp",
334  [](HoverInfo &HI) {
335  HI.Name = "X<T *>";
336  HI.NamespaceScope = "";
337  HI.Kind = index::SymbolKind::Class;
338  HI.Definition = "template <typename T> class X<T *> {}";
339  }},
340  // Constructor of partially-specialized class template
341  {R"cpp(
342  template<typename, typename=void> struct X;
343  template<typename T> struct X<T*>{ [[^X]](); };
344  )cpp",
345  [](HoverInfo &HI) {
346  HI.NamespaceScope = "";
347  HI.Name = "X";
348  HI.LocalScope = "X<T *>::"; // FIXME: X<T *, void>::
349  HI.Kind = index::SymbolKind::Constructor;
350  HI.Definition = "X()";
351  HI.Parameters.emplace();
352  HI.AccessSpecifier = "public";
353  }},
354  {"class X { [[^~]]X(); };", // FIXME: Should be [[~X]]()
355  [](HoverInfo &HI) {
356  HI.NamespaceScope = "";
357  HI.Name = "~X";
358  HI.LocalScope = "X::";
359  HI.Kind = index::SymbolKind::Destructor;
360  HI.Definition = "~X()";
361  HI.Parameters.emplace();
362  HI.AccessSpecifier = "private";
363  }},
364  {"class X { [[op^erator]] int(); };",
365  [](HoverInfo &HI) {
366  HI.NamespaceScope = "";
367  HI.Name = "operator int";
368  HI.LocalScope = "X::";
369  HI.Kind = index::SymbolKind::ConversionFunction;
370  HI.Definition = "operator int()";
371  HI.Parameters.emplace();
372  HI.AccessSpecifier = "private";
373  }},
374  {"class X { operator [[^X]](); };",
375  [](HoverInfo &HI) {
376  HI.NamespaceScope = "";
377  HI.Name = "X";
378  HI.Kind = index::SymbolKind::Class;
379  HI.Definition = "class X {}";
380  }},
381 
382  // auto on lambda
383  {R"cpp(
384  void foo() {
385  [[au^to]] lamb = []{};
386  }
387  )cpp",
388  [](HoverInfo &HI) {
389  HI.Name = "(lambda)";
390  HI.Kind = index::SymbolKind::Class;
391  }},
392  // auto on template instantiation
393  {R"cpp(
394  template<typename T> class Foo{};
395  void foo() {
396  [[au^to]] x = Foo<int>();
397  }
398  )cpp",
399  [](HoverInfo &HI) {
400  HI.Name = "Foo<int>";
401  HI.Kind = index::SymbolKind::Class;
402  }},
403  // auto on specialized template
404  {R"cpp(
405  template<typename T> class Foo{};
406  template<> class Foo<int>{};
407  void foo() {
408  [[au^to]] x = Foo<int>();
409  }
410  )cpp",
411  [](HoverInfo &HI) {
412  HI.Name = "Foo<int>";
413  HI.Kind = index::SymbolKind::Class;
414  }},
415 
416  // macro
417  {R"cpp(
418  // Best MACRO ever.
419  #define MACRO(x,y,z) void foo(x, y, z);
420  [[MAC^RO]](int, double d, bool z = false);
421  )cpp",
422  [](HoverInfo &HI) {
423  HI.Name = "MACRO", HI.Kind = index::SymbolKind::Macro,
424  HI.Definition = "#define MACRO(x, y, z) void foo(x, y, z);";
425  }},
426 
427  // constexprs
428  {R"cpp(
429  constexpr int add(int a, int b) { return a + b; }
430  int [[b^ar]] = add(1, 2);
431  )cpp",
432  [](HoverInfo &HI) {
433  HI.Name = "bar";
434  HI.Definition = "int bar = add(1, 2)";
435  HI.Kind = index::SymbolKind::Variable;
436  HI.Type = "int";
437  HI.NamespaceScope = "";
438  HI.Value = "3";
439  }},
440  {R"cpp(
441  int [[b^ar]] = sizeof(char);
442  )cpp",
443  [](HoverInfo &HI) {
444  HI.Name = "bar";
445  HI.Definition = "int bar = sizeof(char)";
446  HI.Kind = index::SymbolKind::Variable;
447  HI.Type = "int";
448  HI.NamespaceScope = "";
449  HI.Value = "1";
450  }},
451  {R"cpp(
452  template<int a, int b> struct Add {
453  static constexpr int result = a + b;
454  };
455  int [[ba^r]] = Add<1, 2>::result;
456  )cpp",
457  [](HoverInfo &HI) {
458  HI.Name = "bar";
459  HI.Definition = "int bar = Add<1, 2>::result";
460  HI.Kind = index::SymbolKind::Variable;
461  HI.Type = "int";
462  HI.NamespaceScope = "";
463  HI.Value = "3";
464  }},
465  {R"cpp(
466  enum Color { RED, GREEN, };
467  Color x = [[GR^EEN]];
468  )cpp",
469  [](HoverInfo &HI) {
470  HI.Name = "GREEN";
471  HI.NamespaceScope = "";
472  HI.LocalScope = "Color::";
473  HI.Definition = "GREEN";
474  HI.Kind = index::SymbolKind::EnumConstant;
475  HI.Type = "enum Color";
476  HI.Value = "1"; // Numeric when hovering on the enumerator name.
477  }},
478  {R"cpp(
479  enum Color { RED, GREEN, };
480  Color x = GREEN;
481  Color y = [[^x]];
482  )cpp",
483  [](HoverInfo &HI) {
484  HI.Name = "x";
485  HI.NamespaceScope = "";
486  HI.Definition = "Color x = GREEN";
487  HI.Kind = index::SymbolKind::Variable;
488  HI.Type = "enum Color";
489  HI.Value = "GREEN (1)"; // Symbolic when hovering on an expression.
490  }},
491  {R"cpp(
492  template<int a, int b> struct Add {
493  static constexpr int result = a + b;
494  };
495  int bar = Add<1, 2>::[[resu^lt]];
496  )cpp",
497  [](HoverInfo &HI) {
498  HI.Name = "result";
499  HI.Definition = "static constexpr int result = 1 + 2";
500  HI.Kind = index::SymbolKind::StaticProperty;
501  HI.Type = "const int";
502  HI.NamespaceScope = "";
503  HI.LocalScope = "Add<1, 2>::";
504  HI.Value = "3";
505  HI.AccessSpecifier = "public";
506  }},
507  {R"cpp(
508  constexpr int answer() { return 40 + 2; }
509  int x = [[ans^wer]]();
510  )cpp",
511  [](HoverInfo &HI) {
512  HI.Name = "answer";
513  HI.Definition = "constexpr int answer()";
514  HI.Kind = index::SymbolKind::Function;
515  HI.Type = "int ()";
516  HI.ReturnType = "int";
517  HI.Parameters.emplace();
518  HI.NamespaceScope = "";
519  HI.Value = "42";
520  }},
521  {R"cpp(
522  const char *[[ba^r]] = "1234";
523  )cpp",
524  [](HoverInfo &HI) {
525  HI.Name = "bar";
526  HI.Definition = "const char *bar = \"1234\"";
527  HI.Kind = index::SymbolKind::Variable;
528  HI.Type = "const char *";
529  HI.NamespaceScope = "";
530  HI.Value = "&\"1234\"[0]";
531  }},
532  {R"cpp(// Should not crash
533  template <typename T>
534  struct Tmpl {
535  Tmpl(int name);
536  };
537 
538  template <typename A>
539  void boom(int name) {
540  new Tmpl<A>([[na^me]]);
541  })cpp",
542  [](HoverInfo &HI) {
543  HI.Name = "name";
544  HI.Definition = "int name";
545  HI.Kind = index::SymbolKind::Parameter;
546  HI.Type = "int";
547  HI.NamespaceScope = "";
548  HI.LocalScope = "boom::";
549  }},
550  {
551  R"cpp(// Should not print inline or anon namespaces.
552  namespace ns {
553  inline namespace in_ns {
554  namespace a {
555  namespace {
556  namespace b {
557  inline namespace in_ns2 {
558  class Foo {};
559  } // in_ns2
560  } // b
561  } // anon
562  } // a
563  } // in_ns
564  } // ns
565  void foo() {
566  ns::a::b::[[F^oo]] x;
567  (void)x;
568  }
569  )cpp",
570  [](HoverInfo &HI) {
571  HI.Name = "Foo";
572  HI.Kind = index::SymbolKind::Class;
573  HI.NamespaceScope = "ns::a::b::";
574  HI.Definition = "class Foo {}";
575  }},
576  {
577  R"cpp(
578  template <typename T> class Foo {};
579  class X;
580  void foo() {
581  [[^auto]] x = Foo<X>();
582  }
583  )cpp",
584  [](HoverInfo &HI) {
585  HI.Name = "Foo<X>";
586  HI.Kind = index::SymbolKind::Class;
587  }},
588  {// Falls back to primary template, when the type is not instantiated.
589  R"cpp(
590  // comment from primary
591  template <typename T> class Foo {};
592  // comment from specialization
593  template <typename T> class Foo<T*> {};
594  void foo() {
595  [[Fo^o]]<int*> *x = nullptr;
596  }
597  )cpp",
598  [](HoverInfo &HI) {
599  HI.Name = "Foo<int *>";
600  HI.Kind = index::SymbolKind::Class;
601  HI.NamespaceScope = "";
602  HI.Definition = "template <> class Foo<int *>";
603  // FIXME: Maybe force instantiation to make use of real template
604  // pattern.
605  HI.Documentation = "comment from primary";
606  }},
607  {// Template Type Parameter
608  R"cpp(
609  template <typename [[^T]] = int> void foo();
610  )cpp",
611  [](HoverInfo &HI) {
612  HI.Name = "T";
613  HI.Kind = index::SymbolKind::TemplateTypeParm;
614  HI.NamespaceScope = "";
615  HI.Definition = "typename T = int";
616  HI.LocalScope = "foo::";
617  HI.Type = "typename";
618  HI.AccessSpecifier = "public";
619  }},
620  {// TemplateTemplate Type Parameter
621  R"cpp(
622  template <template<typename> class [[^T]]> void foo();
623  )cpp",
624  [](HoverInfo &HI) {
625  HI.Name = "T";
626  HI.Kind = index::SymbolKind::TemplateTemplateParm;
627  HI.NamespaceScope = "";
628  HI.Definition = "template <typename> class T";
629  HI.LocalScope = "foo::";
630  HI.Type = "template <typename> class";
631  HI.AccessSpecifier = "public";
632  }},
633  {// NonType Template Parameter
634  R"cpp(
635  template <int [[^T]] = 5> void foo();
636  )cpp",
637  [](HoverInfo &HI) {
638  HI.Name = "T";
639  HI.Kind = index::SymbolKind::NonTypeTemplateParm;
640  HI.NamespaceScope = "";
641  HI.Definition = "int T = 5";
642  HI.LocalScope = "foo::";
643  HI.Type = "int";
644  HI.AccessSpecifier = "public";
645  }},
646 
647  {// Getter
648  R"cpp(
649  struct X { int Y; float [[^y]]() { return Y; } };
650  )cpp",
651  [](HoverInfo &HI) {
652  HI.Name = "y";
653  HI.Kind = index::SymbolKind::InstanceMethod;
654  HI.NamespaceScope = "";
655  HI.Definition = "float y()";
656  HI.LocalScope = "X::";
657  HI.Documentation = "Trivial accessor for `Y`.";
658  HI.Type = "float ()";
659  HI.ReturnType = "float";
660  HI.Parameters.emplace();
661  HI.AccessSpecifier = "public";
662  }},
663  {// Setter
664  R"cpp(
665  struct X { int Y; void [[^setY]](float v) { Y = v; } };
666  )cpp",
667  [](HoverInfo &HI) {
668  HI.Name = "setY";
669  HI.Kind = index::SymbolKind::InstanceMethod;
670  HI.NamespaceScope = "";
671  HI.Definition = "void setY(float v)";
672  HI.LocalScope = "X::";
673  HI.Documentation = "Trivial setter for `Y`.";
674  HI.Type = "void (float)";
675  HI.ReturnType = "void";
676  HI.Parameters.emplace();
677  HI.Parameters->emplace_back();
678  HI.Parameters->back().Type = "float";
679  HI.Parameters->back().Name = "v";
680  HI.AccessSpecifier = "public";
681  }},
682  {// Setter (builder)
683  R"cpp(
684  struct X { int Y; X& [[^setY]](float v) { Y = v; return *this; } };
685  )cpp",
686  [](HoverInfo &HI) {
687  HI.Name = "setY";
688  HI.Kind = index::SymbolKind::InstanceMethod;
689  HI.NamespaceScope = "";
690  HI.Definition = "X &setY(float v)";
691  HI.LocalScope = "X::";
692  HI.Documentation = "Trivial setter for `Y`.";
693  HI.Type = "struct X &(float)";
694  HI.ReturnType = "struct X &";
695  HI.Parameters.emplace();
696  HI.Parameters->emplace_back();
697  HI.Parameters->back().Type = "float";
698  HI.Parameters->back().Name = "v";
699  HI.AccessSpecifier = "public";
700  }},
701  {// Field type initializer.
702  R"cpp(
703  struct X { int x = 2; };
704  X ^[[x]];
705  )cpp",
706  [](HoverInfo &HI) {
707  HI.Name = "x";
708  HI.Kind = index::SymbolKind::Variable;
709  HI.NamespaceScope = "";
710  HI.Definition = "X x";
711  HI.Type = "struct X";
712  }},
713  {// Don't crash on null types.
714  R"cpp(auto [^[[x]]] = 1; /*error-ok*/)cpp",
715  [](HoverInfo &HI) {
716  HI.Name = "x";
717  HI.Kind = index::SymbolKind::Variable;
718  HI.NamespaceScope = "";
719  HI.Definition = "";
720  HI.Type = "NULL TYPE";
721  // Bindings are in theory public members of an anonymous struct.
722  HI.AccessSpecifier = "public";
723  }},
724  {// Extra info for function call.
725  R"cpp(
726  void fun(int arg_a, int &arg_b) {};
727  void code() {
728  int a = 1, b = 2;
729  fun(a, [[^b]]);
730  }
731  )cpp",
732  [](HoverInfo &HI) {
733  HI.Name = "b";
734  HI.Kind = index::SymbolKind::Variable;
735  HI.NamespaceScope = "";
736  HI.Definition = "int b = 2";
737  HI.LocalScope = "code::";
738  HI.Value = "2";
739  HI.Type = "int";
740  HI.CalleeArgInfo.emplace();
741  HI.CalleeArgInfo->Name = "arg_b";
742  HI.CalleeArgInfo->Type = "int &";
743  HI.CallPassType.emplace();
744  HI.CallPassType->PassBy = PassMode::Ref;
745  HI.CallPassType->Converted = false;
746  }},
747  {// Extra info for method call.
748  R"cpp(
749  class C {
750  public:
751  void fun(int arg_a = 3, int arg_b = 4) {}
752  };
753  void code() {
754  int a = 1, b = 2;
755  C c;
756  c.fun([[^a]], b);
757  }
758  )cpp",
759  [](HoverInfo &HI) {
760  HI.Name = "a";
761  HI.Kind = index::SymbolKind::Variable;
762  HI.NamespaceScope = "";
763  HI.Definition = "int a = 1";
764  HI.LocalScope = "code::";
765  HI.Value = "1";
766  HI.Type = "int";
767  HI.CalleeArgInfo.emplace();
768  HI.CalleeArgInfo->Name = "arg_a";
769  HI.CalleeArgInfo->Type = "int";
770  HI.CalleeArgInfo->Default = "3";
771  HI.CallPassType.emplace();
772  HI.CallPassType->PassBy = PassMode::Value;
773  HI.CallPassType->Converted = false;
774  }},
775  {// Dont crash on invalid decl
776  R"cpp(
777  // error-ok
778  struct Foo {
779  Bar [[x^x]];
780  };)cpp",
781  [](HoverInfo &HI) {
782  HI.Name = "xx";
783  HI.Kind = index::SymbolKind::Field;
784  HI.NamespaceScope = "";
785  HI.Definition = "int xx";
786  HI.LocalScope = "Foo::";
787  HI.Type = "int";
788  HI.AccessSpecifier = "public";
789  }},
790  {R"cpp(
791  // error-ok
792  struct Foo {
793  Bar xx;
794  int [[y^y]];
795  };)cpp",
796  [](HoverInfo &HI) {
797  HI.Name = "yy";
798  HI.Kind = index::SymbolKind::Field;
799  HI.NamespaceScope = "";
800  HI.Definition = "int yy";
801  HI.LocalScope = "Foo::";
802  HI.Type = "int";
803  HI.AccessSpecifier = "public";
804  }},
805  {// No crash on InitListExpr.
806  R"cpp(
807  struct Foo {
808  int a[10];
809  };
810  constexpr Foo k2 = {
811  ^[[{]]1} // FIXME: why the hover range is 1 character?
812  };
813  )cpp",
814  [](HoverInfo &HI) {
815  HI.Name = "expression";
816  HI.Kind = index::SymbolKind::Unknown;
817  HI.Type = "int [10]";
818  HI.Value = "{1}";
819  }}};
820  for (const auto &Case : Cases) {
821  SCOPED_TRACE(Case.Code);
822 
823  Annotations T(Case.Code);
824  TestTU TU = TestTU::withCode(T.code());
825  TU.ExtraArgs.push_back("-std=c++17");
826  // Types might be different depending on the target triplet, we chose a
827  // fixed one to make sure tests passes on different platform.
828  TU.ExtraArgs.push_back("--target=x86_64-pc-linux-gnu");
829  auto AST = TU.build();
830 
831  auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);
832  ASSERT_TRUE(H);
833  HoverInfo Expected;
834  Expected.SymRange = T.range();
835  Case.ExpectedBuilder(Expected);
836 
837  EXPECT_EQ(H->NamespaceScope, Expected.NamespaceScope);
838  EXPECT_EQ(H->LocalScope, Expected.LocalScope);
839  EXPECT_EQ(H->Name, Expected.Name);
840  EXPECT_EQ(H->Kind, Expected.Kind);
841  EXPECT_EQ(H->Documentation, Expected.Documentation);
842  EXPECT_EQ(H->Definition, Expected.Definition);
843  EXPECT_EQ(H->Type, Expected.Type);
844  EXPECT_EQ(H->ReturnType, Expected.ReturnType);
845  EXPECT_EQ(H->Parameters, Expected.Parameters);
846  EXPECT_EQ(H->TemplateParameters, Expected.TemplateParameters);
847  EXPECT_EQ(H->SymRange, Expected.SymRange);
848  EXPECT_EQ(H->Value, Expected.Value);
849  EXPECT_EQ(H->Size, Expected.Size);
850  EXPECT_EQ(H->Offset, Expected.Offset);
851  EXPECT_EQ(H->AccessSpecifier, Expected.AccessSpecifier);
852  EXPECT_EQ(H->CalleeArgInfo, Expected.CalleeArgInfo);
853  EXPECT_EQ(H->CallPassType, Expected.CallPassType);
854  }
855 }
856 
857 TEST(Hover, CallPassType) {
858  const llvm::StringRef CodePrefix = R"cpp(
859 class Base {};
860 class Derived : public Base {};
861 class CustomClass {
862  public:
863  CustomClass() {}
864  CustomClass(const Base &x) {}
865  CustomClass(int &x) {}
866  CustomClass(float x) {}
867 };
868 
869 void int_by_ref(int &x) {}
870 void int_by_const_ref(const int &x) {}
871 void int_by_value(int x) {}
872 void base_by_ref(Base &x) {}
873 void base_by_const_ref(const Base &x) {}
874 void base_by_value(Base x) {}
875 void float_by_value(float x) {}
876 void custom_by_value(CustomClass x) {}
877 
878 void fun() {
879  int int_x;
880  int &int_ref = int_x;
881  const int &int_const_ref = int_x;
882  Base base;
883  const Base &base_const_ref = base;
884  Derived derived;
885  float float_x;
886 )cpp";
887  const llvm::StringRef CodeSuffix = "}";
888 
889  struct {
890  const char *const Code;
892  bool Converted;
893  } Tests[] = {
894  // Integer tests
895  {"int_by_value([[^int_x]]);", PassMode::Value, false},
896  {"int_by_ref([[^int_x]]);", PassMode::Ref, false},
897  {"int_by_const_ref([[^int_x]]);", PassMode::ConstRef, false},
898  {"int_by_value([[^int_ref]]);", PassMode::Value, false},
899  {"int_by_const_ref([[^int_ref]]);", PassMode::ConstRef, false},
900  {"int_by_const_ref([[^int_ref]]);", PassMode::ConstRef, false},
901  {"int_by_const_ref([[^int_const_ref]]);", PassMode::ConstRef, false},
902  // Custom class tests
903  {"base_by_ref([[^base]]);", PassMode::Ref, false},
904  {"base_by_const_ref([[^base]]);", PassMode::ConstRef, false},
905  {"base_by_const_ref([[^base_const_ref]]);", PassMode::ConstRef, false},
906  {"base_by_value([[^base]]);", PassMode::Value, false},
907  {"base_by_value([[^base_const_ref]]);", PassMode::Value, false},
908  {"base_by_ref([[^derived]]);", PassMode::Ref, false},
909  {"base_by_const_ref([[^derived]]);", PassMode::ConstRef, false},
910  {"base_by_value([[^derived]]);", PassMode::Value, false},
911  // Converted tests
912  {"float_by_value([[^int_x]]);", PassMode::Value, true},
913  {"float_by_value([[^int_ref]]);", PassMode::Value, true},
914  {"float_by_value([[^int_const_ref]]);", PassMode::Value, true},
915  {"custom_by_value([[^int_x]]);", PassMode::Ref, true},
916  {"custom_by_value([[^float_x]]);", PassMode::Value, true},
917  {"custom_by_value([[^base]]);", PassMode::ConstRef, true},
918  };
919  for (const auto &Test : Tests) {
920  SCOPED_TRACE(Test.Code);
921 
922  const auto Code = (CodePrefix + Test.Code + CodeSuffix).str();
923  Annotations T(Code);
924  TestTU TU = TestTU::withCode(T.code());
925  TU.ExtraArgs.push_back("-std=c++17");
926  auto AST = TU.build();
927  auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);
928  ASSERT_TRUE(H);
929  EXPECT_EQ(H->CallPassType->PassBy, Test.PassBy);
930  EXPECT_EQ(H->CallPassType->Converted, Test.Converted);
931  }
932 }
933 
934 TEST(Hover, NoHover) {
935  llvm::StringRef Tests[] = {
936  "^int main() {}",
937  "void foo() {^}",
938  R"cpp(// structured binding. Not supported yet
939  struct Bar {};
940  void foo() {
941  Bar a[2];
942  ^auto [x,y] = a;
943  }
944  )cpp",
945  R"cpp(// Template auto parameter. Nothing (Not useful).
946  template<a^uto T>
947  void func() {
948  }
949  void foo() {
950  func<1>();
951  }
952  )cpp",
953  R"cpp(// non-named decls don't get hover. Don't crash!
954  ^static_assert(1, "");
955  )cpp",
956  R"cpp(// non-evaluatable expr
957  template <typename T> void foo() {
958  (void)[[size^of]](T);
959  })cpp",
960  // literals
961  "auto x = t^rue;",
962  "auto x = '^A';",
963  "auto x = ^(int){42};",
964  "auto x = ^42.;",
965  "auto x = ^42.0i;",
966  "auto x = ^42;",
967  "auto x = ^nullptr;",
968  "auto x = ^\"asdf\";",
969  };
970 
971  for (const auto &Test : Tests) {
972  SCOPED_TRACE(Test);
973 
974  Annotations T(Test);
975  TestTU TU = TestTU::withCode(T.code());
976  TU.ExtraArgs.push_back("-std=c++17");
977  auto AST = TU.build();
978  auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);
979  ASSERT_FALSE(H);
980  }
981 }
982 
983 TEST(Hover, All) {
984  struct {
985  const char *const Code;
986  const std::function<void(HoverInfo &)> ExpectedBuilder;
987  } Cases[] = {
988  {
989  R"cpp(// Local variable
990  int main() {
991  int bonjour;
992  ^[[bonjour]] = 2;
993  int test1 = bonjour;
994  }
995  )cpp",
996  [](HoverInfo &HI) {
997  HI.Name = "bonjour";
998  HI.Kind = index::SymbolKind::Variable;
999  HI.NamespaceScope = "";
1000  HI.LocalScope = "main::";
1001  HI.Type = "int";
1002  HI.Definition = "int bonjour";
1003  }},
1004  {
1005  R"cpp(// Local variable in method
1006  struct s {
1007  void method() {
1008  int bonjour;
1009  ^[[bonjour]] = 2;
1010  }
1011  };
1012  )cpp",
1013  [](HoverInfo &HI) {
1014  HI.Name = "bonjour";
1015  HI.Kind = index::SymbolKind::Variable;
1016  HI.NamespaceScope = "";
1017  HI.LocalScope = "s::method::";
1018  HI.Type = "int";
1019  HI.Definition = "int bonjour";
1020  }},
1021  {
1022  R"cpp(// Struct
1023  namespace ns1 {
1024  struct MyClass {};
1025  } // namespace ns1
1026  int main() {
1027  ns1::[[My^Class]]* Params;
1028  }
1029  )cpp",
1030  [](HoverInfo &HI) {
1031  HI.Name = "MyClass";
1032  HI.Kind = index::SymbolKind::Struct;
1033  HI.NamespaceScope = "ns1::";
1034  HI.Definition = "struct MyClass {}";
1035  }},
1036  {
1037  R"cpp(// Class
1038  namespace ns1 {
1039  class MyClass {};
1040  } // namespace ns1
1041  int main() {
1042  ns1::[[My^Class]]* Params;
1043  }
1044  )cpp",
1045  [](HoverInfo &HI) {
1046  HI.Name = "MyClass";
1047  HI.Kind = index::SymbolKind::Class;
1048  HI.NamespaceScope = "ns1::";
1049  HI.Definition = "class MyClass {}";
1050  }},
1051  {
1052  R"cpp(// Union
1053  namespace ns1 {
1054  union MyUnion { int x; int y; };
1055  } // namespace ns1
1056  int main() {
1057  ns1::[[My^Union]] Params;
1058  }
1059  )cpp",
1060  [](HoverInfo &HI) {
1061  HI.Name = "MyUnion";
1062  HI.Kind = index::SymbolKind::Union;
1063  HI.NamespaceScope = "ns1::";
1064  HI.Definition = "union MyUnion {}";
1065  }},
1066  {
1067  R"cpp(// Function definition via pointer
1068  void foo(int) {}
1069  int main() {
1070  auto *X = &^[[foo]];
1071  }
1072  )cpp",
1073  [](HoverInfo &HI) {
1074  HI.Name = "foo";
1075  HI.Kind = index::SymbolKind::Function;
1076  HI.NamespaceScope = "";
1077  HI.Type = "void (int)";
1078  HI.Definition = "void foo(int)";
1079  HI.Documentation = "Function definition via pointer";
1080  HI.ReturnType = "void";
1081  HI.Parameters = {
1082  {std::string("int"), llvm::None, llvm::None},
1083  };
1084  }},
1085  {
1086  R"cpp(// Function declaration via call
1087  int foo(int);
1088  int main() {
1089  return ^[[foo]](42);
1090  }
1091  )cpp",
1092  [](HoverInfo &HI) {
1093  HI.Name = "foo";
1094  HI.Kind = index::SymbolKind::Function;
1095  HI.NamespaceScope = "";
1096  HI.Type = "int (int)";
1097  HI.Definition = "int foo(int)";
1098  HI.Documentation = "Function declaration via call";
1099  HI.ReturnType = "int";
1100  HI.Parameters = {
1101  {std::string("int"), llvm::None, llvm::None},
1102  };
1103  }},
1104  {
1105  R"cpp(// Field
1106  struct Foo { int x; };
1107  int main() {
1108  Foo bar;
1109  (void)bar.^[[x]];
1110  }
1111  )cpp",
1112  [](HoverInfo &HI) {
1113  HI.Name = "x";
1114  HI.Kind = index::SymbolKind::Field;
1115  HI.NamespaceScope = "";
1116  HI.LocalScope = "Foo::";
1117  HI.Type = "int";
1118  HI.Definition = "int x";
1119  }},
1120  {
1121  R"cpp(// Field with initialization
1122  struct Foo { int x = 5; };
1123  int main() {
1124  Foo bar;
1125  (void)bar.^[[x]];
1126  }
1127  )cpp",
1128  [](HoverInfo &HI) {
1129  HI.Name = "x";
1130  HI.Kind = index::SymbolKind::Field;
1131  HI.NamespaceScope = "";
1132  HI.LocalScope = "Foo::";
1133  HI.Type = "int";
1134  HI.Definition = "int x = 5";
1135  }},
1136  {
1137  R"cpp(// Static field
1138  struct Foo { static int x; };
1139  int main() {
1140  (void)Foo::^[[x]];
1141  }
1142  )cpp",
1143  [](HoverInfo &HI) {
1144  HI.Name = "x";
1145  HI.Kind = index::SymbolKind::StaticProperty;
1146  HI.NamespaceScope = "";
1147  HI.LocalScope = "Foo::";
1148  HI.Type = "int";
1149  HI.Definition = "static int x";
1150  }},
1151  {
1152  R"cpp(// Field, member initializer
1153  struct Foo {
1154  int x;
1155  Foo() : ^[[x]](0) {}
1156  };
1157  )cpp",
1158  [](HoverInfo &HI) {
1159  HI.Name = "x";
1160  HI.Kind = index::SymbolKind::Field;
1161  HI.NamespaceScope = "";
1162  HI.LocalScope = "Foo::";
1163  HI.Type = "int";
1164  HI.Definition = "int x";
1165  }},
1166  {
1167  R"cpp(// Field, GNU old-style field designator
1168  struct Foo { int x; };
1169  int main() {
1170  Foo bar = { ^[[x]] : 1 };
1171  }
1172  )cpp",
1173  [](HoverInfo &HI) {
1174  HI.Name = "x";
1175  HI.Kind = index::SymbolKind::Field;
1176  HI.NamespaceScope = "";
1177  HI.LocalScope = "Foo::";
1178  HI.Type = "int";
1179  HI.Definition = "int x";
1180  // FIXME: Initializer for x is a DesignatedInitListExpr, hence it is
1181  // of struct type and omitted.
1182  }},
1183  {
1184  R"cpp(// Field, field designator
1185  struct Foo { int x; int y; };
1186  int main() {
1187  Foo bar = { .^[[x]] = 2, .y = 2 };
1188  }
1189  )cpp",
1190  [](HoverInfo &HI) {
1191  HI.Name = "x";
1192  HI.Kind = index::SymbolKind::Field;
1193  HI.NamespaceScope = "";
1194  HI.LocalScope = "Foo::";
1195  HI.Type = "int";
1196  HI.Definition = "int x";
1197  }},
1198  {
1199  R"cpp(// Method call
1200  struct Foo { int x(); };
1201  int main() {
1202  Foo bar;
1203  bar.^[[x]]();
1204  }
1205  )cpp",
1206  [](HoverInfo &HI) {
1207  HI.Name = "x";
1208  HI.Kind = index::SymbolKind::InstanceMethod;
1209  HI.NamespaceScope = "";
1210  HI.LocalScope = "Foo::";
1211  HI.Type = "int ()";
1212  HI.Definition = "int x()";
1213  HI.ReturnType = "int";
1214  HI.Parameters = std::vector<HoverInfo::Param>{};
1215  }},
1216  {
1217  R"cpp(// Static method call
1218  struct Foo { static int x(); };
1219  int main() {
1220  Foo::^[[x]]();
1221  }
1222  )cpp",
1223  [](HoverInfo &HI) {
1224  HI.Name = "x";
1225  HI.Kind = index::SymbolKind::StaticMethod;
1226  HI.NamespaceScope = "";
1227  HI.LocalScope = "Foo::";
1228  HI.Type = "int ()";
1229  HI.Definition = "static int x()";
1230  HI.ReturnType = "int";
1231  HI.Parameters = std::vector<HoverInfo::Param>{};
1232  }},
1233  {
1234  R"cpp(// Typedef
1235  typedef int Foo;
1236  int main() {
1237  ^[[Foo]] bar;
1238  }
1239  )cpp",
1240  [](HoverInfo &HI) {
1241  HI.Name = "Foo";
1242  HI.Kind = index::SymbolKind::TypeAlias;
1243  HI.NamespaceScope = "";
1244  HI.Definition = "typedef int Foo";
1245  HI.Documentation = "Typedef";
1246  // FIXME: Maybe put underlying type into HI.Type for aliases?
1247  }},
1248  {
1249  R"cpp(// Typedef with embedded definition
1250  typedef struct Bar {} Foo;
1251  int main() {
1252  ^[[Foo]] bar;
1253  }
1254  )cpp",
1255  [](HoverInfo &HI) {
1256  HI.Name = "Foo";
1257  HI.Kind = index::SymbolKind::TypeAlias;
1258  HI.NamespaceScope = "";
1259  HI.Definition = "typedef struct Bar Foo";
1260  HI.Documentation = "Typedef with embedded definition";
1261  }},
1262  {
1263  R"cpp(// Namespace
1264  namespace ns {
1265  struct Foo { static void bar(); };
1266  } // namespace ns
1267  int main() { ^[[ns]]::Foo::bar(); }
1268  )cpp",
1269  [](HoverInfo &HI) {
1270  HI.Name = "ns";
1271  HI.Kind = index::SymbolKind::Namespace;
1272  HI.NamespaceScope = "";
1273  HI.Definition = "namespace ns {}";
1274  }},
1275  {
1276  R"cpp(// Anonymous namespace
1277  namespace ns {
1278  namespace {
1279  int foo;
1280  } // anonymous namespace
1281  } // namespace ns
1282  int main() { ns::[[f^oo]]++; }
1283  )cpp",
1284  [](HoverInfo &HI) {
1285  HI.Name = "foo";
1286  HI.Kind = index::SymbolKind::Variable;
1287  HI.NamespaceScope = "ns::";
1288  HI.Type = "int";
1289  HI.Definition = "int foo";
1290  }},
1291  {
1292  R"cpp(// Macro
1293  #define MACRO 0
1294  int main() { return ^[[MACRO]]; }
1295  )cpp",
1296  [](HoverInfo &HI) {
1297  HI.Name = "MACRO";
1298  HI.Kind = index::SymbolKind::Macro;
1299  HI.Definition = "#define MACRO 0";
1300  }},
1301  {
1302  R"cpp(// Macro
1303  #define MACRO 0
1304  #define MACRO2 ^[[MACRO]]
1305  )cpp",
1306  [](HoverInfo &HI) {
1307  HI.Name = "MACRO";
1308  HI.Kind = index::SymbolKind::Macro;
1309  HI.Definition = "#define MACRO 0";
1310  }},
1311  {
1312  R"cpp(// Macro
1313  #define MACRO {\
1314  return 0;\
1315  }
1316  int main() ^[[MACRO]]
1317  )cpp",
1318  [](HoverInfo &HI) {
1319  HI.Name = "MACRO";
1320  HI.Kind = index::SymbolKind::Macro;
1321  HI.Definition =
1322  R"cpp(#define MACRO \
1323  { return 0; })cpp";
1324  }},
1325  {
1326  R"cpp(// Forward class declaration
1327  class Foo;
1328  class Foo {};
1329  [[F^oo]]* foo();
1330  )cpp",
1331  [](HoverInfo &HI) {
1332  HI.Name = "Foo";
1333  HI.Kind = index::SymbolKind::Class;
1334  HI.NamespaceScope = "";
1335  HI.Definition = "class Foo {}";
1336  HI.Documentation = "Forward class declaration";
1337  }},
1338  {
1339  R"cpp(// Function declaration
1340  void foo();
1341  void g() { [[f^oo]](); }
1342  void foo() {}
1343  )cpp",
1344  [](HoverInfo &HI) {
1345  HI.Name = "foo";
1346  HI.Kind = index::SymbolKind::Function;
1347  HI.NamespaceScope = "";
1348  HI.Type = "void ()";
1349  HI.Definition = "void foo()";
1350  HI.Documentation = "Function declaration";
1351  HI.ReturnType = "void";
1352  HI.Parameters = std::vector<HoverInfo::Param>{};
1353  }},
1354  {
1355  R"cpp(// Enum declaration
1356  enum Hello {
1357  ONE, TWO, THREE,
1358  };
1359  void foo() {
1360  [[Hel^lo]] hello = ONE;
1361  }
1362  )cpp",
1363  [](HoverInfo &HI) {
1364  HI.Name = "Hello";
1365  HI.Kind = index::SymbolKind::Enum;
1366  HI.NamespaceScope = "";
1367  HI.Definition = "enum Hello {}";
1368  HI.Documentation = "Enum declaration";
1369  }},
1370  {
1371  R"cpp(// Enumerator
1372  enum Hello {
1373  ONE, TWO, THREE,
1374  };
1375  void foo() {
1376  Hello hello = [[O^NE]];
1377  }
1378  )cpp",
1379  [](HoverInfo &HI) {
1380  HI.Name = "ONE";
1381  HI.Kind = index::SymbolKind::EnumConstant;
1382  HI.NamespaceScope = "";
1383  HI.LocalScope = "Hello::";
1384  HI.Type = "enum Hello";
1385  HI.Definition = "ONE";
1386  HI.Value = "0";
1387  }},
1388  {
1389  R"cpp(// Enumerator in anonymous enum
1390  enum {
1391  ONE, TWO, THREE,
1392  };
1393  void foo() {
1394  int hello = [[O^NE]];
1395  }
1396  )cpp",
1397  [](HoverInfo &HI) {
1398  HI.Name = "ONE";
1399  HI.Kind = index::SymbolKind::EnumConstant;
1400  HI.NamespaceScope = "";
1401  // FIXME: This should be `(anon enum)::`
1402  HI.LocalScope = "";
1403  HI.Type = "enum (anonymous)";
1404  HI.Definition = "ONE";
1405  HI.Value = "0";
1406  }},
1407  {
1408  R"cpp(// Global variable
1409  static int hey = 10;
1410  void foo() {
1411  [[he^y]]++;
1412  }
1413  )cpp",
1414  [](HoverInfo &HI) {
1415  HI.Name = "hey";
1416  HI.Kind = index::SymbolKind::Variable;
1417  HI.NamespaceScope = "";
1418  HI.Type = "int";
1419  HI.Definition = "static int hey = 10";
1420  HI.Documentation = "Global variable";
1421  // FIXME: Value shouldn't be set in this case
1422  HI.Value = "10";
1423  }},
1424  {
1425  R"cpp(// Global variable in namespace
1426  namespace ns1 {
1427  static int hey = 10;
1428  }
1429  void foo() {
1430  ns1::[[he^y]]++;
1431  }
1432  )cpp",
1433  [](HoverInfo &HI) {
1434  HI.Name = "hey";
1435  HI.Kind = index::SymbolKind::Variable;
1436  HI.NamespaceScope = "ns1::";
1437  HI.Type = "int";
1438  HI.Definition = "static int hey = 10";
1439  HI.Value = "10";
1440  }},
1441  {
1442  R"cpp(// Field in anonymous struct
1443  static struct {
1444  int hello;
1445  } s;
1446  void foo() {
1447  s.[[he^llo]]++;
1448  }
1449  )cpp",
1450  [](HoverInfo &HI) {
1451  HI.Name = "hello";
1452  HI.Kind = index::SymbolKind::Field;
1453  HI.NamespaceScope = "";
1454  HI.LocalScope = "(anonymous struct)::";
1455  HI.Type = "int";
1456  HI.Definition = "int hello";
1457  }},
1458  {
1459  R"cpp(// Templated function
1460  template <typename T>
1461  T foo() {
1462  return 17;
1463  }
1464  void g() { auto x = [[f^oo]]<int>(); }
1465  )cpp",
1466  [](HoverInfo &HI) {
1467  HI.Name = "foo";
1468  HI.Kind = index::SymbolKind::Function;
1469  HI.NamespaceScope = "";
1470  HI.Type = "int ()";
1471  HI.Definition = "template <> int foo<int>()";
1472  HI.Documentation = "Templated function";
1473  HI.ReturnType = "int";
1474  HI.Parameters = std::vector<HoverInfo::Param>{};
1475  // FIXME: We should populate template parameters with arguments in
1476  // case of instantiations.
1477  }},
1478  {
1479  R"cpp(// Anonymous union
1480  struct outer {
1481  union {
1482  int abc, def;
1483  } v;
1484  };
1485  void g() { struct outer o; o.v.[[d^ef]]++; }
1486  )cpp",
1487  [](HoverInfo &HI) {
1488  HI.Name = "def";
1489  HI.Kind = index::SymbolKind::Field;
1490  HI.NamespaceScope = "";
1491  HI.LocalScope = "outer::(anonymous union)::";
1492  HI.Type = "int";
1493  HI.Definition = "int def";
1494  }},
1495  {
1496  R"cpp(// documentation from index
1497  int nextSymbolIsAForwardDeclFromIndexWithNoLocalDocs;
1498  void indexSymbol();
1499  void g() { [[ind^exSymbol]](); }
1500  )cpp",
1501  [](HoverInfo &HI) {
1502  HI.Name = "indexSymbol";
1503  HI.Kind = index::SymbolKind::Function;
1504  HI.NamespaceScope = "";
1505  HI.Type = "void ()";
1506  HI.Definition = "void indexSymbol()";
1507  HI.ReturnType = "void";
1508  HI.Parameters = std::vector<HoverInfo::Param>{};
1509  HI.Documentation = "comment from index";
1510  }},
1511  {
1512  R"cpp(// Simple initialization with auto
1513  void foo() {
1514  ^[[auto]] i = 1;
1515  }
1516  )cpp",
1517  [](HoverInfo &HI) {
1518  HI.Name = "int";
1519  // FIXME: Should be Builtin/Integral.
1520  HI.Kind = index::SymbolKind::Unknown;
1521  }},
1522  {
1523  R"cpp(// Simple initialization with const auto
1524  void foo() {
1525  const ^[[auto]] i = 1;
1526  }
1527  )cpp",
1528  [](HoverInfo &HI) { HI.Name = "int"; }},
1529  {
1530  R"cpp(// Simple initialization with const auto&
1531  void foo() {
1532  const ^[[auto]]& i = 1;
1533  }
1534  )cpp",
1535  [](HoverInfo &HI) { HI.Name = "int"; }},
1536  {
1537  R"cpp(// Simple initialization with auto&
1538  void foo() {
1539  int x;
1540  ^[[auto]]& i = x;
1541  }
1542  )cpp",
1543  [](HoverInfo &HI) { HI.Name = "int"; }},
1544  {
1545  R"cpp(// Simple initialization with auto*
1546  void foo() {
1547  int a = 1;
1548  ^[[auto]]* i = &a;
1549  }
1550  )cpp",
1551  [](HoverInfo &HI) { HI.Name = "int"; }},
1552  {
1553  R"cpp(// Auto with initializer list.
1554  namespace std
1555  {
1556  template<class _E>
1557  class initializer_list {};
1558  }
1559  void foo() {
1560  ^[[auto]] i = {1,2};
1561  }
1562  )cpp",
1563  [](HoverInfo &HI) {
1564  HI.Name = "initializer_list<int>";
1565  HI.Kind = index::SymbolKind::Class;
1566  }},
1567  {
1568  R"cpp(// User defined conversion to auto
1569  struct Bar {
1570  operator ^[[auto]]() const { return 10; }
1571  };
1572  )cpp",
1573  [](HoverInfo &HI) { HI.Name = "int"; }},
1574  {
1575  R"cpp(// Simple initialization with decltype(auto)
1576  void foo() {
1577  ^[[decltype]](auto) i = 1;
1578  }
1579  )cpp",
1580  [](HoverInfo &HI) { HI.Name = "int"; }},
1581  {
1582  R"cpp(// Simple initialization with const decltype(auto)
1583  void foo() {
1584  const int j = 0;
1585  ^[[decltype]](auto) i = j;
1586  }
1587  )cpp",
1588  [](HoverInfo &HI) { HI.Name = "const int"; }},
1589  {
1590  R"cpp(// Simple initialization with const& decltype(auto)
1591  void foo() {
1592  int k = 0;
1593  const int& j = k;
1594  ^[[decltype]](auto) i = j;
1595  }
1596  )cpp",
1597  [](HoverInfo &HI) { HI.Name = "const int &"; }},
1598  {
1599  R"cpp(// Simple initialization with & decltype(auto)
1600  void foo() {
1601  int k = 0;
1602  int& j = k;
1603  ^[[decltype]](auto) i = j;
1604  }
1605  )cpp",
1606  [](HoverInfo &HI) { HI.Name = "int &"; }},
1607  {
1608  R"cpp(// simple trailing return type
1609  ^[[auto]] main() -> int {
1610  return 0;
1611  }
1612  )cpp",
1613  [](HoverInfo &HI) { HI.Name = "int"; }},
1614  {
1615  R"cpp(// auto function return with trailing type
1616  struct Bar {};
1617  ^[[auto]] test() -> decltype(Bar()) {
1618  return Bar();
1619  }
1620  )cpp",
1621  [](HoverInfo &HI) {
1622  HI.Name = "Bar";
1623  HI.Kind = index::SymbolKind::Struct;
1624  HI.Documentation = "auto function return with trailing type";
1625  }},
1626  {
1627  R"cpp(// trailing return type
1628  struct Bar {};
1629  auto test() -> ^[[decltype]](Bar()) {
1630  return Bar();
1631  }
1632  )cpp",
1633  [](HoverInfo &HI) {
1634  HI.Name = "Bar";
1635  HI.Kind = index::SymbolKind::Struct;
1636  HI.Documentation = "trailing return type";
1637  }},
1638  {
1639  R"cpp(// auto in function return
1640  struct Bar {};
1641  ^[[auto]] test() {
1642  return Bar();
1643  }
1644  )cpp",
1645  [](HoverInfo &HI) {
1646  HI.Name = "Bar";
1647  HI.Kind = index::SymbolKind::Struct;
1648  HI.Documentation = "auto in function return";
1649  }},
1650  {
1651  R"cpp(// auto& in function return
1652  struct Bar {};
1653  ^[[auto]]& test() {
1654  static Bar x;
1655  return x;
1656  }
1657  )cpp",
1658  [](HoverInfo &HI) {
1659  HI.Name = "Bar";
1660  HI.Kind = index::SymbolKind::Struct;
1661  HI.Documentation = "auto& in function return";
1662  }},
1663  {
1664  R"cpp(// auto* in function return
1665  struct Bar {};
1666  ^[[auto]]* test() {
1667  Bar* bar;
1668  return bar;
1669  }
1670  )cpp",
1671  [](HoverInfo &HI) {
1672  HI.Name = "Bar";
1673  HI.Kind = index::SymbolKind::Struct;
1674  HI.Documentation = "auto* in function return";
1675  }},
1676  {
1677  R"cpp(// const auto& in function return
1678  struct Bar {};
1679  const ^[[auto]]& test() {
1680  static Bar x;
1681  return x;
1682  }
1683  )cpp",
1684  [](HoverInfo &HI) {
1685  HI.Name = "Bar";
1686  HI.Kind = index::SymbolKind::Struct;
1687  HI.Documentation = "const auto& in function return";
1688  }},
1689  {
1690  R"cpp(// decltype(auto) in function return
1691  struct Bar {};
1692  ^[[decltype]](auto) test() {
1693  return Bar();
1694  }
1695  )cpp",
1696  [](HoverInfo &HI) {
1697  HI.Name = "Bar";
1698  HI.Kind = index::SymbolKind::Struct;
1699  HI.Documentation = "decltype(auto) in function return";
1700  }},
1701  {
1702  R"cpp(// decltype(auto) reference in function return
1703  ^[[decltype]](auto) test() {
1704  static int a;
1705  return (a);
1706  }
1707  )cpp",
1708  [](HoverInfo &HI) { HI.Name = "int &"; }},
1709  {
1710  R"cpp(// decltype lvalue reference
1711  void foo() {
1712  int I = 0;
1713  ^[[decltype]](I) J = I;
1714  }
1715  )cpp",
1716  [](HoverInfo &HI) { HI.Name = "int"; }},
1717  {
1718  R"cpp(// decltype lvalue reference
1719  void foo() {
1720  int I= 0;
1721  int &K = I;
1722  ^[[decltype]](K) J = I;
1723  }
1724  )cpp",
1725  [](HoverInfo &HI) { HI.Name = "int &"; }},
1726  {
1727  R"cpp(// decltype lvalue reference parenthesis
1728  void foo() {
1729  int I = 0;
1730  ^[[decltype]]((I)) J = I;
1731  }
1732  )cpp",
1733  [](HoverInfo &HI) { HI.Name = "int &"; }},
1734  {
1735  R"cpp(// decltype rvalue reference
1736  void foo() {
1737  int I = 0;
1738  ^[[decltype]](static_cast<int&&>(I)) J = static_cast<int&&>(I);
1739  }
1740  )cpp",
1741  [](HoverInfo &HI) { HI.Name = "int &&"; }},
1742  {
1743  R"cpp(// decltype rvalue reference function call
1744  int && bar();
1745  void foo() {
1746  int I = 0;
1747  ^[[decltype]](bar()) J = bar();
1748  }
1749  )cpp",
1750  [](HoverInfo &HI) { HI.Name = "int &&"; }},
1751  {
1752  R"cpp(// decltype of function with trailing return type.
1753  struct Bar {};
1754  auto test() -> decltype(Bar()) {
1755  return Bar();
1756  }
1757  void foo() {
1758  ^[[decltype]](test()) i = test();
1759  }
1760  )cpp",
1761  [](HoverInfo &HI) {
1762  HI.Name = "Bar";
1763  HI.Kind = index::SymbolKind::Struct;
1764  HI.Documentation =
1765  "decltype of function with trailing return type.";
1766  }},
1767  {
1768  R"cpp(// decltype of var with decltype.
1769  void foo() {
1770  int I = 0;
1771  decltype(I) J = I;
1772  ^[[decltype]](J) K = J;
1773  }
1774  )cpp",
1775  [](HoverInfo &HI) { HI.Name = "int"; }},
1776  {
1777  R"cpp(// More complicated structured types.
1778  int bar();
1779  ^[[auto]] (*foo)() = bar;
1780  )cpp",
1781  [](HoverInfo &HI) { HI.Name = "int"; }},
1782  {
1783  R"cpp(// Should not crash when evaluating the initializer.
1784  struct Test {};
1785  void test() { Test && [[te^st]] = {}; }
1786  )cpp",
1787  [](HoverInfo &HI) {
1788  HI.Name = "test";
1789  HI.Kind = index::SymbolKind::Variable;
1790  HI.NamespaceScope = "";
1791  HI.LocalScope = "test::";
1792  HI.Type = "struct Test &&";
1793  HI.Definition = "Test &&test = {}";
1794  }},
1795  {
1796  R"cpp(// auto on alias
1797  typedef int int_type;
1798  ^[[auto]] x = int_type();
1799  )cpp",
1800  [](HoverInfo &HI) { HI.Name = "int"; }},
1801  {
1802  R"cpp(// auto on alias
1803  struct cls {};
1804  typedef cls cls_type;
1805  ^[[auto]] y = cls_type();
1806  )cpp",
1807  [](HoverInfo &HI) {
1808  HI.Name = "cls";
1809  HI.Kind = index::SymbolKind::Struct;
1810  HI.Documentation = "auto on alias";
1811  }},
1812  {
1813  R"cpp(// auto on alias
1814  template <class>
1815  struct templ {};
1816  ^[[auto]] z = templ<int>();
1817  )cpp",
1818  [](HoverInfo &HI) {
1819  HI.Name = "templ<int>";
1820  HI.Kind = index::SymbolKind::Struct;
1821  HI.Documentation = "auto on alias";
1822  }},
1823  {
1824  R"cpp(// should not crash.
1825  template <class T> struct cls {
1826  int method();
1827  };
1828 
1829  auto test = cls<int>().[[m^ethod]]();
1830  )cpp",
1831  [](HoverInfo &HI) {
1832  HI.Definition = "int method()";
1833  HI.Kind = index::SymbolKind::InstanceMethod;
1834  HI.NamespaceScope = "";
1835  HI.LocalScope = "cls<int>::";
1836  HI.Name = "method";
1837  HI.Parameters.emplace();
1838  HI.ReturnType = "int";
1839  HI.Type = "int ()";
1840  }},
1841  {
1842  R"cpp(// type of nested templates.
1843  template <class T> struct cls {};
1844  cls<cls<cls<int>>> [[fo^o]];
1845  )cpp",
1846  [](HoverInfo &HI) {
1847  HI.Definition = "cls<cls<cls<int>>> foo";
1848  HI.Kind = index::SymbolKind::Variable;
1849  HI.NamespaceScope = "";
1850  HI.Name = "foo";
1851  HI.Type = "cls<cls<cls<int>>>";
1852  }},
1853  {
1854  R"cpp(// type of nested templates.
1855  template <class T> struct cls {};
1856  [[cl^s]]<cls<cls<int>>> foo;
1857  )cpp",
1858  [](HoverInfo &HI) {
1859  HI.Definition = "template <> struct cls<cls<cls<int>>> {}";
1860  HI.Kind = index::SymbolKind::Struct;
1861  HI.NamespaceScope = "";
1862  HI.Name = "cls<cls<cls<int>>>";
1863  HI.Documentation = "type of nested templates.";
1864  }},
1865  {
1866  R"cpp(// type with decltype
1867  int a;
1868  decltype(a) [[b^]] = a;)cpp",
1869  [](HoverInfo &HI) {
1870  HI.Definition = "decltype(a) b = a";
1871  HI.Kind = index::SymbolKind::Variable;
1872  HI.NamespaceScope = "";
1873  HI.Name = "b";
1874  HI.Type = "int";
1875  }},
1876  {
1877  R"cpp(// type with decltype
1878  int a;
1879  decltype(a) c;
1880  decltype(c) [[b^]] = a;)cpp",
1881  [](HoverInfo &HI) {
1882  HI.Definition = "decltype(c) b = a";
1883  HI.Kind = index::SymbolKind::Variable;
1884  HI.NamespaceScope = "";
1885  HI.Name = "b";
1886  HI.Type = "int";
1887  }},
1888  {
1889  R"cpp(// type with decltype
1890  int a;
1891  const decltype(a) [[b^]] = a;)cpp",
1892  [](HoverInfo &HI) {
1893  HI.Definition = "const decltype(a) b = a";
1894  HI.Kind = index::SymbolKind::Variable;
1895  HI.NamespaceScope = "";
1896  HI.Name = "b";
1897  HI.Type = "int";
1898  }},
1899  {
1900  R"cpp(// type with decltype
1901  int a;
1902  auto [[f^oo]](decltype(a) x) -> decltype(a) { return 0; })cpp",
1903  [](HoverInfo &HI) {
1904  HI.Definition = "auto foo(decltype(a) x) -> decltype(a)";
1905  HI.Kind = index::SymbolKind::Function;
1906  HI.NamespaceScope = "";
1907  HI.Name = "foo";
1908  // FIXME: Handle composite types with decltype with a printing
1909  // policy.
1910  HI.Type = "auto (decltype(a)) -> decltype(a)";
1911  HI.ReturnType = "int";
1912  HI.Parameters = {
1913  {std::string("int"), std::string("x"), llvm::None}};
1914  }},
1915  {
1916  R"cpp(// sizeof expr
1917  void foo() {
1918  (void)[[size^of]](char);
1919  })cpp",
1920  [](HoverInfo &HI) {
1921  HI.Name = "expression";
1922  HI.Type = "unsigned long";
1923  HI.Value = "1";
1924  }},
1925  {
1926  R"cpp(// alignof expr
1927  void foo() {
1928  (void)[[align^of]](char);
1929  })cpp",
1930  [](HoverInfo &HI) {
1931  HI.Name = "expression";
1932  HI.Type = "unsigned long";
1933  HI.Value = "1";
1934  }},
1935  {
1936  R"cpp(
1937  template <typename T = int>
1938  void foo(const T& = T()) {
1939  [[f^oo]]<>(3);
1940  })cpp",
1941  [](HoverInfo &HI) {
1942  HI.Name = "foo";
1943  HI.Kind = index::SymbolKind::Function;
1944  HI.Type = "void (const int &)";
1945  HI.ReturnType = "void";
1946  HI.Parameters = {
1947  {std::string("const int &"), llvm::None, std::string("T()")}};
1948  HI.Definition = "template <> void foo<int>(const int &)";
1949  HI.NamespaceScope = "";
1950  }},
1951  {
1952  R"cpp(// should not crash
1953  @interface ObjC {
1954  char [[da^ta]];
1955  }@end
1956  )cpp",
1957  [](HoverInfo &HI) {
1958  HI.Name = "data";
1959  HI.Type = "char";
1960  HI.Kind = index::SymbolKind::Field;
1961  HI.NamespaceScope = "ObjC::"; // FIXME: fix it
1962  HI.Definition = "char data";
1963  }},
1964  };
1965 
1966  // Create a tiny index, so tests above can verify documentation is fetched.
1967  Symbol IndexSym = func("indexSymbol");
1968  IndexSym.Documentation = "comment from index";
1970  Symbols.insert(IndexSym);
1971  auto Index =
1972  MemIndex::build(std::move(Symbols).build(), RefSlab(), RelationSlab());
1973 
1974  for (const auto &Case : Cases) {
1975  SCOPED_TRACE(Case.Code);
1976 
1977  Annotations T(Case.Code);
1978  TestTU TU = TestTU::withCode(T.code());
1979  TU.ExtraArgs.push_back("-std=c++17");
1980  TU.ExtraArgs.push_back("-xobjective-c++");
1981 
1982  TU.ExtraArgs.push_back("-Wno-gnu-designator");
1983  // Types might be different depending on the target triplet, we chose a
1984  // fixed one to make sure tests passes on different platform.
1985  TU.ExtraArgs.push_back("--target=x86_64-pc-linux-gnu");
1986  auto AST = TU.build();
1987 
1988  auto H = getHover(AST, T.point(), format::getLLVMStyle(), Index.get());
1989  ASSERT_TRUE(H);
1990  HoverInfo Expected;
1991  Expected.SymRange = T.range();
1992  Case.ExpectedBuilder(Expected);
1993 
1994  SCOPED_TRACE(H->present().asPlainText());
1995  EXPECT_EQ(H->NamespaceScope, Expected.NamespaceScope);
1996  EXPECT_EQ(H->LocalScope, Expected.LocalScope);
1997  EXPECT_EQ(H->Name, Expected.Name);
1998  EXPECT_EQ(H->Kind, Expected.Kind);
1999  EXPECT_EQ(H->Documentation, Expected.Documentation);
2000  EXPECT_EQ(H->Definition, Expected.Definition);
2001  EXPECT_EQ(H->Type, Expected.Type);
2002  EXPECT_EQ(H->ReturnType, Expected.ReturnType);
2003  EXPECT_EQ(H->Parameters, Expected.Parameters);
2004  EXPECT_EQ(H->TemplateParameters, Expected.TemplateParameters);
2005  EXPECT_EQ(H->SymRange, Expected.SymRange);
2006  EXPECT_EQ(H->Value, Expected.Value);
2007  }
2008 }
2009 
2010 TEST(Hover, DocsFromIndex) {
2011  Annotations T(R"cpp(
2012  template <typename T> class X {};
2013  void foo() {
2014  au^to t = X<int>();
2015  X^<int> w;
2016  (void)w;
2017  })cpp");
2018 
2019  TestTU TU = TestTU::withCode(T.code());
2020  auto AST = TU.build();
2021  Symbol IndexSym;
2022  IndexSym.ID = *getSymbolID(&findDecl(AST, "X"));
2023  IndexSym.Documentation = "comment from index";
2025  Symbols.insert(IndexSym);
2026  auto Index =
2027  MemIndex::build(std::move(Symbols).build(), RefSlab(), RelationSlab());
2028 
2029  for (const auto &P : T.points()) {
2030  auto H = getHover(AST, P, format::getLLVMStyle(), Index.get());
2031  ASSERT_TRUE(H);
2032  EXPECT_EQ(H->Documentation, IndexSym.Documentation);
2033  }
2034 }
2035 
2036 TEST(Hover, DocsFromAST) {
2037  Annotations T(R"cpp(
2038  // doc
2039  template <typename T> class X {};
2040  // doc
2041  template <typename T> void bar() {}
2042  // doc
2043  template <typename T> T baz;
2044  void foo() {
2045  au^to t = X<int>();
2046  X^<int>();
2047  b^ar<int>();
2048  au^to T = ba^z<X<int>>;
2049  ba^z<int> = 0;
2050  })cpp");
2051 
2052  TestTU TU = TestTU::withCode(T.code());
2053  auto AST = TU.build();
2054  for (const auto &P : T.points()) {
2055  auto H = getHover(AST, P, format::getLLVMStyle(), nullptr);
2056  ASSERT_TRUE(H);
2057  EXPECT_EQ(H->Documentation, "doc");
2058  }
2059 }
2060 
2061 TEST(Hover, DocsFromMostSpecial) {
2062  Annotations T(R"cpp(
2063  // doc1
2064  template <typename T> class $doc1^X {};
2065  // doc2
2066  template <> class $doc2^X<int> {};
2067  // doc3
2068  template <typename T> class $doc3^X<T*> {};
2069  void foo() {
2070  X$doc1^<char>();
2071  X$doc2^<int>();
2072  X$doc3^<int*>();
2073  })cpp");
2074 
2075  TestTU TU = TestTU::withCode(T.code());
2076  auto AST = TU.build();
2077  for (auto Comment : {"doc1", "doc2", "doc3"}) {
2078  for (const auto &P : T.points(Comment)) {
2079  auto H = getHover(AST, P, format::getLLVMStyle(), nullptr);
2080  ASSERT_TRUE(H);
2081  EXPECT_EQ(H->Documentation, Comment);
2082  }
2083  }
2084 }
2085 
2086 TEST(Hover, Present) {
2087  struct {
2088  const std::function<void(HoverInfo &)> Builder;
2089  llvm::StringRef ExpectedRender;
2090  } Cases[] = {
2091  {
2092  [](HoverInfo &HI) {
2093  HI.Kind = index::SymbolKind::Unknown;
2094  HI.Name = "X";
2095  },
2096  R"(X)",
2097  },
2098  {
2099  [](HoverInfo &HI) {
2100  HI.Kind = index::SymbolKind::NamespaceAlias;
2101  HI.Name = "foo";
2102  },
2103  R"(namespace-alias foo)",
2104  },
2105  {
2106  [](HoverInfo &HI) {
2107  HI.Kind = index::SymbolKind::Class;
2108  HI.Size = 10;
2109  HI.TemplateParameters = {
2110  {std::string("typename"), std::string("T"), llvm::None},
2111  {std::string("typename"), std::string("C"),
2112  std::string("bool")},
2113  };
2114  HI.Documentation = "documentation";
2115  HI.Definition =
2116  "template <typename T, typename C = bool> class Foo {}";
2117  HI.Name = "foo";
2118  HI.NamespaceScope.emplace();
2119  },
2120  R"(class foo
2121 
2122 Size: 10 bytes
2123 documentation
2124 
2125 template <typename T, typename C = bool> class Foo {})",
2126  },
2127  {
2128  [](HoverInfo &HI) {
2129  HI.Kind = index::SymbolKind::Function;
2130  HI.Name = "foo";
2131  HI.Type = "type";
2132  HI.ReturnType = "ret_type";
2133  HI.Parameters.emplace();
2134  HoverInfo::Param P;
2135  HI.Parameters->push_back(P);
2136  P.Type = "type";
2137  HI.Parameters->push_back(P);
2138  P.Name = "foo";
2139  HI.Parameters->push_back(P);
2140  P.Default = "default";
2141  HI.Parameters->push_back(P);
2142  HI.NamespaceScope = "ns::";
2143  HI.Definition = "ret_type foo(params) {}";
2144  },
2145  R"(function foo
2146 
2147 → ret_type
2148 Parameters:
2149 -
2150 - type
2151 - type foo
2152 - type foo = default
2153 
2154 // In namespace ns
2155 ret_type foo(params) {})",
2156  },
2157  {
2158  [](HoverInfo &HI) {
2159  HI.Kind = index::SymbolKind::Field;
2160  HI.LocalScope = "test::Bar::";
2161  HI.Value = "value";
2162  HI.Name = "foo";
2163  HI.Type = "type";
2164  HI.Definition = "def";
2165  HI.Size = 4;
2166  HI.Offset = 12;
2167  },
2168  R"(field foo
2169 
2170 Type: type
2171 Value = value
2172 Offset: 12 bytes
2173 Size: 4 bytes
2174 
2175 // In test::Bar
2176 def)",
2177  },
2178  {
2179  [](HoverInfo &HI) {
2180  HI.Kind = index::SymbolKind::Field;
2181  HI.AccessSpecifier = "public";
2182  HI.Name = "foo";
2183  HI.LocalScope = "test::Bar::";
2184  HI.Definition = "def";
2185  },
2186  R"(field foo
2187 
2188 // In test::Bar
2189 public: def)",
2190  },
2191  {
2192  [](HoverInfo &HI) {
2193  HI.Definition = "int method()";
2194  HI.AccessSpecifier = "protected";
2195  HI.Kind = index::SymbolKind::InstanceMethod;
2196  HI.NamespaceScope = "";
2197  HI.LocalScope = "cls<int>::";
2198  HI.Name = "method";
2199  HI.Parameters.emplace();
2200  HI.ReturnType = "int";
2201  HI.Type = "int ()";
2202  },
2203  R"(instance-method method
2204 
2205 → int
2206 
2207 // In cls<int>
2208 protected: int method())",
2209  },
2210  {
2211  [](HoverInfo &HI) {
2212  HI.Kind = index::SymbolKind::Union;
2213  HI.AccessSpecifier = "private";
2214  HI.Name = "foo";
2215  HI.NamespaceScope = "ns1::";
2216  HI.Definition = "union foo {}";
2217  },
2218  R"(union foo
2219 
2220 // In namespace ns1
2221 private: union foo {})",
2222  },
2223  {
2224  [](HoverInfo &HI) {
2225  HI.Kind = index::SymbolKind::Variable;
2226  HI.Name = "foo";
2227  HI.Definition = "int foo = 3";
2228  HI.LocalScope = "test::Bar::";
2229  HI.Value = "3";
2230  HI.Type = "int";
2231  HI.CalleeArgInfo.emplace();
2232  HI.CalleeArgInfo->Name = "arg_a";
2233  HI.CalleeArgInfo->Type = "int";
2234  HI.CalleeArgInfo->Default = "7";
2235  HI.CallPassType.emplace();
2236  HI.CallPassType->PassBy = PassMode::Value;
2237  HI.CallPassType->Converted = false;
2238  },
2239  R"(variable foo
2240 
2241 Type: int
2242 Value = 3
2243 Passed as arg_a
2244 
2245 // In test::Bar
2246 int foo = 3)",
2247  },
2248  {
2249  [](HoverInfo &HI) {
2250  HI.Kind = index::SymbolKind::Variable;
2251  HI.Name = "foo";
2252  HI.Definition = "int foo = 3";
2253  HI.LocalScope = "test::Bar::";
2254  HI.Value = "3";
2255  HI.Type = "int";
2256  HI.CalleeArgInfo.emplace();
2257  HI.CalleeArgInfo->Name = "arg_a";
2258  HI.CalleeArgInfo->Type = "int";
2259  HI.CalleeArgInfo->Default = "7";
2260  HI.CallPassType.emplace();
2261  HI.CallPassType->PassBy = PassMode::Ref;
2262  HI.CallPassType->Converted = false;
2263  },
2264  R"(variable foo
2265 
2266 Type: int
2267 Value = 3
2268 Passed by reference as arg_a
2269 
2270 // In test::Bar
2271 int foo = 3)",
2272  },
2273  {
2274  [](HoverInfo &HI) {
2275  HI.Kind = index::SymbolKind::Variable;
2276  HI.Name = "foo";
2277  HI.Definition = "int foo = 3";
2278  HI.LocalScope = "test::Bar::";
2279  HI.Value = "3";
2280  HI.Type = "int";
2281  HI.CalleeArgInfo.emplace();
2282  HI.CalleeArgInfo->Name = "arg_a";
2283  HI.CalleeArgInfo->Type = "int";
2284  HI.CalleeArgInfo->Default = "7";
2285  HI.CallPassType.emplace();
2286  HI.CallPassType->PassBy = PassMode::Value;
2287  HI.CallPassType->Converted = true;
2288  },
2289  R"(variable foo
2290 
2291 Type: int
2292 Value = 3
2293 Passed as arg_a (converted to int)
2294 
2295 // In test::Bar
2296 int foo = 3)",
2297  },
2298  {
2299  [](HoverInfo &HI) {
2300  HI.Kind = index::SymbolKind::Variable;
2301  HI.Name = "foo";
2302  HI.Definition = "int foo = 3";
2303  HI.LocalScope = "test::Bar::";
2304  HI.Value = "3";
2305  HI.Type = "int";
2306  HI.CalleeArgInfo.emplace();
2307  HI.CalleeArgInfo->Name = "arg_a";
2308  HI.CalleeArgInfo->Type = "int";
2309  HI.CalleeArgInfo->Default = "7";
2310  HI.CallPassType.emplace();
2311  HI.CallPassType->PassBy = PassMode::ConstRef;
2312  HI.CallPassType->Converted = true;
2313  },
2314  R"(variable foo
2315 
2316 Type: int
2317 Value = 3
2318 Passed by const reference as arg_a (converted to int)
2319 
2320 // In test::Bar
2321 int foo = 3)",
2322  }};
2323 
2324  for (const auto &C : Cases) {
2325  HoverInfo HI;
2326  C.Builder(HI);
2327  EXPECT_EQ(HI.present().asPlainText(), C.ExpectedRender);
2328  }
2329 }
2330 
2331 TEST(Hover, ParseDocumentation) {
2332  struct Case {
2333  llvm::StringRef Documentation;
2334  llvm::StringRef ExpectedRenderMarkdown;
2335  llvm::StringRef ExpectedRenderPlainText;
2336  } Cases[] = {{
2337  " \n foo\nbar",
2338  "foo bar",
2339  "foo bar",
2340  },
2341  {
2342  "foo\nbar \n ",
2343  "foo bar",
2344  "foo bar",
2345  },
2346  {
2347  "foo \nbar",
2348  "foo bar",
2349  "foo bar",
2350  },
2351  {
2352  "foo \nbar",
2353  "foo bar",
2354  "foo bar",
2355  },
2356  {
2357  "foo\n\n\nbar",
2358  "foo \nbar",
2359  "foo\nbar",
2360  },
2361  {
2362  "foo\n\n\n\tbar",
2363  "foo \nbar",
2364  "foo\nbar",
2365  },
2366  {
2367  "foo\n\n\n bar",
2368  "foo \nbar",
2369  "foo\nbar",
2370  },
2371  {
2372  "foo.\nbar",
2373  "foo. \nbar",
2374  "foo.\nbar",
2375  },
2376  {
2377  "foo. \nbar",
2378  "foo. \nbar",
2379  "foo.\nbar",
2380  },
2381  {
2382  "foo\n*bar",
2383  "foo \n\\*bar",
2384  "foo\n*bar",
2385  },
2386  {
2387  "foo\nbar",
2388  "foo bar",
2389  "foo bar",
2390  },
2391  {
2392  "Tests primality of `p`.",
2393  "Tests primality of `p`.",
2394  "Tests primality of `p`.",
2395  },
2396  {
2397  "'`' should not occur in `Code`",
2398  "'\\`' should not occur in `Code`",
2399  "'`' should not occur in `Code`",
2400  },
2401  {
2402  "`not\nparsed`",
2403  "\\`not parsed\\`",
2404  "`not parsed`",
2405  }};
2406 
2407  for (const auto &C : Cases) {
2408  markup::Document Output;
2409  parseDocumentation(C.Documentation, Output);
2410 
2411  EXPECT_EQ(Output.asMarkdown(), C.ExpectedRenderMarkdown);
2412  EXPECT_EQ(Output.asPlainText(), C.ExpectedRenderPlainText);
2413  }
2414 }
2415 
2416 // This is a separate test as headings don't create any differences in plaintext
2417 // mode.
2418 TEST(Hover, PresentHeadings) {
2419  HoverInfo HI;
2420  HI.Kind = index::SymbolKind::Variable;
2421  HI.Name = "foo";
2422 
2423  EXPECT_EQ(HI.present().asMarkdown(), "### variable `foo`");
2424 }
2425 
2426 // This is a separate test as rulers behave differently in markdown vs
2427 // plaintext.
2428 TEST(Hover, PresentRulers) {
2429  HoverInfo HI;
2430  HI.Kind = index::SymbolKind::Variable;
2431  HI.Name = "foo";
2432  HI.Value = "val";
2433  HI.Definition = "def";
2434 
2435  llvm::StringRef ExpectedMarkdown = R"md(### variable `foo`
2436 
2437 ---
2438 Value = `val`
2439 
2440 ---
2441 ```cpp
2442 def
2443 ```)md";
2444  EXPECT_EQ(HI.present().asMarkdown(), ExpectedMarkdown);
2445 
2446  llvm::StringRef ExpectedPlaintext = R"pt(variable foo
2447 
2448 Value = val
2449 
2450 def)pt";
2451  EXPECT_EQ(HI.present().asPlainText(), ExpectedPlaintext);
2452 }
2453 } // namespace
2454 } // namespace clangd
2455 } // namespace clang
clang::clangd::TestTU::ExtraArgs
std::vector< std::string > ExtraArgs
Definition: TestTU.h:59
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
Expected
std::vector< const char * > Expected
Definition: PrintASTTests.cpp:27
TestTU.h
clang::clangd::getHover
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:783
clang::clangd::TextDocumentSyncKind::None
Documents should not be synced at all.
clang::clangd::func
Symbol func(llvm::StringRef Name)
Definition: TestIndex.cpp:60
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
Hover.h
Code
std::string Code
Definition: FindTargetTests.cpp:67
MemIndex.h
Builder
CodeCompletionBuilder Builder
Definition: CodeCompletionStringsTests.cpp:35
clang::clangd::MemIndex::build
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
clang::clangd::TestTU::withCode
static TestTU withCode(llvm::StringRef Code)
Definition: TestTU.h:35
Annotations.h
Output
std::string Output
Definition: TraceTests.cpp:161
Index
const SymbolIndex * Index
Definition: Dexp.cpp:95
TestIndex.h
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
Symbols
SymbolSlab Symbols
Definition: SymbolCollectorTests.cpp:295
clang::clangd::HoverInfo::PassType::PassMode
PassMode
Definition: Hover.h:85
clang::clangd::parseDocumentation
void parseDocumentation(llvm::StringRef Input, markup::Document &Output)
Definition: Hover.cpp:1016
clang::clangd::getSymbolID
llvm::Optional< SymbolID > getSymbolID(const Decl *D)
Gets the symbol ID for a declaration, if possible.
Definition: AST.cpp:285
clang::clangd::CompletionItemKind::Value
AST.h