Fixes https://github.com/dotnet/razor/issues/11237
Needs https://github.com/dotnet/roslyn/pull/76002 and a version bump

Very simple one, though I was a little cheeky. There is basically no
code that could be shared, except for code that removes `__o` and
`k_BackingField` from the results, but those methods operate on VS LSP
types. Given cohosting largely uses Roslyn LSP types, and will be
exclusively FUSE, and FUSE doesn't have `__o`, I just skipped that bit.
Confirmed in VS that having cohosting and FUSE on makes for nice looking
results with no generated code artifacts.

Side note: I don't think anything will ever have `k_BackingField` in the
results, but there is zero test coverage so who knows! 😁
This commit is contained in:
David Wengier 2024-12-02 08:45:09 +11:00 коммит произвёл GitHub
Родитель 5f32f2648d 973553f398
Коммит db3fecf853
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
9 изменённых файлов: 520 добавлений и 58 удалений

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

@ -11,82 +11,82 @@
<Sha>ef10a9fae360251bdd4b7552a4c90bf626977453</Sha>
<SourceBuild RepoName="source-build-reference-packages" ManagedOnly="true" />
</Dependency>
<Dependency Name="Microsoft.Net.Compilers.Toolset" Version="4.13.0-2.24564.3">
<Dependency Name="Microsoft.Net.Compilers.Toolset" Version="4.13.0-3.24576.11">
<Uri>https://github.com/dotnet/roslyn</Uri>
<Sha>826b0db12582b6b645ed1cf5e1565f767af31e53</Sha>
<Sha>6f2ed01d1af9429d874aca1eea60d3212167bc40</Sha>
</Dependency>
<Dependency Name="Microsoft.CommonLanguageServerProtocol.Framework" Version="4.13.0-2.24564.3">
<Dependency Name="Microsoft.CommonLanguageServerProtocol.Framework" Version="4.13.0-3.24576.11">
<Uri>https://github.com/dotnet/roslyn</Uri>
<Sha>826b0db12582b6b645ed1cf5e1565f767af31e53</Sha>
<Sha>6f2ed01d1af9429d874aca1eea60d3212167bc40</Sha>
</Dependency>
<Dependency Name="Microsoft.CodeAnalysis.ExternalAccess.Razor" Version="4.13.0-2.24564.3">
<Dependency Name="Microsoft.CodeAnalysis.ExternalAccess.Razor" Version="4.13.0-3.24576.11">
<Uri>https://github.com/dotnet/roslyn</Uri>
<Sha>826b0db12582b6b645ed1cf5e1565f767af31e53</Sha>
<Sha>6f2ed01d1af9429d874aca1eea60d3212167bc40</Sha>
</Dependency>
<Dependency Name="Microsoft.CodeAnalysis.Common" Version="4.13.0-2.24564.3">
<Dependency Name="Microsoft.CodeAnalysis.Common" Version="4.13.0-3.24576.11">
<Uri>https://github.com/dotnet/roslyn</Uri>
<Sha>826b0db12582b6b645ed1cf5e1565f767af31e53</Sha>
<Sha>6f2ed01d1af9429d874aca1eea60d3212167bc40</Sha>
</Dependency>
<Dependency Name="Microsoft.CodeAnalysis.CSharp" Version="4.13.0-2.24564.3">
<Dependency Name="Microsoft.CodeAnalysis.CSharp" Version="4.13.0-3.24576.11">
<Uri>https://github.com/dotnet/roslyn</Uri>
<Sha>826b0db12582b6b645ed1cf5e1565f767af31e53</Sha>
<Sha>6f2ed01d1af9429d874aca1eea60d3212167bc40</Sha>
</Dependency>
<Dependency Name="Microsoft.CodeAnalysis.CSharp.EditorFeatures" Version="4.13.0-2.24564.3">
<Dependency Name="Microsoft.CodeAnalysis.CSharp.EditorFeatures" Version="4.13.0-3.24576.11">
<Uri>https://github.com/dotnet/roslyn</Uri>
<Sha>826b0db12582b6b645ed1cf5e1565f767af31e53</Sha>
<Sha>6f2ed01d1af9429d874aca1eea60d3212167bc40</Sha>
</Dependency>
<Dependency Name="Microsoft.CodeAnalysis.CSharp.Features" Version="4.13.0-2.24564.3">
<Dependency Name="Microsoft.CodeAnalysis.CSharp.Features" Version="4.13.0-3.24576.11">
<Uri>https://github.com/dotnet/roslyn</Uri>
<Sha>826b0db12582b6b645ed1cf5e1565f767af31e53</Sha>
<Sha>6f2ed01d1af9429d874aca1eea60d3212167bc40</Sha>
</Dependency>
<Dependency Name="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.13.0-2.24564.3">
<Dependency Name="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.13.0-3.24576.11">
<Uri>https://github.com/dotnet/roslyn</Uri>
<Sha>826b0db12582b6b645ed1cf5e1565f767af31e53</Sha>
<Sha>6f2ed01d1af9429d874aca1eea60d3212167bc40</Sha>
</Dependency>
<Dependency Name="Microsoft.CodeAnalysis.EditorFeatures" Version="4.13.0-2.24564.3">
<Dependency Name="Microsoft.CodeAnalysis.EditorFeatures" Version="4.13.0-3.24576.11">
<Uri>https://github.com/dotnet/roslyn</Uri>
<Sha>826b0db12582b6b645ed1cf5e1565f767af31e53</Sha>
<Sha>6f2ed01d1af9429d874aca1eea60d3212167bc40</Sha>
</Dependency>
<Dependency Name="Microsoft.CodeAnalysis.EditorFeatures.Common" Version="4.13.0-2.24564.3">
<Dependency Name="Microsoft.CodeAnalysis.EditorFeatures.Common" Version="4.13.0-3.24576.11">
<Uri>https://github.com/dotnet/roslyn</Uri>
<Sha>826b0db12582b6b645ed1cf5e1565f767af31e53</Sha>
<Sha>6f2ed01d1af9429d874aca1eea60d3212167bc40</Sha>
</Dependency>
<Dependency Name="Microsoft.CodeAnalysis.EditorFeatures.Text" Version="4.13.0-2.24564.3">
<Dependency Name="Microsoft.CodeAnalysis.EditorFeatures.Text" Version="4.13.0-3.24576.11">
<Uri>https://github.com/dotnet/roslyn</Uri>
<Sha>826b0db12582b6b645ed1cf5e1565f767af31e53</Sha>
<Sha>6f2ed01d1af9429d874aca1eea60d3212167bc40</Sha>
</Dependency>
<Dependency Name="Microsoft.CodeAnalysis.EditorFeatures.Wpf" Version="4.13.0-2.24564.3">
<Dependency Name="Microsoft.CodeAnalysis.EditorFeatures.Wpf" Version="4.13.0-3.24576.11">
<Uri>https://github.com/dotnet/roslyn</Uri>
<Sha>826b0db12582b6b645ed1cf5e1565f767af31e53</Sha>
<Sha>6f2ed01d1af9429d874aca1eea60d3212167bc40</Sha>
</Dependency>
<Dependency Name="Microsoft.CodeAnalysis.Remote.ServiceHub" Version="4.13.0-2.24564.3">
<Dependency Name="Microsoft.CodeAnalysis.Remote.ServiceHub" Version="4.13.0-3.24576.11">
<Uri>https://github.com/dotnet/roslyn</Uri>
<Sha>826b0db12582b6b645ed1cf5e1565f767af31e53</Sha>
<Sha>6f2ed01d1af9429d874aca1eea60d3212167bc40</Sha>
</Dependency>
<Dependency Name="Microsoft.CodeAnalysis.VisualBasic.Workspaces" Version="4.13.0-2.24564.3">
<Dependency Name="Microsoft.CodeAnalysis.VisualBasic.Workspaces" Version="4.13.0-3.24576.11">
<Uri>https://github.com/dotnet/roslyn</Uri>
<Sha>826b0db12582b6b645ed1cf5e1565f767af31e53</Sha>
<Sha>6f2ed01d1af9429d874aca1eea60d3212167bc40</Sha>
</Dependency>
<Dependency Name="Microsoft.CodeAnalysis.Workspaces.Common" Version="4.13.0-2.24564.3">
<Dependency Name="Microsoft.CodeAnalysis.Workspaces.Common" Version="4.13.0-3.24576.11">
<Uri>https://github.com/dotnet/roslyn</Uri>
<Sha>826b0db12582b6b645ed1cf5e1565f767af31e53</Sha>
<Sha>6f2ed01d1af9429d874aca1eea60d3212167bc40</Sha>
</Dependency>
<Dependency Name="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="4.13.0-2.24564.3">
<Dependency Name="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="4.13.0-3.24576.11">
<Uri>https://github.com/dotnet/roslyn</Uri>
<Sha>826b0db12582b6b645ed1cf5e1565f767af31e53</Sha>
<Sha>6f2ed01d1af9429d874aca1eea60d3212167bc40</Sha>
</Dependency>
<Dependency Name="Microsoft.VisualStudio.LanguageServices" Version="4.13.0-2.24564.3">
<Dependency Name="Microsoft.VisualStudio.LanguageServices" Version="4.13.0-3.24576.11">
<Uri>https://github.com/dotnet/roslyn</Uri>
<Sha>826b0db12582b6b645ed1cf5e1565f767af31e53</Sha>
<Sha>6f2ed01d1af9429d874aca1eea60d3212167bc40</Sha>
</Dependency>
<Dependency Name="Microsoft.CodeAnalysis.Test.Utilities" Version="4.13.0-2.24564.3">
<Dependency Name="Microsoft.CodeAnalysis.Test.Utilities" Version="4.13.0-3.24576.11">
<Uri>https://github.com/dotnet/roslyn</Uri>
<Sha>826b0db12582b6b645ed1cf5e1565f767af31e53</Sha>
<Sha>6f2ed01d1af9429d874aca1eea60d3212167bc40</Sha>
</Dependency>
<!-- Intermediate is necessary for source build. -->
<Dependency Name="Microsoft.SourceBuild.Intermediate.roslyn" Version="4.13.0-2.24564.3">
<Dependency Name="Microsoft.SourceBuild.Intermediate.roslyn" Version="4.13.0-3.24576.11">
<Uri>https://github.com/dotnet/roslyn</Uri>
<Sha>826b0db12582b6b645ed1cf5e1565f767af31e53</Sha>
<Sha>6f2ed01d1af9429d874aca1eea60d3212167bc40</Sha>
<SourceBuild RepoName="roslyn" ManagedOnly="true" />
</Dependency>
</ProductDependencies>

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

