clang  3.7.0
Replacement.h
Go to the documentation of this file.
1 //===--- Replacement.h - Framework for clang refactoring tools --*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Classes supporting refactorings that span multiple translation units.
11 // While single translation unit refactorings are supported via the Rewriter,
12 // when refactoring multiple translation units changes must be stored in a
13 // SourceManager independent form, duplicate changes need to be removed, and
14 // all changes must be applied at once at the end of the refactoring so that
15 // the code is always parseable.
16 //
17 //===----------------------------------------------------------------------===//
18 
19 #ifndef LLVM_CLANG_TOOLING_CORE_REPLACEMENT_H
20 #define LLVM_CLANG_TOOLING_CORE_REPLACEMENT_H
21 
24 #include "llvm/ADT/StringRef.h"
25 #include <set>
26 #include <string>
27 #include <vector>
28 
29 namespace clang {
30 
31 class Rewriter;
32 
33 namespace tooling {
34 
35 /// \brief A source range independent of the \c SourceManager.
36 class Range {
37 public:
38  Range() : Offset(0), Length(0) {}
39  Range(unsigned Offset, unsigned Length) : Offset(Offset), Length(Length) {}
40 
41  /// \brief Accessors.
42  /// @{
43  unsigned getOffset() const { return Offset; }
44  unsigned getLength() const { return Length; }
45  /// @}
46 
47  /// \name Range Predicates
48  /// @{
49  /// \brief Whether this range overlaps with \p RHS or not.
50  bool overlapsWith(Range RHS) const {
51  return Offset + Length > RHS.Offset && Offset < RHS.Offset + RHS.Length;
52  }
53 
54  /// \brief Whether this range contains \p RHS or not.
55  bool contains(Range RHS) const {
56  return RHS.Offset >= Offset &&
57  (RHS.Offset + RHS.Length) <= (Offset + Length);
58  }
59  /// @}
60 
61 private:
62  unsigned Offset;
63  unsigned Length;
64 };
65 
66 /// \brief A text replacement.
67 ///
68 /// Represents a SourceManager independent replacement of a range of text in a
69 /// specific file.
70 class Replacement {
71 public:
72  /// \brief Creates an invalid (not applicable) replacement.
73  Replacement();
74 
75  /// \brief Creates a replacement of the range [Offset, Offset+Length) in
76  /// FilePath with ReplacementText.
77  ///
78  /// \param FilePath A source file accessible via a SourceManager.
79  /// \param Offset The byte offset of the start of the range in the file.
80  /// \param Length The length of the range in bytes.
81  Replacement(StringRef FilePath, unsigned Offset, unsigned Length,
82  StringRef ReplacementText);
83 
84  /// \brief Creates a Replacement of the range [Start, Start+Length) with
85  /// ReplacementText.
86  Replacement(const SourceManager &Sources, SourceLocation Start,
87  unsigned Length, StringRef ReplacementText);
88 
89  /// \brief Creates a Replacement of the given range with ReplacementText.
90  Replacement(const SourceManager &Sources, const CharSourceRange &Range,
91  StringRef ReplacementText,
92  const LangOptions &LangOpts = LangOptions());
93 
94  /// \brief Creates a Replacement of the node with ReplacementText.
95  template <typename Node>
96  Replacement(const SourceManager &Sources, const Node &NodeToReplace,
97  StringRef ReplacementText,
98  const LangOptions &LangOpts = LangOptions());
99 
100  /// \brief Returns whether this replacement can be applied to a file.
101  ///
102  /// Only replacements that are in a valid file can be applied.
103  bool isApplicable() const;
104 
105  /// \brief Accessors.
106  /// @{
107  StringRef getFilePath() const { return FilePath; }
108  unsigned getOffset() const { return ReplacementRange.getOffset(); }
109  unsigned getLength() const { return ReplacementRange.getLength(); }
110  StringRef getReplacementText() const { return ReplacementText; }
111  /// @}
112 
113  /// \brief Applies the replacement on the Rewriter.
114  bool apply(Rewriter &Rewrite) const;
115 
116  /// \brief Returns a human readable string representation.
117  std::string toString() const;
118 
119  private:
120  void setFromSourceLocation(const SourceManager &Sources,
121  SourceLocation Start, unsigned Length,
122  StringRef ReplacementText);
123  void setFromSourceRange(const SourceManager &Sources,
124  const CharSourceRange &Range,
125  StringRef ReplacementText,
126  const LangOptions &LangOpts);
127 
128  std::string FilePath;
129  Range ReplacementRange;
130  std::string ReplacementText;
131 };
132 
133 /// \brief Less-than operator between two Replacements.
134 bool operator<(const Replacement &LHS, const Replacement &RHS);
135 
136 /// \brief Equal-to operator between two Replacements.
137 bool operator==(const Replacement &LHS, const Replacement &RHS);
138 
139 /// \brief A set of Replacements.
140 /// FIXME: Change to a vector and deduplicate in the RefactoringTool.
141 typedef std::set<Replacement> Replacements;
142 
143 /// \brief Apply all replacements in \p Replaces to the Rewriter \p Rewrite.
144 ///
145 /// Replacement applications happen independently of the success of
146 /// other applications.
147 ///
148 /// \returns true if all replacements apply. false otherwise.
149 bool applyAllReplacements(const Replacements &Replaces, Rewriter &Rewrite);
150 
151 /// \brief Apply all replacements in \p Replaces to the Rewriter \p Rewrite.
152 ///
153 /// Replacement applications happen independently of the success of
154 /// other applications.
155 ///
156 /// \returns true if all replacements apply. false otherwise.
157 bool applyAllReplacements(const std::vector<Replacement> &Replaces,
158  Rewriter &Rewrite);
159 
160 /// \brief Applies all replacements in \p Replaces to \p Code.
161 ///
162 /// This completely ignores the path stored in each replacement. If one or more
163 /// replacements cannot be applied, this returns an empty \c string.
164 std::string applyAllReplacements(StringRef Code, const Replacements &Replaces);
165 
166 /// \brief Calculates how a code \p Position is shifted when \p Replaces are
167 /// applied.
168 unsigned shiftedCodePosition(const Replacements& Replaces, unsigned Position);
169 
170 /// \brief Calculates how a code \p Position is shifted when \p Replaces are
171 /// applied.
172 ///
173 /// \pre Replaces[i].getOffset() <= Replaces[i+1].getOffset().
174 unsigned shiftedCodePosition(const std::vector<Replacement> &Replaces,
175  unsigned Position);
176 
177 /// \brief Removes duplicate Replacements and reports if Replacements conflict
178 /// with one another. All Replacements are assumed to be in the same file.
179 ///
180 /// \post Replaces[i].getOffset() <= Replaces[i+1].getOffset().
181 ///
182 /// This function sorts \p Replaces so that conflicts can be reported simply by
183 /// offset into \p Replaces and number of elements in the conflict.
184 void deduplicate(std::vector<Replacement> &Replaces,
185  std::vector<Range> &Conflicts);
186 
187 /// \brief Collection of Replacements generated from a single translation unit.
189  /// Name of the main source for the translation unit.
190  std::string MainSourceFile;
191 
192  /// A freeform chunk of text to describe the context of the replacements.
193  /// Will be printed, for example, when detecting conflicts during replacement
194  /// deduplication.
195  std::string Context;
196 
197  std::vector<Replacement> Replacements;
198 };
199 
200 /// \brief Apply all replacements in \p Replaces to the Rewriter \p Rewrite.
201 ///
202 /// Replacement applications happen independently of the success of
203 /// other applications.
204 ///
205 /// \returns true if all replacements apply. false otherwise.
206 bool applyAllReplacements(const Replacements &Replaces, Rewriter &Rewrite);
207 
208 /// \brief Apply all replacements in \p Replaces to the Rewriter \p Rewrite.
209 ///
210 /// Replacement applications happen independently of the success of
211 /// other applications.
212 ///
213 /// \returns true if all replacements apply. false otherwise.
214 bool applyAllReplacements(const std::vector<Replacement> &Replaces,
215  Rewriter &Rewrite);
216 
217 /// \brief Applies all replacements in \p Replaces to \p Code.
218 ///
219 /// This completely ignores the path stored in each replacement. If one or more
220 /// replacements cannot be applied, this returns an empty \c string.
221 std::string applyAllReplacements(StringRef Code, const Replacements &Replaces);
222 
223 template <typename Node>
225  const Node &NodeToReplace, StringRef ReplacementText,
226  const LangOptions &LangOpts) {
227  const CharSourceRange Range =
228  CharSourceRange::getTokenRange(NodeToReplace->getSourceRange());
229  setFromSourceRange(Sources, Range, ReplacementText, LangOpts);
230 }
231 
232 } // end namespace tooling
233 } // end namespace clang
234 
235 #endif // LLVM_CLANG_TOOLING_CORE_REPLACEMENT_H
int Position
bool contains(Range RHS) const
Whether this range contains RHS or not.
Definition: Replacement.h:55
static CharSourceRange getTokenRange(SourceRange R)
std::set< Replacement > Replacements
A set of Replacements. FIXME: Change to a vector and deduplicate in the RefactoringTool.
Definition: Replacement.h:141
unsigned getLength() const
Definition: Replacement.h:44
bool operator==(const Replacement &LHS, const Replacement &RHS)
Equal-to operator between two Replacements.
void deduplicate(std::vector< Replacement > &Replaces, std::vector< Range > &Conflicts)
Removes duplicate Replacements and reports if Replacements conflict with one another. All Replacements are assumed to be in the same file.
bool apply(Rewriter &Rewrite) const
Applies the replacement on the Rewriter.
Definition: Replacement.cpp:55
bool applyAllReplacements(const Replacements &Replaces, Rewriter &Rewrite)
Apply all replacements in Replaces to the Rewriter Rewrite.
StringRef getReplacementText() const
Definition: Replacement.h:110
unsigned getLength() const
Definition: Replacement.h:109
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:48
Collection of Replacements generated from a single translation unit.
Definition: Replacement.h:188
uint32_t Offset
Definition: CacheTokens.cpp:43
Replacement()
Creates an invalid (not applicable) replacement.
Definition: Replacement.cpp:31
A text replacement.
Definition: Replacement.h:70
A source range independent of the SourceManager.
Definition: Replacement.h:36
bool operator<(const Replacement &LHS, const Replacement &RHS)
Less-than operator between two Replacements.
Definition: Replacement.cpp:88
Defines the clang::LangOptions interface.
Represents a character-granular source range.
unsigned shiftedCodePosition(const Replacements &Replaces, unsigned Position)
Calculates how a code Position is shifted when Replaces are applied.
unsigned getOffset() const
Definition: Replacement.h:108
Encodes a location in the source. The SourceManager can decode this to get at the full include stack...
std::string MainSourceFile
Name of the main source for the translation unit.
Definition: Replacement.h:190
StringRef getFilePath() const
Accessors.
Definition: Replacement.h:107
unsigned getOffset() const
Accessors.
Definition: Replacement.h:43
ast_type_traits::DynTypedNode Node
std::vector< Replacement > Replacements
Definition: Replacement.h:197
std::string toString() const
Returns a human readable string representation.
Definition: Replacement.cpp:80
bool isApplicable() const
Returns whether this replacement can be applied to a file.
Definition: Replacement.cpp:51
Defines the clang::SourceLocation class and associated facilities.
Range(unsigned Offset, unsigned Length)
Definition: Replacement.h:39
bool overlapsWith(Range RHS) const
Definition: Replacement.h:50
This class handles loading and caching of source files into memory.