blob: 2c45a7cd5a0a90becac46c49ab1114db9e40e3e5 [file] [log] [blame]
//===--- Rewriter.h - Code rewriting interface ------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by Chris Lattner and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the Rewriter class, which is used for code
// transformations.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_REWRITER_H
#define LLVM_CLANG_REWRITER_H
#include "clang/Basic/SourceLocation.h"
#include <map>
#include <vector>
namespace clang {
class SourceManager;
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
/// object is mapped into the output buffer.
struct SourceDelta {
unsigned FileLoc;
int Delta;
};
/// RewriteBuffer - As code is rewritten, SourceBuffer's from the original
/// input with modifications get a new RewriteBuffer associated with them. The
/// RewriteBuffer captures the modified text itself as well as information used
/// to map between SourceLocation's in the original input and offsets in the
/// 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;
/// Buffer - This is the actual buffer itself. Note that using a vector or
/// string is a horribly inefficient way to do this, we should use a rope
/// 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.
///
/// TODO: Consider a bool to indicate whether the text is inserted 'before' or
/// 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;
std::map<unsigned, RewriteBuffer> RewriteBuffers;
public:
explicit Rewriter(SourceManager &SM) : SourceMgr(SM) {}
/// 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
#endif