clang: lib/Edit/Commit.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
17#include "llvm/ADT/StringRef.h"
18#include
19#include
20
21using namespace clang;
22using namespace edit;
23
28 return Loc;
29}
30
34}
35
37 SourceLocation Loc = SM.getLocForStartOfFile(InsertFromRangeOffs.getFID());
41}
42
44 : SourceMgr(Editor.getSourceManager()), LangOpts(Editor.getLangOpts()),
45 PPRec(Editor.getPPCondDirectiveRecord()),
46 Editor(&Editor) {}
47
49 bool afterToken, bool beforePreviousInsertions) {
50 if (text.empty())
51 return true;
52
54 if ((!afterToken && !canInsert(loc, Offs)) ||
55 ( afterToken && !canInsertAfterToken(loc, Offs, loc))) {
56 IsCommitable = false;
57 return false;
58 }
59
60 addInsert(loc, Offs, text, beforePreviousInsertions);
61 return true;
62}
63
66 bool afterToken, bool beforePreviousInsertions) {
68 unsigned RangeLen;
69 if (!canRemoveRange(range, RangeOffs, RangeLen)) {
70 IsCommitable = false;
71 return false;
72 }
73
75 if ((!afterToken && !canInsert(loc, Offs)) ||
76 ( afterToken && !canInsertAfterToken(loc, Offs, loc))) {
77 IsCommitable = false;
78 return false;
79 }
80
81 if (PPRec &&
83 IsCommitable = false;
84 return false;
85 }
86
87 addInsertFromRange(loc, Offs, RangeOffs, RangeLen, beforePreviousInsertions);
88 return true;
89}
90
93 unsigned Len;
94 if (!canRemoveRange(range, Offs, Len)) {
95 IsCommitable = false;
96 return false;
97 }
98
99 addRemove(range.getBegin(), Offs, Len);
100 return true;
101}
102
104 StringRef after) {
105 bool commitableBefore = insert(range.getBegin(), before, false,
106 true);
107 bool commitableAfter;
108 if (range.isTokenRange())
110 else
111 commitableAfter = insert(range.getEnd(), after);
112
113 return commitableBefore && commitableAfter;
114}
115
117 if (text.empty())
118 return remove(range);
119
121 unsigned Len;
122 if (!canInsert(range.getBegin(), Offs) || !canRemoveRange(range, Offs, Len)) {
123 IsCommitable = false;
124 return false;
125 }
126
127 addRemove(range.getBegin(), Offs, Len);
128 addInsert(range.getBegin(), Offs, text, false);
129 return true;
130}
131
135 unsigned OuterLen;
136 if (!canRemoveRange(range, OuterBegin, OuterLen)) {
137 IsCommitable = false;
138 return false;
139 }
140
142 unsigned InnerLen;
143 if (!canRemoveRange(replacementRange, InnerBegin, InnerLen)) {
144 IsCommitable = false;
145 return false;
146 }
147
150 if (OuterBegin.getFID() != InnerBegin.getFID() ||
151 InnerBegin < OuterBegin ||
152 InnerBegin > OuterEnd ||
153 InnerEnd > OuterEnd) {
154 IsCommitable = false;
155 return false;
156 }
157
158 addRemove(range.getBegin(),
160 addRemove(replacementRange.getEnd(),
162 return true;
163}
164
166 StringRef replacementText) {
167 if (text.empty() || replacementText.empty())
168 return true;
169
171 unsigned Len;
172 if (!canReplaceText(loc, replacementText, Offs, Len)) {
173 IsCommitable = false;
174 return false;
175 }
176
177 addRemove(loc, Offs, Len);
178 addInsert(loc, Offs, text, false);
179 return true;
180}
181
183 bool beforePreviousInsertions) {
184 if (text.empty())
185 return;
186
187 Edit data;
189 data.OrigLoc = OrigLoc;
190 data.Offset = Offs;
191 data.Text = text.copy(StrAlloc);
192 data.BeforePrev = beforePreviousInsertions;
193 CachedEdits.push_back(data);
194}
195
197 FileOffset RangeOffs, unsigned RangeLen,
198 bool beforePreviousInsertions) {
199 if (RangeLen == 0)
200 return;
201
202 Edit data;
204 data.OrigLoc = OrigLoc;
205 data.Offset = Offs;
206 data.InsertFromRangeOffs = RangeOffs;
207 data.Length = RangeLen;
208 data.BeforePrev = beforePreviousInsertions;
209 CachedEdits.push_back(data);
210}
211
214 if (Len == 0)
215 return;
216
217 Edit data;
219 data.OrigLoc = OrigLoc;
220 data.Offset = Offs;
221 data.Length = Len;
222 CachedEdits.push_back(data);
223}
224
227 return false;
228
230 isAtStartOfMacroExpansion(loc, &loc);
231
233 loc = SM.getTopMacroCallerLoc(loc);
234
236 if (!isAtStartOfMacroExpansion(loc, &loc))
237 return false;
238
239 if (SM.isInSystemHeader(loc))
240 return false;
241
242 std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc);
243 if (locInfo.first.isInvalid())
244 return false;
245 offs = FileOffset(locInfo.first, locInfo.second);
246 return canInsertInOffset(loc, offs);
247}
248
252
253 return false;
254
258
260 isAtEndOfMacroExpansion(loc, &loc);
261
263 loc = SM.getTopMacroCallerLoc(loc);
264
266 if (!isAtEndOfMacroExpansion(loc, &loc))
267 return false;
268
269 if (SM.isInSystemHeader(loc))
270 return false;
271
274 return false;
275
276 std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc);
277 if (locInfo.first.isInvalid())
278 return false;
279 offs = FileOffset(locInfo.first, locInfo.second);
280 return canInsertInOffset(loc, offs);
281}
282
284 for (const auto &act : CachedEdits)
286 if (act.Offset.getFID() == Offs.getFID() &&
287 Offs > act.Offset && Offs < act.Offset.getWithOffset(act.Length))
288 return false;
289 }
290
291 if (!Editor)
292 return true;
294}
295
300 if (range.isInvalid())
301 return false;
302
303 if (range.getBegin().isMacroID() || range.getEnd().isMacroID())
304 return false;
305 if (SM.isInSystemHeader(range.getBegin()) ||
306 SM.isInSystemHeader(range.getEnd()))
307 return false;
308
310 return false;
311
312 std::pair<FileID, unsigned> beginInfo = SM.getDecomposedLoc(range.getBegin());
313 std::pair<FileID, unsigned> endInfo = SM.getDecomposedLoc(range.getEnd());
314 if (beginInfo.first != endInfo.first ||
315 beginInfo.second > endInfo.second)
316 return false;
317
318 Offs = FileOffset(beginInfo.first, beginInfo.second);
319 Len = endInfo.second - beginInfo.second;
320 return true;
321}
322
323bool Commit::canReplaceText(SourceLocation loc, StringRef text,
325 assert(.empty());
326
327 if (!canInsert(loc, Offs))
328 return false;
329
330
331 bool invalidTemp = false;
333 if (invalidTemp)
334 return false;
335
336 Len = text.size();
337 return file.substr(Offs.getOffset()).starts_with(text);
338}
339
340bool Commit::isAtStartOfMacroExpansion(SourceLocation loc,
343}
344
345bool Commit::isAtEndOfMacroExpansion(SourceLocation loc,
348}
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Defines the clang::SourceLocation class and associated facilities.
Defines the SourceManager interface.
Represents a character-granular source range.
static CharSourceRange getCharRange(SourceRange R)
SourceLocation getEnd() const
static bool isAtStartOfMacroExpansion(SourceLocation loc, const SourceManager &SM, const LangOptions &LangOpts, SourceLocation *MacroBegin=nullptr)
Returns true if the given MacroID location points at the first token of the macro expansion.
static bool isAtEndOfMacroExpansion(SourceLocation loc, const SourceManager &SM, const LangOptions &LangOpts, SourceLocation *MacroEnd=nullptr)
Returns true if the given MacroID location points at the last token of the macro expansion.
static CharSourceRange makeFileCharRange(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts)
Accepts a range and returns a character range with file locations.
static unsigned MeasureTokenLength(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
MeasureTokenLength - Relex the token at the specified location and return its length in bytes in the ...
static SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset, const SourceManager &SM, const LangOptions &LangOpts)
Computes the source location just past the end of the token at this source location.
bool areInDifferentConditionalDirectiveRegion(SourceLocation LHS, SourceLocation RHS) const
Returns true if the given locations are in different regions, separated by conditional directive bloc...
bool rangeIntersectsConditionalDirective(SourceRange Range) const
Returns true if the given range intersects with a conditional directive.
Encodes a location in the source.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
This class handles loading and caching of source files into memory.
StringRef getBufferData(FileID FID, bool *Invalid=nullptr) const
Return a StringRef to the source buffer data for the specified FileID.
SourceLocation getSpellingLoc(SourceLocation Loc) const
Given a SourceLocation object, return the spelling location referenced by the ID.
bool replaceWithInner(CharSourceRange range, CharSourceRange innerRange)
bool insertWrap(StringRef before, CharSourceRange range, StringRef after)
bool insertFromRange(SourceLocation loc, CharSourceRange range, bool afterToken=false, bool beforePreviousInsertions=false)
bool insert(SourceLocation loc, StringRef text, bool afterToken=false, bool beforePreviousInsertions=false)
Commit(EditedSource &Editor)
bool insertAfterToken(SourceLocation loc, StringRef text, bool beforePreviousInsertions=false)
bool remove(CharSourceRange range)
bool replace(CharSourceRange range, StringRef text)
bool replaceText(SourceLocation loc, StringRef text, StringRef replacementText)
bool canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs)
FileOffset getWithOffset(unsigned offset) const
unsigned getOffset() const
RangeSelector range(RangeSelector Begin, RangeSelector End)
DEPRECATED. Use enclose.
EditGenerator edit(ASTEdit E)
Generates a single (specified) edit.
The JSON file list parser is used to communicate input to InstallAPI.
SourceLocation getFileLocation(SourceManager &SM) const
CharSourceRange getFileRange(SourceManager &SM) const
CharSourceRange getInsertFromRange(SourceManager &SM) const