zcov: / lib/Rewrite/Rewriter.cpp


Files: 1 Branches Taken: 59.1% 26 / 44
Generated: 2010-02-10 01:31 Branches Executed: 100.0% 44 / 44
Line Coverage: 91.7% 88 / 96


Programs: 1 Runs 2897


       1                 : //===--- Rewriter.cpp - Code rewriting interface --------------------------===//
       2                 : //
       3                 : //                     The LLVM Compiler Infrastructure
       4                 : //
       5                 : // This file is distributed under the University of Illinois Open Source
       6                 : // License. See LICENSE.TXT for details.
       7                 : //
       8                 : //===----------------------------------------------------------------------===//
       9                 : //
      10                 : //  This file defines the Rewriter class, which is used for code
      11                 : //  transformations.
      12                 : //
      13                 : //===----------------------------------------------------------------------===//
      14                 : 
      15                 : #include "clang/Rewrite/Rewriter.h"
      16                 : #include "clang/AST/Stmt.h"
      17                 : #include "clang/AST/Decl.h"
      18                 : #include "clang/Lex/Lexer.h"
      19                 : #include "clang/Basic/SourceManager.h"
      20                 : #include "llvm/Support/raw_ostream.h"
      21                 : using namespace clang;
      22                 : 
      23                6: void RewriteBuffer::RemoveText(unsigned OrigOffset, unsigned Size) {
      24                 :   // Nothing to remove, exit early.
                        6: branch 0 taken
                        0: branch 1 not taken
      25                6:   if (Size == 0) return;
      26                 : 
      27                6:   unsigned RealOffset = getMappedOffset(OrigOffset, true);
                        6: branch 1 taken
                        0: branch 2 not taken
      28                6:   assert(RealOffset+Size < Buffer.size() && "Invalid location");
      29                 : 
      30                 :   // Remove the dead characters.
      31                6:   Buffer.erase(RealOffset, Size);
      32                 : 
      33                 :   // Add a delta so that future changes are offset correctly.
      34                6:   AddReplaceDelta(OrigOffset, -Size);
      35                 : }
      36                 : 
      37                 : void RewriteBuffer::InsertText(unsigned OrigOffset, const llvm::StringRef &Str,
      38              649:                                bool InsertAfter) {
      39                 : 
      40                 :   // Nothing to insert, exit early.
                      649: branch 1 taken
                        0: branch 2 not taken
      41              649:   if (Str.empty()) return;
      42                 : 
      43              649:   unsigned RealOffset = getMappedOffset(OrigOffset, InsertAfter);
      44              649:   Buffer.insert(RealOffset, Str.begin(), Str.end());
      45                 : 
      46                 :   // Add a delta so that future changes are offset correctly.
      47              649:   AddInsertDelta(OrigOffset, Str.size());
      48                 : }
      49                 : 
      50                 : /// ReplaceText - This method replaces a range of characters in the input
      51                 : /// buffer with a new string.  This is effectively a combined "remove+insert"
      52                 : /// operation.
      53                 : void RewriteBuffer::ReplaceText(unsigned OrigOffset, unsigned OrigLength,
      54              530:                                 const llvm::StringRef &NewStr) {
      55              530:   unsigned RealOffset = getMappedOffset(OrigOffset, true);
      56              530:   Buffer.erase(RealOffset, OrigLength);
      57              530:   Buffer.insert(RealOffset, NewStr.begin(), NewStr.end());
                      502: branch 1 taken
                       28: branch 2 taken
      58              530:   if (OrigLength != NewStr.size())
      59              502:     AddReplaceDelta(OrigOffset, NewStr.size() - OrigLength);
      60              530: }
      61                 : 
      62                 : 
      63                 : //===----------------------------------------------------------------------===//
      64                 : // Rewriter class
      65                 : //===----------------------------------------------------------------------===//
      66                 : 
      67                 : /// getRangeSize - Return the size in bytes of the specified range if they
      68                 : /// are in the same file.  If not, this returns -1.
      69              212: int Rewriter::getRangeSize(SourceRange Range) const {
                      212: branch 2 taken
                        0: branch 3 not taken
                        0: branch 6 not taken
                      212: branch 7 taken
                        0: branch 8 not taken
                      212: branch 9 taken
      70              212:   if (!isRewritable(Range.getBegin()) ||
      71                0:       !isRewritable(Range.getEnd())) return -1;
      72                 : 
      73              212:   FileID StartFileID, EndFileID;
      74                 :   unsigned StartOff, EndOff;
      75                 : 
      76              212:   StartOff = getLocationOffsetAndFileID(Range.getBegin(), StartFileID);
      77              212:   EndOff   = getLocationOffsetAndFileID(Range.getEnd(), EndFileID);
      78                 : 
                        0: branch 1 not taken
                      212: branch 2 taken
      79              212:   if (StartFileID != EndFileID)
      80                0:     return -1;
      81                 : 
      82                 :   // If edits have been made to this buffer, the delta between the range may
      83                 :   // have changed.
      84                 :   std::map<FileID, RewriteBuffer>::const_iterator I =
      85              212:     RewriteBuffers.find(StartFileID);
                      196: branch 2 taken
                       16: branch 3 taken
      86              212:   if (I != RewriteBuffers.end()) {
      87              196:     const RewriteBuffer &RB = I->second;
      88              196:     EndOff = RB.getMappedOffset(EndOff, true);
      89              196:     StartOff = RB.getMappedOffset(StartOff);
      90                 :   }
      91                 : 
      92                 : 
      93                 :   // Adjust the end offset to the end of the last token, instead of being the
      94                 :   // start of the last token.
      95              212:   EndOff += Lexer::MeasureTokenLength(Range.getEnd(), *SourceMgr, *LangOpts);
      96                 : 
      97              212:   return EndOff-StartOff;
      98                 : }
      99                 : 
     100                 : /// getRewrittenText - Return the rewritten form of the text in the specified
     101                 : /// range.  If the start or end of the range was unrewritable or if they are
     102                 : /// in different buffers, this returns an empty string.
     103                 : ///
     104                 : /// Note that this method is not particularly efficient.
     105                 : ///
     106               30: std::string Rewriter::getRewrittenText(SourceRange Range) const {
                       30: branch 2 taken
                        0: branch 3 not taken
                        0: branch 6 not taken
                       30: branch 7 taken
                        0: branch 8 not taken
                       30: branch 9 taken
     107               30:   if (!isRewritable(Range.getBegin()) ||
     108                 :       !isRewritable(Range.getEnd()))
     109                0:     return "";
     110                 : 
     111               30:   FileID StartFileID, EndFileID;
     112                 :   unsigned StartOff, EndOff;
     113               30:   StartOff = getLocationOffsetAndFileID(Range.getBegin(), StartFileID);
     114               30:   EndOff   = getLocationOffsetAndFileID(Range.getEnd(), EndFileID);
     115                 : 
                        0: branch 1 not taken
                       30: branch 2 taken
     116               30:   if (StartFileID != EndFileID)
     117                0:     return ""; // Start and end in different buffers.
     118                 : 
     119                 :   // If edits have been made to this buffer, the delta between the range may
     120                 :   // have changed.
     121                 :   std::map<FileID, RewriteBuffer>::const_iterator I =
     122               30:     RewriteBuffers.find(StartFileID);
                        0: branch 2 not taken
                       30: branch 3 taken
     123               30:   if (I == RewriteBuffers.end()) {
     124                 :     // If the buffer hasn't been rewritten, just return the text from the input.
     125                0:     const char *Ptr = SourceMgr->getCharacterData(Range.getBegin());
     126                 : 
     127                 :     // Adjust the end offset to the end of the last token, instead of being the
     128                 :     // start of the last token.
     129                0:     EndOff += Lexer::MeasureTokenLength(Range.getEnd(), *SourceMgr, *LangOpts);
     130                0:     return std::string(Ptr, Ptr+EndOff-StartOff);
     131                 :   }
     132                 : 
     133               30:   const RewriteBuffer &RB = I->second;
     134               30:   EndOff = RB.getMappedOffset(EndOff, true);
     135               30:   StartOff = RB.getMappedOffset(StartOff);
     136                 : 
     137                 :   // Adjust the end offset to the end of the last token, instead of being the
     138                 :   // start of the last token.
     139               30:   EndOff += Lexer::MeasureTokenLength(Range.getEnd(), *SourceMgr, *LangOpts);
     140                 : 
     141                 :   // Advance the iterators to the right spot, yay for linear time algorithms.
     142               30:   RewriteBuffer::iterator Start = RB.begin();
     143               30:   std::advance(Start, StartOff);
     144               30:   RewriteBuffer::iterator End = Start;
     145               30:   std::advance(End, EndOff-StartOff);
     146                 : 
     147               30:   return std::string(Start, End);
     148                 : }
     149                 : 
     150                 : unsigned Rewriter::getLocationOffsetAndFileID(SourceLocation Loc,
     151             1499:                                               FileID &FID) const {
                     1499: branch 1 taken
                        0: branch 2 not taken
     152             1499:   assert(Loc.isValid() && "Invalid location");
     153             1499:   std::pair<FileID,unsigned> V = SourceMgr->getDecomposedLoc(Loc);
     154             1499:   FID = V.first;
     155             1499:   return V.second;
     156                 : }
     157                 : 
     158                 : 
     159                 : /// getEditBuffer - Get or create a RewriteBuffer for the specified FileID.
     160                 : ///
     161             1036: RewriteBuffer &Rewriter::getEditBuffer(FileID FID) {
     162                 :   std::map<FileID, RewriteBuffer>::iterator I =
     163             1036:     RewriteBuffers.lower_bound(FID);
                      969: branch 2 taken
                       67: branch 3 taken
                      969: branch 6 taken
                        0: branch 7 not taken
                      969: branch 8 taken
                       67: branch 9 taken
     164             1036:   if (I != RewriteBuffers.end() && I->first == FID)
     165              969:     return I->second;
     166               67:   I = RewriteBuffers.insert(I, std::make_pair(FID, RewriteBuffer()));
     167                 : 
     168               67:   std::pair<const char*, const char*> MB = SourceMgr->getBufferData(FID);
     169               67:   I->second.Initialize(MB.first, MB.second);
     170                 : 
     171               67:   return I->second;
     172                 : }
     173                 : 
     174                 : /// InsertText - Insert the specified string at the specified location in the
     175                 : /// original buffer.
     176                 : bool Rewriter::InsertText(SourceLocation Loc, const llvm::StringRef &Str,
     177              488:                           bool InsertAfter) {
                        0: branch 1 not taken
                      488: branch 2 taken
     178              488:   if (!isRewritable(Loc)) return true;
     179              488:   FileID FID;
     180              488:   unsigned StartOffs = getLocationOffsetAndFileID(Loc, FID);
     181              488:   getEditBuffer(FID).InsertText(StartOffs, Str, InsertAfter);
     182              488:   return false;
     183                 : }
     184                 : 
     185                 : /// RemoveText - Remove the specified text region.
     186                6: bool Rewriter::RemoveText(SourceLocation Start, unsigned Length) {
                        0: branch 1 not taken
                        6: branch 2 taken
     187                6:   if (!isRewritable(Start)) return true;
     188                6:   FileID FID;
     189                6:   unsigned StartOffs = getLocationOffsetAndFileID(Start, FID);
     190                6:   getEditBuffer(FID).RemoveText(StartOffs, Length);
     191                6:   return false;
     192                 : }
     193                 : 
     194                 : /// ReplaceText - This method replaces a range of characters in the input
     195                 : /// buffer with a new string.  This is effectively a combined "remove/insert"
     196                 : /// operation.
     197                 : bool Rewriter::ReplaceText(SourceLocation Start, unsigned OrigLength,
     198              521:                            const llvm::StringRef &NewStr) {
                        0: branch 1 not taken
                      521: branch 2 taken
     199              521:   if (!isRewritable(Start)) return true;
     200              521:   FileID StartFileID;
     201              521:   unsigned StartOffs = getLocationOffsetAndFileID(Start, StartFileID);
     202                 : 
     203              521:   getEditBuffer(StartFileID).ReplaceText(StartOffs, OrigLength, NewStr);
     204              521:   return false;
     205                 : }
     206                 : 
     207                 : /// ReplaceStmt - This replaces a Stmt/Expr with another, using the pretty
     208                 : /// printer to generate the replacement code.  This returns true if the input
     209                 : /// could not be rewritten, or false if successful.
     210              133: bool Rewriter::ReplaceStmt(Stmt *From, Stmt *To) {
     211                 :   // Measaure the old text.
     212              133:   int Size = getRangeSize(From->getSourceRange());
                        0: branch 0 not taken
                      133: branch 1 taken
     213              133:   if (Size == -1)
     214                0:     return true;
     215                 : 
     216                 :   // Get the new text.
     217              133:   std::string SStr;
     218              133:   llvm::raw_string_ostream S(SStr);
     219              133:   To->printPretty(S, 0, PrintingPolicy(*LangOpts));
     220              133:   const std::string &Str = S.str();
     221                 : 
     222              133:   ReplaceText(From->getLocStart(), Size, Str);
     223              133:   return false;
     224                 : }
     225                 : 
     226                 : 

Generated: 2010-02-10 01:31 by zcov