From: Argyrios Kyrtzidis Date: Sat, 16 Apr 2011 01:03:33 +0000 (+0000) Subject: Introduce Rewriter::IncreaseIndentation() which increase indentations for the lines... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=10c8d9e63bcc96d55f788e7c08b72ce626c8aeec;p=clang Introduce Rewriter::IncreaseIndentation() which increase indentations for the lines between the given source range. To determine what the indentation should be, a SourceLocation 'parentIndent' parameter is used that should be at a source location with an indentation one degree lower than the given range. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@129628 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Rewrite/Rewriter.h b/include/clang/Rewrite/Rewriter.h index 9513e67464..4ef5820ee3 100644 --- a/include/clang/Rewrite/Rewriter.h +++ b/include/clang/Rewrite/Rewriter.h @@ -246,7 +246,17 @@ public: /// printer to generate the replacement code. This returns true if the input /// could not be rewritten, or false if successful. bool ReplaceStmt(Stmt *From, Stmt *To); - + + /// \brief Increase indentation for the lines between the given source range. + /// To determine what the indentation should be, 'parentIndent' is used + /// that should be at a source location with an indentation one degree + /// lower than the given range. + bool IncreaseIndentation(CharSourceRange range, SourceLocation parentIndent); + bool IncreaseIndentation(SourceRange range, SourceLocation parentIndent) { + return IncreaseIndentation(CharSourceRange::getTokenRange(range), + parentIndent); + } + /// ConvertToString converts statement 'From' to a string using the /// pretty printer. std::string ConvertToString(Stmt *From); diff --git a/lib/Rewrite/Rewriter.cpp b/lib/Rewrite/Rewriter.cpp index 5ccf0f332c..2ff61363ff 100644 --- a/lib/Rewrite/Rewriter.cpp +++ b/lib/Rewrite/Rewriter.cpp @@ -312,3 +312,86 @@ std::string Rewriter::ConvertToString(Stmt *From) { From->printPretty(S, 0, PrintingPolicy(*LangOpts)); return SStr; } + +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; +}