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 const bool ForceCommitInSystemHeader; 54 bool IsCommitable; 55 SmallVector<Edit, 8> CachedEdits; 56 57 llvm::BumpPtrAllocator StrAlloc; 58 59 public: 60 explicit Commit(EditedSource &Editor); 61 Commit(const SourceManager &SM, const LangOptions &LangOpts, 62 const PPConditionalDirectiveRecord *PPRec = 0) SourceMgr(SM)63 : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec), Editor(0), 64 ForceCommitInSystemHeader(true), IsCommitable(true) { } 65 isCommitable()66 bool isCommitable() const { return IsCommitable; } 67 68 bool insert(SourceLocation loc, StringRef text, bool afterToken = false, 69 bool beforePreviousInsertions = false); 70 bool insertAfterToken(SourceLocation loc, StringRef text, 71 bool beforePreviousInsertions = false) { 72 return insert(loc, text, /*afterToken=*/true, beforePreviousInsertions); 73 } insertBefore(SourceLocation loc,StringRef text)74 bool insertBefore(SourceLocation loc, StringRef text) { 75 return insert(loc, text, /*afterToken=*/false, 76 /*beforePreviousInsertions=*/true); 77 } 78 bool insertFromRange(SourceLocation loc, CharSourceRange range, 79 bool afterToken = false, 80 bool beforePreviousInsertions = false); 81 bool insertWrap(StringRef before, CharSourceRange range, StringRef after); 82 83 bool remove(CharSourceRange range); 84 85 bool replace(CharSourceRange range, StringRef text); 86 bool replaceWithInner(CharSourceRange range, CharSourceRange innerRange); 87 bool replaceText(SourceLocation loc, StringRef text, 88 StringRef replacementText); 89 90 bool insertFromRange(SourceLocation loc, SourceRange TokenRange, 91 bool afterToken = false, 92 bool beforePreviousInsertions = false) { 93 return insertFromRange(loc, CharSourceRange::getTokenRange(TokenRange), 94 afterToken, beforePreviousInsertions); 95 } insertWrap(StringRef before,SourceRange TokenRange,StringRef after)96 bool insertWrap(StringRef before, SourceRange TokenRange, StringRef after) { 97 return insertWrap(before, CharSourceRange::getTokenRange(TokenRange), after); 98 } remove(SourceRange TokenRange)99 bool remove(SourceRange TokenRange) { 100 return remove(CharSourceRange::getTokenRange(TokenRange)); 101 } replace(SourceRange TokenRange,StringRef text)102 bool replace(SourceRange TokenRange, StringRef text) { 103 return replace(CharSourceRange::getTokenRange(TokenRange), text); 104 } replaceWithInner(SourceRange TokenRange,SourceRange TokenInnerRange)105 bool replaceWithInner(SourceRange TokenRange, SourceRange TokenInnerRange) { 106 return replaceWithInner(CharSourceRange::getTokenRange(TokenRange), 107 CharSourceRange::getTokenRange(TokenInnerRange)); 108 } 109 110 typedef SmallVectorImpl<Edit>::const_iterator edit_iterator; edit_begin()111 edit_iterator edit_begin() const { return CachedEdits.begin(); } edit_end()112 edit_iterator edit_end() const { return CachedEdits.end(); } 113 114 private: 115 void addInsert(SourceLocation OrigLoc, 116 FileOffset Offs, StringRef text, bool beforePreviousInsertions); 117 void addInsertFromRange(SourceLocation OrigLoc, FileOffset Offs, 118 FileOffset RangeOffs, unsigned RangeLen, 119 bool beforePreviousInsertions); 120 void addRemove(SourceLocation OrigLoc, FileOffset Offs, unsigned Len); 121 122 bool canInsert(SourceLocation loc, FileOffset &Offset); 123 bool canInsertAfterToken(SourceLocation loc, FileOffset &Offset, 124 SourceLocation &AfterLoc); 125 bool canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs); 126 bool canRemoveRange(CharSourceRange range, FileOffset &Offs, unsigned &Len); 127 bool canReplaceText(SourceLocation loc, StringRef text, 128 FileOffset &Offs, unsigned &Len); 129 130 void commitInsert(FileOffset offset, StringRef text, 131 bool beforePreviousInsertions); 132 void commitRemove(FileOffset offset, unsigned length); 133 134 bool isAtStartOfMacroExpansion(SourceLocation loc, 135 SourceLocation *MacroBegin = 0) const; 136 bool isAtEndOfMacroExpansion(SourceLocation loc, 137 SourceLocation *MacroEnd = 0) const; 138 copyString(StringRef str)139 StringRef copyString(StringRef str) { 140 char *buf = StrAlloc.Allocate<char>(str.size()); 141 std::memcpy(buf, str.data(), str.size()); 142 return StringRef(buf, str.size()); 143 } 144 }; 145 146 } 147 148 } // end namespace clang 149 150 #endif 151