18 #include "llvm/ADT/STLExtras.h"
19 #include "llvm/ADT/SmallString.h"
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/ADT/Twine.h"
27 using namespace clang;
36 MacroArgUse &ArgUse) {
42 ExpansionLoc = ImmediateExpansionLoc;
48 Buf, SourceMgr, LangOpts);
51 ArgUse = {&IdentTable.
get(ArgName), ImmediateExpansionLoc,
55 void EditedSource::startingCommit() {}
57 void 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 find_if(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);
91 }) != I->second.end()) {
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++);
268 TopFA->RemoveLen += diff;
277 if (!
commit.isCommitable())
284 Editor.startingCommit();
288 Editor.finishedCommit();
293 I =
commit.edit_begin(), E =
commit.edit_end(); I != E; ++I) {
300 commitInsertFromRange(
edit.OrigLoc,
edit.Offset,
301 edit.InsertFromRangeOffs,
edit.Length,
339 unsigned &len, StringRef &
text) {
340 assert(len &&
text.empty());
342 if (BeginTokLoc != Loc)
345 bool Invalid =
false;
346 StringRef buffer =
SM.getBufferData(offs.
getFID(), &Invalid);
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))
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);
467 EditedSource::FileEditsTy::iterator
468 EditedSource::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();