From 84bf607eac44ea32c9cb662c21ccd4c23da7e174 Mon Sep 17 00:00:00 2001 From: Kadir Cetinkaya Date: Tue, 9 Oct 2018 08:41:12 +0000 Subject: [PATCH] [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 --- clang-tools-extra/clangd/Diagnostics.cpp | 8 ++------ .../unittests/clangd/ClangdUnitTests.cpp | 11 +++++++++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/clang-tools-extra/clangd/Diagnostics.cpp b/clang-tools-extra/clangd/Diagnostics.cpp index a2f86eb949c9..b8ce2e0ed8e5 100644 --- a/clang-tools-extra/clangd/Diagnostics.cpp +++ b/clang-tools-extra/clangd/Diagnostics.cpp @@ -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 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 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) diff --git a/clang-tools-extra/unittests/clangd/ClangdUnitTests.cpp b/clang-tools-extra/unittests/clangd/ClangdUnitTests.cpp index 51cfcfe48f38..fe3fc2006359 100644 --- a/clang-tools-extra/unittests/clangd/ClangdUnitTests.cpp +++ b/clang-tools-extra/unittests/clangd/ClangdUnitTests.cpp @@ -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) {