File: UseExpressionBodyForMethodsHelper.cs
Web Access
Project: ..\..\..\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.
 
#nullable disable
 
using System.Collections.Immutable;
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 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,
                   ImmutableArray.Create(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)
        {
            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);
                return method.ReturnType is INamedTypeSymbol namedType && namedType.Arity != 0;
            }
 
            return !declaration.ReturnType.IsVoid();
        }
    }
}