File: ExpandDeducedTypeTests.cpp

package info (click to toggle)
llvm-toolchain-19 1%3A19.1.7-3~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 1,998,492 kB
  • sloc: cpp: 6,951,680; ansic: 1,486,157; asm: 913,598; python: 232,024; f90: 80,126; objc: 75,281; lisp: 37,276; pascal: 16,990; sh: 10,009; ml: 5,058; perl: 4,724; awk: 3,523; makefile: 3,167; javascript: 2,504; xml: 892; fortran: 664; cs: 573
file content (150 lines) | stat: -rw-r--r-- 6,281 bytes parent folder | download | duplicates (9)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
//===-- ExpandDeducedTypeTests.cpp ------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "TweakTesting.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"

using ::testing::StartsWith;

namespace clang {
namespace clangd {
namespace {

TWEAK_TEST(ExpandDeducedType);

TEST_F(ExpandDeducedTypeTest, Test) {
  Header = R"cpp(
    namespace ns {
      struct Class {
        struct Nested {};
      };
      void Func();
    }
    inline namespace inl_ns {
      namespace {
        struct Visible {};
      }
    }
  )cpp";

  EXPECT_AVAILABLE("^a^u^t^o^ i = 0;");
  EXPECT_UNAVAILABLE("auto ^i^ ^=^ ^0^;^");

  // check primitive type
  EXPECT_EQ(apply("[[auto]] i = 0;"), "int i = 0;");
  EXPECT_EQ(apply("au^to i = 0;"), "int i = 0;");
  // check classes and namespaces
  EXPECT_EQ(apply("^auto C = ns::Class::Nested();"),
            "ns::Class::Nested C = ns::Class::Nested();");
  // check that namespaces are shortened
  EXPECT_EQ(apply("namespace ns { void f() { ^auto C = Class(); } }"),
            "namespace ns { void f() { Class C = Class(); } }");
  // undefined functions should not be replaced
  EXPECT_THAT(apply("au^to x = doesnt_exist(); // error-ok"),
              StartsWith("fail: Could not deduce type for 'auto' type"));
  // function pointers should not be replaced
  EXPECT_THAT(apply("au^to x = &ns::Func;"),
              StartsWith("fail: Could not expand type"));
  // function references should not be replaced
  EXPECT_THAT(apply("au^to &x = ns::Func;"),
              StartsWith("fail: Could not expand type"));
  // lambda types are not replaced
  EXPECT_UNAVAILABLE("au^to x = []{};");
  // inline namespaces
  EXPECT_EQ(apply("au^to x = inl_ns::Visible();"),
            "inl_ns::Visible x = inl_ns::Visible();");
  // local class
  EXPECT_EQ(apply("namespace x { void y() { struct S{}; ^auto z = S(); } }"),
            "namespace x { void y() { struct S{}; S z = S(); } }");
  // replace pointers
  EXPECT_EQ(apply(R"cpp(au^to x = "test";)cpp"),
            R"cpp(const char * x = "test";)cpp");
  // pointers to an array are not replaced
  EXPECT_THAT(apply(R"cpp(au^to s = &"foobar";)cpp"),
              StartsWith("fail: Could not expand type"));

  EXPECT_EQ(apply("ns::Class * foo() { au^to c = foo(); }"),
            "ns::Class * foo() { ns::Class * c = foo(); }");
  EXPECT_EQ(
      apply("void ns::Func() { au^to x = new ns::Class::Nested{}; }"),
      "void ns::Func() { ns::Class::Nested * x = new ns::Class::Nested{}; }");

  EXPECT_EQ(apply("dec^ltype(auto) x = 10;"), "int x = 10;");
  EXPECT_EQ(apply("decltype(au^to) x = 10;"), "int x = 10;");
  // references to array types are not replaced
  EXPECT_THAT(apply(R"cpp(decl^type(auto) s = "foobar"; // error-ok)cpp"),
              StartsWith("fail: Could not expand type"));
  // array types are not replaced
  EXPECT_THAT(apply("int arr[10]; decl^type(auto) foobar = arr; // error-ok"),
              StartsWith("fail: Could not expand type"));
  // pointers to an array are not replaced
  EXPECT_THAT(apply(R"cpp(decl^type(auto) s = &"foobar";)cpp"),
              StartsWith("fail: Could not expand type"));
  // expanding types in structured bindings is syntactically invalid.
  EXPECT_UNAVAILABLE("const ^auto &[x,y] = (int[]){1,2};");

  // unknown types in a template should not be replaced
  EXPECT_THAT(apply("template <typename T> void x() { ^auto y = T::z(); }"),
              StartsWith("fail: Could not deduce type for 'auto' type"));

  // check primitive type
  EXPECT_EQ(apply("decl^type(0) i;"), "int i;");
  // function should not be replaced
  EXPECT_THAT(apply("void f(); decl^type(f) g;"),
              StartsWith("fail: Could not expand type"));
  // check return type in function proto
  EXPECT_EQ(apply("decl^type(0) f();"), "int f();");
  // check trailing return type
  EXPECT_EQ(apply("auto f() -> decl^type(0) { return 0; }"),
            "auto f() -> int { return 0; }");
  // check function parameter type
  EXPECT_EQ(apply("void f(decl^type(0));"), "void f(int);");
  // check template parameter type
  EXPECT_EQ(apply("template <decl^type(0)> struct Foobar {};"),
            "template <int> struct Foobar {};");
  // check default template argument
  EXPECT_EQ(apply("template <class = decl^type(0)> class Foo {};"),
            "template <class = int> class Foo {};");
  // check template argument
  EXPECT_EQ(apply("template <class> class Bar {}; Bar<decl^type(0)> b;"),
            "template <class> class Bar {}; Bar<int> b;");
  // dependent types are not replaced
  EXPECT_THAT(apply("template <class T> struct Foobar { decl^type(T{}) t; };"),
              StartsWith("fail: Could not expand a dependent type"));
  // references to array types are not replaced
  EXPECT_THAT(apply(R"cpp(decl^type("foobar") s; // error-ok)cpp"),
              StartsWith("fail: Could not expand type"));
  // array types are not replaced
  EXPECT_THAT(apply("int arr[10]; decl^type(arr) foobar;"),
              StartsWith("fail: Could not expand type"));
  // pointers to an array are not replaced
  EXPECT_THAT(apply(R"cpp(decl^type(&"foobar") s;)cpp"),
              StartsWith("fail: Could not expand type"));

  ExtraArgs.push_back("-std=c++20");
  EXPECT_UNAVAILABLE("template <au^to X> class Y;");

  EXPECT_THAT(apply("auto X = [](^auto){};"),
              StartsWith("fail: Could not deduce"));
  EXPECT_EQ(apply("auto X = [](^auto){return 0;}; int Y = X(42);"),
            "auto X = [](int){return 0;}; int Y = X(42);");
  EXPECT_THAT(apply("auto X = [](^auto){return 0;}; int Y = X(42) + X('c');"),
              StartsWith("fail: Could not deduce"));
  // FIXME: should work on constrained auto params, once SourceRange is fixed.
  EXPECT_UNAVAILABLE("template<class> concept C = true;"
                     "auto X = [](C ^auto *){return 0;};");

  // lambda should not be replaced
  EXPECT_UNAVAILABLE("auto f = [](){}; decl^type(f) g;");
  EXPECT_UNAVAILABLE("decl^type([]{}) f;");
}

} // namespace
} // namespace clangd
} // namespace clang