LanguageClient: fix crash in call and type hierarchy

The response to a request sent by Call or TypeHierarchy was still
handled by deleted Hierarchy instances. This happens when a second
request was sent before the first was handled. Make sure to cancel a
potentially running request when destructing a hierarchy in order to
prevent accessing the deleted instance.

Change-Id: Icd810f7a6e9eb090b28f13cb1a3254f75a27cdbb
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
David Schulz
2024-09-24 14:23:53 +02:00
parent 88edec1bf4
commit 3004ebc0af

View File

@@ -287,6 +287,12 @@ public:
theWidget, [this](const QModelIndex &index) { onItemDoubleClicked(index); }); theWidget, [this](const QModelIndex &index) { onItemDoubleClicked(index); });
} }
~HierarchyWidgetHelper()
{
if (m_runningRequest && m_runningRequest->first)
m_runningRequest->first->cancelRequest(m_runningRequest->second);
}
void updateHierarchyAtCursorPosition() void updateHierarchyAtCursorPosition()
{ {
m_model.clear(); m_model.clear();
@@ -315,6 +321,17 @@ protected:
item->forChildrenAtLevel(1, [&](const TreeItem *child) { m_view->expand(child->index()); }); item->forChildrenAtLevel(1, [&](const TreeItem *child) { m_view->expand(child->index()); });
} }
void send(Client *client, const JsonRpcMessage &request, const MessageId &requestId)
{
m_runningRequest = std::make_pair(QPointer<Client>(client), requestId);
client->sendMessage(request);
}
void resetRunningRequest()
{
m_runningRequest.reset();
}
private: private:
virtual void sendRequest(Client *client, const TextDocumentPositionParams &params, virtual void sendRequest(Client *client, const TextDocumentPositionParams &params,
const Core::IDocument *document) = 0; const Core::IDocument *document) = 0;
@@ -334,6 +351,7 @@ private:
AnnotatedItemDelegate m_delegate; AnnotatedItemDelegate m_delegate;
NavigationTreeView * const m_view; NavigationTreeView * const m_view;
std::optional<std::pair<QPointer<Client>, MessageId>> m_runningRequest;
TreeModel<TreeItem> m_model; TreeModel<TreeItem> m_model;
}; };
@@ -358,12 +376,13 @@ private:
const PrepareCallHierarchyRequest::Response &response) { const PrepareCallHierarchyRequest::Response &response) {
handlePrepareResponse(client, response); handlePrepareResponse(client, response);
}); });
client->sendMessage(request); send(client, request, request.id());
} }
void handlePrepareResponse(Client *client, void handlePrepareResponse(Client *client,
const PrepareCallHierarchyRequest::Response &response) const PrepareCallHierarchyRequest::Response &response)
{ {
resetRunningRequest();
if (!client) if (!client)
return; return;
const std::optional<PrepareCallHierarchyRequest::Response::Error> error = response.error(); const std::optional<PrepareCallHierarchyRequest::Response::Error> error = response.error();
@@ -401,12 +420,13 @@ private:
const PrepareTypeHierarchyRequest::Response &response) { const PrepareTypeHierarchyRequest::Response &response) {
handlePrepareResponse(client, response); handlePrepareResponse(client, response);
}); });
client->sendMessage(request); send(client, request, request.id());
} }
void handlePrepareResponse(Client *client, void handlePrepareResponse(Client *client,
const PrepareTypeHierarchyRequest::Response &response) const PrepareTypeHierarchyRequest::Response &response)
{ {
resetRunningRequest();
if (!client) if (!client)
return; return;
const std::optional<PrepareTypeHierarchyRequest::Response::Error> error = response.error(); const std::optional<PrepareTypeHierarchyRequest::Response::Error> error = response.error();