@ -53,25 +53,25 @@
<MicrosoftSourceBuildIntermediatearcadePackageVersion>9.0.0-beta.24572.2</MicrosoftSourceBuildIntermediatearcadePackageVersion>
<MicrosoftDotNetXliffTasksPackageVersion>1.0.0-beta.23475.1</MicrosoftDotNetXliffTasksPackageVersion>
<MicrosoftSourceBuildIntermediatexlifftasksPackageVersion>1.0.0-beta.23475.1</MicrosoftSourceBuildIntermediatexlifftasksPackageVersion>
<MicrosoftNetCompilersToolsetPackageVersion>4.13.0-2.24564.3</MicrosoftNetCompilersToolsetPackageVersion>
<MicrosoftCommonLanguageServerProtocolFrameworkPackageVersion>4.13.0-2.24564.3</MicrosoftCommonLanguageServerProtocolFrameworkPackageVersion>
<MicrosoftCodeAnalysisExternalAccessRazorPackageVersion>4.13.0-2.24564.3</MicrosoftCodeAnalysisExternalAccessRazorPackageVersion>
<MicrosoftCodeAnalysisCommonPackageVersion>4.13.0-2.24564.3</MicrosoftCodeAnalysisCommonPackageVersion>
<MicrosoftCodeAnalysisCSharpPackageVersion>4.13.0-2.24564.3</MicrosoftCodeAnalysisCSharpPackageVersion>
<MicrosoftCodeAnalysisCSharpEditorFeaturesPackageVersion>4.13.0-2.24564.3</MicrosoftCodeAnalysisCSharpEditorFeaturesPackageVersion>
<MicrosoftCodeAnalysisCSharpFeaturesPackageVersion>4.13.0-2.24564.3</MicrosoftCodeAnalysisCSharpFeaturesPackageVersion>
<MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion>4.13.0-2.24564.3</MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion>
<MicrosoftCodeAnalysisEditorFeaturesPackageVersion>4.13.0-2.24564.3</MicrosoftCodeAnalysisEditorFeaturesPackageVersion>
<MicrosoftCodeAnalysisEditorFeaturesCommonPackageVersion>4.13.0-2.24564.3</MicrosoftCodeAnalysisEditorFeaturesCommonPackageVersion>
<MicrosoftCodeAnalysisEditorFeaturesTextPackageVersion>4.13.0-2.24564.3</MicrosoftCodeAnalysisEditorFeaturesTextPackageVersion>
<MicrosoftCodeAnalysisEditorFeaturesWpfPackageVersion>4.13.0-2.24564.3</MicrosoftCodeAnalysisEditorFeaturesWpfPackageVersion>
<MicrosoftCodeAnalysisRemoteServiceHubPackageVersion>4.13.0-2.24564.3</MicrosoftCodeAnalysisRemoteServiceHubPackageVersion>
<MicrosoftCodeAnalysisTestUtilitiesPackageVersion>4.13.0-2.24564.3</MicrosoftCodeAnalysisTestUtilitiesPackageVersion>
<MicrosoftCodeAnalysisVisualBasicWorkspacesPackageVersion>4.13.0-2.24564.3</MicrosoftCodeAnalysisVisualBasicWorkspacesPackageVersion>
<MicrosoftCodeAnalysisWorkspacesCommonPackageVersion>4.13.0-2.24564.3</MicrosoftCodeAnalysisWorkspacesCommonPackageVersion>
<MicrosoftCodeAnalysisWorkspacesMSBuildPackageVersion>4.13.0-2.24564.3</MicrosoftCodeAnalysisWorkspacesMSBuildPackageVersion>
<MicrosoftSourceBuildIntermediateroslynPackageVersion>4.13.0-2.24564.3</MicrosoftSourceBuildIntermediateroslynPackageVersion>
<MicrosoftVisualStudioLanguageServicesPackageVersion>4.13.0-2.24564.3</MicrosoftVisualStudioLanguageServicesPackageVersion>
<MicrosoftNetCompilersToolsetPackageVersion>4.13.0-3.24576.11</MicrosoftNetCompilersToolsetPackageVersion>
<MicrosoftCommonLanguageServerProtocolFrameworkPackageVersion>4.13.0-3.24576.11</MicrosoftCommonLanguageServerProtocolFrameworkPackageVersion>
<MicrosoftCodeAnalysisExternalAccessRazorPackageVersion>4.13.0-3.24576.11</MicrosoftCodeAnalysisExternalAccessRazorPackageVersion>
<MicrosoftCodeAnalysisCommonPackageVersion>4.13.0-3.24576.11</MicrosoftCodeAnalysisCommonPackageVersion>
<MicrosoftCodeAnalysisCSharpPackageVersion>4.13.0-3.24576.11</MicrosoftCodeAnalysisCSharpPackageVersion>
<MicrosoftCodeAnalysisCSharpEditorFeaturesPackageVersion>4.13.0-3.24576.11</MicrosoftCodeAnalysisCSharpEditorFeaturesPackageVersion>
<MicrosoftCodeAnalysisCSharpFeaturesPackageVersion>4.13.0-3.24576.11</MicrosoftCodeAnalysisCSharpFeaturesPackageVersion>
<MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion>4.13.0-3.24576.11</MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion>
<MicrosoftCodeAnalysisEditorFeaturesPackageVersion>4.13.0-3.24576.11</MicrosoftCodeAnalysisEditorFeaturesPackageVersion>
<MicrosoftCodeAnalysisEditorFeaturesCommonPackageVersion>4.13.0-3.24576.11</MicrosoftCodeAnalysisEditorFeaturesCommonPackageVersion>
<MicrosoftCodeAnalysisEditorFeaturesTextPackageVersion>4.13.0-3.24576.11</MicrosoftCodeAnalysisEditorFeaturesTextPackageVersion>
<MicrosoftCodeAnalysisEditorFeaturesWpfPackageVersion>4.13.0-3.24576.11</MicrosoftCodeAnalysisEditorFeaturesWpfPackageVersion>
<MicrosoftCodeAnalysisRemoteServiceHubPackageVersion>4.13.0-3.24576.11</MicrosoftCodeAnalysisRemoteServiceHubPackageVersion>
<MicrosoftCodeAnalysisTestUtilitiesPackageVersion>4.13.0-3.24576.11</MicrosoftCodeAnalysisTestUtilitiesPackageVersion>
<MicrosoftCodeAnalysisVisualBasicWorkspacesPackageVersion>4.13.0-3.24576.11</MicrosoftCodeAnalysisVisualBasicWorkspacesPackageVersion>
<MicrosoftCodeAnalysisWorkspacesCommonPackageVersion>4.13.0-3.24576.11</MicrosoftCodeAnalysisWorkspacesCommonPackageVersion>
<MicrosoftCodeAnalysisWorkspacesMSBuildPackageVersion>4.13.0-3.24576.11</MicrosoftCodeAnalysisWorkspacesMSBuildPackageVersion>
<MicrosoftSourceBuildIntermediateroslynPackageVersion>4.13.0-3.24576.11</MicrosoftSourceBuildIntermediateroslynPackageVersion>
<MicrosoftVisualStudioLanguageServicesPackageVersion>4.13.0-3.24576.11</MicrosoftVisualStudioLanguageServicesPackageVersion>
<!--
Exception - Microsoft.Extensions.ObjectPool and System.Collections.Immutable packages are not updated by automation,
but are present in Version.Details.xml for source-build PVP flow. See the comment in Version.Details.xml for more information.

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

