Create remote service and register etc.

This commit is contained in:
David Wengier 2024-07-19 22:19:54 +10:00
Родитель e6a914de23
Коммит 1ebf1de72a
8 изменённых файлов: 114 добавлений и 3 удалений

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

@ -23,5 +23,6 @@
<ServiceHubService Include="Microsoft.VisualStudio.Razor.UriPresentation" ClassName="Microsoft.CodeAnalysis.Remote.Razor.RemoteUriPresentationService+Factory" />
<ServiceHubService Include="Microsoft.VisualStudio.Razor.FoldingRange" ClassName="Microsoft.CodeAnalysis.Remote.Razor.RemoteFoldingRangeService+Factory" />
<ServiceHubService Include="Microsoft.VisualStudio.Razor.SignatureHelp" ClassName="Microsoft.CodeAnalysis.Remote.Razor.RemoteSignatureHelpService+Factory" />
<ServiceHubService Include="Microsoft.VisualStudio.Razor.DocumentHighlight" ClassName="Microsoft.CodeAnalysis.Remote.Razor.RemoteDocumentHighlightService+Factory" />
</ItemGroup>
</Project>

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

@ -4,6 +4,7 @@
using Microsoft.CodeAnalysis.Razor.Logging;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.LanguageServer.Protocol;
using RLSP = Roslyn.LanguageServer.Protocol;
namespace Microsoft.CodeAnalysis.Razor.Workspaces;
@ -12,6 +13,9 @@ internal static class LinePositionExtensions
public static Position ToPosition(this LinePosition linePosition)
=> new Position(linePosition.Line, linePosition.Character);
public static RLSP.Position ToRLSPPosition(this LinePosition linePosition)
=> new RLSP.Position(linePosition.Line, linePosition.Character);
public static bool TryGetAbsoluteIndex(this LinePosition position, SourceText sourceText, ILogger logger, out int absoluteIndex)
=> sourceText.TryGetAbsoluteIndex(position.Line, position.Character, logger, out absoluteIndex);

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

@ -3,6 +3,7 @@
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.LanguageServer.Protocol;
using RLSP = Roslyn.LanguageServer.Protocol;
namespace Microsoft.CodeAnalysis.Razor.Workspaces;
@ -15,6 +16,13 @@ internal static class LinePositionSpanExtensions
End = linePositionSpan.End.ToPosition()
};
public static RLSP.Range ToRLSPRange(this LinePositionSpan linePositionSpan)
=> new RLSP.Range
{
Start = linePositionSpan.Start.ToRLSPPosition(),
End = linePositionSpan.End.ToRLSPPosition()
};
public static TextSpan ToTextSpan(this LinePositionSpan linePositionSpan, SourceText sourceText)
=> sourceText.GetTextSpan(linePositionSpan.Start.Line, linePositionSpan.Start.Character, linePositionSpan.End.Line, linePositionSpan.End.Character);

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

