diff --git a/eng/Version.Details.props b/eng/Version.Details.props
index 1966e0ef10d..cf1ad4498bd 100644
--- a/eng/Version.Details.props
+++ b/eng/Version.Details.props
@@ -7,27 +7,27 @@ This file should be imported by eng/Versions.props
- 5.0.0-2.25380.11
- 5.0.0-2.25380.11
- 5.0.0-2.25380.11
- 5.0.0-2.25380.11
- 5.0.0-2.25380.11
- 5.0.0-2.25380.11
- 5.0.0-2.25380.11
- 5.0.0-2.25380.11
- 5.0.0-2.25380.11
- 5.0.0-2.25380.11
- 5.0.0-2.25380.11
- 5.0.0-2.25380.11
- 5.0.0-2.25380.11
- 5.0.0-2.25380.11
- 5.0.0-2.25380.11
- 5.0.0-2.25380.11
- 5.0.0-2.25380.11
- 5.0.0-2.25380.11
- 5.0.0-2.25380.11
- 5.0.0-2.25380.11
- 5.0.0-2.25380.11
+ 5.0.0-2.25406.1
+ 5.0.0-2.25406.1
+ 5.0.0-2.25406.1
+ 5.0.0-2.25406.1
+ 5.0.0-2.25406.1
+ 5.0.0-2.25406.1
+ 5.0.0-2.25406.1
+ 5.0.0-2.25406.1
+ 5.0.0-2.25406.1
+ 5.0.0-2.25406.1
+ 5.0.0-2.25406.1
+ 5.0.0-2.25406.1
+ 5.0.0-2.25406.1
+ 5.0.0-2.25406.1
+ 5.0.0-2.25406.1
+ 5.0.0-2.25406.1
+ 5.0.0-2.25406.1
+ 5.0.0-2.25406.1
+ 5.0.0-2.25406.1
+ 5.0.0-2.25406.1
+ 5.0.0-2.25406.1
9.0.0-beta.25255.5
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index 0165310fb90..2c7386660b0 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -2,89 +2,89 @@
-
+
https://github.com/dotnet/roslyn
- 512fe5197056a877a86dff3054d8bd0028af13ed
+ 5759a992418f0fd3e206cc6f369b6f33e873dfca
-
+
https://github.com/dotnet/roslyn
- 512fe5197056a877a86dff3054d8bd0028af13ed
+ 5759a992418f0fd3e206cc6f369b6f33e873dfca
-
+
https://github.com/dotnet/roslyn
- 512fe5197056a877a86dff3054d8bd0028af13ed
+ 5759a992418f0fd3e206cc6f369b6f33e873dfca
-
+
https://github.com/dotnet/roslyn
- 512fe5197056a877a86dff3054d8bd0028af13ed
+ 5759a992418f0fd3e206cc6f369b6f33e873dfca
-
+
https://github.com/dotnet/roslyn
- 512fe5197056a877a86dff3054d8bd0028af13ed
+ 5759a992418f0fd3e206cc6f369b6f33e873dfca
-
+
https://github.com/dotnet/roslyn
- 512fe5197056a877a86dff3054d8bd0028af13ed
+ 5759a992418f0fd3e206cc6f369b6f33e873dfca
-
+
https://github.com/dotnet/roslyn
- 512fe5197056a877a86dff3054d8bd0028af13ed
+ 5759a992418f0fd3e206cc6f369b6f33e873dfca
-
+
https://github.com/dotnet/roslyn
- 512fe5197056a877a86dff3054d8bd0028af13ed
+ 5759a992418f0fd3e206cc6f369b6f33e873dfca
-
+
https://github.com/dotnet/roslyn
- 512fe5197056a877a86dff3054d8bd0028af13ed
+ 5759a992418f0fd3e206cc6f369b6f33e873dfca
-
+
https://github.com/dotnet/roslyn
- 512fe5197056a877a86dff3054d8bd0028af13ed
+ 5759a992418f0fd3e206cc6f369b6f33e873dfca
-
+
https://github.com/dotnet/roslyn
- 512fe5197056a877a86dff3054d8bd0028af13ed
+ 5759a992418f0fd3e206cc6f369b6f33e873dfca
-
+
https://github.com/dotnet/roslyn
- 512fe5197056a877a86dff3054d8bd0028af13ed
+ 5759a992418f0fd3e206cc6f369b6f33e873dfca
-
+
https://github.com/dotnet/roslyn
- 512fe5197056a877a86dff3054d8bd0028af13ed
+ 5759a992418f0fd3e206cc6f369b6f33e873dfca
-
+
https://github.com/dotnet/roslyn
- 512fe5197056a877a86dff3054d8bd0028af13ed
+ 5759a992418f0fd3e206cc6f369b6f33e873dfca
-
+
https://github.com/dotnet/roslyn
- 512fe5197056a877a86dff3054d8bd0028af13ed
+ 5759a992418f0fd3e206cc6f369b6f33e873dfca
-
+
https://github.com/dotnet/roslyn
- 512fe5197056a877a86dff3054d8bd0028af13ed
+ 5759a992418f0fd3e206cc6f369b6f33e873dfca
-
+
https://github.com/dotnet/roslyn
- 512fe5197056a877a86dff3054d8bd0028af13ed
+ 5759a992418f0fd3e206cc6f369b6f33e873dfca
-
+
https://github.com/dotnet/roslyn
- 512fe5197056a877a86dff3054d8bd0028af13ed
+ 5759a992418f0fd3e206cc6f369b6f33e873dfca
-
+
https://github.com/dotnet/roslyn
- 512fe5197056a877a86dff3054d8bd0028af13ed
+ 5759a992418f0fd3e206cc6f369b6f33e873dfca
-
+
https://github.com/dotnet/roslyn
- 512fe5197056a877a86dff3054d8bd0028af13ed
+ 5759a992418f0fd3e206cc6f369b6f33e873dfca
-
+
https://github.com/dotnet/roslyn
- 512fe5197056a877a86dff3054d8bd0028af13ed
+ 5759a992418f0fd3e206cc6f369b6f33e873dfca
diff --git a/eng/targets/Services.props b/eng/targets/Services.props
index c1eebc01466..1a90cd2d728 100644
--- a/eng/targets/Services.props
+++ b/eng/targets/Services.props
@@ -42,5 +42,6 @@
+
diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/CodeLens/CohostCodeLensEndpoint.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/CodeLens/CohostCodeLensEndpoint.cs
new file mode 100644
index 00000000000..ff84beda1fe
--- /dev/null
+++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/CodeLens/CohostCodeLensEndpoint.cs
@@ -0,0 +1,70 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections.Immutable;
+using System.Composition;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost;
+using Microsoft.CodeAnalysis.ExternalAccess.Razor.Features;
+using Microsoft.CodeAnalysis.Razor.Cohost;
+using Microsoft.CodeAnalysis.Razor.Remote;
+
+namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost;
+
+#pragma warning disable RS0030 // Do not use banned APIs
+[Shared]
+[CohostEndpoint(Methods.TextDocumentCodeLensName)]
+[Export(typeof(IDynamicRegistrationProvider))]
+[ExportRazorStatelessLspService(typeof(CohostCodeLensEndpoint))]
+[method: ImportingConstructor]
+#pragma warning restore RS0030 // Do not use banned APIs
+internal sealed class CohostCodeLensEndpoint(
+ IIncompatibleProjectService incompatibleProjectService,
+ IRemoteServiceInvoker remoteServiceInvoker)
+ : AbstractCohostDocumentEndpoint(incompatibleProjectService), IDynamicRegistrationProvider
+{
+ private readonly IRemoteServiceInvoker _remoteServiceInvoker = remoteServiceInvoker;
+
+ protected override bool MutatesSolutionState => false;
+ protected override bool RequiresLSPSolution => true;
+
+ public ImmutableArray GetRegistrations(VSInternalClientCapabilities clientCapabilities, RazorCohostRequestContext requestContext)
+ {
+ if (clientCapabilities.TextDocument?.CodeLens?.DynamicRegistration is true)
+ {
+ return [new Registration()
+ {
+ Method = Methods.TextDocumentCodeLensName,
+ RegisterOptions = new CodeLensRegistrationOptions()
+ {
+ ResolveProvider = true
+ }
+ }];
+ }
+
+ return [];
+ }
+
+ protected override RazorTextDocumentIdentifier? GetRazorTextDocumentIdentifier(CodeLensParams request)
+ => request.TextDocument.ToRazorTextDocumentIdentifier();
+
+ protected override async Task HandleRequestAsync(CodeLensParams request, TextDocument razorDocument, CancellationToken cancellationToken)
+ {
+ var result = await _remoteServiceInvoker.TryInvokeAsync(
+ razorDocument.Project.Solution,
+ (service, solutionInfo, cancellationToken) => service.GetCodeLensAsync(solutionInfo, razorDocument.Id, request.TextDocument, cancellationToken),
+ cancellationToken).ConfigureAwait(false);
+
+ return result;
+ }
+
+ internal TestAccessor GetTestAccessor() => new(this);
+
+ internal readonly struct TestAccessor(CohostCodeLensEndpoint instance)
+ {
+ public Task HandleRequestAsync(CodeLensParams request, TextDocument razorDocument, CancellationToken cancellationToken)
+ => instance.HandleRequestAsync(request, razorDocument, cancellationToken);
+ }
+}
diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/CodeLens/CohostResolveCodeLensEndpoint.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/CodeLens/CohostResolveCodeLensEndpoint.cs
new file mode 100644
index 00000000000..81f0a9600bd
--- /dev/null
+++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/CodeLens/CohostResolveCodeLensEndpoint.cs
@@ -0,0 +1,55 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Composition;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost;
+using Microsoft.CodeAnalysis.ExternalAccess.Razor.Features;
+using Microsoft.CodeAnalysis.Razor.Cohost;
+using Microsoft.CodeAnalysis.Razor.Remote;
+using Microsoft.CodeAnalysis.Razor.Workspaces.CodeLens;
+
+namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost;
+
+#pragma warning disable RS0030 // Do not use banned APIs
+[Shared]
+[CohostEndpoint(Methods.CodeLensResolveName)]
+[ExportRazorStatelessLspService(typeof(CohostResolveCodeLensEndpoint))]
+[method: ImportingConstructor]
+#pragma warning restore RS0030 // Do not use banned APIs
+internal sealed class CohostResolveCodeLensEndpoint(
+ IIncompatibleProjectService incompatibleProjectService,
+ IRemoteServiceInvoker remoteServiceInvoker)
+ : AbstractCohostDocumentEndpoint(incompatibleProjectService)
+{
+ private readonly IRemoteServiceInvoker _remoteServiceInvoker = remoteServiceInvoker;
+
+ protected override bool MutatesSolutionState => false;
+ protected override bool RequiresLSPSolution => true;
+
+ protected override RazorTextDocumentIdentifier? GetRazorTextDocumentIdentifier(LspCodeLens request)
+ => RazorCodeLensResolveData.Unwrap(request).TextDocument.ToRazorTextDocumentIdentifier();
+
+ protected override async Task HandleRequestAsync(LspCodeLens request, TextDocument razorDocument, CancellationToken cancellationToken)
+ {
+ var result = await _remoteServiceInvoker.TryInvokeAsync(
+ razorDocument.Project.Solution,
+ (service, solutionInfo, cancellationToken) => service.ResolveCodeLensAsync(solutionInfo, razorDocument.Id, request, cancellationToken),
+ cancellationToken).ConfigureAwait(false);
+
+ return result;
+ }
+
+ internal TestAccessor GetTestAccessor() => new(this);
+
+ internal readonly struct TestAccessor(CohostResolveCodeLensEndpoint instance)
+ {
+ public RazorTextDocumentIdentifier? GetRazorTextDocumentIdentifier(LspCodeLens request)
+ => instance.GetRazorTextDocumentIdentifier(request);
+
+ public Task HandleRequestAsync(LspCodeLens request, TextDocument razorDocument, CancellationToken cancellationToken)
+ => instance.HandleRequestAsync(request, razorDocument, cancellationToken);
+ }
+}
diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/CohostStartupService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/CohostStartupService.cs
index e9e40205ad0..89f9a6675cd 100644
--- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/CohostStartupService.cs
+++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/CohostStartupService.cs
@@ -14,11 +14,13 @@
namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost;
+#pragma warning disable CS0618 // Type or member is obsolete. Will be addressed in https://github.com/dotnet/razor/pull/12079 but Roslyn changes are batched
[Export(typeof(ICohostStartupService))]
[method: ImportingConstructor]
internal sealed class CohostStartupService(
[ImportMany] IEnumerable> lazyStartupServices,
ILoggerFactory loggerFactory) : ICohostStartupService
+#pragma warning restore CS0618 // Type or member is obsolete
{
private readonly ImmutableArray> _lazyStartupServices = [.. lazyStartupServices];
private readonly ILogger _logger = loggerFactory.GetOrCreateLogger();
diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/Microsoft.CodeAnalysis.Razor.CohostingShared.projitems b/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/Microsoft.CodeAnalysis.Razor.CohostingShared.projitems
index 31425b94a4f..9737517b6da 100644
--- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/Microsoft.CodeAnalysis.Razor.CohostingShared.projitems
+++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/Microsoft.CodeAnalysis.Razor.CohostingShared.projitems
@@ -11,6 +11,8 @@
+
+
diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/CodeLens/RazorCodeLensResolveData.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/CodeLens/RazorCodeLensResolveData.cs
new file mode 100644
index 00000000000..0c95f08499a
--- /dev/null
+++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/CodeLens/RazorCodeLensResolveData.cs
@@ -0,0 +1,36 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace Microsoft.CodeAnalysis.Razor.Workspaces.CodeLens;
+
+internal record RazorCodeLensResolveData(
+ // NOTE: Uppercase T here is required to match Roslyn's DocumentResolveData structure, so that the Roslyn
+ // language server can correctly route requests to us in cohosting. In future when we normalize
+ // on to Roslyn types, we should inherit from that class so we don't have to remember to do this.
+ [property: JsonPropertyName("TextDocument")] TextDocumentIdentifier TextDocument,
+ [property: JsonPropertyName("data")] object? OriginalData)
+{
+ public static RazorCodeLensResolveData Unwrap(LspCodeLens codeLens)
+ {
+ if (codeLens.Data is not JsonElement paramsObj)
+ {
+ throw new InvalidOperationException($"Invalid completion item received'{codeLens}'.");
+ }
+
+ if (paramsObj.Deserialize() is not { } data)
+ {
+ throw new InvalidOperationException($"codeLens.Data should be convertible to {nameof(RazorCodeLensResolveData)}");
+ }
+
+ return data;
+ }
+
+ public static void Wrap(LspCodeLens codeLens, TextDocumentIdentifier textDocument)
+ {
+ codeLens.Data = new RazorCodeLensResolveData(textDocument, codeLens.Data);
+ }
+}
diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/GlobalUsings.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/GlobalUsings.cs
index fe8f0f54995..c96b62ec2a0 100644
--- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/GlobalUsings.cs
+++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/GlobalUsings.cs
@@ -8,6 +8,7 @@
// makes for a more pleasant development experience.
// Avoid extern alias in every file that needs to use Range
+global using LspCodeLens = Roslyn.LanguageServer.Protocol.CodeLens;
global using LspColorPresentation = Roslyn.LanguageServer.Protocol.ColorPresentation;
global using LspDiagnostic = Roslyn.LanguageServer.Protocol.Diagnostic;
global using LspDiagnosticSeverity = Roslyn.LanguageServer.Protocol.DiagnosticSeverity;
diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteCodeLensService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteCodeLensService.cs
new file mode 100644
index 00000000000..85bd1b45a16
--- /dev/null
+++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteCodeLensService.cs
@@ -0,0 +1,23 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis.ExternalAccess.Razor;
+
+namespace Microsoft.CodeAnalysis.Razor.Remote;
+
+internal interface IRemoteCodeLensService : IRemoteJsonService
+{
+ ValueTask GetCodeLensAsync(
+ JsonSerializableRazorPinnedSolutionInfoWrapper solutionInfo,
+ JsonSerializableDocumentId razorDocumentId,
+ TextDocumentIdentifier textDocumentIdentifier,
+ CancellationToken cancellationToken);
+
+ ValueTask ResolveCodeLensAsync(
+ JsonSerializableRazorPinnedSolutionInfoWrapper solutionInfo,
+ JsonSerializableDocumentId razorDocumentId,
+ LspCodeLens codeLens,
+ CancellationToken cancellationToken);
+}
diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/RazorServices.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/RazorServices.cs
index 01eaf6df6e7..90bd0fb1efa 100644
--- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/RazorServices.cs
+++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/RazorServices.cs
@@ -45,6 +45,7 @@ internal static class RazorServices
(typeof(IRemoteCodeActionsService), null),
(typeof(IRemoteFindAllReferencesService), null),
(typeof(IRemoteMEFInitializationService), null),
+ (typeof(IRemoteCodeLensService), null),
];
private const string ComponentName = "Razor";
diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/CodeLens/RemoteCodeLensService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/CodeLens/RemoteCodeLensService.cs
new file mode 100644
index 00000000000..3ea5027518d
--- /dev/null
+++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/CodeLens/RemoteCodeLensService.cs
@@ -0,0 +1,89 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Razor.PooledObjects;
+using Microsoft.CodeAnalysis.ExternalAccess.Razor;
+using Microsoft.CodeAnalysis.Razor.DocumentMapping;
+using Microsoft.CodeAnalysis.Razor.Remote;
+using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem;
+
+namespace Microsoft.CodeAnalysis.Remote.Razor;
+
+internal class RemoteCodeLensService(in ServiceArgs args) : RazorDocumentServiceBase(args), IRemoteCodeLensService
+{
+ internal sealed class Factory : FactoryBase
+ {
+ protected override IRemoteCodeLensService CreateService(in ServiceArgs args)
+ => new RemoteCodeLensService(in args);
+ }
+
+ private readonly IDocumentMappingService _documentMappingService = args.ExportProvider.GetExportedValue();
+
+ public ValueTask GetCodeLensAsync(
+ JsonSerializableRazorPinnedSolutionInfoWrapper solutionInfo,
+ JsonSerializableDocumentId razorDocumentId,
+ TextDocumentIdentifier textDocumentIdentifier,
+ CancellationToken cancellationToken)
+ => RunServiceAsync(
+ solutionInfo,
+ razorDocumentId,
+ context => GetCodeLensAsync(context, textDocumentIdentifier, cancellationToken),
+ cancellationToken);
+
+ private async ValueTask GetCodeLensAsync(
+ RemoteDocumentContext context,
+ TextDocumentIdentifier textDocumentIdentifier,
+ CancellationToken cancellationToken)
+ {
+ var snapshot = context.Snapshot;
+ var generatedDocument = await snapshot.GetGeneratedDocumentAsync(cancellationToken).ConfigureAwait(false);
+
+ var csharpCodeLens = await ExternalAccess.Razor.Cohost.Handlers.CodeLens.GetCodeLensAsync(textDocumentIdentifier, generatedDocument, cancellationToken).ConfigureAwait(false);
+
+ if (csharpCodeLens is null)
+ {
+ return null;
+ }
+
+ var codeDocument = await context.GetCodeDocumentAsync(cancellationToken).ConfigureAwait(false);
+ var csharpDocument = codeDocument.GetCSharpDocument();
+ if (csharpDocument is null)
+ {
+ return null;
+ }
+
+ using var results = new PooledArrayBuilder(csharpCodeLens.Length);
+
+ foreach (var codeLens in csharpCodeLens)
+ {
+ if (_documentMappingService.TryMapToRazorDocumentRange(csharpDocument, codeLens.Range, out var razorRange))
+ {
+ codeLens.Range = razorRange;
+ results.Add(codeLens);
+ }
+ }
+
+ return results.ToArrayAndClear();
+ }
+
+ public ValueTask ResolveCodeLensAsync(
+ JsonSerializableRazorPinnedSolutionInfoWrapper solutionInfo,
+ JsonSerializableDocumentId razorDocumentId,
+ LspCodeLens codeLens,
+ CancellationToken cancellationToken)
+ => RunServiceAsync(
+ solutionInfo,
+ razorDocumentId,
+ context => ResolveCodeLensAsync(context, codeLens, cancellationToken),
+ cancellationToken);
+
+ private async ValueTask ResolveCodeLensAsync(RemoteDocumentContext context, LspCodeLens codeLens, CancellationToken cancellationToken)
+ {
+ var snapshot = context.Snapshot;
+ var generatedDocument = await snapshot.GetGeneratedDocumentAsync(cancellationToken).ConfigureAwait(false);
+
+ return await ExternalAccess.Razor.Cohost.Handlers.CodeLens.ResolveCodeLensAsync(codeLens, generatedDocument, cancellationToken).ConfigureAwait(false);
+ }
+}
diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Completion/RemoteCompletionService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Completion/RemoteCompletionService.cs
index 48a304b5a52..2569112203a 100644
--- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Completion/RemoteCompletionService.cs
+++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Completion/RemoteCompletionService.cs
@@ -204,6 +204,7 @@ private async ValueTask GetCompletionAsync(
VSInternalCompletionList? completionList = null;
using (_telemetryReporter.TrackLspRequest(Methods.TextDocumentCompletionName, Constants.ExternalAccessServerName, TelemetryThresholds.CompletionSubLSPTelemetryThreshold, correlationId))
{
+#pragma warning disable CS0618 // Type or member is obsolete. Will be addressed in a future PR but Roslyn changes are batched
completionList = await ExternalAccess.Razor.Cohost.Handlers.Completion.GetCompletionListAsync(
generatedDocument,
mappedLinePosition,
@@ -212,6 +213,7 @@ private async ValueTask GetCompletionAsync(
completionSetting,
cancellationToken)
.ConfigureAwait(false);
+#pragma warning restore CS0618 // Type or member is obsolete
}
if (completionList is null)
@@ -328,12 +330,14 @@ private async ValueTask ResolveCSharpCompletionItemAsy
var clientCapabilities = _clientCapabilitiesService.ClientCapabilities;
var completionListSetting = clientCapabilities.TextDocument?.Completion;
+#pragma warning disable CS0618 // Type or member is obsolete. Will be addressed in a future PR but Roslyn changes are batched
var result = await ExternalAccess.Razor.Cohost.Handlers.Completion.ResolveCompletionItemAsync(
request,
generatedDocument,
clientCapabilities.SupportsVisualStudioExtensions,
completionListSetting ?? new(),
cancellationToken).ConfigureAwait(false);
+#pragma warning restore CS0618 // Type or member is obsolete
var item = JsonHelpers.Convert(result).AssumeNotNull();
diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/InlayHints/RemoteInlayHintService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/InlayHints/RemoteInlayHintService.cs
index 40b123d2fb9..c6aba289f59 100644
--- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/InlayHints/RemoteInlayHintService.cs
+++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/InlayHints/RemoteInlayHintService.cs
@@ -67,8 +67,9 @@ protected override IRemoteInlayHintService CreateService(in ServiceArgs args)
var textDocument = inlayHintParams.TextDocument.WithUri(generatedDocument.CreateUri());
var range = projectedLinePositionSpan.ToRange();
+#pragma warning disable CS0618 // Type or member is obsolete. Will be addressed in a future PR but Roslyn changes are batched
var hints = await InlayHints.GetInlayHintsAsync(generatedDocument, textDocument, range, displayAllOverride, cancellationToken).ConfigureAwait(false);
-
+#pragma warning restore CS0618 // Type or member is obsolete
if (hints is null)
{
return null;
@@ -130,6 +131,8 @@ private async ValueTask ResolveInlayHintAsync(RemoteDocumentContext c
.GetGeneratedDocumentAsync(cancellationToken)
.ConfigureAwait(false);
+#pragma warning disable CS0618 // Type or member is obsolete. Will be addressed in a future PR but Roslyn changes are batched
return await InlayHints.ResolveInlayHintAsync(generatedDocument, inlayHint, cancellationToken).ConfigureAwait(false);
+#pragma warning restore CS0618 // Type or member is obsolete
}
}
diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostCodeLensEndpointTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostCodeLensEndpointTest.cs
new file mode 100644
index 00000000000..ab116f2fa9f
--- /dev/null
+++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostCodeLensEndpointTest.cs
@@ -0,0 +1,116 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.Json;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Razor.Test.Common;
+using Microsoft.CodeAnalysis.ExternalAccess.Razor;
+using Microsoft.CodeAnalysis.Razor.Protocol;
+using Microsoft.CodeAnalysis.Text;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost;
+
+public class CohostCodeLensEndpointTest(ITestOutputHelper testOutputHelper) : CohostEndpointTestBase(testOutputHelper)
+{
+ [Fact]
+ public Task OneMethod()
+ {
+ return VerifyCodeLensAsync("""
+
+
+ @code {
+ public void [|{|Position0:|}Method|]()
+ {
+ // This is a method
+ }
+ }
+ """,
+ expectedTitles: ["0 references"]);
+ }
+
+ [Fact]
+ public Task TwoMethods()
+ {
+ return VerifyCodeLensAsync("""
+
+
+ @code {
+ public void [|{|Position0:|}Method|]()
+ {
+ Method2();
+ }
+
+ public void [|{|Position1:|}Method2|]()
+ {
+ // This is another method
+ }
+ }
+ """,
+ expectedTitles: ["0 references", "1 reference"]);
+ }
+
+ [Fact]
+ public Task UsageInRazor()
+ {
+ return VerifyCodeLensAsync("""
+
+
+ @Method()
+
+ @code {
+ public string [|{|Position0:|}Method|]()
+ {
+ return "Hello, World!";
+ }
+ }
+ """,
+ expectedTitles: ["1 reference"]);
+ }
+
+ private async Task VerifyCodeLensAsync(TestCode input, string[] expectedTitles)
+ {
+ var document = CreateProjectAndRazorDocument(input.Text);
+ var inputText = SourceText.From(input.Text);
+
+ var endpoint = new CohostCodeLensEndpoint(IncompatibleProjectService, RemoteServiceInvoker);
+ var resolveEndpoint = new CohostResolveCodeLensEndpoint(IncompatibleProjectService, RemoteServiceInvoker);
+
+ var request = new CodeLensParams()
+ {
+ TextDocument = new TextDocumentIdentifier() { DocumentUri = document.CreateDocumentUri() },
+ };
+
+ var result = await endpoint.GetTestAccessor().HandleRequestAsync(request, document, DisposalToken);
+
+ Assert.NotNull(result);
+ foreach (var (codeLens, i) in result.Select((l, i) => (l, i)))
+ {
+ Assert.Contains(inputText.GetTextSpan(codeLens.Range), input.Spans);
+
+ // Resolve expects a JsonElement
+ codeLens.Data = JsonSerializer.SerializeToElement(codeLens.Data, JsonHelpers.JsonSerializerOptions);
+
+ var tdi = resolveEndpoint.GetTestAccessor().GetRazorTextDocumentIdentifier(codeLens);
+ Assert.NotNull(tdi);
+ Assert.Equal(document.CreateUri(), tdi.Value.Uri);
+
+ var resolved = await resolveEndpoint.GetTestAccessor().HandleRequestAsync(codeLens, document, DisposalToken);
+
+ Assert.NotNull(resolved);
+ Assert.NotNull(resolved.Command);
+ Assert.NotNull(resolved.Command.Arguments);
+ Assert.Equal(resolved.Command.Title, expectedTitles[i]);
+ Assert.Equal("roslyn.client.peekReferences", resolved.Command.CommandIdentifier);
+
+ var documentUri = Assert.IsType(resolved.Command.Arguments[0]);
+ Assert.Equal(document.CreateDocumentUri(), documentUri);
+
+ var position = Assert.IsType(resolved.Command.Arguments[1]);
+ Assert.Equal(input.NamedSpans[$"Position{i}"].Single(), inputText.GetTextSpan(position.ToZeroWidthRange()));
+ }
+ }
+}