//===-- MemberwiseConstructorTests.cpp ------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "TweakTesting.h" #include "gmock/gmock-matchers.h" #include "gmock/gmock.h" #include "gtest/gtest.h" namespace clang { namespace clangd { namespace { using testing::AllOf; using testing::Eq; using testing::HasSubstr; using testing::Not; TWEAK_TEST(MemberwiseConstructor); TEST_F(MemberwiseConstructorTest, Availability) { EXPECT_AVAILABLE("^struct ^S ^{ int x, y; };"); // Verify no crashes on incomplete member fields. EXPECT_UNAVAILABLE("/*error-ok*/class Forward; class ^A { Forward f;}"); EXPECT_UNAVAILABLE("struct S { ^int ^x, y; }; struct ^S;"); EXPECT_UNAVAILABLE("struct ^S {};"); EXPECT_UNAVAILABLE("union ^S { int x; };"); EXPECT_UNAVAILABLE("struct ^S { int x = 0; };"); EXPECT_UNAVAILABLE("struct ^S { struct { int x; }; };"); EXPECT_UNAVAILABLE("struct ^{ int x; } e;"); } TEST_F(MemberwiseConstructorTest, Edits) { Header = R"cpp( struct Move { Move(Move&&) = default; Move(const Move&) = delete; }; struct Copy { Copy(Copy&&) = delete; Copy(const Copy&); }; )cpp"; EXPECT_EQ(apply("struct ^S{Move M; Copy C; int I; int J=4;};"), "struct S{" "S(Move M, const Copy &C, int I) : M(std::move(M)), C(C), I(I) {}\n" "Move M; Copy C; int I; int J=4;};"); } TEST_F(MemberwiseConstructorTest, FieldTreatment) { Header = R"cpp( struct MoveOnly { MoveOnly(MoveOnly&&) = default; MoveOnly(const MoveOnly&) = delete; }; struct CopyOnly { CopyOnly(CopyOnly&&) = delete; CopyOnly(const CopyOnly&); }; struct CopyTrivial { CopyTrivial(CopyTrivial&&) = default; CopyTrivial(const CopyTrivial&) = default; }; struct Immovable { Immovable(Immovable&&) = delete; Immovable(const Immovable&) = delete; }; template struct Traits { using Type = typename T::Type; }; using IntAlias = int; )cpp"; auto Fail = Eq("unavailable"); auto Move = HasSubstr(": Member(std::move(Member))"); auto CopyRef = AllOf(HasSubstr("S(const "), HasSubstr(": Member(Member)")); auto Copy = AllOf(Not(HasSubstr("S(const ")), HasSubstr(": Member(Member)")); auto With = [](llvm::StringRef Type) { return ("struct ^S { " + Type + " Member; };").str(); }; EXPECT_THAT(apply(With("Immovable")), Fail); EXPECT_THAT(apply(With("MoveOnly")), Move); EXPECT_THAT(apply(With("CopyOnly")), CopyRef); EXPECT_THAT(apply(With("CopyTrivial")), Copy); EXPECT_THAT(apply(With("int")), Copy); EXPECT_THAT(apply(With("IntAlias")), Copy); EXPECT_THAT(apply(With("Immovable*")), Copy); EXPECT_THAT(apply(With("Immovable&")), Copy); EXPECT_THAT(apply("template " + With("T")), Move); EXPECT_THAT(apply("template " + With("typename Traits::Type")), Move); EXPECT_THAT(apply("template " + With("T*")), Copy); } } // namespace } // namespace clangd } // namespace clang