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