@ -36,5 +36,6 @@
<ServiceHubService Include="Microsoft.VisualStudio.Razor.Hover" ClassName="Microsoft.CodeAnalysis.Remote.Razor.RemoteHoverService+Factory" />
<ServiceHubService Include="Microsoft.VisualStudio.Razor.Completion" ClassName="Microsoft.CodeAnalysis.Remote.Razor.RemoteCompletionService+Factory" />
<ServiceHubService Include="Microsoft.VisualStudio.Razor.CodeActions" ClassName="Microsoft.CodeAnalysis.Remote.Razor.RemoteCodeActionsService+Factory" />
<ServiceHubService Include="Microsoft.VisualStudio.Razor.FindAllReferences" ClassName="Microsoft.CodeAnalysis.Remote.Razor.RemoteFindAllReferencesService+Factory" />
</ItemGroup>
</Project>

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

@ -212,6 +212,8 @@ internal partial class RazorLanguageServer : SystemTextJsonLanguageServer<RazorR
services.AddHandler<ColorPresentationEndpoint>();
services.AddHandlerWithCapabilities<ProjectContextsEndpoint>();
services.AddHandlerWithCapabilities<FindAllReferencesEndpoint>();
}
services.AddHandler<WrapWithTagEndpoint>();
@ -219,7 +221,6 @@ internal partial class RazorLanguageServer : SystemTextJsonLanguageServer<RazorR
services.AddHandler<RazorProximityExpressionsEndpoint>();
services.AddHandlerWithCapabilities<ValidateBreakpointRangeEndpoint>();
services.AddHandlerWithCapabilities<FindAllReferencesEndpoint>();
services.AddHandlerWithCapabilities<MapCodeEndpoint>();
}
}

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

