| File: Microsoft.NetCore.Analyzers\Runtime\PreferJsonElementParse.Fixer.cs | Web Access |
| Project: src\sdk\src\Microsoft.CodeAnalysis.NetAnalyzers\src\Microsoft.CodeAnalysis.NetAnalyzers\Microsoft.CodeAnalysis.NetAnalyzers.csproj (Microsoft.CodeAnalysis.NetAnalyzers) |
// 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.Linq; using System.Threading.Tasks; using Analyzer.Utilities; using Analyzer.Utilities.Extensions; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Operations; namespace Microsoft.NetCore.Analyzers.Runtime { /// <summary> /// Fixer for <see cref="PreferJsonElementParse"/>. /// </summary> [ExportCodeFixProvider(LanguageNames.CSharp, LanguageNames.VisualBasic), Shared] public sealed class PreferJsonElementParseFixer : CodeFixProvider { public sealed override ImmutableArray<string> FixableDiagnosticIds { get; } = ImmutableArray.Create(PreferJsonElementParse.RuleId); public sealed override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { Document doc = context.Document; SemanticModel model = await doc.GetRequiredSemanticModelAsync(context.CancellationToken).ConfigureAwait(false); SyntaxNode root = await doc.GetRequiredSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); if (root.FindNode(context.Span, getInnermostNodeForTie: true) is not SyntaxNode node || model.GetOperation(node, context.CancellationToken) is not IPropertyReferenceOperation propertyReference || propertyReference.Property.Name != "RootElement" || propertyReference.Instance is not IInvocationOperation invocation || invocation.TargetMethod.Name != "Parse") { return; } string title = MicrosoftNetCoreAnalyzersResources.PreferJsonElementParseFix; context.RegisterCodeFix( CodeAction.Create( title, createChangedDocument: async ct => { DocumentEditor editor = await DocumentEditor.CreateAsync(doc, ct).ConfigureAwait(false); SyntaxGenerator generator = editor.Generator; // Get the JsonElement type INamedTypeSymbol? jsonElementType = model.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemTextJsonJsonElement); if (jsonElementType == null) { return doc; } // Create the replacement: JsonElement.Parse(...) // We need to use the same arguments that were passed to JsonDocument.Parse var arguments = invocation.Arguments.Select(arg => arg.Syntax).ToArray(); SyntaxNode memberAccess = generator.MemberAccessExpression( generator.TypeExpressionForStaticMemberAccess(jsonElementType), "Parse"); SyntaxNode replacement = generator.InvocationExpression(memberAccess, arguments); // Replace the entire property reference (JsonDocument.Parse(...).RootElement) with JsonElement.Parse(...) editor.ReplaceNode(propertyReference.Syntax, replacement.WithTriviaFrom(propertyReference.Syntax)); return editor.GetChangedDocument(); }, equivalenceKey: title), context.Diagnostics); } } }