aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Schulz <david.schulz@qt.io>2020-09-09 08:15:11 +0200
committerDavid Schulz <david.schulz@qt.io>2020-09-15 10:45:49 +0000
commit116fb0895d054b13d3cc99763ed1569a0964eb85 (patch)
tree12d6a8c2a43a36b9023692bf63f5c9a3ba42c2dc
parentee8e102cbc8a0c8fa96f872afb89538b48357a23 (diff)
LSP: move diagnostic handling from client in a separate class
Change-Id: Id70a7b82137d3a4591de521380199e546e8685f4 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
-rw-r--r--src/plugins/languageclient/CMakeLists.txt1
-rw-r--r--src/plugins/languageclient/client.cpp117
-rw-r--r--src/plugins/languageclient/client.h9
-rw-r--r--src/plugins/languageclient/diagnosticmanager.cpp144
-rw-r--r--src/plugins/languageclient/diagnosticmanager.h62
-rw-r--r--src/plugins/languageclient/languageclient.pro2
-rw-r--r--src/plugins/languageclient/languageclient.qbs2
7 files changed, 221 insertions, 116 deletions
diff --git a/src/plugins/languageclient/CMakeLists.txt b/src/plugins/languageclient/CMakeLists.txt
index 85d2227e12..bda78b7cbb 100644
--- a/src/plugins/languageclient/CMakeLists.txt
+++ b/src/plugins/languageclient/CMakeLists.txt
@@ -3,6 +3,7 @@ add_qtc_plugin(LanguageClient
PLUGIN_DEPENDS ProjectExplorer Core TextEditor
SOURCES
client.cpp client.h
+ diagnosticmanager.cpp diagnosticmanager.h
documentsymbolcache.cpp documentsymbolcache.h
dynamiccapabilities.cpp dynamiccapabilities.h
languageclient.qrc
diff --git a/src/plugins/languageclient/client.cpp b/src/plugins/languageclient/client.cpp
index d8b340c1d8..fd39b03d37 100644
--- a/src/plugins/languageclient/client.cpp
+++ b/src/plugins/languageclient/client.cpp
@@ -30,6 +30,7 @@
#include "languageclientutils.h"
#include "semantichighlightsupport.h"
+#include <coreplugin/editormanager/documentmodel.h>
#include <coreplugin/icore.h>
#include <coreplugin/idocument.h>
#include <coreplugin/messagemanager.h>
@@ -48,11 +49,9 @@
#include <texteditor/texteditor.h>
#include <texteditor/texteditoractionhandler.h>
#include <texteditor/texteditorsettings.h>
-#include <texteditor/textmark.h>
#include <utils/mimetypes/mimedatabase.h>
#include <utils/qtcprocess.h>
#include <utils/synchronousprocess.h>
-#include <utils/utilsicons.h>
#include <QDebug>
#include <QLoggingCategory>
@@ -71,34 +70,10 @@ namespace LanguageClient {
static Q_LOGGING_CATEGORY(LOGLSPCLIENT, "qtc.languageclient.client", QtWarningMsg);
-class TextMark : public TextEditor::TextMark
-{
-public:
- TextMark(const Utils::FilePath &fileName, const Diagnostic &diag, const Utils::Id &clientId)
- : TextEditor::TextMark(fileName, diag.range().start().line() + 1, clientId)
- , m_diagnostic(diag)
- {
- using namespace Utils;
- setLineAnnotation(diag.message());
- setToolTip(diag.message());
- const bool isError
- = diag.severity().value_or(DiagnosticSeverity::Hint) == DiagnosticSeverity::Error;
- setColor(isError ? Theme::CodeModel_Error_TextMarkColor
- : Theme::CodeModel_Warning_TextMarkColor);
-
- setIcon(isError ? Icons::CODEMODEL_ERROR.icon()
- : Icons::CODEMODEL_WARNING.icon());
- }
-
- const Diagnostic &diagnostic() const { return m_diagnostic; }
-
-private:
- const Diagnostic m_diagnostic;
-};
-
Client::Client(BaseClientInterface *clientInterface)
: m_id(Utils::Id::fromString(QUuid::createUuid().toString()))
, m_clientInterface(clientInterface)
+ , m_diagnosticManager(m_id)
, m_documentSymbolCache(this)
, m_hoverHandler(this)
, m_symbolSupport(this)
@@ -145,8 +120,6 @@ Client::~Client()
widget->removeHoverHandler(&m_hoverHandler);
}
}
- for (const DocumentUri &uri : m_diagnostics.keys())
- removeDiagnostics(uri);
for (const DocumentUri &uri : m_highlights.keys()) {
if (TextDocument *doc = TextDocument::textDocumentForFilePath(uri.toFilePath())) {
if (TextEditor::SyntaxHighlighter *highlighter = doc->syntaxHighlighter())
@@ -387,7 +360,7 @@ void Client::closeDocument(TextEditor::TextDocument *document)
void Client::activateDocument(TextEditor::TextDocument *document)
{
auto uri = DocumentUri::fromFilePath(document->filePath());
- showDiagnostics(uri);
+ m_diagnosticManager.showDiagnostics(uri);
SemanticHighligtingSupport::applyHighlight(document, m_highlights.value(uri), capabilities());
// only replace the assist provider if the language server support it
if (m_serverCapabilities.completionProvider()) {
@@ -417,7 +390,7 @@ void Client::activateDocument(TextEditor::TextDocument *document)
void Client::deactivateDocument(TextEditor::TextDocument *document)
{
- hideDiagnostics(document);
+ m_diagnosticManager.hideDiagnostics(document);
resetAssistProviders(document);
document->setFormatter(nullptr);
if (m_serverCapabilities.semanticHighlighting().has_value()) {
@@ -924,12 +897,7 @@ bool Client::needsRestart(const BaseSettings *settings) const
QList<Diagnostic> Client::diagnosticsAt(const DocumentUri &uri, const Range &range) const
{
- QList<Diagnostic> diagnostics;
- for (const Diagnostic &diagnostic : m_diagnostics[uri]) {
- if (diagnostic.range().overlaps(range))
- diagnostics << diagnostic;
- }
- return diagnostics;
+ return m_diagnosticManager.diagnosticsAt(uri, range);
}
bool Client::start()
@@ -948,8 +916,7 @@ bool Client::reset()
updateEditorToolBar(m_openedDocument.keys());
m_serverCapabilities = ServerCapabilities();
m_dynamicCapabilities.reset();
- for (const DocumentUri &uri : m_diagnostics.keys())
- removeDiagnostics(uri);
+ m_diagnosticManager.clearDiagnostics();
for (TextEditor::TextDocument *document : m_openedDocument.keys())
document->disconnect(this);
for (TextEditor::TextDocument *document : m_resetAssistProvider.keys())
@@ -990,18 +957,6 @@ void Client::log(const QString &message, Core::MessageManager::PrintToOutputPane
Core::MessageManager::write(QString("LanguageClient %1: %2").arg(name(), message), flag);
}
-void Client::showDiagnostics(Core::IDocument *doc)
-{
- showDiagnostics(DocumentUri::fromFilePath(doc->filePath()));
-}
-
-void Client::hideDiagnostics(TextEditor::TextDocument *doc)
-{
- if (!doc)
- return;
- qDeleteAll(Utils::filtered(doc->marks(), Utils::equal(&TextEditor::TextMark::category, id())));
-}
-
const ServerCapabilities &Client::capabilities() const
{
return m_serverCapabilities;
@@ -1060,61 +1015,6 @@ void Client::showMessageBox(const ShowMessageRequestParams &message, const Messa
box->show();
}
-static 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)
-{
- const FilePath &filePath = uri.toFilePath();
- if (TextEditor::TextDocument *doc = TextEditor::TextDocument::textDocumentForFilePath(
- filePath)) {
- QList<QTextEdit::ExtraSelection> 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<TextEditor::BaseTextEditor *>(editor)) {
- TextEditor::TextEditorWidget *widget = textEditor->editorWidget();
-
- widget->setExtraSelections(TextEditor::TextEditorWidget::CodeWarningsSelection,
- extraSelections);
- }
- }
- }
-}
-
-void Client::removeDiagnostics(const DocumentUri &uri)
-{
- hideDiagnostics(TextEditor::TextDocument::textDocumentForFilePath(uri.toFilePath()));
- m_diagnostics.remove(uri);
-}
-
void Client::resetAssistProviders(TextEditor::TextDocument *document)
{
const AssistProviders providers = m_resetAssistProvider.take(document);
@@ -1269,11 +1169,10 @@ void Client::handleDiagnostics(const PublishDiagnosticsParams &params)
{
const DocumentUri &uri = params.uri();
- removeDiagnostics(uri);
const QList<Diagnostic> &diagnostics = params.diagnostics();
- m_diagnostics[uri] = diagnostics;
+ m_diagnosticManager.setDiagnostics(uri, params.diagnostics());
if (LanguageClientManager::clientForUri(uri) == this) {
- showDiagnostics(uri);
+ m_diagnosticManager.showDiagnostics(uri);
requestCodeActions(uri, diagnostics);
}
}
diff --git a/src/plugins/languageclient/client.h b/src/plugins/languageclient/client.h
index f31d18087d..d264898474 100644
--- a/src/plugins/languageclient/client.h
+++ b/src/plugins/languageclient/client.h
@@ -25,6 +25,7 @@
#pragma once
+#include "diagnosticmanager.h"
#include "documentsymbolcache.h"
#include "dynamiccapabilities.h"
#include "languageclient_global.h"
@@ -64,13 +65,11 @@ namespace TextEditor
class IAssistProcessor;
class TextDocument;
class TextEditorWidget;
-class TextMark;
}
namespace LanguageClient {
class BaseClientInterface;
-class TextMark;
class LANGUAGECLIENT_EXPORT Client : public QObject
{
@@ -169,9 +168,6 @@ public:
Core::MessageManager::PrintToOutputPaneFlag flag = Core::MessageManager::NoModeSwitch)
{ log(responseError.toString(), flag); }
- void showDiagnostics(Core::IDocument *doc);
- void hideDiagnostics(TextEditor::TextDocument *doc);
-
const LanguageServerProtocol::ServerCapabilities &capabilities() const;
const DynamicCapabilities &dynamicCapabilities() const;
const BaseClientInterface *clientInterface() const;
@@ -208,7 +204,6 @@ private:
void showMessageBox(const LanguageServerProtocol::ShowMessageRequestParams &message,
const LanguageServerProtocol::MessageId &id);
- void showDiagnostics(const LanguageServerProtocol::DocumentUri &uri);
void removeDiagnostics(const LanguageServerProtocol::DocumentUri &uri);
void resetAssistProviders(TextEditor::TextDocument *document);
void sendPostponedDocumentUpdates();
@@ -243,7 +238,7 @@ private:
QHash<LanguageServerProtocol::DocumentUri, LanguageServerProtocol::MessageId> m_highlightRequests;
int m_restartsLeft = 5;
QScopedPointer<BaseClientInterface> m_clientInterface;
- QMap<LanguageServerProtocol::DocumentUri, QList<LanguageServerProtocol::Diagnostic>> m_diagnostics;
+ DiagnosticManager m_diagnosticManager;
DocumentSymbolCache m_documentSymbolCache;
HoverHandler m_hoverHandler;
QHash<LanguageServerProtocol::DocumentUri, TextEditor::HighlightingResults> m_highlights;
diff --git a/src/plugins/languageclient/diagnosticmanager.cpp b/src/plugins/languageclient/diagnosticmanager.cpp
new file mode 100644
index 0000000000..562c2e3c75
--- /dev/null
+++ b/src/plugins/languageclient/diagnosticmanager.cpp
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "diagnosticmanager.h"
+
+#include <coreplugin/editormanager/documentmodel.h>
+#include <texteditor/fontsettings.h>
+#include <texteditor/textdocument.h>
+#include <texteditor/texteditor.h>
+#include <texteditor/texteditorsettings.h>
+#include <texteditor/textmark.h>
+#include <texteditor/textstyles.h>
+#include <utils/utilsicons.h>
+
+#include <QTextEdit>
+
+using namespace LanguageServerProtocol;
+using namespace Utils;
+using namespace TextEditor;
+
+namespace LanguageClient {
+
+class TextMark : public TextEditor::TextMark
+{
+public:
+ TextMark(const FilePath &fileName, const Diagnostic &diag, const Id &clientId)
+ : TextEditor::TextMark(fileName, diag.range().start().line() + 1, clientId)
+ , m_diagnostic(diag)
+ {
+ setLineAnnotation(diag.message());
+ setToolTip(diag.message());
+ const bool isError
+ = diag.severity().value_or(DiagnosticSeverity::Hint) == DiagnosticSeverity::Error;
+ setColor(isError ? Theme::CodeModel_Error_TextMarkColor
+ : Theme::CodeModel_Warning_TextMarkColor);
+
+ setIcon(isError ? Icons::CODEMODEL_ERROR.icon()
+ : Icons::CODEMODEL_WARNING.icon());
+ }
+
+ const Diagnostic &diagnostic() const { return m_diagnostic; }
+
+private:
+ const Diagnostic m_diagnostic;
+};
+
+DiagnosticManager::DiagnosticManager(const Id &clientId)
+ : m_clientId(clientId)
+{}
+
+DiagnosticManager::~DiagnosticManager()
+{
+ clearDiagnostics();
+}
+
+void DiagnosticManager::setDiagnostics(const LanguageServerProtocol::DocumentUri &uri,
+ const QList<LanguageServerProtocol::Diagnostic> &diagnostics)
+{
+ removeDiagnostics(uri);
+ m_diagnostics[uri] = diagnostics;
+}
+
+void DiagnosticManager::hideDiagnostics(TextDocument *doc)
+{
+ if (!doc)
+ return;
+ qDeleteAll(Utils::filtered(doc->marks(), Utils::equal(&TextMark::category, m_clientId)));
+}
+
+void DiagnosticManager::removeDiagnostics(const LanguageServerProtocol::DocumentUri &uri)
+{
+ hideDiagnostics(TextDocument::textDocumentForFilePath(uri.toFilePath()));
+ m_diagnostics.remove(uri);
+}
+
+static QTextEdit::ExtraSelection toDiagnosticsSelections(const Diagnostic &diagnostic,
+ QTextDocument *textDocument)
+{
+ QTextCursor cursor(textDocument);
+ cursor.setPosition(diagnostic.range().start().toPositionInDocument(textDocument));
+ cursor.setPosition(diagnostic.range().end().toPositionInDocument(textDocument),
+ QTextCursor::KeepAnchor);
+
+ const FontSettings &fontSettings = TextEditorSettings::instance()->fontSettings();
+ const DiagnosticSeverity severity = diagnostic.severity().value_or(DiagnosticSeverity::Warning);
+ const TextStyle style = severity == DiagnosticSeverity::Error ? C_ERROR : C_WARNING;
+
+ return QTextEdit::ExtraSelection{cursor, fontSettings.toTextCharFormat(style)};
+}
+
+void DiagnosticManager::showDiagnostics(const DocumentUri &uri)
+{
+ const FilePath &filePath = uri.toFilePath();
+ if (TextDocument *doc = TextDocument::textDocumentForFilePath(filePath)) {
+ QList<QTextEdit::ExtraSelection> extraSelections;
+
+ for (const Diagnostic &diagnostic : m_diagnostics.value(uri)) {
+ doc->addMark(new TextMark(filePath, diagnostic, m_clientId));
+ extraSelections << toDiagnosticsSelections(diagnostic, doc->document());
+ }
+
+ for (BaseTextEditor *editor : BaseTextEditor::textEditorsForDocument(doc)) {
+ editor->editorWidget()->setExtraSelections(TextEditorWidget::CodeWarningsSelection,
+ extraSelections);
+ }
+ }
+}
+
+void DiagnosticManager::clearDiagnostics()
+{
+ for (const DocumentUri &uri : m_diagnostics.keys())
+ removeDiagnostics(uri);
+}
+
+QList<Diagnostic> DiagnosticManager::diagnosticsAt(const DocumentUri &uri, const Range &range) const
+{
+ return Utils::filtered(m_diagnostics.value(uri), [range](const Diagnostic &diagnostic) {
+ return diagnostic.range().overlaps(range);
+ });
+}
+
+} // namespace LanguageClient
diff --git a/src/plugins/languageclient/diagnosticmanager.h b/src/plugins/languageclient/diagnosticmanager.h
new file mode 100644
index 0000000000..9b83f0019d
--- /dev/null
+++ b/src/plugins/languageclient/diagnosticmanager.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <languageserverprotocol/lsptypes.h>
+
+#include <utils/id.h>
+
+#include <QMap>
+
+namespace TextEditor { class TextDocument; }
+
+namespace LanguageClient {
+
+class DiagnosticManager
+{
+public:
+ explicit DiagnosticManager(const Utils::Id &clientId);
+ ~DiagnosticManager();
+
+ void setDiagnostics(const LanguageServerProtocol::DocumentUri &uri,
+ const QList<LanguageServerProtocol::Diagnostic> &diagnostics);
+ void removeDiagnostics(const LanguageServerProtocol::DocumentUri &uri);
+
+ void showDiagnostics(const LanguageServerProtocol::DocumentUri &uri);
+ void hideDiagnostics(TextEditor::TextDocument *doc);
+
+ void clearDiagnostics();
+
+ QList<LanguageServerProtocol::Diagnostic> diagnosticsAt(
+ const LanguageServerProtocol::DocumentUri &uri,
+ const LanguageServerProtocol::Range &range) const;
+
+private:
+ QMap<LanguageServerProtocol::DocumentUri, QList<LanguageServerProtocol::Diagnostic>> m_diagnostics;
+ Utils::Id m_clientId;
+};
+
+} // namespace LanguageClient
diff --git a/src/plugins/languageclient/languageclient.pro b/src/plugins/languageclient/languageclient.pro
index 25fe9b5fcc..c60cf4dca8 100644
--- a/src/plugins/languageclient/languageclient.pro
+++ b/src/plugins/languageclient/languageclient.pro
@@ -4,6 +4,7 @@ DEFINES += LANGUAGECLIENT_LIBRARY
HEADERS += \
client.h \
+ diagnosticmanager.h \
documentsymbolcache.h \
dynamiccapabilities.h \
languageclient_global.h \
@@ -26,6 +27,7 @@ HEADERS += \
SOURCES += \
client.cpp \
+ diagnosticmanager.cpp \
documentsymbolcache.cpp \
dynamiccapabilities.cpp \
languageclientcompletionassist.cpp \
diff --git a/src/plugins/languageclient/languageclient.qbs b/src/plugins/languageclient/languageclient.qbs
index 18b34c963c..c4d3385f29 100644
--- a/src/plugins/languageclient/languageclient.qbs
+++ b/src/plugins/languageclient/languageclient.qbs
@@ -16,6 +16,8 @@ QtcPlugin {
files: [
"client.cpp",
"client.h",
+ "diagnosticmanager.cpp",
+ "diagnosticmanager.h",
"documentsymbolcache.cpp",
"documentsymbolcache.h",
"dynamiccapabilities.cpp",