From 86cc50e27f90357e31d0a4e47db8c473b9eed7dc Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 10 Dec 2017 18:13:25 -0800 Subject: [PATCH] Implement diagnostic range as per clang_formatDiagnostic --- src/clang_utils.cc | 44 +++++++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/src/clang_utils.cc b/src/clang_utils.cc index fa718355..228fcf5d 100644 --- a/src/clang_utils.cc +++ b/src/clang_utils.cc @@ -20,30 +20,46 @@ lsRange GetLsRangeForFixIt(const CXSourceRange& range) { } // namespace +// See clang_formatDiagnostic optional BuildAndDisposeDiagnostic(CXDiagnostic diagnostic, const std::string& path) { // Get diagnostic location. CXFile file; - unsigned int line, column; - clang_getSpellingLocation(clang_getDiagnosticLocation(diagnostic), &file, - &line, &column, nullptr); + unsigned start_line, start_column; + clang_getSpellingLocation(clang_getDiagnosticLocation(diagnostic), + &file, &start_line, &start_column, nullptr); - // Only report diagnostics in the same file. Using - // clang_Location_isInSystemHeader causes crashes for some reason. - if (path != FileName(file)) { + if (file && path != FileName(file)) { clang_disposeDiagnostic(diagnostic); return nullopt; } + unsigned end_line = start_line, end_column = start_column, + num_ranges = clang_getDiagnosticNumRanges(diagnostic); + for (unsigned i = 0; i < num_ranges; i++) { + CXFile file0, file1; + unsigned line0, column0, line1, column1; + CXSourceRange range = clang_getDiagnosticRange(diagnostic, i); + clang_getSpellingLocation(clang_getRangeStart(range), &file0, &line0, + &column0, nullptr); + clang_getSpellingLocation(clang_getRangeEnd(range), &file1, &line1, + &column1, nullptr); + if (file0 != file1 || file0 != file) + continue; + if (line0 < start_line || (line0 == start_line && column0 < start_column)) { + start_line = line0; + start_column = column0; + } + if (line1 > end_line || (line1 == end_line && column1 > end_column)) { + end_line = line1; + end_column = column1; + } + } + // Build diagnostic. lsDiagnostic ls_diagnostic; - - // TODO: consider using clang_getDiagnosticRange - // TODO: ls_diagnostic.range is lsRange, we have Range. We should only be - // storing Range types when inside the indexer so that index <-> buffer - // remapping logic is applied. - ls_diagnostic.range = - lsRange(lsPosition(line - 1, column), lsPosition(line - 1, column)); + ls_diagnostic.range = lsRange(lsPosition(start_line - 1, start_column - 1), + lsPosition(end_line - 1, end_column - 1)); ls_diagnostic.message = ToString(clang_getDiagnosticSpelling(diagnostic)); @@ -57,6 +73,8 @@ optional BuildAndDisposeDiagnostic(CXDiagnostic diagnostic, switch (clang_getDiagnosticSeverity(diagnostic)) { case CXDiagnostic_Ignored: + // llvm_unreachable + break; case CXDiagnostic_Note: ls_diagnostic.severity = lsDiagnosticSeverity::Information; break;