ClangCodeModel: remove duplicates from clangd quickfix assist

Do not report quickfixes with a diagnostic since those are already
collected by the ClangdQuickFixFactory as builtin quickfixes.

Change-Id: I8d29a08b823291f8beaa762c09b7d29a4b9d0384
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
David Schulz
2022-05-13 14:57:08 +02:00
parent 85d2159e41
commit b2e2421d2d
3 changed files with 70 additions and 38 deletions

View File

@@ -1429,12 +1429,31 @@ private:
return nullptr;
}
void handleProposalReady(const QuickFixOperations &ops) override
TextEditor::GenericProposal *handleCodeActionResult(const CodeActionResult &result) override
{
// Step 3: Merge the results upon callback from clangd.
for (const auto &op : ops)
auto toOperation =
[=](const Utils::variant<Command, CodeAction> &item) -> QuickFixOperation * {
if (auto action = Utils::get_if<CodeAction>(&item)) {
const Utils::optional<QList<Diagnostic>> diagnostics = action->diagnostics();
if (!diagnostics.has_value() || diagnostics->isEmpty())
return new CodeActionQuickFixOperation(*action, client());
}
if (auto command = Utils::get_if<Command>(&item))
return new CommandQuickFixOperation(*command, client());
return nullptr;
};
if (auto list = Utils::get_if<QList<Utils::variant<Command, CodeAction>>>(&result)) {
QuickFixOperations ops;
for (const Utils::variant<Command, CodeAction> &item : *list) {
if (QuickFixOperation *op = toOperation(item)) {
op->setDescription("clangd: " + op->description());
setAsyncProposalAvailable(GenericProposal::createProposal(m_interface, ops + m_builtinOps));
ops << op;
}
}
return GenericProposal::createProposal(m_interface, ops + m_builtinOps);
}
return nullptr;
}
QuickFixOperations m_builtinOps;

View File

@@ -55,23 +55,17 @@ void CodeActionQuickFixOperation::perform()
m_client->executeCommand(*command);
}
class CommandQuickFixOperation : public QuickFixOperation
{
public:
CommandQuickFixOperation(const Command &command, Client *client)
CommandQuickFixOperation::CommandQuickFixOperation(const Command &command, Client *client)
: m_command(command)
, m_client(client)
{ setDescription(command.title()); }
void perform() override
{
{ setDescription(command.title()); }
void CommandQuickFixOperation::perform()
{
if (m_client)
m_client->executeCommand(m_command);
}
private:
Command m_command;
QPointer<Client> m_client;
};
}
IAssistProposal *LanguageClientQuickFixAssistProcessor::perform(const AssistInterface *interface)
{
@@ -119,24 +113,26 @@ void LanguageClientQuickFixAssistProcessor::handleCodeActionResponse(const CodeA
m_currentRequest.reset();
if (const Utils::optional<CodeActionRequest::Response::Error> &error = response.error())
m_client->log(*error);
m_client->removeAssistProcessor(this);
GenericProposal *proposal = nullptr;
if (const Utils::optional<CodeActionResult> &result = response.result())
proposal = handleCodeActionResult(*result);
setAsyncProposalAvailable(proposal);
}
GenericProposal *LanguageClientQuickFixAssistProcessor::handleCodeActionResult(const CodeActionResult &result)
{
if (auto list = Utils::get_if<QList<Utils::variant<Command, CodeAction>>>(&result)) {
QuickFixOperations ops;
if (const Utils::optional<CodeActionResult> &result = response.result()) {
if (auto list = Utils::get_if<QList<Utils::variant<Command, CodeAction>>>(&*result)) {
for (const Utils::variant<Command, CodeAction> &item : *list) {
if (auto action = Utils::get_if<CodeAction>(&item))
ops << new CodeActionQuickFixOperation(*action, m_client);
else if (auto command = Utils::get_if<Command>(&item))
ops << new CommandQuickFixOperation(*command, m_client);
}
return GenericProposal::createProposal(m_assistInterface.data(), ops);
}
}
m_client->removeAssistProcessor(this);
handleProposalReady(ops);
}
void LanguageClientQuickFixAssistProcessor::handleProposalReady(const QuickFixOperations &ops)
{
setAsyncProposalAvailable(GenericProposal::createProposal(m_assistInterface.data(), ops));
return nullptr;
}
LanguageClientQuickFixProvider::LanguageClientQuickFixProvider(Client *client)

View File

@@ -35,7 +35,10 @@
#include <QPointer>
namespace TextEditor { class IAssistProposal; }
namespace TextEditor {
class IAssistProposal;
class GenericProposal;
} // namespace TextEditor
namespace LanguageClient {
@@ -52,6 +55,17 @@ private:
QPointer<Client> m_client;
};
class LANGUAGECLIENT_EXPORT CommandQuickFixOperation : public TextEditor::QuickFixOperation
{
public:
CommandQuickFixOperation(const LanguageServerProtocol::Command &command, Client *client);
void perform() override;
private:
LanguageServerProtocol::Command m_command;
QPointer<Client> m_client;
};
class LANGUAGECLIENT_EXPORT LanguageClientQuickFixProvider : public TextEditor::IAssistProvider
{
public:
@@ -77,10 +91,13 @@ public:
protected:
void setOnlyKinds(const QList<LanguageServerProtocol::CodeActionKind> &only);
Client *client() { return m_client; }
private:
void handleCodeActionResponse(const LanguageServerProtocol::CodeActionRequest::Response &response);
virtual void handleProposalReady(const TextEditor::QuickFixOperations &ops);
void handleCodeActionResponse(
const LanguageServerProtocol::CodeActionRequest::Response &response);
virtual TextEditor::GenericProposal *handleCodeActionResult(
const LanguageServerProtocol::CodeActionResult &result);
QSharedPointer<const TextEditor::AssistInterface> m_assistInterface;
Client *m_client = nullptr; // not owned