xref: /llvm-project/clang-tools-extra/clangd/unittests/tweaks/ExpandDeducedTypeTests.cpp (revision 1feb7af046889728233e67e3163ab30020207bb2)
1 //===-- ExpandDeducedTypeTests.cpp ------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "TweakTesting.h"
10 #include "gmock/gmock.h"
11 #include "gtest/gtest.h"
12 
13 using ::testing::StartsWith;
14 
15 namespace clang {
16 namespace clangd {
17 namespace {
18 
19 TWEAK_TEST(ExpandDeducedType);
20 
TEST_F(ExpandDeducedTypeTest,Test)21 TEST_F(ExpandDeducedTypeTest, Test) {
22   Header = R"cpp(
23     namespace ns {
24       struct Class {
25         struct Nested {};
26       };
27       void Func();
28     }
29     inline namespace inl_ns {
30       namespace {
31         struct Visible {};
32       }
33     }
34   )cpp";
35 
36   EXPECT_AVAILABLE("^a^u^t^o^ i = 0;");
37   EXPECT_UNAVAILABLE("auto ^i^ ^=^ ^0^;^");
38 
39   // check primitive type
40   EXPECT_EQ(apply("[[auto]] i = 0;"), "int i = 0;");
41   EXPECT_EQ(apply("au^to i = 0;"), "int i = 0;");
42   // check classes and namespaces
43   EXPECT_EQ(apply("^auto C = ns::Class::Nested();"),
44             "ns::Class::Nested C = ns::Class::Nested();");
45   // check that namespaces are shortened
46   EXPECT_EQ(apply("namespace ns { void f() { ^auto C = Class(); } }"),
47             "namespace ns { void f() { Class C = Class(); } }");
48   // undefined functions should not be replaced
49   EXPECT_THAT(apply("au^to x = doesnt_exist(); // error-ok"),
50               StartsWith("fail: Could not deduce type for 'auto' type"));
51   // function pointers should not be replaced
52   EXPECT_THAT(apply("au^to x = &ns::Func;"),
53               StartsWith("fail: Could not expand type"));
54   // function references should not be replaced
55   EXPECT_THAT(apply("au^to &x = ns::Func;"),
56               StartsWith("fail: Could not expand type"));
57   // lambda types are not replaced
58   EXPECT_UNAVAILABLE("au^to x = []{};");
59   // inline namespaces
60   EXPECT_EQ(apply("au^to x = inl_ns::Visible();"),
61             "inl_ns::Visible x = inl_ns::Visible();");
62   // local class
63   EXPECT_EQ(apply("namespace x { void y() { struct S{}; ^auto z = S(); } }"),
64             "namespace x { void y() { struct S{}; S z = S(); } }");
65   // replace pointers
66   EXPECT_EQ(apply(R"cpp(au^to x = "test";)cpp"),
67             R"cpp(const char * x = "test";)cpp");
68   // pointers to an array are not replaced
69   EXPECT_THAT(apply(R"cpp(au^to s = &"foobar";)cpp"),
70               StartsWith("fail: Could not expand type"));
71 
72   EXPECT_EQ(apply("ns::Class * foo() { au^to c = foo(); }"),
73             "ns::Class * foo() { ns::Class * c = foo(); }");
74   EXPECT_EQ(
75       apply("void ns::Func() { au^to x = new ns::Class::Nested{}; }"),
76       "void ns::Func() { ns::Class::Nested * x = new ns::Class::Nested{}; }");
77 
78   EXPECT_EQ(apply("dec^ltype(auto) x = 10;"), "int x = 10;");
79   EXPECT_EQ(apply("decltype(au^to) x = 10;"), "int x = 10;");
80   // references to array types are not replaced
81   EXPECT_THAT(apply(R"cpp(decl^type(auto) s = "foobar"; // error-ok)cpp"),
82               StartsWith("fail: Could not expand type"));
83   // array types are not replaced
84   EXPECT_THAT(apply("int arr[10]; decl^type(auto) foobar = arr; // error-ok"),
85               StartsWith("fail: Could not expand type"));
86   // pointers to an array are not replaced
87   EXPECT_THAT(apply(R"cpp(decl^type(auto) s = &"foobar";)cpp"),
88               StartsWith("fail: Could not expand type"));
89   // expanding types in structured bindings is syntactically invalid.
90   EXPECT_UNAVAILABLE("const ^auto &[x,y] = (int[]){1,2};");
91 
92   // unknown types in a template should not be replaced
93   EXPECT_THAT(apply("template <typename T> void x() { ^auto y = T::z(); }"),
94               StartsWith("fail: Could not deduce type for 'auto' type"));
95 
96   // check primitive type
97   EXPECT_EQ(apply("decl^type(0) i;"), "int i;");
98   // function should not be replaced
99   EXPECT_THAT(apply("void f(); decl^type(f) g;"),
100               StartsWith("fail: Could not expand type"));
101   // check return type in function proto
102   EXPECT_EQ(apply("decl^type(0) f();"), "int f();");
103   // check trailing return type
104   EXPECT_EQ(apply("auto f() -> decl^type(0) { return 0; }"),
105             "auto f() -> int { return 0; }");
106   // check function parameter type
107   EXPECT_EQ(apply("void f(decl^type(0));"), "void f(int);");
108   // check template parameter type
109   EXPECT_EQ(apply("template <decl^type(0)> struct Foobar {};"),
110             "template <int> struct Foobar {};");
111   // check default template argument
112   EXPECT_EQ(apply("template <class = decl^type(0)> class Foo {};"),
113             "template <class = int> class Foo {};");
114   // check template argument
115   EXPECT_EQ(apply("template <class> class Bar {}; Bar<decl^type(0)> b;"),
116             "template <class> class Bar {}; Bar<int> b;");
117   // dependent types are not replaced
118   EXPECT_THAT(apply("template <class T> struct Foobar { decl^type(T{}) t; };"),
119               StartsWith("fail: Could not expand a dependent type"));
120   // references to array types are not replaced
121   EXPECT_THAT(apply(R"cpp(decl^type("foobar") s; // error-ok)cpp"),
122               StartsWith("fail: Could not expand type"));
123   // array types are not replaced
124   EXPECT_THAT(apply("int arr[10]; decl^type(arr) foobar;"),
125               StartsWith("fail: Could not expand type"));
126   // pointers to an array are not replaced
127   EXPECT_THAT(apply(R"cpp(decl^type(&"foobar") s;)cpp"),
128               StartsWith("fail: Could not expand type"));
129 
130   ExtraArgs.push_back("-std=c++20");
131   EXPECT_UNAVAILABLE("template <au^to X> class Y;");
132 
133   EXPECT_THAT(apply("auto X = [](^auto){};"),
134               StartsWith("fail: Could not deduce"));
135   EXPECT_EQ(apply("auto X = [](^auto){return 0;}; int Y = X(42);"),
136             "auto X = [](int){return 0;}; int Y = X(42);");
137   EXPECT_THAT(apply("auto X = [](^auto){return 0;}; int Y = X(42) + X('c');"),
138               StartsWith("fail: Could not deduce"));
139   // FIXME: should work on constrained auto params, once SourceRange is fixed.
140   EXPECT_UNAVAILABLE("template<class> concept C = true;"
141                      "auto X = [](C ^auto *){return 0;};");
142 
143   // lambda should not be replaced
144   EXPECT_UNAVAILABLE("auto f = [](){}; decl^type(f) g;");
145   EXPECT_UNAVAILABLE("decl^type([]{}) f;");
146 }
147 
148 } // namespace
149 } // namespace clangd
150 } // namespace clang
151