clang  10.0.0svn
Stencil.h
Go to the documentation of this file.
1 //===--- Stencil.h - Stencil class ------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// This file defines the *Stencil* abstraction: a code-generating object,
11 /// parameterized by named references to (bound) AST nodes. Given a match
12 /// result, a stencil can be evaluated to a string of source code.
13 ///
14 /// A stencil is similar in spirit to a format string: it is composed of a
15 /// series of raw text strings, references to nodes (the parameters) and helper
16 /// code-generation operations.
17 ///
18 //===----------------------------------------------------------------------===//
19 
20 #ifndef LLVM_CLANG_TOOLING_TRANSFORMER_STENCIL_H_
21 #define LLVM_CLANG_TOOLING_TRANSFORMER_STENCIL_H_
22 
23 #include "clang/AST/ASTContext.h"
28 #include "llvm/ADT/StringRef.h"
29 #include "llvm/Support/Error.h"
30 #include <string>
31 #include <vector>
32 
33 namespace clang {
34 namespace transformer {
35 /// A stencil is represented as a sequence of "parts" that can each individually
36 /// generate a code string based on a match result. The different kinds of
37 /// parts include (raw) text, references to bound nodes and assorted operations
38 /// on bound nodes.
39 ///
40 /// Users can create custom Stencil operations by implementing this interface.
42 public:
43  virtual ~StencilPartInterface() = default;
44 
45  /// Evaluates this part to a string and appends it to \c Result. \c Result is
46  /// undefined in the case of an error.
48  std::string *Result) const = 0;
49 
50  /// Constructs a string representation of the StencilPart. StencilParts
51  /// generated by the `selection` and `run` functions do not have a unique
52  /// string representation.
53  virtual std::string toString() const = 0;
54 
55 protected:
56  StencilPartInterface() = default;
57 
58  // Since this is an abstract class, copying/assigning only make sense for
59  // derived classes implementing `clone()`.
60  StencilPartInterface(const StencilPartInterface &) = default;
62 };
63 
64 /// A copyable facade for a std::unique_ptr<StencilPartInterface>. Copies result
65 /// in a copy of the underlying pointee object.
66 class StencilPart {
67 public:
68  explicit StencilPart(std::shared_ptr<StencilPartInterface> Impl)
69  : Impl(std::move(Impl)) {}
70 
71  /// See `StencilPartInterface::eval()`.
73  std::string *Result) const {
74  return Impl->eval(Match, Result);
75  }
76 
77  std::string toString() const {
78  if (Impl == nullptr)
79  return "";
80  return Impl->toString();
81  }
82 
83 private:
84  std::shared_ptr<StencilPartInterface> Impl;
85 };
86 
87 /// A sequence of code fragments, references to parameters and code-generation
88 /// operations that together can be evaluated to (a fragment of) source code,
89 /// given a match result.
90 class Stencil {
91 public:
92  Stencil() = default;
93 
94  /// Composes a stencil from a series of parts.
95  template <typename... Ts> static Stencil cat(Ts &&... Parts) {
96  Stencil S;
97  S.Parts = {wrap(std::forward<Ts>(Parts))...};
98  return S;
99  }
100 
101  /// Appends data from a \p OtherStencil to this stencil.
102  void append(Stencil OtherStencil);
103 
104  // Evaluates the stencil given a match result. Requires that the nodes in the
105  // result includes any ids referenced in the stencil. References to missing
106  // nodes will result in an invalid_argument error.
108  eval(const ast_matchers::MatchFinder::MatchResult &Match) const;
109 
110  // Allow Stencils to operate as std::function, for compatibility with
111  // Transformer's TextGenerator.
114  return eval(Result);
115  }
116 
117  /// Constructs a string representation of the Stencil. The string is not
118  /// guaranteed to be unique.
119  std::string toString() const {
120  std::vector<std::string> PartStrings;
121  PartStrings.reserve(Parts.size());
122  for (const auto &Part : Parts)
123  PartStrings.push_back(Part.toString());
124  return llvm::join(PartStrings, ", ");
125  }
126 
127 private:
128  static StencilPart wrap(llvm::StringRef Text);
129  static StencilPart wrap(RangeSelector Selector);
130  static StencilPart wrap(StencilPart Part) { return Part; }
131 
132  std::vector<StencilPart> Parts;
133 };
134 
135 //
136 // Functions for conveniently building stencils.
137 //
138 
139 /// Convenience wrapper for Stencil::cat that can be imported with a using decl.
140 template <typename... Ts> Stencil cat(Ts &&... Parts) {
141  return Stencil::cat(std::forward<Ts>(Parts)...);
142 }
143 
144 /// \returns exactly the text provided.
145 StencilPart text(llvm::StringRef Text);
146 
147 /// \returns the source corresponding to the selected range.
149 
150 /// Generates the source of the expression bound to \p Id, wrapping it in
151 /// parentheses if it may parse differently depending on context. For example, a
152 /// binary operation is always wrapped, while a variable reference is never
153 /// wrapped.
154 StencilPart expression(llvm::StringRef Id);
155 
156 /// Constructs an idiomatic dereferencing of the expression bound to \p ExprId.
157 /// \p ExprId is wrapped in parentheses, if needed.
158 StencilPart deref(llvm::StringRef ExprId);
159 
160 /// Constructs an expression that idiomatically takes the address of the
161 /// expression bound to \p ExprId. \p ExprId is wrapped in parentheses, if
162 /// needed.
163 StencilPart addressOf(llvm::StringRef ExprId);
164 
165 /// Constructs a `MemberExpr` that accesses the named member (\p Member) of the
166 /// object bound to \p BaseId. The access is constructed idiomatically: if \p
167 /// BaseId is bound to `e` and \p Member identifies member `m`, then returns
168 /// `e->m`, when e is a pointer, `e2->m` when e = `*e2` and `e.m` otherwise.
169 /// Additionally, `e` is wrapped in parentheses, if needed.
170 StencilPart access(llvm::StringRef BaseId, StencilPart Member);
171 inline StencilPart access(llvm::StringRef BaseId, llvm::StringRef Member) {
172  return access(BaseId, text(Member));
173 }
174 
175 /// Chooses between the two stencil parts, based on whether \p ID is bound in
176 /// the match.
177 StencilPart ifBound(llvm::StringRef Id, StencilPart TruePart,
178  StencilPart FalsePart);
179 
180 /// Chooses between the two strings, based on whether \p ID is bound in the
181 /// match.
182 inline StencilPart ifBound(llvm::StringRef Id, llvm::StringRef TrueText,
183  llvm::StringRef FalseText) {
184  return ifBound(Id, text(TrueText), text(FalseText));
185 }
186 
187 /// Wraps a MatchConsumer in a StencilPart, so that it can be used in a Stencil.
188 /// This supports user-defined extensions to the Stencil language.
190 
191 /// For debug use only; semantics are not guaranteed.
192 ///
193 /// \returns the string resulting from calling the node's print() method.
194 StencilPart dPrint(llvm::StringRef Id);
195 } // namespace transformer
196 
197 namespace tooling {
198 // DEPRECATED: These are temporary aliases supporting client migration to the
199 // `transformer` namespace.
202 namespace stencil {
203 using transformer::access;
205 using transformer::cat;
206 using transformer::deref;
207 using transformer::dPrint;
210 using transformer::run;
212 using transformer::text;
213 /// \returns the source corresponding to the identified node.
214 /// FIXME: Deprecated. Write `selection(node(Id))` instead.
215 inline transformer::StencilPart node(llvm::StringRef Id) {
216  return selection(tooling::node(Id));
217 }
218 } // namespace stencil
219 } // namespace tooling
220 } // namespace clang
221 #endif // LLVM_CLANG_TOOLING_TRANSFORMER_STENCIL_H_
StencilPartInterface & operator=(const StencilPartInterface &)=default
Defines the clang::ASTContext interface.
Smart pointer class that efficiently represents Objective-C method names.
StencilPart selection(RangeSelector Selector)
Definition: Stencil.cpp:279
MatchConsumer< T > ifBound(std::string ID, MatchConsumer< T > TrueC, MatchConsumer< T > FalseC)
Chooses between the two consumers, based on whether ID is bound in the match.
Definition: MatchConsumer.h:47
A sequence of code fragments, references to parameters and code-generation operations that together c...
Definition: Stencil.h:90
std::string toString() const
Constructs a string representation of the Stencil.
Definition: Stencil.h:119
transformer::StencilPart node(llvm::StringRef Id)
Definition: Stencil.h:215
std::string toString() const
Definition: Stencil.h:77
Definition: Format.h:2392
static Stencil cat(Ts &&... Parts)
Composes a stencil from a series of parts.
Definition: Stencil.h:95
virtual llvm::Error eval(const ast_matchers::MatchFinder::MatchResult &Match, std::string *Result) const =0
Evaluates this part to a string and appends it to Result.
StencilPart deref(llvm::StringRef ExprId)
Constructs an idiomatic dereferencing of the expression bound to ExprId.
Definition: Stencil.cpp:293
StencilPart dPrint(llvm::StringRef Id)
For debug use only; semantics are not guaranteed.
transformer::StencilPart StencilPart
Definition: Stencil.h:201
StencilPart expression(llvm::StringRef Id)
Generates the source of the expression bound to Id, wrapping it in parentheses if it may parse differ...
Definition: Stencil.cpp:288
transformer::Stencil Stencil
Definition: Stencil.h:200
int Id
Definition: ASTDiff.cpp:190
StencilPart addressOf(llvm::StringRef ExprId)
Constructs an expression that idiomatically takes the address of the expression bound to ExprId...
Definition: Stencil.cpp:298
StencilPart run(MatchConsumer< std::string > C)
Wraps a MatchConsumer in a StencilPart, so that it can be used in a Stencil.
Definition: Stencil.cpp:314
A copyable facade for a std::unique_ptr<StencilPartInterface>.
Definition: Stencil.h:66
Contains all information for a given match.
MatchConsumer< CharSourceRange > RangeSelector
Definition: RangeSelector.h:27
std::function< Expected< T >(const ast_matchers::MatchFinder::MatchResult &)> MatchConsumer
A failable computation over nodes bound by AST matchers.
Definition: MatchConsumer.h:35
Stencil cat(Ts &&... Parts)
Convenience wrapper for Stencil::cat that can be imported with a using decl.
Definition: Stencil.h:140
Dataflow Directional Tag Classes.
StencilPart text(llvm::StringRef Text)
llvm::Expected< std::string > operator()(const ast_matchers::MatchFinder::MatchResult &Result) const
Definition: Stencil.h:113
StencilPart(std::shared_ptr< StencilPartInterface > Impl)
Definition: Stencil.h:68
Defines a combinator library supporting the definition of selectors, which select source ranges based...
A stencil is represented as a sequence of "parts" that can each individually generate a code string b...
Definition: Stencil.h:41
llvm::Error eval(const ast_matchers::MatchFinder::MatchResult &Match, std::string *Result) const
See StencilPartInterface::eval().
Definition: Stencil.h:72
StencilPart access(llvm::StringRef BaseId, StencilPart Member)
Constructs a MemberExpr that accesses the named member (Member) of the object bound to BaseId...
StringRef Text
Definition: Format.cpp:1808
RangeSelector node(std::string ID)
Selects a node, including trailing semicolon (for non-expression statements).
virtual std::string toString() const =0
Constructs a string representation of the StencilPart.