diff --git a/clang/include/clang/Tooling/Transformer/RewriteRule.h b/clang/include/clang/Tooling/Transformer/RewriteRule.h --- a/clang/include/clang/Tooling/Transformer/RewriteRule.h +++ b/clang/include/clang/Tooling/Transformer/RewriteRule.h @@ -107,7 +107,7 @@ TextGenerator Replacement; TextGenerator Note; // Not all transformations will want or need to attach metadata and therefore - // should not be requierd to do so. + // should not be required to do so. AnyGenerator Metadata = [](const ast_matchers::MatchFinder::MatchResult &) -> llvm::Expected { return llvm::Expected(llvm::Any()); @@ -131,6 +131,11 @@ /// Generates no edits. inline EditGenerator noEdits() { return editList({}); } +/// Generates a single, no-op edit anchored at the start location of the +/// specified range. A `noopEdit` may be preferred over `noEdits` to associate a +/// diagnostic `Explanation` with the rule. +EditGenerator noopEdit(RangeSelector Anchor); + /// Version of `ifBound` specialized to `ASTEdit`. inline EditGenerator ifBound(std::string ID, ASTEdit TrueEdit, ASTEdit FalseEdit) { diff --git a/clang/lib/Tooling/Transformer/RewriteRule.cpp b/clang/lib/Tooling/Transformer/RewriteRule.cpp --- a/clang/lib/Tooling/Transformer/RewriteRule.cpp +++ b/clang/lib/Tooling/Transformer/RewriteRule.cpp @@ -73,6 +73,24 @@ }; } +EditGenerator transformer::noopEdit(RangeSelector Anchor) { + return [Anchor = std::move(Anchor)](const MatchResult &Result) + -> Expected> { + Expected Range = Anchor(Result); + if (!Range) + return Range.takeError(); + // In case the range is inside a macro expansion, map the location back to a + // "real" source location. + SourceLocation Begin = + Result.SourceManager->getSpellingLoc(Range->getBegin()); + Edit E; + // Implicitly, leave `E.Replacement` as the empty string. + E.Kind = EditKind::Range; + E.Range = CharSourceRange::getCharRange(Begin, Begin); + return SmallVector{E}; + }; +} + EditGenerator transformer::flattenVector(SmallVector Generators) { if (Generators.size() == 1) diff --git a/clang/unittests/Tooling/TransformerTest.cpp b/clang/unittests/Tooling/TransformerTest.cpp --- a/clang/unittests/Tooling/TransformerTest.cpp +++ b/clang/unittests/Tooling/TransformerTest.cpp @@ -426,6 +426,14 @@ testRule(makeRule(returnStmt().bind("return"), noEdits()), Input, Input); } +TEST_F(TransformerTest, NoopEdit) { + using transformer::node; + using transformer::noopEdit; + std::string Input = "int f(int x) { return x; }"; + testRule(makeRule(returnStmt().bind("return"), noopEdit(node("return"))), + Input, Input); +} + TEST_F(TransformerTest, IfBound2Args) { using transformer::ifBound; std::string Input = "int f(int x) { return x; }";