| File: JSInvokableCodeFixProvider.cs | Web Access |
| Project: src\aspnetcore\src\Components\Analyzers\src\Microsoft.AspNetCore.Components.Analyzers.csproj (Microsoft.AspNetCore.Components.Analyzers) |
// 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.Globalization; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; namespace Microsoft.AspNetCore.Components.Analyzers; [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(JSInvokableCodeFixProvider)), Shared] public class JSInvokableCodeFixProvider : CodeFixProvider { private static readonly LocalizableString _title = new LocalizableResourceString(nameof(Resources.JSInvokableMethodShouldBePublic_FixTitle), Resources.ResourceManager, typeof(Resources)); public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(DiagnosticDescriptors.JSInvokableMethodShouldBePublic.Id); public sealed override FixAllProvider GetFixAllProvider() { // See https://github.com/dotnet/roslyn/blob/master/docs/analyzers/FixAllProvider.md for more information on Fix All Providers return WellKnownFixAllProviders.BatchFixer; } public sealed override Task RegisterCodeFixesAsync(CodeFixContext context) { var title = _title.ToString(CultureInfo.InvariantCulture); foreach (var diagnostic in context.Diagnostics) { context.RegisterCodeFix( CodeAction.Create( title: title, createChangedDocument: ct => GetTransformedDocumentAsync(diagnostic, context.Document, ct), equivalenceKey: title), diagnostic); } return Task.CompletedTask; } private static async Task<Document> GetTransformedDocumentAsync( Diagnostic diagnostic, Document document, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); if (root is null) { return document; } var declarationNode = root.FindNode(diagnostic.Location.SourceSpan).FirstAncestorOrSelf<MethodDeclarationSyntax>(); if (declarationNode is null) { return document; } var updatedDeclarationNode = HandleMethodDeclaration(declarationNode); var newSyntaxRoot = root.ReplaceNode(declarationNode, updatedDeclarationNode); return document.WithSyntaxRoot(newSyntaxRoot); } private static SyntaxNode HandleMethodDeclaration(MethodDeclarationSyntax node) { var newModifiers = SyntaxFactory.TokenList( SyntaxFactory.Token(SyntaxKind.PublicKeyword) ); foreach (var modifier in node.Modifiers) { // Skip all existing access modifiers, including 'public' just in case the fix is ran on invalid code with multiple access modifiers (e.g. private public) if (modifier.IsKind(SyntaxKind.PrivateKeyword) || modifier.IsKind(SyntaxKind.ProtectedKeyword) || modifier.IsKind(SyntaxKind.InternalKeyword) || modifier.IsKind(SyntaxKind.PublicKeyword)) { continue; } newModifiers = newModifiers.Add(modifier); } node = node.WithModifiers(newModifiers); return node; } }