EditedSource.cpp revision 30660a898545416f0fea2d717f16f75640001e38
130660a898545416f0fea2d717f16f75640001e38Ted Kremenek//===----- EditedSource.cpp - Collection of source edits ------------------===// 230660a898545416f0fea2d717f16f75640001e38Ted Kremenek// 330660a898545416f0fea2d717f16f75640001e38Ted Kremenek// The LLVM Compiler Infrastructure 430660a898545416f0fea2d717f16f75640001e38Ted Kremenek// 530660a898545416f0fea2d717f16f75640001e38Ted Kremenek// This file is distributed under the University of Illinois Open Source 630660a898545416f0fea2d717f16f75640001e38Ted Kremenek// License. See LICENSE.TXT for details. 730660a898545416f0fea2d717f16f75640001e38Ted Kremenek// 830660a898545416f0fea2d717f16f75640001e38Ted Kremenek//===----------------------------------------------------------------------===// 930660a898545416f0fea2d717f16f75640001e38Ted Kremenek 1030660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Edit/EditedSource.h" 1130660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Edit/Commit.h" 1230660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Edit/EditsReceiver.h" 1330660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Lex/Lexer.h" 1430660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Basic/SourceManager.h" 1530660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "llvm/ADT/SmallString.h" 1630660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "llvm/ADT/Twine.h" 1730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 1830660a898545416f0fea2d717f16f75640001e38Ted Kremenekusing namespace clang; 1930660a898545416f0fea2d717f16f75640001e38Ted Kremenekusing namespace edit; 2030660a898545416f0fea2d717f16f75640001e38Ted Kremenek 2130660a898545416f0fea2d717f16f75640001e38Ted Kremenekvoid EditsReceiver::remove(CharSourceRange range) { 2230660a898545416f0fea2d717f16f75640001e38Ted Kremenek replace(range, StringRef()); 2330660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 2430660a898545416f0fea2d717f16f75640001e38Ted Kremenek 2530660a898545416f0fea2d717f16f75640001e38Ted KremenekStringRef EditedSource::copyString(const Twine &twine) { 2630660a898545416f0fea2d717f16f75640001e38Ted Kremenek llvm::SmallString<128> Data; 2730660a898545416f0fea2d717f16f75640001e38Ted Kremenek return copyString(twine.toStringRef(Data)); 2830660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 2930660a898545416f0fea2d717f16f75640001e38Ted Kremenek 3030660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool EditedSource::canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs) { 3130660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEditsTy::iterator FA = getActionForOffset(Offs); 3230660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (FA != FileEdits.end()) { 3330660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (FA->first != Offs) 3430660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; // position has been removed. 3530660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 3630660a898545416f0fea2d717f16f75640001e38Ted Kremenek 3730660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (SourceMgr.isMacroArgExpansion(OrigLoc)) { 3830660a898545416f0fea2d717f16f75640001e38Ted Kremenek SourceLocation 3930660a898545416f0fea2d717f16f75640001e38Ted Kremenek DefArgLoc = SourceMgr.getImmediateExpansionRange(OrigLoc).first; 4030660a898545416f0fea2d717f16f75640001e38Ted Kremenek SourceLocation 4130660a898545416f0fea2d717f16f75640001e38Ted Kremenek ExpLoc = SourceMgr.getImmediateExpansionRange(DefArgLoc).first; 4230660a898545416f0fea2d717f16f75640001e38Ted Kremenek llvm::DenseMap<unsigned, SourceLocation>::iterator 4330660a898545416f0fea2d717f16f75640001e38Ted Kremenek I = ExpansionToArgMap.find(ExpLoc.getRawEncoding()); 4430660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (I != ExpansionToArgMap.end() && I->second != DefArgLoc) 4530660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; // Trying to write in a macro argument input that has 4630660a898545416f0fea2d717f16f75640001e38Ted Kremenek // already been written for another argument of the same macro. 4730660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 4830660a898545416f0fea2d717f16f75640001e38Ted Kremenek 4930660a898545416f0fea2d717f16f75640001e38Ted Kremenek return true; 5030660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 5130660a898545416f0fea2d717f16f75640001e38Ted Kremenek 5230660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool EditedSource::commitInsert(SourceLocation OrigLoc, 5330660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset Offs, StringRef text, 5430660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool beforePreviousInsertions) { 5530660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (!canInsertInOffset(OrigLoc, Offs)) 5630660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 5730660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (text.empty()) 5830660a898545416f0fea2d717f16f75640001e38Ted Kremenek return true; 5930660a898545416f0fea2d717f16f75640001e38Ted Kremenek 6030660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (SourceMgr.isMacroArgExpansion(OrigLoc)) { 6130660a898545416f0fea2d717f16f75640001e38Ted Kremenek SourceLocation 6230660a898545416f0fea2d717f16f75640001e38Ted Kremenek DefArgLoc = SourceMgr.getImmediateExpansionRange(OrigLoc).first; 6330660a898545416f0fea2d717f16f75640001e38Ted Kremenek SourceLocation 6430660a898545416f0fea2d717f16f75640001e38Ted Kremenek ExpLoc = SourceMgr.getImmediateExpansionRange(DefArgLoc).first; 6530660a898545416f0fea2d717f16f75640001e38Ted Kremenek ExpansionToArgMap[ExpLoc.getRawEncoding()] = DefArgLoc; 6630660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 6730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 6830660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEdit &FA = FileEdits[Offs]; 6930660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (FA.Text.empty()) { 7030660a898545416f0fea2d717f16f75640001e38Ted Kremenek FA.Text = copyString(text); 7130660a898545416f0fea2d717f16f75640001e38Ted Kremenek return true; 7230660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 7330660a898545416f0fea2d717f16f75640001e38Ted Kremenek 7430660a898545416f0fea2d717f16f75640001e38Ted Kremenek Twine concat; 7530660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (beforePreviousInsertions) 7630660a898545416f0fea2d717f16f75640001e38Ted Kremenek concat = Twine(text) + FA.Text; 7730660a898545416f0fea2d717f16f75640001e38Ted Kremenek else 7830660a898545416f0fea2d717f16f75640001e38Ted Kremenek concat = Twine(FA.Text) + text; 7930660a898545416f0fea2d717f16f75640001e38Ted Kremenek 8030660a898545416f0fea2d717f16f75640001e38Ted Kremenek FA.Text = copyString(concat); 8130660a898545416f0fea2d717f16f75640001e38Ted Kremenek return true; 8230660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 8330660a898545416f0fea2d717f16f75640001e38Ted Kremenek 8430660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool EditedSource::commitInsertFromRange(SourceLocation OrigLoc, 8530660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset Offs, 8630660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset InsertFromRangeOffs, unsigned Len, 8730660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool beforePreviousInsertions) { 8830660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (Len == 0) 8930660a898545416f0fea2d717f16f75640001e38Ted Kremenek return true; 9030660a898545416f0fea2d717f16f75640001e38Ted Kremenek 9130660a898545416f0fea2d717f16f75640001e38Ted Kremenek llvm::SmallString<128> StrVec; 9230660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset BeginOffs = InsertFromRangeOffs; 9330660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset EndOffs = BeginOffs.getWithOffset(Len); 9430660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEditsTy::iterator I = FileEdits.upper_bound(BeginOffs); 9530660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (I != FileEdits.begin()) 9630660a898545416f0fea2d717f16f75640001e38Ted Kremenek --I; 9730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 9830660a898545416f0fea2d717f16f75640001e38Ted Kremenek for (; I != FileEdits.end(); ++I) { 9930660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEdit &FA = I->second; 10030660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset B = I->first; 10130660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset E = B.getWithOffset(FA.RemoveLen); 10230660a898545416f0fea2d717f16f75640001e38Ted Kremenek 10330660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (BeginOffs < E) { 10430660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (BeginOffs >= B) { 10530660a898545416f0fea2d717f16f75640001e38Ted Kremenek BeginOffs = E; 10630660a898545416f0fea2d717f16f75640001e38Ted Kremenek ++I; 10730660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 10830660a898545416f0fea2d717f16f75640001e38Ted Kremenek break; 10930660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 11030660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 11130660a898545416f0fea2d717f16f75640001e38Ted Kremenek 11230660a898545416f0fea2d717f16f75640001e38Ted Kremenek for (; I != FileEdits.end() && EndOffs > I->first; ++I) { 11330660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEdit &FA = I->second; 11430660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset B = I->first; 11530660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset E = B.getWithOffset(FA.RemoveLen); 11630660a898545416f0fea2d717f16f75640001e38Ted Kremenek 11730660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (BeginOffs < B) { 11830660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool Invalid = false; 11930660a898545416f0fea2d717f16f75640001e38Ted Kremenek StringRef text = getSourceText(BeginOffs, B, Invalid); 12030660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (Invalid) 12130660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 12230660a898545416f0fea2d717f16f75640001e38Ted Kremenek StrVec += text; 12330660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 12430660a898545416f0fea2d717f16f75640001e38Ted Kremenek StrVec += FA.Text; 12530660a898545416f0fea2d717f16f75640001e38Ted Kremenek BeginOffs = E; 12630660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 12730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 12830660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (BeginOffs < EndOffs) { 12930660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool Invalid = false; 13030660a898545416f0fea2d717f16f75640001e38Ted Kremenek StringRef text = getSourceText(BeginOffs, EndOffs, Invalid); 13130660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (Invalid) 13230660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 13330660a898545416f0fea2d717f16f75640001e38Ted Kremenek StrVec += text; 13430660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 13530660a898545416f0fea2d717f16f75640001e38Ted Kremenek 13630660a898545416f0fea2d717f16f75640001e38Ted Kremenek return commitInsert(OrigLoc, Offs, StrVec.str(), beforePreviousInsertions); 13730660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 13830660a898545416f0fea2d717f16f75640001e38Ted Kremenek 13930660a898545416f0fea2d717f16f75640001e38Ted Kremenekvoid EditedSource::commitRemove(SourceLocation OrigLoc, 14030660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset BeginOffs, unsigned Len) { 14130660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (Len == 0) 14230660a898545416f0fea2d717f16f75640001e38Ted Kremenek return; 14330660a898545416f0fea2d717f16f75640001e38Ted Kremenek 14430660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset EndOffs = BeginOffs.getWithOffset(Len); 14530660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEditsTy::iterator I = FileEdits.upper_bound(BeginOffs); 14630660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (I != FileEdits.begin()) 14730660a898545416f0fea2d717f16f75640001e38Ted Kremenek --I; 14830660a898545416f0fea2d717f16f75640001e38Ted Kremenek 14930660a898545416f0fea2d717f16f75640001e38Ted Kremenek for (; I != FileEdits.end(); ++I) { 15030660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEdit &FA = I->second; 15130660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset B = I->first; 15230660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset E = B.getWithOffset(FA.RemoveLen); 15330660a898545416f0fea2d717f16f75640001e38Ted Kremenek 15430660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (BeginOffs < E) 15530660a898545416f0fea2d717f16f75640001e38Ted Kremenek break; 15630660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 15730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 15830660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset TopBegin, TopEnd; 15930660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEdit *TopFA = 0; 16030660a898545416f0fea2d717f16f75640001e38Ted Kremenek 16130660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (I == FileEdits.end()) { 16230660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEditsTy::iterator 16330660a898545416f0fea2d717f16f75640001e38Ted Kremenek NewI = FileEdits.insert(I, std::make_pair(BeginOffs, FileEdit())); 16430660a898545416f0fea2d717f16f75640001e38Ted Kremenek NewI->second.RemoveLen = Len; 16530660a898545416f0fea2d717f16f75640001e38Ted Kremenek return; 16630660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 16730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 16830660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEdit &FA = I->second; 16930660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset B = I->first; 17030660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset E = B.getWithOffset(FA.RemoveLen); 17130660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (BeginOffs < B) { 17230660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEditsTy::iterator 17330660a898545416f0fea2d717f16f75640001e38Ted Kremenek NewI = FileEdits.insert(I, std::make_pair(BeginOffs, FileEdit())); 17430660a898545416f0fea2d717f16f75640001e38Ted Kremenek TopBegin = BeginOffs; 17530660a898545416f0fea2d717f16f75640001e38Ted Kremenek TopEnd = EndOffs; 17630660a898545416f0fea2d717f16f75640001e38Ted Kremenek TopFA = &NewI->second; 17730660a898545416f0fea2d717f16f75640001e38Ted Kremenek TopFA->RemoveLen = Len; 17830660a898545416f0fea2d717f16f75640001e38Ted Kremenek } else { 17930660a898545416f0fea2d717f16f75640001e38Ted Kremenek TopBegin = B; 18030660a898545416f0fea2d717f16f75640001e38Ted Kremenek TopEnd = E; 18130660a898545416f0fea2d717f16f75640001e38Ted Kremenek TopFA = &I->second; 18230660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (TopEnd >= EndOffs) 18330660a898545416f0fea2d717f16f75640001e38Ted Kremenek return; 18430660a898545416f0fea2d717f16f75640001e38Ted Kremenek unsigned diff = EndOffs.getOffset() - TopEnd.getOffset(); 18530660a898545416f0fea2d717f16f75640001e38Ted Kremenek TopEnd = EndOffs; 18630660a898545416f0fea2d717f16f75640001e38Ted Kremenek TopFA->RemoveLen += diff; 18730660a898545416f0fea2d717f16f75640001e38Ted Kremenek ++I; 18830660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 18930660a898545416f0fea2d717f16f75640001e38Ted Kremenek 19030660a898545416f0fea2d717f16f75640001e38Ted Kremenek while (I != FileEdits.end()) { 19130660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEdit &FA = I->second; 19230660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset B = I->first; 19330660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset E = B.getWithOffset(FA.RemoveLen); 19430660a898545416f0fea2d717f16f75640001e38Ted Kremenek 19530660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (B >= TopEnd) 19630660a898545416f0fea2d717f16f75640001e38Ted Kremenek break; 19730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 19830660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (E <= TopEnd) { 19930660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEdits.erase(I++); 20030660a898545416f0fea2d717f16f75640001e38Ted Kremenek continue; 20130660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 20230660a898545416f0fea2d717f16f75640001e38Ted Kremenek 20330660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (B < TopEnd) { 20430660a898545416f0fea2d717f16f75640001e38Ted Kremenek unsigned diff = E.getOffset() - TopEnd.getOffset(); 20530660a898545416f0fea2d717f16f75640001e38Ted Kremenek TopEnd = E; 20630660a898545416f0fea2d717f16f75640001e38Ted Kremenek TopFA->RemoveLen += diff; 20730660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEdits.erase(I); 20830660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 20930660a898545416f0fea2d717f16f75640001e38Ted Kremenek 21030660a898545416f0fea2d717f16f75640001e38Ted Kremenek break; 21130660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 21230660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 21330660a898545416f0fea2d717f16f75640001e38Ted Kremenek 21430660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool EditedSource::commit(const Commit &commit) { 21530660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (!commit.isCommitable()) 21630660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 21730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 21830660a898545416f0fea2d717f16f75640001e38Ted Kremenek for (edit::Commit::edit_iterator 21930660a898545416f0fea2d717f16f75640001e38Ted Kremenek I = commit.edit_begin(), E = commit.edit_end(); I != E; ++I) { 22030660a898545416f0fea2d717f16f75640001e38Ted Kremenek const edit::Commit::Edit &edit = *I; 22130660a898545416f0fea2d717f16f75640001e38Ted Kremenek switch (edit.Kind) { 22230660a898545416f0fea2d717f16f75640001e38Ted Kremenek case edit::Commit::Act_Insert: 22330660a898545416f0fea2d717f16f75640001e38Ted Kremenek commitInsert(edit.OrigLoc, edit.Offset, edit.Text, edit.BeforePrev); 22430660a898545416f0fea2d717f16f75640001e38Ted Kremenek break; 22530660a898545416f0fea2d717f16f75640001e38Ted Kremenek case edit::Commit::Act_InsertFromRange: 22630660a898545416f0fea2d717f16f75640001e38Ted Kremenek commitInsertFromRange(edit.OrigLoc, edit.Offset, 22730660a898545416f0fea2d717f16f75640001e38Ted Kremenek edit.InsertFromRangeOffs, edit.Length, 22830660a898545416f0fea2d717f16f75640001e38Ted Kremenek edit.BeforePrev); 22930660a898545416f0fea2d717f16f75640001e38Ted Kremenek break; 23030660a898545416f0fea2d717f16f75640001e38Ted Kremenek case edit::Commit::Act_Remove: 23130660a898545416f0fea2d717f16f75640001e38Ted Kremenek commitRemove(edit.OrigLoc, edit.Offset, edit.Length); 23230660a898545416f0fea2d717f16f75640001e38Ted Kremenek break; 23330660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 23430660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 23530660a898545416f0fea2d717f16f75640001e38Ted Kremenek 23630660a898545416f0fea2d717f16f75640001e38Ted Kremenek return true; 23730660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 23830660a898545416f0fea2d717f16f75640001e38Ted Kremenek 23930660a898545416f0fea2d717f16f75640001e38Ted Kremenekstatic void applyRewrite(EditsReceiver &receiver, 24030660a898545416f0fea2d717f16f75640001e38Ted Kremenek StringRef text, FileOffset offs, unsigned len, 24130660a898545416f0fea2d717f16f75640001e38Ted Kremenek const SourceManager &SM) { 24230660a898545416f0fea2d717f16f75640001e38Ted Kremenek assert(!offs.getFID().isInvalid()); 24330660a898545416f0fea2d717f16f75640001e38Ted Kremenek SourceLocation Loc = SM.getLocForStartOfFile(offs.getFID()); 24430660a898545416f0fea2d717f16f75640001e38Ted Kremenek Loc = Loc.getLocWithOffset(offs.getOffset()); 24530660a898545416f0fea2d717f16f75640001e38Ted Kremenek assert(Loc.isFileID()); 24630660a898545416f0fea2d717f16f75640001e38Ted Kremenek CharSourceRange range = CharSourceRange::getCharRange(Loc, 24730660a898545416f0fea2d717f16f75640001e38Ted Kremenek Loc.getLocWithOffset(len)); 24830660a898545416f0fea2d717f16f75640001e38Ted Kremenek 24930660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (text.empty()) { 25030660a898545416f0fea2d717f16f75640001e38Ted Kremenek assert(len); 25130660a898545416f0fea2d717f16f75640001e38Ted Kremenek receiver.remove(range); 25230660a898545416f0fea2d717f16f75640001e38Ted Kremenek return; 25330660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 25430660a898545416f0fea2d717f16f75640001e38Ted Kremenek 25530660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (len) 25630660a898545416f0fea2d717f16f75640001e38Ted Kremenek receiver.replace(range, text); 25730660a898545416f0fea2d717f16f75640001e38Ted Kremenek else 25830660a898545416f0fea2d717f16f75640001e38Ted Kremenek receiver.insert(Loc, text); 25930660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 26030660a898545416f0fea2d717f16f75640001e38Ted Kremenek 26130660a898545416f0fea2d717f16f75640001e38Ted Kremenekvoid EditedSource::applyRewrites(EditsReceiver &receiver) { 26230660a898545416f0fea2d717f16f75640001e38Ted Kremenek llvm::SmallString<128> StrVec; 26330660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset CurOffs, CurEnd; 26430660a898545416f0fea2d717f16f75640001e38Ted Kremenek unsigned CurLen; 26530660a898545416f0fea2d717f16f75640001e38Ted Kremenek 26630660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (FileEdits.empty()) 26730660a898545416f0fea2d717f16f75640001e38Ted Kremenek return; 26830660a898545416f0fea2d717f16f75640001e38Ted Kremenek 26930660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEditsTy::iterator I = FileEdits.begin(); 27030660a898545416f0fea2d717f16f75640001e38Ted Kremenek CurOffs = I->first; 27130660a898545416f0fea2d717f16f75640001e38Ted Kremenek StrVec = I->second.Text; 27230660a898545416f0fea2d717f16f75640001e38Ted Kremenek CurLen = I->second.RemoveLen; 27330660a898545416f0fea2d717f16f75640001e38Ted Kremenek CurEnd = CurOffs.getWithOffset(CurLen); 27430660a898545416f0fea2d717f16f75640001e38Ted Kremenek ++I; 27530660a898545416f0fea2d717f16f75640001e38Ted Kremenek 27630660a898545416f0fea2d717f16f75640001e38Ted Kremenek for (FileEditsTy::iterator E = FileEdits.end(); I != E; ++I) { 27730660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset offs = I->first; 27830660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEdit act = I->second; 27930660a898545416f0fea2d717f16f75640001e38Ted Kremenek assert(offs >= CurEnd); 28030660a898545416f0fea2d717f16f75640001e38Ted Kremenek 28130660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (offs == CurEnd) { 28230660a898545416f0fea2d717f16f75640001e38Ted Kremenek StrVec += act.Text; 28330660a898545416f0fea2d717f16f75640001e38Ted Kremenek CurLen += act.RemoveLen; 28430660a898545416f0fea2d717f16f75640001e38Ted Kremenek CurEnd.getWithOffset(act.RemoveLen); 28530660a898545416f0fea2d717f16f75640001e38Ted Kremenek continue; 28630660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 28730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 28830660a898545416f0fea2d717f16f75640001e38Ted Kremenek applyRewrite(receiver, StrVec.str(), CurOffs, CurLen, SourceMgr); 28930660a898545416f0fea2d717f16f75640001e38Ted Kremenek CurOffs = offs; 29030660a898545416f0fea2d717f16f75640001e38Ted Kremenek StrVec = act.Text; 29130660a898545416f0fea2d717f16f75640001e38Ted Kremenek CurLen = act.RemoveLen; 29230660a898545416f0fea2d717f16f75640001e38Ted Kremenek CurEnd = CurOffs.getWithOffset(CurLen); 29330660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 29430660a898545416f0fea2d717f16f75640001e38Ted Kremenek 29530660a898545416f0fea2d717f16f75640001e38Ted Kremenek applyRewrite(receiver, StrVec.str(), CurOffs, CurLen, SourceMgr); 29630660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 29730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 29830660a898545416f0fea2d717f16f75640001e38Ted Kremenekvoid EditedSource::clearRewrites() { 29930660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEdits.clear(); 30030660a898545416f0fea2d717f16f75640001e38Ted Kremenek StrAlloc.Reset(); 30130660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 30230660a898545416f0fea2d717f16f75640001e38Ted Kremenek 30330660a898545416f0fea2d717f16f75640001e38Ted KremenekStringRef EditedSource::getSourceText(FileOffset BeginOffs, FileOffset EndOffs, 30430660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool &Invalid) { 30530660a898545416f0fea2d717f16f75640001e38Ted Kremenek assert(BeginOffs.getFID() == EndOffs.getFID()); 30630660a898545416f0fea2d717f16f75640001e38Ted Kremenek assert(BeginOffs <= EndOffs); 30730660a898545416f0fea2d717f16f75640001e38Ted Kremenek SourceLocation BLoc = SourceMgr.getLocForStartOfFile(BeginOffs.getFID()); 30830660a898545416f0fea2d717f16f75640001e38Ted Kremenek BLoc = BLoc.getLocWithOffset(BeginOffs.getOffset()); 30930660a898545416f0fea2d717f16f75640001e38Ted Kremenek assert(BLoc.isFileID()); 31030660a898545416f0fea2d717f16f75640001e38Ted Kremenek SourceLocation 31130660a898545416f0fea2d717f16f75640001e38Ted Kremenek ELoc = BLoc.getLocWithOffset(EndOffs.getOffset() - BeginOffs.getOffset()); 31230660a898545416f0fea2d717f16f75640001e38Ted Kremenek return Lexer::getSourceText(CharSourceRange::getCharRange(BLoc, ELoc), 31330660a898545416f0fea2d717f16f75640001e38Ted Kremenek SourceMgr, LangOpts, &Invalid); 31430660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 31530660a898545416f0fea2d717f16f75640001e38Ted Kremenek 31630660a898545416f0fea2d717f16f75640001e38Ted KremenekEditedSource::FileEditsTy::iterator 31730660a898545416f0fea2d717f16f75640001e38Ted KremenekEditedSource::getActionForOffset(FileOffset Offs) { 31830660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEditsTy::iterator I = FileEdits.upper_bound(Offs); 31930660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (I == FileEdits.begin()) 32030660a898545416f0fea2d717f16f75640001e38Ted Kremenek return FileEdits.end(); 32130660a898545416f0fea2d717f16f75640001e38Ted Kremenek --I; 32230660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEdit &FA = I->second; 32330660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset B = I->first; 32430660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset E = B.getWithOffset(FA.RemoveLen); 32530660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (Offs >= B && Offs < E) 32630660a898545416f0fea2d717f16f75640001e38Ted Kremenek return I; 32730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 32830660a898545416f0fea2d717f16f75640001e38Ted Kremenek return FileEdits.end(); 32930660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 330