From: Chris Lattner Date: Fri, 3 Oct 2008 23:31:16 +0000 (+0000) Subject: add a new Rewriter::getRewritenText method that returns the text for a range X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b5cd09a2bf1509167a2e7a46bdd0316812a93335;p=clang add a new Rewriter::getRewritenText method that returns the text for a range that includes any edits in the range. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@57037 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Rewrite/Rewriter.h b/include/clang/Rewrite/Rewriter.h index 6176cfb2dd..9a579f1263 100644 --- a/include/clang/Rewrite/Rewriter.h +++ b/include/clang/Rewrite/Rewriter.h @@ -136,6 +136,11 @@ public: /// are in the same file. If not, this returns -1. int getRangeSize(SourceRange Range) const; + /// getRewritenText - 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 + /// in different buffers, this returns an empty string. + std::string getRewritenText(SourceRange Range) const; + /// 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. diff --git a/lib/Rewrite/Rewriter.cpp b/lib/Rewrite/Rewriter.cpp index f414e1c5f2..9235a91bef 100644 --- a/lib/Rewrite/Rewriter.cpp +++ b/lib/Rewrite/Rewriter.cpp @@ -97,6 +97,55 @@ int Rewriter::getRangeSize(SourceRange Range) const { return EndOff-StartOff; } +/// getRewritenText - 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 +/// in different buffers, this returns an empty string. +/// +/// Note that this method is not particularly efficient. +/// +std::string Rewriter::getRewritenText(SourceRange Range) const { + if (!isRewritable(Range.getBegin()) || + !isRewritable(Range.getEnd())) + return ""; + + unsigned StartOff, StartFileID; + unsigned EndOff , EndFileID; + StartOff = getLocationOffsetAndFileID(Range.getBegin(), StartFileID); + EndOff = getLocationOffsetAndFileID(Range.getEnd(), EndFileID); + + if (StartFileID != EndFileID) + return ""; // Start and end in different buffers. + + // If edits have been made to this buffer, the delta between the range may + // have changed. + std::map::const_iterator I = + RewriteBuffers.find(StartFileID); + if (I == RewriteBuffers.end()) { + // If the buffer hasn't been rewritten, just return the text from the input. + const char *Ptr = SourceMgr->getCharacterData(Range.getBegin()); + + // Adjust the end offset to the end of the last token, instead of being the + // start of the last token. + EndOff += Lexer::MeasureTokenLength(Range.getEnd(), *SourceMgr); + return std::string(Ptr, Ptr+EndOff-StartOff); + } + + const RewriteBuffer &RB = I->second; + EndOff = RB.getMappedOffset(EndOff, true); + StartOff = RB.getMappedOffset(StartOff); + + // Adjust the end offset to the end of the last token, instead of being the + // start of the last token. + EndOff += Lexer::MeasureTokenLength(Range.getEnd(), *SourceMgr); + + // Advance the iterators to the right spot, yay for linear time algorithms. + RewriteBuffer::iterator Start = RB.begin(); + std::advance(Start, StartOff); + RewriteBuffer::iterator End = Start; + std::advance(End, EndOff-StartOff); + + return std::string(Start, End); +} unsigned Rewriter::getLocationOffsetAndFileID(SourceLocation Loc, unsigned &FileID) const {