1//===-- PopulateSwitchTest.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
13namespace clang {
14namespace clangd {
15namespace {
16
17TWEAK_TEST(PopulateSwitch);
18
19TEST_F(PopulateSwitchTest, Test) {
20 struct Case {
21 CodeContext Context;
22 llvm::StringRef TestSource;
23 llvm::StringRef ExpectedSource;
24 llvm::StringRef FileName = "TestTU.cpp";
25 };
26
27 Case Cases[]{
28 {
29 // No enumerators
30 .Context: Function,
31 .TestSource: R""(enum Enum {}; ^switch ((Enum)0) {})"",
32 .ExpectedSource: "unavailable",
33 },
34 {
35 // All enumerators already in switch (unscoped)
36 .Context: Function,
37 .TestSource: R""(enum Enum {A,B}; ^switch (A) {case A:break;case B:break;})"",
38 .ExpectedSource: "unavailable",
39 },
40 {
41 // All enumerators already in switch (scoped)
42 .Context: Function,
43 .TestSource: R""(
44 enum class Enum {A,B};
45 ^switch (Enum::A) {case Enum::A:break;case Enum::B:break;}
46 )"",
47 .ExpectedSource: "unavailable",
48 },
49 {
50 // Default case in switch
51 .Context: Function,
52 .TestSource: R""(
53 enum class Enum {A,B};
54 ^switch (Enum::A) {default:break;}
55 )"",
56 .ExpectedSource: "unavailable",
57 },
58 {
59 // GNU range in switch
60 .Context: Function,
61 .TestSource: R""(
62 enum class Enum {A,B};
63 ^switch (Enum::A) {case Enum::A ... Enum::B:break;}
64 )"",
65 .ExpectedSource: "unavailable",
66 },
67 {
68 // Value dependent case expression
69 .Context: File,
70 .TestSource: R""(
71 enum class Enum {A,B};
72 template<Enum Value>
73 void function() {
74 ^switch (Enum::A) {case Value:break;}
75 }
76 )"",
77 .ExpectedSource: "unavailable",
78 },
79 {
80 // Body not CompoundStmt
81 .Context: Function,
82 .TestSource: R""(enum Enum {A}; ^switch (A);)"",
83 .ExpectedSource: "unavailable",
84 },
85 {
86 // Selection on switch token
87 .Context: Function,
88 .TestSource: R""(enum Enum {A}; ^switch (A) {})"",
89 .ExpectedSource: R""(enum Enum {A}; switch (A) {case A:break;})"",
90 },
91 {
92 // Selection on switch condition
93 .Context: Function,
94 .TestSource: R""(enum Enum {A}; switch (^A) {})"",
95 .ExpectedSource: R""(enum Enum {A}; switch (A) {case A:break;})"",
96 },
97 {
98 // Selection of whole switch condition
99 .Context: Function,
100 .TestSource: R""(enum Enum {A}; switch ([[A]]) {})"",
101 .ExpectedSource: R""(enum Enum {A}; switch (A) {case A:break;})"",
102 },
103 {
104 // Selection in switch body
105 .Context: Function,
106 .TestSource: R""(enum Enum {A}; switch (A) {^})"",
107 .ExpectedSource: R""(enum Enum {A}; switch (A) {case A:break;})"",
108 },
109 {
110 // Scoped enumeration
111 .Context: Function,
112 .TestSource: R""(enum class Enum {A}; ^switch (Enum::A) {})"",
113 .ExpectedSource: R""(enum class Enum {A}; switch (Enum::A) {case Enum::A:break;})"",
114 },
115 {
116 // Scoped enumeration with multiple enumerators
117 .Context: Function,
118 .TestSource: R""(
119 enum class Enum {A,B};
120 ^switch (Enum::A) {}
121 )"",
122 .ExpectedSource: R""(
123 enum class Enum {A,B};
124 switch (Enum::A) {case Enum::A:case Enum::B:break;}
125 )"",
126 },
127 {
128 // Only filling in missing enumerators (unscoped)
129 .Context: Function,
130 .TestSource: R""(
131 enum Enum {A,B,C};
132 ^switch (A) {case B:break;}
133 )"",
134 .ExpectedSource: R""(
135 enum Enum {A,B,C};
136 switch (A) {case B:break;case A:case C:break;}
137 )"",
138 },
139 {
140 // Only filling in missing enumerators,
141 // even when using integer literals
142 .Context: Function,
143 .TestSource: R""(
144 enum Enum {A,B=1,C};
145 ^switch (A) {case 1:break;}
146 )"",
147 .ExpectedSource: R""(
148 enum Enum {A,B=1,C};
149 switch (A) {case 1:break;case A:case C:break;}
150 )"",
151 },
152 {
153 // Only filling in missing enumerators (scoped)
154 .Context: Function,
155 .TestSource: R""(
156 enum class Enum {A,B,C};
157 ^switch (Enum::A)
158 {case Enum::B:break;}
159 )"",
160 .ExpectedSource: R""(
161 enum class Enum {A,B,C};
162 switch (Enum::A)
163 {case Enum::B:break;case Enum::A:case Enum::C:break;}
164 )"",
165 },
166 {
167 // Scoped enumerations in namespace
168 .Context: File,
169 .TestSource: R""(
170 namespace ns { enum class Enum {A}; }
171 void function() { ^switch (ns::Enum::A) {} }
172 )"",
173 .ExpectedSource: R""(
174 namespace ns { enum class Enum {A}; }
175 void function() { switch (ns::Enum::A) {case ns::Enum::A:break;} }
176 )"",
177 },
178 {
179 // Unscoped enumerations in namespace
180 .Context: File,
181 .TestSource: R""(
182 namespace ns { enum Enum {A}; }
183 void function() { ^switch (ns::A) {} }
184 )"",
185 .ExpectedSource: R""(
186 namespace ns { enum Enum {A}; }
187 void function() { switch (ns::A) {case ns::A:break;} }
188 )"",
189 },
190 {
191 // Duplicated constant names
192 .Context: Function,
193 .TestSource: R""(enum Enum {A,B,b=B}; ^switch (A) {})"",
194 .ExpectedSource: R""(enum Enum {A,B,b=B}; switch (A) {case A:case B:break;})"",
195 },
196 {
197 // Duplicated constant names all in switch
198 .Context: Function,
199 .TestSource: R""(enum Enum {A,B,b=B}; ^switch (A) {case A:case B:break;})"",
200 .ExpectedSource: "unavailable",
201 },
202 {
203 // Enum is dependent type
204 .Context: File,
205 .TestSource: R""(template<typename T> void f() {enum Enum {A}; ^switch (A) {}})"",
206 .ExpectedSource: "unavailable",
207 },
208 {// C: Only filling in missing enumerators
209 .Context: Function,
210 .TestSource: R""(
211 enum CEnum {A,B,C};
212 enum CEnum val = A;
213 ^switch (val) {case B:break;}
214 )"",
215 .ExpectedSource: R""(
216 enum CEnum {A,B,C};
217 enum CEnum val = A;
218 switch (val) {case B:break;case A:case C:break;}
219 )"",
220 .FileName: "TestTU.c"},
221 {// C: Only filling in missing enumerators w/ typedefs
222 .Context: Function,
223 .TestSource: R""(
224 typedef unsigned long UInteger;
225 enum ControlState : UInteger;
226 typedef enum ControlState ControlState;
227 enum ControlState : UInteger {A,B,C};
228 ControlState controlState = A;
229 switch (^controlState) {case A:break;}
230 )"",
231 .ExpectedSource: R""(
232 typedef unsigned long UInteger;
233 enum ControlState : UInteger;
234 typedef enum ControlState ControlState;
235 enum ControlState : UInteger {A,B,C};
236 ControlState controlState = A;
237 switch (controlState) {case A:break;case B:case C:break;}
238 )"",
239 .FileName: "TestTU.c"},
240 };
241
242 for (const auto &Case : Cases) {
243 Context = Case.Context;
244 FileName = Case.FileName;
245 EXPECT_EQ(apply(Case.TestSource), Case.ExpectedSource);
246 }
247}
248
249} // namespace
250} // namespace clangd
251} // namespace clang
252

source code of clang-tools-extra/clangd/unittests/tweaks/PopulateSwitchTests.cpp