forked from qt-creator/qt-creator
LSP: move diagnostic handling from client in a separate class
Change-Id: Id70a7b82137d3a4591de521380199e546e8685f4 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -3,6 +3,7 @@ add_qtc_plugin(LanguageClient
|
|||||||
PLUGIN_DEPENDS ProjectExplorer Core TextEditor
|
PLUGIN_DEPENDS ProjectExplorer Core TextEditor
|
||||||
SOURCES
|
SOURCES
|
||||||
client.cpp client.h
|
client.cpp client.h
|
||||||
|
diagnosticmanager.cpp diagnosticmanager.h
|
||||||
documentsymbolcache.cpp documentsymbolcache.h
|
documentsymbolcache.cpp documentsymbolcache.h
|
||||||
dynamiccapabilities.cpp dynamiccapabilities.h
|
dynamiccapabilities.cpp dynamiccapabilities.h
|
||||||
languageclient.qrc
|
languageclient.qrc
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#include "languageclientutils.h"
|
#include "languageclientutils.h"
|
||||||
#include "semantichighlightsupport.h"
|
#include "semantichighlightsupport.h"
|
||||||
|
|
||||||
|
#include <coreplugin/editormanager/documentmodel.h>
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include <coreplugin/idocument.h>
|
#include <coreplugin/idocument.h>
|
||||||
#include <coreplugin/messagemanager.h>
|
#include <coreplugin/messagemanager.h>
|
||||||
@@ -48,11 +49,9 @@
|
|||||||
#include <texteditor/texteditor.h>
|
#include <texteditor/texteditor.h>
|
||||||
#include <texteditor/texteditoractionhandler.h>
|
#include <texteditor/texteditoractionhandler.h>
|
||||||
#include <texteditor/texteditorsettings.h>
|
#include <texteditor/texteditorsettings.h>
|
||||||
#include <texteditor/textmark.h>
|
|
||||||
#include <utils/mimetypes/mimedatabase.h>
|
#include <utils/mimetypes/mimedatabase.h>
|
||||||
#include <utils/qtcprocess.h>
|
#include <utils/qtcprocess.h>
|
||||||
#include <utils/synchronousprocess.h>
|
#include <utils/synchronousprocess.h>
|
||||||
#include <utils/utilsicons.h>
|
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
@@ -71,34 +70,10 @@ namespace LanguageClient {
|
|||||||
|
|
||||||
static Q_LOGGING_CATEGORY(LOGLSPCLIENT, "qtc.languageclient.client", QtWarningMsg);
|
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)
|
Client::Client(BaseClientInterface *clientInterface)
|
||||||
: m_id(Utils::Id::fromString(QUuid::createUuid().toString()))
|
: m_id(Utils::Id::fromString(QUuid::createUuid().toString()))
|
||||||
, m_clientInterface(clientInterface)
|
, m_clientInterface(clientInterface)
|
||||||
|
, m_diagnosticManager(m_id)
|
||||||
, m_documentSymbolCache(this)
|
, m_documentSymbolCache(this)
|
||||||
, m_hoverHandler(this)
|
, m_hoverHandler(this)
|
||||||
, m_symbolSupport(this)
|
, m_symbolSupport(this)
|
||||||
@@ -145,8 +120,6 @@ Client::~Client()
|
|||||||
widget->removeHoverHandler(&m_hoverHandler);
|
widget->removeHoverHandler(&m_hoverHandler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const DocumentUri &uri : m_diagnostics.keys())
|
|
||||||
removeDiagnostics(uri);
|
|
||||||
for (const DocumentUri &uri : m_highlights.keys()) {
|
for (const DocumentUri &uri : m_highlights.keys()) {
|
||||||
if (TextDocument *doc = TextDocument::textDocumentForFilePath(uri.toFilePath())) {
|
if (TextDocument *doc = TextDocument::textDocumentForFilePath(uri.toFilePath())) {
|
||||||
if (TextEditor::SyntaxHighlighter *highlighter = doc->syntaxHighlighter())
|
if (TextEditor::SyntaxHighlighter *highlighter = doc->syntaxHighlighter())
|
||||||
@@ -387,7 +360,7 @@ void Client::closeDocument(TextEditor::TextDocument *document)
|
|||||||
void Client::activateDocument(TextEditor::TextDocument *document)
|
void Client::activateDocument(TextEditor::TextDocument *document)
|
||||||
{
|
{
|
||||||
auto uri = DocumentUri::fromFilePath(document->filePath());
|
auto uri = DocumentUri::fromFilePath(document->filePath());
|
||||||
showDiagnostics(uri);
|
m_diagnosticManager.showDiagnostics(uri);
|
||||||
SemanticHighligtingSupport::applyHighlight(document, m_highlights.value(uri), capabilities());
|
SemanticHighligtingSupport::applyHighlight(document, m_highlights.value(uri), capabilities());
|
||||||
// only replace the assist provider if the language server support it
|
// only replace the assist provider if the language server support it
|
||||||
if (m_serverCapabilities.completionProvider()) {
|
if (m_serverCapabilities.completionProvider()) {
|
||||||
@@ -417,7 +390,7 @@ void Client::activateDocument(TextEditor::TextDocument *document)
|
|||||||
|
|
||||||
void Client::deactivateDocument(TextEditor::TextDocument *document)
|
void Client::deactivateDocument(TextEditor::TextDocument *document)
|
||||||
{
|
{
|
||||||
hideDiagnostics(document);
|
m_diagnosticManager.hideDiagnostics(document);
|
||||||
resetAssistProviders(document);
|
resetAssistProviders(document);
|
||||||
document->setFormatter(nullptr);
|
document->setFormatter(nullptr);
|
||||||
if (m_serverCapabilities.semanticHighlighting().has_value()) {
|
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> Client::diagnosticsAt(const DocumentUri &uri, const Range &range) const
|
||||||
{
|
{
|
||||||
QList<Diagnostic> diagnostics;
|
return m_diagnosticManager.diagnosticsAt(uri, range);
|
||||||
for (const Diagnostic &diagnostic : m_diagnostics[uri]) {
|
|
||||||
if (diagnostic.range().overlaps(range))
|
|
||||||
diagnostics << diagnostic;
|
|
||||||
}
|
|
||||||
return diagnostics;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Client::start()
|
bool Client::start()
|
||||||
@@ -948,8 +916,7 @@ bool Client::reset()
|
|||||||
updateEditorToolBar(m_openedDocument.keys());
|
updateEditorToolBar(m_openedDocument.keys());
|
||||||
m_serverCapabilities = ServerCapabilities();
|
m_serverCapabilities = ServerCapabilities();
|
||||||
m_dynamicCapabilities.reset();
|
m_dynamicCapabilities.reset();
|
||||||
for (const DocumentUri &uri : m_diagnostics.keys())
|
m_diagnosticManager.clearDiagnostics();
|
||||||
removeDiagnostics(uri);
|
|
||||||
for (TextEditor::TextDocument *document : m_openedDocument.keys())
|
for (TextEditor::TextDocument *document : m_openedDocument.keys())
|
||||||
document->disconnect(this);
|
document->disconnect(this);
|
||||||
for (TextEditor::TextDocument *document : m_resetAssistProvider.keys())
|
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);
|
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
|
const ServerCapabilities &Client::capabilities() const
|
||||||
{
|
{
|
||||||
return m_serverCapabilities;
|
return m_serverCapabilities;
|
||||||
@@ -1060,61 +1015,6 @@ void Client::showMessageBox(const ShowMessageRequestParams &message, const Messa
|
|||||||
box->show();
|
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)
|
void Client::resetAssistProviders(TextEditor::TextDocument *document)
|
||||||
{
|
{
|
||||||
const AssistProviders providers = m_resetAssistProvider.take(document);
|
const AssistProviders providers = m_resetAssistProvider.take(document);
|
||||||
@@ -1269,11 +1169,10 @@ void Client::handleDiagnostics(const PublishDiagnosticsParams ¶ms)
|
|||||||
{
|
{
|
||||||
const DocumentUri &uri = params.uri();
|
const DocumentUri &uri = params.uri();
|
||||||
|
|
||||||
removeDiagnostics(uri);
|
|
||||||
const QList<Diagnostic> &diagnostics = params.diagnostics();
|
const QList<Diagnostic> &diagnostics = params.diagnostics();
|
||||||
m_diagnostics[uri] = diagnostics;
|
m_diagnosticManager.setDiagnostics(uri, params.diagnostics());
|
||||||
if (LanguageClientManager::clientForUri(uri) == this) {
|
if (LanguageClientManager::clientForUri(uri) == this) {
|
||||||
showDiagnostics(uri);
|
m_diagnosticManager.showDiagnostics(uri);
|
||||||
requestCodeActions(uri, diagnostics);
|
requestCodeActions(uri, diagnostics);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "diagnosticmanager.h"
|
||||||
#include "documentsymbolcache.h"
|
#include "documentsymbolcache.h"
|
||||||
#include "dynamiccapabilities.h"
|
#include "dynamiccapabilities.h"
|
||||||
#include "languageclient_global.h"
|
#include "languageclient_global.h"
|
||||||
@@ -64,13 +65,11 @@ namespace TextEditor
|
|||||||
class IAssistProcessor;
|
class IAssistProcessor;
|
||||||
class TextDocument;
|
class TextDocument;
|
||||||
class TextEditorWidget;
|
class TextEditorWidget;
|
||||||
class TextMark;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace LanguageClient {
|
namespace LanguageClient {
|
||||||
|
|
||||||
class BaseClientInterface;
|
class BaseClientInterface;
|
||||||
class TextMark;
|
|
||||||
|
|
||||||
class LANGUAGECLIENT_EXPORT Client : public QObject
|
class LANGUAGECLIENT_EXPORT Client : public QObject
|
||||||
{
|
{
|
||||||
@@ -169,9 +168,6 @@ public:
|
|||||||
Core::MessageManager::PrintToOutputPaneFlag flag = Core::MessageManager::NoModeSwitch)
|
Core::MessageManager::PrintToOutputPaneFlag flag = Core::MessageManager::NoModeSwitch)
|
||||||
{ log(responseError.toString(), flag); }
|
{ log(responseError.toString(), flag); }
|
||||||
|
|
||||||
void showDiagnostics(Core::IDocument *doc);
|
|
||||||
void hideDiagnostics(TextEditor::TextDocument *doc);
|
|
||||||
|
|
||||||
const LanguageServerProtocol::ServerCapabilities &capabilities() const;
|
const LanguageServerProtocol::ServerCapabilities &capabilities() const;
|
||||||
const DynamicCapabilities &dynamicCapabilities() const;
|
const DynamicCapabilities &dynamicCapabilities() const;
|
||||||
const BaseClientInterface *clientInterface() const;
|
const BaseClientInterface *clientInterface() const;
|
||||||
@@ -208,7 +204,6 @@ private:
|
|||||||
void showMessageBox(const LanguageServerProtocol::ShowMessageRequestParams &message,
|
void showMessageBox(const LanguageServerProtocol::ShowMessageRequestParams &message,
|
||||||
const LanguageServerProtocol::MessageId &id);
|
const LanguageServerProtocol::MessageId &id);
|
||||||
|
|
||||||
void showDiagnostics(const LanguageServerProtocol::DocumentUri &uri);
|
|
||||||
void removeDiagnostics(const LanguageServerProtocol::DocumentUri &uri);
|
void removeDiagnostics(const LanguageServerProtocol::DocumentUri &uri);
|
||||||
void resetAssistProviders(TextEditor::TextDocument *document);
|
void resetAssistProviders(TextEditor::TextDocument *document);
|
||||||
void sendPostponedDocumentUpdates();
|
void sendPostponedDocumentUpdates();
|
||||||
@@ -243,7 +238,7 @@ private:
|
|||||||
QHash<LanguageServerProtocol::DocumentUri, LanguageServerProtocol::MessageId> m_highlightRequests;
|
QHash<LanguageServerProtocol::DocumentUri, LanguageServerProtocol::MessageId> m_highlightRequests;
|
||||||
int m_restartsLeft = 5;
|
int m_restartsLeft = 5;
|
||||||
QScopedPointer<BaseClientInterface> m_clientInterface;
|
QScopedPointer<BaseClientInterface> m_clientInterface;
|
||||||
QMap<LanguageServerProtocol::DocumentUri, QList<LanguageServerProtocol::Diagnostic>> m_diagnostics;
|
DiagnosticManager m_diagnosticManager;
|
||||||
DocumentSymbolCache m_documentSymbolCache;
|
DocumentSymbolCache m_documentSymbolCache;
|
||||||
HoverHandler m_hoverHandler;
|
HoverHandler m_hoverHandler;
|
||||||
QHash<LanguageServerProtocol::DocumentUri, TextEditor::HighlightingResults> m_highlights;
|
QHash<LanguageServerProtocol::DocumentUri, TextEditor::HighlightingResults> m_highlights;
|
||||||
|
|||||||
144
src/plugins/languageclient/diagnosticmanager.cpp
Normal file
144
src/plugins/languageclient/diagnosticmanager.cpp
Normal file
@@ -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
|
||||||
62
src/plugins/languageclient/diagnosticmanager.h
Normal file
62
src/plugins/languageclient/diagnosticmanager.h
Normal file
@@ -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
|
||||||
@@ -4,6 +4,7 @@ DEFINES += LANGUAGECLIENT_LIBRARY
|
|||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
client.h \
|
client.h \
|
||||||
|
diagnosticmanager.h \
|
||||||
documentsymbolcache.h \
|
documentsymbolcache.h \
|
||||||
dynamiccapabilities.h \
|
dynamiccapabilities.h \
|
||||||
languageclient_global.h \
|
languageclient_global.h \
|
||||||
@@ -26,6 +27,7 @@ HEADERS += \
|
|||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
client.cpp \
|
client.cpp \
|
||||||
|
diagnosticmanager.cpp \
|
||||||
documentsymbolcache.cpp \
|
documentsymbolcache.cpp \
|
||||||
dynamiccapabilities.cpp \
|
dynamiccapabilities.cpp \
|
||||||
languageclientcompletionassist.cpp \
|
languageclientcompletionassist.cpp \
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ QtcPlugin {
|
|||||||
files: [
|
files: [
|
||||||
"client.cpp",
|
"client.cpp",
|
||||||
"client.h",
|
"client.h",
|
||||||
|
"diagnosticmanager.cpp",
|
||||||
|
"diagnosticmanager.h",
|
||||||
"documentsymbolcache.cpp",
|
"documentsymbolcache.cpp",
|
||||||
"documentsymbolcache.h",
|
"documentsymbolcache.h",
|
||||||
"dynamiccapabilities.cpp",
|
"dynamiccapabilities.cpp",
|
||||||
|
|||||||
Reference in New Issue
Block a user