
These classes are not specific to clang and useful for other rewriter tools (flagged in previous review).
108 lines
3.9 KiB
C++
108 lines
3.9 KiB
C++
//===- RewriteBuffer.h - Buffer rewriting interface -----------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/ADT/RewriteBuffer.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
using namespace llvm;
|
|
|
|
raw_ostream &RewriteBuffer::write(raw_ostream &Stream) const {
|
|
// Walk RewriteRope chunks efficiently using MoveToNextPiece() instead of the
|
|
// character iterator.
|
|
for (RopePieceBTreeIterator I = begin(), E = end(); I != E;
|
|
I.MoveToNextPiece())
|
|
Stream << I.piece();
|
|
return Stream;
|
|
}
|
|
|
|
/// Return true if this character is non-new-line whitespace:
|
|
/// ' ', '\\t', '\\f', '\\v', '\\r'.
|
|
static inline bool isWhitespaceExceptNL(unsigned char c) {
|
|
return c == ' ' || c == '\t' || c == '\f' || c == '\v' || c == '\r';
|
|
}
|
|
|
|
void RewriteBuffer::RemoveText(unsigned OrigOffset, unsigned Size,
|
|
bool removeLineIfEmpty) {
|
|
// Nothing to remove, exit early.
|
|
if (Size == 0)
|
|
return;
|
|
|
|
unsigned RealOffset = getMappedOffset(OrigOffset, true);
|
|
assert(RealOffset + Size <= Buffer.size() && "Invalid location");
|
|
|
|
// Remove the dead characters.
|
|
Buffer.erase(RealOffset, Size);
|
|
|
|
// Add a delta so that future changes are offset correctly.
|
|
AddReplaceDelta(OrigOffset, -Size);
|
|
|
|
if (removeLineIfEmpty) {
|
|
// Find the line that the remove occurred and if it is completely empty
|
|
// remove the line as well.
|
|
|
|
iterator curLineStart = begin();
|
|
unsigned curLineStartOffs = 0;
|
|
iterator posI = begin();
|
|
for (unsigned i = 0; i != RealOffset; ++i) {
|
|
if (*posI == '\n') {
|
|
curLineStart = posI;
|
|
++curLineStart;
|
|
curLineStartOffs = i + 1;
|
|
}
|
|
++posI;
|
|
}
|
|
|
|
unsigned lineSize = 0;
|
|
posI = curLineStart;
|
|
while (posI != end() && isWhitespaceExceptNL(*posI)) {
|
|
++posI;
|
|
++lineSize;
|
|
}
|
|
if (posI != end() && *posI == '\n') {
|
|
Buffer.erase(curLineStartOffs, lineSize + 1 /* + '\n'*/);
|
|
// FIXME: Here, the offset of the start of the line is supposed to be
|
|
// expressed in terms of the original input not the "real" rewrite
|
|
// buffer. How do we compute that reliably? It might be tempting to use
|
|
// curLineStartOffs + OrigOffset - RealOffset, but that assumes the
|
|
// difference between the original and real offset is the same at the
|
|
// removed text and at the start of the line, but that's not true if
|
|
// edits were previously made earlier on the line. This bug is also
|
|
// documented by a FIXME on the definition of
|
|
// clang::Rewriter::RewriteOptions::RemoveLineIfEmpty. A reproducer for
|
|
// the implementation below is the test RemoveLineIfEmpty in
|
|
// clang/unittests/Rewrite/RewriteBufferTest.cpp.
|
|
AddReplaceDelta(curLineStartOffs, -(lineSize + 1 /* + '\n'*/));
|
|
}
|
|
}
|
|
}
|
|
|
|
void RewriteBuffer::InsertText(unsigned OrigOffset, StringRef Str,
|
|
bool InsertAfter) {
|
|
// Nothing to insert, exit early.
|
|
if (Str.empty())
|
|
return;
|
|
|
|
unsigned RealOffset = getMappedOffset(OrigOffset, InsertAfter);
|
|
Buffer.insert(RealOffset, Str.begin(), Str.end());
|
|
|
|
// Add a delta so that future changes are offset correctly.
|
|
AddInsertDelta(OrigOffset, Str.size());
|
|
}
|
|
|
|
/// ReplaceText - This method replaces a range of characters in the input
|
|
/// buffer with a new string. This is effectively a combined "remove+insert"
|
|
/// operation.
|
|
void RewriteBuffer::ReplaceText(unsigned OrigOffset, unsigned OrigLength,
|
|
StringRef NewStr) {
|
|
unsigned RealOffset = getMappedOffset(OrigOffset, true);
|
|
Buffer.erase(RealOffset, OrigLength);
|
|
Buffer.insert(RealOffset, NewStr.begin(), NewStr.end());
|
|
if (OrigLength != NewStr.size())
|
|
AddReplaceDelta(OrigOffset, NewStr.size() - OrigLength);
|
|
}
|