diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/AddUsingsCodeActionProviderHelper.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/AddUsingsCodeActionProviderHelper.cs index 0010790ebaa..d60ea8bc994 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/AddUsingsCodeActionProviderHelper.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/AddUsingsCodeActionProviderHelper.cs @@ -48,7 +48,7 @@ public static async Task GetUsingStatementEditsAsync(RazorCodeDocume edits.AddRange(workspaceEdit.DocumentChanges!.Value.First.First().Edits); } - return edits.ToArray(); + return [.. edits]; } private static async Task> FindUsingDirectiveStringsAsync(SourceText originalCSharpText, CancellationToken cancellationToken) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/CSharpCodeActionResolver.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/CSharpCodeActionResolver.cs index 6fb3a635b2b..bb2b1c3b5d9 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/CSharpCodeActionResolver.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/CSharpCodeActionResolver.cs @@ -5,10 +5,6 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions; -internal abstract class CSharpCodeActionResolver : BaseDelegatedCodeActionResolver +internal abstract class CSharpCodeActionResolver(IClientConnection clientConnection) : BaseDelegatedCodeActionResolver(clientConnection) { - public CSharpCodeActionResolver(IClientConnection clientConnection) - : base(clientConnection) - { - } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/DefaultCSharpCodeActionResolver.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/DefaultCSharpCodeActionResolver.cs index 692c9525d0a..9e62f694a04 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/DefaultCSharpCodeActionResolver.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/DefaultCSharpCodeActionResolver.cs @@ -16,7 +16,10 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions; -internal sealed class DefaultCSharpCodeActionResolver : CSharpCodeActionResolver +internal sealed class DefaultCSharpCodeActionResolver( + IDocumentContextFactory documentContextFactory, + IClientConnection clientConnection, + IRazorFormattingService razorFormattingService) : CSharpCodeActionResolver(clientConnection) { // Usually when we need to format code, we utilize the formatting options provided // by the platform. However, we aren't provided such options in the case of code actions @@ -33,28 +36,8 @@ internal sealed class DefaultCSharpCodeActionResolver : CSharpCodeActionResolver }, }; - private readonly IDocumentContextFactory _documentContextFactory; - private readonly IRazorFormattingService _razorFormattingService; - - public DefaultCSharpCodeActionResolver( - IDocumentContextFactory documentContextFactory, - IClientConnection clientConnection, - IRazorFormattingService razorFormattingService) - : base(clientConnection) - { - if (documentContextFactory is null) - { - throw new ArgumentNullException(nameof(documentContextFactory)); - } - - if (razorFormattingService is null) - { - throw new ArgumentNullException(nameof(razorFormattingService)); - } - - _documentContextFactory = documentContextFactory; - _razorFormattingService = razorFormattingService; - } + private readonly IDocumentContextFactory _documentContextFactory = documentContextFactory; + private readonly IRazorFormattingService _razorFormattingService = razorFormattingService; public override string Action => LanguageServerConstants.CodeActions.Default; @@ -63,16 +46,6 @@ public async override Task ResolveAsync( CodeAction codeAction, CancellationToken cancellationToken) { - if (csharpParams is null) - { - throw new ArgumentNullException(nameof(csharpParams)); - } - - if (codeAction is null) - { - throw new ArgumentNullException(nameof(codeAction)); - } - if (!_documentContextFactory.TryCreateForOpenDocument(csharpParams.RazorFileIdentifier, out var documentContext)) { return codeAction; diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/TypeAccessibilityCodeActionProvider.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/TypeAccessibilityCodeActionProvider.cs index 87f76c757c1..7763a850688 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/TypeAccessibilityCodeActionProvider.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/TypeAccessibilityCodeActionProvider.cs @@ -41,22 +41,12 @@ internal sealed class TypeAccessibilityCodeActionProvider : ICSharpCodeActionPro IEnumerable codeActions, CancellationToken cancellationToken) { - if (context is null) - { - throw new ArgumentNullException(nameof(context)); - } - - if (codeActions is null) - { - throw new ArgumentNullException(nameof(codeActions)); - } - if (context.Request?.Context?.Diagnostics is null) { return SpecializedTasks.AsNullable(SpecializedTasks.EmptyReadOnlyList()); } - if (codeActions is null || !codeActions.Any()) + if (!codeActions.Any()) { return SpecializedTasks.AsNullable(SpecializedTasks.EmptyReadOnlyList()); } @@ -276,7 +266,7 @@ private static RazorVSInternalCodeAction CreateFQNCodeAction( var fqnWorkspaceEditDocumentChange = new TextDocumentEdit() { TextDocument = codeDocumentIdentifier, - Edits = new[] { fqnTextEdit }, + Edits = [fqnTextEdit], }; var fqnWorkspaceEdit = new WorkspaceEdit() diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/UnformattedRemappingCSharpCodeActionResolver.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/UnformattedRemappingCSharpCodeActionResolver.cs index a7f33f3d93c..df9aaf7fe45 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/UnformattedRemappingCSharpCodeActionResolver.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/UnformattedRemappingCSharpCodeActionResolver.cs @@ -20,20 +20,13 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions; /// /// Resolves and remaps the code action, without running formatting passes. /// -internal sealed class UnformattedRemappingCSharpCodeActionResolver : CSharpCodeActionResolver +internal sealed class UnformattedRemappingCSharpCodeActionResolver( + IDocumentContextFactory documentContextFactory, + IClientConnection clientConnection, + IRazorDocumentMappingService documentMappingService) : CSharpCodeActionResolver(clientConnection) { - private readonly IDocumentContextFactory _documentContextFactory; - private readonly IRazorDocumentMappingService _documentMappingService; - - public UnformattedRemappingCSharpCodeActionResolver( - IDocumentContextFactory documentContextFactory, - IClientConnection clientConnection, - IRazorDocumentMappingService documentMappingService) - : base(clientConnection) - { - _documentContextFactory = documentContextFactory ?? throw new ArgumentNullException(nameof(documentContextFactory)); - _documentMappingService = documentMappingService ?? throw new ArgumentNullException(nameof(documentMappingService)); - } + private readonly IDocumentContextFactory _documentContextFactory = documentContextFactory; + private readonly IRazorDocumentMappingService _documentMappingService = documentMappingService; public override string Action => LanguageServerConstants.CodeActions.UnformattedRemap; @@ -42,16 +35,6 @@ public async override Task ResolveAsync( CodeAction codeAction, CancellationToken cancellationToken) { - if (csharpParams is null) - { - throw new ArgumentNullException(nameof(csharpParams)); - } - - if (codeAction is null) - { - throw new ArgumentNullException(nameof(codeAction)); - } - cancellationToken.ThrowIfCancellationRequested(); if (!_documentContextFactory.TryCreateForOpenDocument(csharpParams.RazorFileIdentifier, out var documentContext)) @@ -112,7 +95,7 @@ public async override Task ResolveAsync( new TextDocumentEdit() { TextDocument = codeDocumentIdentifier, - Edits = new[] { textEdit }, + Edits = [textEdit], } }, }; diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionEndpoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionEndpoint.cs index fe4609a615f..1872fb25a94 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionEndpoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionEndpoint.cs @@ -58,11 +58,6 @@ internal sealed class CodeActionEndpoint( public async Task[]?> HandleRequestAsync(VSCodeActionParams request, RazorRequestContext requestContext, CancellationToken cancellationToken) { - if (request is null) - { - throw new ArgumentNullException(nameof(request)); - } - var documentContext = requestContext.DocumentContext; if (documentContext is null) { @@ -127,12 +122,12 @@ public void ApplyCapabilities(VSInternalServerCapabilities serverCapabilities, V serverCapabilities.CodeActionProvider = new CodeActionOptions { - CodeActionKinds = new[] - { + CodeActionKinds = + [ CodeActionKind.RefactorExtract, CodeActionKind.QuickFix, CodeActionKind.Refactor - }, + ], ResolveProvider = true, }; } @@ -186,13 +181,13 @@ private async Task> GetDelegatedCodeAc // No point delegating if we're in a Razor context if (languageKind == RazorLanguageKind.Razor) { - return ImmutableArray.Empty; + return []; } var codeActions = await GetCodeActionsFromLanguageServerAsync(languageKind, documentContext, context, correlationId, cancellationToken).ConfigureAwait(false); if (codeActions is not [_, ..]) { - return ImmutableArray.Empty; + return []; } IEnumerable providers; @@ -268,7 +263,7 @@ internal async Task GetCodeActionsFromLanguageServe // For C# we have to map the ranges to the generated document if (!_documentMappingService.TryMapToGeneratedDocumentRange(context.CodeDocument.GetCSharpDocument(), context.Request.Range, out var projectedRange)) { - return Array.Empty(); + return []; } var newContext = context.Request.Context; @@ -301,7 +296,7 @@ internal async Task GetCodeActionsFromLanguageServe { _telemetryReporter?.ReportFault(e, "Error getting code actions from delegate language server for {languageKind}", languageKind); _logger.LogError(e, $"Error getting code actions from delegate language server for {languageKind}"); - return Array.Empty(); + return []; } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionResolveEndpoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionResolveEndpoint.cs index 3892f546301..1744a69d2a8 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionResolveEndpoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionResolveEndpoint.cs @@ -17,55 +17,21 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions; [RazorLanguageServerEndpoint(Methods.CodeActionResolveName)] -internal sealed class CodeActionResolveEndpoint : IRazorDocumentlessRequestHandler +internal sealed class CodeActionResolveEndpoint( + IEnumerable razorCodeActionResolvers, + IEnumerable csharpCodeActionResolvers, + IEnumerable htmlCodeActionResolvers, + ILoggerFactory loggerFactory) : IRazorDocumentlessRequestHandler { - private readonly ImmutableDictionary _razorCodeActionResolvers; - private readonly ImmutableDictionary _csharpCodeActionResolvers; - private readonly ImmutableDictionary _htmlCodeActionResolvers; - private readonly ILogger _logger; + private readonly ImmutableDictionary _razorCodeActionResolvers = CreateResolverMap(razorCodeActionResolvers); + private readonly ImmutableDictionary _csharpCodeActionResolvers = CreateResolverMap(csharpCodeActionResolvers); + private readonly ImmutableDictionary _htmlCodeActionResolvers = CreateResolverMap(htmlCodeActionResolvers); + private readonly ILogger _logger = loggerFactory.GetOrCreateLogger(); public bool MutatesSolutionState => false; - public CodeActionResolveEndpoint( - IEnumerable razorCodeActionResolvers, - IEnumerable csharpCodeActionResolvers, - IEnumerable htmlCodeActionResolvers, - ILoggerFactory loggerFactory) - { - if (razorCodeActionResolvers is null) - { - throw new ArgumentNullException(nameof(razorCodeActionResolvers)); - } - - if (htmlCodeActionResolvers is null) - { - throw new ArgumentNullException(nameof(htmlCodeActionResolvers)); - } - - if (csharpCodeActionResolvers is null) - { - throw new ArgumentNullException(nameof(csharpCodeActionResolvers)); - } - - if (loggerFactory is null) - { - throw new ArgumentNullException(nameof(loggerFactory)); - } - - _logger = loggerFactory.GetOrCreateLogger(); - - _razorCodeActionResolvers = CreateResolverMap(razorCodeActionResolvers); - _csharpCodeActionResolvers = CreateResolverMap(csharpCodeActionResolvers); - _htmlCodeActionResolvers = CreateResolverMap(htmlCodeActionResolvers); - } - public async Task HandleRequestAsync(CodeAction request, RazorRequestContext requestContext, CancellationToken cancellationToken) { - if (request is null) - { - throw new ArgumentNullException(nameof(request)); - } - if (request.Data is not JsonElement paramsObj) { _logger.LogError($"Invalid CodeAction Received '{request.Title}'."); @@ -73,7 +39,6 @@ public async Task HandleRequestAsync(CodeAction request, RazorReques } var resolutionParams = paramsObj.Deserialize(); - if (resolutionParams is null) { throw new ArgumentOutOfRangeException($"request.Data should be convertible to {nameof(RazorCodeActionResolutionParams)}"); diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Html/DefaultHtmlCodeActionProvider.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Html/DefaultHtmlCodeActionProvider.cs index 4fb7ee09b92..6c441da4187 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Html/DefaultHtmlCodeActionProvider.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Html/DefaultHtmlCodeActionProvider.cs @@ -13,14 +13,9 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions; -internal sealed class DefaultHtmlCodeActionProvider : IHtmlCodeActionProvider +internal sealed class DefaultHtmlCodeActionProvider(IRazorDocumentMappingService documentMappingService) : IHtmlCodeActionProvider { - private readonly IRazorDocumentMappingService _documentMappingService; - - public DefaultHtmlCodeActionProvider(IRazorDocumentMappingService documentMappingService) - { - _documentMappingService = documentMappingService; - } + private readonly IRazorDocumentMappingService _documentMappingService = documentMappingService; public async Task?> ProvideAsync( RazorCodeActionContext context, diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Html/DefaultHtmlCodeActionResolver.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Html/DefaultHtmlCodeActionResolver.cs index 8aaaefadca0..604f02a3458 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Html/DefaultHtmlCodeActionResolver.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Html/DefaultHtmlCodeActionResolver.cs @@ -13,30 +13,13 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions; -internal sealed class DefaultHtmlCodeActionResolver : HtmlCodeActionResolver +internal sealed class DefaultHtmlCodeActionResolver( + IDocumentContextFactory documentContextFactory, + IClientConnection clientConnection, + IRazorDocumentMappingService documentMappingService) : HtmlCodeActionResolver(clientConnection) { - private readonly IDocumentContextFactory _documentContextFactory; - private readonly IRazorDocumentMappingService _documentMappingService; - - public DefaultHtmlCodeActionResolver( - IDocumentContextFactory documentContextFactory, - IClientConnection clientConnection, - IRazorDocumentMappingService documentMappingService) - : base(clientConnection) - { - if (documentContextFactory is null) - { - throw new ArgumentNullException(nameof(documentContextFactory)); - } - - if (documentMappingService is null) - { - throw new ArgumentNullException(nameof(documentMappingService)); - } - - _documentContextFactory = documentContextFactory; - _documentMappingService = documentMappingService; - } + private readonly IDocumentContextFactory _documentContextFactory = documentContextFactory; + private readonly IRazorDocumentMappingService _documentMappingService = documentMappingService; public override string Action => LanguageServerConstants.CodeActions.Default; @@ -45,16 +28,6 @@ public async override Task ResolveAsync( CodeAction codeAction, CancellationToken cancellationToken) { - if (resolveParams is null) - { - throw new ArgumentNullException(nameof(resolveParams)); - } - - if (codeAction is null) - { - throw new ArgumentNullException(nameof(codeAction)); - } - if (!_documentContextFactory.TryCreateForOpenDocument(resolveParams.RazorFileIdentifier, out var documentContext)) { return codeAction; diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Html/HtmlCodeActionResolver.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Html/HtmlCodeActionResolver.cs index bb7c517b17d..ad685ba8291 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Html/HtmlCodeActionResolver.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Html/HtmlCodeActionResolver.cs @@ -5,10 +5,6 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions; -internal abstract class HtmlCodeActionResolver : BaseDelegatedCodeActionResolver +internal abstract class HtmlCodeActionResolver(IClientConnection clientConnection) : BaseDelegatedCodeActionResolver(clientConnection) { - public HtmlCodeActionResolver(IClientConnection clientConnection) - : base(clientConnection) - { - } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/AddUsingsCodeActionParams.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/AddUsingsCodeActionParams.cs index 9c9fe60a538..4f1bf25bcae 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/AddUsingsCodeActionParams.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/AddUsingsCodeActionParams.cs @@ -11,8 +11,10 @@ internal sealed class AddUsingsCodeActionParams { [JsonPropertyName("uri")] public required Uri Uri { get; set; } + [JsonPropertyName("namespace")] public required string Namespace { get; set; } + [JsonPropertyName("additionalEdit")] public TextDocumentEdit? AdditionalEdit { get; set; } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/CodeActionExtensions.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/CodeActionExtensions.cs index 47af3510f70..8d10ca7bb71 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/CodeActionExtensions.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/CodeActionExtensions.cs @@ -50,16 +50,6 @@ public static RazorVSInternalCodeAction WrapResolvableCodeAction( string language = LanguageServerConstants.CodeActions.Languages.CSharp, bool isOnAllowList = true) { - if (razorCodeAction is null) - { - throw new ArgumentNullException(nameof(razorCodeAction)); - } - - if (context is null) - { - throw new ArgumentNullException(nameof(context)); - } - var resolveParams = new CodeActionResolveParams() { Data = razorCodeAction.Data, diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/CreateComponentCodeActionParams.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/CreateComponentCodeActionParams.cs index 13e2ea5095c..6fcd3c10a66 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/CreateComponentCodeActionParams.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/CreateComponentCodeActionParams.cs @@ -10,6 +10,7 @@ internal sealed class CreateComponentCodeActionParams { [JsonPropertyName("uri")] public required Uri Uri { get; set; } + [JsonPropertyName("path")] public required string Path { get; set; } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/GenerateMethodCodeActionParams.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/GenerateMethodCodeActionParams.cs index e5a6c0020cc..317c4568e2c 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/GenerateMethodCodeActionParams.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/GenerateMethodCodeActionParams.cs @@ -6,7 +6,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions.Models; -internal class GenerateMethodCodeActionParams +internal sealed class GenerateMethodCodeActionParams { [JsonPropertyName("uri")] public required Uri Uri { get; set; } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/RazorCodeActionResolutionParams.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/RazorCodeActionResolutionParams.cs index 5d47f9828db..149285fb64b 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/RazorCodeActionResolutionParams.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/RazorCodeActionResolutionParams.cs @@ -6,7 +6,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions.Models; -internal class RazorCodeActionResolutionParams +internal sealed class RazorCodeActionResolutionParams { [JsonPropertyName("action")] public required string Action { get; set; } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/RazorVSInternalCodeAction.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/RazorVSInternalCodeAction.cs index cbd71e5e47e..dc53eff8e46 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/RazorVSInternalCodeAction.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/RazorVSInternalCodeAction.cs @@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions.Models; [DataContract] -internal class RazorVSInternalCodeAction : VSInternalCodeAction +internal sealed class RazorVSInternalCodeAction : VSInternalCodeAction { [JsonPropertyName("name")] [DataMember(Name = "name")] diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/AddUsingsCodeActionResolver.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/AddUsingsCodeActionResolver.cs index f679b1566a5..20c49f36af1 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/AddUsingsCodeActionResolver.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/AddUsingsCodeActionResolver.cs @@ -21,14 +21,9 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions; -internal sealed class AddUsingsCodeActionResolver : IRazorCodeActionResolver +internal sealed class AddUsingsCodeActionResolver(IDocumentContextFactory documentContextFactory) : IRazorCodeActionResolver { - private readonly IDocumentContextFactory _documentContextFactory; - - public AddUsingsCodeActionResolver(IDocumentContextFactory documentContextFactory) - { - _documentContextFactory = documentContextFactory ?? throw new ArgumentNullException(nameof(documentContextFactory)); - } + private readonly IDocumentContextFactory _documentContextFactory = documentContextFactory; public string Action => LanguageServerConstants.CodeActions.AddUsing; @@ -47,12 +42,6 @@ public AddUsingsCodeActionResolver(IDocumentContextFactory documentContextFactor var documentSnapshot = documentContext.Snapshot; - var text = await documentSnapshot.GetTextAsync().ConfigureAwait(false); - if (text is null) - { - return null; - } - var codeDocument = await documentSnapshot.GetGeneratedOutputAsync().ConfigureAwait(false); if (codeDocument.IsUnsupported()) { @@ -150,7 +139,7 @@ private static TextDocumentEdit GenerateSingleUsingEditsInterpolated( return new TextDocumentEdit() { TextDocument = codeDocumentIdentifier, - Edits = edits.ToArray(), + Edits = [.. edits] }; } @@ -178,14 +167,14 @@ private static TextDocumentEdit GenerateSingleUsingEditsAtTop( return new TextDocumentEdit { TextDocument = codeDocumentIdentifier, - Edits = new[] - { + Edits = + [ new TextEdit() { NewText = string.Concat($"@using {newUsingNamespace}{Environment.NewLine}"), Range = range, } - } + ] }; } @@ -234,15 +223,5 @@ private static bool IsNamespaceOrPageDirective(SyntaxNode node) return false; } - private readonly struct RazorUsingDirective - { - readonly public RazorDirectiveSyntax Node { get; } - readonly public AddImportChunkGenerator Statement { get; } - - public RazorUsingDirective(RazorDirectiveSyntax node, AddImportChunkGenerator statement) - { - Node = node; - Statement = statement; - } - } + private readonly record struct RazorUsingDirective(RazorDirectiveSyntax Node, AddImportChunkGenerator Statement); } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/CodeBlockService.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/CodeBlockService.cs index 0cea8fd3145..7b20beeda4b 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/CodeBlockService.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/CodeBlockService.cs @@ -80,7 +80,7 @@ public static TextEdit[] CreateFormattedTextEdit(RazorCodeDocument code, string Range = eofRange }; - return new TextEdit[] { start, method, end }; + return [start, method, end]; } // A well-formed @code block exists, generate the method within it. @@ -115,7 +115,7 @@ public static TextEdit[] CreateFormattedTextEdit(RazorCodeDocument code, string NewText = formattedGeneratedMethod }; - return new TextEdit[] { edit }; + return [edit]; } private static string FormatMethodInCodeBlock( @@ -171,5 +171,6 @@ private static string FormatMethodInCodeBlock( /// /// The line to check. /// true if the line is empty, otherwise false. - private static bool IsLineEmpty(TextLine textLine) => textLine.Start == textLine.End; + private static bool IsLineEmpty(TextLine textLine) + => textLine.Start == textLine.End; } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ComponentAccessibilityCodeActionProvider.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ComponentAccessibilityCodeActionProvider.cs index 23c0c992019..880a9123192 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ComponentAccessibilityCodeActionProvider.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ComponentAccessibilityCodeActionProvider.cs @@ -85,13 +85,8 @@ private static bool IsApplicableTag(IStartTagSyntaxNode startTag) return true; } - private void AddCreateComponentFromTag(RazorCodeActionContext context, IStartTagSyntaxNode startTag, List container) + private static void AddCreateComponentFromTag(RazorCodeActionContext context, IStartTagSyntaxNode startTag, List container) { - if (context is null) - { - return; - } - if (!context.SupportsFileCreation) { return; @@ -126,7 +121,7 @@ private void AddCreateComponentFromTag(RazorCodeActionContext context, IStartTag container.Add(codeAction); } - private async Task AddComponentAccessFromTagAsync(RazorCodeActionContext context, IStartTagSyntaxNode startTag, List container, CancellationToken cancellationToken) + private static async Task AddComponentAccessFromTagAsync(RazorCodeActionContext context, IStartTagSyntaxNode startTag, List container, CancellationToken cancellationToken) { var haveAddedNonQualifiedFix = false; @@ -150,7 +145,7 @@ private async Task AddComponentAccessFromTagAsync(RazorCodeActionContext context // For all the matches, add options for add @using and fully qualify foreach (var tagHelperPair in matching) { - if (tagHelperPair._fullyQualified is null) + if (tagHelperPair.FullyQualified is null) { continue; } @@ -158,18 +153,18 @@ private async Task AddComponentAccessFromTagAsync(RazorCodeActionContext context // If they have a typo, eg and we've offered them above, then it would be odd to offer // them as well. We will offer them though, if it // exists. - if (!haveAddedNonQualifiedFix || !tagHelperPair._caseInsensitiveMatch) + if (!haveAddedNonQualifiedFix || !tagHelperPair.CaseInsensitiveMatch) { // if fqn contains a generic typeparam, we should strip it out. Otherwise, replacing tag name will leave generic parameters in razor code, which are illegal // e.g. -> /> - var fullyQualifiedName = DefaultRazorComponentSearchEngine.RemoveGenericContent(tagHelperPair._short.Name.AsMemory()).ToString(); + var fullyQualifiedName = DefaultRazorComponentSearchEngine.RemoveGenericContent(tagHelperPair.Short.Name.AsMemory()).ToString(); // If the match was case insensitive, then see if we can work out a new tag name to use as part of adding a using statement TextDocumentEdit? additionalEdit = null; string? newTagName = null; - if (tagHelperPair._caseInsensitiveMatch) + if (tagHelperPair.CaseInsensitiveMatch) { - newTagName = tagHelperPair._short.TagMatchingRules.FirstOrDefault()?.TagName; + newTagName = tagHelperPair.Short.TagMatchingRules.FirstOrDefault()?.TagName; if (newTagName is not null) { additionalEdit = CreateRenameTagEdit(context, startTag, newTagName).DocumentChanges!.Value.First().First.AssumeNotNull(); @@ -178,7 +173,7 @@ private async Task AddComponentAccessFromTagAsync(RazorCodeActionContext context // We only want to add a using statement if this was a case sensitive match, or if we were able to determine a new tag // name to give the tag. - if (!tagHelperPair._caseInsensitiveMatch || newTagName is not null) + if (!tagHelperPair.CaseInsensitiveMatch || newTagName is not null) { if (AddUsingsCodeActionProviderHelper.TryCreateAddUsingResolutionParams(fullyQualifiedName, context.Request.TextDocument.Uri, additionalEdit, out var @namespace, out var resolutionParams)) { @@ -195,7 +190,7 @@ private async Task AddComponentAccessFromTagAsync(RazorCodeActionContext context } } - private async Task> FindMatchingTagHelpersAsync(RazorCodeActionContext context, IStartTagSyntaxNode startTag, CancellationToken cancellationToken) + private static async Task> FindMatchingTagHelpersAsync(RazorCodeActionContext context, IStartTagSyntaxNode startTag, CancellationToken cancellationToken) { // Get all data necessary for matching var tagName = startTag.Name.Content; @@ -220,7 +215,7 @@ private async Task> FindMatchingTagHelpersAsync(RazorCodeAct { if (SatisfiesRules(tagHelper.TagMatchingRules, tagName.AsSpan(), parentTagName.AsSpan(), attributes, out var caseInsensitiveMatch)) { - matching.Add(tagHelper.Name, new TagHelperPair(@short: tagHelper, caseInsensitiveMatch)); + matching.Add(tagHelper.Name, new TagHelperPair(tagHelper, caseInsensitiveMatch)); } } @@ -229,9 +224,9 @@ private async Task> FindMatchingTagHelpersAsync(RazorCodeAct { if (matching.TryGetValue(tagHelper.Name, out var tagHelperPair)) { - if (tagHelperPair != null && tagHelper != tagHelperPair._short) + if (tagHelperPair != null && tagHelper != tagHelperPair.Short) { - tagHelperPair._fullyQualified = tagHelper; + tagHelperPair.FullyQualified = tagHelper; } } } @@ -239,7 +234,7 @@ private async Task> FindMatchingTagHelpersAsync(RazorCodeAct return new List(matching.Values); } - private bool SatisfiesRules(ImmutableArray tagMatchingRules, ReadOnlySpan tagNameWithoutPrefix, ReadOnlySpan parentTagNameWithoutPrefix, ImmutableArray> tagAttributes, out bool caseInsensitiveMatch) + private static bool SatisfiesRules(ImmutableArray tagMatchingRules, ReadOnlySpan tagNameWithoutPrefix, ReadOnlySpan parentTagNameWithoutPrefix, ImmutableArray> tagAttributes, out bool caseInsensitiveMatch) { caseInsensitiveMatch = false; @@ -308,7 +303,7 @@ private static WorkspaceEdit CreateRenameTagEdit(RazorCodeActionContext context, new TextDocumentEdit() { TextDocument = codeDocumentIdentifier, - Edits = textEdits.ToArray(), + Edits = [.. textEdits] } }, }; @@ -333,16 +328,8 @@ private static bool IsTagUnknown(IStartTagSyntaxNode startTag, RazorCodeActionCo return false; } - private class TagHelperPair + private sealed record class TagHelperPair(TagHelperDescriptor Short, bool CaseInsensitiveMatch) { - public readonly TagHelperDescriptor _short; - public readonly bool _caseInsensitiveMatch; - public TagHelperDescriptor? _fullyQualified = null; - - public TagHelperPair(TagHelperDescriptor @short, bool caseInsensitiveMatch) - { - _short = @short; - _caseInsensitiveMatch = caseInsensitiveMatch; - } + public TagHelperDescriptor? FullyQualified { get; set; } } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/CreateComponentCodeActionResolver.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/CreateComponentCodeActionResolver.cs index 0780869ae28..e3afbcfd3be 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/CreateComponentCodeActionResolver.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/CreateComponentCodeActionResolver.cs @@ -17,16 +17,10 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions; -internal sealed class CreateComponentCodeActionResolver : IRazorCodeActionResolver +internal sealed class CreateComponentCodeActionResolver(IDocumentContextFactory documentContextFactory, LanguageServerFeatureOptions languageServerFeatureOptions) : IRazorCodeActionResolver { - private readonly IDocumentContextFactory _documentContextFactory; - private readonly LanguageServerFeatureOptions _languageServerFeatureOptions; - - public CreateComponentCodeActionResolver(IDocumentContextFactory documentContextFactory, LanguageServerFeatureOptions languageServerFeatureOptions) - { - _documentContextFactory = documentContextFactory ?? throw new ArgumentNullException(nameof(documentContextFactory)); - _languageServerFeatureOptions = languageServerFeatureOptions ?? throw new ArgumentException(nameof(languageServerFeatureOptions)); - } + private readonly IDocumentContextFactory _documentContextFactory = documentContextFactory; + private readonly LanguageServerFeatureOptions _languageServerFeatureOptions = languageServerFeatureOptions; public string Action => LanguageServerConstants.CodeActions.CreateComponentFromTag; @@ -93,14 +87,14 @@ private static void TryAddNamespaceDirective(RazorCodeDocument codeDocument, Uri documentChanges.Add(new TextDocumentEdit { TextDocument = documentIdentifier, - Edits = new[] - { + Edits = + [ new TextEdit() { NewText = namespaceDirective.GetContent(), Range = new Range{ Start = new Position(0, 0), End = new Position(0, 0) }, } - } + ] }); } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ExtractToCodeBehindCodeActionProvider.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ExtractToCodeBehindCodeActionProvider.cs index 4b63a8d3c07..6457b46c0d6 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ExtractToCodeBehindCodeActionProvider.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ExtractToCodeBehindCodeActionProvider.cs @@ -20,27 +20,12 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions; -internal sealed class ExtractToCodeBehindCodeActionProvider : IRazorCodeActionProvider +internal sealed class ExtractToCodeBehindCodeActionProvider(ILoggerFactory loggerFactory) : IRazorCodeActionProvider { - private readonly ILogger _logger; - - public ExtractToCodeBehindCodeActionProvider(ILoggerFactory loggerFactory) - { - if (loggerFactory is null) - { - throw new ArgumentNullException(nameof(loggerFactory)); - } - - _logger = loggerFactory.GetOrCreateLogger(); - } + private readonly ILogger _logger = loggerFactory.GetOrCreateLogger(); public Task?> ProvideAsync(RazorCodeActionContext context, CancellationToken cancellationToken) { - if (context is null) - { - return SpecializedTasks.Null>(); - } - if (!context.SupportsFileCreation) { return SpecializedTasks.Null>(); @@ -64,7 +49,7 @@ public ExtractToCodeBehindCodeActionProvider(ILoggerFactory loggerFactory) return SpecializedTasks.Null>(); } - var directiveNode = owner?.Parent switch + var directiveNode = owner.Parent switch { // When the caret is '@code$$ {' or '@code$${' then tree is: // RazorDirective -> RazorDirectiveBody -> CSharpCodeBlock -> (MetaCode or TextLiteral) @@ -145,10 +130,5 @@ private static bool TryGetNamespace(RazorCodeDocument codeDocument, [NotNullWhen => codeDocument.TryComputeNamespace(fallbackToRootNamespace: true, out @namespace); private static bool HasUnsupportedChildren(Language.Syntax.SyntaxNode node) - { - return node.DescendantNodes().Any(n => - n is MarkupBlockSyntax || - n is CSharpTransitionSyntax || - n is RazorCommentBlockSyntax); - } + => node.DescendantNodes().Any(n => n is MarkupBlockSyntax or CSharpTransitionSyntax or RazorCommentBlockSyntax); } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ExtractToCodeBehindCodeActionResolver.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ExtractToCodeBehindCodeActionResolver.cs index ae27499675c..4fc7b9fd4eb 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ExtractToCodeBehindCodeActionResolver.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ExtractToCodeBehindCodeActionResolver.cs @@ -25,23 +25,16 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions; -internal sealed class ExtractToCodeBehindCodeActionResolver : IRazorCodeActionResolver +internal sealed class ExtractToCodeBehindCodeActionResolver( + IDocumentContextFactory documentContextFactory, + LanguageServerFeatureOptions languageServerFeatureOptions, + IClientConnection clientConnection) : IRazorCodeActionResolver { private static readonly Workspace s_workspace = new AdhocWorkspace(); - private readonly IDocumentContextFactory _documentContextFactory; - private readonly LanguageServerFeatureOptions _languageServerFeatureOptions; - private readonly IClientConnection _clientConnection; - - public ExtractToCodeBehindCodeActionResolver( - IDocumentContextFactory documentContextFactory, - LanguageServerFeatureOptions languageServerFeatureOptions, - IClientConnection clientConnection) - { - _documentContextFactory = documentContextFactory ?? throw new ArgumentNullException(nameof(documentContextFactory)); - _languageServerFeatureOptions = languageServerFeatureOptions ?? throw new ArgumentNullException(nameof(languageServerFeatureOptions)); - _clientConnection = clientConnection ?? throw new ArgumentNullException(nameof(clientConnection)); - } + private readonly IDocumentContextFactory _documentContextFactory = documentContextFactory; + private readonly LanguageServerFeatureOptions _languageServerFeatureOptions = languageServerFeatureOptions; + private readonly IClientConnection _clientConnection = clientConnection; public string Action => LanguageServerConstants.CodeActions.ExtractToCodeBehindAction; @@ -86,10 +79,6 @@ public ExtractToCodeBehindCodeActionResolver( }.Uri; var text = await documentContext.GetSourceTextAsync(cancellationToken).ConfigureAwait(false); - if (text is null) - { - return null; - } var className = Path.GetFileNameWithoutExtension(path); var codeBlockContent = text.GetSubTextString(new CodeAnalysis.Text.TextSpan(actionParams.ExtractStart, actionParams.ExtractEnd - actionParams.ExtractStart)).Trim(); @@ -112,26 +101,30 @@ public ExtractToCodeBehindCodeActionResolver( new TextDocumentEdit { TextDocument = codeDocumentIdentifier, - Edits = new[] - { + Edits = + [ new TextEdit { NewText = string.Empty, Range = removeRange, } - }, + ], }, new TextDocumentEdit { TextDocument = codeBehindDocumentIdentifier, - Edits = new[] - { + Edits = + [ new TextEdit { NewText = codeBehindContent, - Range = new Range { Start = new Position(0, 0), End = new Position(0, 0) }, + Range = new Range + { + Start = new Position(0, 0), + End = new Position(0, 0) + }, } - }, + ], } }; @@ -150,17 +143,17 @@ public ExtractToCodeBehindCodeActionResolver( /// A non-existent file path with the same base name and a codebehind extension. private static string GenerateCodeBehindPath(string path) { + var baseFileName = Path.GetFileNameWithoutExtension(path); + var extension = Path.GetExtension(path); + var directoryName = Path.GetDirectoryName(path).AssumeNotNull(); + var n = 0; string codeBehindPath; do { var identifier = n > 0 ? n.ToString(CultureInfo.InvariantCulture) : string.Empty; // Make it look nice - var directoryName = Path.GetDirectoryName(path); - Assumes.NotNull(directoryName); - codeBehindPath = Path.Combine( - directoryName, - $"{Path.GetFileNameWithoutExtension(path)}{identifier}{Path.GetExtension(path)}.cs"); + codeBehindPath = Path.Combine(directoryName, $"{baseFileName}{identifier}{extension}.cs"); n++; } while (File.Exists(codeBehindPath)); @@ -168,13 +161,14 @@ private static string GenerateCodeBehindPath(string path) return codeBehindPath; } - private async Task GenerateCodeBehindClassAsync(CodeAnalysis.Razor.ProjectSystem.IProjectSnapshot project, Uri codeBehindUri, string className, string namespaceName, string contents, RazorCodeDocument razorCodeDocument, CancellationToken cancellationToken) + private async Task GenerateCodeBehindClassAsync(IProjectSnapshot project, Uri codeBehindUri, string className, string namespaceName, string contents, RazorCodeDocument razorCodeDocument, CancellationToken cancellationToken) { using var _ = StringBuilderPool.GetPooledObject(out var builder); var usingDirectives = razorCodeDocument .GetDocumentIntermediateNode() .FindDescendantNodes(); + foreach (var usingDirective in usingDirectives) { builder.Append("using "); @@ -219,8 +213,8 @@ private async Task GenerateCodeBehindClassAsync(CodeAnalysis.Razor.Proje { // Sadly we can't use a "real" workspace here, because we don't have access. If we use our workspace, it wouldn't have the right settings // for C# formatting, only Razor formatting, and we have no access to Roslyn's real workspace, since it could be in another process. - var node = await CSharpSyntaxTree.ParseText(newFileContent).GetRootAsync(cancellationToken).ConfigureAwait(false); - node = Formatter.Format(node, s_workspace); + var node = await CSharpSyntaxTree.ParseText(newFileContent, cancellationToken: cancellationToken).GetRootAsync(cancellationToken).ConfigureAwait(false); + node = Formatter.Format(node, s_workspace, cancellationToken: cancellationToken); return node.ToFullString(); } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/GenerateMethodCodeActionProvider.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/GenerateMethodCodeActionProvider.cs index e89a7a35b0d..3399a4815de 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/GenerateMethodCodeActionProvider.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/GenerateMethodCodeActionProvider.cs @@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions.Razor; -internal class GenerateMethodCodeActionProvider : IRazorCodeActionProvider +internal sealed class GenerateMethodCodeActionProvider : IRazorCodeActionProvider { public Task?> ProvideAsync(RazorCodeActionContext context, CancellationToken cancellationToken) { @@ -29,18 +29,14 @@ internal class GenerateMethodCodeActionProvider : IRazorCodeActionProvider } var syntaxTree = context.CodeDocument.GetSyntaxTree(); - var owner = syntaxTree.Root.FindToken(context.Location.AbsoluteIndex).Parent; - Assumes.NotNull(owner); + var owner = syntaxTree.Root.FindToken(context.Location.AbsoluteIndex).Parent.AssumeNotNull(); if (IsGenerateEventHandlerValid(owner, out var methodName, out var eventName)) { var uri = context.Request.TextDocument.Uri; - var codeActions = new List() - { + return Task.FromResult?>([ RazorCodeActionFactory.CreateGenerateMethod(uri, methodName, eventName), - RazorCodeActionFactory.CreateAsyncGenerateMethod(uri, methodName, eventName) - }; - return Task.FromResult?>(codeActions); + RazorCodeActionFactory.CreateAsyncGenerateMethod(uri, methodName, eventName)]); } return SpecializedTasks.Null>(); diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/GenerateMethodCodeActionResolver.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/GenerateMethodCodeActionResolver.cs index 6cf869bf21b..ea478048fed 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/GenerateMethodCodeActionResolver.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/GenerateMethodCodeActionResolver.cs @@ -25,40 +25,31 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions.Razor; -internal class GenerateMethodCodeActionResolver : IRazorCodeActionResolver +internal sealed class GenerateMethodCodeActionResolver( + IDocumentContextFactory documentContextFactory, + RazorLSPOptionsMonitor razorLSPOptionsMonitor, + IClientConnection clientConnection, + IRazorDocumentMappingService razorDocumentMappingService, + IRazorFormattingService razorFormattingService) : IRazorCodeActionResolver { - private readonly IDocumentContextFactory _documentContextFactory; - private readonly RazorLSPOptionsMonitor _razorLSPOptionsMonitor; - private readonly IClientConnection _clientConnection; - private readonly IRazorDocumentMappingService _documentMappingService; - private readonly IRazorFormattingService _razorFormattingService; - - private static readonly string s_beginningIndents = $"{FormattingUtilities.InitialIndent}{FormattingUtilities.Indent}"; - private static readonly string s_returnType = "$$ReturnType$$"; - private static readonly string s_methodName = "$$MethodName$$"; - private static readonly string s_eventArgs = "$$EventArgs$$"; + private readonly IDocumentContextFactory _documentContextFactory = documentContextFactory; + private readonly RazorLSPOptionsMonitor _razorLSPOptionsMonitor = razorLSPOptionsMonitor; + private readonly IClientConnection _clientConnection = clientConnection; + private readonly IRazorDocumentMappingService _documentMappingService = razorDocumentMappingService; + private readonly IRazorFormattingService _razorFormattingService = razorFormattingService; + + private const string ReturnType = "$$ReturnType$$"; + private const string MethodName = "$$MethodName$$"; + private const string EventArgs = "$$EventArgs$$"; + private const string BeginningIndents = $"{FormattingUtilities.InitialIndent}{FormattingUtilities.Indent}"; private static readonly string s_generateMethodTemplate = - $"{s_beginningIndents}private {s_returnType} {s_methodName}({s_eventArgs}){Environment.NewLine}" + - s_beginningIndents + "{" + Environment.NewLine + - $"{s_beginningIndents}{FormattingUtilities.Indent}throw new global::System.NotImplementedException();{Environment.NewLine}" + - s_beginningIndents + "}"; + $"{BeginningIndents}private {ReturnType} {MethodName}({EventArgs}){Environment.NewLine}" + + BeginningIndents + "{" + Environment.NewLine + + $"{BeginningIndents}{FormattingUtilities.Indent}throw new global::System.NotImplementedException();{Environment.NewLine}" + + BeginningIndents + "}"; public string Action => LanguageServerConstants.CodeActions.GenerateEventHandler; - public GenerateMethodCodeActionResolver( - IDocumentContextFactory documentContextFactory, - RazorLSPOptionsMonitor razorLSPOptionsMonitor, - IClientConnection clientConnection, - IRazorDocumentMappingService razorDocumentMappingService, - IRazorFormattingService razorFormattingService) - { - _documentContextFactory = documentContextFactory; - _razorLSPOptionsMonitor = razorLSPOptionsMonitor; - _clientConnection = clientConnection; - _documentMappingService = razorDocumentMappingService; - _razorFormattingService = razorFormattingService; - } - public async Task ResolveAsync(JsonElement data, CancellationToken cancellationToken) { var actionParams = data.Deserialize(); @@ -77,9 +68,9 @@ public GenerateMethodCodeActionResolver( var razorClassName = Path.GetFileNameWithoutExtension(uriPath); var codeBehindPath = $"{uriPath}.cs"; - if (!File.Exists(codeBehindPath) - || razorClassName is null - || !code.TryComputeNamespace(fallbackToRootNamespace: true, out var razorNamespace)) + if (!File.Exists(codeBehindPath) || + razorClassName is null || + !code.TryComputeNamespace(fallbackToRootNamespace: true, out var razorNamespace)) { return await GenerateMethodInCodeBlockAsync( code, @@ -136,13 +127,12 @@ public GenerateMethodCodeActionResolver( var result = await _clientConnection.SendRequestAsync( CustomMessageNames.RazorSimplifyMethodEndpointName, delegatedParams, - cancellationToken).ConfigureAwait(false) - ?? new TextEdit[] { edit }; + cancellationToken).ConfigureAwait(false); var codeBehindTextDocEdit = new TextDocumentEdit() { TextDocument = codeBehindTextDocumentIdentifier, - Edits = result + Edits = result ?? [edit] }; return new WorkspaceEdit() { DocumentChanges = new[] { codeBehindTextDocEdit } }; @@ -231,7 +221,7 @@ private async Task GenerateMethodInCodeBlockAsync( RazorLanguageKind.CSharp, result, formattingOptions, - CancellationToken.None).ConfigureAwait(false); + cancellationToken).ConfigureAwait(false); edits = formattedEdits; } @@ -248,10 +238,10 @@ private async Task GenerateMethodInCodeBlockAsync( private static async Task PopulateMethodSignatureAsync(VersionedDocumentContext documentContext, GenerateMethodCodeActionParams actionParams, CancellationToken cancellationToken) { - var templateWithMethodSignature = s_generateMethodTemplate.Replace(s_methodName, actionParams.MethodName); + var templateWithMethodSignature = s_generateMethodTemplate.Replace(MethodName, actionParams.MethodName); var returnType = actionParams.IsAsync ? "global::System.Threading.Tasks.Task" : "void"; - templateWithMethodSignature = templateWithMethodSignature.Replace(s_returnType, returnType); + templateWithMethodSignature = templateWithMethodSignature.Replace(ReturnType, returnType); var tagHelpers = await documentContext.Project.GetTagHelpersAsync(cancellationToken).ConfigureAwait(false); var eventTagHelper = tagHelpers @@ -260,7 +250,7 @@ private static async Task PopulateMethodSignatureAsync(VersionedDocument ? string.Empty // Couldn't find the params, generate no params instead. : $"global::{eventTagHelper.GetEventArgsType()} e"; - return templateWithMethodSignature.Replace(s_eventArgs, eventArgsType); + return templateWithMethodSignature.Replace(EventArgs, eventArgsType); } private static ClassDeclarationSyntax? GetCSharpClassDeclarationSyntax(string csharpContent, string razorNamespace, string razorClassName) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/RazorCodeActionContext.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/RazorCodeActionContext.cs index 56bbf48e407..0fc4c9e384f 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/RazorCodeActionContext.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/RazorCodeActionContext.cs @@ -9,31 +9,11 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions; -internal sealed class RazorCodeActionContext -{ - public RazorCodeActionContext( - VSCodeActionParams request, - IDocumentSnapshot documentSnapshot, - RazorCodeDocument codeDocument, - SourceLocation location, - SourceText sourceText, - bool supportsFileCreation, - bool supportsCodeActionResolve) - { - Request = request ?? throw new ArgumentNullException(nameof(request)); - DocumentSnapshot = documentSnapshot ?? throw new ArgumentNullException(nameof(documentSnapshot)); - CodeDocument = codeDocument ?? throw new ArgumentNullException(nameof(codeDocument)); - Location = location; - SourceText = sourceText ?? throw new ArgumentNullException(nameof(sourceText)); - SupportsFileCreation = supportsFileCreation; - SupportsCodeActionResolve = supportsCodeActionResolve; - } - - public VSCodeActionParams Request { get; } - public IDocumentSnapshot DocumentSnapshot { get; } - public RazorCodeDocument CodeDocument { get; } - public SourceLocation Location { get; } - public SourceText SourceText { get; } - public bool SupportsFileCreation { get; } - public bool SupportsCodeActionResolve { get; } -} +internal sealed record class RazorCodeActionContext( + VSCodeActionParams Request, + IDocumentSnapshot DocumentSnapshot, + RazorCodeDocument CodeDocument, + SourceLocation Location, + SourceText SourceText, + bool SupportsFileCreation, + bool SupportsCodeActionResolve); diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/FormattingUtilities.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/FormattingUtilities.cs index 97895c105f3..9cd27d17513 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/FormattingUtilities.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/FormattingUtilities.cs @@ -8,8 +8,8 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Formatting; internal static class FormattingUtilities { - public static readonly string Indent = "$$Indent$$"; - public static readonly string InitialIndent = "$$InitialIndent$$"; + public const string Indent = "$$Indent$$"; + public const string InitialIndent = "$$InitialIndent$$"; /// /// Adds indenting to the method. diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CSharp/TypeAccessibilityCodeActionProviderTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CSharp/TypeAccessibilityCodeActionProviderTest.cs index 292c08cd818..faebcb9c5c5 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CSharp/TypeAccessibilityCodeActionProviderTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CSharp/TypeAccessibilityCodeActionProviderTest.cs @@ -479,7 +479,7 @@ private static RazorCodeActionContext CreateRazorCodeActionContext( var sourceText = SourceText.From(text); - var context = new RazorCodeActionContext(request, documentSnapshot, codeDocument, location, sourceText, supportsFileCreation, supportsCodeActionResolve: supportsCodeActionResolve); + var context = new RazorCodeActionContext(request, documentSnapshot, codeDocument, location, sourceText, supportsFileCreation, supportsCodeActionResolve); return context; } diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ComponentAccessibilityCodeActionProviderTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ComponentAccessibilityCodeActionProviderTest.cs index 14b5da0614e..d8be67e5eb2 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ComponentAccessibilityCodeActionProviderTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ComponentAccessibilityCodeActionProviderTest.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System; -using System.Collections.Generic; using System.Collections.Immutable; using System.Threading; using System.Threading.Tasks; @@ -480,7 +479,7 @@ private static RazorCodeActionContext CreateRazorCodeActionContext(VSCodeActionP var sourceText = SourceText.From(text); - var context = new RazorCodeActionContext(request, documentSnapshot, codeDocument, location, sourceText, supportsFileCreation, supportsCodeActionResolve: true); + var context = new RazorCodeActionContext(request, documentSnapshot, codeDocument, location, sourceText, supportsFileCreation, SupportsCodeActionResolve: true); return context; } diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ExtractToCodeBehindCodeActionProviderTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ExtractToCodeBehindCodeActionProviderTest.cs index 524fb6746f2..4b5b94fd9cb 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ExtractToCodeBehindCodeActionProviderTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ExtractToCodeBehindCodeActionProviderTest.cs @@ -405,7 +405,7 @@ private static RazorCodeActionContext CreateRazorCodeActionContext(VSCodeActionP var sourceText = SourceText.From(text); - var context = new RazorCodeActionContext(request, documentSnapshot, codeDocument, location, sourceText, supportsFileCreation, supportsCodeActionResolve: true); + var context = new RazorCodeActionContext(request, documentSnapshot, codeDocument, location, sourceText, supportsFileCreation, SupportsCodeActionResolve: true); return context; }