@ -0,0 +1,19 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.ExternalAccess.Razor;
using Roslyn.LanguageServer.Protocol;
using LspLocation = Roslyn.LanguageServer.Protocol.Location;
namespace Microsoft.CodeAnalysis.Razor.Remote;
internal interface IRemoteFindAllReferencesService : IRemoteJsonService
{
ValueTask<RemoteResponse<SumType<VSInternalReferenceItem, LspLocation>[]?>> FindAllReferencesAsync(
JsonSerializableRazorPinnedSolutionInfoWrapper solutionInfo,
JsonSerializableDocumentId razorDocumentId,
Position position,
CancellationToken cancellationToken);
}

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

@ -39,6 +39,7 @@ internal static class RazorServices
(typeof(IRemoteDiagnosticsService), null),
(typeof(IRemoteCompletionService), null),
(typeof(IRemoteCodeActionsService), null),
(typeof(IRemoteFindAllReferencesService), null),
];
private const string ComponentName = "Razor";

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

@ -0,0 +1,116 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.ExternalAccess.Razor;
using Microsoft.CodeAnalysis.Razor.DocumentMapping;
using Microsoft.CodeAnalysis.Razor.Protocol;
using Microsoft.CodeAnalysis.Razor.Remote;
using Microsoft.CodeAnalysis.Remote.Razor.DocumentMapping;
using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem;
using Microsoft.CodeAnalysis.Text;
using Roslyn.LanguageServer.Protocol;
using static Microsoft.CodeAnalysis.Razor.Remote.RemoteResponse<Roslyn.LanguageServer.Protocol.SumType<Roslyn.LanguageServer.Protocol.VSInternalReferenceItem, Roslyn.LanguageServer.Protocol.Location>[]?>;
using ExternalHandlers = Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost.Handlers;
using LspLocation = Roslyn.LanguageServer.Protocol.Location;
using VsLspExtensions = Microsoft.VisualStudio.LanguageServer.Protocol.VsLspExtensions;
namespace Microsoft.CodeAnalysis.Remote.Razor;
internal sealed class RemoteFindAllReferencesService(in ServiceArgs args) : RazorDocumentServiceBase(in args), IRemoteFindAllReferencesService
{
internal sealed class Factory : FactoryBase<IRemoteFindAllReferencesService>
{
protected override IRemoteFindAllReferencesService CreateService(in ServiceArgs args)
=> new RemoteFindAllReferencesService(in args);
}
private readonly IClientCapabilitiesService _clientCapabilitiesService = args.ExportProvider.GetExportedValue<IClientCapabilitiesService>();
protected override IDocumentPositionInfoStrategy DocumentPositionInfoStrategy => PreferAttributeNameDocumentPositionInfoStrategy.Instance;
public ValueTask<RemoteResponse<SumType<VSInternalReferenceItem, LspLocation>[]?>> FindAllReferencesAsync(
JsonSerializableRazorPinnedSolutionInfoWrapper solutionInfo,
JsonSerializableDocumentId documentId,
Position position,
CancellationToken cancellationToken)
=> RunServiceAsync(
solutionInfo,
documentId,
context => GetImplementationAsync(context, position, cancellationToken),
cancellationToken);
private async ValueTask<RemoteResponse<SumType<VSInternalReferenceItem, LspLocation>[]?>> GetImplementationAsync(
RemoteDocumentContext context,
Position position,
CancellationToken cancellationToken)
{
var codeDocument = await context.GetCodeDocumentAsync(cancellationToken).ConfigureAwait(false);
if (!codeDocument.Source.Text.TryGetAbsoluteIndex(position, out var hostDocumentIndex))
{
return NoFurtherHandling;
}
var positionInfo = GetPositionInfo(codeDocument, hostDocumentIndex, preferCSharpOverHtml: true);
if (positionInfo.LanguageKind is not RazorLanguageKind.CSharp)
{
return NoFurtherHandling;
}
// Finally, call into C#.
var generatedDocument = await context.Snapshot
.GetGeneratedDocumentAsync(cancellationToken)
.ConfigureAwait(false);
var results = await ExternalHandlers.FindAllReferences
.FindReferencesAsync(
RemoteWorkspaceAccessor.GetWorkspace(),
generatedDocument,
VsLspExtensions.ToLinePosition(positionInfo.Position),
_clientCapabilitiesService.ClientCapabilities.SupportsVisualStudioExtensions,
cancellationToken)
.ConfigureAwait(false);
if (results is null and not [])
{
// C# didn't return anything, so we're done.
return NoFurtherHandling;
}
// Map the C# locations back to the Razor file.
foreach (var result in results)
{
var location = result.TryGetFirst(out var referenceItem)
? referenceItem.Location
: result.Second;
if (location is null)
{
continue;
}
var (mappedUri, mappedRange) = await DocumentMappingService.MapToHostDocumentUriAndRangeAsync(context.Snapshot, location.Uri, location.Range.ToLinePositionSpan(), cancellationToken).ConfigureAwait(false);
if (referenceItem is not null)
{
// Indicates the reference item is directly available in the code
referenceItem.Origin = VSInternalItemOrigin.Exact;
// If we're going to change the Uri, then also override the file paths
if (mappedUri != location.Uri)
{
referenceItem.DisplayPath = mappedUri.AbsolutePath;
referenceItem.DocumentName = mappedUri.AbsolutePath;
}
}
location.Uri = mappedUri;
location.Range = mappedRange.ToRange();
}
return Results(results);
}
}

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

