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