Esempio n. 1
0
        public void GetSemanticTokens_Razor_SomeTagHelpers_ThenNone()
        {
            var txt          = $"@addTagHelper *, TestAssembly{Environment.NewLine}<test1></test1>";
            var expectedData = new int[] {
                1, 1, 5, 0, 0,
                0, 8, 5, 0, 0,
            };

            var previousResultId = AssertSemanticTokens(txt, expectedData, isRazor: false, out var service);

            var newTxt          = $"addTagHelper *, TestAssembly{Environment.NewLine}<p></p>";
            var newExpectedData = new SemanticTokensDelta
            {
                Edits = new List <SemanticTokensEdit>
                {
                    new SemanticTokensEdit
                    {
                        Start       = 0,
                        Data        = Array.Empty <int>().ToImmutableArray(),
                        DeleteCount = 10,
                    }
                }
            };

            var newResultId = AssertSemanticTokenEdits(newTxt, newExpectedData, isRazor: false, previousResultId: previousResultId, out var _, service);

            Assert.NotEqual(previousResultId, newResultId);
        }
Esempio n. 2
0
        public void GetSemanticTokens_Razor_OnlyDifferences_NewLines()
        {
            var txt          = $"@addTagHelper *, TestAssembly{Environment.NewLine}<test1></test1>";
            var expectedData = new List <int> {
                1, 1, 5, 0, 0, //line, character pos, length, tokenType, modifier
                0, 8, 5, 0, 0
            };

            var previousResultId = AssertSemanticTokens(txt, expectedData, isRazor: false, out var service);

            var newTxt = $"@addTagHelper *, TestAssembly{Environment.NewLine}<test1></test1>{Environment.NewLine}" +
                         $"<test1></test1>";
            var newExpectedData = new SemanticTokensDelta
            {
                Edits = new List <SemanticTokensEdit> {
                    new SemanticTokensEdit
                    {
                        Start = 10,
                        Data  = new int[] {
                            1, 1, 5, 0, 0,
                            0, 8, 5, 0, 0,
                        }.ToImmutableArray(),
                DeleteCount = 0,
                    }
                }
            };
            var newResultId = AssertSemanticTokenEdits(newTxt, newExpectedData, isRazor: false, previousResultId: previousResultId, out _, service);

            Assert.NotEqual(previousResultId, newResultId);
        }
Esempio n. 3
0
        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 = 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.
            var oldSemanticTokensData = await _tokensCache.GetCachedTokensDataAsync(
                request.TextDocument.Uri, request.PreviousResultId, cancellationToken).ConfigureAwait(false);

            if (oldSemanticTokensData == null)
            {
                var newResultId = _tokensCache.GetNextResultId();
                return(new LSP.SemanticTokens {
                    ResultId = newResultId, Data = newSemanticTokensData
                });
            }

            var resultId  = request.PreviousResultId;
            var editArray = ComputeSemanticTokensEdits(oldSemanticTokensData, newSemanticTokensData);

            // If we have edits, generate a new ResultId. Otherwise, re-use the previous one.
            if (editArray.Length != 0)
            {
                resultId = _tokensCache.GetNextResultId();
                var updatedTokens = new LSP.SemanticTokens {
                    ResultId = resultId, Data = newSemanticTokensData
                };
                await _tokensCache.UpdateCacheAsync(
                    request.TextDocument.Uri, updatedTokens, cancellationToken).ConfigureAwait(false);
            }

            var edits = new SemanticTokensDelta
            {
                Edits    = editArray,
                ResultId = resultId
            };

            return(edits);
        }
        public static SemanticTokensFullOrDelta ComputeSemanticTokensEdits(
            SemanticTokensResponse newTokens,
            IReadOnlyList <int> previousResults)
        {
            var differ = new SemanticTokensEditsDiffer(previousResults, newTokens.Data);
            var diffs  = differ.ComputeDiff();
            var edits  = differ.ProcessEdits(diffs);
            var result = new SemanticTokensDelta
            {
                ResultId = newTokens.ResultId,
                Edits    = edits,
            };

            return(result);
        }
