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; }
static void applyRewrite(EditsReceiver &receiver, StringRef text, FileOffset offs, unsigned len, const SourceManager &SM, const LangOptions &LangOpts) { assert(!offs.getFID().isInvalid()); SourceLocation Loc = SM.getLocForStartOfFile(offs.getFID()); Loc = Loc.getLocWithOffset(offs.getOffset()); assert(Loc.isFileID()); if (text.empty()) 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); }
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); }
bool Commit::canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs) { for (const auto &act : CachedEdits) 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::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::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); }
/// \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 = " "; }
/// \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; // FIXME: Remove newline. if (begin == 0) { if (buffer[end] == ' ') ++len; return; } if (buffer[end] == ' ') { if (canRemoveWhitespace(/*left=*/buffer[begin-1], /*beforeWSpace=*/buffer[end-1], /*right=*/buffer[end+1], LangOpts)) ++len; return; } if (!canBeJoined(buffer[begin-1], buffer[end], LangOpts)) text = " "; }