11#include "gmock/gmock.h"
12#include "gtest/gtest.h"
18using ::testing::UnorderedElementsAre;
22TEST_F(DefineOutlineTest, TriggersOnFunctionDecl) {
23 FileName =
"Test.cpp";
26 [[void [[f^o^o]]() [[{
61 [[void [[Bar::[[b^a^z]]]]() [[{
65 FileName = "Test.hpp";
68 [[vo^id ]]foo[[()]] {[[
75 [[void [[f^o^o]]() [[{
85 [[void [[Bar::[[b^a^z]]]]() [[{
92 [[void [[f^o^o^]]() [[{ return; }]]]]
96 [[void [[f^o^o]]() [[{
103 F^oo(const Foo&) = delete;
109 template <typename> struct Foo { void fo^o(){} };
115 template <typename T> void fo^o() {}
116 template <> void fo^o<int>() {}
122 struct { void b^ar() {} } Bar;
131 struct Bar { void b^ar() {} };
146TEST_F(DefineOutlineTest, FailsWithoutSource) {
147 FileName = "Test.hpp";
148 llvm::StringRef Test =
"void fo^o() { return; }";
149 llvm::StringRef Expected =
150 "fail: Couldn't find a suitable implementation file.";
151 EXPECT_EQ(apply(Test), Expected);
154TEST_F(DefineOutlineTest, ApplyTest) {
155 ExtraFiles[
"Test.cpp"] =
"";
156 FileName =
"Test.hpp";
159 llvm::StringRef Test;
160 llvm::StringRef ExpectedHeader;
161 llvm::StringRef ExpectedSource;
165 "void fo^o() { return; }",
167 "void foo() { return; }",
171 "void fo^o(int i = 5);",
172 "void foo(int i = 5);",
173 "void foo(int i ) {}",
179 "int foo() { return {}; }",
183 "inline void fo^o() { return; }",
185 " void foo() { return; }",
189 "void fo^o(int x, int y = 5, int = 2, int (*foo)(int) = nullptr) {}",
190 "void foo(int x, int y = 5, int = 2, int (*foo)(int) = nullptr) ;",
191 "void foo(int x, int y , int , int (*foo)(int) ) {}",
194 "struct Bar{Bar();}; void fo^o(Bar x = {}) {}",
195 "struct Bar{Bar();}; void foo(Bar x = {}) ;",
196 "void foo(Bar x ) {}",
201 class Foo {public: Foo(); Foo(int);};
204 Bar(int x) : f1(x) {}
209 class Foo {public: Foo(); Foo(int);};
212 Bar(int x) : f1(x) {}
221 class Foo {public: Foo(); Foo(int);};
224 B^ar(int x) : f1(x), f2(3) {}
229 class Foo {public: Foo(); Foo(int);};
236 "Bar::Bar(int x) : f1(x), f2(3) {}\n",
241 template <typename T> class Foo {
242 F^oo(T z) __attribute__((weak)) : bar(2){}
246 template <typename T> class Foo {
247 Foo(T z) __attribute__((weak)) ;
249 };template <typename T>
250inline Foo<T>::Foo(T z) __attribute__((weak)) : bar(2){}
263 "Foo::Foo() = default;",
269 virtual void f^oo() {}
275 " void A::foo() {}\n",
280 virtual virtual void virtual f^oo() {}
284 virtual virtual void virtual foo() ;
286 " void A::foo() {}\n",
291 virtual void foo() = 0;
294 void fo^o() override {}
298 virtual void foo() = 0;
301 void foo() override ;
303 "void B::foo() {}\n",
308 virtual void foo() = 0;
315 virtual void foo() = 0;
320 "void B::foo() {}\n",
325 virtual void foo() = 0;
328 void fo^o() final override {}
332 virtual void foo() = 0;
335 void foo() final override ;
337 "void B::foo() {}\n",
342 static void fo^o() {}
348 " void A::foo() {}\n",
353 static static void fo^o() {}
357 static static void foo() ;
359 " void A::foo() {}\n",
364 explicit Fo^o(int) {}
370 " Foo::Foo(int) {}\n",
375 explicit explicit Fo^o(int) {}
379 explicit explicit Foo(int) ;
381 " Foo::Foo(int) {}\n",
386 inline void f^oo(int) {}
392 " void A::foo(int) {}\n",
397 template <typename T, typename ...U> struct O1 {
398 template <class V, int A> struct O2 {
401 E f^oo(T, U..., V, E) { return E1; }
406 template <typename T, typename ...U> struct O1 {
407 template <class V, int A> struct O2 {
410 E foo(T, U..., V, E) ;
413 };template <typename T, typename ...U>
414template <class V, int A>
415inline typename O1<T, U...>::template O2<V, A>::E O1<T, U...>::template O2<V, A>::I::foo(T, U..., V, E) { return E1; }
420 "class A { ~A^(){} };",
421 "class A { ~A(); };",
429 template <typename T, typename, bool B = true>
430 T ^bar() { return {}; }
434 template <typename T, typename, bool B = true>
436 };template <typename T, typename, bool B>
437inline T Foo::bar() { return {}; }
444 template <typename T> struct Foo {
445 template <typename U, bool> T ^bar(const T& t, const U& u) { return {}; }
448 template <typename T> struct Foo {
449 template <typename U, bool> T bar(const T& t, const U& u) ;
450 };template <typename T>
451template <typename U, bool>
452inline T Foo<T>::bar(const T& t, const U& u) { return {}; }
456 for (
const auto &Case : Cases) {
457 SCOPED_TRACE(Case.Test);
458 llvm::StringMap<std::string> EditedFiles;
459 EXPECT_EQ(apply(Case.Test, &EditedFiles), Case.ExpectedHeader);
460 if (Case.ExpectedSource.empty()) {
461 EXPECT_TRUE(EditedFiles.empty());
463 EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
464 testPath(
"Test.cpp"), Case.ExpectedSource)));
469TEST_F(DefineOutlineTest, InCppFile) {
470 FileName =
"Test.cpp";
472 llvm::StringRef Test;
473 llvm::StringRef ExpectedSource;
479 struct Foo { void ba^r() {} };
480 struct Bar { void foo(); };
488 struct Foo { void bar() ; };void Foo::bar() {}
489 struct Bar { void foo(); };
496 for (
const auto &Case : Cases) {
497 SCOPED_TRACE(Case.Test);
498 EXPECT_EQ(apply(Case.Test,
nullptr), Case.ExpectedSource);
502TEST_F(DefineOutlineTest, HandleMacros) {
503 llvm::StringMap<std::string> EditedFiles;
504 ExtraFiles[
"Test.cpp"] =
"";
505 FileName =
"Test.hpp";
506 ExtraArgs.push_back(
"-DVIRTUAL=virtual");
507 ExtraArgs.push_back(
"-DOVER=override");
510 llvm::StringRef Test;
511 llvm::StringRef ExpectedHeader;
512 llvm::StringRef ExpectedSource;
515 #define BODY { return; }
516 void f^oo()BODY)cpp",
518 #define BODY { return; }
524 void f^oo(){BODY})cpp",
531 #define TARGET void foo()
532 [[TARGET]]{ return; })cpp",
534 #define TARGET void foo()
536 "TARGET{ return; }"},
540 void [[TARGET]](){ return; })cpp",
544 "void TARGET(){ return; }"},
545 {R
"cpp(#define VIRT virtual
549 R"cpp(#define VIRT virtual
553 " void A::foo() {}\n"},
556 VIRTUAL void f^oo() {}
562 " void A::foo() {}\n"},
565 virtual void foo() = 0;
572 virtual void foo() = 0;
577 "void B::foo() {}\n"},
578 {R
"cpp(#define STUPID_MACRO(X) virtual
580 STUPID_MACRO(sizeof sizeof int) void f^oo() {}
582 R"cpp(#define STUPID_MACRO(X) virtual
584 STUPID_MACRO(sizeof sizeof int) void foo() ;
586 " void A::foo() {}\n"},
587 {R
"cpp(#define STAT static
591 R"cpp(#define STAT static
595 " void A::foo() {}\n"},
596 {R
"cpp(#define STUPID_MACRO(X) static
598 STUPID_MACRO(sizeof sizeof int) void f^oo() {}
600 R"cpp(#define STUPID_MACRO(X) static
602 STUPID_MACRO(sizeof sizeof int) void foo() ;
604 " void A::foo() {}\n"},
606 for (
const auto &Case : Cases) {
607 SCOPED_TRACE(Case.Test);
608 EXPECT_EQ(apply(Case.Test, &EditedFiles), Case.ExpectedHeader);
609 EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
610 testPath(
"Test.cpp"), Case.ExpectedSource)));
614TEST_F(DefineOutlineTest, QualifyReturnValue) {
615 FileName =
"Test.hpp";
616 ExtraFiles[
"Test.cpp"] =
"";
619 llvm::StringRef Test;
620 llvm::StringRef ExpectedHeader;
621 llvm::StringRef ExpectedSource;
624 namespace a { class Foo{}; }
626 Foo fo^o() { return {}; })cpp",
628 namespace a { class Foo{}; }
631 "a::Foo foo() { return {}; }"},
636 Bar fo^o() { return {}; }
646 "a::Foo::Bar a::Foo::foo() { return {}; }\n"},
649 Foo fo^o() { return {}; })cpp",
653 "Foo foo() { return {}; }"},
655 template <typename T> class Expected {};
658 Expected<Bar> fu^nc() { return {}; }
661 template <typename T> class Expected {};
664 Expected<Bar> func() ;
666 "Expected<Foo::Bar> Foo::func() { return {}; }\n"},
668 llvm::StringMap<std::string> EditedFiles;
669 for (
auto &Case : Cases) {
670 apply(Case.Test, &EditedFiles);
671 EXPECT_EQ(apply(Case.Test, &EditedFiles), Case.ExpectedHeader);
672 EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
673 testPath(
"Test.cpp"), Case.ExpectedSource)));
677TEST_F(DefineOutlineTest, QualifyFunctionName) {
678 FileName =
"Test.hpp";
680 llvm::StringRef TestHeader;
681 llvm::StringRef TestSource;
682 llvm::StringRef ExpectedHeader;
683 llvm::StringRef ExpectedSource;
703 "void a::b::Foo::foo() {}\n",
706 "namespace a { namespace b { void f^oo() {} } }",
708 "namespace a { namespace b { void foo() ; } }",
709 "namespace a{void b::foo() {} }",
712 "namespace a { namespace b { void f^oo() {} } }",
713 "using namespace a;",
714 "namespace a { namespace b { void foo() ; } }",
717 "using namespace a;void a::b::foo() {} ",
720 "namespace a { class A { ~A^(){} }; }",
722 "namespace a { class A { ~A(); }; }",
726 "namespace a { class A { ~A^(){} }; }",
728 "namespace a { class A { ~A(); }; }",
729 "namespace a{A::~A(){} }",
732 llvm::StringMap<std::string> EditedFiles;
733 for (
auto &Case : Cases) {
734 ExtraFiles[
"Test.cpp"] = std::string(Case.TestSource);
735 EXPECT_EQ(apply(Case.TestHeader, &EditedFiles), Case.ExpectedHeader);
736 EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
737 testPath(
"Test.cpp"), Case.ExpectedSource)))
742TEST_F(DefineOutlineTest, FailsMacroSpecifier) {
743 FileName =
"Test.hpp";
744 ExtraFiles[
"Test.cpp"] =
"";
745 ExtraArgs.push_back(
"-DFINALOVER=final override");
747 std::pair<StringRef, StringRef> Cases[] = {
750 #define VIRT virtual void
754 "fail: define outline: couldn't remove `virtual` keyword."},
757 #define OVERFINAL final override
759 virtual void foo() {}
762 void fo^o() OVERFINAL {}
764 "fail: define outline: Can't move out of line as function has a "
765 "macro `override` specifier.\ndefine outline: Can't move out of line "
766 "as function has a macro `final` specifier."},
770 virtual void foo() {}
773 void fo^o() FINALOVER {}
775 "fail: define outline: Can't move out of line as function has a "
776 "macro `override` specifier.\ndefine outline: Can't move out of line "
777 "as function has a macro `final` specifier."},
779 for (
const auto &Case : Cases) {
780 EXPECT_EQ(apply(Case.first), Case.second);
789TEST_F(DefineOutlineWorkspaceTest, FindsCorrespondingSource) {
790 llvm::Annotations HeaderBefore(R
"cpp(
796 std::string SourceBefore(R"cpp(
800 std::string HeaderAfter = R"cpp(
806 std::string SourceAfter = R"cpp(
808void A::bar(){}void A::foo(){}
811 Workspace.addSource("a.hpp", HeaderBefore.code());
812 Workspace.addMainFile(
"a.cpp", SourceBefore);
813 auto Result = apply(
"a.hpp", {HeaderBefore.point(), HeaderBefore.point()});
815 AllOf(withStatus(
"success"),
817 FileWithContents(
testPath(
"a.hpp"), HeaderAfter),
818 FileWithContents(
testPath(
"a.cpp"), SourceAfter)))));
826TEST_F(DefineOutlineWorkspaceTest, SensibleInsertionLocations) {
828 llvm::StringRef HeaderBefore;
829 llvm::StringRef SourceBefore;
830 llvm::StringRef HeaderAfter;
831 llvm::StringRef SourceAfter;
837 void ignored1(); // Too far away
838 void ignored2(); // No definition
839 void ignored3() {} // Defined inline
846void Foo::ignored1() {}
847void Foo::neighbor() {}
851 void ignored1(); // Too far away
852 void ignored2(); // No definition
853 void ignored3() {} // Defined inline
860void Foo::ignored1() {}
862void Foo::neighbor() {}
876void Foo::neighbor() {}
877void Foo::ignored() {}
888void Foo::neighbor() {}void Foo::foo() {}
890void Foo::ignored() {}
907void Foo::neighbor() {}
908void Foo::ignored() {}
923void Foo::neighbor() {}void Foo::foo() {}
925void Foo::ignored() {}
942void NS::Foo::neighbor() {}
943void NS::Foo::ignored() {}
956void NS::Foo::neighbor() {}void NS::Foo::foo() {}
958void NS::Foo::ignored() {}
969inline void Foo::neighbor() {}
973void Foo::ignored() {}
981inline void Foo::foo() {}
982inline void Foo::neighbor() {}
998void Foo::ignored1() {}
1000void Foo::ignored2() {}
1012void Foo::ignored1() {}
1013Foo::Foo() = default;void Foo::func() {}
1015void Foo::ignored2() {}
1019 for (
const auto &Case : Cases) {
1021 llvm::Annotations Hdr(Case.HeaderBefore);
1022 Workspace.addSource(
"a.hpp", Hdr.code());
1023 Workspace.addMainFile(
"a.cpp", Case.SourceBefore);
1024 auto Result = apply(
"a.hpp", {Hdr.point(), Hdr.point()});
1025 if (Case.SourceAfter.empty()) {
1027 AllOf(withStatus(
"success"),
1028 editedFiles(UnorderedElementsAre(FileWithContents(
1029 testPath(
"a.hpp"), Case.HeaderAfter)))));
1034 AllOf(withStatus(
"success"),
1036 FileWithContents(
testPath(
"a.hpp"), Case.HeaderAfter),
1037 FileWithContents(
testPath(
"a.cpp"), Case.SourceAfter)))));
#define TWEAK_TEST(TweakID)
#define TWEAK_WORKSPACE_TEST(TweakID)
#define EXPECT_AVAILABLE(MarkedCode)
#define EXPECT_UNAVAILABLE(MarkedCode)
FIXME: Skip testing on windows temporarily due to the different escaping code mode.
TEST_F(BackgroundIndexTest, NoCrashOnErrorFile)
std::string testPath(PathRef File, llvm::sys::path::Style Style)
::testing::Matcher< TweakResult > editedFiles(EditedFilesMatcher M)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//