Esempio n. 1
0
        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);
        }