EditedSource.cpp revision 55fc873017f10f6f566b182b70f6fc22aefa3464
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" 1155fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Basic/SourceManager.h" 1230660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Edit/Commit.h" 1330660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Edit/EditsReceiver.h" 1430660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Lex/Lexer.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 103055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis if (BeginOffs == B) 104055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis break; 105055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis 10630660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (BeginOffs < E) { 107055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis if (BeginOffs > B) { 10830660a898545416f0fea2d717f16f75640001e38Ted Kremenek BeginOffs = E; 10930660a898545416f0fea2d717f16f75640001e38Ted Kremenek ++I; 11030660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 11130660a898545416f0fea2d717f16f75640001e38Ted Kremenek break; 11230660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 11330660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 11430660a898545416f0fea2d717f16f75640001e38Ted Kremenek 11530660a898545416f0fea2d717f16f75640001e38Ted Kremenek for (; I != FileEdits.end() && EndOffs > I->first; ++I) { 11630660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEdit &FA = I->second; 11730660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset B = I->first; 11830660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset E = B.getWithOffset(FA.RemoveLen); 11930660a898545416f0fea2d717f16f75640001e38Ted Kremenek 12030660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (BeginOffs < B) { 12130660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool Invalid = false; 12230660a898545416f0fea2d717f16f75640001e38Ted Kremenek StringRef text = getSourceText(BeginOffs, B, Invalid); 12330660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (Invalid) 12430660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 12530660a898545416f0fea2d717f16f75640001e38Ted Kremenek StrVec += text; 12630660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 12730660a898545416f0fea2d717f16f75640001e38Ted Kremenek StrVec += FA.Text; 12830660a898545416f0fea2d717f16f75640001e38Ted Kremenek BeginOffs = E; 12930660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 13030660a898545416f0fea2d717f16f75640001e38Ted Kremenek 13130660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (BeginOffs < EndOffs) { 13230660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool Invalid = false; 13330660a898545416f0fea2d717f16f75640001e38Ted Kremenek StringRef text = getSourceText(BeginOffs, EndOffs, Invalid); 13430660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (Invalid) 13530660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 13630660a898545416f0fea2d717f16f75640001e38Ted Kremenek StrVec += text; 13730660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 13830660a898545416f0fea2d717f16f75640001e38Ted Kremenek 13930660a898545416f0fea2d717f16f75640001e38Ted Kremenek return commitInsert(OrigLoc, Offs, StrVec.str(), beforePreviousInsertions); 14030660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 14130660a898545416f0fea2d717f16f75640001e38Ted Kremenek 14230660a898545416f0fea2d717f16f75640001e38Ted Kremenekvoid EditedSource::commitRemove(SourceLocation OrigLoc, 14330660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset BeginOffs, unsigned Len) { 14430660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (Len == 0) 14530660a898545416f0fea2d717f16f75640001e38Ted Kremenek return; 14630660a898545416f0fea2d717f16f75640001e38Ted Kremenek 14730660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset EndOffs = BeginOffs.getWithOffset(Len); 14830660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEditsTy::iterator I = FileEdits.upper_bound(BeginOffs); 14930660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (I != FileEdits.begin()) 15030660a898545416f0fea2d717f16f75640001e38Ted Kremenek --I; 15130660a898545416f0fea2d717f16f75640001e38Ted Kremenek 15230660a898545416f0fea2d717f16f75640001e38Ted Kremenek for (; I != FileEdits.end(); ++I) { 15330660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEdit &FA = I->second; 15430660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset B = I->first; 15530660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset E = B.getWithOffset(FA.RemoveLen); 15630660a898545416f0fea2d717f16f75640001e38Ted Kremenek 15730660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (BeginOffs < E) 15830660a898545416f0fea2d717f16f75640001e38Ted Kremenek break; 15930660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 16030660a898545416f0fea2d717f16f75640001e38Ted Kremenek 16130660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset TopBegin, TopEnd; 16230660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEdit *TopFA = 0; 16330660a898545416f0fea2d717f16f75640001e38Ted Kremenek 16430660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (I == FileEdits.end()) { 16530660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEditsTy::iterator 16630660a898545416f0fea2d717f16f75640001e38Ted Kremenek NewI = FileEdits.insert(I, std::make_pair(BeginOffs, FileEdit())); 16730660a898545416f0fea2d717f16f75640001e38Ted Kremenek NewI->second.RemoveLen = Len; 16830660a898545416f0fea2d717f16f75640001e38Ted Kremenek return; 16930660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 17030660a898545416f0fea2d717f16f75640001e38Ted Kremenek 17130660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEdit &FA = I->second; 17230660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset B = I->first; 17330660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset E = B.getWithOffset(FA.RemoveLen); 17430660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (BeginOffs < B) { 17530660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEditsTy::iterator 17630660a898545416f0fea2d717f16f75640001e38Ted Kremenek NewI = FileEdits.insert(I, std::make_pair(BeginOffs, FileEdit())); 17730660a898545416f0fea2d717f16f75640001e38Ted Kremenek TopBegin = BeginOffs; 17830660a898545416f0fea2d717f16f75640001e38Ted Kremenek TopEnd = EndOffs; 17930660a898545416f0fea2d717f16f75640001e38Ted Kremenek TopFA = &NewI->second; 18030660a898545416f0fea2d717f16f75640001e38Ted Kremenek TopFA->RemoveLen = Len; 18130660a898545416f0fea2d717f16f75640001e38Ted Kremenek } else { 18230660a898545416f0fea2d717f16f75640001e38Ted Kremenek TopBegin = B; 18330660a898545416f0fea2d717f16f75640001e38Ted Kremenek TopEnd = E; 18430660a898545416f0fea2d717f16f75640001e38Ted Kremenek TopFA = &I->second; 18530660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (TopEnd >= EndOffs) 18630660a898545416f0fea2d717f16f75640001e38Ted Kremenek return; 18730660a898545416f0fea2d717f16f75640001e38Ted Kremenek unsigned diff = EndOffs.getOffset() - TopEnd.getOffset(); 18830660a898545416f0fea2d717f16f75640001e38Ted Kremenek TopEnd = EndOffs; 18930660a898545416f0fea2d717f16f75640001e38Ted Kremenek TopFA->RemoveLen += diff; 19030660a898545416f0fea2d717f16f75640001e38Ted Kremenek ++I; 19130660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 19230660a898545416f0fea2d717f16f75640001e38Ted Kremenek 19330660a898545416f0fea2d717f16f75640001e38Ted Kremenek while (I != FileEdits.end()) { 19430660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEdit &FA = I->second; 19530660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset B = I->first; 19630660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset E = B.getWithOffset(FA.RemoveLen); 19730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 19830660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (B >= TopEnd) 19930660a898545416f0fea2d717f16f75640001e38Ted Kremenek break; 20030660a898545416f0fea2d717f16f75640001e38Ted Kremenek 20130660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (E <= TopEnd) { 20230660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEdits.erase(I++); 20330660a898545416f0fea2d717f16f75640001e38Ted Kremenek continue; 20430660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 20530660a898545416f0fea2d717f16f75640001e38Ted Kremenek 20630660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (B < TopEnd) { 20730660a898545416f0fea2d717f16f75640001e38Ted Kremenek unsigned diff = E.getOffset() - TopEnd.getOffset(); 20830660a898545416f0fea2d717f16f75640001e38Ted Kremenek TopEnd = E; 20930660a898545416f0fea2d717f16f75640001e38Ted Kremenek TopFA->RemoveLen += diff; 21030660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEdits.erase(I); 21130660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 21230660a898545416f0fea2d717f16f75640001e38Ted Kremenek 21330660a898545416f0fea2d717f16f75640001e38Ted Kremenek break; 21430660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 21530660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 21630660a898545416f0fea2d717f16f75640001e38Ted Kremenek 21730660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool EditedSource::commit(const Commit &commit) { 21830660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (!commit.isCommitable()) 21930660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 22030660a898545416f0fea2d717f16f75640001e38Ted Kremenek 22130660a898545416f0fea2d717f16f75640001e38Ted Kremenek for (edit::Commit::edit_iterator 22230660a898545416f0fea2d717f16f75640001e38Ted Kremenek I = commit.edit_begin(), E = commit.edit_end(); I != E; ++I) { 22330660a898545416f0fea2d717f16f75640001e38Ted Kremenek const edit::Commit::Edit &edit = *I; 22430660a898545416f0fea2d717f16f75640001e38Ted Kremenek switch (edit.Kind) { 22530660a898545416f0fea2d717f16f75640001e38Ted Kremenek case edit::Commit::Act_Insert: 22630660a898545416f0fea2d717f16f75640001e38Ted Kremenek commitInsert(edit.OrigLoc, edit.Offset, edit.Text, edit.BeforePrev); 22730660a898545416f0fea2d717f16f75640001e38Ted Kremenek break; 22830660a898545416f0fea2d717f16f75640001e38Ted Kremenek case edit::Commit::Act_InsertFromRange: 22930660a898545416f0fea2d717f16f75640001e38Ted Kremenek commitInsertFromRange(edit.OrigLoc, edit.Offset, 23030660a898545416f0fea2d717f16f75640001e38Ted Kremenek edit.InsertFromRangeOffs, edit.Length, 23130660a898545416f0fea2d717f16f75640001e38Ted Kremenek edit.BeforePrev); 23230660a898545416f0fea2d717f16f75640001e38Ted Kremenek break; 23330660a898545416f0fea2d717f16f75640001e38Ted Kremenek case edit::Commit::Act_Remove: 23430660a898545416f0fea2d717f16f75640001e38Ted Kremenek commitRemove(edit.OrigLoc, edit.Offset, edit.Length); 23530660a898545416f0fea2d717f16f75640001e38Ted Kremenek break; 23630660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 23730660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 23830660a898545416f0fea2d717f16f75640001e38Ted Kremenek 23930660a898545416f0fea2d717f16f75640001e38Ted Kremenek return true; 24030660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 24130660a898545416f0fea2d717f16f75640001e38Ted Kremenek 24230660a898545416f0fea2d717f16f75640001e38Ted Kremenekstatic void applyRewrite(EditsReceiver &receiver, 24330660a898545416f0fea2d717f16f75640001e38Ted Kremenek StringRef text, FileOffset offs, unsigned len, 24430660a898545416f0fea2d717f16f75640001e38Ted Kremenek const SourceManager &SM) { 24530660a898545416f0fea2d717f16f75640001e38Ted Kremenek assert(!offs.getFID().isInvalid()); 24630660a898545416f0fea2d717f16f75640001e38Ted Kremenek SourceLocation Loc = SM.getLocForStartOfFile(offs.getFID()); 24730660a898545416f0fea2d717f16f75640001e38Ted Kremenek Loc = Loc.getLocWithOffset(offs.getOffset()); 24830660a898545416f0fea2d717f16f75640001e38Ted Kremenek assert(Loc.isFileID()); 24930660a898545416f0fea2d717f16f75640001e38Ted Kremenek CharSourceRange range = CharSourceRange::getCharRange(Loc, 25030660a898545416f0fea2d717f16f75640001e38Ted Kremenek Loc.getLocWithOffset(len)); 25130660a898545416f0fea2d717f16f75640001e38Ted Kremenek 25230660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (text.empty()) { 25330660a898545416f0fea2d717f16f75640001e38Ted Kremenek assert(len); 25430660a898545416f0fea2d717f16f75640001e38Ted Kremenek receiver.remove(range); 25530660a898545416f0fea2d717f16f75640001e38Ted Kremenek return; 25630660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 25730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 25830660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (len) 25930660a898545416f0fea2d717f16f75640001e38Ted Kremenek receiver.replace(range, text); 26030660a898545416f0fea2d717f16f75640001e38Ted Kremenek else 26130660a898545416f0fea2d717f16f75640001e38Ted Kremenek receiver.insert(Loc, text); 26230660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 26330660a898545416f0fea2d717f16f75640001e38Ted Kremenek 26430660a898545416f0fea2d717f16f75640001e38Ted Kremenekvoid EditedSource::applyRewrites(EditsReceiver &receiver) { 26530660a898545416f0fea2d717f16f75640001e38Ted Kremenek llvm::SmallString<128> StrVec; 26630660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset CurOffs, CurEnd; 26730660a898545416f0fea2d717f16f75640001e38Ted Kremenek unsigned CurLen; 26830660a898545416f0fea2d717f16f75640001e38Ted Kremenek 26930660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (FileEdits.empty()) 27030660a898545416f0fea2d717f16f75640001e38Ted Kremenek return; 27130660a898545416f0fea2d717f16f75640001e38Ted Kremenek 27230660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEditsTy::iterator I = FileEdits.begin(); 27330660a898545416f0fea2d717f16f75640001e38Ted Kremenek CurOffs = I->first; 27430660a898545416f0fea2d717f16f75640001e38Ted Kremenek StrVec = I->second.Text; 27530660a898545416f0fea2d717f16f75640001e38Ted Kremenek CurLen = I->second.RemoveLen; 27630660a898545416f0fea2d717f16f75640001e38Ted Kremenek CurEnd = CurOffs.getWithOffset(CurLen); 27730660a898545416f0fea2d717f16f75640001e38Ted Kremenek ++I; 27830660a898545416f0fea2d717f16f75640001e38Ted Kremenek 27930660a898545416f0fea2d717f16f75640001e38Ted Kremenek for (FileEditsTy::iterator E = FileEdits.end(); I != E; ++I) { 28030660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset offs = I->first; 28130660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEdit act = I->second; 28230660a898545416f0fea2d717f16f75640001e38Ted Kremenek assert(offs >= CurEnd); 28330660a898545416f0fea2d717f16f75640001e38Ted Kremenek 28430660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (offs == CurEnd) { 28530660a898545416f0fea2d717f16f75640001e38Ted Kremenek StrVec += act.Text; 28630660a898545416f0fea2d717f16f75640001e38Ted Kremenek CurLen += act.RemoveLen; 28730660a898545416f0fea2d717f16f75640001e38Ted Kremenek CurEnd.getWithOffset(act.RemoveLen); 28830660a898545416f0fea2d717f16f75640001e38Ted Kremenek continue; 28930660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 29030660a898545416f0fea2d717f16f75640001e38Ted Kremenek 29130660a898545416f0fea2d717f16f75640001e38Ted Kremenek applyRewrite(receiver, StrVec.str(), CurOffs, CurLen, SourceMgr); 29230660a898545416f0fea2d717f16f75640001e38Ted Kremenek CurOffs = offs; 29330660a898545416f0fea2d717f16f75640001e38Ted Kremenek StrVec = act.Text; 29430660a898545416f0fea2d717f16f75640001e38Ted Kremenek CurLen = act.RemoveLen; 29530660a898545416f0fea2d717f16f75640001e38Ted Kremenek CurEnd = CurOffs.getWithOffset(CurLen); 29630660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 29730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 29830660a898545416f0fea2d717f16f75640001e38Ted Kremenek applyRewrite(receiver, StrVec.str(), CurOffs, CurLen, SourceMgr); 29930660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 30030660a898545416f0fea2d717f16f75640001e38Ted Kremenek 30130660a898545416f0fea2d717f16f75640001e38Ted Kremenekvoid EditedSource::clearRewrites() { 30230660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEdits.clear(); 30330660a898545416f0fea2d717f16f75640001e38Ted Kremenek StrAlloc.Reset(); 30430660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 30530660a898545416f0fea2d717f16f75640001e38Ted Kremenek 30630660a898545416f0fea2d717f16f75640001e38Ted KremenekStringRef EditedSource::getSourceText(FileOffset BeginOffs, FileOffset EndOffs, 30730660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool &Invalid) { 30830660a898545416f0fea2d717f16f75640001e38Ted Kremenek assert(BeginOffs.getFID() == EndOffs.getFID()); 30930660a898545416f0fea2d717f16f75640001e38Ted Kremenek assert(BeginOffs <= EndOffs); 31030660a898545416f0fea2d717f16f75640001e38Ted Kremenek SourceLocation BLoc = SourceMgr.getLocForStartOfFile(BeginOffs.getFID()); 31130660a898545416f0fea2d717f16f75640001e38Ted Kremenek BLoc = BLoc.getLocWithOffset(BeginOffs.getOffset()); 31230660a898545416f0fea2d717f16f75640001e38Ted Kremenek assert(BLoc.isFileID()); 31330660a898545416f0fea2d717f16f75640001e38Ted Kremenek SourceLocation 31430660a898545416f0fea2d717f16f75640001e38Ted Kremenek ELoc = BLoc.getLocWithOffset(EndOffs.getOffset() - BeginOffs.getOffset()); 31530660a898545416f0fea2d717f16f75640001e38Ted Kremenek return Lexer::getSourceText(CharSourceRange::getCharRange(BLoc, ELoc), 31630660a898545416f0fea2d717f16f75640001e38Ted Kremenek SourceMgr, LangOpts, &Invalid); 31730660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 31830660a898545416f0fea2d717f16f75640001e38Ted Kremenek 31930660a898545416f0fea2d717f16f75640001e38Ted KremenekEditedSource::FileEditsTy::iterator 32030660a898545416f0fea2d717f16f75640001e38Ted KremenekEditedSource::getActionForOffset(FileOffset Offs) { 32130660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEditsTy::iterator I = FileEdits.upper_bound(Offs); 32230660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (I == FileEdits.begin()) 32330660a898545416f0fea2d717f16f75640001e38Ted Kremenek return FileEdits.end(); 32430660a898545416f0fea2d717f16f75640001e38Ted Kremenek --I; 32530660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileEdit &FA = I->second; 32630660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset B = I->first; 32730660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset E = B.getWithOffset(FA.RemoveLen); 32830660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (Offs >= B && Offs < E) 32930660a898545416f0fea2d717f16f75640001e38Ted Kremenek return I; 33030660a898545416f0fea2d717f16f75640001e38Ted Kremenek 33130660a898545416f0fea2d717f16f75640001e38Ted Kremenek return FileEdits.end(); 33230660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 333