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