public async Task TestGetSemanticTokensEdits_EndInsertionAsync()
        {
            var updatedText =
                @"// Comment
static class C { }
// Comment";

            using var testLspServer = await CreateTestLspServerAsync(s_standardCase);

            var caretLocation = testLspServer.GetLocations("caret").First();

            await RunGetSemanticTokensAsync(testLspServer, caretLocation);
            await UpdateDocumentTextAsync(updatedText, testLspServer.TestWorkspace);

            var results = await RunGetSemanticTokensEditsAsync(testLspServer, caretLocation, previousResultId : "1");

            var expectedEdit = new LSP.SemanticTokensEdit
            {
                Start       = 30,
                DeleteCount = 0,
                Data        = new int[] { 1, 0, 10, SemanticTokensCache.TokenTypeToIndex[LSP.SemanticTokenTypes.Comment], 0 }
            };

            Assert.Equal(expectedEdit, ((LSP.SemanticTokensDelta)results).Edits.First());
            Assert.Equal("2", ((LSP.SemanticTokensDelta)results).ResultId);
        }
        public async Task TestGetSemanticTokensEdits_ReturnMinimalEdits()
        {
            var updatedText =
                @"class
// Comment";

            using var testLspServer = CreateTestLspServer(s_singleLineCase, out var locations);
            var caretLocation = locations["caret"].First();

            await RunGetSemanticTokensAsync(testLspServer, caretLocation);

            // Edit text
            UpdateDocumentText(updatedText, testLspServer.TestWorkspace);

            var results = await RunGetSemanticTokensEditsAsync(testLspServer, caretLocation, previousResultId : "1");

            // 1. Updates length of token (10 to 5) and updates token type (comment to keyword)
            // 2. Creates new token for '// Comment'
            var expectedEdit = new LSP.SemanticTokensEdit
            {
                Start       = 2,
                DeleteCount = 0,
                Data        = new int[]
                {
                    // 'class'
                    /* 0, 0, */ 5, SemanticTokensCache.TokenTypeToIndex[LSP.SemanticTokenTypes.Keyword], 0,

                    // '// Comment'
                    1, 0, /* 10,  SemanticTokensCache.TokenTypeToIndex[LSP.SemanticTokenTypes.Comment], 0 */
                }
            };

            Assert.Equal(expectedEdit, ((LSP.SemanticTokensDelta)results).Edits?[0]);
            Assert.Equal("2", ((LSP.SemanticTokensDelta)results).ResultId);
        }
        public async Task TestGetSemanticTokensEdits_EndDeletionAsync()
        {
            var updatedText =
                @"// Comment";

            using var testLspServer = await CreateTestLspServerAsync(s_standardCase);

            var caretLocation = testLspServer.GetLocations("caret").First();

            await RunGetSemanticTokensAsync(testLspServer, caretLocation);
            await UpdateDocumentTextAsync(updatedText, testLspServer.TestWorkspace);

            var results = await RunGetSemanticTokensEditsAsync(testLspServer, caretLocation, previousResultId : "1");

            var expectedEdit = new LSP.SemanticTokensEdit {
                Start = 5, DeleteCount = 25, Data = System.Array.Empty <int>()
            };

            Assert.Equal(expectedEdit, ((LSP.SemanticTokensDelta)results).Edits.First());
            Assert.Equal("2", ((LSP.SemanticTokensDelta)results).ResultId);
        }
        public async Task TestInsertingNewLineInMiddleOfFile()
        {
            var updatedText = @"// Comment

static class C { }";

            using var testLspServer = await CreateTestLspServerAsync(s_standardCase);

            var caretLocation = testLspServer.GetLocations("caret").First();

            await RunGetSemanticTokensAsync(testLspServer, caretLocation);
            await UpdateDocumentTextAsync(updatedText, testLspServer.TestWorkspace);

            var results = await RunGetSemanticTokensEditsAsync(testLspServer, caretLocation, previousResultId : "1");

            var expectedEdit = new LSP.SemanticTokensEdit {
                Start = 5, DeleteCount = 1, Data = new int[] { 2 }
            };

            Assert.Equal(expectedEdit, ((LSP.SemanticTokensDelta)results).Edits.First());
            Assert.Equal("2", ((LSP.SemanticTokensDelta)results).ResultId);
        }
