From 5d9d0b876a6791b112c55499af0e867b1553d4c3 Mon Sep 17 00:00:00 2001 From: Alexis Murzeau Date: Sun, 26 Apr 2020 22:57:00 +0200 Subject: [PATCH] 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 --- src/plugins/languageclient/client.cpp | 41 ++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/src/plugins/languageclient/client.cpp b/src/plugins/languageclient/client.cpp index 6ee1e58a060..851acd8668a 100644 --- a/src/plugins/languageclient/client.cpp +++ b/src/plugins/languageclient/client.cpp @@ -1036,13 +1036,52 @@ void Client::showMessageBox(const ShowMessageRequestParams &message, const Messa box->show(); } +void addDiagnosticsSelections(const Diagnostic &diagnostic, + QTextDocument *textDocument, + QList &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) { const FilePath &filePath = uri.toFilePath(); if (TextEditor::TextDocument *doc = TextEditor::TextDocument::textDocumentForFilePath( uri.toFilePath())) { - for (const Diagnostic &diagnostic : m_diagnostics.value(uri)) + QList extraSelections; + + for (const Diagnostic &diagnostic : m_diagnostics.value(uri)) { 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(editor)) { + TextEditor::TextEditorWidget *widget = textEditor->editorWidget(); + + widget->setExtraSelections(TextEditor::TextEditorWidget::CodeWarningsSelection, + extraSelections); + } + } } }