Imported Upstream version 6.10.0.49

Former-commit-id: 1d6753294b2993e1fbf92de9366bb9544db4189b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2020-01-16 16:38:04 +00:00
parent d94e79959b
commit 468663ddbb
48518 changed files with 2789335 additions and 61176 deletions

View File

@@ -0,0 +1,14 @@
set(LLVM_LINK_COMPONENTS
Support
)
add_clang_library(clangEdit
Commit.cpp
EditedSource.cpp
RewriteObjCFoundationAPI.cpp
LINK_LIBS
clangAST
clangBasic
clangLex
)

View File

@@ -0,0 +1,346 @@
//===----- Commit.cpp - A unit of edits -----------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "clang/Edit/Commit.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Edit/EditedSource.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/PPConditionalDirectiveRecord.h"
using namespace clang;
using namespace edit;
SourceLocation Commit::Edit::getFileLocation(SourceManager &SM) const {
SourceLocation Loc = SM.getLocForStartOfFile(Offset.getFID());
Loc = Loc.getLocWithOffset(Offset.getOffset());
assert(Loc.isFileID());
return Loc;
}
CharSourceRange Commit::Edit::getFileRange(SourceManager &SM) const {
SourceLocation Loc = getFileLocation(SM);
return CharSourceRange::getCharRange(Loc, Loc.getLocWithOffset(Length));
}
CharSourceRange Commit::Edit::getInsertFromRange(SourceManager &SM) const {
SourceLocation Loc = SM.getLocForStartOfFile(InsertFromRangeOffs.getFID());
Loc = Loc.getLocWithOffset(InsertFromRangeOffs.getOffset());
assert(Loc.isFileID());
return CharSourceRange::getCharRange(Loc, Loc.getLocWithOffset(Length));
}
Commit::Commit(EditedSource &Editor)
: SourceMgr(Editor.getSourceManager()), LangOpts(Editor.getLangOpts()),
PPRec(Editor.getPPCondDirectiveRecord()),
Editor(&Editor), IsCommitable(true) { }
bool Commit::insert(SourceLocation loc, StringRef text,
bool afterToken, bool beforePreviousInsertions) {
if (text.empty())
return true;
FileOffset Offs;
if ((!afterToken && !canInsert(loc, Offs)) ||
( afterToken && !canInsertAfterToken(loc, Offs, loc))) {
IsCommitable = false;
return false;
}
addInsert(loc, Offs, text, beforePreviousInsertions);
return true;
}
bool Commit::insertFromRange(SourceLocation loc,
CharSourceRange range,
bool afterToken, bool beforePreviousInsertions) {
FileOffset RangeOffs;
unsigned RangeLen;
if (!canRemoveRange(range, RangeOffs, RangeLen)) {
IsCommitable = false;
return false;
}
FileOffset Offs;
if ((!afterToken && !canInsert(loc, Offs)) ||
( afterToken && !canInsertAfterToken(loc, Offs, loc))) {
IsCommitable = false;
return false;
}
if (PPRec &&
PPRec->areInDifferentConditionalDirectiveRegion(loc, range.getBegin())) {
IsCommitable = false;
return false;
}
addInsertFromRange(loc, Offs, RangeOffs, RangeLen, beforePreviousInsertions);
return true;
}
bool Commit::remove(CharSourceRange range) {
FileOffset Offs;
unsigned Len;
if (!canRemoveRange(range, Offs, Len)) {
IsCommitable = false;
return false;
}
addRemove(range.getBegin(), Offs, Len);
return true;
}
bool Commit::insertWrap(StringRef before, CharSourceRange range,
StringRef after) {
bool commitableBefore = insert(range.getBegin(), before, /*afterToken=*/false,
/*beforePreviousInsertions=*/true);
bool commitableAfter;
if (range.isTokenRange())
commitableAfter = insertAfterToken(range.getEnd(), after);
else
commitableAfter = insert(range.getEnd(), after);
return commitableBefore && commitableAfter;
}
bool Commit::replace(CharSourceRange range, StringRef text) {
if (text.empty())
return remove(range);
FileOffset Offs;
unsigned Len;
if (!canInsert(range.getBegin(), Offs) || !canRemoveRange(range, Offs, Len)) {
IsCommitable = false;
return false;
}
addRemove(range.getBegin(), Offs, Len);
addInsert(range.getBegin(), Offs, text, false);
return true;
}
bool Commit::replaceWithInner(CharSourceRange range,
CharSourceRange replacementRange) {
FileOffset OuterBegin;
unsigned OuterLen;
if (!canRemoveRange(range, OuterBegin, OuterLen)) {
IsCommitable = false;
return false;
}
FileOffset InnerBegin;
unsigned InnerLen;
if (!canRemoveRange(replacementRange, InnerBegin, InnerLen)) {
IsCommitable = false;
return false;
}
FileOffset OuterEnd = OuterBegin.getWithOffset(OuterLen);
FileOffset InnerEnd = InnerBegin.getWithOffset(InnerLen);
if (OuterBegin.getFID() != InnerBegin.getFID() ||
InnerBegin < OuterBegin ||
InnerBegin > OuterEnd ||
InnerEnd > OuterEnd) {
IsCommitable = false;
return false;
}
addRemove(range.getBegin(),
OuterBegin, InnerBegin.getOffset() - OuterBegin.getOffset());
addRemove(replacementRange.getEnd(),
InnerEnd, OuterEnd.getOffset() - InnerEnd.getOffset());
return true;
}
bool Commit::replaceText(SourceLocation loc, StringRef text,
StringRef replacementText) {
if (text.empty() || replacementText.empty())
return true;
FileOffset Offs;
unsigned Len;
if (!canReplaceText(loc, replacementText, Offs, Len)) {
IsCommitable = false;
return false;
}
addRemove(loc, Offs, Len);
addInsert(loc, Offs, text, false);
return true;
}
void Commit::addInsert(SourceLocation OrigLoc, FileOffset Offs, StringRef text,
bool beforePreviousInsertions) {
if (text.empty())
return;
Edit data;
data.Kind = Act_Insert;
data.OrigLoc = OrigLoc;
data.Offset = Offs;
data.Text = text.copy(StrAlloc);
data.BeforePrev = beforePreviousInsertions;
CachedEdits.push_back(data);
}
void Commit::addInsertFromRange(SourceLocation OrigLoc, FileOffset Offs,
FileOffset RangeOffs, unsigned RangeLen,
bool beforePreviousInsertions) {
if (RangeLen == 0)
return;
Edit data;
data.Kind = Act_InsertFromRange;
data.OrigLoc = OrigLoc;
data.Offset = Offs;
data.InsertFromRangeOffs = RangeOffs;
data.Length = RangeLen;
data.BeforePrev = beforePreviousInsertions;
CachedEdits.push_back(data);
}
void Commit::addRemove(SourceLocation OrigLoc,
FileOffset Offs, unsigned Len) {
if (Len == 0)
return;
Edit data;
data.Kind = Act_Remove;
data.OrigLoc = OrigLoc;
data.Offset = Offs;
data.Length = Len;
CachedEdits.push_back(data);
}
bool Commit::canInsert(SourceLocation loc, FileOffset &offs) {
if (loc.isInvalid())
return false;
if (loc.isMacroID())
isAtStartOfMacroExpansion(loc, &loc);
const SourceManager &SM = SourceMgr;
while (SM.isMacroArgExpansion(loc))
loc = SM.getImmediateSpellingLoc(loc);
if (loc.isMacroID())
if (!isAtStartOfMacroExpansion(loc, &loc))
return false;
if (SM.isInSystemHeader(loc))
return false;
std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc);
if (locInfo.first.isInvalid())
return false;
offs = FileOffset(locInfo.first, locInfo.second);
return canInsertInOffset(loc, offs);
}
bool Commit::canInsertAfterToken(SourceLocation loc, FileOffset &offs,
SourceLocation &AfterLoc) {
if (loc.isInvalid())
return false;
SourceLocation spellLoc = SourceMgr.getSpellingLoc(loc);
unsigned tokLen = Lexer::MeasureTokenLength(spellLoc, SourceMgr, LangOpts);
AfterLoc = loc.getLocWithOffset(tokLen);
if (loc.isMacroID())
isAtEndOfMacroExpansion(loc, &loc);
const SourceManager &SM = SourceMgr;
while (SM.isMacroArgExpansion(loc))
loc = SM.getImmediateSpellingLoc(loc);
if (loc.isMacroID())
if (!isAtEndOfMacroExpansion(loc, &loc))
return false;
if (SM.isInSystemHeader(loc))
return false;
loc = Lexer::getLocForEndOfToken(loc, 0, SourceMgr, LangOpts);
if (loc.isInvalid())
return false;
std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc);
if (locInfo.first.isInvalid())
return false;
offs = FileOffset(locInfo.first, locInfo.second);
return canInsertInOffset(loc, offs);
}
bool Commit::canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs) {
for (unsigned i = 0, e = CachedEdits.size(); i != e; ++i) {
Edit &act = CachedEdits[i];
if (act.Kind == Act_Remove) {
if (act.Offset.getFID() == Offs.getFID() &&
Offs > act.Offset && Offs < act.Offset.getWithOffset(act.Length))
return false; // position has been removed.
}
}
if (!Editor)
return true;
return Editor->canInsertInOffset(OrigLoc, Offs);
}
bool Commit::canRemoveRange(CharSourceRange range,
FileOffset &Offs, unsigned &Len) {
const SourceManager &SM = SourceMgr;
range = Lexer::makeFileCharRange(range, SM, LangOpts);
if (range.isInvalid())
return false;
if (range.getBegin().isMacroID() || range.getEnd().isMacroID())
return false;
if (SM.isInSystemHeader(range.getBegin()) ||
SM.isInSystemHeader(range.getEnd()))
return false;
if (PPRec && PPRec->rangeIntersectsConditionalDirective(range.getAsRange()))
return false;
std::pair<FileID, unsigned> beginInfo = SM.getDecomposedLoc(range.getBegin());
std::pair<FileID, unsigned> endInfo = SM.getDecomposedLoc(range.getEnd());
if (beginInfo.first != endInfo.first ||
beginInfo.second > endInfo.second)
return false;
Offs = FileOffset(beginInfo.first, beginInfo.second);
Len = endInfo.second - beginInfo.second;
return true;
}
bool Commit::canReplaceText(SourceLocation loc, StringRef text,
FileOffset &Offs, unsigned &Len) {
assert(!text.empty());
if (!canInsert(loc, Offs))
return false;
// Try to load the file buffer.
bool invalidTemp = false;
StringRef file = SourceMgr.getBufferData(Offs.getFID(), &invalidTemp);
if (invalidTemp)
return false;
Len = text.size();
return file.substr(Offs.getOffset()).startswith(text);
}
bool Commit::isAtStartOfMacroExpansion(SourceLocation loc,
SourceLocation *MacroBegin) const {
return Lexer::isAtStartOfMacroExpansion(loc, SourceMgr, LangOpts, MacroBegin);
}
bool Commit::isAtEndOfMacroExpansion(SourceLocation loc,
SourceLocation *MacroEnd) const {
return Lexer::isAtEndOfMacroExpansion(loc, SourceMgr, LangOpts, MacroEnd);
}

