forked from qt-creator/qt-creator
LanguageClient: keep semantic tokens after receiving error
A usual error we receive for semantic request is that the request got canceled. This can be due to external changes. But a server might still be able to calculate a diff against a previous token set. So just keep the previously reported tokens and rerequest a new highlight. If the server is not able to calculate a diff it also might send a full token set as a result for the delta request according to the protocol. Fixes: QTCREATORBUG-26624 Change-Id: Ia91e599706519dbbf4cd22050484e4f36cecdab8 Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
@@ -67,19 +67,33 @@ void SemanticTokenSupport::refresh()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SemanticTokenSupport::reloadSemanticTokens(TextDocument *textDocument)
|
void SemanticTokenSupport::reloadSemanticTokens(TextDocument *textDocument)
|
||||||
|
{
|
||||||
|
reloadSemanticTokensImpl(textDocument);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SemanticTokenSupport::reloadSemanticTokensImpl(TextDocument *textDocument,
|
||||||
|
int remainingRerequests)
|
||||||
{
|
{
|
||||||
const SemanticRequestTypes supportedRequests = supportedSemanticRequests(textDocument);
|
const SemanticRequestTypes supportedRequests = supportedSemanticRequests(textDocument);
|
||||||
if (supportedRequests.testFlag(SemanticRequestType::None))
|
if (supportedRequests.testFlag(SemanticRequestType::None))
|
||||||
return;
|
return;
|
||||||
const Utils::FilePath filePath = textDocument->filePath();
|
const Utils::FilePath filePath = textDocument->filePath();
|
||||||
const TextDocumentIdentifier docId(DocumentUri::fromFilePath(filePath));
|
const TextDocumentIdentifier docId(DocumentUri::fromFilePath(filePath));
|
||||||
auto responseCallback = [this, filePath, documentVersion = m_client->documentVersion(filePath)](
|
auto responseCallback = [this,
|
||||||
|
remainingRerequests,
|
||||||
|
filePath,
|
||||||
|
documentVersion = m_client->documentVersion(filePath)](
|
||||||
const SemanticTokensFullRequest::Response &response) {
|
const SemanticTokensFullRequest::Response &response) {
|
||||||
if (const auto error = response.error()) {
|
if (const auto error = response.error()) {
|
||||||
qCDebug(LOGLSPHIGHLIGHT)
|
qCDebug(LOGLSPHIGHLIGHT)
|
||||||
<< "received error" << error->code() << error->message() << "for" << filePath;
|
<< "received error" << error->code() << error->message() << "for" << filePath;
|
||||||
|
if (remainingRerequests > 0) {
|
||||||
|
if (auto document = TextDocument::textDocumentForFilePath(filePath))
|
||||||
|
reloadSemanticTokensImpl(document, remainingRerequests - 1);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
handleSemanticTokens(filePath, response.result().value_or(nullptr), documentVersion);
|
handleSemanticTokens(filePath, response.result().value_or(nullptr), documentVersion);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
/*if (supportedRequests.testFlag(SemanticRequestType::Range)) {
|
/*if (supportedRequests.testFlag(SemanticRequestType::Range)) {
|
||||||
const int start = widget->firstVisibleBlockNumber();
|
const int start = widget->firstVisibleBlockNumber();
|
||||||
@@ -107,6 +121,12 @@ void SemanticTokenSupport::reloadSemanticTokens(TextDocument *textDocument)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SemanticTokenSupport::updateSemanticTokens(TextDocument *textDocument)
|
void SemanticTokenSupport::updateSemanticTokens(TextDocument *textDocument)
|
||||||
|
{
|
||||||
|
updateSemanticTokensImpl(textDocument);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SemanticTokenSupport::updateSemanticTokensImpl(TextDocument *textDocument,
|
||||||
|
int remainingRerequests)
|
||||||
{
|
{
|
||||||
const SemanticRequestTypes supportedRequests = supportedSemanticRequests(textDocument);
|
const SemanticRequestTypes supportedRequests = supportedSemanticRequests(textDocument);
|
||||||
if (supportedRequests.testFlag(SemanticRequestType::FullDelta)) {
|
if (supportedRequests.testFlag(SemanticRequestType::FullDelta)) {
|
||||||
@@ -122,15 +142,22 @@ void SemanticTokenSupport::updateSemanticTokens(TextDocument *textDocument)
|
|||||||
params.setPreviousResultId(previousResultId);
|
params.setPreviousResultId(previousResultId);
|
||||||
SemanticTokensFullDeltaRequest request(params);
|
SemanticTokensFullDeltaRequest request(params);
|
||||||
request.setResponseCallback(
|
request.setResponseCallback(
|
||||||
[this, filePath, documentVersion](
|
[this, filePath, documentVersion, remainingRerequests](
|
||||||
const SemanticTokensFullDeltaRequest::Response &response) {
|
const SemanticTokensFullDeltaRequest::Response &response) {
|
||||||
if (const auto error = response.error()) {
|
if (const auto error = response.error()) {
|
||||||
qCDebug(LOGLSPHIGHLIGHT) << "received error" << error->code()
|
qCDebug(LOGLSPHIGHLIGHT) << "received error" << error->code()
|
||||||
<< error->message() << "for" << filePath;
|
<< error->message() << "for" << filePath;
|
||||||
|
if (auto document = TextDocument::textDocumentForFilePath(filePath)) {
|
||||||
|
if (remainingRerequests > 0)
|
||||||
|
updateSemanticTokensImpl(document, remainingRerequests - 1);
|
||||||
|
else
|
||||||
|
reloadSemanticTokensImpl(document, 1); // try a full reload once
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
handleSemanticTokensDelta(filePath,
|
handleSemanticTokensDelta(filePath,
|
||||||
response.result().value_or(nullptr),
|
response.result().value_or(nullptr),
|
||||||
documentVersion);
|
documentVersion);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
qCDebug(LOGLSPHIGHLIGHT)
|
qCDebug(LOGLSPHIGHLIGHT)
|
||||||
<< "Requesting delta for" << filePath << "with version" << documentVersion;
|
<< "Requesting delta for" << filePath << "with version" << documentVersion;
|
||||||
@@ -292,11 +319,6 @@ void SemanticTokenSupport::handleSemanticTokens(const Utils::FilePath &filePath,
|
|||||||
if (auto tokens = Utils::get_if<SemanticTokens>(&result)) {
|
if (auto tokens = Utils::get_if<SemanticTokens>(&result)) {
|
||||||
m_tokens[filePath] = {*tokens, documentVersion};
|
m_tokens[filePath] = {*tokens, documentVersion};
|
||||||
highlight(filePath);
|
highlight(filePath);
|
||||||
} else {
|
|
||||||
qCDebug(LOGLSPHIGHLIGHT)
|
|
||||||
<< "no data in reply to full semantic tokens request, clearing tokens"
|
|
||||||
<< m_client->name() << filePath;
|
|
||||||
m_tokens.remove(filePath);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -363,12 +385,6 @@ void SemanticTokenSupport::handleSemanticTokensDelta(
|
|||||||
qCDebug(LOGLSPHIGHLIGHT) << "New Data " << newData;
|
qCDebug(LOGLSPHIGHLIGHT) << "New Data " << newData;
|
||||||
tokens.setData(newData);
|
tokens.setData(newData);
|
||||||
tokens.setResultId(tokensDelta->resultId());
|
tokens.setResultId(tokensDelta->resultId());
|
||||||
} else {
|
|
||||||
qCDebug(LOGLSPHIGHLIGHT)
|
|
||||||
<< "no data in reply to semantic tokens delta request, clearing tokens"
|
|
||||||
<< m_client->name() << filePath;
|
|
||||||
m_tokens.remove(filePath);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
highlight(filePath);
|
highlight(filePath);
|
||||||
}
|
}
|
||||||
|
@@ -83,6 +83,8 @@ public:
|
|||||||
void setTokensHandler(const SemanticTokensHandler &handler) { m_tokensHandler = handler; }
|
void setTokensHandler(const SemanticTokensHandler &handler) { m_tokensHandler = handler; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void reloadSemanticTokensImpl(TextEditor::TextDocument *doc, int remainingRerequests = 3);
|
||||||
|
void updateSemanticTokensImpl(TextEditor::TextDocument *doc, int remainingRerequests = 3);
|
||||||
LanguageServerProtocol::SemanticRequestTypes supportedSemanticRequests(
|
LanguageServerProtocol::SemanticRequestTypes supportedSemanticRequests(
|
||||||
TextEditor::TextDocument *document) const;
|
TextEditor::TextDocument *document) const;
|
||||||
void handleSemanticTokens(const Utils::FilePath &filePath,
|
void handleSemanticTokens(const Utils::FilePath &filePath,
|
||||||
|
Reference in New Issue
Block a user