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";
71 [[vo^id ]]foo[[()]] {[[
78 [[void [[f^o^o]]() [[{
88 [[void [[Bar::[[b^a^z]]]]() [[{
95 [[void [[f^o^o^]]() [[{ return; }]]]]
99 [[void [[f^o^o]]() [[{
107 F^oo(const Foo&) = delete;
113 template <typename> struct Foo { void fo^o(){} };
119 template <typename T> void fo^o() {}
120 template <> void fo^o<int>() {}
126 struct { void b^ar() {} } Bar;
135 struct Bar { void b^ar() {} };
150TEST_F(DefineOutlineTest, FailsWithoutSource) {
151 FileName = "Test.hpp";
152 llvm::StringRef Test =
"void fo^o() { return; }";
153 llvm::StringRef Expected =
154 "fail: Couldn't find a suitable implementation file.";
155 EXPECT_EQ(apply(Test), Expected);
158TEST_F(DefineOutlineTest, ApplyTest) {
159 ExtraFiles[
"Test.cpp"] =
"";
160 FileName =
"Test.hpp";
163 llvm::StringRef Test;
164 llvm::StringRef ExpectedHeader;
165 llvm::StringRef ExpectedSource;
169 "void fo^o() { return; }",
171 "void foo() { return; }",
175 "inline void fo^o() { return; }",
177 " void foo() { return; }",
181 "void fo^o(int x, int y = 5, int = 2, int (*foo)(int) = nullptr) {}",
182 "void foo(int x, int y = 5, int = 2, int (*foo)(int) = nullptr) ;",
183 "void foo(int x, int y , int , int (*foo)(int) ) {}",
186 "struct Bar{Bar();}; void fo^o(Bar x = {}) {}",
187 "struct Bar{Bar();}; void foo(Bar x = {}) ;",
188 "void foo(Bar x ) {}",
193 class Foo {public: Foo(); Foo(int);};
196 Bar(int x) : f1(x) {}
201 class Foo {public: Foo(); Foo(int);};
204 Bar(int x) : f1(x) {}
213 class Foo {public: Foo(); Foo(int);};
216 B^ar(int x) : f1(x), f2(3) {}
221 class Foo {public: Foo(); Foo(int);};
228 "Bar::Bar(int x) : f1(x), f2(3) {}\n",
233 template <typename T> class Foo {
234 F^oo(T z) __attribute__((weak)) : bar(2){}
238 template <typename T> class Foo {
239 Foo(T z) __attribute__((weak)) ;
241 };template <typename T>
242inline Foo<T>::Foo(T z) __attribute__((weak)) : bar(2){}
249 virtual void f^oo() {}
255 " void A::foo() {}\n",
260 virtual virtual void virtual f^oo() {}
264 virtual virtual void virtual foo() ;
266 " void A::foo() {}\n",
271 virtual void foo() = 0;
274 void fo^o() override {}
278 virtual void foo() = 0;
281 void foo() override ;
283 "void B::foo() {}\n",
288 virtual void foo() = 0;
295 virtual void foo() = 0;
300 "void B::foo() {}\n",
305 virtual void foo() = 0;
308 void fo^o() final override {}
312 virtual void foo() = 0;
315 void foo() final override ;
317 "void B::foo() {}\n",
322 static void fo^o() {}
328 " void A::foo() {}\n",
333 static static void fo^o() {}
337 static static void foo() ;
339 " void A::foo() {}\n",
344 explicit Fo^o(int) {}
350 " Foo::Foo(int) {}\n",
355 explicit explicit Fo^o(int) {}
359 explicit explicit Foo(int) ;
361 " Foo::Foo(int) {}\n",
366 inline void f^oo(int) {}
372 " void A::foo(int) {}\n",
377 template <typename T, typename ...U> struct O1 {
378 template <class V, int A> struct O2 {
381 E f^oo(T, U..., V, E) { return E1; }
386 template <typename T, typename ...U> struct O1 {
387 template <class V, int A> struct O2 {
390 E foo(T, U..., V, E) ;
393 };template <typename T, typename ...U>
394template <class V, int A>
395inline typename O1<T, U...>::template O2<V, A>::E O1<T, U...>::template O2<V, A>::I::foo(T, U..., V, E) { return E1; }
400 "class A { ~A^(){} };",
401 "class A { ~A(); };",
409 template <typename T, typename, bool B = true>
410 T ^bar() { return {}; }
414 template <typename T, typename, bool B = true>
416 };template <typename T, typename, bool B>
417inline T Foo::bar() { return {}; }
424 template <typename T> struct Foo {
425 template <typename U, bool> T ^bar(const T& t, const U& u) { return {}; }
428 template <typename T> struct Foo {
429 template <typename U, bool> T bar(const T& t, const U& u) ;
430 };template <typename T>
431template <typename U, bool>
432inline T Foo<T>::bar(const T& t, const U& u) { return {}; }
436 for (
const auto &Case : Cases) {
437 SCOPED_TRACE(Case.Test);
438 llvm::StringMap<std::string> EditedFiles;
439 EXPECT_EQ(apply(Case.Test, &EditedFiles), Case.ExpectedHeader);
440 if (Case.ExpectedSource.empty()) {
441 EXPECT_TRUE(EditedFiles.empty());
443 EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
444 testPath(
"Test.cpp"), Case.ExpectedSource)));
449TEST_F(DefineOutlineTest, InCppFile) {
450 FileName =
"Test.cpp";
452 llvm::StringRef Test;
453 llvm::StringRef ExpectedSource;
459 struct Foo { void ba^r() {} };
460 struct Bar { void foo(); };
468 struct Foo { void bar() ; };void Foo::bar() {}
469 struct Bar { void foo(); };
476 for (
const auto &Case : Cases) {
477 SCOPED_TRACE(Case.Test);
478 EXPECT_EQ(apply(Case.Test,
nullptr), Case.ExpectedSource);
482TEST_F(DefineOutlineTest, HandleMacros) {
483 llvm::StringMap<std::string> EditedFiles;
484 ExtraFiles[
"Test.cpp"] =
"";
485 FileName =
"Test.hpp";
486 ExtraArgs.push_back(
"-DVIRTUAL=virtual");
487 ExtraArgs.push_back(
"-DOVER=override");
490 llvm::StringRef Test;
491 llvm::StringRef ExpectedHeader;
492 llvm::StringRef ExpectedSource;
495 #define BODY { return; }
496 void f^oo()BODY)cpp",
498 #define BODY { return; }
504 void f^oo(){BODY})cpp",
511 #define TARGET void foo()
512 [[TARGET]]{ return; })cpp",
514 #define TARGET void foo()
516 "TARGET{ return; }"},
520 void [[TARGET]](){ return; })cpp",
524 "void TARGET(){ return; }"},
525 {R
"cpp(#define VIRT virtual
529 R"cpp(#define VIRT virtual
533 " void A::foo() {}\n"},
536 VIRTUAL void f^oo() {}
542 " void A::foo() {}\n"},
545 virtual void foo() = 0;
552 virtual void foo() = 0;
557 "void B::foo() {}\n"},
558 {R
"cpp(#define STUPID_MACRO(X) virtual
560 STUPID_MACRO(sizeof sizeof int) void f^oo() {}
562 R"cpp(#define STUPID_MACRO(X) virtual
564 STUPID_MACRO(sizeof sizeof int) void foo() ;
566 " void A::foo() {}\n"},
567 {R
"cpp(#define STAT static
571 R"cpp(#define STAT static
575 " void A::foo() {}\n"},
576 {R
"cpp(#define STUPID_MACRO(X) static
578 STUPID_MACRO(sizeof sizeof int) void f^oo() {}
580 R"cpp(#define STUPID_MACRO(X) static
582 STUPID_MACRO(sizeof sizeof int) void foo() ;
584 " void A::foo() {}\n"},
586 for (
const auto &Case : Cases) {
587 SCOPED_TRACE(Case.Test);
588 EXPECT_EQ(apply(Case.Test, &EditedFiles), Case.ExpectedHeader);
589 EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
590 testPath(
"Test.cpp"), Case.ExpectedSource)));
594TEST_F(DefineOutlineTest, QualifyReturnValue) {
595 FileName =
"Test.hpp";
596 ExtraFiles[
"Test.cpp"] =
"";
599 llvm::StringRef Test;
600 llvm::StringRef ExpectedHeader;
601 llvm::StringRef ExpectedSource;
604 namespace a { class Foo{}; }
606 Foo fo^o() { return {}; })cpp",
608 namespace a { class Foo{}; }
611 "a::Foo foo() { return {}; }"},
616 Bar fo^o() { return {}; }
626 "a::Foo::Bar a::Foo::foo() { return {}; }\n"},
629 Foo fo^o() { return {}; })cpp",
633 "Foo foo() { return {}; }"},
635 llvm::StringMap<std::string> EditedFiles;
636 for (
auto &Case : Cases) {
637 apply(Case.Test, &EditedFiles);
638 EXPECT_EQ(apply(Case.Test, &EditedFiles), Case.ExpectedHeader);
639 EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
640 testPath(
"Test.cpp"), Case.ExpectedSource)));
644TEST_F(DefineOutlineTest, QualifyFunctionName) {
645 FileName =
"Test.hpp";
647 llvm::StringRef TestHeader;
648 llvm::StringRef TestSource;
649 llvm::StringRef ExpectedHeader;
650 llvm::StringRef ExpectedSource;
670 "void a::b::Foo::foo() {}\n",
673 "namespace a { namespace b { void f^oo() {} } }",
675 "namespace a { namespace b { void foo() ; } }",
676 "namespace a{void b::foo() {} }",
679 "namespace a { namespace b { void f^oo() {} } }",
680 "using namespace a;",
681 "namespace a { namespace b { void foo() ; } }",
684 "using namespace a;void a::b::foo() {} ",
687 "namespace a { class A { ~A^(){} }; }",
689 "namespace a { class A { ~A(); }; }",
693 "namespace a { class A { ~A^(){} }; }",
695 "namespace a { class A { ~A(); }; }",
696 "namespace a{A::~A(){} }",
699 llvm::StringMap<std::string> EditedFiles;
700 for (
auto &Case : Cases) {
701 ExtraFiles[
"Test.cpp"] = std::string(Case.TestSource);
702 EXPECT_EQ(apply(Case.TestHeader, &EditedFiles), Case.ExpectedHeader);
703 EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
704 testPath(
"Test.cpp"), Case.ExpectedSource)))
709TEST_F(DefineOutlineTest, FailsMacroSpecifier) {
710 FileName =
"Test.hpp";
711 ExtraFiles[
"Test.cpp"] =
"";
712 ExtraArgs.push_back(
"-DFINALOVER=final override");
714 std::pair<StringRef, StringRef> Cases[] = {
717 #define VIRT virtual void
721 "fail: define outline: couldn't remove `virtual` keyword."},
724 #define OVERFINAL final override
726 virtual void foo() {}
729 void fo^o() OVERFINAL {}
731 "fail: define outline: Can't move out of line as function has a "
732 "macro `override` specifier.\ndefine outline: Can't move out of line "
733 "as function has a macro `final` specifier."},
737 virtual void foo() {}
740 void fo^o() FINALOVER {}
742 "fail: define outline: Can't move out of line as function has a "
743 "macro `override` specifier.\ndefine outline: Can't move out of line "
744 "as function has a macro `final` specifier."},
746 for (
const auto &Case : Cases) {
747 EXPECT_EQ(apply(Case.first), Case.second);
756TEST_F(DefineOutlineWorkspaceTest, FindsCorrespondingSource) {
757 llvm::Annotations HeaderBefore(R
"cpp(
763 std::string SourceBefore(R"cpp(
767 std::string HeaderAfter = R"cpp(
773 std::string SourceAfter = R"cpp(
775void A::bar(){}void A::foo(){}
778 Workspace.addSource("a.hpp", HeaderBefore.code());
779 Workspace.addMainFile(
"a.cpp", SourceBefore);
780 auto Result = apply(
"a.hpp", {HeaderBefore.point(), HeaderBefore.point()});
782 AllOf(withStatus(
"success"),
784 FileWithContents(
testPath(
"a.hpp"), HeaderAfter),
785 FileWithContents(
testPath(
"a.cpp"), SourceAfter)))));
793TEST_F(DefineOutlineWorkspaceTest, SensibleInsertionLocations) {
795 llvm::StringRef HeaderBefore;
796 llvm::StringRef SourceBefore;
797 llvm::StringRef HeaderAfter;
798 llvm::StringRef SourceAfter;
804 void ignored1(); // Too far away
805 void ignored2(); // No definition
806 void ignored3() {} // Defined inline
813void Foo::ignored1() {}
814void Foo::neighbor() {}
818 void ignored1(); // Too far away
819 void ignored2(); // No definition
820 void ignored3() {} // Defined inline
827void Foo::ignored1() {}
829void Foo::neighbor() {}
843void Foo::neighbor() {}
844void Foo::ignored() {}
855void Foo::neighbor() {}void Foo::foo() {}
857void Foo::ignored() {}
874void Foo::neighbor() {}
875void Foo::ignored() {}
890void Foo::neighbor() {}void Foo::foo() {}
892void Foo::ignored() {}
909void NS::Foo::neighbor() {}
910void NS::Foo::ignored() {}
923void NS::Foo::neighbor() {}void NS::Foo::foo() {}
925void NS::Foo::ignored() {}
936inline void Foo::neighbor() {}
940void Foo::ignored() {}
948inline void Foo::foo() {}
949inline void Foo::neighbor() {}
955 for (
const auto &Case : Cases) {
957 llvm::Annotations Hdr(Case.HeaderBefore);
958 Workspace.addSource(
"a.hpp", Hdr.code());
959 Workspace.addMainFile(
"a.cpp", Case.SourceBefore);
960 auto Result = apply(
"a.hpp", {Hdr.point(), Hdr.point()});
961 if (Case.SourceAfter.empty()) {
963 AllOf(withStatus(
"success"),
965 testPath(
"a.hpp"), Case.HeaderAfter)))));
970 AllOf(withStatus(
"success"),
972 FileWithContents(
testPath(
"a.hpp"), Case.HeaderAfter),
973 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++ -*-===//