Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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 @@ -186,6 +186,15 @@ private RazorVSInternalCodeAction[] ExtractCSharpCodeActionNamesFromData(RazorVS
continue;
}

// In VS Code, Roslyn adds duplicate code actions for every code action, to implement Fix All functionality.
// Until we implement support for that in the C# Extension, we want to filter them out.
// https://github.com/dotnet/razor/issues/11832
if (jsonData.TryGetProperty("FixAllFlavors", out var fixAllFlavours) &&
fixAllFlavours.GetArrayLength() > 0)
{
continue;
}

actions.Add(codeAction);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,16 @@ private protected void UpdateClientLSPInitializationOptions(Func<RemoteClientLSP
}
}

protected virtual TextDocument CreateProjectAndRazorDocument(
protected abstract TextDocument CreateProjectAndRazorDocument(
string contents,
RazorFileKind? fileKind = null,
string? documentFilePath = null,
(string fileName, string contents)[]? additionalFiles = null,
bool inGlobalNamespace = false,
bool miscellaneousFile = false);

protected TextDocument CreateProjectAndRazorDocument(
CodeAnalysis.Workspace remoteWorkspace,
string contents,
RazorFileKind? fileKind = null,
string? documentFilePath = null,
Expand All @@ -136,7 +145,6 @@ protected virtual TextDocument CreateProjectAndRazorDocument(
var projectId = ProjectId.CreateNewId(debugName: TestProjectData.SomeProject.DisplayName);
var documentId = DocumentId.CreateNewId(projectId, debugName: documentFilePath);

var remoteWorkspace = RemoteWorkspaceProvider.Instance.GetWorkspace();
return CreateProjectAndRazorDocument(remoteWorkspace, projectId, miscellaneousFile, documentId, documentFilePath, contents, additionalFiles, inGlobalNamespace);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
using Microsoft.CodeAnalysis.Razor.SemanticTokens;
using Microsoft.CodeAnalysis.Razor.Workspaces;
using Microsoft.CodeAnalysis.Razor.Workspaces.Settings;
using Microsoft.CodeAnalysis.Remote.Razor;
using Microsoft.VisualStudio.Composition;
using Microsoft.VisualStudio.Language.CodeCleanUp;
using Microsoft.VisualStudio.Razor.Settings;
using Xunit;
using Xunit.Abstractions;
Expand Down Expand Up @@ -94,7 +94,8 @@ protected TextDocument CreateProjectAndRazorDocument(
{
if (remoteOnly)
{
return base.CreateProjectAndRazorDocument(contents, fileKind: null, documentFilePath: null, additionalFiles: null, inGlobalNamespace: false, miscellaneousFile: false);
var remoteWorkspace = RemoteWorkspaceProvider.Instance.GetWorkspace();
return base.CreateProjectAndRazorDocument(remoteWorkspace, contents, fileKind: null, documentFilePath: null, additionalFiles: null, inGlobalNamespace: false, miscellaneousFile: false);
}

return this.CreateProjectAndRazorDocument(contents);
Expand All @@ -108,7 +109,8 @@ protected override TextDocument CreateProjectAndRazorDocument(
bool inGlobalNamespace = false,
bool miscellaneousFile = false)
{
var remoteDocument = base.CreateProjectAndRazorDocument(contents, fileKind, documentFilePath, additionalFiles, inGlobalNamespace, miscellaneousFile);
var remoteWorkspace = RemoteWorkspaceProvider.Instance.GetWorkspace();
var remoteDocument = base.CreateProjectAndRazorDocument(remoteWorkspace, contents, fileKind, documentFilePath, additionalFiles, inGlobalNamespace, miscellaneousFile);

// In this project we simulate remote services running OOP by creating a different workspace with a different
// set of services to represent the devenv Roslyn side of things. We don't have any actual solution syncing set
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<Link>Shared\%(RecursiveDir)%(FileName)%(Extension)</Link>
</Compile>

<Compile Include="..\Microsoft.VisualStudioCode.RazorExtension.Test\Endpoints\Shared\*.cs" LinkBase="Cohost\Shared" />
<Compile Include="..\Microsoft.VisualStudioCode.RazorExtension.Test\Endpoints\Shared\**\*.cs" LinkBase="Cohost\Shared" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,22 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.LanguageServer.Test;
using Microsoft.AspNetCore.Razor.Test.Common.Mef;
using Microsoft.AspNetCore.Razor.Test.Common.Workspaces;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Razor.Remote;
using Microsoft.CodeAnalysis.Razor.SemanticTokens;
using Microsoft.CodeAnalysis.Razor.Workspaces;
using Microsoft.CodeAnalysis.Razor.Workspaces.Settings;
using Microsoft.CodeAnalysis.Remote.Razor;
using Microsoft.VisualStudio.Composition;
using Microsoft.VisualStudioCode.RazorExtension.Configuration;
using Microsoft.VisualStudioCode.RazorExtension.Services;
using Xunit;
using Xunit.Abstractions;

namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost;
Expand All @@ -23,26 +28,24 @@ public abstract class CohostEndpointTestBase(ITestOutputHelper testOutputHelper)
private VSCodeRemoteServiceInvoker? _remoteServiceInvoker;
private IFilePathService? _filePathService;
private ISemanticTokensLegendService? _semanticTokensLegendService;
private Workspace? _workspace;

private protected override IRemoteServiceInvoker RemoteServiceInvoker => _remoteServiceInvoker.AssumeNotNull();
private protected override IClientSettingsManager ClientSettingsManager => _clientSettingsManager.AssumeNotNull();
private protected override IFilePathService FilePathService => _filePathService.AssumeNotNull();
private protected ISemanticTokensLegendService SemanticTokensLegendService => _semanticTokensLegendService.AssumeNotNull();

/// <summary>
/// The export provider for Roslyn "devenv" services, if tests opt-in to using them
/// </summary>
private protected ExportProvider? RoslynDevenvExportProvider { get; private set; }
private protected Workspace Workspace => _workspace.AssumeNotNull();

protected override async Task InitializeAsync()
{
await base.InitializeAsync();

InProcServiceFactory.TestAccessor.SetExportProvider(OOPExportProvider);

_workspace = CreateWorkspace();

var workspaceProvider = new VSCodeWorkspaceProvider();
var remoteWorkspace = RemoteWorkspaceProvider.Instance.GetWorkspace();
workspaceProvider.SetWorkspace(remoteWorkspace);
workspaceProvider.SetWorkspace(Workspace);

_remoteServiceInvoker = new VSCodeRemoteServiceInvoker(workspaceProvider, LoggerFactory);
AddDisposable(_remoteServiceInvoker);
Expand Down Expand Up @@ -82,4 +85,32 @@ private protected override RemoteClientLSPInitializationOptions GetRemoteClientL
TokenTypes = []
};
}

protected override TextDocument CreateProjectAndRazorDocument(
string contents,
RazorFileKind? fileKind = null,
string? documentFilePath = null,
(string fileName, string contents)[]? additionalFiles = null,
bool inGlobalNamespace = false,
bool miscellaneousFile = false)
{
return CreateProjectAndRazorDocument(Workspace, contents, fileKind, documentFilePath, additionalFiles, inGlobalNamespace, miscellaneousFile);
}

private AdhocWorkspace CreateWorkspace()
{
var composition = TestComposition.RoslynFeatures;

// We can't enforce that the composition is entirely valid, because we don't have a full MEF catalog, but we
// can assume there should be no errors related to Razor, and having this array makes debugging failures a lot
// easier.
var errors = composition.GetCompositionErrors().ToArray();
Assert.Empty(errors.Where(e => e.Contains("Razor")));

var roslynExportProvider = composition.ExportProviderFactory.CreateExportProvider();
AddDisposable(roslynExportProvider);
var workspace = TestWorkspace.CreateWithDiagnosticAnalyzers(roslynExportProvider);
AddDisposable(workspace);
return workspace;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ public async Task FullyQualify()
await VerifyCodeActionAsync(input, expected, LanguageServerConstants.CodeActions.FullyQualify);
}

#if !VSCODE
// This uses a nested code action in Roslyn which we don't support in VS Code
// https://github.com/dotnet/razor/issues/11832
[Fact]
public async Task FullyQualify_Multiple()
{
Expand Down Expand Up @@ -58,6 +61,7 @@ public class StringBuilder
codeActionName: LanguageServerConstants.CodeActions.FullyQualify,
childActionIndex: 0);
}
#endif

[Fact]
public async Task AddUsing()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@
using Microsoft.CodeAnalysis.Razor.Utilities;
using Microsoft.CodeAnalysis.Razor.Workspaces;
using Microsoft.CodeAnalysis.Remote.Razor;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.Razor.Settings;
using Roslyn.Test.Utilities;
using Xunit;
using Xunit.Abstractions;
Expand Down Expand Up @@ -220,8 +218,7 @@ private async Task VerifyCodeActionResultAsync(TextDocument document, WorkspaceE
private async Task<WorkspaceEdit> ResolveCodeActionAsync(CodeAnalysis.TextDocument document, CodeAction codeAction)
{
var requestInvoker = new TestHtmlRequestInvoker();
var clientSettingsManager = new ClientSettingsManager(changeTriggers: []);
var endpoint = new CohostCodeActionsResolveEndpoint(IncompatibleProjectService, RemoteServiceInvoker, ClientCapabilitiesService, clientSettingsManager, requestInvoker);
var endpoint = new CohostCodeActionsResolveEndpoint(IncompatibleProjectService, RemoteServiceInvoker, ClientCapabilitiesService, ClientSettingsManager, requestInvoker);

var result = await endpoint.GetTestAccessor().HandleRequestAsync(document, codeAction, DisposalToken);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Threading.Tasks;
using System.IO;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.CodeAnalysis.Razor.Protocol;
using Xunit;
Expand Down Expand Up @@ -30,7 +31,7 @@ Hello World
""",
codeActionName: LanguageServerConstants.CodeActions.PromoteUsingDirective,
additionalExpectedFiles: [
(FileUri(@"..\_Imports.razor"), """
(FileUri(Path.Combine("..", "_Imports.razor")), """
@using System
""")]);
}
Expand Down Expand Up @@ -58,7 +59,7 @@ Hello World
""",
codeActionName: LanguageServerConstants.CodeActions.PromoteUsingDirective,
additionalExpectedFiles: [
(FileUri(@"..\_Imports.razor"), """
(FileUri(Path.Combine("..", "_Imports.razor")), """
@using System
""")]);
}
Expand All @@ -83,7 +84,7 @@ Hello World
codeActionName: LanguageServerConstants.CodeActions.PromoteUsingDirective,
fileKind: RazorFileKind.Legacy,
additionalExpectedFiles: [
(FileUri(@"..\_ViewImports.cshtml"), """
(FileUri(Path.Combine("..", "_ViewImports.cshtml")), """
@using System
""")]);
}
Expand All @@ -99,9 +100,9 @@ @using [||]System
Hello World
</div>
""",
documentFilePath: FilePath(@"My\Deeply\Nested\File.razor"),
documentFilePath: FilePath(Path.Combine("My", "Deeply", "Nested", "File.razor")),
additionalFiles: [
(FilePath(@"My\Deeply\_Imports.razor"), """
(FilePath(Path.Combine("My", "Deeply", "_Imports.razor")), """
@using System.Text
@using Foo.Bar
""")],
Expand All @@ -113,7 +114,7 @@ Hello World
""",
codeActionName: LanguageServerConstants.CodeActions.PromoteUsingDirective,
additionalExpectedFiles: [
(FileUri(@"My\Deeply\_Imports.razor"), """
(FileUri(Path.Combine("My", "Deeply", "_Imports.razor")), """
@using System.Text
@using Foo.Bar
@using System
Expand All @@ -131,9 +132,9 @@ @using [||]System
Hello World
</div>
""",
documentFilePath: FilePath(@"My\Deeply\Nested\File.razor"),
documentFilePath: FilePath(Path.Combine("My", "Deeply", "Nested", "File.razor")),
additionalFiles: [
(FilePath(@"My\Deeply\_Imports.razor"), """
(FilePath(Path.Combine("My", "Deeply", "_Imports.razor")), """
@using System.Text
@using Foo.Bar

Expand All @@ -146,7 +147,7 @@ Hello World
""",
codeActionName: LanguageServerConstants.CodeActions.PromoteUsingDirective,
additionalExpectedFiles: [
(FileUri(@"My\Deeply\_Imports.razor"), """
(FileUri(Path.Combine("My", "Deeply", "_Imports.razor")), """
@using System.Text
@using Foo.Bar
@using System
Expand All @@ -164,9 +165,9 @@ @using [||]System
Hello World
</div>
""",
documentFilePath: FilePath(@"My\Deeply\Nested\File.razor"),
documentFilePath: FilePath(Path.Combine("My", "Deeply", "Nested", "File.razor")),
additionalFiles: [
(FilePath(@"My\Deeply\_Imports.razor"), """
(FilePath(Path.Combine("My", "Deeply", "_Imports.razor")), """
@using System.Text
@using Foo.Bar

Expand All @@ -179,7 +180,7 @@ Hello World
""",
codeActionName: LanguageServerConstants.CodeActions.PromoteUsingDirective,
additionalExpectedFiles: [
(FileUri(@"My\Deeply\_Imports.razor"), """
(FileUri(Path.Combine("My", "Deeply", "_Imports.razor")), """
@using System.Text
@using Foo.Bar
@using System
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ public async Task AddUsingShouldBeFirst()

var document = CreateRazorDocument(input);
var codeActions = await GetCodeActionsAsync(document, input);
Assert.NotNull(codeActions);

Assert.Equal(LanguageServerConstants.CodeActions.AddUsing, codeActions.Select(a => ((RazorVSInternalCodeAction)a.Value!).Name).First());
}
Expand Down