r372936 - [libTooling] Add `run` combinator to Stencils.

Yitzhak Mandelbaum via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 25 17:53:56 PDT 2019


Author: ymandel
Date: Wed Sep 25 17:53:56 2019
New Revision: 372936

URL: http://llvm.org/viewvc/llvm-project?rev=372936&view=rev
Log:
[libTooling] Add `run` combinator to Stencils.

Summary:
This revision adds `run`, a StencilPart that runs a user-defined function that
computes a result over `MatchFinder::MatchResult`.

Reviewers: gribozavr

Subscribers: cfe-commits

Tags: #clang

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

Modified:
    cfe/trunk/include/clang/Tooling/Refactoring/Stencil.h
    cfe/trunk/lib/Tooling/Refactoring/Stencil.cpp
    cfe/trunk/unittests/Tooling/StencilTest.cpp

Modified: cfe/trunk/include/clang/Tooling/Refactoring/Stencil.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/Refactoring/Stencil.h?rev=372936&r1=372935&r2=372936&view=diff
==============================================================================
--- cfe/trunk/include/clang/Tooling/Refactoring/Stencil.h (original)
+++ cfe/trunk/include/clang/Tooling/Refactoring/Stencil.h Wed Sep 25 17:53:56 2019
@@ -23,6 +23,7 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/ASTTypeTraits.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Tooling/Refactoring/MatchConsumer.h"
 #include "clang/Tooling/Refactoring/RangeSelector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Error.h"
@@ -175,6 +176,10 @@ inline StencilPart ifBound(llvm::StringR
   return ifBound(Id, text(TrueText), text(FalseText));
 }
 
+/// Wraps a MatchConsumer in a StencilPart, so that it can be used in a Stencil.
+/// This supports user-defined extensions to the Stencil language.
+StencilPart run(MatchConsumer<std::string> C);
+
 /// For debug use only; semantics are not guaranteed.
 ///
 /// \returns the string resulting from calling the node's print() method.

Modified: cfe/trunk/lib/Tooling/Refactoring/Stencil.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Refactoring/Stencil.cpp?rev=372936&r1=372935&r2=372936&view=diff
==============================================================================
--- cfe/trunk/lib/Tooling/Refactoring/Stencil.cpp (original)
+++ cfe/trunk/lib/Tooling/Refactoring/Stencil.cpp Wed Sep 25 17:53:56 2019
@@ -26,6 +26,7 @@ using namespace tooling;
 using ast_matchers::MatchFinder;
 using llvm::errc;
 using llvm::Error;
+using llvm::Expected;
 using llvm::StringError;
 
 // A down_cast function to safely down cast a StencilPartInterface to a subclass
@@ -102,6 +103,12 @@ bool isEqualData(const IfBoundData &A, c
   return A.Id == B.Id && A.TruePart == B.TruePart && A.FalsePart == B.FalsePart;
 }
 
+// Equality is not defined over MatchConsumers, which are opaque.
+bool isEqualData(const MatchConsumer<std::string> &A,
+                 const MatchConsumer<std::string> &B) {
+  return false;
+}
+
 // The `evalData()` overloads evaluate the given stencil data to a string, given
 // the match result, and append it to `Result`. We define an overload for each
 // type of stencil data.
@@ -159,6 +166,15 @@ Error evalData(const IfBoundData &Data,
       .eval(Match, Result);
 }
 
+Error evalData(const MatchConsumer<std::string> &Fn,
+               const MatchFinder::MatchResult &Match, std::string *Result) {
+  Expected<std::string> Value = Fn(Match);
+  if (!Value)
+    return Value.takeError();
+  *Result += *Value;
+  return Error::success();
+}
+
 template <typename T>
 class StencilPartImpl : public StencilPartInterface {
   T Data;
@@ -233,3 +249,9 @@ StencilPart stencil::ifBound(StringRef I
   return StencilPart(std::make_shared<StencilPartImpl<IfBoundData>>(
       Id, std::move(TruePart), std::move(FalsePart)));
 }
+
+StencilPart stencil::run(MatchConsumer<std::string> Fn) {
+  return StencilPart(
+      std::make_shared<StencilPartImpl<MatchConsumer<std::string>>>(
+          std::move(Fn)));
+}

Modified: cfe/trunk/unittests/Tooling/StencilTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/StencilTest.cpp?rev=372936&r1=372935&r2=372936&view=diff
==============================================================================
--- cfe/trunk/unittests/Tooling/StencilTest.cpp (original)
+++ cfe/trunk/unittests/Tooling/StencilTest.cpp Wed Sep 25 17:53:56 2019
@@ -29,6 +29,7 @@ using stencil::access;
 using stencil::cat;
 using stencil::dPrint;
 using stencil::ifBound;
+using stencil::run;
 using stencil::text;
 
 // Create a valid translation-unit from a statement.
@@ -283,6 +284,15 @@ TEST_F(StencilTest, AccessOpImplicitThis
   EXPECT_THAT_EXPECTED(Stencil.eval(StmtMatch->Result), HasValue("field"));
 }
 
+TEST_F(StencilTest, RunOp) {
+  StringRef Id = "id";
+  auto SimpleFn = [Id](const MatchResult &R) {
+    return std::string(R.Nodes.getNodeAs<Stmt>(Id) != nullptr ? "Bound"
+                                                              : "Unbound");
+  };
+  testExpr(Id, "3;", cat(run(SimpleFn)), "Bound");
+}
+
 TEST(StencilEqualityTest, Equality) {
   auto Lhs = cat("foo", dPrint("dprint_id"));
   auto Rhs = cat("foo", dPrint("dprint_id"));
@@ -307,4 +317,12 @@ TEST(StencilEqualityTest, InEqualitySele
   auto S2 = cat(node("node"));
   EXPECT_NE(S1, S2);
 }
+
+// `run` is opaque.
+TEST(StencilEqualityTest, InEqualityRun) {
+  auto F = [](const MatchResult &R) { return "foo"; };
+  auto S1 = cat(run(F));
+  auto S2 = cat(run(F));
+  EXPECT_NE(S1, S2);
+}
 } // namespace




More information about the cfe-commits mailing list