[clang] [clang][transformer] Add `join` stencil. (PR #107366)

Clement Courbet via cfe-commits cfe-commits at lists.llvm.org
Thu Sep 5 01:29:41 PDT 2024


https://github.com/legrosbuffle created https://github.com/llvm/llvm-project/pull/107366

`join(",", a, b, c)` is the same as `cat(a, ",", b, ",", c)`.

>From 0c9d87c0e25e598f40ecf3f4977cd5ed2e205636 Mon Sep 17 00:00:00 2001
From: Clement Courbet <courbet at google.com>
Date: Thu, 5 Sep 2024 06:53:07 +0000
Subject: [PATCH] [clang][transformer] Add `join` stencil.

`join(",", a, b, c)` is the same as `cat(a, ",", b, ",", c)`.
---
 clang/include/clang/Tooling/Transformer/Stencil.h |  9 +++++++++
 clang/lib/Tooling/Transformer/Stencil.cpp         | 15 +++++++++++++++
 clang/unittests/Tooling/StencilTest.cpp           |  5 +++++
 3 files changed, 29 insertions(+)

diff --git a/clang/include/clang/Tooling/Transformer/Stencil.h b/clang/include/clang/Tooling/Transformer/Stencil.h
index 249f95b7391dfe..461b8ee6b77ae1 100644
--- a/clang/include/clang/Tooling/Transformer/Stencil.h
+++ b/clang/include/clang/Tooling/Transformer/Stencil.h
@@ -65,6 +65,15 @@ template <typename... Ts> Stencil cat(Ts &&... Parts) {
   return catVector({detail::makeStencil(std::forward<Ts>(Parts))...});
 }
 
+// Constructs the string representing the concatenation of the given \p
+// Parts, separated using \p Sep.
+Stencil joinVector(StringRef Sep, std::vector<Stencil> Parts);
+
+// Same as `cat(Parts[0], Sep, Parts[1], Sep, ...,)`.
+template <typename... Ts> Stencil join(StringRef Sep, Ts &&...Parts) {
+  return joinVector(Sep, {detail::makeStencil(std::forward<Ts>(Parts))...});
+}
+
 //
 // Functions for conveniently building stencils.
 //
diff --git a/clang/lib/Tooling/Transformer/Stencil.cpp b/clang/lib/Tooling/Transformer/Stencil.cpp
index bc4fa6e36057c1..15eec577c71659 100644
--- a/clang/lib/Tooling/Transformer/Stencil.cpp
+++ b/clang/lib/Tooling/Transformer/Stencil.cpp
@@ -492,3 +492,18 @@ Stencil transformer::catVector(std::vector<Stencil> Parts) {
     return std::move(Parts[0]);
   return std::make_shared<SequenceStencil>(std::move(Parts));
 }
+
+Stencil transformer::joinVector(StringRef Sep, std::vector<Stencil> Parts) {
+  if (Parts.size() == 1)
+    return std::move(Parts[0]);
+
+  Stencil SepStencil = detail::makeStencil(Sep);
+  std::vector<Stencil> SeparatedParts;
+  SeparatedParts.reserve(2 * Parts.size() - 1);
+  SeparatedParts.push_back(std::move(Parts[0]));
+  for (size_t I = 1, E = Parts.size(); I < E; ++I) {
+    SeparatedParts.emplace_back(SepStencil);
+    SeparatedParts.push_back(std::move(Parts[I]));
+  }
+  return std::make_shared<SequenceStencil>(std::move(SeparatedParts));
+}
diff --git a/clang/unittests/Tooling/StencilTest.cpp b/clang/unittests/Tooling/StencilTest.cpp
index 26257cf2ca3a5f..db6cbe3d120bbd 100644
--- a/clang/unittests/Tooling/StencilTest.cpp
+++ b/clang/unittests/Tooling/StencilTest.cpp
@@ -769,4 +769,9 @@ TEST(StencilToStringTest, SequenceFromVector) {
                        R"repr(ifBound("x", "t", access("e", "f"))))repr";
   EXPECT_EQ(S->toString(), Expected);
 }
+
+TEST(StencilToStringTest, Join) {
+  auto S = join(" sep ", cat("a"), cat("b"), cat("c"));
+  EXPECT_EQ(S->toString(), R"repr(seq("a", " sep ", "b", " sep ", "c"))repr");
+}
 } // namespace



More information about the cfe-commits mailing list