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 <david.schulz@qt.io>
This commit is contained in:
Christian Kandeler
2022-02-04 10:59:11 +01:00
parent 531e24892b
commit 15280d7127
3 changed files with 37 additions and 6 deletions

View File

@@ -1544,8 +1544,18 @@ void ClangdClient::handleDiagnostics(const PublishDiagnosticsParams &params)
return; return;
for (const Diagnostic &diagnostic : params.diagnostics()) { for (const Diagnostic &diagnostic : params.diagnostics()) {
const ClangdDiagnostic clangdDiagnostic(diagnostic); const ClangdDiagnostic clangdDiagnostic(diagnostic);
for (const CodeAction &action : clangdDiagnostic.codeActions().value_or(QList<CodeAction>{})) const auto codeActions = clangdDiagnostic.codeActions();
LanguageClient::updateCodeActionRefactoringMarker(this, action, uri); 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<QString>(&code);
if (codeString && *codeString == "-Wswitch")
requestCodeActions(uri, diagnostic);
}
} }
} }

View File

@@ -866,7 +866,19 @@ SymbolSupport &Client::symbolSupport()
return m_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<Diagnostic> &diagnostics) void Client::requestCodeActions(const DocumentUri &uri, const QList<Diagnostic> &diagnostics)
{
requestCodeActions(uri, {}, diagnostics);
}
void Client::requestCodeActions(const DocumentUri &uri, const Range &range,
const QList<Diagnostic> &diagnostics)
{ {
const Utils::FilePath fileName = uri.toFilePath(); const Utils::FilePath fileName = uri.toFilePath();
TextEditor::TextDocument *doc = TextEditor::TextDocument::textDocumentForFilePath(fileName); TextEditor::TextDocument *doc = TextEditor::TextDocument::textDocumentForFilePath(fileName);
@@ -878,10 +890,14 @@ void Client::requestCodeActions(const DocumentUri &uri, const QList<Diagnostic>
context.setDiagnostics(diagnostics); context.setDiagnostics(diagnostics);
codeActionParams.setContext(context); codeActionParams.setContext(context);
codeActionParams.setTextDocument(TextDocumentIdentifier(uri)); codeActionParams.setTextDocument(TextDocumentIdentifier(uri));
Position start(0, 0); if (range.isEmpty()) {
const QTextBlock &lastBlock = doc->document()->lastBlock(); Position start(0, 0);
Position end(lastBlock.blockNumber(), lastBlock.length() - 1); const QTextBlock &lastBlock = doc->document()->lastBlock();
codeActionParams.setRange(Range(start, end)); Position end(lastBlock.blockNumber(), lastBlock.length() - 1);
codeActionParams.setRange(Range(start, end));
} else {
codeActionParams.setRange(range);
}
CodeActionRequest request(codeActionParams); CodeActionRequest request(codeActionParams);
request.setResponseCallback( request.setResponseCallback(
[uri, self = QPointer<Client>(this)](const CodeActionRequest::Response &response) { [uri, self = QPointer<Client>(this)](const CodeActionRequest::Response &response) {

View File

@@ -168,6 +168,8 @@ public:
void updateConfiguration(const QJsonValue &configuration); void updateConfiguration(const QJsonValue &configuration);
// commands // commands
void requestCodeActions(const LanguageServerProtocol::DocumentUri &uri,
const LanguageServerProtocol::Diagnostic &diagnostic);
void requestCodeActions(const LanguageServerProtocol::DocumentUri &uri, void requestCodeActions(const LanguageServerProtocol::DocumentUri &uri,
const QList<LanguageServerProtocol::Diagnostic> &diagnostics); const QList<LanguageServerProtocol::Diagnostic> &diagnostics);
void requestCodeActions(const LanguageServerProtocol::CodeActionRequest &request); void requestCodeActions(const LanguageServerProtocol::CodeActionRequest &request);
@@ -253,6 +255,9 @@ private:
void requestDocumentHighlightsNow(TextEditor::TextEditorWidget *widget); void requestDocumentHighlightsNow(TextEditor::TextEditorWidget *widget);
LanguageServerProtocol::SemanticRequestTypes supportedSemanticRequests(TextEditor::TextDocument *document) const; LanguageServerProtocol::SemanticRequestTypes supportedSemanticRequests(TextEditor::TextDocument *document) const;
void handleSemanticTokens(const LanguageServerProtocol::SemanticTokens &tokens); void handleSemanticTokens(const LanguageServerProtocol::SemanticTokens &tokens);
void requestCodeActions(const LanguageServerProtocol::DocumentUri &uri,
const LanguageServerProtocol::Range &range,
const QList<LanguageServerProtocol::Diagnostic> &diagnostics);
void documentClosed(Core::IDocument *document); void documentClosed(Core::IDocument *document);
virtual void handleDocumentClosed(TextEditor::TextDocument *) {} virtual void handleDocumentClosed(TextEditor::TextDocument *) {}