[clang] 9945bd5 - Add Metadata to Transformer tooling
Yitzhak Mandelbaum via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 30 08:03:24 PDT 2020
Author: Andy Soffer
Date: 2020-06-30T15:03:07Z
New Revision: 9945bd5911636e7f821ac82fdcf8fdb22126e7dc
URL: https://github.com/llvm/llvm-project/commit/9945bd5911636e7f821ac82fdcf8fdb22126e7dc
DIFF: https://github.com/llvm/llvm-project/commit/9945bd5911636e7f821ac82fdcf8fdb22126e7dc.diff
LOG: Add Metadata to Transformer tooling
This change adds a Metadata field to ASTEdit, Edit, and AtomicChange so that
edits can have associated metadata and that metadata can be constructed with
Transformer-based RewriteRules. Metadata is ignored when applying edits to
source, but other consumers of AtomicChange can use this metadata to direct how
they want to consume each edit.
Reviewed By: ymandel, gribozavr2
Differential Revision: https://reviews.llvm.org/D82226
Added:
Modified:
clang/include/clang/Tooling/Refactoring/AtomicChange.h
clang/include/clang/Tooling/Transformer/RewriteRule.h
clang/lib/Tooling/Refactoring/AtomicChange.cpp
clang/lib/Tooling/Transformer/RewriteRule.cpp
clang/lib/Tooling/Transformer/Transformer.cpp
clang/unittests/Tooling/RefactoringTest.cpp
clang/unittests/Tooling/TransformerTest.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Tooling/Refactoring/AtomicChange.h b/clang/include/clang/Tooling/Refactoring/AtomicChange.h
index 7cb9987e80c7..f1034a3d0579 100644
--- a/clang/include/clang/Tooling/Refactoring/AtomicChange.h
+++ b/clang/include/clang/Tooling/Refactoring/AtomicChange.h
@@ -17,6 +17,7 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Format/Format.h"
#include "clang/Tooling/Core/Replacement.h"
+#include "llvm/ADT/Any.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
@@ -41,6 +42,9 @@ class AtomicChange {
/// is being changed, e.g. the call to a refactored method.
AtomicChange(const SourceManager &SM, SourceLocation KeyPosition);
+ AtomicChange(const SourceManager &SM, SourceLocation KeyPosition,
+ llvm::Any Metadata);
+
/// Creates an atomic change for \p FilePath with a customized key.
AtomicChange(llvm::StringRef FilePath, llvm::StringRef Key)
: Key(Key), FilePath(FilePath) {}
@@ -120,6 +124,8 @@ class AtomicChange {
return RemovedHeaders;
}
+ const llvm::Any &getMetadata() const { return Metadata; }
+
private:
AtomicChange() {}
@@ -135,6 +141,12 @@ class AtomicChange {
std::vector<std::string> InsertedHeaders;
std::vector<std::string> RemovedHeaders;
tooling::Replacements Replaces;
+
+ // This field stores metadata which is ignored for the purposes of applying
+ // edits to source, but may be useful for other consumers of AtomicChanges. In
+ // particular, consumers can use this to direct how they want to consume each
+ // edit.
+ llvm::Any Metadata;
};
using AtomicChanges = std::vector<AtomicChange>;
diff --git a/clang/include/clang/Tooling/Transformer/RewriteRule.h b/clang/include/clang/Tooling/Transformer/RewriteRule.h
index 0a961ccc475d..d9e68717d5c8 100644
--- a/clang/include/clang/Tooling/Transformer/RewriteRule.h
+++ b/clang/include/clang/Tooling/Transformer/RewriteRule.h
@@ -21,6 +21,7 @@
#include "clang/Tooling/Refactoring/AtomicChange.h"
#include "clang/Tooling/Transformer/MatchConsumer.h"
#include "clang/Tooling/Transformer/RangeSelector.h"
+#include "llvm/ADT/Any.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Error.h"
@@ -35,6 +36,7 @@ namespace transformer {
struct Edit {
CharSourceRange Range;
std::string Replacement;
+ llvm::Any Metadata;
};
/// Maps a match result to a list of concrete edits (with possible
@@ -85,6 +87,7 @@ struct ASTEdit {
RangeSelector TargetRange;
TextGenerator Replacement;
TextGenerator Note;
+ llvm::Any Metadata;
};
/// Lifts a list of `ASTEdit`s into an `EditGenerator`.
@@ -258,6 +261,11 @@ inline ASTEdit insertAfter(RangeSelector S, TextGenerator Replacement) {
/// Removes the source selected by \p S.
ASTEdit remove(RangeSelector S);
+inline ASTEdit withMetadata(ASTEdit edit, llvm::Any Metadata) {
+ edit.Metadata = std::move(Metadata);
+ return edit;
+}
+
/// The following three functions are a low-level part of the RewriteRule
/// API. We expose them for use in implementing the fixtures that interpret
/// RewriteRule, like Transformer and TransfomerTidy, or for more advanced
diff --git a/clang/lib/Tooling/Refactoring/AtomicChange.cpp b/clang/lib/Tooling/Refactoring/AtomicChange.cpp
index 3be15b7d8509..069e9c1eb36e 100644
--- a/clang/lib/Tooling/Refactoring/AtomicChange.cpp
+++ b/clang/lib/Tooling/Refactoring/AtomicChange.cpp
@@ -204,6 +204,12 @@ AtomicChange::AtomicChange(const SourceManager &SM,
Key = FilePath + ":" + std::to_string(FileIDAndOffset.second);
}
+AtomicChange::AtomicChange(const SourceManager &SM, SourceLocation KeyPosition,
+ llvm::Any M)
+ : AtomicChange(SM, KeyPosition) {
+ Metadata = std::move(M);
+}
+
AtomicChange::AtomicChange(std::string Key, std::string FilePath,
std::string Error,
std::vector<std::string> InsertedHeaders,
diff --git a/clang/lib/Tooling/Transformer/RewriteRule.cpp b/clang/lib/Tooling/Transformer/RewriteRule.cpp
index ddce6ce59185..995bec03cd66 100644
--- a/clang/lib/Tooling/Transformer/RewriteRule.cpp
+++ b/clang/lib/Tooling/Transformer/RewriteRule.cpp
@@ -47,6 +47,7 @@ translateEdits(const MatchResult &Result, ArrayRef<ASTEdit> ASTEdits) {
transformer::Edit T;
T.Range = *EditRange;
T.Replacement = std::move(*Replacement);
+ T.Metadata = E.Metadata;
Edits.push_back(std::move(T));
}
return Edits;
diff --git a/clang/lib/Tooling/Transformer/Transformer.cpp b/clang/lib/Tooling/Transformer/Transformer.cpp
index 71340bf2f676..e8fc00c4e953 100644
--- a/clang/lib/Tooling/Transformer/Transformer.cpp
+++ b/clang/lib/Tooling/Transformer/Transformer.cpp
@@ -53,7 +53,7 @@ void Transformer::run(const MatchFinder::MatchResult &Result) {
auto ID = Result.SourceManager->getFileID(T.Range.getBegin());
auto Iter = ChangesByFileID
.emplace(ID, AtomicChange(*Result.SourceManager,
- T.Range.getBegin()))
+ T.Range.getBegin(), T.Metadata))
.first;
auto &AC = Iter->second;
if (auto Err = AC.replace(*Result.SourceManager, T.Range, T.Replacement)) {
diff --git a/clang/unittests/Tooling/RefactoringTest.cpp b/clang/unittests/Tooling/RefactoringTest.cpp
index d65c6dba77b2..97a26a71deec 100644
--- a/clang/unittests/Tooling/RefactoringTest.cpp
+++ b/clang/unittests/Tooling/RefactoringTest.cpp
@@ -1296,6 +1296,18 @@ TEST_F(AtomicChangeTest, InsertAfterWithInvalidLocation) {
Replacement(Context.Sources, SourceLocation(), 0, "b")));
}
+TEST_F(AtomicChangeTest, Metadata) {
+ AtomicChange Change(Context.Sources, DefaultLoc, 17);
+ const llvm::Any &Metadata = Change.getMetadata();
+ ASSERT_TRUE(llvm::any_isa<int>(Metadata));
+ EXPECT_EQ(llvm::any_cast<int>(Metadata), 17);
+}
+
+TEST_F(AtomicChangeTest, NoMetadata) {
+ AtomicChange Change(Context.Sources, DefaultLoc);
+ EXPECT_FALSE(Change.getMetadata().hasValue());
+}
+
class ApplyAtomicChangesTest : public ::testing::Test {
protected:
ApplyAtomicChangesTest() : FilePath("file.cc") {
diff --git a/clang/unittests/Tooling/TransformerTest.cpp b/clang/unittests/Tooling/TransformerTest.cpp
index d19f747a69b5..7d6b63293748 100644
--- a/clang/unittests/Tooling/TransformerTest.cpp
+++ b/clang/unittests/Tooling/TransformerTest.cpp
@@ -439,6 +439,29 @@ TEST_F(TransformerTest, RemoveEdit) {
Input, Expected);
}
+TEST_F(TransformerTest, WithMetadata) {
+ std::string Input = R"cc(
+ int f() {
+ int x = 5;
+ return 7;
+ }
+ )cc";
+
+ Transformer T(
+ makeRule(declStmt().bind("decl"),
+ withMetadata(remove(statement(std::string("decl"))), 17)),
+ consumer());
+ T.registerMatchers(&MatchFinder);
+ auto Factory = newFrontendActionFactory(&MatchFinder);
+ EXPECT_TRUE(runToolOnCodeWithArgs(
+ Factory->create(), Input, std::vector<std::string>(), "input.cc",
+ "clang-tool", std::make_shared<PCHContainerOperations>(), {}));
+ ASSERT_EQ(Changes.size(), 1u);
+ const llvm::Any &Metadata = Changes[0].getMetadata();
+ ASSERT_TRUE(llvm::any_isa<int>(Metadata));
+ EXPECT_THAT(llvm::any_cast<int>(Metadata), 17);
+}
+
TEST_F(TransformerTest, MultiChange) {
std::string Input = R"cc(
void foo() {
More information about the cfe-commits
mailing list