clang: lib/Rewrite/Rewriter.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
20#include "llvm/ADT/RewriteBuffer.h"
21#include "llvm/ADT/RewriteRope.h"
22#include "llvm/ADT/SmallVector.h"
23#include "llvm/ADT/StringRef.h"
24#include "llvm/Support/Error.h"
25#include "llvm/Support/raw_ostream.h"
26#include
27#include
28#include
29#include
30
31using namespace clang;
32using llvm::RewriteBuffer;
33
34
35
36
37
38
39
41 return c == ' ' || c == '\t' || c == '\f' || c == '\v' || c == '\r';
42}
43
44
45
50
51 FileID StartFileID, EndFileID;
52 unsigned StartOff = getLocationOffsetAndFileID(Range.getBegin(), StartFileID);
53 unsigned EndOff = getLocationOffsetAndFileID(Range.getEnd(), EndFileID);
54
55 if (StartFileID != EndFileID)
56 return -1;
57
58
59
60 std::map<FileID, RewriteBuffer>::const_iterator I =
61 RewriteBuffers.find(StartFileID);
62 if (I != RewriteBuffers.end()) {
63 const RewriteBuffer &RB = I->second;
66 }
67
68
69
70 if (Range.isTokenRange())
72
73 return EndOff-StartOff;
74}
75
78}
79
80
81
82
83
84
88 return {};
89
90 FileID StartFileID, EndFileID;
91 unsigned StartOff, EndOff;
92 StartOff = getLocationOffsetAndFileID(Range.getBegin(), StartFileID);
93 EndOff = getLocationOffsetAndFileID(Range.getEnd(), EndFileID);
94
95 if (StartFileID != EndFileID)
96 return {};
97
98
99
100 std::map<FileID, RewriteBuffer>::const_iterator I =
101 RewriteBuffers.find(StartFileID);
102 if (I == RewriteBuffers.end()) {
103
105
106
107
108 if (Range.isTokenRange())
109 EndOff +=
111 return std::string(Ptr, Ptr+EndOff-StartOff);
112 }
113
114 const RewriteBuffer &RB = I->second;
115 EndOff = RB.getMappedOffset(EndOff, true);
116 StartOff = RB.getMappedOffset(StartOff);
117
118
119
120 if (Range.isTokenRange())
122
123
124 RewriteBuffer::iterator Start = RB.begin();
125 std::advance(Start, StartOff);
126 RewriteBuffer::iterator End = Start;
127 assert(EndOff >= StartOff && "Invalid iteration distance");
128 std::advance(End, EndOff-StartOff);
129
130 return std::string(Start, End);
131}
132
135 assert(Loc.isValid() && "Invalid location");
137 FID = V.first;
138 return V.second;
139}
140
141
143 std::map<FileID, RewriteBuffer>::iterator I =
144 RewriteBuffers.lower_bound(FID);
145 if (I != RewriteBuffers.end() && I->first == FID)
146 return I->second;
147 I = RewriteBuffers.insert(I, std::make_pair(FID, RewriteBuffer()));
148
150 I->second.Initialize(MB.begin(), MB.end());
151
152 return I->second;
153}
154
155
156
158 bool InsertAfter, bool indentNewLines) {
161 unsigned StartOffs = getLocationOffsetAndFileID(Loc, FID);
162
164 if (indentNewLines && Str.contains('\n')) {
166
167 unsigned lineNo = SourceMgr->getLineNumber(FID, StartOffs) - 1;
171
172
173 StringRef indentSpace;
174 {
175 unsigned i = lineOffs;
177 ++i;
178 indentSpace = MB.substr(lineOffs, i-lineOffs);
179 }
180
182 Str.split(lines, "\n");
183
184 for (unsigned i = 0, e = lines.size(); i != e; ++i) {
185 indentedStr += lines[i];
186 if (i < e-1) {
187 indentedStr += '\n';
188 indentedStr += indentSpace;
189 }
190 }
191 Str = indentedStr.str();
192 }
193
194 getEditBuffer(FID).InsertText(StartOffs, Str, InsertAfter);
195 return false;
196}
197
201 unsigned StartOffs = getLocationOffsetAndFileID(Loc, FID);
205 getEditBuffer(FID).InsertText(StartOffs, Str, true);
206 return false;
207}
208
209
214 unsigned StartOffs = getLocationOffsetAndFileID(Start, FID);
216 return false;
217}
218
219
220
221
223 StringRef NewStr) {
226 unsigned StartOffs = getLocationOffsetAndFileID(Start, StartFileID);
227
228 getEditBuffer(StartFileID).ReplaceText(StartOffs, OrigLength, NewStr);
229 return false;
230}
231
233 if ((range.getBegin())) return true;
234 if ((range.getEnd())) return true;
235 if (replacementRange.isInvalid()) return true;
238 unsigned newLength = getRangeSize(replacementRange);
240 unsigned newOffs = getLocationOffsetAndFileID(replacementRange.getBegin(),
241 FID);
243 return ReplaceText(start, origLength, MB.substr(newOffs, newLength));
244}
245
248 if (range.isInvalid()) return true;
249 if ((range.getBegin())) return true;
250 if ((range.getEnd())) return true;
251 if ((parentIndent)) return true;
252
253 FileID StartFileID, EndFileID, parentFileID;
254 unsigned StartOff, EndOff, parentOff;
255
256 StartOff = getLocationOffsetAndFileID(range.getBegin(), StartFileID);
257 EndOff = getLocationOffsetAndFileID(range.getEnd(), EndFileID);
258 parentOff = getLocationOffsetAndFileID(parentIndent, parentFileID);
259
260 if (StartFileID != EndFileID || StartFileID != parentFileID)
261 return true;
262 if (StartOff > EndOff)
263 return true;
264
265 FileID FID = StartFileID;
267
268 unsigned parentLineNo = SourceMgr->getLineNumber(FID, parentOff) - 1;
269 unsigned startLineNo = SourceMgr->getLineNumber(FID, StartOff) - 1;
270 unsigned endLineNo = SourceMgr->getLineNumber(FID, EndOff) - 1;
271
274
275
276 unsigned parentLineOffs = Content->SourceLineCache[parentLineNo];
277 unsigned startLineOffs = Content->SourceLineCache[startLineNo];
278
279
280 StringRef parentSpace, startSpace;
281 {
282 unsigned i = parentLineOffs;
284 ++i;
285 parentSpace = MB.substr(parentLineOffs, i-parentLineOffs);
286
287 i = startLineOffs;
289 ++i;
290 startSpace = MB.substr(startLineOffs, i-startLineOffs);
291 }
292 if (parentSpace.size() >= startSpace.size())
293 return true;
294 if (!startSpace.starts_with(parentSpace))
295 return true;
296
297 StringRef indent = startSpace.substr(parentSpace.size());
298
299
301 for (unsigned lineNo = startLineNo; lineNo <= endLineNo; ++lineNo) {
303 unsigned i = offs;
305 ++i;
306 StringRef origIndent = MB.substr(offs, i-offs);
307 if (origIndent.starts_with(startSpace))
308 RB.InsertText(offs, indent, false);
309 }
310
311 return false;
312}
313
315 bool AllWritten = true;
317 unsigned OverwriteFailure = Diag.getCustomDiagID(
323 if (auto Error = llvm::writeToOutput(Path, [&](llvm::raw_ostream &OS) {
324 I->second.write(OS);
325 return llvm::Error::success();
326 })) {
327 Diag.Report(OverwriteFailure)
328 << Entry->getName() << llvm::toString(std::move(Error));
329 AllWritten = false;
330 }
331 }
332 return !AllWritten;
333}
Defines the Diagnostic-related interfaces.
Defines the Diagnostic IDs-related interfaces.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
static bool isWhitespaceExceptNL(unsigned char c)
Return true if this character is non-new-line whitespace: ' ', '\t', '\f', '\v', '\r'.
Defines the clang::SourceLocation class and associated facilities.
Defines the SourceManager interface.
__device__ __2f16 float c
Represents a character-granular source range.
static CharSourceRange getTokenRange(SourceRange R)
StringRef getName() const
The name of this FileEntry.
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
bool makeAbsolutePath(SmallVectorImpl< char > &Path) const
Makes Path absolute taking into account FileSystemOptions and the working directory option.
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 ...
std::map< FileID, llvm::RewriteBuffer >::iterator buffer_iterator
int getRangeSize(SourceRange Range, RewriteOptions opts=RewriteOptions()) const
getRangeSize - Return the size in bytes of the specified range if they are in the same file.
bool InsertText(SourceLocation Loc, StringRef Str, bool InsertAfter=true, bool indentNewLines=false)
InsertText - Insert the specified string at the specified location in the original buffer.
bool RemoveText(SourceLocation Start, unsigned Length, RewriteOptions opts=RewriteOptions())
RemoveText - Remove the specified text region.
static bool isRewritable(SourceLocation Loc)
isRewritable - Return true if this location is a raw file location, which is rewritable.
buffer_iterator buffer_end()
SourceManager & getSourceMgr() const
buffer_iterator buffer_begin()
std::string getRewrittenText(CharSourceRange Range) const
getRewrittenText - Return the rewritten form of the text in the specified range.
bool IncreaseIndentation(CharSourceRange range, SourceLocation parentIndent)
Increase indentation for the lines between the given source range.
bool InsertTextAfterToken(SourceLocation Loc, StringRef Str)
Insert the specified string after the token in the specified location.
llvm::RewriteBuffer & getEditBuffer(FileID FID)
getEditBuffer - This is like getRewriteBufferFor, but always returns a buffer, and allows you to writ...
bool overwriteChangedFiles()
overwriteChangedFiles - Save all changed files to disk.
bool ReplaceText(SourceLocation Start, unsigned OrigLength, StringRef NewStr)
ReplaceText - This method replaces a range of characters in the input buffer with a new string.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
DiagnosticsEngine & getDiagnostics() const
OptionalFileEntryRef getFileEntryRefForID(FileID FID) const
Returns the FileEntryRef for the provided FileID.
StringRef getBufferData(FileID FID, bool *Invalid=nullptr) const
Return a StringRef to the source buffer data for the specified FileID.
FileManager & getFileManager() const
const char * getCharacterData(SourceLocation SL, bool *Invalid=nullptr) const
Return a pointer to the start of the specified location in the appropriate spelling MemoryBuffer.
unsigned getLineNumber(FileID FID, unsigned FilePos, bool *Invalid=nullptr) const
Given a SourceLocation, return the spelling line number for the position indicated.
std::pair< FileID, unsigned > getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
const SrcMgr::SLocEntry & getSLocEntry(FileID FID, bool *Invalid=nullptr) const
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
One instance of this struct is kept for every file loaded or used.
LineOffsetMapping SourceLineCache
A bump pointer allocated array of offsets for each source line.
const ContentCache & getContentCache() const
const FileInfo & getFile() const
The JSON file list parser is used to communicate input to InstallAPI.
bool IncludeInsertsAtBeginOfRange
Given a source range, true to include previous inserts at the beginning of the range as part of the r...
bool IncludeInsertsAtEndOfRange
Given a source range, true to include previous inserts at the end of the range as part of the range i...
bool RemoveLineIfEmpty
If true and removing some text leaves a blank line also remove the empty line (false by default).