Index: clangd/Diagnostics.cpp =================================================================== --- clangd/Diagnostics.cpp +++ clangd/Diagnostics.cpp @@ -52,17 +52,28 @@ auto &M = D.getSourceManager(); auto Loc = M.getFileLoc(D.getLocation()); // Accept the first range that contains the location. + llvm::Optional PossibleRange; 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 (!PossibleRange) + PossibleRange = halfOpenToRange(M, R); } // The range may be given as a fixit hint instead. for (const auto &F : D.getFixItHints()) { auto R = Lexer::makeFileCharRange(F.RemoveRange, M, L); if (locationInRange(Loc, R, M)) return halfOpenToRange(M, R); + // 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 (!PossibleRange && R.getBegin() == R.getEnd()) + PossibleRange = halfOpenToRange(M, R); } + if (PossibleRange) + return *PossibleRange; // If no suitable range is found, just use the token at the location. auto R = Lexer::makeFileCharRange(CharSourceRange::getTokenRange(Loc), M, L); if (!R.isValid()) // Fall back to location only, let the editor deal with it. Index: unittests/clangd/ClangdUnitTests.cpp =================================================================== --- unittests/clangd/ClangdUnitTests.cpp +++ unittests/clangd/ClangdUnitTests.cpp @@ -79,8 +79,9 @@ int main() { $typo[[go\ o]](); - foo()$semicolon[[]] + foo()$semicolon[[]]//with comments $unk[[unknown]](); + double bar = $type[["foo"]]; } )cpp"); EXPECT_THAT( @@ -97,7 +98,10 @@ AllOf(Diag(Test.range("semicolon"), "expected ';' after expression"), WithFix(Fix(Test.range("semicolon"), ";", "insert ';'"))), // This range isn't provided by clang, we expand to the token. - Diag(Test.range("unk"), "use of undeclared identifier 'unknown'"))); + 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]'"))); } TEST(DiagnosticsTest, FlagsMatter) {