diff --git a/src/plugins/clangcodemodel/clangdclient.cpp b/src/plugins/clangcodemodel/clangdclient.cpp index 9429b6269bd..d0e628e4cce 100644 --- a/src/plugins/clangcodemodel/clangdclient.cpp +++ b/src/plugins/clangcodemodel/clangdclient.cpp @@ -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(&code); - return !codeString || *codeString != "drv_unknown_argument"; - }; - setDiagnosticsHandlers(textMarkCreator, hideDiagsHandler, diagsFilter); setSymbolStringifier(displayNameFromDocumentSymbol); setSemanticTokensHandler([this](TextDocument *doc, const QList &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 filteredDiagnostics(const QList &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(&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( diff --git a/src/plugins/clangcodemodel/clangdclient.h b/src/plugins/clangcodemodel/clangdclient.h index 7c9135a0c57..aa67e3c7898 100644 --- a/src/plugins/clangcodemodel/clangdclient.h +++ b/src/plugins/clangcodemodel/clangdclient.h @@ -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; diff --git a/src/plugins/languageclient/client.cpp b/src/plugins/languageclient/client.cpp index d88c0ae86d2..becb4c3ab47 100644 --- a/src/plugins/languageclient/client.cpp +++ b/src/plugins/languageclient/client.cpp @@ -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 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 ¶ms) const DocumentUri &uri = params.uri(); const QList &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); } diff --git a/src/plugins/languageclient/client.h b/src/plugins/languageclient/client.h index 88e27afbf20..4fb656c9a13 100644 --- a/src/plugins/languageclient/client.h +++ b/src/plugins/languageclient/client.h @@ -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 ¶ms); + virtual DiagnosticManager *createDiagnosticManager(); private: void sendMessage(const LanguageServerProtocol::BaseMessage &message); @@ -300,7 +299,7 @@ private: QHash m_highlightRequests; int m_restartsLeft = 5; QScopedPointer m_clientInterface; - DiagnosticManager m_diagnosticManager; + DiagnosticManager *m_diagnosticManager = nullptr; DocumentSymbolCache m_documentSymbolCache; HoverHandler m_hoverHandler; QHash m_highlights; diff --git a/src/plugins/languageclient/diagnosticmanager.cpp b/src/plugins/languageclient/diagnosticmanager.cpp index a1b729ce9bf..6aadf0b28a4 100644 --- a/src/plugins/languageclient/diagnosticmanager.cpp +++ b/src/plugins/languageclient/diagnosticmanager.cpp @@ -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 &diagnostics, +void DiagnosticManager::setDiagnostics(const DocumentUri &uri, + const QList &diagnostics, const Utils::optional &version) { hideDiagnostics(uri.toFilePath()); - const QList 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 DiagnosticManager::filteredDiagnostics(const QList &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 diff --git a/src/plugins/languageclient/diagnosticmanager.h b/src/plugins/languageclient/diagnosticmanager.h index f201aaf50c2..b6366752ce1 100644 --- a/src/plugins/languageclient/diagnosticmanager.h +++ b/src/plugins/languageclient/diagnosticmanager.h @@ -25,6 +25,8 @@ #pragma once +#include "languageclient_global.h" + #include #include @@ -42,24 +44,21 @@ namespace LanguageClient { class Client; -using TextMarkCreator = std::function; -using HideDiagnosticsHandler = std::function; -using DiagnosticsFilter = std::function; - -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, - const QList &diagnostics, - const Utils::optional &version); + virtual void setDiagnostics(const LanguageServerProtocol::DocumentUri &uri, + const QList &diagnostics, + const Utils::optional &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 filteredDiagnostics( + const QList &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 version; QList diagnostics; }; QMap m_diagnostics; QMap> m_marks; - TextMarkCreator m_textMarkCreator; - HideDiagnosticsHandler m_hideHandler; - DiagnosticsFilter m_filter; Client *m_client; };