@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Razor.Language;
using Microsoft.CodeAnalysis.Razor.Logging;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.LanguageServer.Protocol;
using RLSP = Roslyn.LanguageServer.Protocol;
namespace Microsoft.CodeAnalysis.Razor.Workspaces;
@ -15,6 +16,9 @@ internal static class PositionExtensions
public static LinePosition ToLinePosition(this Position position)
=> new LinePosition(position.Line, position.Character);
public static LinePosition ToLinePosition(this RLSP.Position position)
=> new LinePosition(position.Line, position.Character);
public static bool TryGetAbsoluteIndex(this Position position, SourceText sourceText, ILogger? logger, out int absoluteIndex)
{
if (position is null)

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

@ -5,6 +5,7 @@ using System;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.LanguageServer.Protocol;
using Range = Microsoft.VisualStudio.LanguageServer.Protocol.Range;
using RLSP = Roslyn.LanguageServer.Protocol;
namespace Microsoft.CodeAnalysis.Razor.Workspaces;
@ -110,6 +111,9 @@ internal static class RangeExtensions
public static LinePositionSpan ToLinePositionSpan(this Range range)
=> new LinePositionSpan(range.Start.ToLinePosition(), range.End.ToLinePosition());
public static LinePositionSpan ToLinePositionSpan(this RLSP.Range range)
=> new LinePositionSpan(range.Start.ToLinePosition(), range.End.ToLinePosition());
public static bool IsUndefined(this Range range)
{
if (range is null)

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

@ -5,6 +5,7 @@ using System.Runtime.Serialization;
using Microsoft.CodeAnalysis.Razor.Workspaces;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.LanguageServer.Protocol;
using RLSP = Roslyn.LanguageServer.Protocol;
namespace Microsoft.CodeAnalysis.Razor.Protocol.DocumentHighlight;
@ -15,8 +16,8 @@ internal readonly record struct RemoteDocumentHighlight(
[property: DataMember(Order = 0)] LinePositionSpan Position,
[property: DataMember(Order = 1)] DocumentHighlightKind Kind)
{
public static RemoteDocumentHighlight FromLspDocumentHighlight(DocumentHighlight h)
=> new RemoteDocumentHighlight(h.Range.ToLinePositionSpan(), h.Kind);
public static RemoteDocumentHighlight FromRLSPDocumentHighlight(RLSP.DocumentHighlight h)
=> new RemoteDocumentHighlight(h.Range.ToLinePositionSpan(), (DocumentHighlightKind)h.Kind);
public static DocumentHighlight ToLspDocumentHighlight(RemoteDocumentHighlight r)
=> new DocumentHighlight

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

@ -19,7 +19,8 @@ internal static class RazorServices
(typeof(IRemoteSemanticTokensService), null),
(typeof(IRemoteHtmlDocumentService), null),
(typeof(IRemoteUriPresentationService), null),
(typeof(IRemoteFoldingRangeService), null)
(typeof(IRemoteFoldingRangeService), null),
(typeof(IRemoteDocumentHighlightService), null),
];
// Internal for testing

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

@ -0,0 +1,88 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.CodeAnalysis.ExternalAccess.Razor;
using Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost.Handlers;
using Microsoft.CodeAnalysis.Razor.DocumentMapping;
using Microsoft.CodeAnalysis.Razor.Protocol;
using Microsoft.CodeAnalysis.Razor.Protocol.DocumentHighlight;
using Microsoft.CodeAnalysis.Razor.Remote;
using Microsoft.CodeAnalysis.Razor.Workspaces;
using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis.Remote.Razor;
internal sealed partial class RemoteDocumentHighlightService(in ServiceArgs args) : RazorDocumentServiceBase(in args), IRemoteDocumentHighlightService
{
internal sealed class Factory : FactoryBase<IRemoteDocumentHighlightService>
{
protected override IRemoteDocumentHighlightService CreateService(in ServiceArgs args)
=> new RemoteDocumentHighlightService(in args);
}
private readonly IRazorDocumentMappingService _documentMappingService = args.ExportProvider.GetExportedValue<IRazorDocumentMappingService>();
private readonly IFilePathService _filePathService = args.ExportProvider.GetExportedValue<IFilePathService>();
public ValueTask<RemoteDocumentHighlight[]?> GetHighlightsAsync(
RazorPinnedSolutionInfoWrapper solutionInfo,
DocumentId razorDocumentId,
LinePosition position,
CancellationToken cancellationToken)
=> RunServiceAsync(
solutionInfo,
razorDocumentId,
context => GetHighlightsAsync(context, position, cancellationToken),
cancellationToken);
private async ValueTask<RemoteDocumentHighlight[]?> GetHighlightsAsync(
RemoteDocumentContext context,
LinePosition position,
CancellationToken cancellationToken)
{
var sourceText = await context.GetSourceTextAsync(cancellationToken).ConfigureAwait(false);
if (!sourceText.TryGetAbsoluteIndex(position.Line, position.Character, out var index))
{
return null;
}
var codeDocument = await context.GetCodeDocumentAsync(cancellationToken).ConfigureAwait(false);
var languageKind = _documentMappingService.GetLanguageKind(codeDocument, index, rightAssociative: true);
if (languageKind is RazorLanguageKind.Html)
{
// Returning null indicates we have nothing to say, so go to Html
return null;
}
else if (languageKind is RazorLanguageKind.CSharp)
{
var csharpDocument = codeDocument.GetCSharpDocument();
if (_documentMappingService.TryMapToGeneratedDocumentPosition(csharpDocument, index, out var mappedPosition, out _))
{
var generatedDocument = await context.GetGeneratedDocumentAsync(_filePathService, cancellationToken).ConfigureAwait(false);
var highlights = await DocumentHighlights.GetHighlightsAsync(generatedDocument, mappedPosition, cancellationToken).ConfigureAwait(false);
if (highlights is not null)
{
foreach (var highlight in highlights)
{
if (_documentMappingService.TryMapToHostDocumentRange(csharpDocument, highlight.Range.ToLinePositionSpan(), out var mappedRange))
{
highlight.Range = mappedRange.ToRLSPRange();
}
}
return highlights.Select(RemoteDocumentHighlight.FromRLSPDocumentHighlight).ToArray();
}
}
}
// We don't do anything for Razor, but we return an empty array so the caller knows not to bother asking Html
return [];
}
}