File: src\Analyzers\CSharp\Analyzers\UseExpressionBody\Helpers\UseExpressionBodyForMethodsHelper.cs
Web Access
Project: src\src\CodeStyle\CSharp\Analyzers\Microsoft.CodeAnalysis.CSharp.CodeStyle.csproj (Microsoft.CodeAnalysis.CSharp.CodeStyle)
// 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.Threading;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeGeneration;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
 
namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody;
 
internal sealed class UseExpressionBodyForMethodsHelper :
    UseExpressionBodyHelper<MethodDeclarationSyntax>
{
    public static readonly UseExpressionBodyForMethodsHelper Instance = new();
 
    private UseExpressionBodyForMethodsHelper()
        : base(IDEDiagnosticIds.UseExpressionBodyForMethodsDiagnosticId,
               EnforceOnBuildValues.UseExpressionBodyForMethods,
               new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_expression_body_for_method), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)),
               new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_block_body_for_method), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)),
               CSharpCodeStyleOptions.PreferExpressionBodiedMethods,
               [SyntaxKind.MethodDeclaration])
    {
    }
 
    public override CodeStyleOption2<ExpressionBodyPreference> GetExpressionBodyPreference(CSharpCodeGenerationOptions options)
        => options.PreferExpressionBodiedMethods;
 
    protected override BlockSyntax? GetBody(MethodDeclarationSyntax declaration)
        => declaration.Body;
 
    protected override ArrowExpressionClauseSyntax? GetExpressionBody(MethodDeclarationSyntax declaration)
        => declaration.ExpressionBody;
 
    protected override SyntaxToken GetSemicolonToken(MethodDeclarationSyntax declaration)
        => declaration.SemicolonToken;
 
    protected override MethodDeclarationSyntax WithSemicolonToken(MethodDeclarationSyntax declaration, SyntaxToken token)
        => declaration.WithSemicolonToken(token);
 
    protected override MethodDeclarationSyntax WithExpressionBody(MethodDeclarationSyntax declaration, ArrowExpressionClauseSyntax? expressionBody)
        => declaration.WithExpressionBody(expressionBody);
 
    protected override MethodDeclarationSyntax WithBody(MethodDeclarationSyntax declaration, BlockSyntax? body)
        => declaration.WithBody(body);
 
    protected override bool CreateReturnStatementForExpression(
        SemanticModel semanticModel, MethodDeclarationSyntax declaration, CancellationToken cancellationToken)
    {
        if (declaration.Modifiers.Any(SyntaxKind.AsyncKeyword))
        {
            // if it's 'async TaskLike' (where TaskLike is non-generic) we do *not* want to
            // create a return statement.  This is just the 'async' version of a 'void' method.
            var method = semanticModel.GetDeclaredSymbol(declaration, cancellationToken);
            return method is { ReturnType: INamedTypeSymbol { Arity: not 0 } };
        }
 
        return !declaration.ReturnType.IsVoid();
    }
}