@ -0,0 +1,83 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System.Collections.Immutable;
using System.Composition;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost;
using Microsoft.CodeAnalysis.Razor.Remote;
using Roslyn.LanguageServer.Protocol;
using LspLocation = Roslyn.LanguageServer.Protocol.Location;
using VSLSP = Microsoft.VisualStudio.LanguageServer.Protocol;
namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost;
#pragma warning disable RS0030 // Do not use banned APIs
[Shared]
[CohostEndpoint(Methods.TextDocumentReferencesName)]
[Export(typeof(IDynamicRegistrationProvider))]
[ExportCohostStatelessLspService(typeof(CohostFindAllReferencesEndpoint))]
[method: ImportingConstructor]
#pragma warning restore RS0030 // Do not use banned APIs
internal sealed class CohostFindAllReferencesEndpoint(
IRemoteServiceInvoker remoteServiceInvoker)
: AbstractRazorCohostDocumentRequestHandler<ReferenceParams, SumType<VSInternalReferenceItem, LspLocation>[]?>, IDynamicRegistrationProvider
{
private readonly IRemoteServiceInvoker _remoteServiceInvoker = remoteServiceInvoker;
protected override bool MutatesSolutionState => false;
protected override bool RequiresLSPSolution => true;
public ImmutableArray<VSLSP.Registration> GetRegistrations(VSLSP.VSInternalClientCapabilities clientCapabilities, RazorCohostRequestContext requestContext)
{
if (clientCapabilities.TextDocument?.References?.DynamicRegistration == true)
{
return [new VSLSP.Registration
{
Method = Methods.TextDocumentReferencesName,
RegisterOptions = new VSLSP.ReferenceRegistrationOptions()
}];
}
return [];
}
protected override RazorTextDocumentIdentifier? GetRazorTextDocumentIdentifier(ReferenceParams request)
=> request.TextDocument.ToRazorTextDocumentIdentifier();
protected override Task<SumType<VSInternalReferenceItem, LspLocation>[]?> HandleRequestAsync(ReferenceParams request, RazorCohostRequestContext context, CancellationToken cancellationToken)
=> HandleRequestAsync(
context.TextDocument.AssumeNotNull(),
request.Position,
cancellationToken);
private async Task<SumType<VSInternalReferenceItem, LspLocation>[]?> HandleRequestAsync(TextDocument razorDocument, Position position, CancellationToken cancellationToken)
{
var response = await _remoteServiceInvoker
.TryInvokeAsync<IRemoteFindAllReferencesService, RemoteResponse<SumType<VSInternalReferenceItem, LspLocation>[]?>>(
razorDocument.Project.Solution,
(service, solutionInfo, cancellationToken) =>
service.FindAllReferencesAsync(solutionInfo, razorDocument.Id, position, cancellationToken),
cancellationToken)
.ConfigureAwait(false);
if (response.Result is SumType<VSInternalReferenceItem, LspLocation>[] results)
{
return results;
}
return null;
}
internal TestAccessor GetTestAccessor() => new(this);
internal readonly struct TestAccessor(CohostFindAllReferencesEndpoint instance)
{
public Task<SumType<VSInternalReferenceItem, LspLocation>[]?> HandleRequestAsync(TextDocument razorDocument, Position position, CancellationToken cancellationToken)
=> instance.HandleRequestAsync(razorDocument, position, cancellationToken);
}
}

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

