LanguageClient: disable diagnostics after document changes

Calculating new diagnostics after a document change can take a while.
The old ClangCodeModel disabled diagnostics (changed the color to gray)
that were reported before the last document change after some time.
Adapt this behavior to Clangd and other LSP based codemodels.

Change-Id: I0589ba0d0c023f6e7ea3e97fc5b45eb156ddcd37
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
David Schulz
2022-05-23 12:33:01 +02:00
parent 16aaf8c59c
commit 4ab935349f
3 changed files with 31 additions and 10 deletions

View File

@@ -918,6 +918,7 @@ void Client::documentContentsChanged(TextEditor::TextDocument *document,
{ {
if (!d->m_openedDocument.contains(document) || !reachable()) if (!d->m_openedDocument.contains(document) || !reachable())
return; return;
d->m_diagnosticManager->disableDiagnostics(document);
const QString method(DidChangeTextDocumentNotification::methodName); const QString method(DidChangeTextDocumentNotification::methodName);
TextDocumentSyncKind syncKind = d->m_serverCapabilities.textDocumentSyncKindHelper(); TextDocumentSyncKind syncKind = d->m_serverCapabilities.textDocumentSyncKindHelper();
if (Utils::optional<bool> registered = d->m_dynamicCapabilities.isRegistered(method)) { if (Utils::optional<bool> registered = d->m_dynamicCapabilities.isRegistered(method)) {

View File

@@ -90,7 +90,7 @@ void DiagnosticManager::hideDiagnostics(const Utils::FilePath &filePath)
for (BaseTextEditor *editor : BaseTextEditor::textEditorsForDocument(doc)) for (BaseTextEditor *editor : BaseTextEditor::textEditorsForDocument(doc))
editor->editorWidget()->setExtraSelections(m_extraSelectionsId, {}); editor->editorWidget()->setExtraSelections(m_extraSelectionsId, {});
} }
qDeleteAll(m_marks.take(filePath)); m_marks.remove(filePath);
} }
QList<Diagnostic> DiagnosticManager::filteredDiagnostics(const QList<Diagnostic> &diagnostics) const QList<Diagnostic> DiagnosticManager::filteredDiagnostics(const QList<Diagnostic> &diagnostics) const
@@ -98,6 +98,17 @@ QList<Diagnostic> DiagnosticManager::filteredDiagnostics(const QList<Diagnostic>
return diagnostics; return diagnostics;
} }
void DiagnosticManager::disableDiagnostics(TextEditor::TextDocument *document)
{
Marks &marks = m_marks[document->filePath()];
if (!marks.enabled)
return;
for (TextEditor::TextMark *mark : marks.marks)
mark->setColor(Utils::Theme::Color::IconsDisabledColor);
marks.enabled = false;
}
void DiagnosticManager::showDiagnostics(const DocumentUri &uri, int version) void DiagnosticManager::showDiagnostics(const DocumentUri &uri, int version)
{ {
const FilePath &filePath = uri.toFilePath(); const FilePath &filePath = uri.toFilePath();
@@ -106,7 +117,7 @@ void DiagnosticManager::showDiagnostics(const DocumentUri &uri, int version)
const VersionedDiagnostics &versionedDiagnostics = m_diagnostics.value(uri); const VersionedDiagnostics &versionedDiagnostics = m_diagnostics.value(uri);
if (versionedDiagnostics.version.value_or(version) == version if (versionedDiagnostics.version.value_or(version) == version
&& !versionedDiagnostics.diagnostics.isEmpty()) { && !versionedDiagnostics.diagnostics.isEmpty()) {
QList<TextEditor::TextMark *> &marks = m_marks[filePath]; Marks &marks = m_marks[filePath];
const bool isProjectFile = m_client->project() const bool isProjectFile = m_client->project()
&& m_client->project()->isKnownFile(filePath); && m_client->project()->isKnownFile(filePath);
for (const Diagnostic &diagnostic : versionedDiagnostics.diagnostics) { for (const Diagnostic &diagnostic : versionedDiagnostics.diagnostics) {
@@ -115,9 +126,9 @@ void DiagnosticManager::showDiagnostics(const DocumentUri &uri, int version)
if (!selection.cursor.isNull()) if (!selection.cursor.isNull())
extraSelections << selection; extraSelections << selection;
if (TextEditor::TextMark *mark = createTextMark(filePath, diagnostic, isProjectFile)) if (TextEditor::TextMark *mark = createTextMark(filePath, diagnostic, isProjectFile))
marks.append(mark); marks.marks.append(mark);
} }
if (!marks.isEmpty()) if (!marks.marks.isEmpty())
emit textMarkCreated(filePath); emit textMarkCreated(filePath);
} }
@@ -170,11 +181,7 @@ void DiagnosticManager::clearDiagnostics()
for (const DocumentUri &uri : m_diagnostics.keys()) for (const DocumentUri &uri : m_diagnostics.keys())
hideDiagnostics(uri.toFilePath()); hideDiagnostics(uri.toFilePath());
m_diagnostics.clear(); m_diagnostics.clear();
if (!QTC_GUARD(m_marks.isEmpty())) { QTC_ASSERT(m_marks.isEmpty(), m_marks.clear());
for (const QList<TextEditor::TextMark *> &marks : qAsConst(m_marks))
qDeleteAll(marks);
m_marks.clear();
}
} }
QList<Diagnostic> DiagnosticManager::diagnosticsAt(const DocumentUri &uri, QList<Diagnostic> DiagnosticManager::diagnosticsAt(const DocumentUri &uri,
@@ -218,4 +225,9 @@ bool DiagnosticManager::hasDiagnostics(const TextDocument *doc) const
return !it->diagnostics.isEmpty(); return !it->diagnostics.isEmpty();
} }
DiagnosticManager::Marks::~Marks()
{
qDeleteAll(marks);
}
} // namespace LanguageClient } // namespace LanguageClient

View File

@@ -61,6 +61,7 @@ public:
virtual QList<LanguageServerProtocol::Diagnostic> filteredDiagnostics( virtual QList<LanguageServerProtocol::Diagnostic> filteredDiagnostics(
const QList<LanguageServerProtocol::Diagnostic> &diagnostics) const; const QList<LanguageServerProtocol::Diagnostic> &diagnostics) const;
void disableDiagnostics(TextEditor::TextDocument *document);
void clearDiagnostics(); void clearDiagnostics();
QList<LanguageServerProtocol::Diagnostic> diagnosticsAt( QList<LanguageServerProtocol::Diagnostic> diagnosticsAt(
@@ -91,7 +92,14 @@ private:
QList<LanguageServerProtocol::Diagnostic> diagnostics; QList<LanguageServerProtocol::Diagnostic> diagnostics;
}; };
QMap<LanguageServerProtocol::DocumentUri, VersionedDiagnostics> m_diagnostics; QMap<LanguageServerProtocol::DocumentUri, VersionedDiagnostics> m_diagnostics;
QMap<Utils::FilePath, QList<TextEditor::TextMark *>> m_marks; class Marks
{
public:
~Marks();
bool enabled = true;
QList<TextEditor::TextMark *> marks;
};
QMap<Utils::FilePath, Marks> m_marks;
Client *m_client; Client *m_client;
Utils::Id m_extraSelectionsId; Utils::Id m_extraSelectionsId;
}; };