diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Edit/EditedSource.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Edit/EditedSource.cpp | 80 |
1 files changed, 73 insertions, 7 deletions
diff --git a/contrib/llvm/tools/clang/lib/Edit/EditedSource.cpp b/contrib/llvm/tools/clang/lib/Edit/EditedSource.cpp index b2a1663..dd99ca9 100644 --- a/contrib/llvm/tools/clang/lib/Edit/EditedSource.cpp +++ b/contrib/llvm/tools/clang/lib/Edit/EditedSource.cpp @@ -8,10 +8,11 @@ //===----------------------------------------------------------------------===// #include "clang/Edit/EditedSource.h" +#include "clang/Basic/CharInfo.h" +#include "clang/Basic/SourceManager.h" #include "clang/Edit/Commit.h" #include "clang/Edit/EditsReceiver.h" #include "clang/Lex/Lexer.h" -#include "clang/Basic/SourceManager.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" @@ -23,7 +24,7 @@ void EditsReceiver::remove(CharSourceRange range) { } StringRef EditedSource::copyString(const Twine &twine) { - llvm::SmallString<128> Data; + SmallString<128> Data; return copyString(twine.toStringRef(Data)); } @@ -88,7 +89,7 @@ bool EditedSource::commitInsertFromRange(SourceLocation OrigLoc, if (Len == 0) return true; - llvm::SmallString<128> StrVec; + SmallString<128> StrVec; FileOffset BeginOffs = InsertFromRangeOffs; FileOffset EndOffs = BeginOffs.getWithOffset(Len); FileEditsTy::iterator I = FileEdits.upper_bound(BeginOffs); @@ -239,13 +240,78 @@ bool EditedSource::commit(const Commit &commit) { return true; } +// \brief Returns true if it is ok to make the two given characters adjacent. +static bool canBeJoined(char left, char right, const LangOptions &LangOpts) { + // FIXME: Should use TokenConcatenation to make sure we don't allow stuff like + // making two '<' adjacent. + return !(Lexer::isIdentifierBodyChar(left, LangOpts) && + Lexer::isIdentifierBodyChar(right, LangOpts)); +} + +/// \brief Returns true if it is ok to eliminate the trailing whitespace between +/// the given characters. +static bool canRemoveWhitespace(char left, char beforeWSpace, char right, + const LangOptions &LangOpts) { + if (!canBeJoined(left, right, LangOpts)) + return false; + if (isWhitespace(left) || isWhitespace(right)) + return true; + if (canBeJoined(beforeWSpace, right, LangOpts)) + return false; // the whitespace was intentional, keep it. + return true; +} + +/// \brief Check the range that we are going to remove and: +/// -Remove any trailing whitespace if possible. +/// -Insert a space if removing the range is going to mess up the source tokens. +static void adjustRemoval(const SourceManager &SM, const LangOptions &LangOpts, + SourceLocation Loc, FileOffset offs, + unsigned &len, StringRef &text) { + assert(len && text.empty()); + SourceLocation BeginTokLoc = Lexer::GetBeginningOfToken(Loc, SM, LangOpts); + if (BeginTokLoc != Loc) + return; // the range is not at the beginning of a token, keep the range. + + bool Invalid = false; + StringRef buffer = SM.getBufferData(offs.getFID(), &Invalid); + if (Invalid) + return; + + unsigned begin = offs.getOffset(); + unsigned end = begin + len; + + // FIXME: Remove newline. + + if (begin == 0) { + if (buffer[end] == ' ') + ++len; + return; + } + + if (buffer[end] == ' ') { + if (canRemoveWhitespace(/*left=*/buffer[begin-1], + /*beforeWSpace=*/buffer[end-1], + /*right=*/buffer[end+1], + LangOpts)) + ++len; + return; + } + + if (!canBeJoined(buffer[begin-1], buffer[end], LangOpts)) + text = " "; +} + static void applyRewrite(EditsReceiver &receiver, StringRef text, FileOffset offs, unsigned len, - const SourceManager &SM) { + const SourceManager &SM, const LangOptions &LangOpts) { assert(!offs.getFID().isInvalid()); SourceLocation Loc = SM.getLocForStartOfFile(offs.getFID()); Loc = Loc.getLocWithOffset(offs.getOffset()); assert(Loc.isFileID()); + + if (text.empty()) + adjustRemoval(SM, LangOpts, Loc, offs, len, text); + CharSourceRange range = CharSourceRange::getCharRange(Loc, Loc.getLocWithOffset(len)); @@ -262,7 +328,7 @@ static void applyRewrite(EditsReceiver &receiver, } void EditedSource::applyRewrites(EditsReceiver &receiver) { - llvm::SmallString<128> StrVec; + SmallString<128> StrVec; FileOffset CurOffs, CurEnd; unsigned CurLen; @@ -288,14 +354,14 @@ void EditedSource::applyRewrites(EditsReceiver &receiver) { continue; } - applyRewrite(receiver, StrVec.str(), CurOffs, CurLen, SourceMgr); + applyRewrite(receiver, StrVec.str(), CurOffs, CurLen, SourceMgr, LangOpts); CurOffs = offs; StrVec = act.Text; CurLen = act.RemoveLen; CurEnd = CurOffs.getWithOffset(CurLen); } - applyRewrite(receiver, StrVec.str(), CurOffs, CurLen, SourceMgr); + applyRewrite(receiver, StrVec.str(), CurOffs, CurLen, SourceMgr, LangOpts); } void EditedSource::clearRewrites() { |