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/IOSandbox.h"
26#include "llvm/Support/raw_ostream.h"
33using llvm::RewriteBuffer;
42 return c ==
' ' ||
c ==
'\t' ||
c ==
'\f' ||
c ==
'\v' ||
c ==
'\r';
52 FileID StartFileID, EndFileID;
53 unsigned StartOff = getLocationOffsetAndFileID(Range.getBegin(), StartFileID);
54 unsigned EndOff = getLocationOffsetAndFileID(Range.getEnd(), EndFileID);
56 if (StartFileID != EndFileID)
61 std::map<FileID, RewriteBuffer>::const_iterator I =
62 RewriteBuffers.find(StartFileID);
63 if (I != RewriteBuffers.end()) {
64 const RewriteBuffer &RB = I->second;
71 if (Range.isTokenRange())
74 return EndOff-StartOff;
91 FileID StartFileID, EndFileID;
92 unsigned StartOff, EndOff;
93 StartOff = getLocationOffsetAndFileID(Range.getBegin(), StartFileID);
94 EndOff = getLocationOffsetAndFileID(Range.getEnd(), EndFileID);
96 if (StartFileID != EndFileID)
101 std::map<FileID, RewriteBuffer>::const_iterator I =
102 RewriteBuffers.find(StartFileID);
103 if (I == RewriteBuffers.end()) {
105 const char *Ptr = SourceMgr->getCharacterData(Range.getBegin());
109 if (Range.isTokenRange())
112 return std::string(Ptr, Ptr+EndOff-StartOff);
115 const RewriteBuffer &RB = I->second;
116 EndOff = RB.getMappedOffset(EndOff,
true);
117 StartOff = RB.getMappedOffset(StartOff);
121 if (Range.isTokenRange())
125 RewriteBuffer::iterator Start = RB.begin();
126 std::advance(Start, StartOff);
127 RewriteBuffer::iterator End = Start;
128 assert(EndOff >= StartOff &&
"Invalid iteration distance");
129 std::advance(End, EndOff-StartOff);
131 return std::string(Start, End);
136 assert(Loc.
isValid() &&
"Invalid location");
144 std::map<FileID, RewriteBuffer>::iterator I =
145 RewriteBuffers.lower_bound(FID);
146 if (I != RewriteBuffers.end() && I->first == FID)
148 I = RewriteBuffers.insert(I, std::make_pair(FID, RewriteBuffer()));
150 StringRef MB = SourceMgr->getBufferData(FID);
151 I->second.Initialize(MB.begin(), MB.end());
159 bool InsertAfter,
bool indentNewLines) {
162 unsigned StartOffs = getLocationOffsetAndFileID(Loc, FID);
165 if (indentNewLines && Str.contains(
'\n')) {
166 StringRef MB = SourceMgr->getBufferData(FID);
168 unsigned lineNo = SourceMgr->getLineNumber(FID, StartOffs) - 1;
170 &SourceMgr->getSLocEntry(FID).getFile().getContentCache();
174 StringRef indentSpace;
176 unsigned i = lineOffs;
179 indentSpace = MB.substr(lineOffs, i-lineOffs);
183 Str.split(lines,
"\n");
185 for (
unsigned i = 0, e = lines.size(); i != e; ++i) {
186 indentedStr += lines[i];
189 indentedStr += indentSpace;
192 Str = indentedStr.str();
202 unsigned StartOffs = getLocationOffsetAndFileID(Loc, FID);
215 unsigned StartOffs = getLocationOffsetAndFileID(Start, FID);
227 unsigned StartOffs = getLocationOffsetAndFileID(Start, StartFileID);
229 getEditBuffer(StartFileID).ReplaceText(StartOffs, OrigLength, NewStr);
236 if (replacementRange.
isInvalid())
return true;
241 unsigned newOffs = getLocationOffsetAndFileID(replacementRange.
getBegin(),
243 StringRef MB = SourceMgr->getBufferData(FID);
244 return ReplaceText(start, origLength, MB.substr(newOffs, newLength));
249 if (range.isInvalid())
return true;
254 FileID StartFileID, EndFileID, parentFileID;
255 unsigned StartOff, EndOff, parentOff;
257 StartOff = getLocationOffsetAndFileID(range.getBegin(), StartFileID);
258 EndOff = getLocationOffsetAndFileID(range.getEnd(), EndFileID);
259 parentOff = getLocationOffsetAndFileID(parentIndent, parentFileID);
261 if (StartFileID != EndFileID || StartFileID != parentFileID)
263 if (StartOff > EndOff)
267 StringRef MB = SourceMgr->getBufferData(FID);
269 unsigned parentLineNo = SourceMgr->getLineNumber(FID, parentOff) - 1;
270 unsigned startLineNo = SourceMgr->getLineNumber(FID, StartOff) - 1;
271 unsigned endLineNo = SourceMgr->getLineNumber(FID, EndOff) - 1;
274 &SourceMgr->getSLocEntry(FID).getFile().getContentCache();
281 StringRef parentSpace, startSpace;
283 unsigned i = parentLineOffs;
286 parentSpace = MB.substr(parentLineOffs, i-parentLineOffs);
291 startSpace = MB.substr(startLineOffs, i-startLineOffs);
293 if (parentSpace.size() >= startSpace.size())
295 if (!startSpace.starts_with(parentSpace))
298 StringRef indent = startSpace.substr(parentSpace.size());
302 for (
unsigned lineNo = startLineNo; lineNo <= endLineNo; ++lineNo) {
307 StringRef origIndent = MB.substr(offs, i-offs);
308 if (origIndent.starts_with(startSpace))
309 RB.InsertText(offs, indent,
false);
316 bool AllWritten =
true;
318 unsigned OverwriteFailure =
Diag.getCustomDiagID(
325 auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
326 if (
auto Error = llvm::writeToOutput(Path, [&](llvm::raw_ostream &OS) {
328 return llvm::Error::success();
330 Diag.Report(OverwriteFailure)
331 << Entry->
getName() << llvm::toString(std::move(
Error));
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.
FileManager & getFileManager() 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.
The JSON file list parser is used to communicate input to InstallAPI.
CustomizableOptional< FileEntryRef > OptionalFileEntryRef
std::pair< FileID, unsigned > FileIDAndOffset
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).