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