1 //===- Commit.h - A unit of edits -------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_CLANG_EDIT_COMMIT_H 10 #define LLVM_CLANG_EDIT_COMMIT_H 11 12 #include "clang/Basic/LLVM.h" 13 #include "clang/Basic/SourceLocation.h" 14 #include "clang/Edit/FileOffset.h" 15 #include "llvm/ADT/SmallVector.h" 16 #include "llvm/ADT/StringRef.h" 17 #include "llvm/Support/Allocator.h" 18 19 namespace clang { 20 21 class LangOptions; 22 class PPConditionalDirectiveRecord; 23 class SourceManager; 24 25 namespace edit { 26 27 class EditedSource; 28 29 class Commit { 30 public: 31 enum EditKind { 32 Act_Insert, 33 Act_InsertFromRange, 34 Act_Remove 35 }; 36 37 struct Edit { 38 EditKind Kind; 39 StringRef Text; 40 SourceLocation OrigLoc; 41 FileOffset Offset; 42 FileOffset InsertFromRangeOffs; 43 unsigned Length; 44 bool BeforePrev; 45 46 SourceLocation getFileLocation(SourceManager &SM) const; 47 CharSourceRange getFileRange(SourceManager &SM) const; 48 CharSourceRange getInsertFromRange(SourceManager &SM) const; 49 }; 50 51 private: 52 const SourceManager &SourceMgr; 53 const LangOptions &LangOpts; 54 const PPConditionalDirectiveRecord *PPRec; 55 EditedSource *Editor = nullptr; 56 57 bool IsCommitable = true; 58 SmallVector<Edit, 8> CachedEdits; 59 60 llvm::BumpPtrAllocator StrAlloc; 61 62 public: 63 explicit Commit(EditedSource &Editor); 64 Commit(const SourceManager &SM, const LangOptions &LangOpts, 65 const PPConditionalDirectiveRecord *PPRec = nullptr) SourceMgr(SM)66 : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec) {} 67 isCommitable()68 bool isCommitable() const { return IsCommitable; } 69 70 bool insert(SourceLocation loc, StringRef text, bool afterToken = false, 71 bool beforePreviousInsertions = false); 72 73 bool insertAfterToken(SourceLocation loc, StringRef text, 74 bool beforePreviousInsertions = false) { 75 return insert(loc, text, /*afterToken=*/true, beforePreviousInsertions); 76 } 77 insertBefore(SourceLocation loc,StringRef text)78 bool insertBefore(SourceLocation loc, StringRef text) { 79 return insert(loc, text, /*afterToken=*/false, 80 /*beforePreviousInsertions=*/true); 81 } 82 83 bool insertFromRange(SourceLocation loc, CharSourceRange range, 84 bool afterToken = false, 85 bool beforePreviousInsertions = false); 86 bool insertWrap(StringRef before, CharSourceRange range, StringRef after); 87 88 bool remove(CharSourceRange range); 89 90 bool replace(CharSourceRange range, StringRef text); 91 bool replaceWithInner(CharSourceRange range, CharSourceRange innerRange); 92 bool replaceText(SourceLocation loc, StringRef text, 93 StringRef replacementText); 94 95 bool insertFromRange(SourceLocation loc, SourceRange TokenRange, 96 bool afterToken = false, 97 bool beforePreviousInsertions = false) { 98 return insertFromRange(loc, CharSourceRange::getTokenRange(TokenRange), 99 afterToken, beforePreviousInsertions); 100 } 101 insertWrap(StringRef before,SourceRange TokenRange,StringRef after)102 bool insertWrap(StringRef before, SourceRange TokenRange, StringRef after) { 103 return insertWrap(before, CharSourceRange::getTokenRange(TokenRange), after); 104 } 105 remove(SourceRange TokenRange)106 bool remove(SourceRange TokenRange) { 107 return remove(CharSourceRange::getTokenRange(TokenRange)); 108 } 109 replace(SourceRange TokenRange,StringRef text)110 bool replace(SourceRange TokenRange, StringRef text) { 111 return replace(CharSourceRange::getTokenRange(TokenRange), text); 112 } 113 replaceWithInner(SourceRange TokenRange,SourceRange TokenInnerRange)114 bool replaceWithInner(SourceRange TokenRange, SourceRange TokenInnerRange) { 115 return replaceWithInner(CharSourceRange::getTokenRange(TokenRange), 116 CharSourceRange::getTokenRange(TokenInnerRange)); 117 } 118 119 using edit_iterator = SmallVectorImpl<Edit>::const_iterator; 120 edit_begin()121 edit_iterator edit_begin() const { return CachedEdits.begin(); } edit_end()122 edit_iterator edit_end() const { return CachedEdits.end(); } 123 124 private: 125 void addInsert(SourceLocation OrigLoc, 126 FileOffset Offs, StringRef text, bool beforePreviousInsertions); 127 void addInsertFromRange(SourceLocation OrigLoc, FileOffset Offs, 128 FileOffset RangeOffs, unsigned RangeLen, 129 bool beforePreviousInsertions); 130 void addRemove(SourceLocation OrigLoc, FileOffset Offs, unsigned Len); 131 132 bool canInsert(SourceLocation loc, FileOffset &Offset); 133 bool canInsertAfterToken(SourceLocation loc, FileOffset &Offset, 134 SourceLocation &AfterLoc); 135 bool canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs); 136 bool canRemoveRange(CharSourceRange range, FileOffset &Offs, unsigned &Len); 137 bool canReplaceText(SourceLocation loc, StringRef text, 138 FileOffset &Offs, unsigned &Len); 139 140 void commitInsert(FileOffset offset, StringRef text, 141 bool beforePreviousInsertions); 142 void commitRemove(FileOffset offset, unsigned length); 143 144 bool isAtStartOfMacroExpansion(SourceLocation loc, 145 SourceLocation *MacroBegin = nullptr) const; 146 bool isAtEndOfMacroExpansion(SourceLocation loc, 147 SourceLocation *MacroEnd = nullptr) const; 148 }; 149 150 } // namespace edit 151 152 } // namespace clang 153 154 #endif // LLVM_CLANG_EDIT_COMMIT_H 155