10b57cec5SDimitry Andric //===- Commit.h - A unit of edits -------------------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #ifndef LLVM_CLANG_EDIT_COMMIT_H 100b57cec5SDimitry Andric #define LLVM_CLANG_EDIT_COMMIT_H 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #include "clang/Basic/LLVM.h" 130b57cec5SDimitry Andric #include "clang/Basic/SourceLocation.h" 140b57cec5SDimitry Andric #include "clang/Edit/FileOffset.h" 150b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 160b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 170b57cec5SDimitry Andric #include "llvm/Support/Allocator.h" 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric namespace clang { 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric class LangOptions; 220b57cec5SDimitry Andric class PPConditionalDirectiveRecord; 230b57cec5SDimitry Andric class SourceManager; 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric namespace edit { 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric class EditedSource; 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric class Commit { 300b57cec5SDimitry Andric public: 310b57cec5SDimitry Andric enum EditKind { 320b57cec5SDimitry Andric Act_Insert, 330b57cec5SDimitry Andric Act_InsertFromRange, 340b57cec5SDimitry Andric Act_Remove 350b57cec5SDimitry Andric }; 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric struct Edit { 380b57cec5SDimitry Andric EditKind Kind; 390b57cec5SDimitry Andric StringRef Text; 400b57cec5SDimitry Andric SourceLocation OrigLoc; 410b57cec5SDimitry Andric FileOffset Offset; 420b57cec5SDimitry Andric FileOffset InsertFromRangeOffs; 430b57cec5SDimitry Andric unsigned Length; 440b57cec5SDimitry Andric bool BeforePrev; 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric SourceLocation getFileLocation(SourceManager &SM) const; 470b57cec5SDimitry Andric CharSourceRange getFileRange(SourceManager &SM) const; 480b57cec5SDimitry Andric CharSourceRange getInsertFromRange(SourceManager &SM) const; 490b57cec5SDimitry Andric }; 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric private: 520b57cec5SDimitry Andric const SourceManager &SourceMgr; 530b57cec5SDimitry Andric const LangOptions &LangOpts; 540b57cec5SDimitry Andric const PPConditionalDirectiveRecord *PPRec; 550b57cec5SDimitry Andric EditedSource *Editor = nullptr; 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric bool IsCommitable = true; 580b57cec5SDimitry Andric SmallVector<Edit, 8> CachedEdits; 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric llvm::BumpPtrAllocator StrAlloc; 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric public: 630b57cec5SDimitry Andric explicit Commit(EditedSource &Editor); 640b57cec5SDimitry Andric Commit(const SourceManager &SM, const LangOptions &LangOpts, 650b57cec5SDimitry Andric const PPConditionalDirectiveRecord *PPRec = nullptr) SourceMgr(SM)660b57cec5SDimitry Andric : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec) {} 670b57cec5SDimitry Andric isCommitable()680b57cec5SDimitry Andric bool isCommitable() const { return IsCommitable; } 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric bool insert(SourceLocation loc, StringRef text, bool afterToken = false, 710b57cec5SDimitry Andric bool beforePreviousInsertions = false); 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric bool insertAfterToken(SourceLocation loc, StringRef text, 740b57cec5SDimitry Andric bool beforePreviousInsertions = false) { 750b57cec5SDimitry Andric return insert(loc, text, /*afterToken=*/true, beforePreviousInsertions); 760b57cec5SDimitry Andric } 770b57cec5SDimitry Andric insertBefore(SourceLocation loc,StringRef text)780b57cec5SDimitry Andric bool insertBefore(SourceLocation loc, StringRef text) { 790b57cec5SDimitry Andric return insert(loc, text, /*afterToken=*/false, 800b57cec5SDimitry Andric /*beforePreviousInsertions=*/true); 810b57cec5SDimitry Andric } 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric bool insertFromRange(SourceLocation loc, CharSourceRange range, 840b57cec5SDimitry Andric bool afterToken = false, 850b57cec5SDimitry Andric bool beforePreviousInsertions = false); 860b57cec5SDimitry Andric bool insertWrap(StringRef before, CharSourceRange range, StringRef after); 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric bool remove(CharSourceRange range); 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric bool replace(CharSourceRange range, StringRef text); 910b57cec5SDimitry Andric bool replaceWithInner(CharSourceRange range, CharSourceRange innerRange); 920b57cec5SDimitry Andric bool replaceText(SourceLocation loc, StringRef text, 930b57cec5SDimitry Andric StringRef replacementText); 940b57cec5SDimitry Andric 950b57cec5SDimitry Andric bool insertFromRange(SourceLocation loc, SourceRange TokenRange, 960b57cec5SDimitry Andric bool afterToken = false, 970b57cec5SDimitry Andric bool beforePreviousInsertions = false) { 980b57cec5SDimitry Andric return insertFromRange(loc, CharSourceRange::getTokenRange(TokenRange), 990b57cec5SDimitry Andric afterToken, beforePreviousInsertions); 1000b57cec5SDimitry Andric } 1010b57cec5SDimitry Andric insertWrap(StringRef before,SourceRange TokenRange,StringRef after)1020b57cec5SDimitry Andric bool insertWrap(StringRef before, SourceRange TokenRange, StringRef after) { 1030b57cec5SDimitry Andric return insertWrap(before, CharSourceRange::getTokenRange(TokenRange), after); 1040b57cec5SDimitry Andric } 1050b57cec5SDimitry Andric remove(SourceRange TokenRange)1060b57cec5SDimitry Andric bool remove(SourceRange TokenRange) { 1070b57cec5SDimitry Andric return remove(CharSourceRange::getTokenRange(TokenRange)); 1080b57cec5SDimitry Andric } 1090b57cec5SDimitry Andric replace(SourceRange TokenRange,StringRef text)1100b57cec5SDimitry Andric bool replace(SourceRange TokenRange, StringRef text) { 1110b57cec5SDimitry Andric return replace(CharSourceRange::getTokenRange(TokenRange), text); 1120b57cec5SDimitry Andric } 1130b57cec5SDimitry Andric replaceWithInner(SourceRange TokenRange,SourceRange TokenInnerRange)1140b57cec5SDimitry Andric bool replaceWithInner(SourceRange TokenRange, SourceRange TokenInnerRange) { 1150b57cec5SDimitry Andric return replaceWithInner(CharSourceRange::getTokenRange(TokenRange), 1160b57cec5SDimitry Andric CharSourceRange::getTokenRange(TokenInnerRange)); 1170b57cec5SDimitry Andric } 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric using edit_iterator = SmallVectorImpl<Edit>::const_iterator; 1200b57cec5SDimitry Andric edit_begin()1210b57cec5SDimitry Andric edit_iterator edit_begin() const { return CachedEdits.begin(); } edit_end()1220b57cec5SDimitry Andric edit_iterator edit_end() const { return CachedEdits.end(); } 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric private: 1250b57cec5SDimitry Andric void addInsert(SourceLocation OrigLoc, 1260b57cec5SDimitry Andric FileOffset Offs, StringRef text, bool beforePreviousInsertions); 1270b57cec5SDimitry Andric void addInsertFromRange(SourceLocation OrigLoc, FileOffset Offs, 1280b57cec5SDimitry Andric FileOffset RangeOffs, unsigned RangeLen, 1290b57cec5SDimitry Andric bool beforePreviousInsertions); 1300b57cec5SDimitry Andric void addRemove(SourceLocation OrigLoc, FileOffset Offs, unsigned Len); 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric bool canInsert(SourceLocation loc, FileOffset &Offset); 1330b57cec5SDimitry Andric bool canInsertAfterToken(SourceLocation loc, FileOffset &Offset, 1340b57cec5SDimitry Andric SourceLocation &AfterLoc); 1350b57cec5SDimitry Andric bool canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs); 1360b57cec5SDimitry Andric bool canRemoveRange(CharSourceRange range, FileOffset &Offs, unsigned &Len); 1370b57cec5SDimitry Andric bool canReplaceText(SourceLocation loc, StringRef text, 1380b57cec5SDimitry Andric FileOffset &Offs, unsigned &Len); 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric void commitInsert(FileOffset offset, StringRef text, 1410b57cec5SDimitry Andric bool beforePreviousInsertions); 1420b57cec5SDimitry Andric void commitRemove(FileOffset offset, unsigned length); 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric bool isAtStartOfMacroExpansion(SourceLocation loc, 1450b57cec5SDimitry Andric SourceLocation *MacroBegin = nullptr) const; 1460b57cec5SDimitry Andric bool isAtEndOfMacroExpansion(SourceLocation loc, 1470b57cec5SDimitry Andric SourceLocation *MacroEnd = nullptr) const; 1480b57cec5SDimitry Andric }; 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric } // namespace edit 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric } // namespace clang 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric #endif // LLVM_CLANG_EDIT_COMMIT_H 155