r373916 - [libTooling] Add `toString` method to the Stencil class

Yitzhak Mandelbaum via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 7 09:20:22 PDT 2019


Author: ymandel
Date: Mon Oct  7 09:20:22 2019
New Revision: 373916

URL: http://llvm.org/viewvc/llvm-project?rev=373916&view=rev
Log:
[libTooling] Add `toString` method to the Stencil class

Summary:
`toString` generates a string representation of the stencil.

Patch by Harshal T. Lehri.

Reviewers: gribozavr

Subscribers: cfe-commits

Tags: #clang

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

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=373916&r1=373915&r2=373916&view=diff
==============================================================================
--- cfe/trunk/include/clang/Tooling/Refactoring/Stencil.h (original)
+++ cfe/trunk/include/clang/Tooling/Refactoring/Stencil.h Mon Oct  7 09:20:22 2019
@@ -50,6 +50,11 @@ public:
 
   virtual bool isEqual(const StencilPartInterface &other) const = 0;
 
+  /// Constructs a string representation of the StencilPart. StencilParts
+  /// generated by the `selection` and `run` functions do not have a unique
+  /// string representation.
+  virtual std::string toString() const = 0;
+
   const void *typeId() const { return TypeId; }
 
 protected:
@@ -86,6 +91,12 @@ public:
     return Impl->isEqual(*Other.Impl);
   }
 
+  std::string toString() const {
+    if (Impl == nullptr)
+      return "";
+    return Impl->toString();
+  }
+
 private:
   std::shared_ptr<StencilPartInterface> Impl;
 };
@@ -120,6 +131,16 @@ public:
     return eval(Result);
   }
 
+  /// Constructs a string representation of the Stencil. The string is not
+  /// guaranteed to be unique.
+  std::string toString() const {
+    std::vector<std::string> PartStrings;
+    PartStrings.reserve(Parts.size());
+    for (const auto &Part : Parts)
+      PartStrings.push_back(Part.toString());
+    return llvm::join(PartStrings, ", ");
+  }
+
 private:
   friend bool operator==(const Stencil &A, const Stencil &B);
   static StencilPart wrap(llvm::StringRef Text);

Modified: cfe/trunk/lib/Tooling/Refactoring/Stencil.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Refactoring/Stencil.cpp?rev=373916&r1=373915&r2=373916&view=diff
==============================================================================
--- cfe/trunk/lib/Tooling/Refactoring/Stencil.cpp (original)
+++ cfe/trunk/lib/Tooling/Refactoring/Stencil.cpp Mon Oct  7 09:20:22 2019
@@ -15,6 +15,7 @@
 #include "clang/Lex/Lexer.h"
 #include "clang/Tooling/Refactoring/SourceCode.h"
 #include "clang/Tooling/Refactoring/SourceCodeBuilders.h"
+#include "llvm/ADT/Twine.h"
 #include "llvm/Support/Errc.h"
 #include <atomic>
 #include <memory>
@@ -128,6 +129,54 @@ bool isEqualData(const MatchConsumer<std
   return false;
 }
 
+std::string toStringData(const RawTextData &Data) {
+  std::string Result;
+  llvm::raw_string_ostream OS(Result);
+  OS << "\"";
+  OS.write_escaped(Data.Text);
+  OS << "\"";
+  OS.flush();
+  return Result;
+}
+
+std::string toStringData(const DebugPrintNodeData &Data) {
+  return (llvm::Twine("dPrint(\"") + Data.Id + "\")").str();
+}
+
+std::string toStringData(const UnaryOperationData &Data) {
+  StringRef OpName;
+  switch (Data.Op) {
+  case UnaryNodeOperator::Parens:
+    OpName = "expression";
+    break;
+  case UnaryNodeOperator::Deref:
+    OpName = "deref";
+    break;
+  case UnaryNodeOperator::Address:
+    OpName = "addressOf";
+    break;
+  }
+  return (OpName + "(\"" + Data.Id + "\")").str();
+}
+
+std::string toStringData(const SelectorData &) { return "SelectorData()"; }
+
+std::string toStringData(const AccessData &Data) {
+  return (llvm::Twine("access(\"") + Data.BaseId + "\", " +
+          Data.Member.toString() + ")")
+      .str();
+}
+
+std::string toStringData(const IfBoundData &Data) {
+  return (llvm::Twine("ifBound(\"") + Data.Id + "\", " +
+          Data.TruePart.toString() + ", " + Data.FalsePart.toString() + ")")
+      .str();
+}
+
+std::string toStringData(const MatchConsumer<std::string> &) {
+  return "MatchConsumer<std::string>()";
+}
+
 // 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.
