#include "ParsedAST.h"
#include "refactor/InsertionPoint.h"
#include "refactor/Tweak.h"
-#include "support/Logger.h"
#include "clang/AST/DeclCXX.h"
-#include "clang/Basic/SourceLocation.h"
-#include "clang/Basic/SourceManager.h"
#include "clang/Sema/Sema.h"
#include "clang/Tooling/Core/Replacement.h"
#include "llvm/ADT/StringRef.h"
// - to understand the implicit behavior
// - to avoid relying on the implicit behavior
// - as a baseline for explicit modification
-class DeclareCopyMove : public Tweak {
+class SpecialMembers : public Tweak {
public:
const char *id() const final;
llvm::StringLiteral kind() const override {
// Trigger only on class definitions.
if (auto *N = Inputs.ASTSelection.commonAncestor())
Class = const_cast<CXXRecordDecl *>(N->ASTNode.get<CXXRecordDecl>());
- if (!Class || !Class->isThisDeclarationADefinition())
+ if (!Class || !Class->isThisDeclarationADefinition() || Class->isUnion())
return false;
// Tweak is only available if some members are missing.
bool NeedCopy = false, NeedMove = false;
CXXRecordDecl *Class = nullptr;
};
-REGISTER_TWEAK(DeclareCopyMove)
+REGISTER_TWEAK(SpecialMembers)
} // namespace
} // namespace clangd
#include "TestFS.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-#include <atomic>
#include <chrono>
#include <optional>
+#include <utility>
namespace clang {
namespace clangd {
FS.Files.erase(testPath("foo.cc"));
}
- std::string get(std::chrono::steady_clock::time_point FreshTime,
- bool ExpectParse) const {
+ std::pair<std::string, /*Parsed=*/bool>
+ get(std::chrono::steady_clock::time_point FreshTime) const {
bool GotParse = false;
- bool GotRead;
+ bool GotRead = false;
std::string Result;
read(
FS, FreshTime,
GotRead = true;
Result = Value;
});
- EXPECT_EQ(GotParse, ExpectParse);
EXPECT_TRUE(GotRead);
- return Result;
+ return {Result, GotParse};
}
};
+MATCHER_P(Parsed, Value, "") { return arg.second && arg.first == Value; }
+MATCHER_P(Cached, Value, "") { return !arg.second && arg.first == Value; }
+
TEST(FileCacheTest, Invalidation) {
TestCache C;
auto MustBeFresh = StaleOK + std::chrono::hours(1);
C.setContents("a");
- EXPECT_EQ("a", C.get(StaleOK, /*ExpectParse=*/true)) << "Parsed first time";
- EXPECT_EQ("a", C.get(StaleOK, /*ExpectParse=*/false)) << "Cached (time)";
- EXPECT_EQ("a", C.get(MustBeFresh, /*ExpectParse=*/false)) << "Cached (stat)";
+ EXPECT_THAT(C.get(StaleOK), Parsed("a")) << "Parsed first time";
+ EXPECT_THAT(C.get(StaleOK), Cached("a")) << "Cached (time)";
+ EXPECT_THAT(C.get(MustBeFresh), Cached("a")) << "Cached (stat)";
C.setContents("bb");
- EXPECT_EQ("a", C.get(StaleOK, /*ExpectParse=*/false)) << "Cached (time)";
- EXPECT_EQ("bb", C.get(MustBeFresh, /*ExpectParse=*/true)) << "Size changed";
- EXPECT_EQ("bb", C.get(MustBeFresh, /*ExpectParse=*/true)) << "Cached (stat)";
+ EXPECT_THAT(C.get(StaleOK), Cached("a")) << "Cached (time)";
+ EXPECT_THAT(C.get(MustBeFresh), Parsed("bb")) << "Size changed";
+ EXPECT_THAT(C.get(MustBeFresh), Cached("bb")) << "Cached (stat)";
C.setContents(nullptr);
- EXPECT_EQ("bb", C.get(StaleOK, /*ExpectParse=*/false)) << "Cached (time)";
- EXPECT_EQ("", C.get(MustBeFresh, /*ExpectParse=*/true)) << "Stat failed";
- EXPECT_EQ("", C.get(MustBeFresh, /*ExpectParse=*/false)) << "Cached (404)";
+ EXPECT_THAT(C.get(StaleOK), Cached("bb")) << "Cached (time)";
+ EXPECT_THAT(C.get(MustBeFresh), Parsed("")) << "stat failed";
+ EXPECT_THAT(C.get(MustBeFresh), Cached("")) << "Cached (404)";
C.setContents("bb"); // Match the previous stat values!
- EXPECT_EQ("", C.get(StaleOK, /*ExpectParse=*/false)) << "Cached (time)";
- EXPECT_EQ("bb", C.get(MustBeFresh, /*ExpectParse=*/true)) << "Size changed";
+ EXPECT_THAT(C.get(StaleOK), Cached("")) << "Cached (time)";
+ EXPECT_THAT(C.get(MustBeFresh), Parsed("bb")) << "Size changed";
}
} // namespace
//===----------------------------------------------------------------------===//
#include "TweakTesting.h"
-#include "gmock/gmock-matchers.h"
-#include "gmock/gmock.h"
#include "gtest/gtest.h"
namespace clang {
"S &operator=(S&&); S &operator=(const S&);"
"};");
- const char *Output = R"cpp(struct S{S(const S &) = default;
- S(S &&) = default;
- S &operator=(const S &) = default;
- S &operator=(S &&) = default;
+ const char *Output = R"cpp(struct S{S(const S&) = default;
+S(S&&) = default;
+S &operator=(const S&) = default;
+S &operator=(S&&) = default;
};)cpp";
EXPECT_EQ(apply("struct ^S{};"), Output);
- Output = R"cpp(struct S{S(const S &) = default;
-S(S &&) = default;
-S &operator=(const S &) = delete;
-S &operator=(S &&) = delete;
+ Output = R"cpp(struct S{S(const S&) = default;
+S(S&&) = default;
+S &operator=(const S&) = delete;
+S &operator=(S&&) = delete;
int& ref;};)cpp";
EXPECT_EQ(apply("struct ^S{int& ref;};"), Output);
}