[cfe-commits] r42868 - in /cfe/trunk: Basic/SourceManager.cpp Driver/RewriteTest.cpp Rewrite/Rewriter.cpp include/clang/Basic/SourceManager.h include/clang/Rewrite/Rewriter.h

Chris Lattner sabre at nondot.org
Thu Oct 11 11:38:33 PDT 2007


Author: lattner
Date: Thu Oct 11 13:38:32 2007
New Revision: 42868

URL: http://llvm.org/viewvc/llvm-project?rev=42868&view=rev
Log:
Push the rewriting APIs along.  Build a trivial client that replaces tabs
with x's for now.  The APIs are all unimplemented, so it doesn't do 
anything yet! :)

Modified:
    cfe/trunk/Basic/SourceManager.cpp
    cfe/trunk/Driver/RewriteTest.cpp
    cfe/trunk/Rewrite/Rewriter.cpp
    cfe/trunk/include/clang/Basic/SourceManager.h
    cfe/trunk/include/clang/Rewrite/Rewriter.h

Modified: cfe/trunk/Basic/SourceManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Basic/SourceManager.cpp?rev=42868&r1=42867&r2=42868&view=diff

==============================================================================
--- cfe/trunk/Basic/SourceManager.cpp (original)
+++ cfe/trunk/Basic/SourceManager.cpp Thu Oct 11 13:38:32 2007
@@ -209,6 +209,13 @@
   return SourceLocation::getMacroLoc(MacroIDs.size()-1, 0, 0);
 }
 
+/// getBufferData - Return a pointer to the start and end of the character
+/// data for the specified FileID.
+std::pair<const char*, const char*> 
+SourceManager::getBufferData(unsigned FileID) const {
+  const llvm::MemoryBuffer *Buf = getBuffer(FileID);
+  return std::make_pair(Buf->getBufferStart(), Buf->getBufferEnd());
+}
 
 
 /// getCharacterData - Return a pointer to the start of the specified location

Modified: cfe/trunk/Driver/RewriteTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/RewriteTest.cpp?rev=42868&r1=42867&r2=42868&view=diff

==============================================================================
--- cfe/trunk/Driver/RewriteTest.cpp (original)
+++ cfe/trunk/Driver/RewriteTest.cpp Thu Oct 11 13:38:32 2007
@@ -12,32 +12,82 @@
 //===----------------------------------------------------------------------===//
 
 #include "ASTConsumers.h"
+#include "clang/Rewrite/Rewriter.h"
 #include "clang/AST/AST.h"
 #include "clang/AST/ASTConsumer.h"
