]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/llvm/tools/clang/include/clang/Rewrite/Rewriter.h
Copy head to stable/9 as part of 9.0-RELEASE release cycle.
[FreeBSD/stable/9.git] / contrib / llvm / tools / clang / include / clang / Rewrite / Rewriter.h
1 //===--- Rewriter.h - Code rewriting interface ------------------*- 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 //  This file defines the Rewriter class, which is used for code
11 //  transformations.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #ifndef LLVM_CLANG_REWRITER_H
16 #define LLVM_CLANG_REWRITER_H
17
18 #include "clang/Basic/SourceLocation.h"
19 #include "clang/Rewrite/DeltaTree.h"
20 #include "clang/Rewrite/RewriteRope.h"
21 #include "llvm/ADT/StringRef.h"
22 #include <cstring>
23 #include <map>
24 #include <string>
25
26 namespace llvm { class raw_ostream; }
27
28 namespace clang {
29   class LangOptions;
30   class Rewriter;
31   class SourceManager;
32   class Stmt;
33
34 /// RewriteBuffer - As code is rewritten, SourceBuffer's from the original
35 /// input with modifications get a new RewriteBuffer associated with them.  The
36 /// RewriteBuffer captures the modified text itself as well as information used
37 /// to map between SourceLocation's in the original input and offsets in the
38 /// RewriteBuffer.  For example, if text is inserted into the buffer, any
39 /// locations after the insertion point have to be mapped.
40 class RewriteBuffer {
41   friend class Rewriter;
42   /// Deltas - Keep track of all the deltas in the source code due to insertions
43   /// and deletions.
44   DeltaTree Deltas;
45
46   /// Buffer - This is the actual buffer itself.  Note that using a vector or
47   /// string is a horribly inefficient way to do this, we should use a rope
48   /// instead.
49   typedef RewriteRope BufferTy;
50   BufferTy Buffer;
51 public:
52   typedef BufferTy::const_iterator iterator;
53   iterator begin() const { return Buffer.begin(); }
54   iterator end() const { return Buffer.end(); }
55   unsigned size() const { return Buffer.size(); }
56
57   llvm::raw_ostream &write(llvm::raw_ostream &) const;
58
59   /// RemoveText - Remove the specified text.
60   void RemoveText(unsigned OrigOffset, unsigned Size,
61                   bool removeLineIfEmpty = false);
62
63   /// InsertText - Insert some text at the specified point, where the offset in
64   /// the buffer is specified relative to the original SourceBuffer.  The
65   /// text is inserted after the specified location.
66   ///
67   void InsertText(unsigned OrigOffset, llvm::StringRef Str,
68                   bool InsertAfter = true);
69
70
71   /// InsertTextBefore - Insert some text before the specified point, where the
72   /// offset in the buffer is specified relative to the original
73   /// SourceBuffer. The text is inserted before the specified location.  This is
74   /// method is the same as InsertText with "InsertAfter == false".
75   void InsertTextBefore(unsigned OrigOffset, llvm::StringRef Str) {
76     InsertText(OrigOffset, Str, false);
77   }
78
79   /// InsertTextAfter - Insert some text at the specified point, where the
80   /// offset in the buffer is specified relative to the original SourceBuffer.
81   /// The text is inserted after the specified location.
82   void InsertTextAfter(unsigned OrigOffset, llvm::StringRef Str) {
83     InsertText(OrigOffset, Str);
84   }
85
86   /// ReplaceText - This method replaces a range of characters in the input
87   /// buffer with a new string.  This is effectively a combined "remove/insert"
88   /// operation.
89   void ReplaceText(unsigned OrigOffset, unsigned OrigLength,
90                    llvm::StringRef NewStr);
91
92 private:  // Methods only usable by Rewriter.
93
94   /// Initialize - Start this rewrite buffer out with a copy of the unmodified
95   /// input buffer.
96   void Initialize(const char *BufStart, const char *BufEnd) {
97     Buffer.assign(BufStart, BufEnd);
98   }
99
100   /// getMappedOffset - Given an offset into the original SourceBuffer that this
101   /// RewriteBuffer is based on, map it into the offset space of the
102   /// RewriteBuffer.  If AfterInserts is true and if the OrigOffset indicates a
103   /// position where text is inserted, the location returned will be after any
104   /// inserted text at the position.
105   unsigned getMappedOffset(unsigned OrigOffset,
106                            bool AfterInserts = false) const{
107     return Deltas.getDeltaAt(2*OrigOffset+AfterInserts)+OrigOffset;
108   }
109
110   /// AddInsertDelta - When an insertion is made at a position, this
111   /// method is used to record that information.
112   void AddInsertDelta(unsigned OrigOffset, int Change) {
113     return Deltas.AddDelta(2*OrigOffset, Change);
114   }
115
116   /// AddReplaceDelta - When a replacement/deletion is made at a position, this
117   /// method is used to record that information.
118   void AddReplaceDelta(unsigned OrigOffset, int Change) {
119     return Deltas.AddDelta(2*OrigOffset+1, Change);
120   }
121 };
122
123
124 /// Rewriter - This is the main interface to the rewrite buffers.  Its primary
125 /// job is to dispatch high-level requests to the low-level RewriteBuffers that
126 /// are involved.
127 class Rewriter {
128   SourceManager *SourceMgr;
129   const LangOptions *LangOpts;
130   std::map<FileID, RewriteBuffer> RewriteBuffers;
131 public:
132   struct RewriteOptions {
133     /// \brief Given a source range, true to include previous inserts at the
134     /// beginning of the range as part of the range itself (true by default).
135     bool IncludeInsertsAtBeginOfRange;
136     /// \brief Given a source range, true to include previous inserts at the
137     /// end of the range as part of the range itself (true by default).
138     bool IncludeInsertsAtEndOfRange;
139     /// \brief If true and removing some text leaves a blank line
140     /// also remove the empty line (false by default).
141     bool RemoveLineIfEmpty;
142
143     RewriteOptions()
144       : IncludeInsertsAtBeginOfRange(true),
145         IncludeInsertsAtEndOfRange(true),
146         RemoveLineIfEmpty(false) { }
147   };
148
149   typedef std::map<FileID, RewriteBuffer>::iterator buffer_iterator;
150
151   explicit Rewriter(SourceManager &SM, const LangOptions &LO)
152     : SourceMgr(&SM), LangOpts(&LO) {}
153   explicit Rewriter() : SourceMgr(0), LangOpts(0) {}
154
155   void setSourceMgr(SourceManager &SM, const LangOptions &LO) {
156     SourceMgr = &SM;
157     LangOpts = &LO;
158   }
159   SourceManager &getSourceMgr() { return *SourceMgr; }
160   const LangOptions &getLangOpts() { return *LangOpts; }
161
162   /// isRewritable - Return true if this location is a raw file location, which
163   /// is rewritable.  Locations from macros, etc are not rewritable.
164   static bool isRewritable(SourceLocation Loc) {
165     return Loc.isFileID();
166   }
167
168   /// getRangeSize - Return the size in bytes of the specified range if they
169   /// are in the same file.  If not, this returns -1.
170   int getRangeSize(SourceRange Range,
171                    RewriteOptions opts = RewriteOptions()) const;
172   int getRangeSize(const CharSourceRange &Range,
173                    RewriteOptions opts = RewriteOptions()) const;
174
175   /// getRewrittenText - Return the rewritten form of the text in the specified
176   /// range.  If the start or end of the range was unrewritable or if they are
177   /// in different buffers, this returns an empty string.
178   ///
179   /// Note that this method is not particularly efficient.
180   ///
181   std::string getRewrittenText(SourceRange Range) const;
182
183   /// InsertText - Insert the specified string at the specified location in the
184   /// original buffer.  This method returns true (and does nothing) if the input
185   /// location was not rewritable, false otherwise.
186   ///
187   /// \param indentNewLines if true new lines in the string are indented
188   /// using the indentation of the source line in position \arg Loc.
189   bool InsertText(SourceLocation Loc, llvm::StringRef Str,
190                   bool InsertAfter = true, bool indentNewLines = false);
191
192   /// InsertTextAfter - Insert the specified string at the specified location in
193   ///  the original buffer.  This method returns true (and does nothing) if
194   ///  the input location was not rewritable, false otherwise.  Text is
195   ///  inserted after any other text that has been previously inserted
196   ///  at the some point (the default behavior for InsertText).
197   bool InsertTextAfter(SourceLocation Loc, llvm::StringRef Str) {
198     return InsertText(Loc, Str);
199   }
200
201   /// \brief Insert the specified string after the token in the
202   /// specified location.
203   bool InsertTextAfterToken(SourceLocation Loc, llvm::StringRef Str);
204
205   /// InsertText - Insert the specified string at the specified location in the
206   /// original buffer.  This method returns true (and does nothing) if the input
207   /// location was not rewritable, false otherwise.  Text is
208   /// inserted before any other text that has been previously inserted
209   /// at the some point.
210   bool InsertTextBefore(SourceLocation Loc, llvm::StringRef Str) {
211     return InsertText(Loc, Str, false);
212   }
213
214   /// RemoveText - Remove the specified text region.
215   bool RemoveText(SourceLocation Start, unsigned Length,
216                   RewriteOptions opts = RewriteOptions());
217
218   /// \brief Remove the specified text region.
219   bool RemoveText(CharSourceRange range,
220                   RewriteOptions opts = RewriteOptions()) {
221     return RemoveText(range.getBegin(), getRangeSize(range, opts), opts);
222   }
223
224   /// \brief Remove the specified text region.
225   bool RemoveText(SourceRange range, RewriteOptions opts = RewriteOptions()) {
226     return RemoveText(range.getBegin(), getRangeSize(range, opts), opts);
227   }
228
229   /// ReplaceText - This method replaces a range of characters in the input
230   /// buffer with a new string.  This is effectively a combined "remove/insert"
231   /// operation.
232   bool ReplaceText(SourceLocation Start, unsigned OrigLength,
233                    llvm::StringRef NewStr);
234
235   /// ReplaceText - This method replaces a range of characters in the input
236   /// buffer with a new string.  This is effectively a combined "remove/insert"
237   /// operation.
238   bool ReplaceText(SourceRange range, llvm::StringRef NewStr) {
239     return ReplaceText(range.getBegin(), getRangeSize(range), NewStr);
240   }
241
242   /// ReplaceText - This method replaces a range of characters in the input
243   /// buffer with a new string.  This is effectively a combined "remove/insert"
244   /// operation.
245   bool ReplaceText(SourceRange range, SourceRange replacementRange);
246
247   /// ReplaceStmt - This replaces a Stmt/Expr with another, using the pretty
248   /// printer to generate the replacement code.  This returns true if the input
249   /// could not be rewritten, or false if successful.
250   bool ReplaceStmt(Stmt *From, Stmt *To);
251
252   /// \brief Increase indentation for the lines between the given source range.
253   /// To determine what the indentation should be, 'parentIndent' is used
254   /// that should be at a source location with an indentation one degree
255   /// lower than the given range.
256   bool IncreaseIndentation(CharSourceRange range, SourceLocation parentIndent);
257   bool IncreaseIndentation(SourceRange range, SourceLocation parentIndent) {
258     return IncreaseIndentation(CharSourceRange::getTokenRange(range),
259                                parentIndent);
260   }
261
262   /// ConvertToString converts statement 'From' to a string using the
263   /// pretty printer.
264   std::string ConvertToString(Stmt *From);
265
266   /// getEditBuffer - This is like getRewriteBufferFor, but always returns a
267   /// buffer, and allows you to write on it directly.  This is useful if you
268   /// want efficient low-level access to apis for scribbling on one specific
269   /// FileID's buffer.
270   RewriteBuffer &getEditBuffer(FileID FID);
271
272   /// getRewriteBufferFor - Return the rewrite buffer for the specified FileID.
273   /// If no modification has been made to it, return null.
274   const RewriteBuffer *getRewriteBufferFor(FileID FID) const {
275     std::map<FileID, RewriteBuffer>::const_iterator I =
276       RewriteBuffers.find(FID);
277     return I == RewriteBuffers.end() ? 0 : &I->second;
278   }
279
280   // Iterators over rewrite buffers.
281   buffer_iterator buffer_begin() { return RewriteBuffers.begin(); }
282   buffer_iterator buffer_end() { return RewriteBuffers.end(); }
283
284 private:
285   unsigned getLocationOffsetAndFileID(SourceLocation Loc, FileID &FID) const;
286 };
287
288 } // end namespace clang
289
290 #endif