LSP: underline code with diagnostics from the language server

When the language server reports diagnostics, it also reports to which
part of the code the diagnostic applies.

That part of the code wasn't emphasized before, there is only an icon
next to the line and part of the diagnostic message in the text editor,
but no exact clue of which word is targeted by the diagnostic.

This commit add information about the affected code by diagnostics using
extra selection of type CodeWarningsSelection as other plugins do (like
the clang code model).

If a diagnostic has no severity or is not Error, Warning is used (the word
will be underlined in yellow).
Diagnostics can be either Error, Warning, Information or Hint.

For example, clangd uses Hint for remarks and Information for notes.
Notes can be related to a warning or an error, for example
when a function call has an incorrect number of argument, the call site
will have an error diagnostic with red color and the called function
declaration will have a Hint diagnostic with a yellow color.

Change-Id: Ifa433553be95a4913541d5570a2758ac213e7075
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Alexis Murzeau
2020-04-26 22:57:00 +02:00
parent aa68902b62
commit 5d9d0b876a

View File

@@ -1036,13 +1036,52 @@ void Client::showMessageBox(const ShowMessageRequestParams &message, const Messa
box->show(); box->show();
} }
void addDiagnosticsSelections(const Diagnostic &diagnostic,
QTextDocument *textDocument,
QList<QTextEdit::ExtraSelection> &extraSelections)
{
QTextCursor cursor(textDocument);
cursor.setPosition(::Utils::Text::positionInText(textDocument,
diagnostic.range().start().line() + 1,
diagnostic.range().start().character() + 1));
cursor.setPosition(::Utils::Text::positionInText(textDocument,
diagnostic.range().end().line() + 1,
diagnostic.range().end().character() + 1),
QTextCursor::KeepAnchor);
QTextCharFormat format;
const TextEditor::FontSettings& fontSettings = TextEditor::TextEditorSettings::instance()->fontSettings();
DiagnosticSeverity severity = diagnostic.severity().value_or(DiagnosticSeverity::Warning);
if (severity == DiagnosticSeverity::Error) {
format = fontSettings.toTextCharFormat(TextEditor::C_ERROR);
} else {
format = fontSettings.toTextCharFormat(TextEditor::C_WARNING);
}
extraSelections.push_back(std::move(QTextEdit::ExtraSelection{cursor, format}));
}
void Client::showDiagnostics(const DocumentUri &uri) void Client::showDiagnostics(const DocumentUri &uri)
{ {
const FilePath &filePath = uri.toFilePath(); const FilePath &filePath = uri.toFilePath();
if (TextEditor::TextDocument *doc = TextEditor::TextDocument::textDocumentForFilePath( if (TextEditor::TextDocument *doc = TextEditor::TextDocument::textDocumentForFilePath(
uri.toFilePath())) { uri.toFilePath())) {
for (const Diagnostic &diagnostic : m_diagnostics.value(uri)) QList<QTextEdit::ExtraSelection> extraSelections;
for (const Diagnostic &diagnostic : m_diagnostics.value(uri)) {
doc->addMark(new TextMark(filePath, diagnostic, id())); doc->addMark(new TextMark(filePath, diagnostic, id()));
addDiagnosticsSelections(diagnostic, doc->document(), extraSelections);
}
for (Core::IEditor *editor : Core::DocumentModel::editorsForDocument(doc)) {
if (auto textEditor = qobject_cast<TextEditor::BaseTextEditor *>(editor)) {
TextEditor::TextEditorWidget *widget = textEditor->editorWidget();
widget->setExtraSelections(TextEditor::TextEditorWidget::CodeWarningsSelection,
extraSelections);
}
}
} }
} }