xref: /llvm-project/clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp (revision 46575f60380b18bf20c5f4cafc5fd06f561c4e7b)
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 
TEST_F(RemoveUsingNamespaceTest,All)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