File: src\Analyzers\CSharp\CodeFixes\AssignOutParameters\AssignOutParametersAboveReturnCodeFixProvider.cs
Web Access
Project: src\src\Features\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.Features.csproj (Microsoft.CodeAnalysis.CSharp.Features)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System;
using System.Collections.Immutable;
using System.Composition;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities;
 
namespace Microsoft.CodeAnalysis.CSharp.AssignOutParameters;
 
[ExportCodeFixProvider(LanguageNames.CSharp, Name = PredefinedCodeFixProviderNames.AssignOutParametersAboveReturn), Shared]
[method: ImportingConstructor]
[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
internal sealed class AssignOutParametersAboveReturnCodeFixProvider() : AbstractAssignOutParametersCodeFixProvider
{
    protected override void TryRegisterFix(CodeFixContext context, Document document, SyntaxNode container, SyntaxNode location)
    {
        RegisterCodeFix(context, CSharpCodeFixesResources.Assign_out_parameters, nameof(CSharpCodeFixesResources.Assign_out_parameters));
    }
 
    protected override void AssignOutParameters(
        SyntaxEditor editor, SyntaxNode container,
        MultiDictionary<SyntaxNode, (SyntaxNode exprOrStatement, ImmutableArray<IParameterSymbol> unassignedParameters)>.ValueSet values,
        CancellationToken cancellationToken)
    {
        foreach (var (exprOrStatement, unassignedParameters) in values)
        {
            var statements = GenerateAssignmentStatements(editor.Generator, unassignedParameters);
            AddAssignmentStatements(editor, exprOrStatement, statements);
        }
    }
 
    private static void AddAssignmentStatements(
        SyntaxEditor editor, SyntaxNode exprOrStatement, ImmutableArray<SyntaxNode> statements)
    {
        var generator = editor.Generator;
 
        if (exprOrStatement is LocalFunctionStatementSyntax { ExpressionBody: { } localFunctionExpressionBody })
        {
            // Expression-bodied local functions report CS0177 on the method name instead of the expression.
            // Reassign exprOrStatement so the code fix implementation works as it does for other expression-bodied
            // members.
            exprOrStatement = localFunctionExpressionBody.Expression;
        }
 
        var parent = exprOrStatement.GetRequiredParent();
        if (parent.IsEmbeddedStatementOwner())
        {
            var newBody = SyntaxFactory.Block(statements.Add(exprOrStatement).Cast<StatementSyntax>());
            editor.ReplaceNode(exprOrStatement, newBody);
            editor.ReplaceNode(
                exprOrStatement.GetRequiredParent(),
                (c, _) => c.WithAdditionalAnnotations(Formatter.Annotation));
        }
        else if (parent is BlockSyntax or SwitchSectionSyntax)
        {
            editor.InsertBefore(exprOrStatement, statements);
        }
        else if (parent is ArrowExpressionClauseSyntax)
        {
            statements = statements.Add(generator.ReturnStatement(exprOrStatement));
            editor.ReplaceNode(
                parent.GetRequiredParent(),
                generator.WithStatements(parent.GetRequiredParent(), statements));
        }
        else
        {
            var lambda = (LambdaExpressionSyntax)parent;
            var newBody = SyntaxFactory.Block(statements.Add(generator.ReturnStatement(exprOrStatement)).Cast<StatementSyntax>());
            editor.ReplaceNode(
                lambda,
                lambda.WithBody(newBody)
                      .WithAdditionalAnnotations(Formatter.Annotation));
        }
    }
}