1 | |
2 | |
3 | |
4 | |
5 | |
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 | |
19 | namespace clang { |
20 | |
21 | class LangOptions; |
22 | class PPConditionalDirectiveRecord; |
23 | class SourceManager; |
24 | |
25 | namespace edit { |
26 | |
27 | class EditedSource; |
28 | |
29 | class Commit { |
30 | public: |
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 | |
51 | private: |
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 | |
62 | public: |
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, , beforePreviousInsertions); |
76 | } |
77 | |
78 | bool insertBefore(SourceLocation loc, StringRef text) { |
79 | return insert(loc, text, , |
80 | ); |
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 | |
124 | private: |
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 | } |
151 | |
152 | } |
153 | |
154 | #endif |
155 | |