18#include "llvm/ADT/STLExtras.h"
19#include "llvm/ADT/StringRef.h"
20#include "llvm/ADT/Twine.h"
34 MacroArgUse &ArgUse) {
40 ExpansionLoc = ImmediateExpansionLoc;
46 Buf, SourceMgr, LangOpts);
49 ArgUse = {&IdentTable.
get(ArgName), ImmediateExpansionLoc,
53void EditedSource::startingCommit() {}
55void EditedSource::finishedCommit() {
56 for (
auto &ExpArg : CurrCommitMacroArgExps) {
59 std::tie(ExpLoc, ArgUse) = ExpArg;
60 auto &ArgUses = ExpansionToArgMap[ExpLoc];
61 if (!llvm::is_contained(ArgUses, ArgUse))
62 ArgUses.push_back(ArgUse);
64 CurrCommitMacroArgExps.clear();
73 FileEditsTy::iterator FA = getActionForOffset(Offs);
74 if (FA != FileEdits.end()) {
75 if (FA->first != Offs)
82 deconstructMacroArgLoc(OrigLoc, ExpLoc, ArgUse);
83 auto I = ExpansionToArgMap.find(ExpLoc);
84 if (I != ExpansionToArgMap.end() &&
85 llvm::any_of(I->second, [&](
const MacroArgUse &
U) {
86 return ArgUse.Identifier == U.Identifier &&
87 std::tie(ArgUse.ImmediateExpansionLoc, ArgUse.UseLoc) !=
88 std::tie(U.ImmediateExpansionLoc, U.UseLoc);
111 bool beforePreviousInsertions) {
120 deconstructMacroArgLoc(OrigLoc, ExpLoc, ArgUse);
121 if (ArgUse.Identifier)
122 CurrCommitMacroArgExps.emplace_back(ExpLoc, ArgUse);
125 FileEdit &FA = FileEdits[Offs];
126 if (FA.Text.empty()) {
131 if (beforePreviousInsertions)
142 bool beforePreviousInsertions) {
149 FileEditsTy::iterator I = FileEdits.upper_bound(BeginOffs);
150 if (I != FileEdits.begin())
153 for (; I != FileEdits.end(); ++I) {
154 FileEdit &FA = I->second;
170 for (; I != FileEdits.end() && EndOffs > I->first; ++I) {
171 FileEdit &FA = I->second;
177 StringRef
text = getSourceText(BeginOffs, B,
Invalid);
186 if (BeginOffs < EndOffs) {
188 StringRef
text = getSourceText(BeginOffs, EndOffs,
Invalid);
194 return commitInsert(OrigLoc, Offs, StrVec, beforePreviousInsertions);
203 FileEditsTy::iterator I = FileEdits.upper_bound(BeginOffs);
204 if (I != FileEdits.begin())
207 for (; I != FileEdits.end(); ++I) {
208 FileEdit &FA = I->second;
217 FileEdit *TopFA =
nullptr;
219 if (I == FileEdits.end()) {
220 FileEditsTy::iterator
221 NewI = FileEdits.insert(I, std::make_pair(BeginOffs, FileEdit()));
222 NewI->second.RemoveLen = Len;
226 FileEdit &FA = I->second;
230 FileEditsTy::iterator
231 NewI = FileEdits.insert(I, std::make_pair(BeginOffs, FileEdit()));
232 TopBegin = BeginOffs;
234 TopFA = &NewI->second;
235 TopFA->RemoveLen = Len;
240 if (TopEnd >= EndOffs)
244 TopFA->RemoveLen += diff;
246 TopFA->Text = StringRef();
250 while (I != FileEdits.end()) {
251 FileEdit &FA = I->second;
259 FileEdits.erase(I++);
264 unsigned diff =
E.getOffset() - TopEnd.
getOffset();
266 TopFA->RemoveLen += diff;
275 if (!
commit.isCommitable())
282 Editor.startingCommit();
286 Editor.finishedCommit();
295 commitInsert(edit.OrigLoc, edit.Offset, edit.Text, edit.BeforePrev);
298 commitInsertFromRange(edit.OrigLoc, edit.Offset,
299 edit.InsertFromRangeOffs, edit.Length,
303 commitRemove(edit.OrigLoc, edit.Offset, edit.Length);
337 unsigned &len, StringRef &text) {
338 assert(len && text.empty());
340 if (BeginTokLoc !=
Loc)
349 unsigned end = begin + len;
352 if (end == buffer.size())
355 assert(begin < buffer.size() && end < buffer.size() &&
"Invalid range!");
360 if (buffer[end] ==
' ')
365 if (buffer[end] ==
' ') {
366 assert((end + 1 != buffer.size() || buffer.data()[end + 1] == 0) &&
367 "buffer not zero-terminated!");
370 buffer.data()[end + 1],
376 if (!
canBeJoined(buffer[begin-1], buffer[end], LangOpts))
381 StringRef text,
FileOffset offs,
unsigned len,
383 bool shouldAdjustRemovals) {
389 if (text.empty() && shouldAdjustRemovals)
408 bool shouldAdjustRemovals) {
413 if (FileEdits.empty())
416 FileEditsTy::iterator I = FileEdits.begin();
418 StrVec = I->second.Text;
419 CurLen = I->second.RemoveLen;
423 for (FileEditsTy::iterator
E = FileEdits.end(); I !=
E; ++I) {
425 FileEdit act = I->second;
426 assert(offs >= CurEnd);
428 if (offs == CurEnd) {
430 CurLen += act.RemoveLen;
435 applyRewrite(receiver, StrVec, CurOffs, CurLen, SourceMgr, LangOpts,
436 shouldAdjustRemovals);
439 CurLen = act.RemoveLen;
443 applyRewrite(receiver, StrVec, CurOffs, CurLen, SourceMgr, LangOpts,
444 shouldAdjustRemovals);
455 assert(BeginOffs <= EndOffs);
462 SourceMgr, LangOpts, &
Invalid);
465EditedSource::FileEditsTy::iterator
466EditedSource::getActionForOffset(
FileOffset Offs) {
467 FileEditsTy::iterator I = FileEdits.upper_bound(Offs);
468 if (I == FileEdits.begin())
469 return FileEdits.end();
471 FileEdit &FA = I->second;
474 if (Offs >= B && Offs <
E)
477 return FileEdits.end();
static bool canBeJoined(char left, char right, const LangOptions &LangOpts)
static void applyRewrite(EditsReceiver &receiver, StringRef text, FileOffset offs, unsigned len, const SourceManager &SM, const LangOptions &LangOpts, bool shouldAdjustRemovals)
static void adjustRemoval(const SourceManager &SM, const LangOptions &LangOpts, SourceLocation Loc, FileOffset offs, unsigned &len, StringRef &text)
Check the range that we are going to remove and: -Remove any trailing whitespace if possible.
static bool canRemoveWhitespace(char left, char beforeWSpace, char right, const LangOptions &LangOpts)
Returns true if it is ok to eliminate the trailing whitespace between the given characters.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Defines the clang::SourceLocation class and associated facilities.
Defines the SourceManager interface.
Represents a character-granular source range.
static CharSourceRange getCharRange(SourceRange R)
SourceLocation getBegin() const
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
static StringRef getSourceText(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts, bool *Invalid=nullptr)
Returns a string for the source that the range encompasses.
static unsigned getSpelling(const Token &Tok, const char *&Buffer, const SourceManager &SourceMgr, const LangOptions &LangOpts, bool *Invalid=nullptr)
getSpelling - This method is used to get the spelling of a token into a preallocated buffer,...
static bool isAsciiIdentifierContinueChar(char c, const LangOptions &LangOpts)
Returns true if the given character could appear in an identifier.
static SourceLocation GetBeginningOfToken(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
Given a location any where in a source buffer, find the location that corresponds to the beginning of...
Encodes a location in the source.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
This class handles loading and caching of source files into memory.
bool isMacroBodyExpansion(SourceLocation Loc) const
Tests whether the given source location represents the expansion of a macro body.
bool isMacroArgExpansion(SourceLocation Loc, SourceLocation *StartLoc=nullptr) const
Tests whether the given source location represents a macro argument's expansion into the function-lik...
SourceLocation getSpellingLoc(SourceLocation Loc) const
Given a SourceLocation object, return the spelling location referenced by the ID.
CharSourceRange getImmediateExpansionRange(SourceLocation Loc) const
Return the start/end of the expansion information for an expansion location.
SourceLocation getLocForStartOfFile(FileID FID) const
Return the source location corresponding to the first byte of the specified file.
SmallVectorImpl< Edit >::const_iterator edit_iterator
StringRef copyString(StringRef str)
bool canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs)
void applyRewrites(EditsReceiver &receiver, bool adjustRemovals=true)
bool commit(const Commit &commit)
virtual void insert(SourceLocation loc, StringRef text)=0
virtual void remove(CharSourceRange range)
By default it calls replace with an empty string.
virtual void replace(CharSourceRange range, StringRef text)=0
FileOffset getWithOffset(unsigned offset) const
unsigned getOffset() const
The JSON file list parser is used to communicate input to InstallAPI.
LLVM_READONLY bool isWhitespace(unsigned char c)
Return true if this character is horizontal or vertical ASCII whitespace: ' ', '\t',...