20 #include "llvm/ADT/SmallString.h"
21 #include "llvm/Support/FileSystem.h"
22 #include "llvm/Support/raw_ostream.h"
23 using namespace clang;
50 bool removeLineIfEmpty) {
52 if (Size == 0)
return;
54 unsigned RealOffset = getMappedOffset(OrigOffset,
true);
55 assert(RealOffset+Size <= Buffer.
size() &&
"Invalid location");
58 Buffer.
erase(RealOffset, Size);
61 AddReplaceDelta(OrigOffset, -Size);
63 if (removeLineIfEmpty) {
68 unsigned curLineStartOffs = 0;
70 for (
unsigned i = 0; i != RealOffset; ++i) {
74 curLineStartOffs = i + 1;
79 unsigned lineSize = 0;
85 if (posI !=
end() && *posI ==
'\n') {
86 Buffer.
erase(curLineStartOffs, lineSize + 1);
87 AddReplaceDelta(curLineStartOffs, -(lineSize + 1));
96 if (Str.empty())
return;
98 unsigned RealOffset = getMappedOffset(OrigOffset, InsertAfter);
99 Buffer.
insert(RealOffset, Str.begin(), Str.end());
102 AddInsertDelta(OrigOffset, Str.size());
110 unsigned RealOffset = getMappedOffset(OrigOffset,
true);
111 Buffer.
erase(RealOffset, OrigLength);
112 Buffer.
insert(RealOffset, NewStr.begin(), NewStr.end());
113 if (OrigLength != NewStr.size())
114 AddReplaceDelta(OrigOffset, NewStr.size() - OrigLength);
129 FileID StartFileID, EndFileID;
130 unsigned StartOff, EndOff;
132 StartOff = getLocationOffsetAndFileID(Range.
getBegin(), StartFileID);
133 EndOff = getLocationOffsetAndFileID(Range.
getEnd(), EndFileID);
135 if (StartFileID != EndFileID)
140 std::map<FileID, RewriteBuffer>::const_iterator
I =
141 RewriteBuffers.find(StartFileID);
142 if (I != RewriteBuffers.end()) {
154 return EndOff-StartOff;
173 FileID StartFileID, EndFileID;
174 unsigned StartOff, EndOff;
175 StartOff = getLocationOffsetAndFileID(Range.
getBegin(), StartFileID);
176 EndOff = getLocationOffsetAndFileID(Range.
getEnd(), EndFileID);
178 if (StartFileID != EndFileID)
183 std::map<FileID, RewriteBuffer>::const_iterator
I =
184 RewriteBuffers.find(StartFileID);
185 if (I == RewriteBuffers.end()) {
192 return std::string(Ptr, Ptr+EndOff-StartOff);
196 EndOff = RB.getMappedOffset(EndOff,
true);
197 StartOff = RB.getMappedOffset(StartOff);
205 std::advance(Start, StartOff);
207 std::advance(End, EndOff-StartOff);
209 return std::string(Start, End);
214 assert(Loc.
isValid() &&
"Invalid location");
225 RewriteBuffers.lower_bound(FID);
226 if (I != RewriteBuffers.end() && I->first == FID)
228 I = RewriteBuffers.insert(I, std::make_pair(FID,
RewriteBuffer()));
231 I->second.Initialize(MB.begin(), MB.end());
239 bool InsertAfter,
bool indentNewLines) {
242 unsigned StartOffs = getLocationOffsetAndFileID(Loc, FID);
245 if (indentNewLines && Str.find(
'\n') != StringRef::npos) {
248 unsigned lineNo = SourceMgr->
getLineNumber(FID, StartOffs) - 1;
249 const SrcMgr::ContentCache *
251 unsigned lineOffs = Content->SourceLineCache[lineNo];
254 StringRef indentSpace;
256 unsigned i = lineOffs;
259 indentSpace = MB.substr(lineOffs, i-lineOffs);
263 Str.split(lines,
"\n");
265 for (
unsigned i = 0, e = lines.size(); i != e; ++i) {
266 indentedStr += lines[i];
269 indentedStr += indentSpace;
272 Str = indentedStr.str();
282 unsigned StartOffs = getLocationOffsetAndFileID(Loc, FID);
295 unsigned StartOffs = getLocationOffsetAndFileID(Start, FID);
307 unsigned StartOffs = getLocationOffsetAndFileID(Start, StartFileID);
316 if (replacementRange.
isInvalid())
return true;
321 unsigned newOffs = getLocationOffsetAndFileID(replacementRange.
getBegin(),
324 return ReplaceText(start, origLength, MB.substr(newOffs, newLength));
334 FileID StartFileID, EndFileID, parentFileID;
335 unsigned StartOff, EndOff, parentOff;
337 StartOff = getLocationOffsetAndFileID(range.
getBegin(), StartFileID);
338 EndOff = getLocationOffsetAndFileID(range.
getEnd(), EndFileID);
339 parentOff = getLocationOffsetAndFileID(parentIndent, parentFileID);
341 if (StartFileID != EndFileID || StartFileID != parentFileID)
343 if (StartOff > EndOff)
349 unsigned parentLineNo = SourceMgr->
getLineNumber(FID, parentOff) - 1;
350 unsigned startLineNo = SourceMgr->
getLineNumber(FID, StartOff) - 1;
351 unsigned endLineNo = SourceMgr->
getLineNumber(FID, EndOff) - 1;
353 const SrcMgr::ContentCache *
357 unsigned parentLineOffs = Content->SourceLineCache[parentLineNo];
358 unsigned startLineOffs = Content->SourceLineCache[startLineNo];
361 StringRef parentSpace, startSpace;
363 unsigned i = parentLineOffs;
366 parentSpace = MB.substr(parentLineOffs, i-parentLineOffs);
371 startSpace = MB.substr(startLineOffs, i-startLineOffs);
373 if (parentSpace.size() >= startSpace.size())
375 if (!startSpace.startswith(parentSpace))
378 StringRef indent = startSpace.substr(parentSpace.size());
382 for (
unsigned lineNo = startLineNo; lineNo <= endLineNo; ++lineNo) {
383 unsigned offs = Content->SourceLineCache[lineNo];
387 StringRef origIndent = MB.substr(offs, i-offs);
388 if (origIndent.startswith(startSpace))
402 class AtomicallyMovedFile {
406 : Diagnostics(Diagnostics), Filename(Filename), AllWritten(AllWritten) {
408 TempFilename +=
"-%%%%%%%%";
410 if (llvm::sys::fs::createUniqueFile(TempFilename, FD, TempFilename)) {
412 Diagnostics.
Report(clang::diag::err_unable_to_make_temp)
415 FileStream.reset(
new llvm::raw_fd_ostream(FD,
true));
419 ~AtomicallyMovedFile() {
424 if (std::error_code ec = llvm::sys::fs::rename(TempFilename, Filename)) {
426 Diagnostics.
Report(clang::diag::err_unable_to_rename_temp)
427 << TempFilename << Filename << ec.message();
430 llvm::sys::fs::remove(TempFilename);
434 bool ok() {
return (
bool)FileStream; }
435 raw_ostream &getStream() {
return *FileStream; }
441 std::unique_ptr<llvm::raw_fd_ostream> FileStream;
447 bool AllWritten =
true;
454 I->second.write(File.getStream());
SourceLocation getEnd() const
void insert(unsigned Offset, const char *Start, const char *End)
bool IncreaseIndentation(CharSourceRange range, SourceLocation parentIndent)
Increase indentation for the lines between the given source range.
SourceLocation getBegin() const
SourceManager & getSourceMgr() const
Defines the SourceManager interface.
static CharSourceRange getTokenRange(SourceRange R)
const SrcMgr::SLocEntry & getSLocEntry(FileID FID, bool *Invalid=nullptr) 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...
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
bool RemoveText(SourceLocation Start, unsigned Length, RewriteOptions opts=RewriteOptions())
RemoveText - Remove the specified text region.
void erase(unsigned Offset, unsigned NumBytes)
RewriteBuffer & getEditBuffer(FileID FID)
getEditBuffer - This is like getRewriteBufferFor, but always returns a buffer, and allows you to writ...
RewriteBuffer - As code is rewritten, SourceBuffer's from the original input with modifications get a...
StringRef getBufferData(FileID FID, bool *Invalid=nullptr) const
Return a StringRef to the source buffer data for the specified FileID.
bool ReplaceText(SourceLocation Start, unsigned OrigLength, StringRef NewStr)
ReplaceText - This method replaces a range of characters in the input buffer with a new string...
Concrete class used by the front-end to report problems and issues.
detail::InMemoryDirectory::const_iterator I
buffer_iterator buffer_end()
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
Represents a character-granular source range.
SourceLocation getEnd() const
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 ...
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...
bool overwriteChangedFiles()
overwriteChangedFiles - Save all changed files to disk.
bool isTokenRange() const
Return true if the end of this range specifies the start of the last token.
const char * getName() const
void ReplaceText(unsigned OrigOffset, 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.
static bool isWhitespaceExceptNL(unsigned char c)
Return true if this character is non-new-line whitespace: ' ', '\t', '\f', '\v', '\r'.
const TemplateArgument * iterator
bool isValid() const
Return true if this is a valid SourceLocation object.
Cached information about one file (either on disk or in the virtual file system). ...
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 RemoveLineIfEmpty
If true and removing some text leaves a blank line also remove the empty line (false by default)...
void RemoveText(unsigned OrigOffset, unsigned Size, bool removeLineIfEmpty=false)
RemoveText - Remove the specified text.
const FileInfo & getFile() const
SourceLocation getBegin() const
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...
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
RopePieceBTreeIterator - This class provides read-only forward iteration over bytes that are in a Rop...
const ContentCache * getContentCache() const
unsigned getLineNumber(FileID FID, unsigned FilePos, bool *Invalid=nullptr) const
Given a SourceLocation, return the spelling line number for the position indicated.
detail::InMemoryDirectory::const_iterator E
Defines the Diagnostic-related interfaces.
raw_ostream & write(raw_ostream &Stream) const
Write to Stream the result of applying all changes to the original buffer.
std::string getRewrittenText(SourceRange Range) const
getRewrittenText - Return the rewritten form of the text in the specified range.
bool IncludeInsertsAtBeginOfRange
Given a source range, true to include previous inserts at the beginning of the range as part of the r...
std::map< FileID, RewriteBuffer >::iterator buffer_iterator
buffer_iterator buffer_begin()
static bool isRewritable(SourceLocation Loc)
isRewritable - Return true if this location is a raw file location, which is rewritable.
Defines the Diagnostic IDs-related interfaces.
A trivial tuple used to represent a source range.
bool InsertTextAfterToken(SourceLocation Loc, StringRef Str)
Insert the specified string after the token in the specified location.
std::pair< FileID, unsigned > getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
bool IncludeInsertsAtEndOfRange
Given a source range, true to include previous inserts at the end of the range as part of the range i...