View File

@@ -0,0 +1,468 @@
//===----- EditedSource.cpp - Collection of source edits ------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "clang/Edit/EditedSource.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Edit/Commit.h"
#include "clang/Edit/EditsReceiver.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
using namespace clang;
using namespace edit;
void EditsReceiver::remove(CharSourceRange range) {
replace(range, StringRef());
}
void EditedSource::deconstructMacroArgLoc(SourceLocation Loc,
SourceLocation &ExpansionLoc,
MacroArgUse &ArgUse) {
assert(SourceMgr.isMacroArgExpansion(Loc));
SourceLocation DefArgLoc = SourceMgr.getImmediateExpansionRange(Loc).first;
SourceLocation ImmediateExpansionLoc =
SourceMgr.getImmediateExpansionRange(DefArgLoc).first;
ExpansionLoc = ImmediateExpansionLoc;
while (SourceMgr.isMacroBodyExpansion(ExpansionLoc))
ExpansionLoc = SourceMgr.getImmediateExpansionRange(ExpansionLoc).first;
SmallString<20> Buf;
StringRef ArgName = Lexer::getSpelling(SourceMgr.getSpellingLoc(DefArgLoc),
Buf, SourceMgr, LangOpts);
ArgUse = MacroArgUse{nullptr, SourceLocation(), SourceLocation()};
if (!ArgName.empty())
ArgUse = {&IdentTable.get(ArgName), ImmediateExpansionLoc,
SourceMgr.getSpellingLoc(DefArgLoc)};
}
void EditedSource::startingCommit() {}
void EditedSource::finishedCommit() {
for (auto &ExpArg : CurrCommitMacroArgExps) {
SourceLocation ExpLoc;
MacroArgUse ArgUse;
std::tie(ExpLoc, ArgUse) = ExpArg;
auto &ArgUses = ExpansionToArgMap[ExpLoc.getRawEncoding()];
if (std::find(ArgUses.begin(), ArgUses.end(), ArgUse) == ArgUses.end())
ArgUses.push_back(ArgUse);
}
CurrCommitMacroArgExps.clear();
}
StringRef EditedSource::copyString(const Twine &twine) {
SmallString<128> Data;
return copyString(twine.toStringRef(Data));
}
bool EditedSource::canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs) {
FileEditsTy::iterator FA = getActionForOffset(Offs);
if (FA != FileEdits.end()) {
if (FA->first != Offs)
return false; // position has been removed.
}
if (SourceMgr.isMacroArgExpansion(OrigLoc)) {
SourceLocation ExpLoc;
MacroArgUse ArgUse;
deconstructMacroArgLoc(OrigLoc, ExpLoc, ArgUse);
auto I = ExpansionToArgMap.find(ExpLoc.getRawEncoding());
if (I != ExpansionToArgMap.end() &&
find_if(I->second, [&](const MacroArgUse &U) {
return ArgUse.Identifier == U.Identifier &&
std::tie(ArgUse.ImmediateExpansionLoc, ArgUse.UseLoc) !=
std::tie(U.ImmediateExpansionLoc, U.UseLoc);
}) != I->second.end()) {
// Trying to write in a macro argument input that has already been
// written by a previous commit for another expansion of the same macro
// argument name. For example:
//
// \code
// #define MAC(x) ((x)+(x))
// MAC(a)
// \endcode
//
// A commit modified the macro argument 'a' due to the first '(x)'
// expansion inside the macro definition, and a subsequent commit tried
// to modify 'a' again for the second '(x)' expansion. The edits of the
// second commit will be rejected.
return false;
}
}
return true;
}
bool EditedSource::commitInsert(SourceLocation OrigLoc,
FileOffset Offs, StringRef text,
bool beforePreviousInsertions) {
if (!canInsertInOffset(OrigLoc, Offs))
return false;
if (text.empty())
return true;
if (SourceMgr.isMacroArgExpansion(OrigLoc)) {
MacroArgUse ArgUse;
SourceLocation ExpLoc;
deconstructMacroArgLoc(OrigLoc, ExpLoc, ArgUse);
if (ArgUse.Identifier)
CurrCommitMacroArgExps.emplace_back(ExpLoc, ArgUse);
}
FileEdit &FA = FileEdits[Offs];
if (FA.Text.empty()) {
FA.Text = copyString(text);
return true;
}
if (beforePreviousInsertions)
FA.Text = copyString(Twine(text) + FA.Text);
else
FA.Text = copyString(Twine(FA.Text) + text);
return true;
}
bool EditedSource::commitInsertFromRange(SourceLocation OrigLoc,
FileOffset Offs,
FileOffset InsertFromRangeOffs, unsigned Len,
bool beforePreviousInsertions) {
if (Len == 0)
return true;
SmallString<128> StrVec;
FileOffset BeginOffs = InsertFromRangeOffs;
FileOffset EndOffs = BeginOffs.getWithOffset(Len);
FileEditsTy::iterator I = FileEdits.upper_bound(BeginOffs);
if (I != FileEdits.begin())
--I;
for (; I != FileEdits.end(); ++I) {
FileEdit &FA = I->second;
FileOffset B = I->first;
FileOffset E = B.getWithOffset(FA.RemoveLen);
if (BeginOffs == B)
break;
if (BeginOffs < E) {
if (BeginOffs > B) {
BeginOffs = E;
++I;
}
break;
}
}
for (; I != FileEdits.end() && EndOffs > I->first; ++I) {
FileEdit &FA = I->second;
FileOffset B = I->first;
FileOffset E = B.getWithOffset(FA.RemoveLen);
if (BeginOffs < B) {
bool Invalid = false;
StringRef text = getSourceText(BeginOffs, B, Invalid);
if (Invalid)
return false;
StrVec += text;
}
StrVec += FA.Text;
BeginOffs = E;
}
if (BeginOffs < EndOffs) {
bool Invalid = false;
StringRef text = getSourceText(BeginOffs, EndOffs, Invalid);
if (Invalid)
return false;
StrVec += text;
}
return commitInsert(OrigLoc, Offs, StrVec, beforePreviousInsertions);
}
void EditedSource::commitRemove(SourceLocation OrigLoc,
FileOffset BeginOffs, unsigned Len) {
if (Len == 0)
return;
FileOffset EndOffs = BeginOffs.getWithOffset(Len);
FileEditsTy::iterator I = FileEdits.upper_bound(BeginOffs);
if (I != FileEdits.begin())
--I;
for (; I != FileEdits.end(); ++I) {
FileEdit &FA = I->second;
FileOffset B = I->first;
FileOffset E = B.getWithOffset(FA.RemoveLen);
if (BeginOffs < E)
break;
}
FileOffset TopBegin, TopEnd;
FileEdit *TopFA = nullptr;
if (I == FileEdits.end()) {
FileEditsTy::iterator
NewI = FileEdits.insert(I, std::make_pair(BeginOffs, FileEdit()));
NewI->second.RemoveLen = Len;
return;
}
FileEdit &FA = I->second;
FileOffset B = I->first;
FileOffset E = B.getWithOffset(FA.RemoveLen);
if (BeginOffs < B) {
FileEditsTy::iterator
NewI = FileEdits.insert(I, std::make_pair(BeginOffs, FileEdit()));
TopBegin = BeginOffs;
TopEnd = EndOffs;
TopFA = &NewI->second;
TopFA->RemoveLen = Len;
} else {
TopBegin = B;
TopEnd = E;
TopFA = &I->second;
if (TopEnd >= EndOffs)
return;
unsigned diff = EndOffs.getOffset() - TopEnd.getOffset();
TopEnd = EndOffs;
TopFA->RemoveLen += diff;
if (B == BeginOffs)
TopFA->Text = StringRef();
++I;
}
while (I != FileEdits.end()) {
FileEdit &FA = I->second;
FileOffset B = I->first;
FileOffset E = B.getWithOffset(FA.RemoveLen);
if (B >= TopEnd)
break;
if (E <= TopEnd) {
FileEdits.erase(I++);
continue;
}
if (B < TopEnd) {
unsigned diff = E.getOffset() - TopEnd.getOffset();
TopEnd = E;
TopFA->RemoveLen += diff;
FileEdits.erase(I);
}
break;
}
}
bool EditedSource::commit(const Commit &commit) {
if (!commit.isCommitable())
return false;
struct CommitRAII {
EditedSource &Editor;
CommitRAII(EditedSource &Editor) : Editor(Editor) {
Editor.startingCommit();
}
~CommitRAII() {
Editor.finishedCommit();
}
} CommitRAII(*this);
for (edit::Commit::edit_iterator
I = commit.edit_begin(), E = commit.edit_end(); I != E; ++I) {
const edit::Commit::Edit &edit = *I;
switch (edit.Kind) {
case edit::Commit::Act_Insert:
commitInsert(edit.OrigLoc, edit.Offset, edit.Text, edit.BeforePrev);
break;
case edit::Commit::Act_InsertFromRange:
commitInsertFromRange(edit.OrigLoc, edit.Offset,
edit.InsertFromRangeOffs, edit.Length,
edit.BeforePrev);
break;
case edit::Commit::Act_Remove:
commitRemove(edit.OrigLoc, edit.Offset, edit.Length);
break;
}
}
return true;
}
// \brief Returns true if it is ok to make the two given characters adjacent.
static bool canBeJoined(char left, char right, const LangOptions &LangOpts) {
// FIXME: Should use TokenConcatenation to make sure we don't allow stuff like
// making two '<' adjacent.
return !(Lexer::isIdentifierBodyChar(left, LangOpts) &&
Lexer::isIdentifierBodyChar(right, LangOpts));
}
/// \brief Returns true if it is ok to eliminate the trailing whitespace between
/// the given characters.
static bool canRemoveWhitespace(char left, char beforeWSpace, char right,
const LangOptions &LangOpts) {
if (!canBeJoined(left, right, LangOpts))
return false;
if (isWhitespace(left) || isWhitespace(right))
return true;
if (canBeJoined(beforeWSpace, right, LangOpts))
return false; // the whitespace was intentional, keep it.
return true;
}
/// \brief Check the range that we are going to remove and:
/// -Remove any trailing whitespace if possible.
/// -Insert a space if removing the range is going to mess up the source tokens.
static void adjustRemoval(const SourceManager &SM, const LangOptions &LangOpts,
SourceLocation Loc, FileOffset offs,
unsigned &len, StringRef &text) {
assert(len && text.empty());
SourceLocation BeginTokLoc = Lexer::GetBeginningOfToken(Loc, SM, LangOpts);
if (BeginTokLoc != Loc)
return; // the range is not at the beginning of a token, keep the range.
bool Invalid = false;
StringRef buffer = SM.getBufferData(offs.getFID(), &Invalid);
if (Invalid)
return;
unsigned begin = offs.getOffset();
unsigned end = begin + len;
// Do not try to extend the removal if we're at the end of the buffer already.
if (end == buffer.size())
return;
assert(begin < buffer.size() && end < buffer.size() && "Invalid range!");
// FIXME: Remove newline.
if (begin == 0) {
if (buffer[end] == ' ')
++len;
return;
}
if (buffer[end] == ' ') {
assert((end + 1 != buffer.size() || buffer.data()[end + 1] == 0) &&
"buffer not zero-terminated!");
if (canRemoveWhitespace(/*left=*/buffer[begin-1],
/*beforeWSpace=*/buffer[end-1],
/*right=*/buffer.data()[end + 1], // zero-terminated
LangOpts))
++len;
return;
}
if (!canBeJoined(buffer[begin-1], buffer[end], LangOpts))
text = " ";
}
static void applyRewrite(EditsReceiver &receiver,
StringRef text, FileOffset offs, unsigned len,
const SourceManager &SM, const LangOptions &LangOpts,
bool shouldAdjustRemovals) {
assert(offs.getFID().isValid());
SourceLocation Loc = SM.getLocForStartOfFile(offs.getFID());
Loc = Loc.getLocWithOffset(offs.getOffset());
assert(Loc.isFileID());
if (text.empty() && shouldAdjustRemovals)
adjustRemoval(SM, LangOpts, Loc, offs, len, text);
CharSourceRange range = CharSourceRange::getCharRange(Loc,
Loc.getLocWithOffset(len));
if (text.empty()) {
assert(len);
receiver.remove(range);
return;
}
if (len)
receiver.replace(range, text);
else
receiver.insert(Loc, text);
}
void EditedSource::applyRewrites(EditsReceiver &receiver,
bool shouldAdjustRemovals) {
SmallString<128> StrVec;
FileOffset CurOffs, CurEnd;
unsigned CurLen;
if (FileEdits.empty())
return;
FileEditsTy::iterator I = FileEdits.begin();
CurOffs = I->first;
StrVec = I->second.Text;
CurLen = I->second.RemoveLen;
CurEnd = CurOffs.getWithOffset(CurLen);
++I;
for (FileEditsTy::iterator E = FileEdits.end(); I != E; ++I) {
FileOffset offs = I->first;
FileEdit act = I->second;
assert(offs >= CurEnd);
if (offs == CurEnd) {
StrVec += act.Text;
CurLen += act.RemoveLen;
CurEnd.getWithOffset(act.RemoveLen);
continue;
}
applyRewrite(receiver, StrVec, CurOffs, CurLen, SourceMgr, LangOpts,
shouldAdjustRemovals);
CurOffs = offs;
StrVec = act.Text;
CurLen = act.RemoveLen;
CurEnd = CurOffs.getWithOffset(CurLen);
}
applyRewrite(receiver, StrVec, CurOffs, CurLen, SourceMgr, LangOpts,
shouldAdjustRemovals);
}
void EditedSource::clearRewrites() {
FileEdits.clear();
StrAlloc.Reset();
}
StringRef EditedSource::getSourceText(FileOffset BeginOffs, FileOffset EndOffs,
bool &Invalid) {
assert(BeginOffs.getFID() == EndOffs.getFID());
assert(BeginOffs <= EndOffs);
SourceLocation BLoc = SourceMgr.getLocForStartOfFile(BeginOffs.getFID());
BLoc = BLoc.getLocWithOffset(BeginOffs.getOffset());
assert(BLoc.isFileID());
SourceLocation
ELoc = BLoc.getLocWithOffset(EndOffs.getOffset() - BeginOffs.getOffset());
return Lexer::getSourceText(CharSourceRange::getCharRange(BLoc, ELoc),
SourceMgr, LangOpts, &Invalid);
}
EditedSource::FileEditsTy::iterator
EditedSource::getActionForOffset(FileOffset Offs) {
FileEditsTy::iterator I = FileEdits.upper_bound(Offs);
if (I == FileEdits.begin())
return FileEdits.end();
--I;
FileEdit &FA = I->second;
FileOffset B = I->first;
FileOffset E = B.getWithOffset(FA.RemoveLen);
if (Offs >= B && Offs < E)
return I;
return FileEdits.end();
}

File diff suppressed because it is too large Load Diff