[TableGen] Fix validateOperandClass for non Phyical Reg (#118146)
[llvm-project.git] / clang-tools-extra / clangd / unittests / tweaks / DefineOutlineTests.cpp
blobb5f09f9b14604f4b164c2853750210cb718da8ef
1 //===-- DefineOutline.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 //===----------------------------------------------------------------------===//
9 #include "TestFS.h"
10 #include "TweakTesting.h"
11 #include "gmock/gmock.h"
12 #include "gtest/gtest.h"
14 namespace clang {
15 namespace clangd {
16 namespace {
18 TWEAK_TEST(DefineOutline);
20 TEST_F(DefineOutlineTest, TriggersOnFunctionDecl) {
21 FileName = "Test.cpp";
22 // Not available for free function unless in a header file.
23 EXPECT_UNAVAILABLE(R"cpp(
24 [[void [[f^o^o]]() [[{
25 return;
26 }]]]])cpp");
28 // Available in soure file.
29 EXPECT_AVAILABLE(R"cpp(
30 struct Foo {
31 void f^oo() {}
33 )cpp");
35 // Available within named namespace in source file.
36 EXPECT_AVAILABLE(R"cpp(
37 namespace N {
38 struct Foo {
39 void f^oo() {}
41 } // namespace N
42 )cpp");
44 // Available within anonymous namespace in source file.
45 EXPECT_AVAILABLE(R"cpp(
46 namespace {
47 struct Foo {
48 void f^oo() {}
50 } // namespace
51 )cpp");
53 // Not available for out-of-line method.
54 EXPECT_UNAVAILABLE(R"cpp(
55 class Bar {
56 void baz();
59 [[void [[Bar::[[b^a^z]]]]() [[{
60 return;
61 }]]]])cpp");
63 FileName = "Test.hpp";
64 // Not available unless function name or fully body is selected.
65 EXPECT_UNAVAILABLE(R"cpp(
66 // Not a definition
67 vo^i[[d^ ^f]]^oo();
69 [[vo^id ]]foo[[()]] {[[
70 [[(void)(5+3);
71 return;]]
72 }]])cpp");
74 // Available even if there are no implementation files.
75 EXPECT_AVAILABLE(R"cpp(
76 [[void [[f^o^o]]() [[{
77 return;
78 }]]]])cpp");
80 // Not available for out-of-line methods.
81 EXPECT_UNAVAILABLE(R"cpp(
82 class Bar {
83 void baz();
86 [[void [[Bar::[[b^a^z]]]]() [[{
87 return;
88 }]]]])cpp");
90 // Basic check for function body and signature.
91 EXPECT_AVAILABLE(R"cpp(
92 class Bar {
93 [[void [[f^o^o^]]() [[{ return; }]]]]
96 void foo();
97 [[void [[f^o^o]]() [[{
98 return;
99 }]]]])cpp");
101 // Not available on defaulted/deleted members.
102 EXPECT_UNAVAILABLE(R"cpp(
103 class Foo {
104 Fo^o() = default;
105 F^oo(const Foo&) = delete;
106 };)cpp");
108 // Not available within templated classes with unnamed parameters, as it is
109 // hard to spell class name out-of-line in such cases.
110 EXPECT_UNAVAILABLE(R"cpp(
111 template <typename> struct Foo { void fo^o(){} };
112 )cpp");
114 // Not available on function template specializations and free function
115 // templates.
116 EXPECT_UNAVAILABLE(R"cpp(
117 template <typename T> void fo^o() {}
118 template <> void fo^o<int>() {}
119 )cpp");
121 // Not available on methods of unnamed classes.
122 EXPECT_UNAVAILABLE(R"cpp(
123 struct Foo {
124 struct { void b^ar() {} } Bar;
126 )cpp");
128 // Not available on methods of named classes with unnamed parent in parents
129 // nesting.
130 EXPECT_UNAVAILABLE(R"cpp(
131 struct Foo {
132 struct {
133 struct Bar { void b^ar() {} };
134 } Baz;
136 )cpp");
138 // Not available on definitions in header file within unnamed namespaces
139 EXPECT_UNAVAILABLE(R"cpp(
140 namespace {
141 struct Foo {
142 void f^oo() {}
144 } // namespace
145 )cpp");
148 TEST_F(DefineOutlineTest, FailsWithoutSource) {
149 FileName = "Test.hpp";
150 llvm::StringRef Test = "void fo^o() { return; }";
151 llvm::StringRef Expected =
152 "fail: Couldn't find a suitable implementation file.";
153 EXPECT_EQ(apply(Test), Expected);
156 TEST_F(DefineOutlineTest, ApplyTest) {
157 ExtraFiles["Test.cpp"] = "";
158 FileName = "Test.hpp";
160 struct {
161 llvm::StringRef Test;
162 llvm::StringRef ExpectedHeader;
163 llvm::StringRef ExpectedSource;
164 } Cases[] = {
165 // Simple check
167 "void fo^o() { return; }",
168 "void foo() ;",
169 "void foo() { return; }",
171 // Inline specifier.
173 "inline void fo^o() { return; }",
174 " void foo() ;",
175 " void foo() { return; }",
177 // Default args.
179 "void fo^o(int x, int y = 5, int = 2, int (*foo)(int) = nullptr) {}",
180 "void foo(int x, int y = 5, int = 2, int (*foo)(int) = nullptr) ;",
181 "void foo(int x, int y , int , int (*foo)(int) ) {}",
184 "struct Bar{Bar();}; void fo^o(Bar x = {}) {}",
185 "struct Bar{Bar();}; void foo(Bar x = {}) ;",
186 "void foo(Bar x ) {}",
188 // Constructors
190 R"cpp(
191 class Foo {public: Foo(); Foo(int);};
192 class Bar {
193 Ba^r() {}
194 Bar(int x) : f1(x) {}
195 Foo f1;
196 Foo f2 = 2;
197 };)cpp",
198 R"cpp(
199 class Foo {public: Foo(); Foo(int);};
200 class Bar {
201 Bar() ;
202 Bar(int x) : f1(x) {}
203 Foo f1;
204 Foo f2 = 2;
205 };)cpp",
206 "Bar::Bar() {}\n",
208 // Ctor with initializer.
210 R"cpp(
211 class Foo {public: Foo(); Foo(int);};
212 class Bar {
213 Bar() {}
214 B^ar(int x) : f1(x), f2(3) {}
215 Foo f1;
216 Foo f2 = 2;
217 };)cpp",
218 R"cpp(
219 class Foo {public: Foo(); Foo(int);};
220 class Bar {
221 Bar() {}
222 Bar(int x) ;
223 Foo f1;
224 Foo f2 = 2;
225 };)cpp",
226 "Bar::Bar(int x) : f1(x), f2(3) {}\n",
228 // Ctor initializer with attribute.
230 R"cpp(
231 template <typename T> class Foo {
232 F^oo(T z) __attribute__((weak)) : bar(2){}
233 int bar;
234 };)cpp",
235 R"cpp(
236 template <typename T> class Foo {
237 Foo(T z) __attribute__((weak)) ;
238 int bar;
239 };template <typename T>
240 inline Foo<T>::Foo(T z) __attribute__((weak)) : bar(2){}
241 )cpp",
242 ""},
243 // Virt specifiers.
245 R"cpp(
246 struct A {
247 virtual void f^oo() {}
248 };)cpp",
249 R"cpp(
250 struct A {
251 virtual void foo() ;
252 };)cpp",
253 " void A::foo() {}\n",
256 R"cpp(
257 struct A {
258 virtual virtual void virtual f^oo() {}
259 };)cpp",
260 R"cpp(
261 struct A {
262 virtual virtual void virtual foo() ;
263 };)cpp",
264 " void A::foo() {}\n",
267 R"cpp(
268 struct A {
269 virtual void foo() = 0;
271 struct B : A {
272 void fo^o() override {}
273 };)cpp",
274 R"cpp(
275 struct A {
276 virtual void foo() = 0;
278 struct B : A {
279 void foo() override ;
280 };)cpp",
281 "void B::foo() {}\n",
284 R"cpp(
285 struct A {
286 virtual void foo() = 0;
288 struct B : A {
289 void fo^o() final {}
290 };)cpp",
291 R"cpp(
292 struct A {
293 virtual void foo() = 0;
295 struct B : A {
296 void foo() final ;
297 };)cpp",
298 "void B::foo() {}\n",
301 R"cpp(
302 struct A {
303 virtual void foo() = 0;
305 struct B : A {
306 void fo^o() final override {}
307 };)cpp",
308 R"cpp(
309 struct A {
310 virtual void foo() = 0;
312 struct B : A {
313 void foo() final override ;
314 };)cpp",
315 "void B::foo() {}\n",
318 R"cpp(
319 struct A {
320 static void fo^o() {}
321 };)cpp",
322 R"cpp(
323 struct A {
324 static void foo() ;
325 };)cpp",
326 " void A::foo() {}\n",
329 R"cpp(
330 struct A {
331 static static void fo^o() {}
332 };)cpp",
333 R"cpp(
334 struct A {
335 static static void foo() ;
336 };)cpp",
337 " void A::foo() {}\n",
340 R"cpp(
341 struct Foo {
342 explicit Fo^o(int) {}
343 };)cpp",
344 R"cpp(
345 struct Foo {
346 explicit Foo(int) ;
347 };)cpp",
348 " Foo::Foo(int) {}\n",
351 R"cpp(
352 struct Foo {
353 explicit explicit Fo^o(int) {}
354 };)cpp",
355 R"cpp(
356 struct Foo {
357 explicit explicit Foo(int) ;
358 };)cpp",
359 " Foo::Foo(int) {}\n",
362 R"cpp(
363 struct A {
364 inline void f^oo(int) {}
365 };)cpp",
366 R"cpp(
367 struct A {
368 void foo(int) ;
369 };)cpp",
370 " void A::foo(int) {}\n",
372 // Complex class template
374 R"cpp(
375 template <typename T, typename ...U> struct O1 {
376 template <class V, int A> struct O2 {
377 enum E { E1, E2 };
378 struct I {
379 E f^oo(T, U..., V, E) { return E1; }
382 };)cpp",
383 R"cpp(
384 template <typename T, typename ...U> struct O1 {
385 template <class V, int A> struct O2 {
386 enum E { E1, E2 };
387 struct I {
388 E foo(T, U..., V, E) ;
391 };template <typename T, typename ...U>
392 template <class V, int A>
393 inline typename O1<T, U...>::template O2<V, A>::E O1<T, U...>::template O2<V, A>::I::foo(T, U..., V, E) { return E1; }
394 )cpp",
395 ""},
396 // Destructors
398 "class A { ~A^(){} };",
399 "class A { ~A(); };",
400 "A::~A(){} ",
403 // Member template
405 R"cpp(
406 struct Foo {
407 template <typename T, typename, bool B = true>
408 T ^bar() { return {}; }
409 };)cpp",
410 R"cpp(
411 struct Foo {
412 template <typename T, typename, bool B = true>
413 T bar() ;
414 };template <typename T, typename, bool B>
415 inline T Foo::bar() { return {}; }
416 )cpp",
417 ""},
419 // Class template with member template
421 R"cpp(
422 template <typename T> struct Foo {
423 template <typename U, bool> T ^bar(const T& t, const U& u) { return {}; }
424 };)cpp",
425 R"cpp(
426 template <typename T> struct Foo {
427 template <typename U, bool> T bar(const T& t, const U& u) ;
428 };template <typename T>
429 template <typename U, bool>
430 inline T Foo<T>::bar(const T& t, const U& u) { return {}; }
431 )cpp",
432 ""},
434 for (const auto &Case : Cases) {
435 SCOPED_TRACE(Case.Test);
436 llvm::StringMap<std::string> EditedFiles;
437 EXPECT_EQ(apply(Case.Test, &EditedFiles), Case.ExpectedHeader);
438 if (Case.ExpectedSource.empty()) {
439 EXPECT_TRUE(EditedFiles.empty());
440 } else {
441 EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
442 testPath("Test.cpp"), Case.ExpectedSource)));
447 TEST_F(DefineOutlineTest, InCppFile) {
448 FileName = "Test.cpp";
450 struct {
451 llvm::StringRef Test;
452 llvm::StringRef ExpectedSource;
453 } Cases[] = {
455 R"cpp(
456 namespace foo {
457 namespace {
458 struct Foo { void ba^r() {} };
459 struct Bar { void foo(); };
460 void Bar::foo() {}
463 )cpp",
464 R"cpp(
465 namespace foo {
466 namespace {
467 struct Foo { void bar() ; };void Foo::bar() {}
468 struct Bar { void foo(); };
469 void Bar::foo() {}
472 )cpp"},
475 for (const auto &Case : Cases) {
476 SCOPED_TRACE(Case.Test);
477 EXPECT_EQ(apply(Case.Test, nullptr), Case.ExpectedSource);
481 TEST_F(DefineOutlineTest, HandleMacros) {
482 llvm::StringMap<std::string> EditedFiles;
483 ExtraFiles["Test.cpp"] = "";
484 FileName = "Test.hpp";
485 ExtraArgs.push_back("-DVIRTUAL=virtual");
486 ExtraArgs.push_back("-DOVER=override");
488 struct {
489 llvm::StringRef Test;
490 llvm::StringRef ExpectedHeader;
491 llvm::StringRef ExpectedSource;
492 } Cases[] = {
493 {R"cpp(
494 #define BODY { return; }
495 void f^oo()BODY)cpp",
496 R"cpp(
497 #define BODY { return; }
498 void foo();)cpp",
499 "void foo()BODY"},
501 {R"cpp(
502 #define BODY return;
503 void f^oo(){BODY})cpp",
504 R"cpp(
505 #define BODY return;
506 void foo();)cpp",
507 "void foo(){BODY}"},
509 {R"cpp(
510 #define TARGET void foo()
511 [[TARGET]]{ return; })cpp",
512 R"cpp(
513 #define TARGET void foo()
514 TARGET;)cpp",
515 "TARGET{ return; }"},
517 {R"cpp(
518 #define TARGET foo
519 void [[TARGET]](){ return; })cpp",
520 R"cpp(
521 #define TARGET foo
522 void TARGET();)cpp",
523 "void TARGET(){ return; }"},
524 {R"cpp(#define VIRT virtual
525 struct A {
526 VIRT void f^oo() {}
527 };)cpp",
528 R"cpp(#define VIRT virtual
529 struct A {
530 VIRT void foo() ;
531 };)cpp",
532 " void A::foo() {}\n"},
533 {R"cpp(
534 struct A {
535 VIRTUAL void f^oo() {}
536 };)cpp",
537 R"cpp(
538 struct A {
539 VIRTUAL void foo() ;
540 };)cpp",
541 " void A::foo() {}\n"},
542 {R"cpp(
543 struct A {
544 virtual void foo() = 0;
546 struct B : A {
547 void fo^o() OVER {}
548 };)cpp",
549 R"cpp(
550 struct A {
551 virtual void foo() = 0;
553 struct B : A {
554 void foo() OVER ;
555 };)cpp",
556 "void B::foo() {}\n"},
557 {R"cpp(#define STUPID_MACRO(X) virtual
558 struct A {
559 STUPID_MACRO(sizeof sizeof int) void f^oo() {}
560 };)cpp",
561 R"cpp(#define STUPID_MACRO(X) virtual
562 struct A {
563 STUPID_MACRO(sizeof sizeof int) void foo() ;
564 };)cpp",
565 " void A::foo() {}\n"},
566 {R"cpp(#define STAT static
567 struct A {
568 STAT void f^oo() {}
569 };)cpp",
570 R"cpp(#define STAT static
571 struct A {
572 STAT void foo() ;
573 };)cpp",
574 " void A::foo() {}\n"},
575 {R"cpp(#define STUPID_MACRO(X) static
576 struct A {
577 STUPID_MACRO(sizeof sizeof int) void f^oo() {}
578 };)cpp",
579 R"cpp(#define STUPID_MACRO(X) static
580 struct A {
581 STUPID_MACRO(sizeof sizeof int) void foo() ;
582 };)cpp",
583 " void A::foo() {}\n"},
585 for (const auto &Case : Cases) {
586 SCOPED_TRACE(Case.Test);
587 EXPECT_EQ(apply(Case.Test, &EditedFiles), Case.ExpectedHeader);
588 EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
589 testPath("Test.cpp"), Case.ExpectedSource)));
593 TEST_F(DefineOutlineTest, QualifyReturnValue) {
594 FileName = "Test.hpp";
595 ExtraFiles["Test.cpp"] = "";
597 struct {
598 llvm::StringRef Test;
599 llvm::StringRef ExpectedHeader;
600 llvm::StringRef ExpectedSource;
601 } Cases[] = {
602 {R"cpp(
603 namespace a { class Foo{}; }
604 using namespace a;
605 Foo fo^o() { return {}; })cpp",
606 R"cpp(
607 namespace a { class Foo{}; }
608 using namespace a;
609 Foo foo() ;)cpp",
610 "a::Foo foo() { return {}; }"},
611 {R"cpp(
612 namespace a {
613 class Foo {
614 class Bar {};
615 Bar fo^o() { return {}; }
617 })cpp",
618 R"cpp(
619 namespace a {
620 class Foo {
621 class Bar {};
622 Bar foo() ;
624 })cpp",
625 "a::Foo::Bar a::Foo::foo() { return {}; }\n"},
626 {R"cpp(
627 class Foo {};
628 Foo fo^o() { return {}; })cpp",
629 R"cpp(
630 class Foo {};
631 Foo foo() ;)cpp",
632 "Foo foo() { return {}; }"},
634 llvm::StringMap<std::string> EditedFiles;
635 for (auto &Case : Cases) {
636 apply(Case.Test, &EditedFiles);
637 EXPECT_EQ(apply(Case.Test, &EditedFiles), Case.ExpectedHeader);
638 EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
639 testPath("Test.cpp"), Case.ExpectedSource)));
643 TEST_F(DefineOutlineTest, QualifyFunctionName) {
644 FileName = "Test.hpp";
645 struct {
646 llvm::StringRef TestHeader;
647 llvm::StringRef TestSource;
648 llvm::StringRef ExpectedHeader;
649 llvm::StringRef ExpectedSource;
650 } Cases[] = {
652 R"cpp(
653 namespace a {
654 namespace b {
655 class Foo {
656 void fo^o() {}
659 })cpp",
661 R"cpp(
662 namespace a {
663 namespace b {
664 class Foo {
665 void foo() ;
668 })cpp",
669 "void a::b::Foo::foo() {}\n",
672 "namespace a { namespace b { void f^oo() {} } }",
673 "namespace a{}",
674 "namespace a { namespace b { void foo() ; } }",
675 "namespace a{void b::foo() {} }",
678 "namespace a { namespace b { void f^oo() {} } }",
679 "using namespace a;",
680 "namespace a { namespace b { void foo() ; } }",
681 // FIXME: Take using namespace directives in the source file into
682 // account. This can be spelled as b::foo instead.
683 "using namespace a;void a::b::foo() {} ",
686 "namespace a { class A { ~A^(){} }; }",
688 "namespace a { class A { ~A(); }; }",
689 "a::A::~A(){} ",
692 "namespace a { class A { ~A^(){} }; }",
693 "namespace a{}",
694 "namespace a { class A { ~A(); }; }",
695 "namespace a{A::~A(){} }",
698 llvm::StringMap<std::string> EditedFiles;
699 for (auto &Case : Cases) {
700 ExtraFiles["Test.cpp"] = std::string(Case.TestSource);
701 EXPECT_EQ(apply(Case.TestHeader, &EditedFiles), Case.ExpectedHeader);
702 EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
703 testPath("Test.cpp"), Case.ExpectedSource)))
704 << Case.TestHeader;
708 TEST_F(DefineOutlineTest, FailsMacroSpecifier) {
709 FileName = "Test.hpp";
710 ExtraFiles["Test.cpp"] = "";
711 ExtraArgs.push_back("-DFINALOVER=final override");
713 std::pair<StringRef, StringRef> Cases[] = {
715 R"cpp(
716 #define VIRT virtual void
717 struct A {
718 VIRT fo^o() {}
719 };)cpp",
720 "fail: define outline: couldn't remove `virtual` keyword."},
722 R"cpp(
723 #define OVERFINAL final override
724 struct A {
725 virtual void foo() {}
727 struct B : A {
728 void fo^o() OVERFINAL {}
729 };)cpp",
730 "fail: define outline: Can't move out of line as function has a "
731 "macro `override` specifier.\ndefine outline: Can't move out of line "
732 "as function has a macro `final` specifier."},
734 R"cpp(
735 struct A {
736 virtual void foo() {}
738 struct B : A {
739 void fo^o() FINALOVER {}
740 };)cpp",
741 "fail: define outline: Can't move out of line as function has a "
742 "macro `override` specifier.\ndefine outline: Can't move out of line "
743 "as function has a macro `final` specifier."},
745 for (const auto &Case : Cases) {
746 EXPECT_EQ(apply(Case.first), Case.second);
750 } // namespace
751 } // namespace clangd
752 } // namespace clang