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 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.str(), beforePreviousInsertions); }
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(); }
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; } }