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 19namespace clang { 20 21class LangOptions; 22class PPConditionalDirectiveRecord; 23class SourceManager; 24 25namespace edit { 26 27class EditedSource; 28 29class Commit { 30public: 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 51private: 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 62public: 63 explicit Commit(EditedSource &Editor); 64 Commit(const SourceManager &SM, const LangOptions &LangOpts, 65 const PPConditionalDirectiveRecord *PPRec = nullptr) 66 : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec) {} 67 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 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 102 bool insertWrap(StringRef before, SourceRange TokenRange, StringRef after) { 103 return insertWrap(before, CharSourceRange::getTokenRange(TokenRange), after); 104 } 105 106 bool remove(SourceRange TokenRange) { 107 return remove(CharSourceRange::getTokenRange(TokenRange)); 108 } 109 110 bool replace(SourceRange TokenRange, StringRef text) { 111 return replace(CharSourceRange::getTokenRange(TokenRange), text); 112 } 113 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 121 edit_iterator edit_begin() const { return CachedEdits.begin(); } 122 edit_iterator edit_end() const { return CachedEdits.end(); } 123 124private: 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