1 //===- RewriteBuffer.h - Buffer 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 #ifndef LLVM_CLANG_REWRITE_CORE_REWRITEBUFFER_H
11 #define LLVM_CLANG_REWRITE_CORE_REWRITEBUFFER_H
12 
13 #include "clang/Basic/LLVM.h"
14 #include "clang/Rewrite/Core/DeltaTree.h"
15 #include "clang/Rewrite/Core/RewriteRope.h"
16 #include "llvm/ADT/StringRef.h"
17 
18 namespace clang {
19 
20 /// RewriteBuffer - As code is rewritten, SourceBuffer's from the original
21 /// input with modifications get a new RewriteBuffer associated with them.  The
22 /// RewriteBuffer captures the modified text itself as well as information used
23 /// to map between SourceLocation's in the original input and offsets in the
24 /// RewriteBuffer.  For example, if text is inserted into the buffer, any
25 /// locations after the insertion point have to be mapped.
26 class RewriteBuffer {
27   friend class Rewriter;
28 
29   /// Deltas - Keep track of all the deltas in the source code due to insertions
30   /// and deletions.
31   DeltaTree Deltas;
32 
33   RewriteRope Buffer;
34 
35 public:
36   using iterator = RewriteRope::const_iterator;
37 
begin()38   iterator begin() const { return Buffer.begin(); }
end()39   iterator end() const { return Buffer.end(); }
size()40   unsigned size() const { return Buffer.size(); }
41 
42   /// Initialize - Start this rewrite buffer out with a copy of the unmodified
43   /// input buffer.
Initialize(const char * BufStart,const char * BufEnd)44   void Initialize(const char *BufStart, const char *BufEnd) {
45     Buffer.assign(BufStart, BufEnd);
46   }
Initialize(StringRef Input)47   void Initialize(StringRef Input) {
48     Initialize(Input.begin(), Input.end());
49   }
50 
51   /// Write to \p Stream the result of applying all changes to the
52   /// original buffer.
53   /// Note that it isn't safe to use this function to overwrite memory mapped
54   /// files in-place (PR17960). Consider using a higher-level utility such as
55   /// Rewriter::overwriteChangedFiles() instead.
56   ///
57   /// The original buffer is not actually changed.
58   raw_ostream &write(raw_ostream &Stream) const;
59 
60   /// RemoveText - Remove the specified text.
61   void RemoveText(unsigned OrigOffset, unsigned Size,
62                   bool removeLineIfEmpty = false);
63 
64   /// InsertText - Insert some text at the specified point, where the offset in
65   /// the buffer is specified relative to the original SourceBuffer.  The
66   /// text is inserted after the specified location.
67   void InsertText(unsigned OrigOffset, 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".
InsertTextBefore(unsigned OrigOffset,StringRef Str)75   void InsertTextBefore(unsigned OrigOffset, 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.
InsertTextAfter(unsigned OrigOffset,StringRef Str)82   void InsertTextAfter(unsigned OrigOffset, 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                    StringRef NewStr);
91 
92 private:
93   /// getMappedOffset - Given an offset into the original SourceBuffer that this
94   /// RewriteBuffer is based on, map it into the offset space of the
95   /// RewriteBuffer.  If AfterInserts is true and if the OrigOffset indicates a
96   /// position where text is inserted, the location returned will be after any
97   /// inserted text at the position.
98   unsigned getMappedOffset(unsigned OrigOffset,
99                            bool AfterInserts = false) const{
100     return Deltas.getDeltaAt(2*OrigOffset+AfterInserts)+OrigOffset;
101   }
102 
103   /// AddInsertDelta - When an insertion is made at a position, this
104   /// method is used to record that information.
AddInsertDelta(unsigned OrigOffset,int Change)105   void AddInsertDelta(unsigned OrigOffset, int Change) {
106     return Deltas.AddDelta(2*OrigOffset, Change);
107   }
108 
109   /// AddReplaceDelta - When a replacement/deletion is made at a position, this
110   /// method is used to record that information.
AddReplaceDelta(unsigned OrigOffset,int Change)111   void AddReplaceDelta(unsigned OrigOffset, int Change) {
112     return Deltas.AddDelta(2*OrigOffset+1, Change);
113   }
114 };
115 
116 } // namespace clang
117 
118 #endif // LLVM_CLANG_REWRITE_CORE_REWRITEBUFFER_H
119