clang-tools 10.0.0

TweakTests.cpp
Go to the documentation of this file.
1 //===-- TweakTests.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 "Annotations.h"
10 #include "SourceCode.h"
11 #include "TestFS.h"
12 #include "TestTU.h"
13 #include "TweakTesting.h"
14 #include "refactor/Tweak.h"
15 #include "clang/AST/Expr.h"
16 #include "clang/Basic/Diagnostic.h"
17 #include "clang/Basic/DiagnosticIDs.h"
18 #include "clang/Basic/DiagnosticOptions.h"
19 #include "clang/Basic/FileManager.h"
20 #include "clang/Basic/FileSystemOptions.h"
21 #include "clang/Basic/LLVM.h"
22 #include "clang/Basic/SourceLocation.h"
23 #include "clang/Basic/SourceManager.h"
24 #include "clang/Rewrite/Core/Rewriter.h"
25 #include "clang/Tooling/Core/Replacement.h"
26 #include "llvm/ADT/IntrusiveRefCntPtr.h"
27 #include "llvm/ADT/StringExtras.h"
28 #include "llvm/ADT/StringMap.h"
29 #include "llvm/ADT/StringRef.h"
30 #include "llvm/Support/Error.h"
31 #include "llvm/Support/MemoryBuffer.h"
32 #include "llvm/Support/VirtualFileSystem.h"
33 #include "llvm/Testing/Support/Error.h"
34 #include "gmock/gmock-matchers.h"
35 #include "gmock/gmock.h"
36 #include "gtest/gtest.h"
37 #include <cassert>
38 #include <string>
39 #include <utility>
40 #include <vector>
41
42 using ::testing::AllOf;
43 using ::testing::ElementsAre;
44 using ::testing::HasSubstr;
45 using ::testing::StartsWith;
46
47 namespace clang {
48 namespace clangd {
49 namespace {
50
51 MATCHER_P2(FileWithContents, FileName, Contents, "") {
52 return arg.first() == FileName && arg.second == Contents;
53 }
54
55 TEST(FileEdits, AbsolutePath) {
56 auto RelPaths = {"a.h", "foo.cpp", "test/test.cpp"};
57
58 llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> MemFS(
59 new llvm::vfs::InMemoryFileSystem);
60 MemFS->setCurrentWorkingDirectory(testRoot());
61 for (auto Path : RelPaths)
62 MemFS->addFile(Path, 0, llvm::MemoryBuffer::getMemBuffer("", Path));
63 FileManager FM(FileSystemOptions(), MemFS);
64 DiagnosticsEngine DE(new DiagnosticIDs, new DiagnosticOptions);
65 SourceManager SM(DE, FM);
66
67 for (auto Path : RelPaths) {
68 auto FID = SM.createFileID(*FM.getFile(Path), SourceLocation(),
69 clang::SrcMgr::C_User);
70 auto Res = Tweak::Effect::fileEdit(SM, FID, tooling::Replacements());
71 ASSERT_THAT_EXPECTED(Res, llvm::Succeeded());
72 EXPECT_EQ(Res->first, testPath(Path));
73 }
74 }
75
76 TWEAK_TEST(SwapIfBranches);
77 TEST_F(SwapIfBranchesTest, Test) {
78 Context = Function;
79 EXPECT_EQ(apply("^if (true) {return 100;} else {continue;}"),
80 "if (true) {continue;} else {return 100;}");
81 EXPECT_EQ(apply("^if () {return 100;} else {continue;}"),
82 "if () {continue;} else {return 100;}")
83 << "broken condition";
84 EXPECT_AVAILABLE("^i^f^^(^t^r^u^e^) { return 100; } ^e^l^s^e^ { continue; }");
85 EXPECT_UNAVAILABLE("if (true) {^return ^100;^ } else { ^continue^;^ }");
86 // Available in subexpressions of the condition;
87 EXPECT_THAT("if(2 + [[2]] + 2) { return 2 + 2 + 2; } else {continue;}",
88 isAvailable());
89 // But not as part of the branches.
90 EXPECT_THAT("if(2 + 2 + 2) { return 2 + [[2]] + 2; } else { continue; }",
91 Not(isAvailable()));
92 // Range covers the "else" token, so available.
93 EXPECT_THAT("if(2 + 2 + 2) { return 2 + [[2 + 2; } else {continue;]]}",
94 isAvailable());
95 // Not available in compound statements in condition.
96 EXPECT_THAT(
97 "if([]{return [[true]];}()) { return 2 + 2 + 2; } else { continue; }",
98 Not(isAvailable()));
99 // Not available if both sides aren't braced.
100 EXPECT_THAT("^if (1) return; else { return; }", Not(isAvailable()));
101 // Only one if statement is supported!
102 EXPECT_THAT("[[if(1){}else{}if(2){}else{}]]", Not(isAvailable()));
103 }
104
105 TWEAK_TEST(RawStringLiteral);
106 TEST_F(RawStringLiteralTest, Test) {
107 Context = Expression;
108 EXPECT_AVAILABLE(R"cpp(^"^f^o^o^\^n^")cpp");
109 EXPECT_AVAILABLE(R"cpp(R"(multi )" ^"token " "str\ning")cpp");
110 EXPECT_UNAVAILABLE(R"cpp(^"f^o^o^o")cpp"); // no chars need escaping
111 EXPECT_UNAVAILABLE(R"cpp(R"(multi )" ^"token " u8"str\ning")cpp"); // nonascii
112 EXPECT_UNAVAILABLE(R"cpp(^R^"^(^multi )" "token " "str\ning")cpp"); // raw
113 EXPECT_UNAVAILABLE(R"cpp(^"token\n" __FILE__)cpp"); // chunk is macro
114 EXPECT_UNAVAILABLE(R"cpp(^"a\r\n";)cpp"); // forbidden escape char
115
116 const char *Input = R"cpp(R"(multi
117 token)" "\nst^ring\n" "literal")cpp";
118 const char *Output = R"cpp(R"(multi
119 token
120 string
121 literal)")cpp";
122 EXPECT_EQ(apply(Input), Output);
123 }
124
125 TWEAK_TEST(ObjCLocalizeStringLiteral);
126 TEST_F(ObjCLocalizeStringLiteralTest, Test) {
127 ExtraArgs.push_back("-x");
128 ExtraArgs.push_back("objective-c");
129
130 // Ensure the action can be initiated in the string literal.
131 EXPECT_AVAILABLE(R"(id x = ^[[@[[^"^t^est^"]]]];)");
132
133 // Ensure that the action can't be initiated in other places.
134 EXPECT_UNAVAILABLE(R"([[i^d ^[[x]] ^= @"test";^]])");
135
136 // Ensure that the action is not available for regular C strings.
137 EXPECT_UNAVAILABLE(R"(const char * x= "^test";)");
138
139 const char *Input = R"(id x = [[@"test"]];)";
140 const char *Output = R"(id x = NSLocalizedString(@"test", @"");)";
141 EXPECT_EQ(apply(Input), Output);
142 }
143
144 TWEAK_TEST(DumpAST);
145 TEST_F(DumpASTTest, Test) {
146 EXPECT_AVAILABLE("^int f^oo() { re^turn 2 ^+ 2; }");
147 EXPECT_UNAVAILABLE("/*c^omment*/ int foo() return 2 ^ + 2; }");
148 EXPECT_THAT(apply("int x = 2 ^+ 2;"),
149 AllOf(StartsWith("message:"), HasSubstr("BinaryOperator"),
150 HasSubstr("'+'"), HasSubstr("|-IntegerLiteral"),
151 HasSubstr("<col:9> 'int' 2\n`-IntegerLiteral"),
152 HasSubstr("<col:13> 'int' 2")));
153 }
154
155 TWEAK_TEST(DumpSymbol);
156 TEST_F(DumpSymbolTest, Test) {
157 std::string ID = R"("id":"CA2EBE44A1D76D2A")";
158 std::string USR = R"("usr":"c:@F@foo#")";
159 EXPECT_THAT(apply("void f^oo();"),
160 AllOf(StartsWith("message:"), testing::HasSubstr(ID),
161 testing::HasSubstr(USR)));
162 }
163
164 TWEAK_TEST(ShowSelectionTree);
165 TEST_F(ShowSelectionTreeTest, Test) {
166 EXPECT_AVAILABLE("^int f^oo() { re^turn 2 ^+ 2; }");
167 EXPECT_AVAILABLE("/*c^omment*/ int foo() return 2 ^ + 2; }");
168
169 const char *Output = R"(message:
170 TranslationUnitDecl
171 VarDecl int x = fcall(2 + 2)
172 .CallExpr fcall(2 + 2)
173 ImplicitCastExpr fcall
174 .DeclRefExpr fcall
175 .BinaryOperator 2 + 2
176 *IntegerLiteral 2
177 )";
178 EXPECT_EQ(apply("int fcall(int); int x = fca[[ll(2 +]]2);"), Output);
179 }
180
181 TWEAK_TEST(DumpRecordLayout);
182 TEST_F(DumpRecordLayoutTest, Test) {
183 EXPECT_AVAILABLE("^s^truct ^X ^{ int x; ^};");
184 EXPECT_THAT("struct X { int ^a; };", Not(isAvailable()));
185 EXPECT_THAT("struct ^X;", Not(isAvailable()));
186 EXPECT_THAT("template <typename T> struct ^X { T t; };", Not(isAvailable()));
187 EXPECT_THAT("enum ^X {};", Not(isAvailable()));
188
189 EXPECT_THAT(apply("struct ^X { int x; int y; }"),
190 AllOf(StartsWith("message:"), HasSubstr("0 | int x")));
191 }
192
193 TWEAK_TEST(ExtractVariable);
194 TEST_F(ExtractVariableTest, Test) {
195 const char *AvailableCases = R"cpp(
196 int xyz(int a = 1) {
197 struct T {
198 int bar(int a = 1);
199 int z;
200 } t;
201 // return statement
202 return [[[[t.b[[a]]r]](t.z)]];
203 }
204 void f() {
205 int a = [[5 +]] [[4 * [[[[xyz]]()]]]];
206 // multivariable initialization
207 if(1)
208 int x = [[1]], y = [[a + 1]], a = [[1]], z = a + 1;
209 // if without else
210 if([[1]])
211 a = [[1]];
212 // if with else
213 if(a < [[3]])
214 if(a == [[4]])
215 a = [[5]];
216 else
217 a = [[5]];
218 else if (a < [[4]])
219 a = [[4]];
220 else
221 a = [[5]];
222 // for loop
223 for(a = [[1]]; a > [[[[3]] + [[4]]]]; a++)
224 a = [[2]];
225 // while
226 while(a < [[1]])
227 a = [[1]];
228 // do while
229 do
230 a = [[1]];
231 while(a < [[3]]);
232 }
233 )cpp";
234 EXPECT_AVAILABLE(AvailableCases);
235
236 const char *NoCrashCases = R"cpp(
237 template<typename T, typename ...Args>
238 struct Test<T, Args...> {
239 Test(const T &v) :val[[(^]]) {}
240 T val;
241 };
242 )cpp";
243 EXPECT_UNAVAILABLE(NoCrashCases);
244
245 const char *UnavailableCases = R"cpp(
246 int xyz(int a = [[1]]) {
247 struct T {
248 int bar(int a = [[1]]);
249 int z = [[1]];
250 } t;
251 return [[t]].bar([[[[t]].z]]);
252 }
253 void v() { return; }
254 // function default argument
255 void f(int b = [[1]]) {
256 // empty selection
257 int a = ^1 ^+ ^2;
258 // void expressions
259 auto i = new int, j = new int;
260 [[[[delete i]], delete j]];
261 [[v]]();
262 // if
263 if(1)
264 int x = 1, y = a + 1, a = 1, z = [[a + 1]];
265 if(int a = 1)
266 if([[a + 1]] == 4)
267 a = [[[[a]] +]] 1;
268 // for loop
269 for(int a = 1, b = 2, c = 3; a > [[b + c]]; [[a++]])
270 a = [[a + 1]];
271 // lambda
272 auto lamb = [&[[a]], &[[b]]](int r = [[1]]) {return 1;}
273 // assignment
274 xyz([[a = 5]]);
275 xyz([[a *= 5]]);
276 // Variable DeclRefExpr
277 a = [[b]];
278 // statement expression
279 [[xyz()]];
280 while (a)
281 [[++a]];
282 // label statement
283 goto label;
284 label:
285 a = [[1]];
286 }
287 )cpp";
288 EXPECT_UNAVAILABLE(UnavailableCases);
289
290 // vector of pairs of input and output strings
291 const std::vector<std::pair<std::string, std::string>>
292 InputOutputs = {
293 // extraction from variable declaration/assignment
294 {R"cpp(void varDecl() {
295 int a = 5 * (4 + (3 [[- 1)]]);
296 })cpp",
297 R"cpp(void varDecl() {
298 auto dummy = (3 - 1); int a = 5 * (4 + dummy);
299 })cpp"},
300 // FIXME: extraction from switch case
301 /*{R"cpp(void f(int a) {
302 if(1)
303 while(a < 1)
304 switch (1) {
305 case 1:
306 a = [[1 + 2]];
307 break;
308 default:
309 break;
310 }
311 })cpp",
312 R"cpp(void f(int a) {
313 auto dummy = 1 + 2; if(1)
314 while(a < 1)
315 switch (1) {
316 case 1:
317 a = dummy;
318 break;
319 default:
320 break;
321 }
322 })cpp"},*/
323 // Macros
324 {R"cpp(#define PLUS(x) x++
325 void f(int a) {
326 int y = PLUS([[1+a]]);
327 })cpp",
328 /*FIXME: It should be extracted like this.
329 R"cpp(#define PLUS(x) x++
330 void f(int a) {
331 auto dummy = 1+a; int y = PLUS(dummy);
332 })cpp"},*/
333 R"cpp(#define PLUS(x) x++
334 void f(int a) {
335 auto dummy = PLUS(1+a); int y = dummy;
336 })cpp"},
337 // ensure InsertionPoint isn't inside a macro
338 {R"cpp(#define LOOP(x) while (1) {a = x;}
339 void f(int a) {
340 if(1)
341 LOOP(5 + [[3]])
342 })cpp",
343 R"cpp(#define LOOP(x) while (1) {a = x;}
344 void f(int a) {
345 auto dummy = 3; if(1)
346 LOOP(5 + dummy)
347 })cpp"},
348 {R"cpp(#define LOOP(x) do {x;} while(1);
349 void f(int a) {
350 if(1)
351 LOOP(5 + [[3]])
352 })cpp",
353 R"cpp(#define LOOP(x) do {x;} while(1);
354 void f(int a) {
355 auto dummy = 3; if(1)
356 LOOP(5 + dummy)
357 })cpp"},
358 // attribute testing
359 {R"cpp(void f(int a) {
360 [ [gsl::suppress("type")] ] for (;;) a = [[1]];
361 })cpp",
362 R"cpp(void f(int a) {
363 auto dummy = 1; [ [gsl::suppress("type")] ] for (;;) a = dummy;
364 })cpp"},
365 // MemberExpr
366 {R"cpp(class T {
367 T f() {
368 return [[T().f()]].f();
369 }
370 };)cpp",
371 R"cpp(class T {
372 T f() {
373 auto dummy = T().f(); return dummy.f();
374 }
375 };)cpp"},
376 // Function DeclRefExpr
377 {R"cpp(int f() {
378 return [[f]]();
379 })cpp",
380 R"cpp(int f() {
381 auto dummy = f(); return dummy;
382 })cpp"},
383 // FIXME: Wrong result for \[\[clang::uninitialized\]\] int b = [[1]];
384 // since the attr is inside the DeclStmt and the bounds of
385 // DeclStmt don't cover the attribute.
386
387 // Binary subexpressions
388 {R"cpp(void f() {
389 int x = 1 + [[2 + 3 + 4]] + 5;
390 })cpp",
391 R"cpp(void f() {
392 auto dummy = 2 + 3 + 4; int x = 1 + dummy + 5;
393 })cpp"},
394 {R"cpp(void f() {
395 int x = [[1 + 2 + 3]] + 4 + 5;
396 })cpp",
397 R"cpp(void f() {
398 auto dummy = 1 + 2 + 3; int x = dummy + 4 + 5;
399 })cpp"},
400 {R"cpp(void f() {
401 int x = 1 + 2 + [[3 + 4 + 5]];
402 })cpp",
403 R"cpp(void f() {
404 auto dummy = 3 + 4 + 5; int x = 1 + 2 + dummy;
405 })cpp"},
406 // Non-associative operations have no special support
407 {R"cpp(void f() {
408 int x = 1 - [[2 - 3 - 4]] - 5;
409 })cpp",
410 R"cpp(void f() {
411 auto dummy = 1 - 2 - 3 - 4; int x = dummy - 5;
412 })cpp"},
413 // A mix of associative operators isn't associative.
414 {R"cpp(void f() {
415 int x = 0 + 1 * [[2 + 3]] * 4 + 5;
416 })cpp",
417 R"cpp(void f() {
418 auto dummy = 1 * 2 + 3 * 4; int x = 0 + dummy + 5;
419 })cpp"},
420 // Overloaded operators are supported, we assume associativity
421 // as if they were built-in.
422 {R"cpp(struct S {
423 S(int);
424 };
425 S operator+(S, S);
426
427 void f() {
428 S x = S(1) + [[S(2) + S(3) + S(4)]] + S(5);
429 })cpp",
430 R"cpp(struct S {
431 S(int);
432 };
433 S operator+(S, S);
434
435 void f() {
436 auto dummy = S(2) + S(3) + S(4); S x = S(1) + dummy + S(5);
437 })cpp"},
438 // Don't try to analyze across macro boundaries
439 // FIXME: it'd be nice to do this someday (in a safe way)
440 {R"cpp(#define ECHO(X) X
441 void f() {
442 int x = 1 + [[ECHO(2 + 3) + 4]] + 5;
443 })cpp",
444 R"cpp(#define ECHO(X) X
445 void f() {
446 auto dummy = 1 + ECHO(2 + 3) + 4; int x = dummy + 5;
447 })cpp"},
448 {R"cpp(#define ECHO(X) X
449 void f() {
450 int x = 1 + [[ECHO(2) + ECHO(3) + 4]] + 5;
451 })cpp",
452 R"cpp(#define ECHO(X) X
453 void f() {
454 auto dummy = 1 + ECHO(2) + ECHO(3) + 4; int x = dummy + 5;
455 })cpp"},
456 };
457 for (const auto &IO : InputOutputs) {
458 EXPECT_EQ(IO.second, apply(IO.first)) << IO.first;
459 }
460 }
461
462 TWEAK_TEST(AnnotateHighlightings);
463 TEST_F(AnnotateHighlightingsTest, Test) {
464 EXPECT_AVAILABLE("^vo^id^ ^f(^) {^}^"); // available everywhere.
465 EXPECT_AVAILABLE("[[int a; int b;]]");
466 EXPECT_EQ("void /* entity.name.function.cpp */f() {}", apply("void ^f() {}"));
467
468 EXPECT_EQ(apply("[[void f1(); void f2();]]"),
469 "void /* entity.name.function.cpp */f1(); "
470 "void /* entity.name.function.cpp */f2();");
471
472 EXPECT_EQ(apply("void f1(); void f2() {^}"),
473 "void f1(); "
474 "void /* entity.name.function.cpp */f2() {}");
475 }
476
477 TWEAK_TEST(ExpandMacro);
478 TEST_F(ExpandMacroTest, Test) {
479 Header = R"cpp(
480 #define FOO 1 2 3
481 #define FUNC(X) X+X+X
482 #define EMPTY
483 #define EMPTY_FN(X)
484 )cpp";
485
486 // Available on macro names, not available anywhere else.
487 EXPECT_AVAILABLE("^F^O^O^ BAR ^F^O^O^");
488 EXPECT_AVAILABLE("^F^U^N^C^(1)");
489 EXPECT_UNAVAILABLE("^#^d^efine^ ^XY^Z 1 ^2 ^3^");
490 EXPECT_UNAVAILABLE("FOO ^B^A^R^ FOO ^");
491 EXPECT_UNAVAILABLE("FUNC(^1^)^");
492
493 // Works as expected on object-like macros.
494 EXPECT_EQ(apply("^FOO BAR FOO"), "1 2 3 BAR FOO");
495 EXPECT_EQ(apply("FOO BAR ^FOO"), "FOO BAR 1 2 3");
496 // And function-like macros.
497 EXPECT_EQ(apply("F^UNC(2)"), "2 + 2 + 2");
498
499 // Works on empty macros.
500 EXPECT_EQ(apply("int a ^EMPTY;"), "int a ;");
501 EXPECT_EQ(apply("int a ^EMPTY_FN(1 2 3);"), "int a ;");
502 EXPECT_EQ(apply("int a = 123 ^EMPTY EMPTY_FN(1);"),
503 "int a = 123 EMPTY_FN(1);");
504 EXPECT_EQ(apply("int a = 123 ^EMPTY_FN(1) EMPTY;"), "int a = 123 EMPTY;");
505 EXPECT_EQ(apply("int a = 123 EMPTY_FN(1) ^EMPTY;"),
506 "int a = 123 EMPTY_FN(1) ;");
507 }
508
509 TWEAK_TEST(ExpandAutoType);
510 TEST_F(ExpandAutoTypeTest, Test) {
511
512 Header = R"cpp(
513 namespace ns {
514 struct Class {
515 struct Nested {};
516 }
517 void Func();
518 }
519 inline namespace inl_ns {
520 namespace {
521 struct Visible {};
522 }
523 }
524 )cpp";
525
526 EXPECT_AVAILABLE("^a^u^t^o^ i = 0;");
527 EXPECT_UNAVAILABLE("auto ^i^ ^=^ ^0^;^");
528
529 // check primitive type
530 EXPECT_EQ(apply("[[auto]] i = 0;"), "int i = 0;");
531 EXPECT_EQ(apply("au^to i = 0;"), "int i = 0;");
532 // check classes and namespaces
533 EXPECT_EQ(apply("^auto C = ns::Class::Nested();"),
534 "ns::Class::Nested C = ns::Class::Nested();");
535 // check that namespaces are shortened
536 EXPECT_EQ(apply("namespace ns { void f() { ^auto C = Class(); } }"),
537 "namespace ns { void f() { Class C = Class(); } }");
538 // undefined functions should not be replaced
539 EXPECT_THAT(apply("au^to x = doesnt_exist();"),
540 StartsWith("fail: Could not deduce type for 'auto' type"));
541 // function pointers should not be replaced
542 EXPECT_THAT(apply("au^to x = &ns::Func;"),
543 StartsWith("fail: Could not expand type of function pointer"));
544 // lambda types are not replaced
545 EXPECT_THAT(apply("au^to x = []{};"),
546 StartsWith("fail: Could not expand type of lambda expression"));
547 // inline namespaces
548 EXPECT_EQ(apply("au^to x = inl_ns::Visible();"),
549 "Visible x = inl_ns::Visible();");
550 // local class
551 EXPECT_EQ(apply("namespace x { void y() { struct S{}; ^auto z = S(); } }"),
552 "namespace x { void y() { struct S{}; S z = S(); } }");
553 // replace array types
554 EXPECT_EQ(apply(R"cpp(au^to x = "test")cpp"),
555 R"cpp(const char * x = "test")cpp");
556
557 EXPECT_UNAVAILABLE("dec^ltype(au^to) x = 10;");
558
559 // FIXME: Auto-completion in a template requires disabling delayed template
560 // parsing.
561 ExtraArgs.push_back("-fno-delayed-template-parsing");
562 // unknown types in a template should not be replaced
563 EXPECT_THAT(apply("template <typename T> void x() { ^auto y = T::z(); }"),
564 StartsWith("fail: Could not deduce type for 'auto' type"));
565 }
566
567 TWEAK_TEST(ExtractFunction);
568 TEST_F(ExtractFunctionTest, FunctionTest) {
569 Context = Function;
570
571 // Root statements should have common parent.
572 EXPECT_EQ(apply("for(;;) [[1+2; 1+2;]]"), "unavailable");
573 // Expressions aren't extracted.
574 EXPECT_EQ(apply("int x = 0; [[x++;]]"), "unavailable");
575 // We don't support extraction from lambdas.
576 EXPECT_EQ(apply("auto lam = [](){ [[int x;]] }; "), "unavailable");
577 // Partial statements aren't extracted.
578 EXPECT_THAT(apply("int [[x = 0]];"), "unavailable");
579
580 // Ensure that end of Zone and Beginning of PostZone being adjacent doesn't
581 // lead to break being included in the extraction zone.
582 EXPECT_THAT(apply("for(;;) { [[int x;]]break; }"), HasSubstr("extracted"));
583 // FIXME: ExtractFunction should be unavailable inside loop construct
584 // initalizer/condition.
585 EXPECT_THAT(apply(" for([[int i = 0;]];);"), HasSubstr("extracted"));
586 // Don't extract because needs hoisting.
587 EXPECT_THAT(apply(" [[int a = 5;]] a++; "), StartsWith("fail"));
588 // Extract certain return
589 EXPECT_THAT(apply(" if(true) [[{ return; }]] "), HasSubstr("extracted"));
590 // Don't extract uncertain return
591 EXPECT_THAT(apply(" if(true) [[if (false) return;]] "), StartsWith("fail"));
592 }
593
594 TEST_F(ExtractFunctionTest, FileTest) {
595 // Check all parameters are in order
596 std::string ParameterCheckInput = R"cpp(
597 struct Foo {
598 int x;
599 };
600 void f(int a) {
601 int b;
602 int *ptr = &a;
603 Foo foo;
604 [[a += foo.x + b;
605 *ptr++;]]
606 })cpp";
607 std::string ParameterCheckOutput = R"cpp(
608 struct Foo {
609 int x;
610 };
611 void extracted(int &a, int &b, int * &ptr, Foo &foo) {
612 a += foo.x + b;
613 *ptr++;
614 }
615 void f(int a) {
616 int b;
617 int *ptr = &a;
618 Foo foo;
619 extracted(a, b, ptr, foo);
620 })cpp";
621 EXPECT_EQ(apply(ParameterCheckInput), ParameterCheckOutput);
622
623 // Check const qualifier
624 std::string ConstCheckInput = R"cpp(
625 void f(const int c) {
626 [[while(c) {}]]
627 })cpp";
628 std::string ConstCheckOutput = R"cpp(
629 void extracted(const int &c) {
630 while(c) {}
631 }
632 void f(const int c) {
633 extracted(c);
634 })cpp";
635 EXPECT_EQ(apply(ConstCheckInput), ConstCheckOutput);
636
637 // Don't extract when we need to make a function as a parameter.
638 EXPECT_THAT(apply("void f() { [[int a; f();]] }"), StartsWith("fail"));
639
640 // We don't extract from methods for now since they may involve multi-file
641 // edits
642 std::string MethodFailInput = R"cpp(
643 class T {
644 void f() {
645 [[int x;]]
646 }
647 };
648 )cpp";
649 EXPECT_EQ(apply(MethodFailInput), "unavailable");
650
651 // We don't extract from templated functions for now as templates are hard
652 // to deal with.
653 std::string TemplateFailInput = R"cpp(
654 template<typename T>
655 void f() {
656 [[int x;]]
657 }
658 )cpp";
659 EXPECT_EQ(apply(TemplateFailInput), "unavailable");
660
661 std::string MacroInput = R"cpp(
662 #define F(BODY) void f() { BODY }
663 F ([[int x = 0;]])
664 )cpp";
665 std::string MacroOutput = R"cpp(
666 #define F(BODY) void f() { BODY }
667 void extracted() {
668 int x = 0;
669 }
670 F (extracted();)
671 )cpp";
672 EXPECT_EQ(apply(MacroInput), MacroOutput);
673
674 // Shouldn't crash.
675 EXPECT_EQ(apply("void f([[int a]]);"), "unavailable");
676 // Don't extract if we select the entire function body (CompoundStmt).
677 std::string CompoundFailInput = R"cpp(
678 void f() [[{
679 int a;
680 }]]
681 )cpp";
682 EXPECT_EQ(apply(CompoundFailInput), "unavailable");
683 }
684
685 TEST_F(ExtractFunctionTest, ControlFlow) {
686 Context = Function;
687 // We should be able to extract break/continue with a parent loop/switch.
688 EXPECT_THAT(apply(" [[for(;;) if(1) break;]] "), HasSubstr("extracted"));
689 EXPECT_THAT(apply(" for(;;) [[while(1) break;]] "), HasSubstr("extracted"));
690 EXPECT_THAT(apply(" [[switch(1) { break; }]]"), HasSubstr("extracted"));
691 EXPECT_THAT(apply(" [[while(1) switch(1) { continue; }]]"),
692 HasSubstr("extracted"));
693 // Don't extract break and continue without a loop/switch parent.
694 EXPECT_THAT(apply(" for(;;) [[if(1) continue;]] "), StartsWith("fail"));
695 EXPECT_THAT(apply(" while(1) [[if(1) break;]] "), StartsWith("fail"));
696 EXPECT_THAT(apply(" switch(1) { [[break;]] }"), StartsWith("fail"));
697 EXPECT_THAT(apply(" for(;;) { [[while(1) break; break;]] }"),
698 StartsWith("fail"));
699 }
700
701 TEST_F(ExtractFunctionTest, ExistingReturnStatement) {
702 Context = File;
703 const char* Before = R"cpp(
704 bool lucky(int N);
705 int getNum(bool Superstitious, int Min, int Max) {
706 if (Superstitious) [[{
707 for (int I = Min; I <= Max; ++I)
708 if (lucky(I))
709 return I;
710 return -1;
711 }]] else {
712 return (Min + Max) / 2;
713 }
714 }
715 )cpp";
716 // FIXME: min/max should be by value.
717 // FIXME: avoid emitting redundant braces
718 const char* After = R"cpp(
719 bool lucky(int N);
720 int extracted(int &Min, int &Max) {
721 {
722 for (int I = Min; I <= Max; ++I)
723 if (lucky(I))
724 return I;
725 return -1;
726 }
727 }
728 int getNum(bool Superstitious, int Min, int Max) {
729 if (Superstitious) return extracted(Min, Max); else {
730 return (Min + Max) / 2;
731 }
732 }
733 )cpp";
734 EXPECT_EQ(apply(Before), After);
735 }
736
737 TWEAK_TEST(RemoveUsingNamespace);
738 TEST_F(RemoveUsingNamespaceTest, All) {
739 std::pair<llvm::StringRef /*Input*/, llvm::StringRef /*Expected*/> Cases[] = {
740 {// Remove all occurrences of ns. Qualify only unqualified.
741 R"cpp(
742 namespace ns1 { struct vector {}; }
743 namespace ns2 { struct map {}; }
744 using namespace n^s1;
745 using namespace ns2;
746 using namespace ns1;
747 int main() {
748 ns1::vector v1;
749 vector v2;
750 map m1;
751 }
752 )cpp",
753 R"cpp(
754 namespace ns1 { struct vector {}; }
755 namespace ns2 { struct map {}; }
756
757 using namespace ns2;
758
759 int main() {
760 ns1::vector v1;
761 ns1::vector v2;
762 map m1;
763 }
764 )cpp"},
765 {// Ident to be qualified is a macro arg.
766 R"cpp(
767 #define DECLARE(x, y) x y
768 namespace ns { struct vector {}; }
769 using namespace n^s;
770 int main() {
771 DECLARE(ns::vector, v1);
772 DECLARE(vector, v2);
773 }
774 )cpp",
775 R"cpp(
776 #define DECLARE(x, y) x y
777 namespace ns { struct vector {}; }
778
779 int main() {
780 DECLARE(ns::vector, v1);
781 DECLARE(ns::vector, v2);
782 }
783 )cpp"},
784 {// Nested namespace: Fully qualify ident from inner ns.
785 R"cpp(
786 namespace aa { namespace bb { struct map {}; }}
787 using namespace aa::b^b;
788 int main() {
789 map m;
790 }
791 )cpp",
792 R"cpp(
793 namespace aa { namespace bb { struct map {}; }}
794
795 int main() {
796 aa::bb::map m;
797 }
798 )cpp"},
799 {// Nested namespace: Fully qualify ident from inner ns.
800 R"cpp(
801 namespace aa { namespace bb { struct map {}; }}
802 using namespace a^a;
803 int main() {
804 bb::map m;
805 }
806 )cpp",
807 R"cpp(
808 namespace aa { namespace bb { struct map {}; }}
809
810 int main() {
811 aa::bb::map m;
812 }
813 )cpp"},
814 {// Typedef.
815 R"cpp(
816 namespace aa { namespace bb { struct map {}; }}
817 using namespace a^a;
818 typedef bb::map map;
819 int main() { map M; }
820 )cpp",
821 R"cpp(
822 namespace aa { namespace bb { struct map {}; }}
823
824 typedef aa::bb::map map;
825 int main() { map M; }
826 )cpp"},
827 {// FIXME: Nested namespaces: Not aware of using ns decl of outer ns.
828 R"cpp(
829 namespace aa { namespace bb { struct map {}; }}
830 using name[[space aa::b]]b;
831 using namespace aa;
832 int main() {
833 map m;
834 }
835 )cpp",
836 R"cpp(
837 namespace aa { namespace bb { struct map {}; }}
838
839 using namespace aa;
840 int main() {
841 aa::bb::map m;
842 }
843 )cpp"},
844 {// Does not qualify ident from inner namespace.
845 R"cpp(
846 namespace aa { namespace bb { struct map {}; }}
847 using namespace aa::bb;
848 using namespace a^a;
849 int main() {
850 map m;
851 }
852 )cpp",
853 R"cpp(
854 namespace aa { namespace bb { struct map {}; }}
855 using namespace aa::bb;
856
857 int main() {
858 map m;
859 }
860 )cpp"},
861 {// Available only for top level namespace decl.
862 R"cpp(
863 namespace aa {
864 namespace bb { struct map {}; }
865 using namespace b^b;
866 }
867 int main() { aa::map m; }
868 )cpp",
869 "unavailable"},
870 {// FIXME: Unavailable for namespaces containing using-namespace decl.
871 R"cpp(
872 namespace aa {
873 namespace bb { struct map {}; }
874 using namespace bb;
875 }
876 using namespace a^a;
877 int main() {
878 map m;
879 }
880 )cpp",
881 "unavailable"},
882 {R"cpp(
883 namespace a::b { struct Foo {}; }
884 using namespace a;
885 using namespace a::[[b]];
886 using namespace b;
887 int main() { Foo F;}
888 )cpp",
889 R"cpp(
890 namespace a::b { struct Foo {}; }
891 using namespace a;
892
893
894 int main() { a::b::Foo F;}
895 )cpp"},
896 {R"cpp(
897 namespace a::b { struct Foo {}; }
898 using namespace a;
899 using namespace a::b;
900 using namespace [[b]];
901 int main() { Foo F;}
902 )cpp",
903 R"cpp(
904 namespace a::b { struct Foo {}; }
905 using namespace a;
906
907
908 int main() { b::Foo F;}
909 )cpp"},
910 {// Enumerators.
911 R"cpp(
912 namespace tokens {
913 enum Token {
914 comma, identifier, numeric
915 };
916 }
917 using namespace tok^ens;
918 int main() {
919 auto x = comma;
920 }
921 )cpp",
922 R"cpp(
923 namespace tokens {
924 enum Token {
925 comma, identifier, numeric
926 };
927 }
928
929 int main() {
930 auto x = tokens::comma;
931 }
932 )cpp"},
933 {// inline namespaces.
934 R"cpp(
935 namespace std { inline namespace ns1 { inline namespace ns2 { struct vector {}; }}}
936 using namespace st^d;
937 int main() {
938 vector V;
939 }
940 )cpp",
941 R"cpp(
942 namespace std { inline namespace ns1 { inline namespace ns2 { struct vector {}; }}}
943
944 int main() {
945 std::vector V;
946 }
947 )cpp"}};
948 for (auto C : Cases)
949 EXPECT_EQ(C.second, apply(C.first)) << C.first;
950 }
951
952 TWEAK_TEST(DefineInline);
953 TEST_F(DefineInlineTest, TriggersOnFunctionDecl) {
954 // Basic check for function body and signature.
955 EXPECT_AVAILABLE(R"cpp(
956 class Bar {
957 void baz();
958 };
959
960 [[void [[Bar::[[b^a^z]]]]() [[{
961 return;
962 }]]]]
963
964 void foo();
965 [[void [[f^o^o]]() [[{
966 return;
967 }]]]]
968 )cpp");
969
970 EXPECT_UNAVAILABLE(R"cpp(
971 // Not a definition
972 vo^i[[d^ ^f]]^oo();
973
974 [[vo^id ]]foo[[()]] {[[
975 [[(void)(5+3);
976 return;]]
977 }]]
978
979 // Definition with no body.
980 class Bar { Bar() = def^ault; }
981 )cpp");
982 }
983
984 TEST_F(DefineInlineTest, NoForwardDecl) {
985 Header = "void bar();";
986 EXPECT_UNAVAILABLE(R"cpp(
987 void bar() {
988 return;
989 }
990 // FIXME: Generate a decl in the header.
991 void fo^o() {
992 return;
993 })cpp");
994 }
995
996 TEST_F(DefineInlineTest, ReferencedDecls) {
997 EXPECT_AVAILABLE(R"cpp(
998 void bar();
999 void foo(int test);
1000
1001 void fo^o(int baz) {
1002 int x = 10;
1003 bar();
1004 })cpp");
1005
1006 // Internal symbol usage.
1007 Header = "void foo(int test);";
1008 EXPECT_UNAVAILABLE(R"cpp(
1009 void bar();
1010 void fo^o(int baz) {
1011 int x = 10;
1012 bar();
1013 })cpp");
1014
1015 // Becomes available after making symbol visible.
1016 Header = "void bar();" + Header;
1017 EXPECT_AVAILABLE(R"cpp(
1018 void fo^o(int baz) {
1019 int x = 10;
1020 bar();
1021 })cpp");
1022
1023 // FIXME: Move declaration below bar to make it visible.
1024 Header.clear();
1025 EXPECT_UNAVAILABLE(R"cpp(
1026 void foo();
1027 void bar();
1028
1029 void fo^o() {
1030 bar();
1031 })cpp");
1032
1033 // Order doesn't matter within a class.
1034 EXPECT_AVAILABLE(R"cpp(
1035 class Bar {
1036 void foo();
1037 void bar();
1038 };
1039
1040 void Bar::fo^o() {
1041 bar();
1042 })cpp");
1043
1044 // FIXME: Perform include insertion to make symbol visible.
1045 ExtraFiles["a.h"] = "void bar();";
1046 Header = "void foo(int test);";
1047 EXPECT_UNAVAILABLE(R"cpp(
1048 #include "a.h"
1049 void fo^o(int baz) {
1050 int x = 10;
1051 bar();
1052 })cpp");
1053 }
1054
1055 TEST_F(DefineInlineTest, TemplateSpec) {
1056 EXPECT_UNAVAILABLE(R"cpp(
1057 template <typename T> void foo();
1058 template<> void foo<char>();
1059
1060 template<> void f^oo<int>() {
1061 })cpp");
1062 EXPECT_UNAVAILABLE(R"cpp(
1063 template <typename T> void foo();
1064
1065 template<> void f^oo<int>() {
1066 })cpp");
1067 EXPECT_UNAVAILABLE(R"cpp(
1068 template <typename T> struct Foo { void foo(); };
1069
1070 template <typename T> void Foo<T>::f^oo() {
1071 })cpp");
1072 EXPECT_AVAILABLE(R"cpp(
1073 template <typename T> void foo();
1074 void bar();
1075 template <> void foo<int>();
1076
1077 template<> void f^oo<int>() {
1078 bar();
1079 })cpp");
1080 }
1081
1082 TEST_F(DefineInlineTest, CheckForCanonDecl) {
1083 EXPECT_UNAVAILABLE(R"cpp(
1084 void foo();
1085
1086 void bar() {}
1087 void f^oo() {
1088 // This bar normally refers to the definition just above, but it is not
1089 // visible from the forward declaration of foo.
1090 bar();
1091 })cpp");
1092 // Make it available with a forward decl.
1093 EXPECT_AVAILABLE(R"cpp(
1094 void bar();
1095 void foo();
1096
1097 void bar() {}
1098 void f^oo() {
1099 bar();
1100 })cpp");
1101 }
1102
1103 TEST_F(DefineInlineTest, UsingShadowDecls) {
1104 // Template body is not parsed until instantiation time on windows, which
1105 // results in arbitrary failures as function body becomes NULL.
1106 ExtraArgs.push_back("-fno-delayed-template-parsing");
1107 EXPECT_UNAVAILABLE(R"cpp(
1108 namespace ns1 { void foo(int); }
1109 namespace ns2 { void foo(int*); }
1110 template <typename T>
1111 void bar();
1112
1113 using ns1::foo;
1114 using ns2::foo;
1115
1116 template <typename T>
1117 void b^ar() {
1118 foo(T());
1119 })cpp");
1120 }
1121
1122 TEST_F(DefineInlineTest, TransformNestedNamespaces) {
1123 auto Test = R"cpp(
1124 namespace a {
1125 void bar();
1126 namespace b {
1127 void baz();
1128 namespace c {
1129 void aux();
1130 }
1131 }
1132 }
1133
1134 void foo();
1135 using namespace a;
1136 using namespace b;
1137 using namespace c;
1138 void f^oo() {
1139 bar();
1140 a::bar();
1141
1142 baz();
1143 b::baz();
1144 a::b::baz();
1145
1146 aux();
1147 c::aux();
1148 b::c::aux();
1149 a::b::c::aux();
1150 })cpp";
1151 auto Expected = R"cpp(
1152 namespace a {
1153 void bar();
1154 namespace b {
1155 void baz();
1156 namespace c {
1157 void aux();
1158 }
1159 }
1160 }
1161
1162 void foo(){
1163 a::bar();
1164 a::bar();
1165
1166 a::b::baz();
1167 a::b::baz();
1168 a::b::baz();
1169
1170 a::b::c::aux();
1171 a::b::c::aux();
1172 a::b::c::aux();
1173 a::b::c::aux();
1174 }
1175 using namespace a;
1176 using namespace b;
1177 using namespace c;
1178 )cpp";
1179 EXPECT_EQ(apply(Test), Expected);
1180 }
1181
1182 TEST_F(DefineInlineTest, TransformUsings) {
1183 auto Test = R"cpp(
1184 namespace a { namespace b { namespace c { void aux(); } } }
1185
1186 void foo();
1187 void f^oo() {
1188 using namespace a;
1189 using namespace b;
1190 using namespace c;
1191 using c::aux;
1192 namespace d = c;
1193 })cpp";
1194 auto Expected = R"cpp(
1195 namespace a { namespace b { namespace c { void aux(); } } }
1196
1197 void foo(){
1198 using namespace a;
1199 using namespace a::b;
1200 using namespace a::b::c;
1201 using a::b::c::aux;
1202 namespace d = a::b::c;
1203 }
1204 )cpp";
1205 EXPECT_EQ(apply(Test), Expected);
1206 }
1207
1208 TEST_F(DefineInlineTest, TransformDecls) {
1209 auto Test = R"cpp(
1210 void foo();
1211 void f^oo() {
1212 class Foo {
1213 public:
1214 void foo();
1215 int x;
1216 static int y;
1217 };
1218 Foo::y = 0;
1219
1220 enum En { Zero, One };
1221 En x = Zero;
1222
1223 enum class EnClass { Zero, One };
1224 EnClass y = EnClass::Zero;
1225 })cpp";
1226 auto Expected = R"cpp(
1227 void foo(){
1228 class Foo {
1229 public:
1230 void foo();
1231 int x;
1232 static int y;
1233 };
1234 Foo::y = 0;
1235
1236 enum En { Zero, One };
1237 En x = Zero;
1238
1239 enum class EnClass { Zero, One };
1240 EnClass y = EnClass::Zero;
1241 }
1242 )cpp";
1243 EXPECT_EQ(apply(Test), Expected);
1244 }
1245
1246 TEST_F(DefineInlineTest, TransformTemplDecls) {
1247 auto Test = R"cpp(
1248 namespace a {
1249 template <typename T> class Bar {
1250 public:
1251 void bar();
1252 };
1253 template <typename T> T bar;
1254 template <typename T> void aux() {}
1255 }
1256
1257 void foo();
1258
1259 using namespace a;
1260 void f^oo() {
1261 bar<Bar<int>>.bar();
1262 aux<Bar<int>>();
1263 })cpp";
1264 auto Expected = R"cpp(
1265 namespace a {
1266 template <typename T> class Bar {
1267 public:
1268 void bar();
1269 };
1270 template <typename T> T bar;
1271 template <typename T> void aux() {}
1272 }
1273
1274 void foo(){
1275 a::bar<a::Bar<int>>.bar();
1276 a::aux<a::Bar<int>>();
1277 }
1278
1279 using namespace a;
1280 )cpp";
1281 EXPECT_EQ(apply(Test), Expected);
1282 }
1283
1284 TEST_F(DefineInlineTest, TransformMembers) {
1285 auto Test = R"cpp(
1286 class Foo {
1287 void foo();
1288 };
1289
1290 void Foo::f^oo() {
1291 return;
1292 })cpp";
1293 auto Expected = R"cpp(
1294 class Foo {
1295 void foo(){
1296 return;
1297 }
1298 };
1299
1300 )cpp";
1301 EXPECT_EQ(apply(Test), Expected);
1302
1303 ExtraFiles["a.h"] = R"cpp(
1304 class Foo {
1305 void foo();
1306 };)cpp";
1307
1308 llvm::StringMap<std::string> EditedFiles;
1309 Test = R"cpp(
1310 #include "a.h"
1311 void Foo::f^oo() {
1312 return;
1313 })cpp";
1314 Expected = R"cpp(
1315 #include "a.h"
1316 )cpp";
1317 EXPECT_EQ(apply(Test, &EditedFiles), Expected);
1318
1319 Expected = R"cpp(
1320 class Foo {
1321 void foo(){
1322 return;
1323 }
1324 };)cpp";
1325 EXPECT_THAT(EditedFiles,
1326 ElementsAre(FileWithContents(testPath("a.h"), Expected)));
1327 }
1328
1329 TEST_F(DefineInlineTest, TransformDependentTypes) {
1330 auto Test = R"cpp(
1331 namespace a {
1332 template <typename T> class Bar {};
1333 }
1334
1335 template <typename T>
1336 void foo();
1337
1338 using namespace a;
1339 template <typename T>
1340 void f^oo() {
1341 Bar<T> B;
1342 Bar<Bar<T>> q;
1343 })cpp";
1344 auto Expected = R"cpp(
1345 namespace a {
1346 template <typename T> class Bar {};
1347 }
1348
1349 template <typename T>
1350 void foo(){
1351 a::Bar<T> B;
1352 a::Bar<a::Bar<T>> q;
1353 }
1354
1355 using namespace a;
1356 )cpp";
1357
1358 // Template body is not parsed until instantiation time on windows, which
1359 // results in arbitrary failures as function body becomes NULL.
1360 ExtraArgs.push_back("-fno-delayed-template-parsing");
1361 EXPECT_EQ(apply(Test), Expected);
1362 }
1363
1364 TEST_F(DefineInlineTest, TransformFunctionTempls) {
1365 // Check we select correct specialization decl.
1366 std::pair<llvm::StringRef, llvm::StringRef> Cases[] = {
1367 {R"cpp(
1368 template <typename T>
1369 void foo(T p);
1370
1371 template <>
1372 void foo<int>(int p);
1373
1374 template <>
1375 void foo<char>(char p);
1376
1377 template <>
1378 void fo^o<int>(int p) {
1379 return;
1380 })cpp",
1381 R"cpp(
1382 template <typename T>
1383 void foo(T p);
1384
1385 template <>
1386 void foo<int>(int p){
1387 return;
1388 }
1389
1390 template <>
1391 void foo<char>(char p);
1392
1393 )cpp"},
1394 {// Make sure we are not selecting the first specialization all the time.
1395 R"cpp(
1396 template <typename T>
1397 void foo(T p);
1398
1399 template <>
1400 void foo<int>(int p);
1401
1402 template <>
1403 void foo<char>(char p);
1404
1405 template <>
1406 void fo^o<char>(char p) {
1407 return;
1408 })cpp",
1409 R"cpp(
1410 template <typename T>
1411 void foo(T p);
1412
1413 template <>
1414 void foo<int>(int p);
1415
1416 template <>
1417 void foo<char>(char p){
1418 return;
1419 }
1420
1421 )cpp"},
1422 {R"cpp(
1423 template <typename T>
1424 void foo(T p);
1425
1426 template <>
1427 void foo<int>(int p);
1428
1429 template <typename T>
1430 void fo^o(T p) {
1431 return;
1432 })cpp",
1433 R"cpp(
1434 template <typename T>
1435 void foo(T p){
1436 return;
1437 }
1438
1439 template <>
1440 void foo<int>(int p);
1441
1442 )cpp"},
1443 };
1444 // Template body is not parsed until instantiation time on windows, which
1445 // results in arbitrary failures as function body becomes NULL.
1446 ExtraArgs.push_back("-fno-delayed-template-parsing");
1447 for (const auto &Case : Cases)
1448 EXPECT_EQ(apply(Case.first), Case.second) << Case.first;
1449 }
1450
1451 TEST_F(DefineInlineTest, TransformTypeLocs) {
1452 auto Test = R"cpp(
1453 namespace a {
1454 template <typename T> class Bar {
1455 public:
1456 template <typename Q> class Baz {};
1457 };
1458 class Foo{};
1459 }
1460
1461 void foo();
1462
1463 using namespace a;
1464 void f^oo() {
1465 Bar<int> B;
1466 Foo foo;
1467 a::Bar<Bar<int>>::Baz<Bar<int>> q;
1468 })cpp";
1469 auto Expected = R"cpp(
1470 namespace a {
1471 template <typename T> class Bar {
1472 public:
1473 template <typename Q> class Baz {};
1474 };
1475 class Foo{};
1476 }
1477
1478 void foo(){
1479 a::Bar<int> B;
1480 a::Foo foo;
1481 a::Bar<a::Bar<int>>::Baz<a::Bar<int>> q;
1482 }
1483
1484 using namespace a;
1485 )cpp";
1486 EXPECT_EQ(apply(Test), Expected);
1487 }
1488
1489 TEST_F(DefineInlineTest, TransformDeclRefs) {
1490 auto Test = R"cpp(
1491 namespace a {
1492 template <typename T> class Bar {
1493 public:
1494 void foo();
1495 static void bar();
1496 int x;
1497 static int y;
1498 };
1499 void bar();
1500 void test();
1501 }
1502
1503 void foo();
1504 using namespace a;
1505 void f^oo() {
1506 a::Bar<int> B;
1507 B.foo();
1508 a::bar();
1509 Bar<Bar<int>>::bar();
1510 a::Bar<int>::bar();
1511 B.x = Bar<int>::y;
1512 Bar<int>::y = 3;
1513 bar();
1514 a::test();
1515 })cpp";
1516 auto Expected = R"cpp(
1517 namespace a {
1518 template <typename T> class Bar {
1519 public:
1520 void foo();
1521 static void bar();
1522 int x;
1523 static int y;
1524 };
1525 void bar();
1526 void test();
1527 }
1528
1529 void foo(){
1530 a::Bar<int> B;
1531 B.foo();
1532 a::bar();
1533 a::Bar<a::Bar<int>>::bar();
1534 a::Bar<int>::bar();
1535 B.x = a::Bar<int>::y;
1536 a::Bar<int>::y = 3;
1537 a::bar();
1538 a::test();
1539 }
1540 using namespace a;
1541 )cpp";
1542 EXPECT_EQ(apply(Test), Expected);
1543 }
1544
1545 TEST_F(DefineInlineTest, StaticMembers) {
1546 auto Test = R"cpp(
1547 namespace ns { class X { static void foo(); void bar(); }; }
1548 void ns::X::b^ar() {
1549 foo();
1550 })cpp";
1551 auto Expected = R"cpp(
1552 namespace ns { class X { static void foo(); void bar(){
1553 foo();
1554 } }; }
1555 )cpp";
1556 EXPECT_EQ(apply(Test), Expected);
1557 }
1558
1559 TEST_F(DefineInlineTest, TransformParamNames) {
1560 std::pair<llvm::StringRef, llvm::StringRef> Cases[] = {
1561 {R"cpp(
1562 void foo(int, bool b, int T\
1563 est);
1564 void ^foo(int f, bool x, int z) {})cpp",
1565 R"cpp(
1566 void foo(int f, bool x, int z){}
1567 )cpp"},
1568 {R"cpp(
1569 #define PARAM int Z
1570 void foo(PARAM);
1571
1572 void ^foo(int X) {})cpp",
1573 "fail: Cant rename parameter inside macro body."},
1574 {R"cpp(
1575 #define TYPE int
1576 #define PARAM TYPE Z
1577 #define BODY(x) 5 * (x) + 2
1578 template <int P>
1579 void foo(PARAM, TYPE Q, TYPE, TYPE W = BODY(P));
1580 template <int x>
1581 void ^foo(int Z, int b, int c, int d) {})cpp",
1582 R"cpp(
1583 #define TYPE int
1584 #define PARAM TYPE Z
1585 #define BODY(x) 5 * (x) + 2
1586 template <int x>
1587 void foo(PARAM, TYPE b, TYPE c, TYPE d = BODY(x)){}
1588 )cpp"},
1589 };
1590 ExtraArgs.push_back("-fno-delayed-template-parsing");
1591 for (const auto &Case : Cases)
1592 EXPECT_EQ(apply(Case.first), Case.second) << Case.first;
1593 }
1594
1595 TEST_F(DefineInlineTest, TransformTemplParamNames) {
1596 auto Test = R"cpp(
1597 struct Foo {
1598 struct Bar {
1599 template <class, class X,
1600 template<typename> class, template<typename> class Y,
1601 int, int Z>
1602 void foo(X, Y<X>, int W = 5 * Z + 2);
1603 };
1604 };
1605
1606 template <class T, class U,
1607 template<typename> class V, template<typename> class W,
1608 int X, int Y>
1609 void Foo::Bar::f^oo(U, W<U>, int Q) {})cpp";
1610 auto Expected = R"cpp(
1611 struct Foo {
1612 struct Bar {
1613 template <class T, class U,
1614 template<typename> class V, template<typename> class W,
1615 int X, int Y>
1616 void foo(U, W<U>, int Q = 5 * Y + 2){}
1617 };
1618 };
1619
1620 )cpp";
1621 ExtraArgs.push_back("-fno-delayed-template-parsing");
1622 EXPECT_EQ(apply(Test), Expected);
1623 }
1624
1625 TEST_F(DefineInlineTest, TransformInlineNamespaces) {
1626 auto Test = R"cpp(
1627 namespace a { inline namespace b { namespace { struct Foo{}; } } }
1628 void foo();
1629
1630 using namespace a;
1631 void ^foo() {Foo foo;})cpp";
1632 auto Expected = R"cpp(
1633 namespace a { inline namespace b { namespace { struct Foo{}; } } }
1634 void foo(){a::Foo foo;}
1635
1636 using namespace a;
1637 )cpp";
1638 EXPECT_EQ(apply(Test), Expected);
1639 }
1640
1641 TEST_F(DefineInlineTest, TokensBeforeSemicolon) {
1642 std::pair<llvm::StringRef, llvm::StringRef> Cases[] = {
1643 {R"cpp(
1644 void foo() /*Comment -_-*/ /*Com 2*/ ;
1645 void fo^o() { return ; })cpp",
1646 R"cpp(
1647 void foo() /*Comment -_-*/ /*Com 2*/ { return ; }
1648 )cpp"},
1649
1650 {R"cpp(
1651 void foo();
1652 void fo^o() { return ; })cpp",
1653 R"cpp(
1654 void foo(){ return ; }
1655 )cpp"},
1656
1657 {R"cpp(
1658 #define SEMI ;
1659 void foo() SEMI
1660 void fo^o() { return ; })cpp",
1661 "fail: Couldn't find semicolon for target declaration."},
1662 };
1663 for (const auto &Case : Cases)
1664 EXPECT_EQ(apply(Case.first), Case.second) << Case.first;
1665 }
1666
1667 TEST_F(DefineInlineTest, HandleMacros) {
1668 EXPECT_UNAVAILABLE(R"cpp(
1669 #define BODY { return; }
1670 void foo();
1671 void f^oo()BODY)cpp");
1672
1673 EXPECT_UNAVAILABLE(R"cpp(
1674 #define BODY void foo(){ return; }
1675 void foo();
1676 [[BODY]])cpp");
1677
1678 std::pair<llvm::StringRef, llvm::StringRef> Cases[] = {
1679 // We don't qualify declarations coming from macros.
1680 {R"cpp(
1681 #define BODY Foo
1682 namespace a { class Foo{}; }
1683 void foo();
1684 using namespace a;
1685 void f^oo(){BODY})cpp",
1686 R"cpp(
1687 #define BODY Foo
1688 namespace a { class Foo{}; }
1689 void foo(){BODY}
1690 using namespace a;
1691 )cpp"},
1692
1693 // Macro is not visible at declaration location, but we proceed.
1694 {R"cpp(
1695 void foo();
1696 #define BODY return;
1697 void f^oo(){BODY})cpp",
1698 R"cpp(
1699 void foo(){BODY}
1700 #define BODY return;
1701 )cpp"},
1702
1703 {R"cpp(
1704 #define TARGET void foo()
1705 TARGET;
1706 void f^oo(){ return; })cpp",
1707 R"cpp(
1708 #define TARGET void foo()
1709 TARGET{ return; }
1710 )cpp"},
1711
1712 {R"cpp(
1713 #define TARGET foo
1714 void TARGET();
1715 void f^oo(){ return; })cpp",
1716 R"cpp(
1717 #define TARGET foo
1718 void TARGET(){ return; }
1719 )cpp"},
1720 };
1721 for (const auto &Case : Cases)
1722 EXPECT_EQ(apply(Case.first), Case.second) << Case.first;
1723 }
1724
1725 TEST_F(DefineInlineTest, DropCommonNameSpecifiers) {
1726 struct {
1727 llvm::StringRef Test;
1728 llvm::StringRef Expected;
1729 } Cases[] = {
1730 {R"cpp(
1731 namespace a { namespace b { void aux(); } }
1732 namespace ns1 {
1733 void foo();
1734 namespace qq { void test(); }
1735 namespace ns2 {
1736 void bar();
1737 namespace ns3 { void baz(); }
1738 }
1739 }
1740
1741 using namespace a;
1742 using namespace a::b;
1743 using namespace ns1::qq;
1744 void ns1::ns2::ns3::b^az() {
1745 foo();
1746 bar();
1747 baz();
1748 ns1::ns2::ns3::baz();
1749 aux();
1750 test();
1751 })cpp",
1752 R"cpp(
1753 namespace a { namespace b { void aux(); } }
1754 namespace ns1 {
1755 void foo();
1756 namespace qq { void test(); }
1757 namespace ns2 {
1758 void bar();
1759 namespace ns3 { void baz(){
1760 foo();
1761 bar();
1762 baz();
1763 ns1::ns2::ns3::baz();
1764 a::b::aux();
1765 qq::test();
1766 } }
1767 }
1768 }
1769
1770 using namespace a;
1771 using namespace a::b;
1772 using namespace ns1::qq;
1773 )cpp"},
1774 {R"cpp(
1775 namespace ns1 {
1776 namespace qq { struct Foo { struct Bar {}; }; using B = Foo::Bar; }
1777 namespace ns2 { void baz(); }
1778 }
1779
1780 using namespace ns1::qq;
1781 void ns1::ns2::b^az() { Foo f; B b; })cpp",
1782 R"cpp(
1783 namespace ns1 {
1784 namespace qq { struct Foo { struct Bar {}; }; using B = Foo::Bar; }
1785 namespace ns2 { void baz(){ qq::Foo f; qq::B b; } }
1786 }
1787
1788 using namespace ns1::qq;
1789 )cpp"},
1790 {R"cpp(
1791 namespace ns1 {
1792 namespace qq {
1793 template<class T> struct Foo { template <class U> struct Bar {}; };
1794 template<class T, class U>
1795 using B = typename Foo<T>::template Bar<U>;
1796 }
1797 namespace ns2 { void baz(); }
1798 }
1799
1800 using namespace ns1::qq;
1801 void ns1::ns2::b^az() { B<int, bool> b; })cpp",
1802 R"cpp(
1803 namespace ns1 {
1804 namespace qq {
1805 template<class T> struct Foo { template <class U> struct Bar {}; };
1806 template<class T, class U>
1807 using B = typename Foo<T>::template Bar<U>;
1808 }
1809 namespace ns2 { void baz(){ qq::B<int, bool> b; } }
1810 }
1811
1812 using namespace ns1::qq;
1813 )cpp"},
1814 };
1815 for (const auto &Case : Cases)
1816 EXPECT_EQ(apply(Case.Test), Case.Expected) << Case.Test;
1817 }
1818
1819 TEST_F(DefineInlineTest, QualifyWithUsingDirectives) {
1820 llvm::StringRef Test = R"cpp(
1821 namespace a {
1822 void bar();
1823 namespace b { struct Foo{}; void aux(); }
1824 namespace c { void cux(); }
1825 }
1826 using namespace a;
1827 using X = b::Foo;
1828 void foo();
1829
1830 using namespace b;
1831 using namespace c;
1832 void ^foo() {
1833 cux();
1834 bar();
1835 X x;
1836 aux();
1837 using namespace c;
1838 // FIXME: The last reference to cux() in body of foo should not be
1839 // qualified, since there is a using directive inside the function body.
1840 cux();
1841 })cpp";
1842 llvm::StringRef Expected = R"cpp(
1843 namespace a {
1844 void bar();
1845 namespace b { struct Foo{}; void aux(); }
1846 namespace c { void cux(); }
1847 }
1848 using namespace a;
1849 using X = b::Foo;
1850 void foo(){
1851 c::cux();
1852 bar();
1853 X x;
1854 b::aux();
1855 using namespace c;
1856 // FIXME: The last reference to cux() in body of foo should not be
1857 // qualified, since there is a using directive inside the function body.
1858 c::cux();
1859 }
1860
1861 using namespace b;
1862 using namespace c;
1863 )cpp";
1864 EXPECT_EQ(apply(Test), Expected) << Test;
1865 }
1866
1867 TEST_F(DefineInlineTest, AddInline) {
1868 ExtraArgs.push_back("-fno-delayed-template-parsing");
1869 llvm::StringMap<std::string> EditedFiles;
1870 ExtraFiles["a.h"] = "void foo();";
1871 apply(R"cpp(#include "a.h"
1872 void fo^o() {})cpp",
1873 &EditedFiles);
1874 EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
1875 testPath("a.h"), "inline void foo(){}")));
1876
1877 // Check we put inline before cv-qualifiers.
1878 ExtraFiles["a.h"] = "const int foo();";
1879 apply(R"cpp(#include "a.h"
1880 const int fo^o() {})cpp",
1881 &EditedFiles);
1882 EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
1883 testPath("a.h"), "inline const int foo(){}")));
1884
1885 // No double inline.
1886 ExtraFiles["a.h"] = "inline void foo();";
1887 apply(R"cpp(#include "a.h"
1888 inline void fo^o() {})cpp",
1889 &EditedFiles);
1890 EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
1891 testPath("a.h"), "inline void foo(){}")));
1892
1893 // Constexprs don't need "inline".
1894 ExtraFiles["a.h"] = "constexpr void foo();";
1895 apply(R"cpp(#include "a.h"
1896 constexpr void fo^o() {})cpp",
1897 &EditedFiles);
1898 EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
1899 testPath("a.h"), "constexpr void foo(){}")));
1900
1901 // Class members don't need "inline".
1902 ExtraFiles["a.h"] = "struct Foo { void foo(); }";
1903 apply(R"cpp(#include "a.h"
1904 void Foo::fo^o() {})cpp",
1905 &EditedFiles);
1906 EXPECT_THAT(EditedFiles,
1907 testing::ElementsAre(FileWithContents(
1908 testPath("a.h"), "struct Foo { void foo(){} }")));
1909
1910 // Function template doesn't need to be "inline"d.
1911 ExtraFiles["a.h"] = "template <typename T> void foo();";
1912 apply(R"cpp(#include "a.h"
1913 template <typename T>
1914 void fo^o() {})cpp",
1915 &EditedFiles);
1916 EXPECT_THAT(EditedFiles,
1917 testing::ElementsAre(FileWithContents(
1918 testPath("a.h"), "template <typename T> void foo(){}")));
1919
1920 // Specializations needs to be marked "inline".
1921 ExtraFiles["a.h"] = R"cpp(
1922 template <typename T> void foo();
1923 template <> void foo<int>();)cpp";
1924 apply(R"cpp(#include "a.h"
1925 template <>
1926 void fo^o<int>() {})cpp",
1927 &EditedFiles);
1928 EXPECT_THAT(EditedFiles,
1929 testing::ElementsAre(FileWithContents(testPath("a.h"),
1930 R"cpp(
1931 template <typename T> void foo();
1932 template <> inline void foo<int>(){})cpp")));
1933 }
1934
1935 TWEAK_TEST(DefineOutline);
1936 TEST_F(DefineOutlineTest, TriggersOnFunctionDecl) {
1937 FileName = "Test.cpp";
1938 // Not available unless in a header file.
1939 EXPECT_UNAVAILABLE(R"cpp(
1940 [[void [[f^o^o]]() [[{
1941 return;
1942 }]]]])cpp");
1943
1944 FileName = "Test.hpp";
1945 // Not available unless function name or fully body is selected.
1946 EXPECT_UNAVAILABLE(R"cpp(
1947 // Not a definition
1948 vo^i[[d^ ^f]]^oo();
1949
1950 [[vo^id ]]foo[[()]] {[[
1951 [[(void)(5+3);
1952 return;]]
1953 }]])cpp");
1954
1955 // Available even if there are no implementation files.
1956 EXPECT_AVAILABLE(R"cpp(
1957 [[void [[f^o^o]]() [[{
1958 return;
1959 }]]]])cpp");
1960
1961 // Not available for out-of-line methods.
1962 EXPECT_UNAVAILABLE(R"cpp(
1963 class Bar {
1964 void baz();
1965 };
1966
1967 [[void [[Bar::[[b^a^z]]]]() [[{
1968 return;
1969 }]]]])cpp");
1970
1971 // Basic check for function body and signature.
1972 EXPECT_AVAILABLE(R"cpp(
1973 class Bar {
1974 [[void [[f^o^o]]() [[{ return; }]]]]
1975 };
1976
1977 void foo();
1978 [[void [[f^o^o]]() [[{
1979 return;
1980 }]]]])cpp");
1981
1982 // Not available on defaulted/deleted members.
1983 EXPECT_UNAVAILABLE(R"cpp(
1984 class Foo {
1985 Fo^o() = default;
1986 F^oo(const Foo&) = delete;
1987 };)cpp");
1988
1989 // Not available within templated classes, as it is hard to spell class name
1990 // out-of-line in such cases.
1991 EXPECT_UNAVAILABLE(R"cpp(
1992 template <typename> struct Foo { void fo^o(){} };
1993 })cpp");
1994 }
1995
1996 TEST_F(DefineOutlineTest, FailsWithoutSource) {
1997 FileName = "Test.hpp";
1998 llvm::StringRef Test = "void fo^o() { return; }";
1999 llvm::StringRef Expected =
2000 "fail: Couldn't find a suitable implementation file.";
2001 EXPECT_EQ(apply(Test), Expected);
2002 }
2003
2004 TEST_F(DefineOutlineTest, ApplyTest) {
2005 llvm::StringMap<std::string> EditedFiles;
2006 ExtraFiles["Test.cpp"] = "";
2007 FileName = "Test.hpp";
2008 // Template body is not parsed until instantiation time on windows, which
2009 // results in arbitrary failures as function body becomes NULL.
2010 ExtraArgs.push_back("-fno-delayed-template-parsing");
2011
2012 struct {
2013 llvm::StringRef Test;
2014 llvm::StringRef ExpectedHeader;
2015 llvm::StringRef ExpectedSource;
2016 } Cases[] = {
2017 // Simple check
2018 {
2019 "void fo^o() { return; }",
2020 "void foo() ;",
2021 "void foo() { return; }",
2022 },
2023 // Templated function.
2024 {
2025 "template <typename T> void fo^o(T, T x) { return; }",
2026 "template <typename T> void foo(T, T x) ;",
2027 "template <typename T> void foo(T, T x) { return; }",
2028 },
2029 {
2030 "template <typename> void fo^o() { return; }",
2031 "template <typename> void foo() ;",
2032 "template <typename> void foo() { return; }",
2033 },
2034 // Template specialization.
2035 {
2036 R"cpp(
2037 template <typename> void foo();
2038 template <> void fo^o<int>() { return; })cpp",
2039 R"cpp(
2040 template <typename> void foo();
2041 template <> void foo<int>() ;)cpp",
2042 "template <> void foo<int>() { return; }",
2043 },
2044 // Default args.
2045 {
2046 "void fo^o(int x, int y = 5, int = 2, int (*foo)(int) = nullptr) {}",
2047 "void foo(int x, int y = 5, int = 2, int (*foo)(int) = nullptr) ;",
2048 "void foo(int x, int y , int , int (*foo)(int) ) {}",
2049 },
2050 // Ctor initializers.
2051 {
2052 R"cpp(
2053 class Foo {
2054 int y = 2;
2055 F^oo(int z) __attribute__((weak)) : bar(2){}
2056 int bar;
2057 int z = 2;
2058 };)cpp",
2059 R"cpp(
2060 class Foo {
2061 int y = 2;
2062 Foo(int z) __attribute__((weak)) ;
2063 int bar;
2064 int z = 2;
2065 };)cpp",
2066 "Foo::Foo(int z) __attribute__((weak)) : bar(2){}\n",
2067 },
2068 // Virt specifiers.
2069 {
2070 R"cpp(
2071 struct A {
2072 virtual void f^oo() {}
2073 };)cpp",
2074 R"cpp(
2075 struct A {
2076 virtual void foo() ;
2077 };)cpp",
2078 " void A::foo() {}\n",
2079 },
2080 {
2081 R"cpp(
2082 struct A {
2083 virtual virtual void virtual f^oo() {}
2084 };)cpp",
2085 R"cpp(
2086 struct A {
2087 virtual virtual void virtual foo() ;
2088 };)cpp",
2089 " void A::foo() {}\n",
2090 },
2091 {
2092 R"cpp(
2093 struct A {
2094 virtual void foo() = 0;
2095 };
2096 struct B : A {
2097 void fo^o() override {}
2098 };)cpp",
2099 R"cpp(
2100 struct A {
2101 virtual void foo() = 0;
2102 };
2103 struct B : A {
2104 void foo() override ;
2105 };)cpp",
2106 "void B::foo() {}\n",
2107 },
2108 {
2109 R"cpp(
2110 struct A {
2111 virtual void foo() = 0;
2112 };
2113 struct B : A {
2114 void fo^o() final {}
2115 };)cpp",
2116 R"cpp(
2117 struct A {
2118 virtual void foo() = 0;
2119 };
2120 struct B : A {
2121 void foo() final ;
2122 };)cpp",
2123 "void B::foo() {}\n",
2124 },
2125 {
2126 R"cpp(
2127 struct A {
2128 virtual void foo() = 0;
2129 };
2130 struct B : A {
2131 void fo^o() final override {}
2132 };)cpp",
2133 R"cpp(
2134 struct A {
2135 virtual void foo() = 0;
2136 };
2137 struct B : A {
2138 void foo() final override ;
2139 };)cpp",
2140 "void B::foo() {}\n",
2141 },
2142 };
2143 for (const auto &Case : Cases) {
2144 SCOPED_TRACE(Case.Test);
2145 EXPECT_EQ(apply(Case.Test, &EditedFiles), Case.ExpectedHeader);
2146 EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
2147 testPath("Test.cpp"), Case.ExpectedSource)));
2148 }
2149 }
2150
2151 TEST_F(DefineOutlineTest, HandleMacros) {
2152 llvm::StringMap<std::string> EditedFiles;
2153 ExtraFiles["Test.cpp"] = "";
2154 FileName = "Test.hpp";
2155 ExtraArgs.push_back("-DVIRTUAL=virtual");
2156 ExtraArgs.push_back("-DOVER=override");
2157
2158 struct {
2159 llvm::StringRef Test;
2160 llvm::StringRef ExpectedHeader;
2161 llvm::StringRef ExpectedSource;
2162 } Cases[] = {
2163 {R"cpp(
2164 #define BODY { return; }
2165 void f^oo()BODY)cpp",
2166 R"cpp(
2167 #define BODY { return; }
2168 void foo();)cpp",
2169 "void foo()BODY"},
2170
2171 {R"cpp(
2172 #define BODY return;
2173 void f^oo(){BODY})cpp",
2174 R"cpp(
2175 #define BODY return;
2176 void foo();)cpp",
2177 "void foo(){BODY}"},
2178
2179 {R"cpp(
2180 #define TARGET void foo()
2181 [[TARGET]]{ return; })cpp",
2182 R"cpp(
2183 #define TARGET void foo()
2184 TARGET;)cpp",
2185 "TARGET{ return; }"},
2186
2187 {R"cpp(
2188 #define TARGET foo
2189 void [[TARGET]](){ return; })cpp",
2190 R"cpp(
2191 #define TARGET foo
2192 void TARGET();)cpp",
2193 "void TARGET(){ return; }"},
2194 {R"cpp(#define VIRT virtual
2195 struct A {
2196 VIRT void f^oo() {}
2197 };)cpp",
2198 R"cpp(#define VIRT virtual
2199 struct A {
2200 VIRT void foo() ;
2201 };)cpp",
2202 " void A::foo() {}\n"},
2203 {R"cpp(
2204 struct A {
2205 VIRTUAL void f^oo() {}
2206 };)cpp",
2207 R"cpp(
2208 struct A {
2209 VIRTUAL void foo() ;
2210 };)cpp",
2211 " void A::foo() {}\n"},
2212 {R"cpp(
2213 struct A {
2214 virtual void foo() = 0;
2215 };
2216 struct B : A {
2217 void fo^o() OVER {}
2218 };)cpp",
2219 R"cpp(
2220 struct A {
2221 virtual void foo() = 0;
2222 };
2223 struct B : A {
2224 void foo() OVER ;
2225 };)cpp",
2226 "void B::foo() {}\n"},
2227 {R"cpp(#define STUPID_MACRO(X) virtual
2228 struct A {
2229 STUPID_MACRO(sizeof sizeof int) void f^oo() {}
2230 };)cpp",
2231 R"cpp(#define STUPID_MACRO(X) virtual
2232 struct A {
2233 STUPID_MACRO(sizeof sizeof int) void foo() ;
2234 };)cpp",
2235 " void A::foo() {}\n"},
2236 };
2237 for (const auto &Case : Cases) {
2238 SCOPED_TRACE(Case.Test);
2239 EXPECT_EQ(apply(Case.Test, &EditedFiles), Case.ExpectedHeader);
2240 EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
2241 testPath("Test.cpp"), Case.ExpectedSource)));
2242 }
2243 }
2244
2245 TEST_F(DefineOutlineTest, QualifyReturnValue) {
2246 FileName = "Test.hpp";
2247 ExtraFiles["Test.cpp"] = "";
2248
2249 struct {
2250 llvm::StringRef Test;
2251 llvm::StringRef ExpectedHeader;
2252 llvm::StringRef ExpectedSource;
2253 } Cases[] = {
2254 {R"cpp(
2255 namespace a { class Foo; }
2256 using namespace a;
2257 Foo fo^o() { return; })cpp",
2258 R"cpp(
2259 namespace a { class Foo; }
2260 using namespace a;
2261 Foo foo() ;)cpp",
2262 "a::Foo foo() { return; }"},
2263 {R"cpp(
2264 namespace a {
2265 class Foo {
2266 class Bar {};
2267 Bar fo^o() { return {}; }
2268 };
2269 })cpp",
2270 R"cpp(
2271 namespace a {
2272 class Foo {
2273 class Bar {};
2274 Bar foo() ;
2275 };
2276 })cpp",
2277 "a::Foo::Bar a::Foo::foo() { return {}; }\n"},
2278 {R"cpp(
2279 class Foo;
2280 Foo fo^o() { return; })cpp",
2281 R"cpp(
2282 class Foo;
2283 Foo foo() ;)cpp",
2284 "Foo foo() { return; }"},
2285 };
2286 llvm::StringMap<std::string> EditedFiles;
2287 for (auto &Case : Cases) {
2288 apply(Case.Test, &EditedFiles);
2289 EXPECT_EQ(apply(Case.Test, &EditedFiles), Case.ExpectedHeader);
2290 EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
2291 testPath("Test.cpp"), Case.ExpectedSource)));
2292 }
2293 }
2294
2295 TEST_F(DefineOutlineTest, QualifyFunctionName) {
2296 FileName = "Test.hpp";
2297 struct {
2298 llvm::StringRef TestHeader;
2299 llvm::StringRef TestSource;
2300 llvm::StringRef ExpectedHeader;
2301 llvm::StringRef ExpectedSource;
2302 } Cases[] = {
2303 {
2304 R"cpp(
2305 namespace a {
2306 namespace b {
2307 class Foo {
2308 void fo^o() {}
2309 };
2310 }
2311 })cpp",
2312 "",
2313 R"cpp(
2314 namespace a {
2315 namespace b {
2316 class Foo {
2317 void foo() ;
2318 };
2319 }
2320 })cpp",
2321 "void a::b::Foo::foo() {}\n",
2322 },
2323 {
2324 "namespace a { namespace b { void f^oo() {} } }",
2325 "namespace a{}",
2326 "namespace a { namespace b { void foo() ; } }",
2327 "namespace a{void b::foo() {} }",
2328 },
2329 {
2330 "namespace a { namespace b { void f^oo() {} } }",
2331 "using namespace a;",
2332 "namespace a { namespace b { void foo() ; } }",
2333 // FIXME: Take using namespace directives in the source file into
2334 // account. This can be spelled as b::foo instead.
2335 "using namespace a;void a::b::foo() {} ",
2336 },
2337 };
2338 llvm::StringMap<std::string> EditedFiles;
2339 for (auto &Case : Cases) {
2340 ExtraFiles["Test.cpp"] = Case.TestSource;
2341 EXPECT_EQ(apply(Case.TestHeader, &EditedFiles), Case.ExpectedHeader);
2342 EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
2343 testPath("Test.cpp"), Case.ExpectedSource)))
2344 << Case.TestHeader;
2345 }
2346 }
2347
2348 TEST_F(DefineOutlineTest, FailsMacroSpecifier) {
2349 FileName = "Test.hpp";
2350 ExtraFiles["Test.cpp"] = "";
2351 ExtraArgs.push_back("-DFINALOVER=final override");
2352
2353 std::pair<StringRef, StringRef> Cases[] = {
2354 {
2355 R"cpp(
2356 #define VIRT virtual void
2357 struct A {
2358 VIRT fo^o() {}
2359 };)cpp",
2360 "fail: define outline: Can't move out of line as function has a "
2361 "macro `virtual` specifier."},
2362 {
2363 R"cpp(
2364 #define OVERFINAL final override
2365 struct A {
2366 virtual void foo() {}
2367 };
2368 struct B : A {
2369 void fo^o() OVERFINAL {}
2370 };)cpp",
2371 "fail: define outline: Can't move out of line as function has a "
2372 "macro `override` specifier.\ndefine outline: Can't move out of line "
2373 "as function has a macro `final` specifier."},
2374 {
2375 R"cpp(
2376 struct A {
2377 virtual void foo() {}
2378 };
2379 struct B : A {
2380 void fo^o() FINALOVER {}
2381 };)cpp",
2382 "fail: define outline: Can't move out of line as function has a "
2383 "macro `override` specifier.\ndefine outline: Can't move out of line "
2384 "as function has a macro `final` specifier."},
2385 };
2386 for (const auto &Case : Cases) {
2387 EXPECT_EQ(apply(Case.first), Case.second);
2388 }
2389 }
2390 } // namespace
2391 } // namespace clangd
2392 } // namespace clang
Contents
llvm::StringRef Contents
Definition: CodeComplete.cpp:1021
TweakTesting.h
SourceCode.h
InMemoryFileSystem
llvm::IntrusiveRefCntPtr< llvm::vfs::InMemoryFileSystem > InMemoryFileSystem
Definition: IndexActionTests.cpp:108
TestFS.h
TestTU.h
TWEAK_TEST
#define TWEAK_TEST(TweakID)
Definition: TweakTesting.h:103
Tweak.h
clang::clangd::TEST_F
TEST_F(BackgroundIndexTest, NoCrashOnErrorFile)
Definition: BackgroundIndexTests.cpp:88
EXPECT_UNAVAILABLE
#define EXPECT_UNAVAILABLE(MarkedCode)
Definition: TweakTesting.h:115
Annotations.h
clang::clangd::TEST
TEST(BackgroundQueueTest, Priority)
Definition: BackgroundIndexTests.cpp:647
clang::clangd::testPath
std::string testPath(PathRef File)
Definition: TestFS.cpp:82
clang::clangd::Path
std::string Path
A typedef to represent a file path.
Definition: Path.h:20
clang::clangd::testRoot
const char * testRoot()
Definition: TestFS.cpp:74
FileName
PathRef FileName
Definition: CodeComplete.cpp:1018
clang::clangd::FileEdits
llvm::StringMap< Edit > FileEdits
A mapping from absolute file path (the one used for accessing the underlying VFS) to edits...
Definition: SourceCode.h:222
clang::clangd::CompletionItemKind::Function
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
clang::clangd::Tweak::Effect::fileEdit
static llvm::Expected< std::pair< Path, Edit > > fileEdit(const SourceManager &SM, FileID FID, tooling::Replacements Replacements)
Path is the absolute, symlink-resolved path for the file pointed by FID in SM.
Definition: Tweak.cpp:93
Expected
std::vector< const char * > Expected
Definition: PrintASTTests.cpp:27
EXPECT_AVAILABLE
#define EXPECT_AVAILABLE(MarkedCode)
Definition: TweakTesting.h:109