Commit.cpp revision 6bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89
130660a898545416f0fea2d717f16f75640001e38Ted Kremenek//===----- Commit.cpp - A unit of 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/Commit.h" 1155fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Basic/SourceManager.h" 1230660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Edit/EditedSource.h" 1330660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Lex/Lexer.h" 1437ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis#include "clang/Lex/PPConditionalDirectiveRecord.h" 1530660a898545416f0fea2d717f16f75640001e38Ted Kremenek 1630660a898545416f0fea2d717f16f75640001e38Ted Kremenekusing namespace clang; 1730660a898545416f0fea2d717f16f75640001e38Ted Kremenekusing namespace edit; 1830660a898545416f0fea2d717f16f75640001e38Ted Kremenek 1930660a898545416f0fea2d717f16f75640001e38Ted KremenekSourceLocation Commit::Edit::getFileLocation(SourceManager &SM) const { 2030660a898545416f0fea2d717f16f75640001e38Ted Kremenek SourceLocation Loc = SM.getLocForStartOfFile(Offset.getFID()); 2130660a898545416f0fea2d717f16f75640001e38Ted Kremenek Loc = Loc.getLocWithOffset(Offset.getOffset()); 2230660a898545416f0fea2d717f16f75640001e38Ted Kremenek assert(Loc.isFileID()); 2330660a898545416f0fea2d717f16f75640001e38Ted Kremenek return Loc; 2430660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 2530660a898545416f0fea2d717f16f75640001e38Ted Kremenek 2630660a898545416f0fea2d717f16f75640001e38Ted KremenekCharSourceRange Commit::Edit::getFileRange(SourceManager &SM) const { 2730660a898545416f0fea2d717f16f75640001e38Ted Kremenek SourceLocation Loc = getFileLocation(SM); 2830660a898545416f0fea2d717f16f75640001e38Ted Kremenek return CharSourceRange::getCharRange(Loc, Loc.getLocWithOffset(Length)); 2930660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 3030660a898545416f0fea2d717f16f75640001e38Ted Kremenek 3130660a898545416f0fea2d717f16f75640001e38Ted KremenekCharSourceRange Commit::Edit::getInsertFromRange(SourceManager &SM) const { 3230660a898545416f0fea2d717f16f75640001e38Ted Kremenek SourceLocation Loc = SM.getLocForStartOfFile(InsertFromRangeOffs.getFID()); 3330660a898545416f0fea2d717f16f75640001e38Ted Kremenek Loc = Loc.getLocWithOffset(InsertFromRangeOffs.getOffset()); 3430660a898545416f0fea2d717f16f75640001e38Ted Kremenek assert(Loc.isFileID()); 3530660a898545416f0fea2d717f16f75640001e38Ted Kremenek return CharSourceRange::getCharRange(Loc, Loc.getLocWithOffset(Length)); 3630660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 3730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 3830660a898545416f0fea2d717f16f75640001e38Ted KremenekCommit::Commit(EditedSource &Editor) 394e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie : SourceMgr(Editor.getSourceManager()), LangOpts(Editor.getLangOpts()), 4037ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis PPRec(Editor.getPPCondDirectiveRecord()), 416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Editor(&Editor), IsCommitable(true) { } 4230660a898545416f0fea2d717f16f75640001e38Ted Kremenek 4330660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool Commit::insert(SourceLocation loc, StringRef text, 4430660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool afterToken, bool beforePreviousInsertions) { 4530660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (text.empty()) 4630660a898545416f0fea2d717f16f75640001e38Ted Kremenek return true; 4730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 4830660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset Offs; 4930660a898545416f0fea2d717f16f75640001e38Ted Kremenek if ((!afterToken && !canInsert(loc, Offs)) || 5030660a898545416f0fea2d717f16f75640001e38Ted Kremenek ( afterToken && !canInsertAfterToken(loc, Offs, loc))) { 5130660a898545416f0fea2d717f16f75640001e38Ted Kremenek IsCommitable = false; 5230660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 5330660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 5430660a898545416f0fea2d717f16f75640001e38Ted Kremenek 5530660a898545416f0fea2d717f16f75640001e38Ted Kremenek addInsert(loc, Offs, text, beforePreviousInsertions); 5630660a898545416f0fea2d717f16f75640001e38Ted Kremenek return true; 5730660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 5830660a898545416f0fea2d717f16f75640001e38Ted Kremenek 5930660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool Commit::insertFromRange(SourceLocation loc, 6030660a898545416f0fea2d717f16f75640001e38Ted Kremenek CharSourceRange range, 6130660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool afterToken, bool beforePreviousInsertions) { 6230660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset RangeOffs; 6330660a898545416f0fea2d717f16f75640001e38Ted Kremenek unsigned RangeLen; 6430660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (!canRemoveRange(range, RangeOffs, RangeLen)) { 6530660a898545416f0fea2d717f16f75640001e38Ted Kremenek IsCommitable = false; 6630660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 6730660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 6830660a898545416f0fea2d717f16f75640001e38Ted Kremenek 6930660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset Offs; 7030660a898545416f0fea2d717f16f75640001e38Ted Kremenek if ((!afterToken && !canInsert(loc, Offs)) || 7130660a898545416f0fea2d717f16f75640001e38Ted Kremenek ( afterToken && !canInsertAfterToken(loc, Offs, loc))) { 7230660a898545416f0fea2d717f16f75640001e38Ted Kremenek IsCommitable = false; 7330660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 7430660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 7530660a898545416f0fea2d717f16f75640001e38Ted Kremenek 7630660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (PPRec && 7730660a898545416f0fea2d717f16f75640001e38Ted Kremenek PPRec->areInDifferentConditionalDirectiveRegion(loc, range.getBegin())) { 7830660a898545416f0fea2d717f16f75640001e38Ted Kremenek IsCommitable = false; 7930660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 8030660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 8130660a898545416f0fea2d717f16f75640001e38Ted Kremenek 8230660a898545416f0fea2d717f16f75640001e38Ted Kremenek addInsertFromRange(loc, Offs, RangeOffs, RangeLen, beforePreviousInsertions); 8330660a898545416f0fea2d717f16f75640001e38Ted Kremenek return true; 8430660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 8530660a898545416f0fea2d717f16f75640001e38Ted Kremenek 8630660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool Commit::remove(CharSourceRange range) { 8730660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset Offs; 8830660a898545416f0fea2d717f16f75640001e38Ted Kremenek unsigned Len; 8930660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (!canRemoveRange(range, Offs, Len)) { 9030660a898545416f0fea2d717f16f75640001e38Ted Kremenek IsCommitable = false; 9130660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 9230660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 9330660a898545416f0fea2d717f16f75640001e38Ted Kremenek 9430660a898545416f0fea2d717f16f75640001e38Ted Kremenek addRemove(range.getBegin(), Offs, Len); 9530660a898545416f0fea2d717f16f75640001e38Ted Kremenek return true; 9630660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 9730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 9830660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool Commit::insertWrap(StringRef before, CharSourceRange range, 9930660a898545416f0fea2d717f16f75640001e38Ted Kremenek StringRef after) { 10030660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool commitableBefore = insert(range.getBegin(), before, /*afterToken=*/false, 10130660a898545416f0fea2d717f16f75640001e38Ted Kremenek /*beforePreviousInsertions=*/true); 10230660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool commitableAfter; 10330660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (range.isTokenRange()) 10430660a898545416f0fea2d717f16f75640001e38Ted Kremenek commitableAfter = insertAfterToken(range.getEnd(), after); 10530660a898545416f0fea2d717f16f75640001e38Ted Kremenek else 10630660a898545416f0fea2d717f16f75640001e38Ted Kremenek commitableAfter = insert(range.getEnd(), after); 10730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 10830660a898545416f0fea2d717f16f75640001e38Ted Kremenek return commitableBefore && commitableAfter; 10930660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 11030660a898545416f0fea2d717f16f75640001e38Ted Kremenek 11130660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool Commit::replace(CharSourceRange range, StringRef text) { 11230660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (text.empty()) 11330660a898545416f0fea2d717f16f75640001e38Ted Kremenek return remove(range); 11430660a898545416f0fea2d717f16f75640001e38Ted Kremenek 11530660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset Offs; 11630660a898545416f0fea2d717f16f75640001e38Ted Kremenek unsigned Len; 11730660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (!canInsert(range.getBegin(), Offs) || !canRemoveRange(range, Offs, Len)) { 11830660a898545416f0fea2d717f16f75640001e38Ted Kremenek IsCommitable = false; 11930660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 12030660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 12130660a898545416f0fea2d717f16f75640001e38Ted Kremenek 12230660a898545416f0fea2d717f16f75640001e38Ted Kremenek addRemove(range.getBegin(), Offs, Len); 12330660a898545416f0fea2d717f16f75640001e38Ted Kremenek addInsert(range.getBegin(), Offs, text, false); 12430660a898545416f0fea2d717f16f75640001e38Ted Kremenek return true; 12530660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 12630660a898545416f0fea2d717f16f75640001e38Ted Kremenek 12730660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool Commit::replaceWithInner(CharSourceRange range, 12830660a898545416f0fea2d717f16f75640001e38Ted Kremenek CharSourceRange replacementRange) { 12930660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset OuterBegin; 13030660a898545416f0fea2d717f16f75640001e38Ted Kremenek unsigned OuterLen; 13130660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (!canRemoveRange(range, OuterBegin, OuterLen)) { 13230660a898545416f0fea2d717f16f75640001e38Ted Kremenek IsCommitable = false; 13330660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 13430660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 13530660a898545416f0fea2d717f16f75640001e38Ted Kremenek 13630660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset InnerBegin; 13730660a898545416f0fea2d717f16f75640001e38Ted Kremenek unsigned InnerLen; 13830660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (!canRemoveRange(replacementRange, InnerBegin, InnerLen)) { 13930660a898545416f0fea2d717f16f75640001e38Ted Kremenek IsCommitable = false; 14030660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 14130660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 14230660a898545416f0fea2d717f16f75640001e38Ted Kremenek 14330660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset OuterEnd = OuterBegin.getWithOffset(OuterLen); 14430660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset InnerEnd = InnerBegin.getWithOffset(InnerLen); 14530660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (OuterBegin.getFID() != InnerBegin.getFID() || 14630660a898545416f0fea2d717f16f75640001e38Ted Kremenek InnerBegin < OuterBegin || 14730660a898545416f0fea2d717f16f75640001e38Ted Kremenek InnerBegin > OuterEnd || 14830660a898545416f0fea2d717f16f75640001e38Ted Kremenek InnerEnd > OuterEnd) { 14930660a898545416f0fea2d717f16f75640001e38Ted Kremenek IsCommitable = false; 15030660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 15130660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 15230660a898545416f0fea2d717f16f75640001e38Ted Kremenek 15330660a898545416f0fea2d717f16f75640001e38Ted Kremenek addRemove(range.getBegin(), 15430660a898545416f0fea2d717f16f75640001e38Ted Kremenek OuterBegin, InnerBegin.getOffset() - OuterBegin.getOffset()); 15530660a898545416f0fea2d717f16f75640001e38Ted Kremenek addRemove(replacementRange.getEnd(), 15630660a898545416f0fea2d717f16f75640001e38Ted Kremenek InnerEnd, OuterEnd.getOffset() - InnerEnd.getOffset()); 15730660a898545416f0fea2d717f16f75640001e38Ted Kremenek return true; 15830660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 15930660a898545416f0fea2d717f16f75640001e38Ted Kremenek 16030660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool Commit::replaceText(SourceLocation loc, StringRef text, 16130660a898545416f0fea2d717f16f75640001e38Ted Kremenek StringRef replacementText) { 16230660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (text.empty() || replacementText.empty()) 16330660a898545416f0fea2d717f16f75640001e38Ted Kremenek return true; 16430660a898545416f0fea2d717f16f75640001e38Ted Kremenek 16530660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset Offs; 16630660a898545416f0fea2d717f16f75640001e38Ted Kremenek unsigned Len; 16730660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (!canReplaceText(loc, replacementText, Offs, Len)) { 16830660a898545416f0fea2d717f16f75640001e38Ted Kremenek IsCommitable = false; 16930660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 17030660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 17130660a898545416f0fea2d717f16f75640001e38Ted Kremenek 17230660a898545416f0fea2d717f16f75640001e38Ted Kremenek addRemove(loc, Offs, Len); 17330660a898545416f0fea2d717f16f75640001e38Ted Kremenek addInsert(loc, Offs, text, false); 17430660a898545416f0fea2d717f16f75640001e38Ted Kremenek return true; 17530660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 17630660a898545416f0fea2d717f16f75640001e38Ted Kremenek 17730660a898545416f0fea2d717f16f75640001e38Ted Kremenekvoid Commit::addInsert(SourceLocation OrigLoc, FileOffset Offs, StringRef text, 17830660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool beforePreviousInsertions) { 17930660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (text.empty()) 18030660a898545416f0fea2d717f16f75640001e38Ted Kremenek return; 18130660a898545416f0fea2d717f16f75640001e38Ted Kremenek 18230660a898545416f0fea2d717f16f75640001e38Ted Kremenek Edit data; 18330660a898545416f0fea2d717f16f75640001e38Ted Kremenek data.Kind = Act_Insert; 18430660a898545416f0fea2d717f16f75640001e38Ted Kremenek data.OrigLoc = OrigLoc; 18530660a898545416f0fea2d717f16f75640001e38Ted Kremenek data.Offset = Offs; 1861921b58a2aba4f5073d6634d476356b6a4ff8815Fariborz Jahanian data.Text = copyString(text); 18730660a898545416f0fea2d717f16f75640001e38Ted Kremenek data.BeforePrev = beforePreviousInsertions; 18830660a898545416f0fea2d717f16f75640001e38Ted Kremenek CachedEdits.push_back(data); 18930660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 19030660a898545416f0fea2d717f16f75640001e38Ted Kremenek 19130660a898545416f0fea2d717f16f75640001e38Ted Kremenekvoid Commit::addInsertFromRange(SourceLocation OrigLoc, FileOffset Offs, 19230660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset RangeOffs, unsigned RangeLen, 19330660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool beforePreviousInsertions) { 19430660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (RangeLen == 0) 19530660a898545416f0fea2d717f16f75640001e38Ted Kremenek return; 19630660a898545416f0fea2d717f16f75640001e38Ted Kremenek 19730660a898545416f0fea2d717f16f75640001e38Ted Kremenek Edit data; 19830660a898545416f0fea2d717f16f75640001e38Ted Kremenek data.Kind = Act_InsertFromRange; 19930660a898545416f0fea2d717f16f75640001e38Ted Kremenek data.OrigLoc = OrigLoc; 20030660a898545416f0fea2d717f16f75640001e38Ted Kremenek data.Offset = Offs; 20130660a898545416f0fea2d717f16f75640001e38Ted Kremenek data.InsertFromRangeOffs = RangeOffs; 20230660a898545416f0fea2d717f16f75640001e38Ted Kremenek data.Length = RangeLen; 20330660a898545416f0fea2d717f16f75640001e38Ted Kremenek data.BeforePrev = beforePreviousInsertions; 20430660a898545416f0fea2d717f16f75640001e38Ted Kremenek CachedEdits.push_back(data); 20530660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 20630660a898545416f0fea2d717f16f75640001e38Ted Kremenek 20730660a898545416f0fea2d717f16f75640001e38Ted Kremenekvoid Commit::addRemove(SourceLocation OrigLoc, 20830660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset Offs, unsigned Len) { 20930660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (Len == 0) 21030660a898545416f0fea2d717f16f75640001e38Ted Kremenek return; 21130660a898545416f0fea2d717f16f75640001e38Ted Kremenek 21230660a898545416f0fea2d717f16f75640001e38Ted Kremenek Edit data; 21330660a898545416f0fea2d717f16f75640001e38Ted Kremenek data.Kind = Act_Remove; 21430660a898545416f0fea2d717f16f75640001e38Ted Kremenek data.OrigLoc = OrigLoc; 21530660a898545416f0fea2d717f16f75640001e38Ted Kremenek data.Offset = Offs; 21630660a898545416f0fea2d717f16f75640001e38Ted Kremenek data.Length = Len; 21730660a898545416f0fea2d717f16f75640001e38Ted Kremenek CachedEdits.push_back(data); 21830660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 21930660a898545416f0fea2d717f16f75640001e38Ted Kremenek 22030660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool Commit::canInsert(SourceLocation loc, FileOffset &offs) { 22130660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (loc.isInvalid()) 22230660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 22330660a898545416f0fea2d717f16f75640001e38Ted Kremenek 22430660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (loc.isMacroID()) 22530660a898545416f0fea2d717f16f75640001e38Ted Kremenek isAtStartOfMacroExpansion(loc, &loc); 22630660a898545416f0fea2d717f16f75640001e38Ted Kremenek 22730660a898545416f0fea2d717f16f75640001e38Ted Kremenek const SourceManager &SM = SourceMgr; 22830660a898545416f0fea2d717f16f75640001e38Ted Kremenek while (SM.isMacroArgExpansion(loc)) 22930660a898545416f0fea2d717f16f75640001e38Ted Kremenek loc = SM.getImmediateSpellingLoc(loc); 23030660a898545416f0fea2d717f16f75640001e38Ted Kremenek 23130660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (loc.isMacroID()) 23230660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (!isAtStartOfMacroExpansion(loc, &loc)) 23330660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 23430660a898545416f0fea2d717f16f75640001e38Ted Kremenek 2356bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (SM.isInSystemHeader(loc)) 23630660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 23730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 23830660a898545416f0fea2d717f16f75640001e38Ted Kremenek std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc); 23930660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (locInfo.first.isInvalid()) 24030660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 24130660a898545416f0fea2d717f16f75640001e38Ted Kremenek offs = FileOffset(locInfo.first, locInfo.second); 24230660a898545416f0fea2d717f16f75640001e38Ted Kremenek return canInsertInOffset(loc, offs); 24330660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 24430660a898545416f0fea2d717f16f75640001e38Ted Kremenek 24530660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool Commit::canInsertAfterToken(SourceLocation loc, FileOffset &offs, 24630660a898545416f0fea2d717f16f75640001e38Ted Kremenek SourceLocation &AfterLoc) { 24730660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (loc.isInvalid()) 24830660a898545416f0fea2d717f16f75640001e38Ted Kremenek 24930660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 25030660a898545416f0fea2d717f16f75640001e38Ted Kremenek 25130660a898545416f0fea2d717f16f75640001e38Ted Kremenek SourceLocation spellLoc = SourceMgr.getSpellingLoc(loc); 25230660a898545416f0fea2d717f16f75640001e38Ted Kremenek unsigned tokLen = Lexer::MeasureTokenLength(spellLoc, SourceMgr, LangOpts); 25330660a898545416f0fea2d717f16f75640001e38Ted Kremenek AfterLoc = loc.getLocWithOffset(tokLen); 25430660a898545416f0fea2d717f16f75640001e38Ted Kremenek 25530660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (loc.isMacroID()) 25630660a898545416f0fea2d717f16f75640001e38Ted Kremenek isAtEndOfMacroExpansion(loc, &loc); 25730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 25830660a898545416f0fea2d717f16f75640001e38Ted Kremenek const SourceManager &SM = SourceMgr; 25930660a898545416f0fea2d717f16f75640001e38Ted Kremenek while (SM.isMacroArgExpansion(loc)) 26030660a898545416f0fea2d717f16f75640001e38Ted Kremenek loc = SM.getImmediateSpellingLoc(loc); 26130660a898545416f0fea2d717f16f75640001e38Ted Kremenek 26230660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (loc.isMacroID()) 26330660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (!isAtEndOfMacroExpansion(loc, &loc)) 26430660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 26530660a898545416f0fea2d717f16f75640001e38Ted Kremenek 2666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (SM.isInSystemHeader(loc)) 26730660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 26830660a898545416f0fea2d717f16f75640001e38Ted Kremenek 26930660a898545416f0fea2d717f16f75640001e38Ted Kremenek loc = Lexer::getLocForEndOfToken(loc, 0, SourceMgr, LangOpts); 27030660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (loc.isInvalid()) 27130660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 27230660a898545416f0fea2d717f16f75640001e38Ted Kremenek 27330660a898545416f0fea2d717f16f75640001e38Ted Kremenek std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc); 27430660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (locInfo.first.isInvalid()) 27530660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 27630660a898545416f0fea2d717f16f75640001e38Ted Kremenek offs = FileOffset(locInfo.first, locInfo.second); 27730660a898545416f0fea2d717f16f75640001e38Ted Kremenek return canInsertInOffset(loc, offs); 27830660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 27930660a898545416f0fea2d717f16f75640001e38Ted Kremenek 28030660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool Commit::canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs) { 28130660a898545416f0fea2d717f16f75640001e38Ted Kremenek for (unsigned i = 0, e = CachedEdits.size(); i != e; ++i) { 28230660a898545416f0fea2d717f16f75640001e38Ted Kremenek Edit &act = CachedEdits[i]; 28330660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (act.Kind == Act_Remove) { 28430660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (act.Offset.getFID() == Offs.getFID() && 28530660a898545416f0fea2d717f16f75640001e38Ted Kremenek Offs > act.Offset && Offs < act.Offset.getWithOffset(act.Length)) 28630660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; // position has been removed. 28730660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 28830660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 28930660a898545416f0fea2d717f16f75640001e38Ted Kremenek 29030660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (!Editor) 29130660a898545416f0fea2d717f16f75640001e38Ted Kremenek return true; 29230660a898545416f0fea2d717f16f75640001e38Ted Kremenek return Editor->canInsertInOffset(OrigLoc, Offs); 29330660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 29430660a898545416f0fea2d717f16f75640001e38Ted Kremenek 29530660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool Commit::canRemoveRange(CharSourceRange range, 29630660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset &Offs, unsigned &Len) { 29730660a898545416f0fea2d717f16f75640001e38Ted Kremenek const SourceManager &SM = SourceMgr; 29830660a898545416f0fea2d717f16f75640001e38Ted Kremenek range = Lexer::makeFileCharRange(range, SM, LangOpts); 29930660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (range.isInvalid()) 30030660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 30130660a898545416f0fea2d717f16f75640001e38Ted Kremenek 30230660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (range.getBegin().isMacroID() || range.getEnd().isMacroID()) 30330660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 3046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (SM.isInSystemHeader(range.getBegin()) || 3056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines SM.isInSystemHeader(range.getEnd())) 30630660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 30730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 30830660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (PPRec && PPRec->rangeIntersectsConditionalDirective(range.getAsRange())) 30930660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 31030660a898545416f0fea2d717f16f75640001e38Ted Kremenek 31130660a898545416f0fea2d717f16f75640001e38Ted Kremenek std::pair<FileID, unsigned> beginInfo = SM.getDecomposedLoc(range.getBegin()); 31230660a898545416f0fea2d717f16f75640001e38Ted Kremenek std::pair<FileID, unsigned> endInfo = SM.getDecomposedLoc(range.getEnd()); 31330660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (beginInfo.first != endInfo.first || 31430660a898545416f0fea2d717f16f75640001e38Ted Kremenek beginInfo.second > endInfo.second) 31530660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 31630660a898545416f0fea2d717f16f75640001e38Ted Kremenek 31730660a898545416f0fea2d717f16f75640001e38Ted Kremenek Offs = FileOffset(beginInfo.first, beginInfo.second); 31830660a898545416f0fea2d717f16f75640001e38Ted Kremenek Len = endInfo.second - beginInfo.second; 31930660a898545416f0fea2d717f16f75640001e38Ted Kremenek return true; 32030660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 32130660a898545416f0fea2d717f16f75640001e38Ted Kremenek 32230660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool Commit::canReplaceText(SourceLocation loc, StringRef text, 32330660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileOffset &Offs, unsigned &Len) { 32430660a898545416f0fea2d717f16f75640001e38Ted Kremenek assert(!text.empty()); 32530660a898545416f0fea2d717f16f75640001e38Ted Kremenek 32630660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (!canInsert(loc, Offs)) 32730660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 32830660a898545416f0fea2d717f16f75640001e38Ted Kremenek 32930660a898545416f0fea2d717f16f75640001e38Ted Kremenek // Try to load the file buffer. 33030660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool invalidTemp = false; 33130660a898545416f0fea2d717f16f75640001e38Ted Kremenek StringRef file = SourceMgr.getBufferData(Offs.getFID(), &invalidTemp); 33230660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (invalidTemp) 33330660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 33430660a898545416f0fea2d717f16f75640001e38Ted Kremenek 335af505c58222a87058fa4ac26cd8da27c141eec42Argyrios Kyrtzidis Len = text.size(); 33630660a898545416f0fea2d717f16f75640001e38Ted Kremenek return file.substr(Offs.getOffset()).startswith(text); 33730660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 33830660a898545416f0fea2d717f16f75640001e38Ted Kremenek 33930660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool Commit::isAtStartOfMacroExpansion(SourceLocation loc, 34030660a898545416f0fea2d717f16f75640001e38Ted Kremenek SourceLocation *MacroBegin) const { 34130660a898545416f0fea2d717f16f75640001e38Ted Kremenek return Lexer::isAtStartOfMacroExpansion(loc, SourceMgr, LangOpts, MacroBegin); 34230660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 34330660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool Commit::isAtEndOfMacroExpansion(SourceLocation loc, 34430660a898545416f0fea2d717f16f75640001e38Ted Kremenek SourceLocation *MacroEnd) const { 34530660a898545416f0fea2d717f16f75640001e38Ted Kremenek return Lexer::isAtEndOfMacroExpansion(loc, SourceMgr, LangOpts, MacroEnd); 34630660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 347