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