LLVM 20.0.0git
RewriteBuffer.cpp
Go to the documentation of this file.
1//===- RewriteBuffer.h - Buffer rewriting interface -----------------------===//
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
11
12using namespace llvm;
13
15 // Walk RewriteRope chunks efficiently using MoveToNextPiece() instead of the
16 // character iterator.
17 for (RopePieceBTreeIterator I = begin(), E = end(); I != E;
18 I.MoveToNextPiece())
19 Stream << I.piece();
20 return Stream;
21}
22
23/// Return true if this character is non-new-line whitespace:
24/// ' ', '\\t', '\\f', '\\v', '\\r'.
25static inline bool isWhitespaceExceptNL(unsigned char c) {
26 return c == ' ' || c == '\t' || c == '\f' || c == '\v' || c == '\r';
27}
28
29void RewriteBuffer::RemoveText(unsigned OrigOffset, unsigned Size,
30 bool removeLineIfEmpty) {
31 // Nothing to remove, exit early.
32 if (Size == 0)
33 return;
34
35 unsigned RealOffset = getMappedOffset(OrigOffset, true);
36 assert(RealOffset + Size <= Buffer.size() && "Invalid location");
37
38 // Remove the dead characters.
39 Buffer.erase(RealOffset, Size);
40
41 // Add a delta so that future changes are offset correctly.
42 AddReplaceDelta(OrigOffset, -Size);
43
44 if (removeLineIfEmpty) {
45 // Find the line that the remove occurred and if it is completely empty
46 // remove the line as well.
47
48 iterator curLineStart = begin();
49 unsigned curLineStartOffs = 0;
50 iterator posI = begin();
51 for (unsigned i = 0; i != RealOffset; ++i) {
52 if (*posI == '\n') {
53 curLineStart = posI;
54 ++curLineStart;
55 curLineStartOffs = i + 1;
56 }
57 ++posI;
58 }
59
60 unsigned lineSize = 0;
61 posI = curLineStart;
62 while (posI != end() && isWhitespaceExceptNL(*posI)) {
63 ++posI;
64 ++lineSize;
65 }
66 if (posI != end() && *posI == '\n') {
67 Buffer.erase(curLineStartOffs, lineSize + 1 /* + '\n'*/);
68 // FIXME: Here, the offset of the start of the line is supposed to be
69 // expressed in terms of the original input not the "real" rewrite
70 // buffer. How do we compute that reliably? It might be tempting to use
71 // curLineStartOffs + OrigOffset - RealOffset, but that assumes the
72 // difference between the original and real offset is the same at the
73 // removed text and at the start of the line, but that's not true if
74 // edits were previously made earlier on the line. This bug is also
75 // documented by a FIXME on the definition of
76 // clang::Rewriter::RewriteOptions::RemoveLineIfEmpty. A reproducer for
77 // the implementation below is the test RemoveLineIfEmpty in
78 // clang/unittests/Rewrite/RewriteBufferTest.cpp.
79 AddReplaceDelta(curLineStartOffs, -(lineSize + 1 /* + '\n'*/));
80 }
81 }
82}
83
84void RewriteBuffer::InsertText(unsigned OrigOffset, StringRef Str,
85 bool InsertAfter) {
86 // Nothing to insert, exit early.
87 if (Str.empty())
88 return;
89
90 unsigned RealOffset = getMappedOffset(OrigOffset, InsertAfter);
91 Buffer.insert(RealOffset, Str.begin(), Str.end());
92
93 // Add a delta so that future changes are offset correctly.
94 AddInsertDelta(OrigOffset, Str.size());
95}
96
97/// ReplaceText - This method replaces a range of characters in the input
98/// buffer with a new string. This is effectively a combined "remove+insert"
99/// operation.
100void RewriteBuffer::ReplaceText(unsigned OrigOffset, unsigned OrigLength,
101 StringRef NewStr) {
102 unsigned RealOffset = getMappedOffset(OrigOffset, true);
103 Buffer.erase(RealOffset, OrigLength);
104 Buffer.insert(RealOffset, NewStr.begin(), NewStr.end());
105 if (OrigLength != NewStr.size())
106 AddReplaceDelta(OrigOffset, NewStr.size() - OrigLength);
107}
uint64_t Size
#define I(x, y, z)
Definition: MD5.cpp:58
static bool isWhitespaceExceptNL(unsigned char c)
Return true if this character is non-new-line whitespace: ' ', '\t', '\f', '\v', '\r'.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void RemoveText(unsigned OrigOffset, unsigned Size, bool removeLineIfEmpty=false)
RemoveText - Remove the specified text.
raw_ostream & write(raw_ostream &Stream) const
Write to Stream the result of applying all changes to the original buffer.
iterator end() const
Definition: RewriteBuffer.h:43
void InsertText(unsigned OrigOffset, StringRef Str, bool InsertAfter=true)
InsertText - Insert some text at the specified point, where the offset in the buffer is specified rel...
iterator begin() const
Definition: RewriteBuffer.h:42
void ReplaceText(unsigned OrigOffset, unsigned OrigLength, StringRef NewStr)
ReplaceText - This method replaces a range of characters in the input buffer with a new string.
unsigned size() const
Definition: RewriteRope.h:193
void insert(unsigned Offset, const char *Start, const char *End)
Definition: RewriteRope.h:203
void erase(unsigned Offset, unsigned NumBytes)
Definition: RewriteRope.h:210
RopePieceBTreeIterator - This class provides read-only forward iteration over bytes that are in a Rop...
Definition: RewriteRope.h:86
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
iterator begin() const
Definition: StringRef.h:111
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:137
iterator end() const
Definition: StringRef.h:113
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18