Esempio n. 5
0
        public void GetSemanticTokens_Razor_CoalesceDeleteAndAdd()
        {
            var txt          = $"@addTagHelper *, TestAssembly{Environment.NewLine}<test1 />";
            var expectedData = new List <int>
            {
                1, 1, 5, 0, 0, //line, character pos, length, tokenType, modifier
            };

            var previousResultId = AssertSemanticTokens(txt, expectedData, isRazor: false, out var service);

            var newTxt          = $"@addTagHelper *, TestAssembly{Environment.NewLine}{Environment.NewLine}  <p @minimized></p>";
            var newExpectedData = new SemanticTokensDelta
            {
                Edits = new SemanticTokensEdit[] {
                    new SemanticTokensEdit
                    {
                        Start       = 0,
                        DeleteCount = 0,
                        Data        = new List <int> {
                            2, 5,
                        }.ToImmutableArray(),
                    },
                    new SemanticTokensEdit
                    {
                        Start       = 1,
                        DeleteCount = 0,
                        Data        = new List <int>
                        {
                            2, 0, 0,
                        }.ToImmutableArray(),
                    },
                    new SemanticTokensEdit
                    {
                        Start       = 2,
                        DeleteCount = 2,
                        Data        = new List <int>
                        {
                            9, 4,
                        }.ToImmutableArray()
                    }
                }
            };

            var newResultId = AssertSemanticTokenEdits(newTxt, newExpectedData, isRazor: true, previousResultId: previousResultId, out var _, service);

            Assert.NotEqual(previousResultId, newResultId);
        }
Esempio n. 6
0
        public void GetSemanticTokens_Razor_Modify()
        {
            var txt = $"@addTagHelper *, TestAssembly{Environment.NewLine}" +
                      $"<test1 bool-val=\"true\" />{Environment.NewLine}" +
                      $"<test1 bool-val=\"true\" />{Environment.NewLine}" +
                      $"<test1 bool-val=\"true\" />{Environment.NewLine}";
            var expectedData = new List <int> {
                1, 1, 5, 0, 0, //line, character pos, length, tokenType, modifier
                0, 6, 8, 1, 0,
                1, 1, 5, 0, 0,
                0, 6, 8, 1, 0,
                1, 1, 5, 0, 0,
                0, 6, 8, 1, 0,
            };

            var previousResultId = AssertSemanticTokens(txt, expectedData, isRazor: false, out var service);

            var newTxt = $"@addTagHelper *, TestAssembly{Environment.NewLine}" +
                         $"<test1 bool-va=\"true\" />{Environment.NewLine}" +
                         $"<test1 bool-val=\"true\" />{Environment.NewLine}" +
                         $"<test1 bool-val=\"true\" />{Environment.NewLine}";
            var newExpectedData = new SemanticTokensDelta
            {
                Edits = new List <SemanticTokensEdit>
                {
                    new SemanticTokensEdit
                    {
                        Start       = 5,
                        Data        = Array.Empty <int>().ToImmutableArray(),
                        DeleteCount = 5,
                    },
                }
            };
            var newResultId = AssertSemanticTokenEdits(newTxt, newExpectedData, isRazor: false, previousResultId: previousResultId, out _, service);

            Assert.NotEqual(previousResultId, newResultId);
        }
Esempio n. 7
0
        public SemanticTokensFullOrDelta GetSemanticTokensEdits()
        {
            if (!_prevData.HasValue)
            {
                return(GetSemanticTokens());
            }

            var prevData       = _prevData.Value;
            var prevDataLength = prevData.Length;
            var dataLength     = Data.Length;
            var startIndex     = 0;

            while (startIndex < dataLength && startIndex < prevDataLength && prevData[startIndex] ==
                   Data[startIndex])
            {
                startIndex++;
            }

            if (startIndex < dataLength && startIndex < prevDataLength)
            {
                // Find end index
                var endIndex = 0;
                while (endIndex < dataLength && endIndex < prevDataLength &&
                       prevData[prevDataLength - 1 - endIndex] == Data[dataLength - 1 - endIndex])
                {
                    endIndex++;
                }

                var newData = ImmutableArray.Create(Data, startIndex, dataLength - endIndex - startIndex);
                var result  = new SemanticTokensDelta {
                    ResultId = Id,
                    Edits    = new[] {
                        new SemanticTokensEdit {
                            Start       = startIndex,
                            DeleteCount = prevDataLength - endIndex - startIndex,
                            Data        = newData
                        }
                    }
                };
                return(result);
            }

            if (startIndex < dataLength)
            {
                return(new SemanticTokensDelta {
                    ResultId = Id, Edits = new[] {
                        new SemanticTokensEdit {
                            Start = startIndex,
                            DeleteCount = 0,
                            Data = ImmutableArray.Create(Data, startIndex, DataLen - startIndex)
                        }
                    }
                });
            }

            if (startIndex < prevDataLength)
            {
                return(new SemanticTokensDelta {
                    ResultId = Id,
                    Edits = new[] {
                        new SemanticTokensEdit {
                            Start = startIndex,
                            DeleteCount = prevDataLength - startIndex
                        }
                    }
                });
            }

            return(new SemanticTokensDelta {
                ResultId = Id, Edits = Array.Empty <SemanticTokensEdit>()
            });
        }