22 #include "llvm/Support/FileSystem.h"
23 #include "llvm/Support/Path.h"
24 #include "llvm/Support/raw_os_ostream.h"
35 StringRef ReplacementText)
36 : FilePath(FilePath), ReplacementRange(Offset, Length),
37 ReplacementText(ReplacementText) {}
40 unsigned Length, StringRef ReplacementText) {
41 setFromSourceLocation(Sources, Start, Length, ReplacementText);
46 StringRef ReplacementText,
48 setFromSourceRange(Sources, Range, ReplacementText, LangOpts);
70 getLocWithOffset(ReplacementRange.
getOffset());
75 Start, ReplacementRange.
getLength(), ReplacementText);
76 assert(RewriteSucceeded);
77 return RewriteSucceeded;
82 llvm::raw_string_ostream Stream(Result);
83 Stream << FilePath <<
": " << ReplacementRange.
getOffset() <<
":+"
84 << ReplacementRange.
getLength() <<
":\"" << ReplacementText <<
"\"";
110 void Replacement::setFromSourceLocation(
const SourceManager &Sources,
112 StringRef ReplacementText) {
113 const std::pair<FileID, unsigned> DecomposedLocation =
117 this->ReplacementRange = Range(DecomposedLocation.second, Length);
118 this->ReplacementText = ReplacementText;
129 std::pair<FileID, unsigned> Start = Sources.
getDecomposedLoc(SpellingBegin);
131 if (Start.first != End.first)
return -1;
134 return End.second - Start.second;
137 void Replacement::setFromSourceRange(
const SourceManager &Sources,
139 StringRef ReplacementText,
146 template <
typename T>
149 for (
const auto& R : Replaces) {
150 if (R.getOffset() + R.getLength() <=
Position) {
151 Offset += R.getReplacementText().size() - R.getLength();
154 if (R.getOffset() < Position &&
155 R.getOffset() + R.getReplacementText().size() <=
Position) {
156 Position = R.getOffset() + R.getReplacementText().size() - 1;
175 std::vector<Range> &Conflicts) {
176 if (Replaces.empty())
181 return LHS.
getOffset() < RHS.getOffset();
183 return LHS.
getLength() < RHS.getLength();
188 return LHS.
getOffset() == RHS.getOffset() &&
195 std::sort(Replaces.begin(), Replaces.end(), LessNoPath);
196 Replaces.erase(std::unique(Replaces.begin(), Replaces.end(), EqualNoPath),
200 Range ConflictRange(Replaces.front().getOffset(),
201 Replaces.front().getLength());
202 unsigned ConflictStart = 0;
203 unsigned ConflictLength = 1;
204 for (
unsigned i = 1; i < Replaces.size(); ++i) {
205 Range
Current(Replaces[i].getOffset(), Replaces[i].getLength());
206 if (ConflictRange.overlapsWith(Current)) {
208 ConflictRange = Range(ConflictRange.getOffset(),
209 std::max(ConflictRange.getLength(),
211 ConflictRange.getOffset()));
214 if (ConflictLength > 1)
215 Conflicts.push_back(Range(ConflictStart, ConflictLength));
222 if (ConflictLength > 1)
223 Conflicts.push_back(Range(ConflictStart, ConflictLength));
228 for (Replacements::const_iterator
I = Replaces.begin(),
231 if (
I->isApplicable()) {
232 Result =
I->apply(Rewrite) && Result;
245 for (std::vector<Replacement>::const_iterator
I = Replaces.begin(),
248 if (
I->isApplicable()) {
249 Result =
I->apply(Rewrite) && Result;
266 InMemoryFileSystem->addFile(
267 "<stdin>", 0, llvm::MemoryBuffer::getMemBuffer(Code,
"<stdin>"));
270 for (Replacements::const_iterator
I = Replaces.begin(),
E = Replaces.end();
272 Replacement Replace(
"<stdin>",
I->getOffset(),
I->getLength(),
273 I->getReplacementText());
274 if (!Replace.apply(Rewrite))
278 llvm::raw_string_ostream OS(Result);
305 class MergedReplacement {
307 MergedReplacement(
const Replacement &R,
bool MergeSecond,
int D)
308 : MergeSecond(MergeSecond),
Delta(D),
FilePath(R.getFilePath()),
309 Offset(R.getOffset() + (MergeSecond ? 0 :
Delta)), Length(R.getLength()),
310 Text(R.getReplacementText()) {
318 void merge(
const Replacement &R) {
320 unsigned REnd = R.getOffset() +
Delta + R.getLength();
323 Length += REnd -
End;
326 StringRef TextRef =
Text;
327 StringRef Head = TextRef.substr(0, R.getOffset() +
Delta -
Offset);
328 StringRef Tail = TextRef.substr(REnd -
Offset);
329 Text = (Head + R.getReplacementText() + Tail).str();
330 Delta += R.getReplacementText().size() - R.getLength();
333 StringRef RText = R.getReplacementText();
334 StringRef Tail = RText.substr(End - R.getOffset());
336 if (R.getOffset() + RText.size() >
End) {
337 Length = R.getOffset() + R.getLength() -
Offset;
340 Length += R.getLength() - RText.size();
348 bool endsBefore(
const Replacement &R)
const {
351 return Offset + Length < R.getOffset();
382 if (First.empty() || Second.empty())
383 return First.empty() ? Second : First;
394 for (
auto FirstI = First.begin(), SecondI = Second.begin();
395 FirstI != First.end() || SecondI != Second.end();) {
396 bool NextIsFirst = SecondI == Second.end() ||
397 (FirstI != First.end() &&
398 FirstI->getOffset() < SecondI->getOffset() +
Delta);
399 MergedReplacement Merged(NextIsFirst ? *FirstI : *SecondI, NextIsFirst,
401 ++(NextIsFirst ? FirstI : SecondI);
403 while ((Merged.mergeSecond() && SecondI != Second.end()) ||
404 (!Merged.mergeSecond() && FirstI != First.end())) {
405 auto &
I = Merged.mergeSecond() ? SecondI : FirstI;
406 if (Merged.endsBefore(*
I))
411 Delta -= Merged.deltaFirst();
412 Result.insert(Merged.asReplacement());
SourceLocation getBegin() const
Implements support for file system lookup, file system caching, and directory search management...
SourceManager & getSourceMgr() const
Defines the clang::FileManager interface and associated types.
SourceLocation getSpellingLoc(SourceLocation Loc) const
Given a SourceLocation object, return the spelling location referenced by the ID. ...
Defines the SourceManager interface.
RewriteBuffer & getEditBuffer(FileID FID)
getEditBuffer - This is like getRewriteBufferFor, but always returns a buffer, and allows you to writ...
bool ReplaceText(SourceLocation Start, unsigned OrigLength, StringRef NewStr)
ReplaceText - This method replaces a range of characters in the input buffer with a new string...
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
An in-memory file system.
Concrete class used by the front-end to report problems and issues.
SourceLocation translateFileLineCol(const FileEntry *SourceFile, unsigned Line, unsigned Col) const
Get the source location for the given file:line:col triplet.
detail::InMemoryDirectory::const_iterator I
const FileEntry * getFile(StringRef Filename, bool OpenFile=false, bool CacheFailure=true)
Lookup, cache, and verify the specified file (real or virtual).
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
ID
Defines the set of possible language-specific address spaces.
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 ...
FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos, SrcMgr::CharacteristicKind FileCharacter, int LoadedID=0, unsigned LoadedOffset=0)
Create a new FileID that represents the specified file being #included from the specified IncludePosi...
FileManager & getFileManager() const
The result type of a method or function.
bool isTokenRange() const
Return true if the end of this range specifies the start of the last token.
const char * getName() const
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
Options for controlling the compiler diagnostics engine.
Cached information about one file (either on disk or in the virtual file system). ...
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Used for handling and querying diagnostic IDs.
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.
Keeps track of options that affect how file operations are performed.
Rewriter - This is the main interface to the rewrite buffers.
Defines the Diagnostic IDs-related interfaces.
SourceLocation getLocForStartOfFile(FileID FID) const
Return the source location corresponding to the first byte of the specified file. ...
std::pair< FileID, unsigned > getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
This class handles loading and caching of source files into memory.