16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/Support/ScopedPrinter.h"
18 #include "gmock/gmock.h"
19 #include "gtest/gtest.h"
26 return Stream << Hint.
label <<
"@" << Hint.
range;
31 using ::testing::ElementsAre;
32 using ::testing::IsEmpty;
35 std::vector<InlayHint> Result;
36 for (
auto &Hint :
inlayHints(AST, llvm::None)) {
37 if (Hint.kind ==
Kind)
38 Result.push_back(Hint);
50 friend llvm::raw_ostream &
operator<<(llvm::raw_ostream &Stream,
51 const ExpectedHint &Hint) {
52 return Stream << Hint.Label <<
"@$" << Hint.RangeName;
57 llvm::StringRef ExpectedView(
Expected.Label);
58 if (arg.label != ExpectedView.trim(
" ") ||
59 arg.paddingLeft != ExpectedView.startswith(
" ") ||
60 arg.paddingRight != ExpectedView.endswith(
" ")) {
61 *result_listener <<
"label is '" << arg.label <<
"'";
65 *result_listener <<
"range is " << llvm::to_string(arg.range) <<
" but $"
77 C.InlayHints.Parameters =
false;
78 C.InlayHints.DeducedTypes =
false;
79 C.InlayHints.Designators =
false;
83 template <
typename... ExpectedHints>
86 Annotations Source(AnnotatedSource);
88 TU.ExtraArgs.push_back(
"-std=c++20");
89 auto AST = TU.
build();
91 EXPECT_THAT(hintsOfKind(AST,
Kind),
92 ElementsAre(HintMatcher(
Expected, Source)...));
95 WithContextValue WithCfg(
Config::Key, noHintsConfig());
96 EXPECT_THAT(
inlayHints(AST, llvm::None), IsEmpty());
100 template <
typename... T>
void ignore(T &&...) {}
102 template <
typename... ExpectedHints>
103 void assertParameterHints(llvm::StringRef AnnotatedSource,
109 template <
typename... ExpectedHints>
110 void assertTypeHints(llvm::StringRef AnnotatedSource,
116 template <
typename... ExpectedHints>
117 void assertDesignatorHints(llvm::StringRef AnnotatedSource,
121 WithContextValue WithCfg(
Config::Key, std::move(Cfg));
125 TEST(ParameterHints, Smoke) {
126 assertParameterHints(R
"cpp(
132 ExpectedHint{"param: ",
"param"});
135 TEST(ParameterHints, NoName) {
137 assertParameterHints(R
"cpp(
145 TEST(ParameterHints, NoNameConstReference) {
147 assertParameterHints(R
"cpp(
148 void foo(const int&);
155 TEST(ParameterHints, NoNameReference) {
157 assertParameterHints(R
"cpp(
164 ExpectedHint{"&: ",
"param"});
167 TEST(ParameterHints, NoNameRValueReference) {
169 assertParameterHints(R
"cpp(
177 TEST(ParameterHints, NameInDefinition) {
179 assertParameterHints(R
"cpp(
184 void foo(int param) {};
186 ExpectedHint{"param: ",
"param"});
189 TEST(ParameterHints, NameMismatch) {
191 assertParameterHints(R
"cpp(
196 void foo(int bad) {};
198 ExpectedHint{"good: ",
"good"});
201 TEST(ParameterHints, NameConstReference) {
203 assertParameterHints(R
"cpp(
204 void foo(const int& param);
209 ExpectedHint{"param: ",
"param"});
212 TEST(ParameterHints, NameTypeAliasConstReference) {
214 assertParameterHints(R
"cpp(
215 using alias = const int&;
216 void foo(alias param);
222 ExpectedHint{"param: ",
"param"});
225 TEST(ParameterHints, NameReference) {
227 assertParameterHints(R
"cpp(
228 void foo(int& param);
234 ExpectedHint{"¶m: ",
"param"});
237 TEST(ParameterHints, NameTypeAliasReference) {
239 assertParameterHints(R
"cpp(
241 void foo(alias param);
247 ExpectedHint{"¶m: ",
"param"});
250 TEST(ParameterHints, NameRValueReference) {
252 assertParameterHints(R
"cpp(
253 void foo(int&& param);
258 ExpectedHint{"param: ",
"param"});
261 TEST(ParameterHints, Operator) {
263 assertParameterHints(R
"cpp(
265 void operator+(S lhs, S rhs);
278 assertParameterHints(R
"cpp(
280 #define ExpandsToCall() foo(42)
288 assertParameterHints(R
"cpp(
290 void foo(double param);
295 ExpectedHint{"param: ",
"param"});
298 assertParameterHints(R
"cpp(
300 #define ASSERT(expr) if (!expr) abort()
303 ASSERT(foo($param[[42]]) == 0);
306 ExpectedHint{"param: ",
"param"});
309 TEST(ParameterHints, ConstructorParens) {
310 assertParameterHints(R
"cpp(
318 ExpectedHint{"param: ",
"param"});
321 TEST(ParameterHints, ConstructorBraces) {
322 assertParameterHints(R
"cpp(
330 ExpectedHint{"param: ",
"param"});
333 TEST(ParameterHints, ConstructorStdInitList) {
335 assertParameterHints(R
"cpp(
337 template <typename> class initializer_list {};
340 S(std::initializer_list<int> param);
348 TEST(ParameterHints, MemberInit) {
349 assertParameterHints(R"cpp(
355 T() : member($param[[42]]) {}
358 ExpectedHint{"param: ",
"param"});
361 TEST(ParameterHints, ImplicitConstructor) {
362 assertParameterHints(R
"cpp(
368 // Do not show hint for implicit constructor call in argument.
370 // Do not show hint for implicit constructor call in return.
376 TEST(ParameterHints, ArgMatchesParam) {
377 assertParameterHints(R"cpp(
380 static const int param = 42;
384 // Do not show redundant "param: param".
386 // But show it if the argument is qualified.
387 foo($param[[S::param]]);
392 // Do not show "param: param" for member-expr.
397 ExpectedHint{"param: ",
"param"});
400 TEST(ParameterHints, ArgMatchesParamReference) {
401 assertParameterHints(R
"cpp(
402 void foo(int& param);
403 void foo2(const int& param);
406 // show reference hint on mutable reference
407 foo($param[[param]]);
408 // but not on const reference
412 ExpectedHint{"&: ",
"param"});
415 TEST(ParameterHints, LeadingUnderscore) {
416 assertParameterHints(R
"cpp(
417 void foo(int p1, int _p2, int __p3);
419 foo($p1[[41]], $p2[[42]], $p3[[43]]);
422 ExpectedHint{"p1: ",
"p1"}, ExpectedHint{
"p2: ",
"p2"},
423 ExpectedHint{
"p3: ",
"p3"});
426 TEST(ParameterHints, DependentCalls) {
427 assertParameterHints(R
"cpp(
428 template <typename T>
429 void nonmember(T par1);
431 template <typename T>
434 static void static_member(T par3);
437 void overload(int anInt);
438 void overload(double aDouble);
440 template <typename T>
442 void bar(A<T> a, T t) {
443 nonmember($par1[[t]]);
444 a.member($par2[[t]]);
445 A<T>::static_member($par3[[t]]);
446 // We don't want to arbitrarily pick between
447 // "anInt" or "aDouble", so just show no hint.
452 ExpectedHint{"par1: ",
"par1"},
453 ExpectedHint{
"par2: ",
"par2"},
454 ExpectedHint{
"par3: ",
"par3"});
457 TEST(ParameterHints, VariadicFunction) {
458 assertParameterHints(R
"cpp(
459 template <typename... T>
460 void foo(int fixed, T... variadic);
463 foo($fixed[[41]], 42, 43);
466 ExpectedHint{"fixed: ",
"fixed"});
469 TEST(ParameterHints, VarargsFunction) {
470 assertParameterHints(R
"cpp(
471 void foo(int fixed, ...);
474 foo($fixed[[41]], 42, 43);
477 ExpectedHint{"fixed: ",
"fixed"});
480 TEST(ParameterHints, CopyOrMoveConstructor) {
482 assertParameterHints(R
"cpp(
496 TEST(ParameterHints, AggregateInit) {
499 assertParameterHints(R
"cpp(
510 TEST(ParameterHints, UserDefinedLiteral) {
512 assertParameterHints(R
"cpp(
513 long double operator"" _w(long double param);
520 TEST(ParameterHints, ParamNameComment) {
523 assertParameterHints(R
"cpp(
527 foo( /* param = */ 42);
528 foo(/* the answer */$param[[42]]);
531 ExpectedHint{"param: ",
"param"});
534 TEST(ParameterHints, SetterFunctions) {
535 assertParameterHints(R
"cpp(
537 void setParent(S* parent);
538 void set_parent(S* parent);
539 void setTimeout(int timeoutMillis);
540 void setTimeoutMillis(int timeout_millis);
544 // Parameter name matches setter name - omit hint.
545 s.setParent(nullptr);
546 // Support snake_case
547 s.set_parent(nullptr);
548 // Parameter name may contain extra info - show hint.
549 s.setTimeout($timeoutMillis[[120]]);
550 // FIXME: Ideally we'd want to omit this.
551 s.setTimeoutMillis($timeout_millis[[120]]);
554 ExpectedHint{"timeoutMillis: ",
"timeoutMillis"},
555 ExpectedHint{
"timeout_millis: ",
"timeout_millis"});
558 TEST(ParameterHints, BuiltinFunctions) {
560 assertParameterHints(R
"cpp(
561 namespace std { template <typename T> T&& forward(T&); }
569 TEST(ParameterHints, IncludeAtNonGlobalScope) {
570 Annotations FooInc(R"cpp(
571 void bar() { foo(42); }
573 Annotations FooCC(R"cpp(
580 TestWorkspace Workspace;
581 Workspace.addSource("foo.inc", FooInc.code());
582 Workspace.addMainFile(
"foo.cc", FooCC.code());
584 auto AST = Workspace.openFile(
"foo.cc");
585 ASSERT_TRUE(
bool(AST));
591 TEST(TypeHints, Smoke) {
592 assertTypeHints(R
"cpp(
593 auto $waldo[[waldo]] = 42;
595 ExpectedHint{": int",
"waldo"});
598 TEST(TypeHints, Decorations) {
599 assertTypeHints(R
"cpp(
601 auto* $var1[[var1]] = &x;
602 auto&& $var2[[var2]] = x;
603 const auto& $var3[[var3]] = x;
605 ExpectedHint{": int *",
"var1"},
606 ExpectedHint{
": int &",
"var2"},
607 ExpectedHint{
": const int &",
"var3"});
610 TEST(TypeHints, DecltypeAuto) {
611 assertTypeHints(R
"cpp(
614 decltype(auto) $z[[z]] = y;
616 ExpectedHint{": int &",
"z"});
619 TEST(TypeHints, NoQualifiers) {
620 assertTypeHints(R
"cpp(
625 auto $x[[x]] = foo();
628 template <typename T>
631 S2::Inner<int> bar();
632 auto $y[[y]] = bar();
636 ExpectedHint{": S1",
"x"},
643 ExpectedHint{
": S2::Inner<int>",
"y"});
646 TEST(TypeHints, Lambda) {
649 assertTypeHints(R
"cpp(
652 auto $L[[L]] = [cap, $init[[init]] = 1 + 1](int a$ret[[)]] {
653 return a + cap + init;
657 ExpectedHint{": (lambda)",
"L"},
658 ExpectedHint{
": int",
"init"}, ExpectedHint{
"-> int",
"ret"});
662 assertTypeHints(
"auto $L[[x]] = <:$ret[[:>]]{return 42;};",
663 ExpectedHint{
": (lambda)",
"L"},
664 ExpectedHint{
"-> int",
"ret"});
670 TEST(TypeHints, StructuredBindings_PublicStruct) {
671 assertTypeHints(R
"cpp(
672 // Struct with public fields.
678 auto [$x[[x]], $y[[y]]] = foo();
680 ExpectedHint{": int",
"x"}, ExpectedHint{
": int",
"y"});
683 TEST(TypeHints, StructuredBindings_Array) {
684 assertTypeHints(R
"cpp(
686 auto [$x[[x]], $y[[y]]] = arr;
688 ExpectedHint{": int",
"x"}, ExpectedHint{
": int",
"y"});
691 TEST(TypeHints, StructuredBindings_TupleLike) {
692 assertTypeHints(R
"cpp(
699 template <typename T>
700 struct tuple_size {};
702 struct tuple_size<IntPair> {
703 constexpr static unsigned value = 2;
705 template <unsigned I, typename T>
706 struct tuple_element {};
707 template <unsigned I>
708 struct tuple_element<I, IntPair> {
712 template <unsigned I>
713 int get(const IntPair& p) {
714 if constexpr (I == 0) {
716 } else if constexpr (I == 1) {
721 auto [$x[[x]], $y[[y]]] = bar();
723 ExpectedHint{": int",
"x"}, ExpectedHint{
": int",
"y"});
726 TEST(TypeHints, StructuredBindings_NoInitializer) {
727 assertTypeHints(R
"cpp(
728 // No initializer (ill-formed).
729 // Do not show useless "NULL TYPE" hint.
730 auto [x, y]; /*error-ok*/
734 TEST(TypeHints, ReturnTypeDeduction) {
737 auto f1(int x$ret1a[[)]]; // Hint forward declaration too
738 auto f1(int x$ret1b[[)]] { return x + 1; }
740 // Include pointer operators in hint
742 auto& f2($ret2[[)]] { return s; }
744 // Do not hint `auto` for trailing return type.
747 // Do not hint when a trailing return type is specified.
748 auto f4() -> auto* { return "foo"; }
750 auto f5($noreturn[[)]] {}
752 // `auto` conversion operator
754 operator auto($retConv[[)]] { return 42; }
757 // FIXME: Dependent types do not work yet.
758 template <typename T>
760 auto method() { return T(); }
763 ExpectedHint{"-> int",
"ret1a"}, ExpectedHint{
"-> int",
"ret1b"},
764 ExpectedHint{
"-> int &",
"ret2"}, ExpectedHint{
"-> void",
"noreturn"},
765 ExpectedHint{
"-> int",
"retConv"});
768 TEST(TypeHints, DependentType) {
769 assertTypeHints(R
"cpp(
770 template <typename T>
772 // The hint would just be "auto" and we can't do any better.
773 auto var1 = arg.method();
774 // FIXME: It would be nice to show "T" as the hint.
775 auto $var2[[var2]] = arg;
780 TEST(TypeHints, LongTypeName) {
781 assertTypeHints(R"cpp(
782 template <typename, typename, typename>
784 struct MultipleWords {};
785 A<MultipleWords, MultipleWords, MultipleWords> foo();
786 // Omit type hint past a certain length (currently 32)
791 TEST(TypeHints, DefaultTemplateArgs) {
792 assertTypeHints(R"cpp(
793 template <typename, typename = int>
796 auto $var[[var]] = foo();
798 ExpectedHint{": A<float>",
"var"});
801 TEST(TypeHints, Deduplication) {
802 assertTypeHints(R
"cpp(
803 template <typename T>
805 auto $var[[var]] = 42;
807 template void foo<int>();
808 template void foo<float>();
810 ExpectedHint{": int",
"var"});
813 TEST(TypeHints, SinglyInstantiatedTemplate) {
814 assertTypeHints(R
"cpp(
815 auto $lambda[[x]] = [](auto *$param[[y]], auto) { return 42; };
818 ExpectedHint{": (lambda)",
"lambda"},
819 ExpectedHint{
": const char *",
"param"});
822 assertTypeHints(R
"cpp(
823 int x(auto $a[[a]], auto... b, auto c) { return 42; }
824 int m = x<void*, char, float>(nullptr, 'c', 2.0, 2);
826 ExpectedHint{": void *",
"a"});
829 TEST(TypeHints, Aliased) {
833 TU.ExtraArgs.push_back(
"-xc");
834 auto AST = TU.
build();
839 TEST(DesignatorHints, Basic) {
840 assertDesignatorHints(R
"cpp(
841 struct S { int x, y, z; };
842 S s {$x[[1]], $y[[2+2]]};
844 int x[] = {$0[[0]], $1[[1]]};
846 ExpectedHint{".x=",
"x"}, ExpectedHint{
".y=",
"y"},
847 ExpectedHint{
"[0]=",
"0"}, ExpectedHint{
"[1]=",
"1"});
850 TEST(DesignatorHints, Nested) {
851 assertDesignatorHints(R
"cpp(
852 struct Inner { int x, y; };
853 struct Outer { Inner a, b; };
854 Outer o{ $a[[{ $x[[1]], $y[[2]] }]], $bx[[3]] };
856 ExpectedHint{".a=",
"a"}, ExpectedHint{
".x=",
"x"},
857 ExpectedHint{
".y=",
"y"}, ExpectedHint{
".b.x=",
"bx"});
860 TEST(DesignatorHints, AnonymousRecord) {
861 assertDesignatorHints(R
"cpp(
873 ExpectedHint{".x.y=",
"xy"});
876 TEST(DesignatorHints, Suppression) {
877 assertDesignatorHints(R
"cpp(
878 struct Point { int a, b, c, d, e, f, g, h; };
879 Point p{/*a=*/1, .c=2, /* .d = */3, $e[[4]]};
881 ExpectedHint{".e=",
"e"});
884 TEST(DesignatorHints, StdArray) {
887 assertDesignatorHints(R
"cpp(
888 template <typename T, int N> struct Array { T __elements[N]; };
889 Array<int, 2> x = {$0[[0]], $1[[1]]};
891 ExpectedHint{"[0]=",
"0"}, ExpectedHint{
"[1]=",
"1"});
894 TEST(DesignatorHints, OnlyAggregateInit) {
895 assertDesignatorHints(R
"cpp(
896 struct Copyable { int x; } c;
899 struct Constructible { Constructible(int x); };
904 TEST(InlayHints, RestrictRange) {
905 Annotations
Code(R
"cpp(
913 ElementsAre(labelIs(
": int"), labelIs(
": char")));