[cfe-commits] r129085 - in /cfe/trunk: include/clang/Rewrite/Rewriter.h lib/Rewrite/Rewriter.cpp

Argyrios Kyrtzidis akyrtzi at gmail.com
Thu Apr 7 11:10:12 PDT 2011


Author: akirtzidis
Date: Thu Apr  7 13:10:12 2011
New Revision: 129085

URL: http://llvm.org/viewvc/llvm-project?rev=129085&view=rev
Log:
Enhance the Rewriter.

-Allow removing a line completely if it ends up empty
-Provide more control on what should be removed.

Modified:
    cfe/trunk/include/clang/Rewrite/Rewriter.h
    cfe/trunk/lib/Rewrite/Rewriter.cpp

Modified: cfe/trunk/include/clang/Rewrite/Rewriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Rewrite/Rewriter.h?rev=129085&r1=129084&r2=129085&view=diff
==============================================================================
--- cfe/trunk/include/clang/Rewrite/Rewriter.h (original)
+++ cfe/trunk/include/clang/Rewrite/Rewriter.h Thu Apr  7 13:10:12 2011
@@ -58,7 +58,8 @@
   llvm::raw_ostream &write(llvm::raw_ostream &) const;
 
   /// RemoveText - Remove the specified text.
-  void RemoveText(unsigned OrigOffset, unsigned Size);
+  void RemoveText(unsigned OrigOffset, unsigned Size,
+                  bool removeLineIfEmpty = false);
 
   /// InsertText - Insert some text at the specified point, where the offset in
   /// the buffer is specified relative to the original SourceBuffer.  The
@@ -150,8 +151,11 @@
 
   /// getRangeSize - Return the size in bytes of the specified range if they
   /// are in the same file.  If not, this returns -1.
-  int getRangeSize(SourceRange Range) const;
-  int getRangeSize(const CharSourceRange &Range) const;
+  /// If AfterInserts is true and if the beginning of range indicates a position
+  /// where text is inserted, the beginning of range will be after any inserted
+  /// text at the position.
+  int getRangeSize(SourceRange Range, bool AfterInserts = false) const;
+  int getRangeSize(const CharSourceRange &Range, bool AfterInserts=false) const;
 
   /// getRewrittenText - Return the rewritten form of the text in the specified
   /// range.  If the start or end of the range was unrewritable or if they are
@@ -176,6 +180,10 @@
     return InsertText(Loc, Str);
   }
 
+  /// \brief Insert the specified string after the token in the
+  /// specified location.
+  bool InsertTextAfterToken(SourceLocation Loc, llvm::StringRef Str);
+
   /// InsertText - Insert the specified string at the specified location in the
   /// original buffer.  This method returns true (and does nothing) if the input
   /// location was not rewritable, false otherwise.  Text is
@@ -186,7 +194,34 @@
   }
 
   /// RemoveText - Remove the specified text region.
-  bool RemoveText(SourceLocation Start, unsigned Length);
+  bool RemoveText(SourceLocation Start, unsigned Length,
+                  bool removeLineIfEmpty = false);
+
+  /// \brief Remove the specified text region.
+  ///
+  /// \param afterInserts if true the beginning of removal will be after any
+  /// inserted text at the position.
+  ///
+  /// \param removeLineIfEmpty if true and removing the text leaves a blank line
+  /// also remove the empty line.
+  bool RemoveText(CharSourceRange range, bool afterInserts = false,
+                  bool removeLineIfEmpty = false) {
+    return RemoveText(range.getBegin(), getRangeSize(range, afterInserts),
+                      removeLineIfEmpty);
+  }
+
+  /// \brief Remove the specified text region.
+  ///
+  /// \param afterInserts if true the beginning of removal will be after any
+  /// inserted text at the position.
+  ///
+  /// \param removeLineIfEmpty if true and removing the text leaves a blank line
+  /// also remove the empty line.
+  bool RemoveText(SourceRange range, bool afterInserts = false,
+                  bool removeLineIfEmpty = false) {
+    return RemoveText(range.getBegin(), getRangeSize(range, afterInserts),
+                      removeLineIfEmpty);
+  }
 
   /// ReplaceText - This method replaces a range of characters in the input
   /// buffer with a new string.  This is effectively a combined "remove/insert"
@@ -194,6 +229,18 @@
   bool ReplaceText(SourceLocation Start, unsigned OrigLength,
                    llvm::StringRef NewStr);
 
+  /// ReplaceText - This method replaces a range of characters in the input
+  /// buffer with a new string.  This is effectively a combined "remove/insert"
+  /// operation.
+  bool ReplaceText(SourceRange range, llvm::StringRef NewStr) {
+    return ReplaceText(range.getBegin(), getRangeSize(range), NewStr);
+  }
+
+  /// ReplaceText - This method replaces a range of characters in the input
+  /// buffer with a new string.  This is effectively a combined "remove/insert"
+  /// operation.
+  bool ReplaceText(SourceRange range, SourceRange replacementRange);
+
   /// 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.

Modified: cfe/trunk/lib/Rewrite/Rewriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/Rewriter.cpp?rev=129085&r1=129084&r2=129085&view=diff
==============================================================================
--- cfe/trunk/lib/Rewrite/Rewriter.cpp (original)
+++ cfe/trunk/lib/Rewrite/Rewriter.cpp Thu Apr  7 13:10:12 2011
@@ -26,7 +26,23 @@
   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 @@
 
   // 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 @@
 
 /// 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,
+                           bool AfterInserts) const {
   if (!isRewritable(Range.getBegin()) ||
       !isRewritable(Range.getEnd())) return -1;
 
@@ -92,7 +137,7 @@
   if (I != RewriteBuffers.end()) {
     const RewriteBuffer &RB = I->second;
     EndOff = RB.getMappedOffset(EndOff, true);
-    StartOff = RB.getMappedOffset(StartOff);
+    StartOff = RB.getMappedOffset(StartOff, AfterInserts);
   }
 
 
@@ -104,8 +149,8 @@
   return EndOff-StartOff;
 }
 
-int Rewriter::getRangeSize(SourceRange Range) const {
-  return getRangeSize(CharSourceRange::getTokenRange(Range));
+int Rewriter::getRangeSize(SourceRange Range, bool AfterInserts) const {
+  return getRangeSize(CharSourceRange::getTokenRange(Range), AfterInserts);
 }
 
 
@@ -194,12 +239,22 @@
   return false;
 }
 
+bool Rewriter::InsertTextAfterToken(SourceLocation Loc, llvm::StringRef Str) {
+  if (!isRewritable(Loc)) return true;
+  FileID FID;
+  unsigned StartOffs = getLocationOffsetAndFileID(Loc, FID);
+  StartOffs += getRangeSize(SourceRange(Loc, Loc), /*AfterInserts*/true);
+  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,
+                          bool removeLineIfEmpty) {
   if (!isRewritable(Start)) return true;
   FileID FID;
   unsigned StartOffs = getLocationOffsetAndFileID(Start, FID);
-  getEditBuffer(FID).RemoveText(StartOffs, Length);
+  getEditBuffer(FID).RemoveText(StartOffs, Length, removeLineIfEmpty);
   return false;
 }
 
@@ -216,6 +271,20 @@
   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.





More information about the cfe-commits mailing list