From 15280d71273603a8c5e4cc4e97b8a41a0e1275b9 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Fri, 4 Feb 2022 10:59:11 +0100 Subject: [PATCH] ClangCodeModel: Request clangd quickfix for -Wswitch warning This way, a warning about missing switch cases will be accompanied by a matching code action, which allows the user to fix it right away by clicking on the lightbulb. Requires clangd >= 15; see https://reviews.llvm.org/D118976. Change-Id: I11e82264c41e4154f979d28a5e44e72c8158595b Reviewed-by: David Schulz --- src/plugins/clangcodemodel/clangdclient.cpp | 14 ++++++++++-- src/plugins/languageclient/client.cpp | 24 +++++++++++++++++---- src/plugins/languageclient/client.h | 5 +++++ 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/plugins/clangcodemodel/clangdclient.cpp b/src/plugins/clangcodemodel/clangdclient.cpp index cfa58315945..fe495d9eed6 100644 --- a/src/plugins/clangcodemodel/clangdclient.cpp +++ b/src/plugins/clangcodemodel/clangdclient.cpp @@ -1544,8 +1544,18 @@ void ClangdClient::handleDiagnostics(const PublishDiagnosticsParams ¶ms) return; for (const Diagnostic &diagnostic : params.diagnostics()) { const ClangdDiagnostic clangdDiagnostic(diagnostic); - for (const CodeAction &action : clangdDiagnostic.codeActions().value_or(QList{})) - LanguageClient::updateCodeActionRefactoringMarker(this, action, uri); + const auto codeActions = clangdDiagnostic.codeActions(); + if (codeActions && !codeActions->isEmpty()) { + for (const CodeAction &action : *codeActions) + LanguageClient::updateCodeActionRefactoringMarker(this, action, uri); + } else { + // We know that there's only one kind of diagnostic for which clangd has + // a quickfix tweak, so let's not be wasteful. + const Diagnostic::Code code = diagnostic.code().value_or(Diagnostic::Code()); + const QString * const codeString = Utils::get_if(&code); + if (codeString && *codeString == "-Wswitch") + requestCodeActions(uri, diagnostic); + } } } diff --git a/src/plugins/languageclient/client.cpp b/src/plugins/languageclient/client.cpp index 467cd021665..8158254163e 100644 --- a/src/plugins/languageclient/client.cpp +++ b/src/plugins/languageclient/client.cpp @@ -866,7 +866,19 @@ SymbolSupport &Client::symbolSupport() return m_symbolSupport; } +void Client::requestCodeActions(const LanguageServerProtocol::DocumentUri &uri, + const LanguageServerProtocol::Diagnostic &diagnostic) +{ + requestCodeActions(uri, diagnostic.range(), {diagnostic}); +} + void Client::requestCodeActions(const DocumentUri &uri, const QList &diagnostics) +{ + requestCodeActions(uri, {}, diagnostics); +} + +void Client::requestCodeActions(const DocumentUri &uri, const Range &range, + const QList &diagnostics) { const Utils::FilePath fileName = uri.toFilePath(); TextEditor::TextDocument *doc = TextEditor::TextDocument::textDocumentForFilePath(fileName); @@ -878,10 +890,14 @@ void Client::requestCodeActions(const DocumentUri &uri, const QList context.setDiagnostics(diagnostics); codeActionParams.setContext(context); codeActionParams.setTextDocument(TextDocumentIdentifier(uri)); - Position start(0, 0); - const QTextBlock &lastBlock = doc->document()->lastBlock(); - Position end(lastBlock.blockNumber(), lastBlock.length() - 1); - codeActionParams.setRange(Range(start, end)); + if (range.isEmpty()) { + Position start(0, 0); + const QTextBlock &lastBlock = doc->document()->lastBlock(); + Position end(lastBlock.blockNumber(), lastBlock.length() - 1); + codeActionParams.setRange(Range(start, end)); + } else { + codeActionParams.setRange(range); + } CodeActionRequest request(codeActionParams); request.setResponseCallback( [uri, self = QPointer(this)](const CodeActionRequest::Response &response) { diff --git a/src/plugins/languageclient/client.h b/src/plugins/languageclient/client.h index a689797a968..cffdbb0ac93 100644 --- a/src/plugins/languageclient/client.h +++ b/src/plugins/languageclient/client.h @@ -168,6 +168,8 @@ public: void updateConfiguration(const QJsonValue &configuration); // commands + void requestCodeActions(const LanguageServerProtocol::DocumentUri &uri, + const LanguageServerProtocol::Diagnostic &diagnostic); void requestCodeActions(const LanguageServerProtocol::DocumentUri &uri, const QList &diagnostics); void requestCodeActions(const LanguageServerProtocol::CodeActionRequest &request); @@ -253,6 +255,9 @@ private: void requestDocumentHighlightsNow(TextEditor::TextEditorWidget *widget); LanguageServerProtocol::SemanticRequestTypes supportedSemanticRequests(TextEditor::TextDocument *document) const; void handleSemanticTokens(const LanguageServerProtocol::SemanticTokens &tokens); + void requestCodeActions(const LanguageServerProtocol::DocumentUri &uri, + const LanguageServerProtocol::Range &range, + const QList &diagnostics); void documentClosed(Core::IDocument *document); virtual void handleDocumentClosed(TextEditor::TextDocument *) {}