@@ -247,6 +296,8 @@ public:
       return isEqualData(Data, OtherPtr->Data);
     return false;
   }
+
+  std::string toString() const override { return toStringData(Data); }
 };
 } // namespace
 

Modified: cfe/trunk/unittests/Tooling/StencilTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/StencilTest.cpp?rev=373916&r1=373915&r2=373916&view=diff
==============================================================================
--- cfe/trunk/unittests/Tooling/StencilTest.cpp (original)
+++ cfe/trunk/unittests/Tooling/StencilTest.cpp Mon Oct  7 09:20:22 2019
@@ -389,4 +389,59 @@ TEST(StencilEqualityTest, InEqualityRun)
   auto S2 = cat(run(F));
   EXPECT_NE(S1, S2);
 }
+
+TEST(StencilToStringTest, RawTextOp) {
+  auto S = cat("foo bar baz");
+  EXPECT_EQ(S.toString(), R"("foo bar baz")");
+}
+
+TEST(StencilToStringTest, RawTextOpEscaping) {
+  auto S = cat("foo \"bar\" baz\\n");
+  EXPECT_EQ(S.toString(), R"("foo \"bar\" baz\\n")");
+}
+
+TEST(StencilToStringTest, DebugPrintNodeOp) {
+  auto S = cat(dPrint("Id"));
+  EXPECT_EQ(S.toString(), R"repr(dPrint("Id"))repr");
+}
+
+TEST(StencilToStringTest, ExpressionOp) {
+  auto S = cat(expression("Id"));
+  EXPECT_EQ(S.toString(), R"repr(expression("Id"))repr");
+}
+
+TEST(StencilToStringTest, DerefOp) {
+  auto S = cat(deref("Id"));
+  EXPECT_EQ(S.toString(), R"repr(deref("Id"))repr");
+}
+
+TEST(StencilToStringTest, AddressOfOp) {
+  auto S = cat(addressOf("Id"));
+  EXPECT_EQ(S.toString(), R"repr(addressOf("Id"))repr");
+}
+
+TEST(StencilToStringTest, AccessOp) {
+  auto S = cat(access("Id", text("memberData")));
+  EXPECT_EQ(S.toString(), R"repr(access("Id", "memberData"))repr");
+}
+
+TEST(StencilToStringTest, AccessOpStencilPart) {
+  auto S = cat(access("Id", access("subId", "memberData")));
+  EXPECT_EQ(S.toString(),
+            R"repr(access("Id", access("subId", "memberData")))repr");
+}
+
+TEST(StencilToStringTest, IfBoundOp) {
+  auto S = cat(ifBound("Id", text("trueText"), access("exprId", "memberData")));
+  EXPECT_EQ(
+      S.toString(),
+      R"repr(ifBound("Id", "trueText", access("exprId", "memberData")))repr");
+}
+
+TEST(StencilToStringTest, MultipleOp) {
+  auto S = cat("foo", access("x", "m()"), "bar",
+               ifBound("x", text("t"), access("e", "f")));
+  EXPECT_EQ(S.toString(), R"repr("foo", access("x", "m()"), "bar", )repr"
+                          R"repr(ifBound("x", "t", access("e", "f")))repr");
+}
 } // namespace




More information about the cfe-commits mailing list