1 | //===-- RemoveUsingNamespaceTest.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-matchers.h" |
11 | #include "gmock/gmock.h" |
12 | #include "gtest/gtest.h" |
13 | |
14 | namespace clang { |
15 | namespace clangd { |
16 | namespace { |
17 | |
18 | TWEAK_TEST(RemoveUsingNamespace); |
19 | |
20 | TEST_F(RemoveUsingNamespaceTest, All) { |
21 | std::pair<llvm::StringRef /*Input*/, llvm::StringRef /*Expected*/> Cases[] = { |
22 | {// Remove all occurrences of ns. Qualify only unqualified. |
23 | R"cpp( |
24 | namespace ns1 { struct vector {}; } |
25 | namespace ns2 { struct map {}; } |
26 | using namespace n^s1; |
27 | using namespace ns2; |
28 | using namespace ns1; |
29 | int main() { |
30 | ns1::vector v1; |
31 | vector v2; |
32 | map m1; |
33 | } |
34 | )cpp" , |
35 | R"cpp( |
36 | namespace ns1 { struct vector {}; } |
37 | namespace ns2 { struct map {}; } |
38 | |
39 | using namespace ns2; |
40 | |
41 | int main() { |
42 | ns1::vector v1; |
43 | ns1::vector v2; |
44 | map m1; |
45 | } |
46 | )cpp" }, |
47 | {// Ident to be qualified is a macro arg. |
48 | R"cpp( |
49 | #define DECLARE(x, y) x y |
50 | namespace ns { struct vector {}; } |
51 | using namespace n^s; |
52 | int main() { |
53 | DECLARE(ns::vector, v1); |
54 | DECLARE(vector, v2); |
55 | } |
56 | )cpp" , |
57 | R"cpp( |
58 | #define DECLARE(x, y) x y |
59 | namespace ns { struct vector {}; } |
60 | |
61 | int main() { |
62 | DECLARE(ns::vector, v1); |
63 | DECLARE(ns::vector, v2); |
64 | } |
65 | )cpp" }, |
66 | {// Nested namespace: Fully qualify ident from inner ns. |
67 | R"cpp( |
68 | namespace aa { namespace bb { struct map {}; }} |
69 | using namespace aa::b^b; |
70 | int main() { |
71 | map m; |
72 | } |
73 | )cpp" , |
74 | R"cpp( |
75 | namespace aa { namespace bb { struct map {}; }} |
76 | |
77 | int main() { |
78 | aa::bb::map m; |
79 | } |
80 | )cpp" }, |
81 | {// Nested namespace: Fully qualify ident from inner ns. |
82 | R"cpp( |
83 | namespace aa { namespace bb { struct map {}; }} |
84 | using namespace a^a; |
85 | int main() { |
86 | bb::map m; |
87 | } |
88 | )cpp" , |
89 | R"cpp( |
90 | namespace aa { namespace bb { struct map {}; }} |
91 | |
92 | int main() { |
93 | aa::bb::map m; |
94 | } |
95 | )cpp" }, |
96 | {// Typedef. |
97 | R"cpp( |
98 | namespace aa { namespace bb { struct map {}; }} |
99 | using namespace a^a; |
100 | typedef bb::map map; |
101 | int main() { map M; } |
102 | )cpp" , |
103 | R"cpp( |
104 | namespace aa { namespace bb { struct map {}; }} |
105 | |
106 | typedef aa::bb::map map; |
107 | int main() { map M; } |
108 | )cpp" }, |
109 | {// FIXME: Nested namespaces: Not aware of using ns decl of outer ns. |
110 | R"cpp( |
111 | namespace aa { namespace bb { struct map {}; }} |
112 | using name[[space aa::b]]b; |
113 | using namespace aa; |
114 | int main() { |
115 | map m; |
116 | } |
117 | )cpp" , |
118 | R"cpp( |
119 | namespace aa { namespace bb { struct map {}; }} |
120 | |
121 | using namespace aa; |
122 | int main() { |
123 | aa::bb::map m; |
124 | } |
125 | )cpp" }, |
126 | {// Does not qualify ident from inner namespace. |
127 | R"cpp( |
128 | namespace aa { namespace bb { struct map {}; }} |
129 | using namespace aa::bb; |
130 | using namespace a^a; |
131 | int main() { |
132 | map m; |
133 | } |
134 | )cpp" , |
135 | R"cpp( |
136 | namespace aa { namespace bb { struct map {}; }} |
137 | using namespace aa::bb; |
138 | |
139 | int main() { |
140 | map m; |
141 | } |
142 | )cpp" }, |
143 | {// Available only for top level namespace decl. |
144 | R"cpp( |
145 | namespace aa { |
146 | namespace bb { struct map {}; } |
147 | using namespace b^b; |
148 | } |
149 | int main() { aa::map m; } |
150 | )cpp" , |
151 | "unavailable" }, |
152 | {// FIXME: Unavailable for namespaces containing using-namespace decl. |
153 | R"cpp( |
154 | namespace aa { |
155 | namespace bb { struct map {}; } |
156 | using namespace bb; |
157 | } |
158 | using namespace a^a; |
159 | int main() { |
160 | map m; |
161 | } |
162 | )cpp" , |
163 | "unavailable" }, |
164 | {R"cpp( |
165 | namespace a::b { struct Foo {}; } |
166 | using namespace a; |
167 | using namespace a::[[b]]; |
168 | using namespace b; |
169 | int main() { Foo F;} |
170 | )cpp" , |
171 | R"cpp( |
172 | namespace a::b { struct Foo {}; } |
173 | using namespace a; |
174 | |
175 | |
176 | int main() { a::b::Foo F;} |
177 | )cpp" }, |
178 | {R"cpp( |
179 | namespace a::b { struct Foo {}; } |
180 | using namespace a; |
181 | using namespace a::b; |
182 | using namespace [[b]]; |
183 | int main() { Foo F;} |
184 | )cpp" , |
185 | R"cpp( |
186 | namespace a::b { struct Foo {}; } |
187 | using namespace a; |
188 | |
189 | |
190 | int main() { b::Foo F;} |
191 | )cpp" }, |
192 | {// Enumerators. |
193 | R"cpp( |
194 | namespace tokens { |
195 | enum Token { |
196 | comma, identifier, numeric |
197 | }; |
198 | } |
199 | using namespace tok^ens; |
200 | int main() { |
201 | auto x = comma; |
202 | } |
203 | )cpp" , |
204 | R"cpp( |
205 | namespace tokens { |
206 | enum Token { |
207 | comma, identifier, numeric |
208 | }; |
209 | } |
210 | |
211 | int main() { |
212 | auto x = tokens::comma; |
213 | } |
214 | )cpp" }, |
215 | {// inline namespaces. |
216 | R"cpp( |
217 | namespace std { inline namespace ns1 { inline namespace ns2 { struct vector {}; }}} |
218 | using namespace st^d; |
219 | int main() { |
220 | vector V; |
221 | } |
222 | )cpp" , |
223 | R"cpp( |
224 | namespace std { inline namespace ns1 { inline namespace ns2 { struct vector {}; }}} |
225 | |
226 | int main() { |
227 | std::vector V; |
228 | } |
229 | )cpp" }, |
230 | {// Does not qualify operators declared in a non-class context |
231 | R"cpp( |
232 | namespace ns { |
233 | struct Foo {}; |
234 | void operator+(const Foo &, int) {} |
235 | } |
236 | using namespace n^s; |
237 | int main() { |
238 | Foo foo; |
239 | foo + 10; |
240 | } |
241 | )cpp" , |
242 | R"cpp( |
243 | namespace ns { |
244 | struct Foo {}; |
245 | void operator+(const Foo &, int) {} |
246 | } |
247 | |
248 | int main() { |
249 | ns::Foo foo; |
250 | foo + 10; |
251 | } |
252 | )cpp" }, |
253 | {// Does not qualify user-defined literals |
254 | R"cpp( |
255 | namespace ns { |
256 | long double operator "" _w(long double); |
257 | } |
258 | using namespace n^s; |
259 | int main() { 1.5_w; } |
260 | )cpp" , |
261 | R"cpp( |
262 | namespace ns { |
263 | long double operator "" _w(long double); |
264 | } |
265 | |
266 | int main() { 1.5_w; } |
267 | )cpp" }, |
268 | { |
269 | R"cpp( |
270 | namespace a { inline namespace b { void foobar(); } } |
271 | using namespace a::[[b]]; |
272 | int main() { foobar(); } |
273 | )cpp" , |
274 | R"cpp( |
275 | namespace a { inline namespace b { void foobar(); } } |
276 | |
277 | int main() { a::b::foobar(); } |
278 | )cpp" }}; |
279 | for (auto C : Cases) |
280 | EXPECT_EQ(C.second, apply(C.first)) << C.first; |
281 | } |
282 | |
283 | } // namespace |
284 | } // namespace clangd |
285 | } // namespace clang |
286 | |