18#include "llvm/ADT/STLExtras.h"
19#include "llvm/ADT/SmallString.h"
20#include "llvm/ADT/StringRef.h"
21#include "llvm/ADT/Twine.h"
36 MacroArgUse &ArgUse) {
42 ExpansionLoc = ImmediateExpansionLoc;
48 Buf, SourceMgr, LangOpts);
51 ArgUse = {&IdentTable.
get(ArgName), ImmediateExpansionLoc,
55void EditedSource::startingCommit() {}
57void EditedSource::finishedCommit() {
58 for (
auto &ExpArg : CurrCommitMacroArgExps) {
61 std::tie(ExpLoc, ArgUse) = ExpArg;
62 auto &ArgUses = ExpansionToArgMap[ExpLoc];
63 if (!llvm::is_contained(ArgUses, ArgUse))
64 ArgUses.push_back(ArgUse);
66 CurrCommitMacroArgExps.clear();
75 FileEditsTy::iterator FA = getActionForOffset(Offs);
76 if (FA != FileEdits.end()) {
77 if (FA->first != Offs)
84 deconstructMacroArgLoc(OrigLoc, ExpLoc, ArgUse);
85 auto I = ExpansionToArgMap.find(ExpLoc);
86 if (I != ExpansionToArgMap.end() &&
87 llvm::any_of(I->second, [&](
const MacroArgUse &
U) {
88 return ArgUse.Identifier == U.Identifier &&
89 std::tie(ArgUse.ImmediateExpansionLoc, ArgUse.UseLoc) !=
90 std::tie(U.ImmediateExpansionLoc, U.UseLoc);
113 bool beforePreviousInsertions) {
122 deconstructMacroArgLoc(OrigLoc, ExpLoc, ArgUse);
123 if (ArgUse.Identifier)
124 CurrCommitMacroArgExps.emplace_back(ExpLoc, ArgUse);
127 FileEdit &FA = FileEdits[Offs];
128 if (FA.Text.empty()) {
133 if (beforePreviousInsertions)
144 bool beforePreviousInsertions) {
151 FileEditsTy::iterator I = FileEdits.upper_bound(BeginOffs);
152 if (I != FileEdits.begin())
155 for (; I != FileEdits.end(); ++I) {
156 FileEdit &FA = I->second;
172 for (; I != FileEdits.end() && EndOffs > I->first; ++I) {
173 FileEdit &FA = I->second;
179 StringRef
text = getSourceText(BeginOffs, B,
Invalid);
188 if (BeginOffs < EndOffs) {
190 StringRef
text = getSourceText(BeginOffs, EndOffs,
Invalid);
196 return commitInsert(OrigLoc, Offs, StrVec, beforePreviousInsertions);
205 FileEditsTy::iterator I = FileEdits.upper_bound(BeginOffs);
206 if (I != FileEdits.begin())
209 for (; I != FileEdits.end(); ++I) {
210 FileEdit &FA = I->second;
219 FileEdit *TopFA =
nullptr;
221 if (I == FileEdits.end()) {
222 FileEditsTy::iterator
223 NewI = FileEdits.insert(I, std::make_pair(BeginOffs, FileEdit()));
224 NewI->second.RemoveLen = Len;
228 FileEdit &FA = I->second;
232 FileEditsTy::iterator
233 NewI = FileEdits.insert(I, std::make_pair(BeginOffs, FileEdit()));
234 TopBegin = BeginOffs;
236 TopFA = &NewI->second;
237 TopFA->RemoveLen = Len;
242 if (TopEnd >= EndOffs)
246 TopFA->RemoveLen += diff;
248 TopFA->Text = StringRef();
252 while (I != FileEdits.end()) {
253 FileEdit &FA = I->second;
261 FileEdits.erase(I++);
266 unsigned diff =
E.getOffset() - TopEnd.
getOffset();
268 TopFA->RemoveLen += diff;
277 if (!
commit.isCommitable())
284 Editor.startingCommit();
288 Editor.finishedCommit();
297 commitInsert(edit.OrigLoc, edit.Offset, edit.Text, edit.BeforePrev);
300 commitInsertFromRange(edit.OrigLoc, edit.Offset,
301 edit.InsertFromRangeOffs, edit.Length,
305 commitRemove(edit.OrigLoc, edit.Offset, edit.Length);
339 unsigned &len, StringRef &text) {
340 assert(len && text.empty());
342 if (BeginTokLoc !=
Loc)
351 unsigned end = begin + len;
354 if (end == buffer.size())
357 assert(begin < buffer.size() && end < buffer.size() &&
"Invalid range!");
362 if (buffer[end] ==
' ')
367 if (buffer[end] ==
' ') {
368 assert((end + 1 != buffer.size() || buffer.data()[end + 1] == 0) &&
369 "buffer not zero-terminated!");
372 buffer.data()[end + 1],
378 if (!
canBeJoined(buffer[begin-1], buffer[end], LangOpts))
383 StringRef text,
FileOffset offs,
unsigned len,
385 bool shouldAdjustRemovals) {
391 if (text.empty() && shouldAdjustRemovals)
410 bool shouldAdjustRemovals) {
415 if (FileEdits.empty())
418 FileEditsTy::iterator I = FileEdits.begin();
420 StrVec = I->second.Text;
421 CurLen = I->second.RemoveLen;
425 for (FileEditsTy::iterator
E = FileEdits.end(); I !=
E; ++I) {
427 FileEdit act = I->second;
428 assert(offs >= CurEnd);
430 if (offs == CurEnd) {
432 CurLen += act.RemoveLen;
437 applyRewrite(receiver, StrVec, CurOffs, CurLen, SourceMgr, LangOpts,
438 shouldAdjustRemovals);
441 CurLen = act.RemoveLen;
445 applyRewrite(receiver, StrVec, CurOffs, CurLen, SourceMgr, LangOpts,
446 shouldAdjustRemovals);
457 assert(BeginOffs <= EndOffs);
464 SourceMgr, LangOpts, &
Invalid);
467EditedSource::FileEditsTy::iterator
468EditedSource::getActionForOffset(
FileOffset Offs) {
469 FileEditsTy::iterator I = FileEdits.upper_bound(Offs);
470 if (I == FileEdits.begin())
471 return FileEdits.end();
473 FileEdit &FA = I->second;
476 if (Offs >= B && Offs <
E)
479 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',...