-
+#include "clang/Basic/SourceManager.h"
 using namespace clang;
 
 
 namespace {
-  class ASTViewer : public ASTConsumer {
+  class RewriteTest : public ASTConsumer {
     SourceManager *SM;
+    unsigned MainFileID;
   public:
-    void Initialize(ASTContext &Context, unsigned MainFileID) {
+    void Initialize(ASTContext &Context, unsigned mainFileID) {
       SM = &Context.SourceMgr;
+      MainFileID = mainFileID;
     }
     
     virtual void HandleTopLevelDecl(Decl *D);
+
+    
+    ~RewriteTest();
   };
 }
 
-ASTConsumer *clang::CreateCodeRewriterTest() { return new ASTViewer(); }
-
+ASTConsumer *clang::CreateCodeRewriterTest() { return new RewriteTest(); }
 
-
-
-void ASTViewer::HandleTopLevelDecl(Decl *D) {
+void RewriteTest::HandleTopLevelDecl(Decl *D) {
+  // Nothing to do here yet.
+#if 0
   if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
     if (ND->getName())
       printf("%s\n", ND->getName());
+#endif
+}
+
+
+
+RewriteTest::~RewriteTest() {
+  Rewriter Rewrite(*SM);
+  
+  // Get the top-level buffer that this corresponds to.
+  std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
+  const char *MainBufStart = MainBuf.first;
+  const char *MainBufEnd = MainBuf.second;
+  
+  // Loop over the whole file, looking for tabs.
+  for (const char *BufPtr = MainBufStart; BufPtr != MainBufEnd; ++BufPtr) {
+    if (*BufPtr != '\t')
+      continue;
+    
+    // Okay, we found a tab.  This tab will turn into at least one character,
+    // but it depends on which 'virtual column' it is in.  Compute that now.
+    unsigned VCol = 0;
+    while (BufPtr-VCol != MainBufStart && BufPtr[-VCol-1] != '\t' &&
+           BufPtr[-VCol-1] != '\n' && BufPtr[-VCol-1] != '\r')
+      ++VCol;
+    
+    // Okay, now that we know the virtual column, we know how many spaces to
+    // insert.  We assume 8-character tab-stops.
+    unsigned Spaces = 8-(VCol & 7);
+    
+    // Get the location of the tab.
+    SourceLocation TabLoc =
+      SourceLocation::getFileLoc(MainFileID, BufPtr-MainBufStart);
+    
+    // Rewrite the single tab character into a sequence of spaces.
+    Rewrite.ReplaceText(TabLoc, 1, "xxxxxxxxxxx", Spaces);
+  }
   
+  // Get the buffer corresponding to MainFileID.  If we haven't changed it, then
+  // we are done.
+  if (const RewriteBuffer *RewriteBuf = 
+          Rewrite.getRewriteBufferFor(MainFileID)) {
+    RewriteBuf = 0;
+    printf("Changed\n");
+  } else {
+    printf("No changes\n");
+  }
 }

Modified: cfe/trunk/Rewrite/Rewriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Rewrite/Rewriter.cpp?rev=42868&r1=42867&r2=42868&view=diff

==============================================================================
--- cfe/trunk/Rewrite/Rewriter.cpp (original)
+++ cfe/trunk/Rewrite/Rewriter.cpp Thu Oct 11 13:38:32 2007
@@ -13,6 +13,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/Rewrite/Rewriter.h"
+#include "clang/Basic/SourceManager.h"
 using namespace clang;
 
 
@@ -24,3 +25,31 @@
                                const char *StrData, unsigned StrLen) {
   // FIXME:
 }
+
+
+
+//===----------------------------------------------------------------------===//
+// Rewriter class
+//===----------------------------------------------------------------------===//
+
+/// getEditBuffer - Get or create a RewriteBuffer for the specified FileID.
+///
+RewriteBuffer &Rewriter::getEditBuffer(unsigned FileID) {
+  std::map<unsigned, RewriteBuffer>::iterator I =
+    RewriteBuffers.lower_bound(FileID);
+  if (I != RewriteBuffers.end() && I->first == FileID) 
+    return I->second;
+  I = RewriteBuffers.insert(I, std::make_pair(FileID, RewriteBuffer()));
+  
+  std::pair<const char*, const char*> MB = SourceMgr.getBufferData(FileID);
+  I->second.Initialize(MB.first, MB.second);
+  
+  return I->second;
+}
+
+
+void Rewriter::ReplaceText(SourceLocation Start, unsigned OrigLength,
+                           const char *NewStr, unsigned NewLength) {
+  assert(isRewritable(Start) && "Not a rewritable location!");
+  
+}

Modified: cfe/trunk/include/clang/Basic/SourceManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/SourceManager.h?rev=42868&r1=42867&r2=42868&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/SourceManager.h (original)
+++ cfe/trunk/include/clang/Basic/SourceManager.h Thu Oct 11 13:38:32 2007
@@ -198,6 +198,10 @@
     return getFileInfo(FileID)->Buffer;
   }
   
+  /// getBufferData - Return a pointer to the start and end of the character
+  /// data for the specified FileID.
+  std::pair<const char*, const char*> getBufferData(unsigned FileID) const;
+  
   /// getIncludeLoc - Return the location of the #include for the specified
   /// SourceLocation.  If this is a macro expansion, this transparently figures
   /// out which file includes the file being expanded into.

Modified: cfe/trunk/include/clang/Rewrite/Rewriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Rewrite/Rewriter.h?rev=42868&r1=42867&r2=42868&view=diff

==============================================================================
--- cfe/trunk/include/clang/Rewrite/Rewriter.h (original)
+++ cfe/trunk/include/clang/Rewrite/Rewriter.h Thu Oct 11 13:38:32 2007
@@ -15,11 +15,13 @@
 #ifndef LLVM_CLANG_REWRITER_H
 #define LLVM_CLANG_REWRITER_H
 
+#include "clang/Basic/SourceLocation.h"
+#include <map>
 #include <vector>
 
 namespace clang {
   class SourceManager;
-  class SourceLocation;
+  class Rewriter;
   
 /// SourceDelta - As code in the original input buffer is added and deleted,
 /// SourceDelta records are used to keep track of how the input SourceLocation
@@ -37,6 +39,7 @@
 /// RewriteBuffer.  For example, if text is inserted into the buffer, any
 /// locations after the insertion point have to be mapped.
 class RewriteBuffer {
+  friend class Rewriter;
   /// Deltas - Keep track of all the deltas in the source code due to insertions
   /// and deletions.  These are kept in sorted order based on the FileLoc.
   std::vector<SourceDelta> Deltas;
@@ -46,11 +49,20 @@
   /// instead.
   std::vector<char> Buffer;
 public:
+
+  
+  
+private:  // Methods only usable by Rewriter.
+  
+  /// Initialize - Start this rewrite buffer out with a copy of the unmodified
+  /// input buffer.
+  void Initialize(const char *BufStart, const char *BufEnd) {
+    Buffer.assign(BufStart, BufEnd);
+  }
   
   /// RemoveText - Remove the specified text.
   void RemoveText(unsigned OrigOffset, unsigned Size);
   
-  
   /// InsertText - Insert some text at the specified point, where the offset in
   /// the buffer is specified relative to the original SourceBuffer.
   ///
@@ -58,29 +70,50 @@
   /// after the atomic point: i.e. whether the atomic point is moved to after
   /// the inserted text or not.
   void InsertText(unsigned OrigOffset, const char *StrData, unsigned StrLen);
-  
 };
   
+
+/// Rewriter - This is the main interface to the rewrite buffers.  Its primary
+/// job is to dispatch high-level requests to the low-level RewriteBuffers that
+/// are involved.
 class Rewriter {
   SourceManager &SourceMgr;
   
-  // FIXME: list of buffers.
+  std::map<unsigned, RewriteBuffer> RewriteBuffers;
 public:
   explicit Rewriter(SourceManager &SM) : SourceMgr(SM) {}
   
-  /// InsertText - Insert the specified string at the specified location in the
-  /// original buffer.
-  bool InsertText(SourceLocation Loc, const char *StrData, unsigned StrLen);
-  
-  /// RemoveText - Remove the specified text region.
-  bool RemoveText(SourceLocation Start, SourceLocation End);
-  
-  
-  // TODO: Replace Stmt/Expr with another.
-  
-  
-  // Write out output buffer.
+  /// isRewritable - Return true if this location is a raw file location, which
+  /// is rewritable.  Locations from macros, etc are not rewritable.
+  static bool isRewritable(SourceLocation Loc) {
+    return Loc.isFileID();
+  }
   
+  /// InsertText - Insert the specified string at the specified location in the
+  /// original buffer.  This method is only valid on rewritable source
+  /// locations.
+  void InsertText(SourceLocation Loc, const char *StrData, unsigned StrLen);
+  
+  /// RemoveText - Remove the specified text region.  This method is only valid
+  /// on rewritable source locations.
+  void RemoveText(SourceLocation Start, SourceLocation End);
+  
+  
+  void ReplaceText(SourceLocation Start, unsigned OrigLength,
+                   const char *NewStr, unsigned NewLength);
+  
+  // TODO: Replace Stmt/Expr with another.  Return bool to indicate whether the
+  // locations were rewritable.
+  
+  /// getRewriteBufferFor - Return the rewrite buffer for the specified FileID.
+  /// If no modification has been made to it, return null.
+  const RewriteBuffer *getRewriteBufferFor(unsigned FileID) const {
+    std::map<unsigned, RewriteBuffer>::const_iterator I =
+      RewriteBuffers.find(FileID);
+    return I == RewriteBuffers.end() ? 0 : &I->second;
+  }
+private:
+  RewriteBuffer &getEditBuffer(unsigned FileID);
 };
   
 } // end namespace clang





More information about the cfe-commits mailing list