ymandel created this revision.
ymandel added a reviewer: tdl-g.
ymandel requested review of this revision.
Herald added a project: clang.
Adds a convenience function for creating a rule that only generates a
diagnostic, without any correpsonding edits.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D94453

Files:
  clang-tools-extra/unittests/clang-tidy/TransformerClangTidyCheckTest.cpp
  clang/include/clang/Tooling/Transformer/RewriteRule.h
  clang/unittests/Tooling/TransformerTest.cpp

Index: clang/unittests/Tooling/TransformerTest.cpp
===================================================================
--- clang/unittests/Tooling/TransformerTest.cpp
+++ clang/unittests/Tooling/TransformerTest.cpp
@@ -26,6 +26,7 @@
 using ::clang::transformer::before;
 using ::clang::transformer::cat;
 using ::clang::transformer::changeTo;
+using ::clang::transformer::makeDiagnosticRule;
 using ::clang::transformer::makeRule;
 using ::clang::transformer::member;
 using ::clang::transformer::name;
@@ -1531,7 +1532,7 @@
 // of the expanded text. That is, the edit would have to be applied to the
 // macro's definition to succeed and editing the expansion point would not
 // suffice.
-TEST_F(TransformerTest, NoPartialRewriteOMacroExpansion) {
+TEST_F(TransformerTest, NoPartialRewriteOfMacroExpansion) {
   std::string Input = R"cc(
 #define ZERO_PLUS 0 + 3
     int f(string s) { return ZERO_PLUS; })cc";
@@ -1638,4 +1639,19 @@
       << "Could not update code: " << llvm::toString(UpdatedCode.takeError());
   EXPECT_EQ(format(*UpdatedCode), format(Header));
 }
+
+// The Transformer engine doesn't use the `Explanation` field of rules, so at
+// most we can check that the rule doesn't make any changes. If/when it starts
+// handling that field, we should expand these tests appropriately.
+TEST_F(TransformerTest, DiagnosticRule) {
+  std::string Input = "int f(int x) { return x; }";
+  testRule(makeDiagnosticRule(returnStmt(), cat("message")), Input, Input);
+}
+
+TEST_F(TransformerTest, DiagnosticRuleWithAnchor) {
+  std::string Input = "int f(int x) { return x; }";
+  testRule(makeDiagnosticRule(returnStmt(hasReturnValue(expr().bind("e"))),
+                              node("e"), cat("message")),
+           Input, Input);
+}
 } // namespace
Index: clang/include/clang/Tooling/Transformer/RewriteRule.h
===================================================================
--- clang/include/clang/Tooling/Transformer/RewriteRule.h
+++ clang/include/clang/Tooling/Transformer/RewriteRule.h
@@ -305,6 +305,21 @@
   return makeRule(std::move(M), edit(std::move(Edit)), std::move(Explanation));
 }
 
+/// Constructs a diagnostic \c RewriteRule. That is, a rule that only prints a
+/// diagnostic, without generating an edit. The two-argument version locates the
+/// diagnostic at the beginning of the code matched by \p M. To specify a
+/// different source range, pass \p Anchor in the three-argument version.
+inline RewriteRule makeDiagnosticRule(ast_matchers::internal::DynTypedMatcher M,
+                                      TextGenerator Explanation) {
+  return makeRule(std::move(M), noopEdit(node(RootID)), std::move(Explanation));
+}
+inline RewriteRule makeDiagnosticRule(ast_matchers::internal::DynTypedMatcher M,
+                                      RangeSelector Anchor,
+                                      TextGenerator Explanation) {
+  return makeRule(std::move(M), noopEdit(std::move(Anchor)),
+                  std::move(Explanation));
+}
+
 /// For every case in Rule, adds an include directive for the given header. The
 /// common use is assumed to be a rule with only one case. For example, to
 /// replace a function call and add headers corresponding to the new code, one
Index: clang-tools-extra/unittests/clang-tidy/TransformerClangTidyCheckTest.cpp
===================================================================
--- clang-tools-extra/unittests/clang-tidy/TransformerClangTidyCheckTest.cpp
+++ clang-tools-extra/unittests/clang-tidy/TransformerClangTidyCheckTest.cpp
@@ -12,6 +12,7 @@
 #include "clang/Tooling/Transformer/RangeSelector.h"
 #include "clang/Tooling/Transformer/Stencil.h"
 #include "clang/Tooling/Transformer/Transformer.h"
+#include "gmock/gmock.h"
 #include "gtest/gtest.h"
 
 namespace clang {
@@ -68,6 +69,45 @@
   EXPECT_EQ(Expected, test::runCheckOnCode<IfInverterCheck>(Input));
 }
 
+TEST(TransformerClangTidyCheckTest, MakeDiagnosticRule) {
+  class DiagOnlyCheck : public TransformerClangTidyCheck {
+  public:
+    DiagOnlyCheck(StringRef Name, ClangTidyContext *Context)
+        : TransformerClangTidyCheck(
+              makeDiagnosticRule(returnStmt(), cat("message")), Name, Context) {
+    }
+  };
+  std::string Input = "int h() { return 5; }";
+  std::vector<ClangTidyError> Errors;
+  EXPECT_EQ(Input, test::runCheckOnCode<DiagOnlyCheck>(Input, &Errors));
+  EXPECT_EQ(Errors.size(), 1U);
+  EXPECT_EQ(Errors[0].Message.Message, "message");
+  EXPECT_THAT(Errors[0].Ranges, testing::IsEmpty());
+
+  // The diagnostic is anchored to the match, "return 5".
+  EXPECT_EQ(Errors[0].Message.FileOffset, 10U);
+}
+
+TEST(TransformerClangTidyCheckTest, MakeDiagnosticRuleWithAnchor) {
+  class DiagOnlyCheck : public TransformerClangTidyCheck {
+  public:
+    DiagOnlyCheck(StringRef Name, ClangTidyContext *Context)
+        : TransformerClangTidyCheck(
+              makeDiagnosticRule(returnStmt(hasReturnValue(expr().bind("e"))),
+                                 node("e"), cat("message")),
+              Name, Context) {}
+  };
+  std::string Input = "int h() { return 5; }";
+  std::vector<ClangTidyError> Errors;
+  EXPECT_EQ(Input, test::runCheckOnCode<DiagOnlyCheck>(Input, &Errors));
+  EXPECT_EQ(Errors.size(), 1U);
+  EXPECT_THAT(Errors[0].Ranges, testing::IsEmpty());
+  EXPECT_EQ(Errors[0].Message.Message, "message");
+
+  // The diagnostic is anchored to the returned expression, "5".
+  EXPECT_EQ(Errors[0].Message.FileOffset, 17U);
+}
+
 class IntLitCheck : public TransformerClangTidyCheck {
 public:
   IntLitCheck(StringRef Name, ClangTidyContext *Context)
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D94453: [libToo... Yitzhak Mandelbaum via Phabricator via cfe-commits

Reply via email to