[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