23#include "llvm/ADT/SmallString.h"
24#include "llvm/ADT/SmallVector.h"
25#include "llvm/ADT/StringRef.h"
26#include "llvm/Support/FileSystem.h"
27#include "llvm/Support/raw_ostream.h"
32#include <system_error>
62 bool removeLineIfEmpty) {
64 if (Size == 0)
return;
66 unsigned RealOffset = getMappedOffset(OrigOffset,
true);
67 assert(RealOffset+Size <= Buffer.
size() &&
"Invalid location");
70 Buffer.
erase(RealOffset, Size);
73 AddReplaceDelta(OrigOffset, -Size);
75 if (removeLineIfEmpty) {
80 unsigned curLineStartOffs = 0;
82 for (
unsigned i = 0; i != RealOffset; ++i) {
86 curLineStartOffs = i + 1;
91 unsigned lineSize = 0;
97 if (posI !=
end() && *posI ==
'\n') {
98 Buffer.
erase(curLineStartOffs, lineSize + 1);
110 AddReplaceDelta(curLineStartOffs, -(lineSize + 1));
118 if (Str.empty())
return;
120 unsigned RealOffset = getMappedOffset(OrigOffset, InsertAfter);
121 Buffer.
insert(RealOffset, Str.begin(), Str.end());
124 AddInsertDelta(OrigOffset, Str.size());
132 unsigned RealOffset = getMappedOffset(OrigOffset,
true);
133 Buffer.
erase(RealOffset, OrigLength);
134 Buffer.
insert(RealOffset, NewStr.begin(), NewStr.end());
135 if (OrigLength != NewStr.size())
136 AddReplaceDelta(OrigOffset, NewStr.size() - OrigLength);
150 FileID StartFileID, EndFileID;
151 unsigned StartOff = getLocationOffsetAndFileID(Range.getBegin(), StartFileID);
152 unsigned EndOff = getLocationOffsetAndFileID(Range.getEnd(), EndFileID);
154 if (StartFileID != EndFileID)
159 std::map<FileID, RewriteBuffer>::const_iterator I =
160 RewriteBuffers.find(StartFileID);
161 if (I != RewriteBuffers.end()) {
169 if (Range.isTokenRange())
172 return EndOff-StartOff;
189 FileID StartFileID, EndFileID;
190 unsigned StartOff, EndOff;
191 StartOff = getLocationOffsetAndFileID(Range.getBegin(), StartFileID);
192 EndOff = getLocationOffsetAndFileID(Range.getEnd(), EndFileID);
194 if (StartFileID != EndFileID)
199 std::map<FileID, RewriteBuffer>::const_iterator I =
200 RewriteBuffers.find(StartFileID);
201 if (I == RewriteBuffers.end()) {
207 if (Range.isTokenRange())
210 return std::string(Ptr, Ptr+EndOff-StartOff);
214 EndOff = RB.getMappedOffset(EndOff,
true);
215 StartOff = RB.getMappedOffset(StartOff);
219 if (Range.isTokenRange())
224 std::advance(Start, StartOff);
226 assert(EndOff >= StartOff &&
"Invalid iteration distance");
227 std::advance(End, EndOff-StartOff);
229 return std::string(Start, End);
234 assert(Loc.
isValid() &&
"Invalid location");
242 std::map<FileID, RewriteBuffer>::iterator I =
243 RewriteBuffers.lower_bound(FID);
244 if (I != RewriteBuffers.end() && I->first == FID)
246 I = RewriteBuffers.insert(I, std::make_pair(FID,
RewriteBuffer()));
249 I->second.Initialize(MB.begin(), MB.end());
257 bool InsertAfter,
bool indentNewLines) {
260 unsigned StartOffs = getLocationOffsetAndFileID(Loc, FID);
263 if (indentNewLines && Str.contains(
'\n')) {
266 unsigned lineNo = SourceMgr->
getLineNumber(FID, StartOffs) - 1;
272 StringRef indentSpace;
274 unsigned i = lineOffs;
277 indentSpace = MB.substr(lineOffs, i-lineOffs);
281 Str.split(lines,
"\n");
283 for (
unsigned i = 0, e = lines.size(); i != e; ++i) {
284 indentedStr += lines[i];
287 indentedStr += indentSpace;
290 Str = indentedStr.str();
300 unsigned StartOffs = getLocationOffsetAndFileID(Loc, FID);
313 unsigned StartOffs = getLocationOffsetAndFileID(Start, FID);
325 unsigned StartOffs = getLocationOffsetAndFileID(Start, StartFileID);
334 if (replacementRange.
isInvalid())
return true;
339 unsigned newOffs = getLocationOffsetAndFileID(replacementRange.
getBegin(),
342 return ReplaceText(start, origLength, MB.substr(newOffs, newLength));
347 if (range.isInvalid())
return true;
352 FileID StartFileID, EndFileID, parentFileID;
353 unsigned StartOff, EndOff, parentOff;
355 StartOff = getLocationOffsetAndFileID(range.getBegin(), StartFileID);
356 EndOff = getLocationOffsetAndFileID(range.getEnd(), EndFileID);
357 parentOff = getLocationOffsetAndFileID(parentIndent, parentFileID);
359 if (StartFileID != EndFileID || StartFileID != parentFileID)
361 if (StartOff > EndOff)
367 unsigned parentLineNo = SourceMgr->
getLineNumber(FID, parentOff) - 1;
368 unsigned startLineNo = SourceMgr->
getLineNumber(FID, StartOff) - 1;
369 unsigned endLineNo = SourceMgr->
getLineNumber(FID, EndOff) - 1;
379 StringRef parentSpace, startSpace;
381 unsigned i = parentLineOffs;
384 parentSpace = MB.substr(parentLineOffs, i-parentLineOffs);
389 startSpace = MB.substr(startLineOffs, i-startLineOffs);
391 if (parentSpace.size() >= startSpace.size())
393 if (!startSpace.startswith(parentSpace))
396 StringRef indent = startSpace.substr(parentSpace.size());
400 for (
unsigned lineNo = startLineNo; lineNo <= endLineNo; ++lineNo) {
405 StringRef origIndent = MB.substr(offs, i-offs);
406 if (origIndent.startswith(startSpace))
421class AtomicallyMovedFile {
427 TempFilename +=
"-%%%%%%%%";
429 if (llvm::sys::fs::createUniqueFile(TempFilename, FD, TempFilename)) {
431 Diagnostics.
Report(clang::diag::err_unable_to_make_temp)
434 FileStream.reset(
new llvm::raw_fd_ostream(FD,
true));
438 ~AtomicallyMovedFile() {
443 if (std::error_code ec = llvm::sys::fs::rename(TempFilename,
Filename)) {
445 Diagnostics.
Report(clang::diag::err_unable_to_rename_temp)
446 << TempFilename <<
Filename << ec.message();
449 llvm::sys::fs::remove(TempFilename);
453 bool ok() {
return (
bool)FileStream; }
454 raw_ostream &getStream() {
return *FileStream; }
460 std::unique_ptr<llvm::raw_fd_ostream> FileStream;
467 bool AllWritten =
true;
474 I->second.write(
File.getStream());
Defines the Diagnostic-related interfaces.
Defines the Diagnostic IDs-related interfaces.
Defines the clang::FileManager interface and associated types.
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)
Concrete class used by the front-end to report problems and issues.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Cached information about one file (either on disk or in the virtual file system).
StringRef getName() const
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
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 ...
RewriteBuffer - As code is rewritten, SourceBuffer's from the original input with modifications get a...
void RemoveText(unsigned OrigOffset, unsigned Size, bool removeLineIfEmpty=false)
RemoveText - Remove the specified text.
raw_ostream & write(raw_ostream &Stream) const
Write to Stream the result of applying all changes to the original buffer.
void InsertText(unsigned OrigOffset, StringRef Str, bool InsertAfter=true)
InsertText - Insert some text at the specified point, where the offset in the buffer is specified rel...
void ReplaceText(unsigned OrigOffset, unsigned OrigLength, StringRef NewStr)
ReplaceText - This method replaces a range of characters in the input buffer with a new string.
void erase(unsigned Offset, unsigned NumBytes)
void insert(unsigned Offset, const char *Start, const char *End)
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::map< FileID, RewriteBuffer >::iterator buffer_iterator
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.
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.
RopePieceBTreeIterator - This class provides read-only forward iteration over bytes that are in a Rop...
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
StringRef getBufferData(FileID FID, bool *Invalid=nullptr) const
Return a StringRef to the source buffer data for the specified FileID.
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 FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
const SrcMgr::SLocEntry & getSLocEntry(FileID FID, bool *Invalid=nullptr) const
A trivial tuple used to represent a source range.
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
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).