Add and use RazorCodeDocument.GetLanguageKind(...) extension method

This commit is contained in:
Dustin Campbell 2024-09-04 16:42:38 -07:00
Родитель e8eede823a
Коммит f575ad02ca
15 изменённых файлов: 28 добавлений и 54 удалений

Просмотреть файл

@ -177,7 +177,7 @@ internal sealed class CodeActionEndpoint(
private async Task<ImmutableArray<RazorVSInternalCodeAction>> GetDelegatedCodeActionsAsync(DocumentContext documentContext, RazorCodeActionContext context, Guid correlationId, CancellationToken cancellationToken)
{
var languageKind = _documentMappingService.GetLanguageKind(context.CodeDocument, context.Location.AbsoluteIndex, rightAssociative: false);
var languageKind = context.CodeDocument.GetLanguageKind(context.Location.AbsoluteIndex, rightAssociative: false);
// No point delegating if we're in a Razor context
if (languageKind == RazorLanguageKind.Razor)

Просмотреть файл

@ -55,7 +55,7 @@ internal class RazorBreakpointSpanEndpoint(
}
var projectedIndex = hostDocumentIndex;
var languageKind = _documentMappingService.GetLanguageKind(codeDocument, hostDocumentIndex, rightAssociative: false);
var languageKind = codeDocument.GetLanguageKind(hostDocumentIndex, rightAssociative: false);
// If we're in C#, then map to the right position in the generated document
if (languageKind == RazorLanguageKind.CSharp &&
!_documentMappingService.TryMapToGeneratedDocumentPosition(codeDocument.GetCSharpDocument(), hostDocumentIndex, out _, out projectedIndex))

Просмотреть файл

@ -56,7 +56,7 @@ internal class RazorProximityExpressionsEndpoint(
}
var projectedIndex = hostDocumentIndex;
var languageKind = _documentMappingService.GetLanguageKind(codeDocument, hostDocumentIndex, rightAssociative: false);
var languageKind = codeDocument.GetLanguageKind(hostDocumentIndex, rightAssociative: false);
// If we're in C#, then map to the right position in the generated document
if (languageKind == RazorLanguageKind.CSharp &&
!_documentMappingService.TryMapToGeneratedDocumentPosition(codeDocument.GetCSharpDocument(), hostDocumentIndex, out _, out projectedIndex))

Просмотреть файл

@ -3,8 +3,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
@ -71,7 +69,7 @@ internal abstract class AbstractTextDocumentPresentationEndpointBase<TParams>(
return null;
}
var languageKind = _documentMappingService.GetLanguageKind(codeDocument, hostDocumentIndex, rightAssociative: false);
var languageKind = codeDocument.GetLanguageKind(hostDocumentIndex, rightAssociative: false);
// See if we can handle this directly in Razor. If not, we'll let things flow to the below delegated handling.
var result = await TryGetRazorWorkspaceEditAsync(languageKind, request, cancellationToken).ConfigureAwait(false);
if (result is not null)

Просмотреть файл

@ -3,16 +3,13 @@
using System;
using System.Collections.Frozen;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.LanguageServer.EndpointContracts;
using Microsoft.AspNetCore.Razor.LanguageServer.Hosting;
using Microsoft.CodeAnalysis.Razor.DocumentMapping;
using Microsoft.CodeAnalysis.Razor.Formatting;
using Microsoft.CodeAnalysis.Razor.Logging;
using Microsoft.CodeAnalysis.Razor.ProjectSystem;

Просмотреть файл

@ -11,7 +11,6 @@ using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.LanguageServer.EndpointContracts;
using Microsoft.AspNetCore.Razor.LanguageServer.Formatting;
using Microsoft.AspNetCore.Razor.LanguageServer.Hosting;
using Microsoft.AspNetCore.Razor.PooledObjects;
using Microsoft.CodeAnalysis.Razor.DocumentMapping;
@ -86,7 +85,7 @@ internal sealed class InlineCompletionEndpoint(
var sourceText = await documentContext.GetSourceTextAsync(cancellationToken).ConfigureAwait(false);
var hostDocumentIndex = sourceText.GetPosition(request.Position);
var languageKind = _documentMappingService.GetLanguageKind(codeDocument, hostDocumentIndex, rightAssociative: false);
var languageKind = codeDocument.GetLanguageKind(hostDocumentIndex, rightAssociative: false);
// Map to the location in the C# document.
if (languageKind != RazorLanguageKind.CSharp ||

Просмотреть файл

@ -61,7 +61,7 @@ internal sealed class RazorLanguageQueryEndpoint(IDocumentMappingService documen
var responsePositionIndex = hostDocumentIndex;
var languageKind = _documentMappingService.GetLanguageKind(codeDocument, hostDocumentIndex, rightAssociative: false);
var languageKind = codeDocument.GetLanguageKind(hostDocumentIndex, rightAssociative: false);
if (languageKind == RazorLanguageKind.CSharp)
{
if (_documentMappingService.TryMapToGeneratedDocumentPosition(codeDocument.GetCSharpDocument(), hostDocumentIndex, out Position? projectedPosition, out var projectedIndex))

Просмотреть файл

@ -1,7 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
@ -9,7 +8,6 @@ using Microsoft.AspNetCore.Razor.Language.Syntax;
using Microsoft.AspNetCore.Razor.LanguageServer.EndpointContracts;
using Microsoft.AspNetCore.Razor.LanguageServer.Formatting;
using Microsoft.AspNetCore.Razor.LanguageServer.Hosting;
using Microsoft.CodeAnalysis.Razor.DocumentMapping;
using Microsoft.CodeAnalysis.Razor.Logging;
using Microsoft.CodeAnalysis.Razor.Protocol;
using Microsoft.CodeAnalysis.Text;
@ -18,14 +16,9 @@ using Microsoft.VisualStudio.LanguageServer.Protocol;
namespace Microsoft.AspNetCore.Razor.LanguageServer.WrapWithTag;
[RazorLanguageServerEndpoint(LanguageServerConstants.RazorWrapWithTagEndpoint)]
internal class WrapWithTagEndpoint(
IClientConnection clientConnection,
IDocumentMappingService documentMappingService,
ILoggerFactory loggerFactory)
: IRazorRequestHandler<WrapWithTagParams, WrapWithTagResponse?>
internal class WrapWithTagEndpoint(IClientConnection clientConnection, ILoggerFactory loggerFactory) : IRazorRequestHandler<WrapWithTagParams, WrapWithTagResponse?>
{
private readonly IClientConnection _clientConnection = clientConnection ?? throw new ArgumentNullException(nameof(clientConnection));
private readonly IDocumentMappingService _documentMappingService = documentMappingService ?? throw new ArgumentNullException(nameof(documentMappingService));
private readonly IClientConnection _clientConnection = clientConnection;
private readonly ILogger _logger = loggerFactory.GetOrCreateLogger<WrapWithTagEndpoint>();
public bool MutatesSolutionState => false;
@ -69,7 +62,7 @@ internal class WrapWithTagEndpoint(
//
// Instead of C#, which certainly would be expected to go in an if statement, we'll see HTML, which obviously
// is the better choice for this operation.
var languageKind = _documentMappingService.GetLanguageKind(codeDocument, hostDocumentIndex, rightAssociative: true);
var languageKind = codeDocument.GetLanguageKind(hostDocumentIndex, rightAssociative: true);
if (languageKind is not RazorLanguageKind.Html)
{
// In general, we don't support C# for obvious reasons, but we can support implicit expressions. ie

Просмотреть файл

@ -48,7 +48,7 @@ internal static class IDocumentMappingServiceExtensions
var sourceText = codeDocument.Source.Text;
var position = sourceText.GetPosition(hostDocumentIndex);
var languageKind = service.GetLanguageKind(codeDocument, hostDocumentIndex, rightAssociative: false);
var languageKind = codeDocument.GetLanguageKind(hostDocumentIndex, rightAssociative: false);
if (languageKind is not RazorLanguageKind.Razor)
{
var generatedDocument = languageKind is RazorLanguageKind.CSharp

Просмотреть файл

@ -7,6 +7,7 @@ using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Microsoft.AspNetCore.Razor.Language.Intermediate;
using Microsoft.CodeAnalysis.Razor;
using Microsoft.CodeAnalysis.Razor.DocumentMapping;
using Microsoft.CodeAnalysis.Razor.Protocol;
using Microsoft.CodeAnalysis.Razor.Workspaces;
using Microsoft.CodeAnalysis.Text;
@ -139,4 +140,13 @@ internal static class RazorCodeDocumentExtensions
return namespaceNode.Content == fullyQualifiedNamespace;
}
public static RazorLanguageKind GetLanguageKind(this RazorCodeDocument codeDocument, int hostDocumentIndex, bool rightAssociative)
{
var classifiedSpans = LanguageKindHelper.GetClassifiedSpans(codeDocument);
var tagHelperSpans = LanguageKindHelper.GetTagHelperSpans(codeDocument);
var documentLength = codeDocument.Source.Text.Length;
return LanguageKindHelper.GetLanguageKindCore(classifiedSpans, tagHelperSpans, hostDocumentIndex, documentLength, rightAssociative);
}
}

Просмотреть файл

@ -31,7 +31,6 @@ internal class RazorFormattingService : IRazorFormattingService
private static readonly FrozenSet<string> s_htmlTriggerCharacterSet = FrozenSet.ToFrozenSet(["\n", "{", "}", ";"], StringComparer.Ordinal);
private readonly IFormattingCodeDocumentProvider _codeDocumentProvider;
private readonly IDocumentMappingService _documentMappingService;
private readonly IAdhocWorkspaceFactory _workspaceFactory;
private readonly ImmutableArray<IFormattingPass> _documentFormattingPasses;
@ -46,7 +45,6 @@ internal class RazorFormattingService : IRazorFormattingService
ILoggerFactory loggerFactory)
{
_codeDocumentProvider = codeDocumentProvider;
_documentMappingService = documentMappingService;
_workspaceFactory = workspaceFactory;
_htmlOnTypeFormattingPass = new HtmlOnTypeFormattingPass(loggerFactory);
@ -200,7 +198,7 @@ internal class RazorFormattingService : IRazorFormattingService
public bool TryGetOnTypeFormattingTriggerKind(RazorCodeDocument codeDocument, int hostDocumentIndex, string triggerCharacter, out RazorLanguageKind triggerCharacterKind)
{
triggerCharacterKind = _documentMappingService.GetLanguageKind(codeDocument, hostDocumentIndex, rightAssociative: false);
triggerCharacterKind = codeDocument.GetLanguageKind(hostDocumentIndex, rightAssociative: false);
return triggerCharacterKind switch
{

Просмотреть файл

@ -53,7 +53,7 @@ internal sealed partial class RemoteDocumentHighlightService(in ServiceArgs args
var codeDocument = await context.GetCodeDocumentAsync(cancellationToken).ConfigureAwait(false);
var languageKind = _documentMappingService.GetLanguageKind(codeDocument, index, rightAssociative: true);
var languageKind = codeDocument.GetLanguageKind(index, rightAssociative: true);
if (languageKind is RazorLanguageKind.Html)
{
return Response.CallHtml;

Просмотреть файл

@ -4,6 +4,7 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.CodeAnalysis.ExternalAccess.Razor;
using Microsoft.CodeAnalysis.Razor.DocumentPresentation;
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
@ -51,7 +52,7 @@ internal sealed partial class RemoteUriPresentationService(in ServiceArgs args)
var codeDocument = await context.GetCodeDocumentAsync(cancellationToken).ConfigureAwait(false);
var languageKind = DocumentMappingService.GetLanguageKind(codeDocument, index, rightAssociative: true);
var languageKind = codeDocument.GetLanguageKind(index, rightAssociative: true);
if (languageKind is not RazorLanguageKind.Html)
{
// Roslyn doesn't currently support Uri presentation, and whilst it might seem counter intuitive,

Просмотреть файл

@ -139,7 +139,7 @@ public class FormattingTestBase : RazorToolingIntegrationTestBase
var filePathService = new LSPFilePathService(TestLanguageServerFeatureOptions.Instance);
var mappingService = new LspDocumentMappingService(
filePathService, new TestDocumentContextFactory(), LoggerFactory);
var languageKind = mappingService.GetLanguageKind(codeDocument, positionAfterTrigger, rightAssociative: false);
var languageKind = codeDocument.GetLanguageKind(positionAfterTrigger, rightAssociative: false);
var formattingService = await TestRazorFormattingService.CreateWithFullSupportAsync(LoggerFactory, codeDocument, razorLSPOptions);
var options = new FormattingOptions()
@ -213,7 +213,7 @@ public class FormattingTestBase : RazorToolingIntegrationTestBase
var filePathService = new LSPFilePathService(TestLanguageServerFeatureOptions.Instance);
var mappingService = new LspDocumentMappingService(filePathService, new TestDocumentContextFactory(), LoggerFactory);
var languageKind = mappingService.GetLanguageKind(codeDocument, positionAfterTrigger, rightAssociative: false);
var languageKind = codeDocument.GetLanguageKind(positionAfterTrigger, rightAssociative: false);
if (languageKind == RazorLanguageKind.Html)
{
throw new NotImplementedException("Code action formatting is not yet supported for HTML in Razor.");

Просмотреть файл

@ -9,7 +9,6 @@ using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.LanguageServer.Formatting;
using Microsoft.AspNetCore.Razor.LanguageServer.Hosting;
using Microsoft.AspNetCore.Razor.Test.Common.LanguageServer;
using Microsoft.CodeAnalysis.Razor.DocumentMapping;
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
using Microsoft.CodeAnalysis.Razor.Protocol;
using Microsoft.VisualStudio.LanguageServer.Protocol;
@ -35,11 +34,8 @@ public class WrapWithTagEndpointTest(ITestOutputHelper testOutput) : LanguageSer
.Setup(l => l.SendRequestAsync<WrapWithTagParams, WrapWithTagResponse>(LanguageServerConstants.RazorWrapWithTagEndpoint, It.IsAny<WrapWithTagParams>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(response);
var documentMappingService = Mock.Of<IDocumentMappingService>(
s => s.GetLanguageKind(codeDocument, It.IsAny<int>(), It.IsAny<bool>()) == RazorLanguageKind.Html, MockBehavior.Strict);
var endpoint = new WrapWithTagEndpoint(
clientConnection.Object,
documentMappingService,
LoggerFactory);
var wrapWithDivParams = new WrapWithTagParams(new TextDocumentIdentifier { Uri = uri })
@ -70,11 +66,8 @@ public class WrapWithTagEndpointTest(ITestOutputHelper testOutput) : LanguageSer
.Setup(l => l.SendRequestAsync<WrapWithTagParams, WrapWithTagResponse>(LanguageServerConstants.RazorWrapWithTagEndpoint, It.IsAny<WrapWithTagParams>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(response);
var documentMappingService = Mock.Of<IDocumentMappingService>(
s => s.GetLanguageKind(codeDocument, It.IsAny<int>(), It.IsAny<bool>()) == RazorLanguageKind.CSharp, MockBehavior.Strict);
var endpoint = new WrapWithTagEndpoint(
clientConnection.Object,
documentMappingService,
LoggerFactory);
var wrapWithDivParams = new WrapWithTagParams(new TextDocumentIdentifier { Uri = uri })
@ -105,11 +98,8 @@ public class WrapWithTagEndpointTest(ITestOutputHelper testOutput) : LanguageSer
.Setup(l => l.SendRequestAsync<WrapWithTagParams, WrapWithTagResponse>(LanguageServerConstants.RazorWrapWithTagEndpoint, It.IsAny<WrapWithTagParams>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(response);
var documentMappingService = Mock.Of<IDocumentMappingService>(
s => s.GetLanguageKind(codeDocument, It.IsAny<int>(), It.IsAny<bool>()) == RazorLanguageKind.CSharp, MockBehavior.Strict);
var endpoint = new WrapWithTagEndpoint(
clientConnection.Object,
documentMappingService,
LoggerFactory);
var wrapWithDivParams = new WrapWithTagParams(new TextDocumentIdentifier { Uri = uri })
@ -140,11 +130,8 @@ public class WrapWithTagEndpointTest(ITestOutputHelper testOutput) : LanguageSer
.Setup(l => l.SendRequestAsync<WrapWithTagParams, WrapWithTagResponse>(LanguageServerConstants.RazorWrapWithTagEndpoint, It.IsAny<WrapWithTagParams>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(response);
var documentMappingService = Mock.Of<IDocumentMappingService>(
s => s.GetLanguageKind(codeDocument, It.IsAny<int>(), It.IsAny<bool>()) == RazorLanguageKind.CSharp, MockBehavior.Strict);
var endpoint = new WrapWithTagEndpoint(
clientConnection.Object,
documentMappingService,
LoggerFactory);
var wrapWithDivParams = new WrapWithTagParams(new TextDocumentIdentifier { Uri = uri })
@ -175,11 +162,8 @@ public class WrapWithTagEndpointTest(ITestOutputHelper testOutput) : LanguageSer
.Setup(l => l.SendRequestAsync<WrapWithTagParams, WrapWithTagResponse>(LanguageServerConstants.RazorWrapWithTagEndpoint, It.IsAny<WrapWithTagParams>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(response);
var documentMappingService = Mock.Of<IDocumentMappingService>(
s => s.GetLanguageKind(codeDocument, It.IsAny<int>(), It.IsAny<bool>()) == RazorLanguageKind.CSharp, MockBehavior.Strict);
var endpoint = new WrapWithTagEndpoint(
clientConnection.Object,
documentMappingService,
LoggerFactory);
var wrapWithDivParams = new WrapWithTagParams(new TextDocumentIdentifier { Uri = uri })
@ -200,15 +184,11 @@ public class WrapWithTagEndpointTest(ITestOutputHelper testOutput) : LanguageSer
public async Task Handle_DocumentNotFound_ReturnsNull()
{
// Arrange
var codeDocument = CreateCodeDocument("<div></div>");
var realUri = new Uri("file://path/test.razor");
var missingUri = new Uri("file://path/nottest.razor");
var clientConnection = new Mock<IClientConnection>(MockBehavior.Strict);
var documentMappingService = Mock.Of<IDocumentMappingService>(
s => s.GetLanguageKind(codeDocument, It.IsAny<int>(), It.IsAny<bool>()) == RazorLanguageKind.Html, MockBehavior.Strict);
var endpoint = new WrapWithTagEndpoint(clientConnection.Object, documentMappingService, LoggerFactory);
var endpoint = new WrapWithTagEndpoint(clientConnection.Object, LoggerFactory);
var wrapWithDivParams = new WrapWithTagParams(new TextDocumentIdentifier { Uri = missingUri })
{
@ -234,9 +214,7 @@ public class WrapWithTagEndpointTest(ITestOutputHelper testOutput) : LanguageSer
var clientConnection = new Mock<IClientConnection>(MockBehavior.Strict);
var documentMappingService = Mock.Of<IDocumentMappingService>(
s => s.GetLanguageKind(codeDocument, It.IsAny<int>(), It.IsAny<bool>()) == RazorLanguageKind.Html, MockBehavior.Strict);
var endpoint = new WrapWithTagEndpoint(clientConnection.Object, documentMappingService, LoggerFactory);
var endpoint = new WrapWithTagEndpoint(clientConnection.Object, LoggerFactory);
var wrapWithDivParams = new WrapWithTagParams(new TextDocumentIdentifier { Uri = uri })
{