summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Edit/EditedSource.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Edit/EditedSource.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Edit/EditedSource.cpp80
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() {
OpenPOWER on IntegriCloud