| File: StateHasChangedCodeFixProvider.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.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp.Syntax; namespace Microsoft.AspNetCore.Components.Analyzers; [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(StateHasChangedCodeFixProvider)), Shared] public class StateHasChangedCodeFixProvider : CodeFixProvider { private static readonly LocalizableString Title = new LocalizableResourceString(nameof(Resources.UnnecessaryStateHasChangedCall_FixTitle), Resources.ResourceManager, typeof(Resources)); public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(DiagnosticDescriptors.UnnecessaryStateHasChangedCall.Id); public sealed override FixAllProvider GetFixAllProvider() { return WellKnownFixAllProviders.BatchFixer; } public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); if (root is null) { return; } var diagnostic = context.Diagnostics.First(); var diagnosticSpan = diagnostic.Location.SourceSpan; var invocation = root.FindToken(diagnosticSpan.Start) .Parent? .AncestorsAndSelf() .OfType<InvocationExpressionSyntax>() .FirstOrDefault(); if (invocation is null) { return; } var title = Title.ToString(CultureInfo.CurrentCulture); context.RegisterCodeFix( CodeAction.Create( title: title, createChangedDocument: cancellationToken => RemoveStateHasChangedCallAsync(context.Document, root, invocation, cancellationToken), equivalenceKey: title), diagnostic); } private static Task<Document> RemoveStateHasChangedCallAsync(Document document, SyntaxNode root, InvocationExpressionSyntax invocation, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); SyntaxNode nodeToRemove; if (invocation.Parent is ExpressionStatementSyntax expressionStatement) { nodeToRemove = expressionStatement; } else if (invocation.Parent is ArrowExpressionClauseSyntax { Parent: MethodDeclarationSyntax containingMethod }) { nodeToRemove = containingMethod; } else { nodeToRemove = invocation; } var newRoot = root.RemoveNode(nodeToRemove, SyntaxRemoveOptions.KeepExteriorTrivia); return Task.FromResult(newRoot is null ? document : document.WithSyntaxRoot(newRoot)); } }