]> granicus.if.org Git - clang/commitdiff
Introduce Rewriter::IncreaseIndentation() which increase indentations for the lines...
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Sat, 16 Apr 2011 01:03:33 +0000 (01:03 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Sat, 16 Apr 2011 01:03:33 +0000 (01:03 +0000)
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

include/clang/Rewrite/Rewriter.h
lib/Rewrite/Rewriter.cpp

index 9513e674649b2583cbfd50992eb76f79297c4ffc..4ef5820ee3b48fb99c272f4774205ae703ee781f 100644 (file)
@@ -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);
index 5ccf0f332cb8d79f2844345098195f8b9f0c0023..2ff61363ffbd7d3e2f5c9412c801383c6b3cba41 100644 (file)
@@ -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;
+}