diff --git a/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/RoslynSemanticTokens.cs b/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/RoslynSemanticTokens.cs deleted file mode 100644 index 44a391d4c8459..0000000000000 --- a/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/RoslynSemanticTokens.cs +++ /dev/null @@ -1,26 +0,0 @@ -// 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. - -#nullable enable - -using System.Runtime.Serialization; -using LSP = Microsoft.VisualStudio.LanguageServer.Protocol; - -namespace Microsoft.CodeAnalysis.LanguageServer.Handler.SemanticTokens -{ - internal sealed class RoslynSemanticTokens : LSP.SemanticTokens - { - /// - /// True if the token set is complete, meaning it's generated using a full semantic - /// model rather than a frozen one. - /// - /// - /// Certain clients such as Razor need to know whether we're returning partial - /// (i.e. possibly inaccurate) results. This may occur if the full compilation - /// is not yet available. - /// - [DataMember(Name = "isFinalized")] - public bool IsFinalized { get; set; } - } -} diff --git a/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensHelpers.cs b/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensHelpers.cs index 379a7864f883a..a164f8910bb8e 100644 --- a/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensHelpers.cs +++ b/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensHelpers.cs @@ -130,7 +130,7 @@ static SemanticTokensHelpers() /// /// Returns the semantic tokens data for a given document with an optional range. /// - internal static async Task<(int[], bool isFinalized)> ComputeSemanticTokensDataAsync( + internal static async Task ComputeSemanticTokensDataAsync( Document document, Dictionary tokenTypesToIndex, LSP.Range? range, @@ -147,10 +147,12 @@ static SemanticTokensHelpers() // If the full compilation is not yet available, we'll try getting a partial one. It may contain inaccurate // results but will speed up how quickly we can respond to the client's request. - var frozenDocument = document.WithFrozenPartialSemantics(cancellationToken); - var semanticModel = await frozenDocument.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); - var isFinalized = document.Project.TryGetCompilation(out var compilation) && compilation == semanticModel.Compilation; - document = frozenDocument; + // Razor cannot use frozen partial semantics as there is currently no way to know whether we have full semantics + // available, which is an impediment to Razor caching. + if (!document.IsRazorDocument()) + { + document = document.WithFrozenPartialSemantics(cancellationToken); + } var classifiedSpans = await GetClassifiedSpansForDocumentAsync( document, textSpan, options, includeSyntacticClassifications, cancellationToken).ConfigureAwait(false); @@ -161,7 +163,7 @@ static SemanticTokensHelpers() // TO-DO: We should implement support for streaming if LSP adds support for it: // https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1276300 - return (ComputeTokens(text.Lines, updatedClassifiedSpans, tokenTypesToIndex), isFinalized); + return ComputeTokens(text.Lines, updatedClassifiedSpans, tokenTypesToIndex); } private static async Task GetClassifiedSpansForDocumentAsync( diff --git a/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensRangeHandler.cs b/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensRangeHandler.cs index bdd4c460a84e1..7dbfb1740b40b 100644 --- a/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensRangeHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensRangeHandler.cs @@ -54,7 +54,7 @@ public SemanticTokensRangeHandler(IGlobalOptionService globalOptions) // partial token results. In addition, a range request is only ever called with a whole // document request, so caching range results is unnecessary since the whole document // handler will cache the results anyway. - var (tokensData, isFinalized) = await SemanticTokensHelpers.ComputeSemanticTokensDataAsync( + var tokensData = await SemanticTokensHelpers.ComputeSemanticTokensDataAsync( context.Document, SemanticTokensHelpers.TokenTypeToIndex, request.Range, @@ -62,7 +62,7 @@ public SemanticTokensRangeHandler(IGlobalOptionService globalOptions) includeSyntacticClassifications: context.Document.IsRazorDocument(), cancellationToken).ConfigureAwait(false); - return new RoslynSemanticTokens { Data = tokensData, IsFinalized = isFinalized }; + return new LSP.SemanticTokens { Data = tokensData }; } } } diff --git a/src/Features/LanguageServer/ProtocolUnitTests/SemanticTokens/AbstractSemanticTokensTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/SemanticTokens/AbstractSemanticTokensTests.cs index e76778c1fa6af..b97ec47b5c79f 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/SemanticTokens/AbstractSemanticTokensTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/SemanticTokens/AbstractSemanticTokensTests.cs @@ -8,7 +8,6 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; -using Microsoft.CodeAnalysis.LanguageServer.Handler.SemanticTokens; using Microsoft.CodeAnalysis.Text; using Roslyn.Test.Utilities; using Roslyn.Utilities; @@ -21,7 +20,7 @@ public abstract class AbstractSemanticTokensTests : AbstractLanguageServerProtoc { private protected static async Task RunGetSemanticTokensRangeAsync(TestLspServer testLspServer, LSP.Location caret, LSP.Range range) { - var result = await testLspServer.ExecuteRequestAsync(LSP.Methods.TextDocumentSemanticTokensRangeName, + var result = await testLspServer.ExecuteRequestAsync(LSP.Methods.TextDocumentSemanticTokensRangeName, CreateSemanticTokensRangeParams(caret, range), CancellationToken.None); Contract.ThrowIfNull(result); return result; diff --git a/src/Features/LanguageServer/ProtocolUnitTests/SemanticTokens/SemanticTokensRangeTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/SemanticTokens/SemanticTokensRangeTests.cs index c2c827c6e6e6e..ae0f70de56044 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/SemanticTokens/SemanticTokensRangeTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/SemanticTokens/SemanticTokensRangeTests.cs @@ -53,7 +53,7 @@ static class C { } var range = new LSP.Range { Start = new Position(0, 0), End = new Position(2, 0) }; var options = ClassificationOptions.Default; - var (results, _) = await SemanticTokensHelpers.ComputeSemanticTokensDataAsync( + var results = await SemanticTokensHelpers.ComputeSemanticTokensDataAsync( document, SemanticTokensHelpers.TokenTypeToIndex, range, options, includeSyntacticClassifications: true, CancellationToken.None); var expectedResults = new LSP.SemanticTokens @@ -87,7 +87,7 @@ static class C { } var document = testLspServer.GetCurrentSolution().Projects.First().Documents.First(); var range = new LSP.Range { Start = new Position(1, 0), End = new Position(2, 0) }; var options = ClassificationOptions.Default; - var (results, _) = await SemanticTokensHelpers.ComputeSemanticTokensDataAsync( + var results = await SemanticTokensHelpers.ComputeSemanticTokensDataAsync( document, SemanticTokensHelpers.TokenTypeToIndex, range, options, includeSyntacticClassifications: true, CancellationToken.None); var expectedResults = new LSP.SemanticTokens @@ -122,7 +122,7 @@ public async Task TestGetSemanticTokensRange_MultiLineComment_RazorAsync() var document = testLspServer.GetCurrentSolution().Projects.First().Documents.First(); var range = new LSP.Range { Start = new Position(0, 0), End = new Position(4, 0) }; var options = ClassificationOptions.Default; - var (results, _) = await SemanticTokensHelpers.ComputeSemanticTokensDataAsync( + var results = await SemanticTokensHelpers.ComputeSemanticTokensDataAsync( document, SemanticTokensHelpers.TokenTypeToIndex, range, options, includeSyntacticClassifications: true, CancellationToken.None); var expectedResults = new LSP.SemanticTokens @@ -197,7 +197,7 @@ void M() var document = testLspServer.GetCurrentSolution().Projects.First().Documents.First(); var range = new LSP.Range { Start = new Position(0, 0), End = new Position(9, 0) }; var options = ClassificationOptions.Default; - var (results, _) = await SemanticTokensHelpers.ComputeSemanticTokensDataAsync( + var results = await SemanticTokensHelpers.ComputeSemanticTokensDataAsync( document, SemanticTokensHelpers.TokenTypeToIndex, range, options, includeSyntacticClassifications: true, CancellationToken.None); var expectedResults = new LSP.SemanticTokens @@ -250,7 +250,7 @@ void M() var document = testLspServer.GetCurrentSolution().Projects.First().Documents.First(); var range = new LSP.Range { Start = new Position(0, 0), End = new Position(9, 0) }; var options = ClassificationOptions.Default; - var (results, _) = await SemanticTokensHelpers.ComputeSemanticTokensDataAsync( + var results = await SemanticTokensHelpers.ComputeSemanticTokensDataAsync( document, SemanticTokensHelpers.TokenTypeToIndex, range, options, includeSyntacticClassifications: true, CancellationToken.None); var expectedResults = new LSP.SemanticTokens