[clangd] Revert back to previous heuristic for diagnostic range extraction.

Summary: Also add a few new test cases and a special case into handling of empty fixit ranges that  collides with location of a diag.

Reviewers: sammccall, ilya-biryukov

Reviewed By: sammccall

Subscribers: ilya-biryukov, ioeric, MaskRay, jkorous, arphaman, cfe-commits

Differential Revision: https://reviews.llvm.org/D52889

llvm-svn: 344025
This commit is contained in:
Kadir Cetinkaya 2018-10-09 08:41:12 +00:00
parent 7734e63ad8
commit 84bf607eac
2 changed files with 11 additions and 8 deletions

View File

@ -51,16 +51,12 @@ bool locationInRange(SourceLocation L, CharSourceRange R,
Range diagnosticRange(const clang::Diagnostic &D, const LangOptions &L) {
auto &M = D.getSourceManager();
auto Loc = M.getFileLoc(D.getLocation());
// Accept the first range that contains the location.
llvm::Optional<Range> FallbackRange;
for (const auto &CR : D.getRanges()) {
auto R = Lexer::makeFileCharRange(CR, M, L);
if (locationInRange(Loc, R, M))
return halfOpenToRange(M, R);
// If there are no ranges that contain the location report the first range.
if (!FallbackRange)
FallbackRange = halfOpenToRange(M, R);
}
llvm::Optional<Range> FallbackRange;
// The range may be given as a fixit hint instead.
for (const auto &F : D.getFixItHints()) {
auto R = Lexer::makeFileCharRange(F.RemoveRange, M, L);
@ -69,7 +65,7 @@ Range diagnosticRange(const clang::Diagnostic &D, const LangOptions &L) {
// If there's a fixit that performs insertion, it has zero-width. Therefore
// it can't contain the location of the diag, but it might be possible that
// this should be reported as range. For example missing semicolon.
if (!FallbackRange && R.getBegin() == R.getEnd())
if (R.getBegin() == R.getEnd() && Loc == R.getBegin())
FallbackRange = halfOpenToRange(M, R);
}
if (FallbackRange)

View File

@ -75,13 +75,17 @@ Position pos(int line, int character) {
TEST(DiagnosticsTest, DiagnosticRanges) {
// Check we report correct ranges, including various edge-cases.
Annotations Test(R"cpp(
namespace test{};
void $decl[[foo]]();
int main() {
$typo[[go\
o]]();
foo()$semicolon[[]]//with comments
$unk[[unknown]]();
double bar = $type[["foo"]];
double $type[[bar]] = "foo";
struct Foo { int x; }; Foo a;
a.$nomember[[y]];
test::$nomembernamespace[[test]];
}
)cpp");
EXPECT_THAT(
@ -103,7 +107,10 @@ o]]();
Diag(Test.range("unk"), "use of undeclared identifier 'unknown'"),
Diag(Test.range("type"),
"cannot initialize a variable of type 'double' with an lvalue "
"of type 'const char [4]'")));
"of type 'const char [4]'"),
Diag(Test.range("nomember"), "no member named 'y' in 'Foo'"),
Diag(Test.range("nomembernamespace"),
"no member named 'test' in namespace 'test'")));
}
TEST(DiagnosticsTest, FlagsMatter) {