19 #include "llvm/ADT/STLExtras.h" 20 #include "llvm/ADT/SmallString.h" 21 #include "llvm/ADT/StringRef.h" 22 #include "llvm/ADT/Twine.h" 28 using namespace clang;
37 MacroArgUse &ArgUse) {
38 assert(SourceMgr.isMacroArgExpansion(Loc));
40 SourceMgr.getImmediateExpansionRange(Loc).getBegin();
42 SourceMgr.getImmediateExpansionRange(DefArgLoc).getBegin();
43 ExpansionLoc = ImmediateExpansionLoc;
44 while (SourceMgr.isMacroBodyExpansion(ExpansionLoc))
46 SourceMgr.getImmediateExpansionRange(ExpansionLoc).getBegin();
49 Buf, SourceMgr, LangOpts);
52 ArgUse = {&IdentTable.get(ArgName), ImmediateExpansionLoc,
53 SourceMgr.getSpellingLoc(DefArgLoc)};
56 void EditedSource::startingCommit() {}
58 void EditedSource::finishedCommit() {
59 for (
auto &ExpArg : CurrCommitMacroArgExps) {
62 std::tie(ExpLoc, ArgUse) = ExpArg;
64 if (std::find(ArgUses.begin(), ArgUses.end(), ArgUse) == ArgUses.end())
65 ArgUses.push_back(ArgUse);
67 CurrCommitMacroArgExps.clear();
76 FileEditsTy::iterator FA = getActionForOffset(Offs);
77 if (FA != FileEdits.end()) {
78 if (FA->first != Offs)
82 if (SourceMgr.isMacroArgExpansion(OrigLoc)) {
85 deconstructMacroArgLoc(OrigLoc, ExpLoc, ArgUse);
87 if (I != ExpansionToArgMap.end() &&
88 find_if(I->second, [&](
const MacroArgUse &U) {
89 return ArgUse.Identifier == U.Identifier &&
90 std::tie(ArgUse.ImmediateExpansionLoc, ArgUse.UseLoc) !=
91 std::tie(U.ImmediateExpansionLoc, U.UseLoc);
92 }) != I->second.end()) {
114 bool beforePreviousInsertions) {
115 if (!canInsertInOffset(OrigLoc, Offs))
120 if (SourceMgr.isMacroArgExpansion(OrigLoc)) {
123 deconstructMacroArgLoc(OrigLoc, ExpLoc, ArgUse);
124 if (ArgUse.Identifier)
125 CurrCommitMacroArgExps.emplace_back(ExpLoc, ArgUse);
128 FileEdit &FA = FileEdits[Offs];
129 if (FA.Text.empty()) {
134 if (beforePreviousInsertions)
145 bool beforePreviousInsertions) {
152 FileEditsTy::iterator I = FileEdits.upper_bound(BeginOffs);
153 if (I != FileEdits.begin())
156 for (; I != FileEdits.end(); ++I) {
157 FileEdit &FA = I->second;
173 for (; I != FileEdits.end() && EndOffs > I->first; ++I) {
174 FileEdit &FA = I->second;
179 bool Invalid =
false;
180 StringRef
text = getSourceText(BeginOffs, B, Invalid);
189 if (BeginOffs < EndOffs) {
190 bool Invalid =
false;
191 StringRef
text = getSourceText(BeginOffs, EndOffs, Invalid);
197 return commitInsert(OrigLoc, Offs, StrVec, beforePreviousInsertions);
206 FileEditsTy::iterator I = FileEdits.upper_bound(BeginOffs);
207 if (I != FileEdits.begin())
210 for (; I != FileEdits.end(); ++I) {
211 FileEdit &FA = I->second;
220 FileEdit *TopFA =
nullptr;
222 if (I == FileEdits.end()) {
223 FileEditsTy::iterator
224 NewI = FileEdits.insert(I, std::make_pair(BeginOffs, FileEdit()));
225 NewI->second.RemoveLen = Len;
229 FileEdit &FA = I->second;
233 FileEditsTy::iterator
234 NewI = FileEdits.insert(I, std::make_pair(BeginOffs, FileEdit()));
235 TopBegin = BeginOffs;
237 TopFA = &NewI->second;
238 TopFA->RemoveLen = Len;
243 if (TopEnd >= EndOffs)
247 TopFA->RemoveLen += diff;
249 TopFA->Text = StringRef();
253 while (I != FileEdits.end()) {
254 FileEdit &FA = I->second;
262 FileEdits.erase(I++);
269 TopFA->RemoveLen += diff;
285 Editor.startingCommit();
289 Editor.finishedCommit();
340 unsigned &len, StringRef &
text) {
341 assert(len && text.empty());
343 if (BeginTokLoc != Loc)
346 bool Invalid =
false;
352 unsigned end = begin + len;
355 if (end == buffer.size())
358 assert(begin < buffer.size() && end < buffer.size() &&
"Invalid range!");
363 if (buffer[end] ==
' ')
368 if (buffer[end] ==
' ') {
369 assert((end + 1 != buffer.size() || buffer.data()[end + 1] == 0) &&
370 "buffer not zero-terminated!");
373 buffer.data()[end + 1],
379 if (!
canBeJoined(buffer[begin-1], buffer[end], LangOpts))
386 bool shouldAdjustRemovals) {
390 assert(Loc.isFileID());
392 if (text.empty() && shouldAdjustRemovals)
396 Loc.getLocWithOffset(len));
407 receiver.
insert(Loc, text);
411 bool shouldAdjustRemovals) {
416 if (FileEdits.empty())
419 FileEditsTy::iterator I = FileEdits.begin();
421 StrVec = I->second.Text;
422 CurLen = I->second.RemoveLen;
426 for (FileEditsTy::iterator E = FileEdits.end(); I != E; ++I) {
428 FileEdit act = I->second;
429 assert(offs >= CurEnd);
431 if (offs == CurEnd) {
433 CurLen += act.RemoveLen;
438 applyRewrite(receiver, StrVec, CurOffs, CurLen, SourceMgr, LangOpts,
439 shouldAdjustRemovals);
442 CurLen = act.RemoveLen;
446 applyRewrite(receiver, StrVec, CurOffs, CurLen, SourceMgr, LangOpts,
447 shouldAdjustRemovals);
458 assert(BeginOffs <= EndOffs);
465 SourceMgr, LangOpts, &Invalid);
468 EditedSource::FileEditsTy::iterator
469 EditedSource::getActionForOffset(
FileOffset Offs) {
470 FileEditsTy::iterator I = FileEdits.upper_bound(Offs);
471 if (I == FileEdits.begin())
472 return FileEdits.end();
474 FileEdit &FA = I->second;
477 if (Offs >= B && Offs < E)
480 return FileEdits.end();
SourceLocation getLocForStartOfFile(FileID FID) const
Return the source location corresponding to the first byte of the specified file. ...
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...
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
unsigned getRawEncoding() const
When a SourceLocation itself cannot be used, this returns an (opaque) 32-bit integer encoding for it...
Defines the SourceManager interface.
SmallVectorImpl< Edit >::const_iterator edit_iterator
StringRef getBufferData(FileID FID, bool *Invalid=nullptr) const
Return a StringRef to the source buffer data for the specified FileID.
edit_iterator edit_end() const
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
LLVM_READONLY bool isWhitespace(unsigned char c)
Return true if this character is horizontal or vertical ASCII whitespace: ' ', '\t', '\f', '\v', '\n', '\r'.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
static StringRef getSourceText(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts, bool *Invalid=nullptr)
Returns a string for the source that the range encompasses.
Represents a character-granular source range.
virtual void replace(CharSourceRange range, StringRef text)=0
edit_iterator edit_begin() const
FileOffset InsertFromRangeOffs
virtual void remove(CharSourceRange range)
By default it calls replace with an empty string.
FileOffset getWithOffset(unsigned offset) const
static CharSourceRange getCharRange(SourceRange R)
Encodes a location in the source.
static bool canBeJoined(char left, char right, const LangOptions &LangOpts)
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...
StringRef copyString(StringRef str)
Dataflow Directional Tag Classes.
bool isCommitable() const
unsigned getOffset() const
bool commit(const Commit &commit)
static bool isIdentifierBodyChar(char c, const LangOptions &LangOpts)
Returns true if the given character could appear in an identifier.
bool canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs)
void applyRewrites(EditsReceiver &receiver, bool adjustRemovals=true)
Defines the clang::SourceLocation class and associated facilities.
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.
virtual void insert(SourceLocation loc, StringRef text)=0
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 void applyRewrite(EditsReceiver &receiver, StringRef text, FileOffset offs, unsigned len, const SourceManager &SM, const LangOptions &LangOpts, bool shouldAdjustRemovals)
This class handles loading and caching of source files into memory.