@ -0,0 +1,241 @@
// 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.Tasks;
using Microsoft.AspNetCore.Razor;
using Microsoft.AspNetCore.Razor.Test.Common;
using Microsoft.AspNetCore.Razor.Utilities;
using Microsoft.CodeAnalysis.ExternalAccess.Razor;
using Microsoft.CodeAnalysis.Text;
using Roslyn.LanguageServer.Protocol;
using Xunit;
using Xunit.Abstractions;
namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost;
public class CohostFindAllReferencesEndpointTest(ITestOutputHelper testOutputHelper) : CohostEndpointTestBase(testOutputHelper)
{
[Theory]
[CombinatorialData]
public Task FindCSharpMember(bool supportsVSExtensions)
=> VerifyFindAllReferencesAsync("""
@{
string M()
{
return [|MyName|];
}
}
<p>@[|MyName|]</p>
@code {
private const string [|$$MyName|] = "David";
}
""",
supportsVSExtensions);
[Theory]
[CombinatorialData]
public async Task ComponentAttribute(bool supportsVSExtensions)
{
TestCode input = """
<SurveyPrompt [|Ti$$tle|]="InputValue" />
""";
TestCode surveyPrompt = """
@namespace SomeProject
<div></div>
@code
{
[Parameter]
public string [|Title|] { get; set; }
}
""";
TestCode surveyPromptGeneratedCode = """
// <auto-generated/>
#pragma warning disable 1591
namespace SomeProject
{
#line default
using global::System;
using global::System.Collections.Generic;
using global::System.Linq;
using global::System.Threading.Tasks;
#nullable restore
#line 1 "c:\users\example\src\SomeProject\_Imports.razor"
using Microsoft.AspNetCore.Components;
#nullable disable
#nullable restore
#line 2 "c:\users\example\src\SomeProject\_Imports.razor"
using Microsoft.AspNetCore.Components.Authorization;
#nullable disable
#nullable restore
#line 3 "c:\users\example\src\SomeProject\_Imports.razor"
using Microsoft.AspNetCore.Components.Forms;
#nullable disable
#nullable restore
#line 4 "c:\users\example\src\SomeProject\_Imports.razor"
using Microsoft.AspNetCore.Components.Routing;
#nullable disable
#nullable restore
#line 5 "c:\users\example\src\SomeProject\_Imports.razor"
using Microsoft.AspNetCore.Components.Web;
#line default
#line hidden
#nullable disable
#nullable restore
public partial class SurveyPrompt : global::Microsoft.AspNetCore.Components.ComponentBase
#nullable disable
{
#pragma warning disable 219
private void __RazorDirectiveTokenHelpers__() {
((global::System.Action)(() => {
#nullable restore
#line 1 "c:\users\example\src\SomeProject\SurveyPrompt.razor"
global::System.Object __typeHelper = nameof(SomeProject);
#line default
#line hidden
#nullable disable
}
))();
}
#pragma warning restore 219
#pragma warning disable 0414
private static object __o = null;
#pragma warning restore 0414
#pragma warning disable 1998
protected override void BuildRenderTree(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
{
}
#pragma warning restore 1998
#nullable restore
#line 6 "c:\users\example\src\SomeProject\SurveyPrompt.razor"
[Parameter]
public string Title { get; set; }
#line default
#line hidden
#nullable disable
}
}
#pragma warning restore 1591
""";
await VerifyFindAllReferencesAsync(input, supportsVSExtensions,
(FilePath("SurveyPrompt.razor"), surveyPrompt),
(FilePath("SurveyPrompt.razor.g.cs"), surveyPromptGeneratedCode));
}
[Theory]
[CombinatorialData]
public async Task OtherCSharpFile(bool supportsVSExtensions)
{
TestCode input = """
@code
{
public void M()
{
var x = new OtherClass();
x.[|D$$ate|].ToString();
}
}
""";
TestCode otherClass = """
using System;
namespace SomeProject;
public class OtherClass
{
public DateTime [|Date|] => DateTime.Now;
}
""";
await VerifyFindAllReferencesAsync(input, supportsVSExtensions,
(FilePath("OtherClass.cs"), otherClass));
}
private async Task VerifyFindAllReferencesAsync(TestCode input, bool supportsVSExtensions, params (string fileName, TestCode testCode)[]? additionalFiles)
{
UpdateClientLSPInitializationOptions(c =>
{
c.ClientCapabilities.SupportsVisualStudioExtensions = supportsVSExtensions;
return c;
});
var document = await CreateProjectAndRazorDocumentAsync(input.Text, additionalFiles: additionalFiles.Select(f => (f.fileName, f.testCode.Text)).ToArray());
var inputText = await document.GetTextAsync(DisposalToken);
var position = inputText.GetPosition(input.Position);
var endpoint = new CohostFindAllReferencesEndpoint(RemoteServiceInvoker);
var textDocumentPositionParams = new TextDocumentPositionParams
{
Position = position,
TextDocument = new TextDocumentIdentifier { Uri = document.CreateUri() },
};
var results = await endpoint.GetTestAccessor().HandleRequestAsync(document, position, DisposalToken);
Assumes.NotNull(results);
var totalSpans = input.Spans.Length + additionalFiles.Sum(f => f.testCode.TryGetNamedSpans("", out var spans) ? spans.Length : 0);
Assert.Equal(totalSpans, results.Length);
var razorDocumentUri = document.CreateUri();
foreach (var result in results)
{
if (result.TryGetFirst(out var referenceItem))
{
Assert.True(supportsVSExtensions);
if (referenceItem.DisplayPath is not null)
{
Assert.False(referenceItem.DisplayPath.EndsWith(".g.cs"));
}
if (referenceItem.DocumentName is not null)
{
Assert.False(referenceItem.DocumentName.EndsWith(".g.cs"));
}
}
else
{
Assert.False(supportsVSExtensions);
}
}
foreach (var location in results.Select(GetLocation))
{
if (razorDocumentUri.Equals(location.Uri))
{
Assert.Single(input.Spans.Where(s => inputText.GetRange(s).Equals(location.Range)));
}
else
{
var additionalFile = Assert.Single(additionalFiles.Where(f => FilePathNormalizingComparer.Instance.Equals(f.fileName, location.Uri.AbsolutePath)));
var text = SourceText.From(additionalFile.testCode.Text);
Assert.Single(additionalFile.testCode.Spans.Where(s => text.GetRange(s).Equals(location.Range)));
}
}
}
private static Location GetLocation(SumType<VSInternalReferenceItem, Location> r)
{
return r.TryGetFirst(out var refItem)
? refItem.Location ?? Assumed.Unreachable<Location>()
: r.Second;
}
}