summaryrefslogtreecommitdiffstats
path: root/lib/Rewrite/Rewriter.cpp
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2011-05-02 19:39:53 +0000
committerdim <dim@FreeBSD.org>2011-05-02 19:39:53 +0000
commit110eaaceddcec790f7e6a5e3bf1261c9aa1e73ab (patch)
tree64a10f4c4154739d4a8191d7e1b52ce497f4ebd6 /lib/Rewrite/Rewriter.cpp
parenta0fb00f9837bd0d2e5948f16f6a6b82a7a628f51 (diff)
downloadFreeBSD-src-110eaaceddcec790f7e6a5e3bf1261c9aa1e73ab.zip
FreeBSD-src-110eaaceddcec790f7e6a5e3bf1261c9aa1e73ab.tar.gz
Vendor import of clang trunk r130700:
http://llvm.org/svn/llvm-project/cfe/trunk@130700
Diffstat (limited to 'lib/Rewrite/Rewriter.cpp')
-rw-r--r--lib/Rewrite/Rewriter.cpp177
1 files changed, 169 insertions, 8 deletions
diff --git a/lib/Rewrite/Rewriter.cpp b/lib/Rewrite/Rewriter.cpp
index 92e2b03..51fe379 100644
--- a/lib/Rewrite/Rewriter.cpp
+++ b/lib/Rewrite/Rewriter.cpp
@@ -26,7 +26,23 @@ llvm::raw_ostream &RewriteBuffer::write(llvm::raw_ostream &os) const {
return os;
}
-void RewriteBuffer::RemoveText(unsigned OrigOffset, unsigned Size) {
+/// \brief Return true if this character is non-new-line whitespace:
+/// ' ', '\t', '\f', '\v', '\r'.
+static inline bool isWhitespace(unsigned char c) {
+ switch (c) {
+ case ' ':
+ case '\t':
+ case '\f':
+ case '\v':
+ case '\r':
+ return true;
+ default:
+ return false;
+ }
+}
+
+void RewriteBuffer::RemoveText(unsigned OrigOffset, unsigned Size,
+ bool removeLineIfEmpty) {
// Nothing to remove, exit early.
if (Size == 0) return;
@@ -38,6 +54,34 @@ void RewriteBuffer::RemoveText(unsigned OrigOffset, unsigned 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() && isWhitespace(*posI)) {
+ ++posI;
+ ++lineSize;
+ }
+ if (posI != end() && *posI == '\n') {
+ Buffer.erase(curLineStartOffs, lineSize + 1/* + '\n'*/);
+ AddReplaceDelta(curLineStartOffs, -(lineSize + 1/* + '\n'*/));
+ }
+ }
}
void RewriteBuffer::InsertText(unsigned OrigOffset, llvm::StringRef Str,
@@ -72,7 +116,8 @@ void RewriteBuffer::ReplaceText(unsigned OrigOffset, unsigned OrigLength,
/// getRangeSize - Return the size in bytes of the specified range if they
/// are in the same file. If not, this returns -1.
-int Rewriter::getRangeSize(const CharSourceRange &Range) const {
+int Rewriter::getRangeSize(const CharSourceRange &Range,
+ RewriteOptions opts) const {
if (!isRewritable(Range.getBegin()) ||
!isRewritable(Range.getEnd())) return -1;
@@ -91,8 +136,8 @@ int Rewriter::getRangeSize(const CharSourceRange &Range) const {
RewriteBuffers.find(StartFileID);
if (I != RewriteBuffers.end()) {
const RewriteBuffer &RB = I->second;
- EndOff = RB.getMappedOffset(EndOff, true);
- StartOff = RB.getMappedOffset(StartOff);
+ EndOff = RB.getMappedOffset(EndOff, opts.IncludeInsertsAtEndOfRange);
+ StartOff = RB.getMappedOffset(StartOff, !opts.IncludeInsertsAtBeginOfRange);
}
@@ -104,8 +149,8 @@ int Rewriter::getRangeSize(const CharSourceRange &Range) const {
return EndOff-StartOff;
}
-int Rewriter::getRangeSize(SourceRange Range) const {
- return getRangeSize(CharSourceRange::getTokenRange(Range));
+int Rewriter::getRangeSize(SourceRange Range, RewriteOptions opts) const {
+ return getRangeSize(CharSourceRange::getTokenRange(Range), opts);
}
@@ -194,12 +239,24 @@ bool Rewriter::InsertText(SourceLocation Loc, llvm::StringRef Str,
return false;
}
+bool Rewriter::InsertTextAfterToken(SourceLocation Loc, llvm::StringRef Str) {
+ if (!isRewritable(Loc)) return true;
+ FileID FID;
+ unsigned StartOffs = getLocationOffsetAndFileID(Loc, FID);
+ RewriteOptions rangeOpts;
+ rangeOpts.IncludeInsertsAtBeginOfRange = false;
+ StartOffs += getRangeSize(SourceRange(Loc, Loc), rangeOpts);
+ getEditBuffer(FID).InsertText(StartOffs, Str, /*InsertAfter*/true);
+ return false;
+}
+
/// RemoveText - Remove the specified text region.
-bool Rewriter::RemoveText(SourceLocation Start, unsigned Length) {
+bool Rewriter::RemoveText(SourceLocation Start, unsigned Length,
+ RewriteOptions opts) {
if (!isRewritable(Start)) return true;
FileID FID;
unsigned StartOffs = getLocationOffsetAndFileID(Start, FID);
- getEditBuffer(FID).RemoveText(StartOffs, Length);
+ getEditBuffer(FID).RemoveText(StartOffs, Length, opts.RemoveLineIfEmpty);
return false;
}
@@ -216,6 +273,20 @@ bool Rewriter::ReplaceText(SourceLocation Start, unsigned OrigLength,
return false;
}
+bool Rewriter::ReplaceText(SourceRange range, SourceRange replacementRange) {
+ if (!isRewritable(range.getBegin())) return true;
+ if (!isRewritable(range.getEnd())) return true;
+ if (replacementRange.isInvalid()) return true;
+ SourceLocation start = range.getBegin();
+ unsigned origLength = getRangeSize(range);
+ unsigned newLength = getRangeSize(replacementRange);
+ FileID FID;
+ unsigned newOffs = getLocationOffsetAndFileID(replacementRange.getBegin(),
+ FID);
+ llvm::StringRef MB = SourceMgr->getBufferData(FID);
+ return ReplaceText(start, origLength, MB.substr(newOffs, newLength));
+}
+
/// ReplaceStmt - This replaces a Stmt/Expr with another, using the pretty
/// printer to generate the replacement code. This returns true if the input
/// could not be rewritten, or false if successful.
@@ -234,3 +305,93 @@ bool Rewriter::ReplaceStmt(Stmt *From, Stmt *To) {
ReplaceText(From->getLocStart(), Size, Str);
return false;
}
+
+std::string Rewriter::ConvertToString(Stmt *From) {
+ std::string SStr;
+ llvm::raw_string_ostream S(SStr);
+ From->printPretty(S, 0, PrintingPolicy(*LangOpts));
+ return S.str();
+}
+
+bool Rewriter::IncreaseIndentation(CharSourceRange range,
+ SourceLocation parentIndent) {
+ using llvm::StringRef;
+
+ if (!isRewritable(range.getBegin())) return true;
+ if (!isRewritable(range.getEnd())) return true;
+ if (!isRewritable(parentIndent)) return true;
+
+ FileID StartFileID, EndFileID, parentFileID;
+ unsigned StartOff, EndOff, parentOff;
+
+ StartOff = getLocationOffsetAndFileID(range.getBegin(), StartFileID);
+ EndOff = getLocationOffsetAndFileID(range.getEnd(), EndFileID);
+ parentOff = getLocationOffsetAndFileID(parentIndent, parentFileID);
+
+ if (StartFileID != EndFileID || StartFileID != parentFileID)
+ return true;
+ if (StartOff >= EndOff || parentOff >= StartOff)
+ return true;
+
+ FileID FID = StartFileID;
+ StringRef MB = SourceMgr->getBufferData(FID);
+
+ unsigned parentLineNo = SourceMgr->getLineNumber(FID, parentOff) - 1;
+ unsigned startLineNo = SourceMgr->getLineNumber(FID, StartOff) - 1;
+ unsigned endLineNo = SourceMgr->getLineNumber(FID, EndOff) - 1;
+
+ const SrcMgr::ContentCache *
+ Content = SourceMgr->getSLocEntry(FID).getFile().getContentCache();
+
+ // Find where the line starts for the three offsets.
+ unsigned parentLineOffs = Content->SourceLineCache[parentLineNo];
+ unsigned startLineOffs = Content->SourceLineCache[startLineNo];
+ unsigned endLineOffs = Content->SourceLineCache[endLineNo];
+
+ if (startLineOffs == endLineOffs || startLineOffs == parentLineOffs)
+ return true;
+
+ // Find the whitespace at the start of each line.
+ StringRef parentSpace, startSpace, endSpace;
+ {
+ unsigned i = parentLineOffs;
+ while (isWhitespace(MB[i]))
+ ++i;
+ parentSpace = MB.substr(parentLineOffs, i-parentLineOffs);
+
+ i = startLineOffs;
+ while (isWhitespace(MB[i]))
+ ++i;
+ startSpace = MB.substr(startLineOffs, i-startLineOffs);
+
+ i = endLineOffs;
+ while (isWhitespace(MB[i]))
+ ++i;
+ endSpace = MB.substr(endLineOffs, i-endLineOffs);
+ }
+ if (parentSpace.size() >= startSpace.size())
+ return true;
+ if (!startSpace.startswith(parentSpace))
+ return true;
+
+ llvm::StringRef indent = startSpace.substr(parentSpace.size());
+
+ // Indent the lines between start/end offsets.
+ RewriteBuffer &RB = getEditBuffer(FID);
+ for (unsigned i = startLineOffs; i != endLineOffs; ++i) {
+ if (MB[i] == '\n') {
+ unsigned startOfLine = i+1;
+ if (startOfLine == endLineOffs)
+ break;
+ StringRef origIndent;
+ unsigned ws = startOfLine;
+ while (isWhitespace(MB[ws]))
+ ++ws;
+ origIndent = MB.substr(startOfLine, ws-startOfLine);
+ if (origIndent.startswith(startSpace))
+ RB.InsertText(startOfLine, indent, /*InsertAfter=*/false);
+ }
+ }
+
+ return false;
+}
OpenPOWER on IntegriCloud