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