LanguageClient: export DiagnosticManager

Change-Id: I60b3e6b14bf364da60fb8b3de6d5d5cc1cd2e634
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
David Schulz
2022-04-01 07:34:49 +02:00
parent 929e40a9f2
commit e437cf7a71
6 changed files with 92 additions and 70 deletions

View File

@@ -1427,20 +1427,6 @@ ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir)
}
setCurrentProject(project);
setDocumentChangeUpdateThreshold(d->settings.documentUpdateThreshold);
const auto textMarkCreator = [this](const Utils::FilePath &filePath,
const Diagnostic &diag, bool isProjectFile) {
if (d->isTesting)
emit textMarkCreated(filePath);
return new ClangdTextMark(filePath, diag, isProjectFile, this);
};
const auto hideDiagsHandler = []{ ClangDiagnosticManager::clearTaskHubIssues(); };
static const auto diagsFilter = [](const Diagnostic &diag) {
const Diagnostic::Code code = diag.code().value_or(Diagnostic::Code());
const QString * const codeString = Utils::get_if<QString>(&code);
return !codeString || *codeString != "drv_unknown_argument";
};
setDiagnosticsHandlers(textMarkCreator, hideDiagsHandler, diagsFilter);
setSymbolStringifier(displayNameFromDocumentSymbol);
setSemanticTokensHandler([this](TextDocument *doc, const QList<ExpandedSemanticToken> &tokens,
int version, bool force) {
@@ -1615,6 +1601,44 @@ const LanguageClient::Client::CustomInspectorTabs ClangdClient::createCustomInsp
return {std::make_pair(new MemoryUsageWidget(this), tr("Memory Usage"))};
}
class ClangdDiagnosticManager : public LanguageClient::DiagnosticManager
{
public:
using LanguageClient::DiagnosticManager::DiagnosticManager;
void hideDiagnostics(const Utils::FilePath &filePath) override
{
DiagnosticManager::hideDiagnostics(filePath);
ClangDiagnosticManager::clearTaskHubIssues();
}
QList<Diagnostic> filteredDiagnostics(const QList<Diagnostic> &diagnostics) const override
{
return Utils::filtered(diagnostics, [](const Diagnostic &diag){
const Diagnostic::Code code = diag.code().value_or(Diagnostic::Code());
const QString * const codeString = Utils::get_if<QString>(&code);
return !codeString || *codeString != "drv_unknown_argument";
});
}
TextMark *createTextMark(const Utils::FilePath &filePath,
const Diagnostic &diagnostic,
bool isProjectFile) const override
{
return new ClangdTextMark(filePath, diagnostic, isProjectFile, client());
}
};
DiagnosticManager *ClangdClient::createDiagnosticManager()
{
auto diagnosticManager = new ClangdDiagnosticManager(this);
if (d->isTesting) {
connect(diagnosticManager, &DiagnosticManager::textMarkCreated,
this, &ClangdClient::textMarkCreated);
}
return diagnosticManager;
}
RefactoringChangesData *ClangdClient::createRefactoringChangesBackend() const
{
return new CppEditor::CppRefactoringChangesData(

View File

@@ -112,6 +112,7 @@ private:
TextEditor::TextDocument *doc) override;
const CustomInspectorTabs createCustomInspectorTabs() override;
TextEditor::RefactoringChangesData *createRefactoringChangesBackend() const override;
LanguageClient::DiagnosticManager *createDiagnosticManager() override;
class Private;
class FollowSymbolData;

View File

@@ -81,7 +81,6 @@ static Q_LOGGING_CATEGORY(LOGLSPCLIENT, "qtc.languageclient.client", QtWarningMs
Client::Client(BaseClientInterface *clientInterface)
: m_id(Utils::Id::fromString(QUuid::createUuid().toString()))
, m_clientInterface(clientInterface)
, m_diagnosticManager(this)
, m_documentSymbolCache(this)
, m_hoverHandler(this)
, m_symbolSupport(this)
@@ -158,6 +157,7 @@ Client::~Client()
// do not handle messages while shutting down
disconnect(m_clientInterface.data(), &BaseClientInterface::messageReceived,
this, &Client::handleMessage);
delete m_diagnosticManager;
}
static ClientCapabilities generateClientCapabilities()
@@ -598,7 +598,8 @@ void Client::activateDocument(TextEditor::TextDocument *document)
{
const FilePath &filePath = document->filePath();
auto uri = DocumentUri::fromFilePath(filePath);
m_diagnosticManager.showDiagnostics(uri, m_documentVersions.value(filePath));
if (m_diagnosticManager)
m_diagnosticManager->showDiagnostics(uri, m_documentVersions.value(filePath));
m_tokenSupport.updateSemanticTokens(document);
// only replace the assist provider if the language server support it
updateCompletionProvider(document);
@@ -622,7 +623,8 @@ void Client::activateDocument(TextEditor::TextDocument *document)
void Client::deactivateDocument(TextEditor::TextDocument *document)
{
m_diagnosticManager.hideDiagnostics(document->filePath());
if (m_diagnosticManager)
m_diagnosticManager->hideDiagnostics(document->filePath());
resetAssistProviders(document);
document->setFormatter(nullptr);
m_tokenSupport.clearHighlight(document);
@@ -1075,20 +1077,22 @@ void Client::removeAssistProcessor(TextEditor::IAssistProcessor *processor)
QList<Diagnostic> Client::diagnosticsAt(const DocumentUri &uri, const QTextCursor &cursor) const
{
return m_diagnosticManager.diagnosticsAt(uri, cursor);
if (m_diagnosticManager)
return m_diagnosticManager->diagnosticsAt(uri, cursor);
return {};
}
bool Client::hasDiagnostic(const LanguageServerProtocol::DocumentUri &uri,
const LanguageServerProtocol::Diagnostic &diag) const
{
return m_diagnosticManager.hasDiagnostic(uri, documentForFilePath(uri.toFilePath()), diag);
if (m_diagnosticManager)
return m_diagnosticManager->hasDiagnostic(uri, documentForFilePath(uri.toFilePath()), diag);
return false;
}
void Client::setDiagnosticsHandlers(const TextMarkCreator &textMarkCreator,
const HideDiagnosticsHandler &hideHandler,
const DiagnosticsFilter &filter)
DiagnosticManager *Client::createDiagnosticManager()
{
m_diagnosticManager.setDiagnosticsHandlers(textMarkCreator, hideHandler, filter);
return new DiagnosticManager(this);
}
void Client::setSemanticTokensHandler(const SemanticTokensHandler &handler)
@@ -1165,7 +1169,8 @@ bool Client::reset()
updateEditorToolBar(m_openedDocument.keys());
m_serverCapabilities = ServerCapabilities();
m_dynamicCapabilities.reset();
m_diagnosticManager.clearDiagnostics();
if (m_diagnosticManager)
m_diagnosticManager->clearDiagnostics();
for (auto it = m_openedDocument.cbegin(); it != m_openedDocument.cend(); ++it)
it.key()->disconnect(this);
m_openedDocument.clear();
@@ -1503,9 +1508,11 @@ void Client::handleDiagnostics(const PublishDiagnosticsParams &params)
const DocumentUri &uri = params.uri();
const QList<Diagnostic> &diagnostics = params.diagnostics();
m_diagnosticManager.setDiagnostics(uri, diagnostics, params.version());
if (!m_diagnosticManager)
m_diagnosticManager = createDiagnosticManager();
m_diagnosticManager->setDiagnostics(uri, diagnostics, params.version());
if (LanguageClientManager::clientForUri(uri) == this) {
m_diagnosticManager.showDiagnostics(uri, m_documentVersions.value(uri.toFilePath()));
m_diagnosticManager->showDiagnostics(uri, m_documentVersions.value(uri.toFilePath()));
if (m_autoRequestCodeActions)
requestCodeActions(uri, diagnostics);
}

View File

@@ -188,8 +188,6 @@ public:
const QTextCursor &cursor) const;
bool hasDiagnostic(const LanguageServerProtocol::DocumentUri &uri,
const LanguageServerProtocol::Diagnostic &diag) const;
void setDiagnosticsHandlers(const TextMarkCreator &textMarkCreator,
const HideDiagnosticsHandler &hideHandler, const DiagnosticsFilter &filter);
void setSemanticTokensHandler(const SemanticTokensHandler &handler);
void setSymbolStringifier(const LanguageServerProtocol::SymbolStringifier &stringifier);
LanguageServerProtocol::SymbolStringifier symbolStringifier() const;
@@ -227,6 +225,7 @@ protected:
const QString &message);
void handleMessage(const LanguageServerProtocol::BaseMessage &message);
virtual void handleDiagnostics(const LanguageServerProtocol::PublishDiagnosticsParams &params);
virtual DiagnosticManager *createDiagnosticManager();
private:
void sendMessage(const LanguageServerProtocol::BaseMessage &message);
@@ -300,7 +299,7 @@ private:
QHash<TextEditor::TextEditorWidget *, LanguageServerProtocol::MessageId> m_highlightRequests;
int m_restartsLeft = 5;
QScopedPointer<BaseClientInterface> m_clientInterface;
DiagnosticManager m_diagnosticManager;
DiagnosticManager *m_diagnosticManager = nullptr;
DocumentSymbolCache m_documentSymbolCache;
HoverHandler m_hoverHandler;
QHash<LanguageServerProtocol::DocumentUri, TextEditor::HighlightingResults> m_highlights;

View File

@@ -75,9 +75,6 @@ private:
DiagnosticManager::DiagnosticManager(Client *client)
: m_client(client)
{
m_textMarkCreator = [this](const FilePath &filePath, const Diagnostic &diagnostic, bool /*isProjectFile*/) {
return createTextMark(filePath, diagnostic);
};
}
DiagnosticManager::~DiagnosticManager()
@@ -85,20 +82,16 @@ DiagnosticManager::~DiagnosticManager()
clearDiagnostics();
}
void DiagnosticManager::setDiagnostics(const LanguageServerProtocol::DocumentUri &uri,
const QList<LanguageServerProtocol::Diagnostic> &diagnostics,
void DiagnosticManager::setDiagnostics(const DocumentUri &uri,
const QList<Diagnostic> &diagnostics,
const Utils::optional<int> &version)
{
hideDiagnostics(uri.toFilePath());
const QList<Diagnostic> filteredDiags = m_filter
? Utils::filtered(diagnostics, m_filter) : diagnostics;
m_diagnostics[uri] = {version, filteredDiags};
m_diagnostics[uri] = {version, filteredDiagnostics(diagnostics)};
}
void DiagnosticManager::hideDiagnostics(const Utils::FilePath &filePath)
{
if (m_hideHandler)
m_hideHandler();
if (auto doc = TextDocument::textDocumentForFilePath(filePath)) {
for (BaseTextEditor *editor : BaseTextEditor::textEditorsForDocument(doc))
editor->editorWidget()->setExtraSelections(TextEditorWidget::CodeWarningsSelection, {});
@@ -106,6 +99,11 @@ void DiagnosticManager::hideDiagnostics(const Utils::FilePath &filePath)
qDeleteAll(m_marks.take(filePath));
}
QList<Diagnostic> DiagnosticManager::filteredDiagnostics(const QList<Diagnostic> &diagnostics) const
{
return diagnostics;
}
static QTextEdit::ExtraSelection toDiagnosticsSelections(const Diagnostic &diagnostic,
QTextDocument *textDocument)
{
@@ -134,8 +132,10 @@ void DiagnosticManager::showDiagnostics(const DocumentUri &uri, int version)
&& m_client->project()->isKnownFile(filePath);
for (const Diagnostic &diagnostic : versionedDiagnostics.diagnostics) {
extraSelections << toDiagnosticsSelections(diagnostic, doc->document());
marks.append(m_textMarkCreator(filePath, diagnostic, isProjectFile));
marks.append(createTextMark(filePath, diagnostic, isProjectFile));
}
if (!marks.isEmpty())
emit textMarkCreated(filePath);
}
for (BaseTextEditor *editor : BaseTextEditor::textEditorsForDocument(doc)) {
@@ -146,7 +146,8 @@ void DiagnosticManager::showDiagnostics(const DocumentUri &uri, int version)
}
TextEditor::TextMark *DiagnosticManager::createTextMark(const FilePath &filePath,
const Diagnostic &diagnostic) const
const Diagnostic &diagnostic,
bool isProjectFile) const
{
static const auto icon = QIcon::fromTheme("edit-copy", Utils::Icons::COPY.icon());
static const QString tooltip = tr("Copy to Clipboard");
@@ -202,13 +203,4 @@ bool DiagnosticManager::hasDiagnostic(const LanguageServerProtocol::DocumentUri
return it->diagnostics.contains(diag);
}
void DiagnosticManager::setDiagnosticsHandlers(const TextMarkCreator &textMarkCreator,
const HideDiagnosticsHandler &removalHandler,
const DiagnosticsFilter &filter)
{
m_textMarkCreator = textMarkCreator;
m_hideHandler = removalHandler;
m_filter = filter;
}
} // namespace LanguageClient

View File

@@ -25,6 +25,8 @@
#pragma once
#include "languageclient_global.h"
#include <languageserverprotocol/lsptypes.h>
#include <utils/id.h>
@@ -42,24 +44,21 @@ namespace LanguageClient {
class Client;
using TextMarkCreator = std::function<TextEditor::TextMark *(const Utils::FilePath &,
const LanguageServerProtocol::Diagnostic &, bool)>;
using HideDiagnosticsHandler = std::function<void()>;
using DiagnosticsFilter = std::function<bool(const LanguageServerProtocol::Diagnostic &)>;
class DiagnosticManager
class LANGUAGECLIENT_EXPORT DiagnosticManager : public QObject
{
Q_DECLARE_TR_FUNCTIONS(LanguageClient::DiagnosticManager)
Q_OBJECT
public:
explicit DiagnosticManager(Client *client);
~DiagnosticManager();
void setDiagnostics(const LanguageServerProtocol::DocumentUri &uri,
virtual void setDiagnostics(const LanguageServerProtocol::DocumentUri &uri,
const QList<LanguageServerProtocol::Diagnostic> &diagnostics,
const Utils::optional<int> &version);
void showDiagnostics(const LanguageServerProtocol::DocumentUri &uri, int version);
void hideDiagnostics(const Utils::FilePath &filePath);
virtual void showDiagnostics(const LanguageServerProtocol::DocumentUri &uri, int version);
virtual void hideDiagnostics(const Utils::FilePath &filePath);
virtual QList<LanguageServerProtocol::Diagnostic> filteredDiagnostics(
const QList<LanguageServerProtocol::Diagnostic> &diagnostics) const;
void clearDiagnostics();
@@ -70,22 +69,22 @@ public:
const TextEditor::TextDocument *doc,
const LanguageServerProtocol::Diagnostic &diag) const;
void setDiagnosticsHandlers(const TextMarkCreator &shownHandler,
const HideDiagnosticsHandler &removalHandler,
const DiagnosticsFilter &filter);
signals:
void textMarkCreated(const Utils::FilePath &path);
protected:
Client *client() const { return m_client; }
virtual TextEditor::TextMark *createTextMark(const Utils::FilePath &filePath,
const LanguageServerProtocol::Diagnostic &diagnostic,
bool isProjectFile) const;
private:
TextEditor::TextMark *createTextMark(const Utils::FilePath &filePath,
const LanguageServerProtocol::Diagnostic &diagnostic) const;
struct VersionedDiagnostics {
Utils::optional<int> version;
QList<LanguageServerProtocol::Diagnostic> diagnostics;
};
QMap<LanguageServerProtocol::DocumentUri, VersionedDiagnostics> m_diagnostics;
QMap<Utils::FilePath, QList<TextEditor::TextMark *>> m_marks;
TextMarkCreator m_textMarkCreator;
HideDiagnosticsHandler m_hideHandler;
DiagnosticsFilter m_filter;
Client *m_client;
};