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