Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cohosting tests for Uri presentation #10642

Merged
merged 6 commits into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
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 Microsoft.CodeAnalysis.Razor.Workspaces;
Expand Down Expand Up @@ -58,14 +59,15 @@ internal class CohostUriPresentationEndpoint(
protected override RazorTextDocumentIdentifier? GetRazorTextDocumentIdentifier(VSInternalUriPresentationParams request)
=> request.TextDocument.ToRazorTextDocumentIdentifier();

protected override async Task<WorkspaceEdit?> HandleRequestAsync(VSInternalUriPresentationParams request, RazorCohostRequestContext context, CancellationToken cancellationToken)
{
var razorDocument = context.TextDocument.AssumeNotNull();
protected override Task<WorkspaceEdit?> HandleRequestAsync(VSInternalUriPresentationParams request, RazorCohostRequestContext context, CancellationToken cancellationToken)
=> HandleRequestAsync(request, context.TextDocument.AssumeNotNull(), cancellationToken);

private async Task<WorkspaceEdit?> HandleRequestAsync(VSInternalUriPresentationParams request, TextDocument razorDocument, CancellationToken cancellationToken)
{
var data = await _remoteServiceInvoker.TryInvokeAsync<IRemoteUriPresentationService, TextChange?>(
razorDocument.Project.Solution,
(service, solutionInfo, cancellationToken) => service.GetPresentationAsync(solutionInfo, razorDocument.Id, request.Range.ToLinePositionSpan(), request.Uris, cancellationToken),
cancellationToken).ConfigureAwait(false);
razorDocument.Project.Solution,
(service, solutionInfo, cancellationToken) => service.GetPresentationAsync(solutionInfo, razorDocument.Id, request.Range.ToLinePositionSpan(), request.Uris, cancellationToken),
cancellationToken).ConfigureAwait(false);

// If we got a response back, then either Razor or C# wants to do something with this, so we're good to go
if (data is { } textChange)
Expand Down Expand Up @@ -134,4 +136,12 @@ internal class CohostUriPresentationEndpoint(

return workspaceEdit;
}

internal TestAccessor GetTestAccessor() => new(this);

internal readonly struct TestAccessor(CohostUriPresentationEndpoint instance)
{
public Task<WorkspaceEdit?> HandleRequestAsync(VSInternalUriPresentationParams request, TextDocument razorDocument, CancellationToken cancellationToken)
=> instance.HandleRequestAsync(request, razorDocument, cancellationToken);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,22 @@ internal static class TestProjectData
static TestProjectData()
{
var baseDirectory = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "c:\\users\\example\\src" : "/home/example";
var someProjectPath = Path.Combine(baseDirectory, "SomeProject");
var someProjectObjPath = Path.Combine(someProjectPath, "obj");
SomeProjectPath = Path.Combine(baseDirectory, "SomeProject");
var someProjectObjPath = Path.Combine(SomeProjectPath, "obj");

SomeProject = new HostProject(Path.Combine(someProjectPath, "SomeProject.csproj"), someProjectObjPath, RazorConfiguration.Default, "SomeProject");
SomeProjectFile1 = new HostDocument(Path.Combine(someProjectPath, "File1.cshtml"), "File1.cshtml", FileKinds.Legacy);
SomeProjectFile2 = new HostDocument(Path.Combine(someProjectPath, "File2.cshtml"), "File2.cshtml", FileKinds.Legacy);
SomeProjectImportFile = new HostDocument(Path.Combine(someProjectPath, "_ViewImports.cshtml"), "_ViewImports.cshtml", FileKinds.Legacy);
SomeProjectNestedFile3 = new HostDocument(Path.Combine(someProjectPath, "Nested", "File3.cshtml"), "Nested\\File3.cshtml", FileKinds.Legacy);
SomeProjectNestedFile4 = new HostDocument(Path.Combine(someProjectPath, "Nested", "File4.cshtml"), "Nested\\File4.cshtml", FileKinds.Legacy);
SomeProjectNestedImportFile = new HostDocument(Path.Combine(someProjectPath, "Nested", "_ViewImports.cshtml"), "Nested\\_ViewImports.cshtml", FileKinds.Legacy);
SomeProjectComponentFile1 = new HostDocument(Path.Combine(someProjectPath, "File1.razor"), "File1.razor", FileKinds.Component);
SomeProjectComponentFile2 = new HostDocument(Path.Combine(someProjectPath, "File2.razor"), "File2.razor", FileKinds.Component);
SomeProjectComponentImportFile1 = new HostDocument(Path.Combine(someProjectPath, "_Imports.razor"), "_Imports.razor", FileKinds.Component);
SomeProjectNestedComponentFile3 = new HostDocument(Path.Combine(someProjectPath, "Nested", "File3.razor"), "Nested\\File3.razor", FileKinds.Component);
SomeProjectNestedComponentFile4 = new HostDocument(Path.Combine(someProjectPath, "Nested", "File4.razor"), "Nested\\File4.razor", FileKinds.Component);
SomeProjectCshtmlComponentFile5 = new HostDocument(Path.Combine(someProjectPath, "File5.cshtml"), "File5.cshtml", FileKinds.Component);
SomeProject = new HostProject(Path.Combine(SomeProjectPath, "SomeProject.csproj"), someProjectObjPath, RazorConfiguration.Default, "SomeProject");
SomeProjectFile1 = new HostDocument(Path.Combine(SomeProjectPath, "File1.cshtml"), "File1.cshtml", FileKinds.Legacy);
SomeProjectFile2 = new HostDocument(Path.Combine(SomeProjectPath, "File2.cshtml"), "File2.cshtml", FileKinds.Legacy);
SomeProjectImportFile = new HostDocument(Path.Combine(SomeProjectPath, "_ViewImports.cshtml"), "_ViewImports.cshtml", FileKinds.Legacy);
SomeProjectNestedFile3 = new HostDocument(Path.Combine(SomeProjectPath, "Nested", "File3.cshtml"), "Nested\\File3.cshtml", FileKinds.Legacy);
SomeProjectNestedFile4 = new HostDocument(Path.Combine(SomeProjectPath, "Nested", "File4.cshtml"), "Nested\\File4.cshtml", FileKinds.Legacy);
SomeProjectNestedImportFile = new HostDocument(Path.Combine(SomeProjectPath, "Nested", "_ViewImports.cshtml"), "Nested\\_ViewImports.cshtml", FileKinds.Legacy);
SomeProjectComponentFile1 = new HostDocument(Path.Combine(SomeProjectPath, "File1.razor"), "File1.razor", FileKinds.Component);
SomeProjectComponentFile2 = new HostDocument(Path.Combine(SomeProjectPath, "File2.razor"), "File2.razor", FileKinds.Component);
SomeProjectComponentImportFile1 = new HostDocument(Path.Combine(SomeProjectPath, "_Imports.razor"), "_Imports.razor", FileKinds.Component);
SomeProjectNestedComponentFile3 = new HostDocument(Path.Combine(SomeProjectPath, "Nested", "File3.razor"), "Nested\\File3.razor", FileKinds.Component);
SomeProjectNestedComponentFile4 = new HostDocument(Path.Combine(SomeProjectPath, "Nested", "File4.razor"), "Nested\\File4.razor", FileKinds.Component);
SomeProjectCshtmlComponentFile5 = new HostDocument(Path.Combine(SomeProjectPath, "File5.cshtml"), "File5.cshtml", FileKinds.Component);

var anotherProjectPath = Path.Combine(baseDirectory, "AnotherProject");
var anotherProjectObjPath = Path.Combine(anotherProjectPath, "obj");
Expand All @@ -53,6 +53,7 @@ static TestProjectData()
}

public static readonly HostProject SomeProject;
public static readonly string SomeProjectPath;
public static readonly HostDocument SomeProjectFile1;
public static readonly HostDocument SomeProjectFile2;
public static readonly HostDocument SomeProjectImportFile;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using Microsoft.AspNetCore.Razor.Test.Common.Workspaces;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Razor.Remote;
using Microsoft.CodeAnalysis.Razor.Workspaces;
using Microsoft.CodeAnalysis.Remote.Razor;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.Composition;
Expand All @@ -25,8 +26,11 @@ public abstract class CohostEndpointTestBase(ITestOutputHelper testOutputHelper)
private ExportProvider? _exportProvider;
private TestRemoteServiceInvoker? _remoteServiceInvoker;
private RemoteClientInitializationOptions _clientInitializationOptions;
private IFilePathService? _filePathService;

private protected TestRemoteServiceInvoker RemoteServiceInvoker => _remoteServiceInvoker.AssumeNotNull();
private protected IFilePathService FilePathService => _filePathService.AssumeNotNull();
private protected RemoteLanguageServerFeatureOptions FeatureOptions => OOPExportProvider.GetExportedValue<RemoteLanguageServerFeatureOptions>();

/// <summary>
/// The export provider for Razor OOP services (not Roslyn)
Expand Down Expand Up @@ -54,16 +58,17 @@ protected override async Task InitializeAsync()
UseRazorCohostServer = true
};
UpdateClientInitializationOptions(c => c);

_filePathService = new RemoteFilePathService(FeatureOptions);
}

private protected void UpdateClientInitializationOptions(Func<RemoteClientInitializationOptions, RemoteClientInitializationOptions> mutation)
{
_clientInitializationOptions = mutation(_clientInitializationOptions);
var featureOptions = OOPExportProvider.GetExportedValue<RemoteLanguageServerFeatureOptions>();
featureOptions.SetOptions(_clientInitializationOptions);
FeatureOptions.SetOptions(_clientInitializationOptions);
}

protected TextDocument CreateProjectAndRazorDocument(string contents, string? fileKind = null)
protected TextDocument CreateProjectAndRazorDocument(string contents, string? fileKind = null, (string fileName, string contents)[]? additionalFiles = null)
{
// Using IsLegacy means null == component, so easier for test authors
var isComponent = !FileKinds.IsLegacy(fileKind);
Expand All @@ -85,6 +90,7 @@ protected TextDocument CreateProjectAndRazorDocument(string contents, string? fi
assemblyName: projectName,
LanguageNames.CSharp,
documentFilePath)
.WithDefaultNamespace(TestProjectData.SomeProject.RootNamespace)
.WithMetadataReferences(AspNet80.ReferenceInfos.All.Select(r => r.Reference));

var solution = Workspace.CurrentSolution.AddProject(projectInfo);
Expand Down Expand Up @@ -119,6 +125,16 @@ @using Microsoft.AspNetCore.Components.Web
"""),
filePath: TestProjectData.SomeProjectImportFile.FilePath);

if (additionalFiles is not null)
{
foreach (var file in additionalFiles)
{
solution = Path.GetExtension(file.fileName) == ".cs"
? solution.AddDocument(DocumentId.CreateNewId(projectId), name: file.fileName, text: SourceText.From(file.contents), filePath: file.fileName)
: solution.AddAdditionalDocument(DocumentId.CreateNewId(projectId), name: file.fileName, text: SourceText.From(file.contents), filePath: file.fileName);
}
}

return solution.GetAdditionalDocument(documentId).AssumeNotNull();
}
}
Loading