public async Task <LSP.SemanticTokens> HandleRequestAsync( LSP.SemanticTokensParams request, RequestContext context, CancellationToken cancellationToken) { Contract.ThrowIfNull(request.TextDocument, "TextDocument is null."); Contract.ThrowIfNull(context.Document, "Document is null."); var resultId = _tokensCache.GetNextResultId(); var(tokensData, isFinalized) = await SemanticTokensHelpers.ComputeSemanticTokensDataAsync( context.Document, SemanticTokensCache.TokenTypeToIndex, range : null, cancellationToken).ConfigureAwait(false); var tokens = new RoslynSemanticTokens { ResultId = resultId, Data = tokensData, IsFinalized = isFinalized }; if (tokensData.Length > 0) { await _tokensCache.UpdateCacheAsync(request.TextDocument.Uri, tokens, cancellationToken).ConfigureAwait(false); } return(tokens); }
public async Task <SumType <LSP.SemanticTokens, LSP.SemanticTokensDelta> > HandleRequestAsync( LSP.SemanticTokensDeltaParams request, RequestContext context, CancellationToken cancellationToken) { Contract.ThrowIfNull(request.TextDocument, "TextDocument is null."); Contract.ThrowIfNull(request.PreviousResultId, "previousResultId is null."); Contract.ThrowIfNull(context.Document, "Document is null."); // Even though we want to ultimately pass edits back to LSP, we still need to compute all semantic tokens, // both for caching purposes and in order to have a baseline comparison when computing the edits. var(newSemanticTokensData, isFinalized) = await SemanticTokensHelpers.ComputeSemanticTokensDataAsync( context.Document, SemanticTokensCache.TokenTypeToIndex, range : null, cancellationToken).ConfigureAwait(false); Contract.ThrowIfNull(newSemanticTokensData, "newSemanticTokensData is null."); // Getting the cached tokens for the document. If we don't have an applicable cached token set, // we can't calculate edits, so we must return all semantic tokens instead. Likewise, if the new // token set is empty, there's no need to calculate edits. var oldSemanticTokensData = await _tokensCache.GetCachedTokensDataAsync( request.TextDocument.Uri, request.PreviousResultId, cancellationToken).ConfigureAwait(false); if (oldSemanticTokensData == null || newSemanticTokensData.Length == 0) { var newResultId = _tokensCache.GetNextResultId(); var updatedTokens = new RoslynSemanticTokens { ResultId = newResultId, Data = newSemanticTokensData, IsFinalized = isFinalized, }; if (newSemanticTokensData.Length > 0) { await _tokensCache.UpdateCacheAsync( request.TextDocument.Uri, updatedTokens, cancellationToken).ConfigureAwait(false); } return(updatedTokens); } var editArray = await ComputeSemanticTokensEditsAsync(oldSemanticTokensData, newSemanticTokensData).ConfigureAwait(false); var resultId = request.PreviousResultId; // If we have edits, generate a new ResultId. Otherwise, re-use the previous one. if (editArray.Length != 0) { resultId = _tokensCache.GetNextResultId(); var updatedTokens = new RoslynSemanticTokens { ResultId = resultId, Data = newSemanticTokensData, IsFinalized = isFinalized }; await _tokensCache.UpdateCacheAsync( request.TextDocument.Uri, updatedTokens, cancellationToken).ConfigureAwait(false); } var edits = new RoslynSemanticTokensDelta { ResultId = resultId, Edits = editArray, IsFinalized = isFinalized }; return(edits); }