Example #5
0
        public async Task TestAllHandlersAsync()
        {
            var markup =
                @"{|caret:|}// Comment
static class C { }
";

            using var testLspServer = await CreateTestLspServerAsync(markup);

            var caretLocation = testLspServer.GetLocations("caret").First();

            // 1. Range handler
            var range = new LSP.Range {
                Start = new Position(1, 0), End = new Position(2, 0)
            };
            var rangeResults = await RunGetSemanticTokensRangeAsync(testLspServer, caretLocation, range);

            var expectedRangeResults = new LSP.SemanticTokens
            {
                Data = new int[]
                {
                    // Line | Char | Len | Token type                                                               | Modifier
                    1, 0, 6, SemanticTokensCache.TokenTypeToIndex[LSP.SemanticTokenTypes.Keyword], 0,                             // 'static'
                    0, 7, 5, SemanticTokensCache.TokenTypeToIndex[LSP.SemanticTokenTypes.Keyword], 0,                             // 'class'
                    0, 6, 1, SemanticTokensCache.TokenTypeToIndex[ClassificationTypeNames.ClassName], (int)TokenModifiers.Static, // 'C'
                    0, 2, 1, SemanticTokensCache.TokenTypeToIndex[ClassificationTypeNames.Punctuation], 0,                        // '{'
                    0, 2, 1, SemanticTokensCache.TokenTypeToIndex[ClassificationTypeNames.Punctuation], 0,                        // '}'
                },
                ResultId = "1"
            };

            await VerifyNoMultiLineTokens(testLspServer, rangeResults.Data !).ConfigureAwait(false);

            Assert.Equal(expectedRangeResults.Data, rangeResults.Data);
            Assert.Equal(expectedRangeResults.ResultId, rangeResults.ResultId);
            Assert.True(rangeResults is RoslynSemanticTokens);

            // 2. Whole document handler
            var wholeDocResults = await RunGetSemanticTokensAsync(testLspServer, caretLocation);

            var expectedWholeDocResults = new LSP.SemanticTokens
            {
                Data = new int[]
                {
                    // Line | Char | Len | Token type                                                               | Modifier
                    0, 0, 10, SemanticTokensCache.TokenTypeToIndex[LSP.SemanticTokenTypes.Comment], 0,                            // '// Comment'
                    1, 0, 6, SemanticTokensCache.TokenTypeToIndex[LSP.SemanticTokenTypes.Keyword], 0,                             // 'static'
                    0, 7, 5, SemanticTokensCache.TokenTypeToIndex[LSP.SemanticTokenTypes.Keyword], 0,                             // 'class'
                    0, 6, 1, SemanticTokensCache.TokenTypeToIndex[ClassificationTypeNames.ClassName], (int)TokenModifiers.Static, // 'C'
                    0, 2, 1, SemanticTokensCache.TokenTypeToIndex[ClassificationTypeNames.Punctuation], 0,                        // '{'
                    0, 2, 1, SemanticTokensCache.TokenTypeToIndex[ClassificationTypeNames.Punctuation], 0,                        // '}'
                },
                ResultId = "2"
            };

            await VerifyNoMultiLineTokens(testLspServer, wholeDocResults.Data !).ConfigureAwait(false);

            Assert.Equal(expectedWholeDocResults.Data, wholeDocResults.Data);
            Assert.Equal(expectedWholeDocResults.ResultId, wholeDocResults.ResultId);
            Assert.True(wholeDocResults is RoslynSemanticTokens);

            // 3. Edits handler - insert newline at beginning of file
            var newMarkup = @"
// Comment
static class C { }
";

            await UpdateDocumentTextAsync(newMarkup, testLspServer.TestWorkspace);

            var editResults = await RunGetSemanticTokensEditsAsync(testLspServer, caretLocation, previousResultId : "2");

            var expectedEdit = new LSP.SemanticTokensEdit {
                Start = 0, DeleteCount = 1, Data = new int[] { 1 }
            };

            Assert.Equal(expectedEdit, ((LSP.SemanticTokensDelta)editResults).Edits.First());
            Assert.Equal("3", ((LSP.SemanticTokensDelta)editResults).ResultId);
            Assert.True((LSP.SemanticTokensDelta)editResults is RoslynSemanticTokensDelta);

            // 4. Edits handler - no changes (ResultId should remain same)
            var editResultsNoChange = await RunGetSemanticTokensEditsAsync(testLspServer, caretLocation, previousResultId : "3");

            Assert.Equal("3", ((LSP.SemanticTokensDelta)editResultsNoChange).ResultId);
            Assert.True((LSP.SemanticTokensDelta)editResultsNoChange is RoslynSemanticTokensDelta);

            // 5. Re-request whole document handler (may happen if LSP runs into an error)
            var wholeDocResults2 = await RunGetSemanticTokensAsync(testLspServer, caretLocation);

            var expectedWholeDocResults2 = new LSP.SemanticTokens
            {
                Data = new int[]
                {
                    // Line | Char | Len | Token type                                                               | Modifier
                    1, 0, 10, SemanticTokensCache.TokenTypeToIndex[LSP.SemanticTokenTypes.Comment], 0,                            // '// Comment'
                    1, 0, 6, SemanticTokensCache.TokenTypeToIndex[LSP.SemanticTokenTypes.Keyword], 0,                             // 'static'
                    0, 7, 5, SemanticTokensCache.TokenTypeToIndex[LSP.SemanticTokenTypes.Keyword], 0,                             // 'class'
                    0, 6, 1, SemanticTokensCache.TokenTypeToIndex[ClassificationTypeNames.ClassName], (int)TokenModifiers.Static, // 'C'
                    0, 2, 1, SemanticTokensCache.TokenTypeToIndex[ClassificationTypeNames.Punctuation], 0,                        // '{'
                    0, 2, 1, SemanticTokensCache.TokenTypeToIndex[ClassificationTypeNames.Punctuation], 0,                        // '}'
                },
                ResultId = "4"
            };

            await VerifyNoMultiLineTokens(testLspServer, wholeDocResults2.Data !).ConfigureAwait(false);

            Assert.Equal(expectedWholeDocResults2.Data, wholeDocResults2.Data);
            Assert.Equal(expectedWholeDocResults2.ResultId, wholeDocResults2.ResultId);
            Assert.True(wholeDocResults2 is RoslynSemanticTokens);
        }