clang  9.0.0
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_REFACTOR_STENCIL_H_
21 #define LLVM_CLANG_TOOLING_REFACTOR_STENCIL_H_
22 
23 #include "clang/AST/ASTContext.h"
27 #include "llvm/ADT/StringRef.h"
28 #include "llvm/Support/Error.h"
29 #include <string>
30 #include <vector>
31 
32 namespace clang {
33 namespace tooling {
34 
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  virtual bool isEqual(const StencilPartInterface &other) const = 0;
51 
52  const void *typeId() const { return TypeId; }
53 
54 protected:
55  StencilPartInterface(const void *DerivedId) : TypeId(DerivedId) {}
56 
57  // Since this is an abstract class, copying/assigning only make sense for
58  // derived classes implementing `clone()`.
59  StencilPartInterface(const StencilPartInterface &) = default;
61 
62  /// Unique identifier of the concrete type of this instance. Supports safe
63  /// downcasting.
64  const void *TypeId;
65 };
66 
67 /// A copyable facade for a std::unique_ptr<StencilPartInterface>. Copies result
68 /// in a copy of the underlying pointee object.
69 class StencilPart {
70 public:
71  explicit StencilPart(std::shared_ptr<StencilPartInterface> Impl)
72  : Impl(std::move(Impl)) {}
73 
74  /// See `StencilPartInterface::eval()`.
76  std::string *Result) const {
77  return Impl->eval(Match, Result);
78  }
79 
80  bool operator==(const StencilPart &Other) const {
81  if (Impl == Other.Impl)
82  return true;
83  if (Impl == nullptr || Other.Impl == nullptr)
84  return false;
85  return Impl->isEqual(*Other.Impl);
86  }
87 
88 private:
89  std::shared_ptr<StencilPartInterface> Impl;
90 };
91 
92 /// A sequence of code fragments, references to parameters and code-generation
93 /// operations that together can be evaluated to (a fragment of) source code,
94 /// given a match result.
95 class Stencil {
96 public:
97  Stencil() = default;
98 
99  /// Composes a stencil from a series of parts.
100  template <typename... Ts> static Stencil cat(Ts &&... Parts) {
101  Stencil S;
102  S.Parts = {wrap(std::forward<Ts>(Parts))...};
103  return S;
104  }
105 
106  /// Appends data from a \p OtherStencil to this stencil.
107  void append(Stencil OtherStencil);
108 
109  // Evaluates the stencil given a match result. Requires that the nodes in the
110  // result includes any ids referenced in the stencil. References to missing
111  // nodes will result in an invalid_argument error.
113  eval(const ast_matchers::MatchFinder::MatchResult &Match) const;
114 
115  // Allow Stencils to operate as std::function, for compatibility with
116  // Transformer's TextGenerator.
119  return eval(Result);
120  }
121 
122 private:
123  friend bool operator==(const Stencil &A, const Stencil &B);
124  static StencilPart wrap(llvm::StringRef Text);
125  static StencilPart wrap(RangeSelector Selector);
126  static StencilPart wrap(StencilPart Part) { return Part; }
127 
128  std::vector<StencilPart> Parts;
129 };
130 
131 inline bool operator==(const Stencil &A, const Stencil &B) {
132  return A.Parts == B.Parts;
133 }
134 
135 inline bool operator!=(const Stencil &A, const Stencil &B) { return !(A == B); }
136 
137 // Functions for conveniently building stencils.
138 namespace stencil {
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 /// \returns the source corresponding to the identified node.
151 /// FIXME: Deprecated. Write `selection(node(Id))` instead.
152 inline StencilPart node(llvm::StringRef Id) {
153  return selection(tooling::node(Id));
154 }
155 
156 /// Variant of \c node() that identifies the node as a statement, for purposes
157 /// of deciding whether to include any trailing semicolon. Only relevant for
158 /// Expr nodes, which, by default, are *not* considered as statements.
159 /// \returns the source corresponding to the identified node, considered as a
160 /// statement.
161 /// FIXME: Deprecated. Write `selection(statement(Id))` instead.
162 inline StencilPart sNode(llvm::StringRef Id) {
163  return selection(tooling::statement(Id));
164 }
165 
166 /// For debug use only; semantics are not guaranteed.
167 ///
168 /// \returns the string resulting from calling the node's print() method.
169 StencilPart dPrint(llvm::StringRef Id);
170 } // namespace stencil
171 } // namespace tooling
172 } // namespace clang
173 #endif // LLVM_CLANG_TOOLING_REFACTOR_STENCIL_H_
Defines the clang::ASTContext interface.
A stencil is represented as a sequence of "parts" that can each individually generate a code string b...
Definition: Stencil.h:41
Smart pointer class that efficiently represents Objective-C method names.
A sequence of code fragments, references to parameters and code-generation operations that together c...
Definition: Stencil.h:95
virtual bool isEqual(const StencilPartInterface &other) const =0
bool operator==(const Replacement &LHS, const Replacement &RHS)
Equal-to operator between two Replacements.
RangeSelector statement(std::string ID)
Selects a node, including trailing semicolon (always).
Definition: Format.h:2274
llvm::Expected< std::string > operator()(const ast_matchers::MatchFinder::MatchResult &Result) const
Definition: Stencil.h:118
StencilPartInterface(const void *DerivedId)
Definition: Stencil.h:55
std::function< Expected< CharSourceRange >(const ast_matchers::MatchFinder::MatchResult &)> RangeSelector
Definition: RangeSelector.h:27
llvm::Error eval(const ast_matchers::MatchFinder::MatchResult &Match, std::string *Result) const
See StencilPartInterface::eval().
Definition: Stencil.h:75
bool operator!=(const Stencil &A, const Stencil &B)
Definition: Stencil.h:135
RangeSelector node(std::string ID)
Selects a node, including trailing semicolon (for non-expression statements).
A copyable facade for a std::unique_ptr<StencilPartInterface>.
Definition: Stencil.h:69
int Id
Definition: ASTDiff.cpp:190
StencilPartInterface & operator=(const StencilPartInterface &)=default
Contains all information for a given match.
StencilPart selection(RangeSelector Selector)
Definition: Stencil.cpp:169
Stencil cat(Ts &&... Parts)
Convenience wrapper for Stencil::cat that can be imported with a using decl.
Definition: Stencil.h:140
bool operator==(const StencilPart &Other) const
Definition: Stencil.h:80
Dataflow Directional Tag Classes.
StencilPart dPrint(llvm::StringRef Id)
For debug use only; semantics are not guaranteed.
Defines a combinator library supporting the definition of selectors, which select source ranges based...
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(std::shared_ptr< StencilPartInterface > Impl)
Definition: Stencil.h:71
static Stencil cat(Ts &&... Parts)
Composes a stencil from a series of parts.
Definition: Stencil.h:100
StringRef Text
Definition: Format.cpp:1712
const void * TypeId
Unique identifier of the concrete type of this instance.
Definition: Stencil.h:64
TextGenerator text(std::string M)
Wraps a string as a TextGenerator.
Definition: Transformer.h:42
const void * typeId() const
Definition: Stencil.h:52
StencilPart sNode(llvm::StringRef Id)
Variant of node() that identifies the node as a statement, for purposes of deciding whether to includ...
Definition: Stencil.h:162