/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/LanguageServer/ProtocolUnitTests/SemanticTokens/AbstractSemanticTokensTests.cs
128 строк
6 KB
David Wengier
Remove unused classes, constants, methods
23 апр 2026, 04:05
23 апр 2026, 04:05
5cc07ee
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.LanguageServer.Handler.SemanticTokens; using Roslyn.LanguageServer.Protocol; using Roslyn.Test.Utilities; using Xunit; using Xunit.Abstractions; using LSP = Roslyn.LanguageServer.Protocol; namespace Microsoft.CodeAnalysis.LanguageServer.UnitTests.SemanticTokens; public abstract class AbstractSemanticTokensTests : AbstractLanguageServerProtocolTests { protected AbstractSemanticTokensTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) { } private protected static IReadOnlyDictionary<string, int> GetTokenTypeToIndex(TestLspServer server) => SemanticTokensSchema.GetSchema(server.ClientCapabilities.HasVisualStudioLspCapability()).TokenTypeToIndex; private protected static async Task<LSP.SemanticTokens> RunGetSemanticTokensFullAsync(TestLspServer testLspServer, LSP.Location caret) { var result = await testLspServer.ExecuteRequestAsync<LSP.SemanticTokensFullParams, LSP.SemanticTokens>(LSP.Methods.TextDocumentSemanticTokensFullName, CreateSemanticTokensFullParams(caret), CancellationToken.None); Contract.ThrowIfNull(result); return result; } private protected static async Task<LSP.SemanticTokens> RunGetSemanticTokensRangeAsync(TestLspServer testLspServer, LSP.Location location) { var result = await testLspServer.ExecuteRequestAsync<LSP.SemanticTokensRangeParams, LSP.SemanticTokens>(LSP.Methods.TextDocumentSemanticTokensRangeName, CreateSemanticTokensRangeParams(location), CancellationToken.None); Contract.ThrowIfNull(result); return result; } private static LSP.SemanticTokensFullParams CreateSemanticTokensFullParams(LSP.Location caret) => new() { TextDocument = new LSP.TextDocumentIdentifier { DocumentUri = caret.DocumentUri } }; private static LSP.SemanticTokensRangeParams CreateSemanticTokensRangeParams(LSP.Location location) => new() { TextDocument = new LSP.TextDocumentIdentifier { DocumentUri = location.DocumentUri }, Range = location.Range }; // VS doesn't currently support multi-line tokens, so we want to verify that we aren't // returning any in the tokens array. private protected static async Task VerifyBasicInvariantsAndNoMultiLineTokens(TestLspServer testLspServer, int[] tokens) { var document = testLspServer.GetCurrentSolution().Projects.First().Documents.First(); var text = await document.GetTextAsync().ConfigureAwait(false); var currentLine = 0; var currentChar = 0; Assert.True(tokens.Length % 5 == 0); for (var i = 0; i < tokens.Length; i += 5) { // i: line # (relative to previous line) // i + 1: character # (relative to start of previous token in the line or 0) // i + 2: token length // Gets the current absolute line index Assert.True(tokens[i] >= 0, "The line offset should never be negative."); currentLine += tokens[i]; // Gets the character # relative to the start of the line Assert.True(tokens[i + 1] >= 0, "The character offset should never be negative."); if (tokens[i] != 0) { currentChar = tokens[i + 1]; } else { currentChar += tokens[i + 1]; Assert.True(currentChar >= 0, "The first token on the line can't be a negative position, but applying an offset took us there."); } // Gets the length of the token var tokenLength = tokens[i + 2]; Assert.True(tokenLength >= 0, "The token cannot have a negative length."); var lineLength = text.Lines[currentLine].SpanIncludingLineBreak.Length; // If this assertion fails, we didn't break up a multi-line token properly. var tokenTypeToIndex = GetTokenTypeToIndex(testLspServer); var kind = tokenTypeToIndex.Where(kvp => kvp.Value == tokens[i + 3]).Single().Key; Assert.True(currentChar + tokenLength <= lineLength, $"Multi-line token of type {kind} found on line {currentLine} at character index {currentChar}. " + $"The token ends at index {currentChar + tokenLength}, which exceeds the line length of {lineLength}."); } } /// <summary> /// This converts the raw array form back to a slightly more readable form for the purposes of understanding the diff should a test /// fail. This groups rows by five (so that way the diff can't desynced from the start of a new token), and also replaces the token index /// back with the string again. /// </summary> private protected static ImmutableArray<string> ConvertToReadableFormat( ClientCapabilities capabilities, int[] data) { var convertedStringsBuilder = ImmutableArray.CreateBuilder<string>(data.Length / 5); var tokenTypeToIndex = SemanticTokensSchema.GetSchema(capabilities.HasVisualStudioLspCapability()).TokenTypeToIndex; for (var i = 0; i < data.Length; i += 5) { var kind = tokenTypeToIndex.Single(kvp => kvp.Value == data[i + 3]).Key; convertedStringsBuilder.Add($"{data[i]}, {data[i + 1]}, {data[i + 2]}, {kind}, {data[i + 4]}"); } return convertedStringsBuilder.MoveToImmutable(); } }