Skip to content
Snippets Groups Projects
Commit 5964df14 authored by Argyrios Kyrtzidis's avatar Argyrios Kyrtzidis
Browse files

Use some heuristics so that when a fixit removes a source range, we try

to also remove a trailing space if possible.

For example, removing '__bridge' from:

i = (__bridge I*)p;

should result in:

i = (I*)p;

not:

i = ( I*)p;

rdar://11314821

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@170764 91177308-0d34-0410-b5e6-96231b3b80d8
parent 7c441069
No related branches found
No related tags found
No related merge requests found
...@@ -239,13 +239,82 @@ bool EditedSource::commit(const Commit &commit) { ...@@ -239,13 +239,82 @@ bool EditedSource::commit(const Commit &commit) {
return true; return true;
} }
static inline bool isIdentifierChar(char c, const LangOptions &LangOpts) {
return std::isalnum(c) || c == '_' || (c == '$' && LangOpts.DollarIdents);
}
// \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 the Lexer to make sure we don't allow stuff like
// making two '<' adjacent.
return !(isIdentifierChar(left, LangOpts) &&
isIdentifierChar(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 (std::isspace(left) || std::isspace(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, static void applyRewrite(EditsReceiver &receiver,
StringRef text, FileOffset offs, unsigned len, StringRef text, FileOffset offs, unsigned len,
const SourceManager &SM) { const SourceManager &SM, const LangOptions &LangOpts) {
assert(!offs.getFID().isInvalid()); assert(!offs.getFID().isInvalid());
SourceLocation Loc = SM.getLocForStartOfFile(offs.getFID()); SourceLocation Loc = SM.getLocForStartOfFile(offs.getFID());
Loc = Loc.getLocWithOffset(offs.getOffset()); Loc = Loc.getLocWithOffset(offs.getOffset());
assert(Loc.isFileID()); assert(Loc.isFileID());
if (text.empty())
adjustRemoval(SM, LangOpts, Loc, offs, len, text);
CharSourceRange range = CharSourceRange::getCharRange(Loc, CharSourceRange range = CharSourceRange::getCharRange(Loc,
Loc.getLocWithOffset(len)); Loc.getLocWithOffset(len));
...@@ -288,14 +357,14 @@ void EditedSource::applyRewrites(EditsReceiver &receiver) { ...@@ -288,14 +357,14 @@ void EditedSource::applyRewrites(EditsReceiver &receiver) {
continue; continue;
} }
applyRewrite(receiver, StrVec.str(), CurOffs, CurLen, SourceMgr); applyRewrite(receiver, StrVec.str(), CurOffs, CurLen, SourceMgr, LangOpts);
CurOffs = offs; CurOffs = offs;
StrVec = act.Text; StrVec = act.Text;
CurLen = act.RemoveLen; CurLen = act.RemoveLen;
CurEnd = CurOffs.getWithOffset(CurLen); CurEnd = CurOffs.getWithOffset(CurLen);
} }
applyRewrite(receiver, StrVec.str(), CurOffs, CurLen, SourceMgr); applyRewrite(receiver, StrVec.str(), CurOffs, CurLen, SourceMgr, LangOpts);
} }
void EditedSource::clearRewrites() { void EditedSource::clearRewrites() {
......
...@@ -192,7 +192,7 @@ int test_logical_and_false(int k) { ...@@ -192,7 +192,7 @@ int test_logical_and_false(int k) {
return x; // expected-note {{uninitialized use}} return x; // expected-note {{uninitialized use}}
} }
// CHECK: fix-it:"{{.*}}":{189:3-191:9}:"" // CHECK: fix-it:"{{.*}}":{189:3-191:10}:""
// CHECK: fix-it:"{{.*}}":{188:8-188:8}:" = 0" // CHECK: fix-it:"{{.*}}":{188:8-188:8}:" = 0"
...@@ -232,7 +232,7 @@ int test_logical_or_true(int k) { ...@@ -232,7 +232,7 @@ int test_logical_or_true(int k) {
return x; // expected-note {{uninitialized use}} return x; // expected-note {{uninitialized use}}
} }
// CHECK: fix-it:"{{.*}}":{229:3-231:9}:"" // CHECK: fix-it:"{{.*}}":{229:3-231:10}:""
// CHECK: fix-it:"{{.*}}":{228:8-228:8}:" = 0" // CHECK: fix-it:"{{.*}}":{228:8-228:8}:" = 0"
......
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
@interface I
@end
void foo(void *p) {
I *i = (__bridge I*)p;
I *i2 = (__bridge/*cake*/I*)p;
}
// CHECK: {7:11-7:20}:""
// CHECK: {8:12-8:20}:""
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment