[clang-tools-extra] r369914 - [clang-tidy] TransformerClangTidyCheck: change choice of location for diagnostic message.

Yitzhak Mandelbaum via cfe-commits cfe-commits at lists.llvm.org
Mon Aug 26 08:17:29 PDT 2019


Author: ymandel
Date: Mon Aug 26 08:17:29 2019
New Revision: 369914

URL: http://llvm.org/viewvc/llvm-project?rev=369914&view=rev
Log:
[clang-tidy] TransformerClangTidyCheck: change choice of location for diagnostic message.

Summary:
This patch changes the location specified to the
`ClangTidyCheck::diag()`. Currently, the beginning of the matched range is
used. This patch uses the beginning of the first fix's range.  This change both
simplifies the code and (hopefully) gives a more intuitive result: the reported
location aligns with the fix(es) provided, rather than the (arbitrary) range of
the rule's match.

N.B. this patch will break the line offset numbers in lit tests if the first fix
is not at the beginning of the match.

Reviewers: gribozavr

Subscribers: xazax.hun, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D66676

Modified:
    clang-tools-extra/trunk/clang-tidy/utils/TransformerClangTidyCheck.cpp
    clang-tools-extra/trunk/unittests/clang-tidy/TransformerClangTidyCheckTest.cpp

Modified: clang-tools-extra/trunk/clang-tidy/utils/TransformerClangTidyCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/utils/TransformerClangTidyCheck.cpp?rev=369914&r1=369913&r2=369914&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/utils/TransformerClangTidyCheck.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/utils/TransformerClangTidyCheck.cpp Mon Aug 26 08:17:29 2019
@@ -71,14 +71,6 @@ void TransformerClangTidyCheck::check(
   if (Result.Context->getDiagnostics().hasErrorOccurred())
     return;
 
-  // Verify the existence and validity of the AST node that roots this rule.
-  const ast_matchers::BoundNodes::IDToNodeMap &NodesMap = Result.Nodes.getMap();
-  auto Root = NodesMap.find(RewriteRule::RootID);
-  assert(Root != NodesMap.end() && "Transformation failed: missing root node.");
-  SourceLocation RootLoc = Result.SourceManager->getExpansionLoc(
-      Root->second.getSourceRange().getBegin());
-  assert(RootLoc.isValid() && "Invalid location for Root node of match.");
-
   assert(Rule && "check() should not fire if Rule is None");
   RewriteRule::Case Case = tooling::detail::findSelectedCase(Result, *Rule);
   Expected<SmallVector<tooling::detail::Transformation, 1>> Transformations =
@@ -99,10 +91,12 @@ void TransformerClangTidyCheck::check(
                  << llvm::toString(Explanation.takeError()) << "\n";
     return;
   }
-  DiagnosticBuilder Diag = diag(RootLoc, *Explanation);
-  for (const auto &T : *Transformations) {
+
+  // Associate the diagnostic with the location of the first change.
+  DiagnosticBuilder Diag =
+      diag((*Transformations)[0].Range.getBegin(), *Explanation);
+  for (const auto &T : *Transformations)
     Diag << FixItHint::CreateReplacement(T.Range, T.Replacement);
-  }
 
   for (const auto &I : Case.AddedIncludes) {
     auto &Header = I.first;

Modified: clang-tools-extra/trunk/unittests/clang-tidy/TransformerClangTidyCheckTest.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clang-tidy/TransformerClangTidyCheckTest.cpp?rev=369914&r1=369913&r2=369914&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/clang-tidy/TransformerClangTidyCheckTest.cpp (original)
+++ clang-tools-extra/trunk/unittests/clang-tidy/TransformerClangTidyCheckTest.cpp Mon Aug 26 08:17:29 2019
@@ -18,18 +18,18 @@ namespace clang {
 namespace tidy {
 namespace utils {
 namespace {
+using namespace ::clang::ast_matchers;
+
 using tooling::change;
 using tooling::IncludeFormat;
+using tooling::node;
 using tooling::RewriteRule;
+using tooling::statement;
 using tooling::text;
 using tooling::stencil::cat;
 
 // Invert the code of an if-statement, while maintaining its semantics.
 RewriteRule invertIf() {
-  using namespace ::clang::ast_matchers;
-  using tooling::node;
-  using tooling::statement;
-
   StringRef C = "C", T = "T", E = "E";
   RewriteRule Rule = tooling::makeRule(
       ifStmt(hasCondition(expr().bind(C)), hasThen(stmt().bind(T)),
@@ -67,6 +67,56 @@ TEST(TransformerClangTidyCheckTest, Basi
   EXPECT_EQ(Expected, test::runCheckOnCode<IfInverterCheck>(Input));
 }
 
+class IntLitCheck : public TransformerClangTidyCheck {
+public:
+  IntLitCheck(StringRef Name, ClangTidyContext *Context)
+      : TransformerClangTidyCheck(tooling::makeRule(integerLiteral(),
+                                                    change(text("LIT")),
+                                                    text("no message")),
+                                  Name, Context) {}
+};
+
+// Tests that two changes in a single macro expansion do not lead to conflicts
+// in applying the changes.
+TEST(TransformerClangTidyCheckTest, TwoChangesInOneMacroExpansion) {
+  const std::string Input = R"cc(
+#define PLUS(a,b) (a) + (b)
+    int f() { return PLUS(3, 4); }
+  )cc";
+  const std::string Expected = R"cc(
+#define PLUS(a,b) (a) + (b)
+    int f() { return PLUS(LIT, LIT); }
+  )cc";
+
+  EXPECT_EQ(Expected, test::runCheckOnCode<IntLitCheck>(Input));
+}
+
+class BinOpCheck : public TransformerClangTidyCheck {
+public:
+  BinOpCheck(StringRef Name, ClangTidyContext *Context)
+      : TransformerClangTidyCheck(
+            tooling::makeRule(
+                binaryOperator(hasOperatorName("+"), hasRHS(expr().bind("r"))),
+                change(node("r"), text("RIGHT")), text("no message")),
+            Name, Context) {}
+};
+
+// Tests case where the rule's match spans both source from the macro and its
+// argument, while the change spans only the argument AND there are two such
+// matches. We verify that both replacements succeed.
+TEST(TransformerClangTidyCheckTest, TwoMatchesInMacroExpansion) {
+  const std::string Input = R"cc(
+#define M(a,b) (1 + a) * (1 + b)
+    int f() { return M(3, 4); }
+  )cc";
+  const std::string Expected = R"cc(
+#define M(a,b) (1 + a) * (1 + b)
+    int f() { return M(RIGHT, RIGHT); }
+  )cc";
+
+  EXPECT_EQ(Expected, test::runCheckOnCode<BinOpCheck>(Input));
+}
+
 // A trivial rewrite-rule generator that requires Objective-C code.
 Optional<RewriteRule> needsObjC(const LangOptions &LangOpts,
                                 const ClangTidyCheck::OptionsView &Options) {




More information about the cfe-commits mailing list