diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Services/RazorSemanticTokensInfoService.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Services/RazorSemanticTokensInfoService.cs index f92b881e465..7c894855520 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Services/RazorSemanticTokensInfoService.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Services/RazorSemanticTokensInfoService.cs @@ -70,6 +70,10 @@ public RazorSemanticTokensInfoService( { csharpSemanticRanges = await GetCSharpSemanticRangesAsync(codeDocument, textDocumentIdentifier, range, razorSemanticTokensLegend, documentContext.Version, correlationId, cancellationToken).ConfigureAwait(false); } + catch (OperationCanceledException) + { + return null; + } catch (Exception ex) { _logger.LogError(ex, "Error thrown while retrieving CSharp semantic range."); @@ -230,7 +234,7 @@ private static bool ContainsOnlySpacesOrTabs(SourceText razorSource, int startIn var end = startIndex + count; for (var i = startIndex; i < end; i++) { - if (razorSource[i] is not ' ' or '\t') + if (razorSource[i] is not (' ' or '\t')) { return false; } diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Endpoints/SemanticTokens.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Endpoints/SemanticTokens.cs index 080435375cd..d1d5d4f64e2 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Endpoints/SemanticTokens.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Endpoints/SemanticTokens.cs @@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Razor.LanguageServer.Semantic; using Microsoft.AspNetCore.Razor.LanguageServer.Semantic.Models; using Microsoft.AspNetCore.Razor.PooledObjects; +using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.LanguageServer.ContainedLanguage; using Microsoft.VisualStudio.LanguageServer.Protocol; using StreamJsonRpc; @@ -85,10 +86,12 @@ internal partial class RazorCustomMessageTarget var nonEmptyResults = results.Select(r => r?.Response?.Data).WithoutNull().ToArray(); if (nonEmptyResults.Length != semanticTokensParams.Ranges.Length) { + _logger?.LogDebug("Made {count} semantic tokens requests to Roslyn but only got {nonEmpty} results back", semanticTokensParams.Ranges.Length, nonEmptyResults.Length); // Weren't able to re-invoke C# semantic tokens but we have to indicate it's due to out of sync by providing the old version return new ProvideSemanticTokensResponse(tokens: null, hostDocumentSyncVersion: csharpDoc.HostDocumentSyncVersion ?? -1); } + _logger?.LogDebug("Made {count} semantic tokens requests to Roslyn", semanticTokensParams.Ranges.Length); return new ProvideSemanticTokensResponse(nonEmptyResults, semanticTokensParams.RequiredHostDocumentVersion); } } diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Semantic/RazorSemanticTokensInfoServiceTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Semantic/RazorSemanticTokensInfoServiceTest.cs index f5b461df88e..547515c3a16 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Semantic/RazorSemanticTokensInfoServiceTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Semantic/RazorSemanticTokensInfoServiceTest.cs @@ -5,13 +5,11 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.LanguageServer.Common; using Microsoft.AspNetCore.Razor.LanguageServer.Extensions; using Microsoft.AspNetCore.Razor.Test.Common; using Microsoft.CodeAnalysis.Razor.Workspaces; using Microsoft.CodeAnalysis.Razor.Workspaces.Extensions; -using Microsoft.CodeAnalysis.Text; using Microsoft.CommonLanguageServerProtocol.Framework; using Microsoft.Extensions.Options; using Microsoft.VisualStudio.LanguageServer.Protocol; @@ -803,6 +801,32 @@ public void M() Assert.NotEmpty(csharpTokens.Tokens); } + [Fact] + public async Task GetSemanticTokens_CSharp_Tabs_Static_WithBackground() + { + var documentText = """ + @using System + @code + { + private static bool + _isStatic; + + public void M() + { + if (_isStatic) + { + } + } + } + """; + + var razorRange = GetRange(documentText); + var csharpTokens = await GetCSharpSemanticTokensResponseAsync(documentText, razorRange, isRazorFile: true); + await AssertSemanticTokensAsync(documentText, isRazorFile: true, razorRange, csharpTokens: csharpTokens, withCSharpBackground: true); + Assert.NotNull(csharpTokens.Tokens); + Assert.NotEmpty(csharpTokens.Tokens); + } + [Fact] public async Task GetSemanticTokens_CSharp_WithBackground() { diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Semantic/TestFiles/RangeParamsRazorSemanticTokensInfoServiceTest/GetSemanticTokens_CSharp_Tabs_Static_WithBackground.semantic.txt b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Semantic/TestFiles/RangeParamsRazorSemanticTokensInfoServiceTest/GetSemanticTokens_CSharp_Tabs_Static_WithBackground.semantic.txt new file mode 100644 index 00000000000..affff796618 --- /dev/null +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Semantic/TestFiles/RangeParamsRazorSemanticTokensInfoServiceTest/GetSemanticTokens_CSharp_Tabs_Static_WithBackground.semantic.txt @@ -0,0 +1,40 @@ +//line,characterPos,length,tokenType,modifier,text +0 0 1 razorTransition 0 [@] +0 1 5 keyword 4 [using] +0 5 1 markupTextLiteral 4 [ ] +0 1 6 namespace name 4 [System] +1 0 1 razorTransition 0 [@] +0 1 4 razorDirective 0 [code] +1 0 1 razorTransition 0 [{] +1 0 1 markupTextLiteral 4 [ ] +0 1 7 keyword 4 [private] +0 7 1 markupTextLiteral 4 [ ] +0 1 6 keyword 4 [static] +0 6 1 markupTextLiteral 4 [ ] +0 1 4 keyword 4 [bool] +1 0 2 markupTextLiteral 4 [ ] +0 2 9 field name 5 [_isStatic] +0 9 1 punctuation 4 [;] +2 0 1 markupTextLiteral 4 [ ] +0 1 6 keyword 4 [public] +0 6 1 markupTextLiteral 4 [ ] +0 1 4 keyword 4 [void] +0 4 1 markupTextLiteral 4 [ ] +0 1 1 method name 4 [M] +0 1 1 punctuation 4 [(] +0 1 1 punctuation 4 [)] +1 0 1 markupTextLiteral 4 [ ] +0 1 1 punctuation 4 [{] +1 0 2 markupTextLiteral 4 [ ] +0 2 2 keyword - control 4 [if] +0 2 1 markupTextLiteral 4 [ ] +0 1 1 punctuation 4 [(] +0 1 9 field name 5 [_isStatic] +0 9 1 punctuation 4 [)] +1 0 2 markupTextLiteral 4 [ ] +0 2 1 punctuation 4 [{] +1 0 2 markupTextLiteral 4 [ ] +0 2 1 punctuation 4 [}] +1 0 1 markupTextLiteral 4 [ ] +0 1 1 punctuation 4 [}] +1 0 1 razorTransition 0 [}] diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Semantic/TestFiles/RangesParamsRazorSemanticTokensInfoServiceTest/GetSemanticTokens_CSharp_Tabs_Static_WithBackground.semantic.txt b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Semantic/TestFiles/RangesParamsRazorSemanticTokensInfoServiceTest/GetSemanticTokens_CSharp_Tabs_Static_WithBackground.semantic.txt new file mode 100644 index 00000000000..affff796618 --- /dev/null +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Semantic/TestFiles/RangesParamsRazorSemanticTokensInfoServiceTest/GetSemanticTokens_CSharp_Tabs_Static_WithBackground.semantic.txt @@ -0,0 +1,40 @@ +//line,characterPos,length,tokenType,modifier,text +0 0 1 razorTransition 0 [@] +0 1 5 keyword 4 [using] +0 5 1 markupTextLiteral 4 [ ] +0 1 6 namespace name 4 [System] +1 0 1 razorTransition 0 [@] +0 1 4 razorDirective 0 [code] +1 0 1 razorTransition 0 [{] +1 0 1 markupTextLiteral 4 [ ] +0 1 7 keyword 4 [private] +0 7 1 markupTextLiteral 4 [ ] +0 1 6 keyword 4 [static] +0 6 1 markupTextLiteral 4 [ ] +0 1 4 keyword 4 [bool] +1 0 2 markupTextLiteral 4 [ ] +0 2 9 field name 5 [_isStatic] +0 9 1 punctuation 4 [;] +2 0 1 markupTextLiteral 4 [ ] +0 1 6 keyword 4 [public] +0 6 1 markupTextLiteral 4 [ ] +0 1 4 keyword 4 [void] +0 4 1 markupTextLiteral 4 [ ] +0 1 1 method name 4 [M] +0 1 1 punctuation 4 [(] +0 1 1 punctuation 4 [)] +1 0 1 markupTextLiteral 4 [ ] +0 1 1 punctuation 4 [{] +1 0 2 markupTextLiteral 4 [ ] +0 2 2 keyword - control 4 [if] +0 2 1 markupTextLiteral 4 [ ] +0 1 1 punctuation 4 [(] +0 1 9 field name 5 [_isStatic] +0 9 1 punctuation 4 [)] +1 0 2 markupTextLiteral 4 [ ] +0 2 1 punctuation 4 [{] +1 0 2 markupTextLiteral 4 [ ] +0 2 1 punctuation 4 [}] +1 0 1 markupTextLiteral 4 [ ] +0 1 1 punctuation 4 [}] +1 0 1 razorTransition 0 [}]