LanguageClient: fix semanctic token delta data manipulation

Make sure that multiple edits are in order.

The SemanticTokensEdit start is relative to the start of the data and
not to the position of the previous edit.

Do not try to be smart when calculating the start of the modification,
but assume that start is always a preedit index.

Change-Id: I3e1513f5fe631aac21fecb5e0611d987355e2c21
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
David Schulz
2021-05-06 12:39:37 +02:00
parent cb39e2404c
commit 0ab08e8574

View File

@@ -378,29 +378,29 @@ void SemanticTokenSupport::handleSemanticTokensDelta(
if (auto tokens = Utils::get_if<SemanticTokens>(&result)) { if (auto tokens = Utils::get_if<SemanticTokens>(&result)) {
m_tokens[filePath] = *tokens; m_tokens[filePath] = *tokens;
} else if (auto tokensDelta = Utils::get_if<SemanticTokensDelta>(&result)) { } else if (auto tokensDelta = Utils::get_if<SemanticTokensDelta>(&result)) {
const QList<SemanticTokensEdit> &edits = tokensDelta->edits(); QList<SemanticTokensEdit> edits = tokensDelta->edits();
if (edits.isEmpty()) if (edits.isEmpty())
return; return;
Utils::sort(edits, &SemanticTokensEdit::start);
SemanticTokens &tokens = m_tokens[filePath]; SemanticTokens &tokens = m_tokens[filePath];
QList<int> data = tokens.data(); const QList<int> &data = tokens.data();
int newDataSize = data.size(); int newDataSize = data.size();
for (const SemanticTokensEdit &edit : edits) for (const SemanticTokensEdit &edit : qAsConst(edits))
newDataSize += edit.dataSize() - edit.deleteCount(); newDataSize += edit.dataSize() - edit.deleteCount();
QList<int> newData; QList<int> newData;
newData.reserve(newDataSize); newData.reserve(newDataSize);
auto it = data.begin(); auto it = data.begin();
int currentDelta = 0; for (const SemanticTokensEdit &edit : qAsConst(edits)) {
for (const SemanticTokensEdit &edit : edits) { if (edit.start() > data.size()) // prevent edits after the previously reported data
for (const auto start = it + edit.start() + currentDelta; it != start; ++it) return;
for (const auto start = data.begin() + edit.start(); it < start; ++it)
newData.append(*it); newData.append(*it);
const QList<int> insertData = edit.data().value_or(QList<int>()); newData.append(edit.data().value_or(QList<int>()));
newData.append(insertData); it += edit.deleteCount();
const int deleteCount = edit.deleteCount();
currentDelta += insertData.size() - deleteCount;
it += deleteCount;
} }
for (const auto end = data.end(); it != end; ++it) for (const auto end = data.end(); it != end; ++it)
newData.append(*it); newData.append(*it);