diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpCodeGenerationService.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpCodeGenerationService.cs index 64b0a8de06fc794a7337502293aa8c64b0b29503..10a4fdd67dbdf3090646d8a2a0a4e9e442f30be2 100644 --- a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpCodeGenerationService.cs +++ b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpCodeGenerationService.cs @@ -154,12 +154,14 @@ protected override TDeclarationNode AddMethod(TDeclarationNode if (method.MethodKind == MethodKind.Conversion) { - return Cast(ConversionGenerator.AddConversionTo(typeDeclaration, method, options, availableIndices)); + return Cast(ConversionGenerator.AddConversionTo( + typeDeclaration, method, Workspace, options, availableIndices)); } if (method.MethodKind == MethodKind.UserDefinedOperator) { - return Cast(OperatorGenerator.AddOperatorTo(typeDeclaration, method, options, availableIndices)); + return Cast(OperatorGenerator.AddOperatorTo( + typeDeclaration, method, Workspace, options, availableIndices)); } return Cast(MethodGenerator.AddMethodTo( @@ -626,11 +628,11 @@ public override SyntaxNode CreateFieldDeclaration(IFieldSymbol field, CodeGenera } else if (method.IsUserDefinedOperator()) { - return OperatorGenerator.GenerateOperatorDeclaration(method, destination, options); + return OperatorGenerator.GenerateOperatorDeclaration(method, destination, Workspace, options); } else if (method.IsConversion()) { - return ConversionGenerator.GenerateConversionDeclaration(method, destination, options); + return ConversionGenerator.GenerateConversionDeclaration(method, destination, Workspace, options); } else { diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/ConversionGenerator.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/ConversionGenerator.cs index ed95c47e3de5e20b0aadfce8c376bffa47542df8..a662ebe3ce2dd198f6f7540e7b469a00e5bb40d9 100644 --- a/src/Workspaces/CSharp/Portable/CodeGeneration/ConversionGenerator.cs +++ b/src/Workspaces/CSharp/Portable/CodeGeneration/ConversionGenerator.cs @@ -1,7 +1,9 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using Microsoft.CodeAnalysis.CodeGeneration; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -15,10 +17,12 @@ internal static class ConversionGenerator internal static TypeDeclarationSyntax AddConversionTo( TypeDeclarationSyntax destination, IMethodSymbol method, + Workspace workspace, CodeGenerationOptions options, IList availableIndices) { - var methodDeclaration = GenerateConversionDeclaration(method, GetDestination(destination), options); + var methodDeclaration = GenerateConversionDeclaration( + method, GetDestination(destination), workspace, options); var members = Insert(destination.Members, methodDeclaration, options, availableIndices, after: LastOperator); @@ -28,9 +32,10 @@ internal static class ConversionGenerator internal static ConversionOperatorDeclarationSyntax GenerateConversionDeclaration( IMethodSymbol method, CodeGenerationDestination destination, + Workspace workspace, CodeGenerationOptions options) { - var declaration = GenerateConversionDeclarationWorker(method, destination, options); + var declaration = GenerateConversionDeclarationWorker(method, destination, workspace, options); return AddCleanupAnnotationsTo(AddAnnotationsTo(method, ConditionallyAddDocumentationCommentTo(declaration, method, options))); } @@ -38,6 +43,7 @@ internal static class ConversionGenerator private static ConversionOperatorDeclarationSyntax GenerateConversionDeclarationWorker( IMethodSymbol method, CodeGenerationDestination destination, + Workspace workspace, CodeGenerationOptions options) { var hasNoBody = !options.GenerateMethodBodies || method.IsExtern; @@ -53,7 +59,7 @@ internal static class ConversionGenerator ? SyntaxFactory.Token(SyntaxKind.ImplicitKeyword) : SyntaxFactory.Token(SyntaxKind.ExplicitKeyword); - return SyntaxFactory.ConversionOperatorDeclaration( + var declaration = SyntaxFactory.ConversionOperatorDeclaration( attributeLists: AttributeGenerator.GenerateAttributeLists(method.GetAttributes(), options), modifiers: GenerateModifiers(method), implicitOrExplicitKeyword: keyword, @@ -62,6 +68,31 @@ internal static class ConversionGenerator parameterList: ParameterGenerator.GenerateParameterList(method.Parameters, isExplicit: false, options: options), body: hasNoBody ? null : StatementGenerator.GenerateBlock(method), semicolonToken: hasNoBody ? SyntaxFactory.Token(SyntaxKind.SemicolonToken) : new SyntaxToken()); + + declaration = UseExpressionBodyIfDesired(workspace, declaration); + + return declaration; + } + + private static ConversionOperatorDeclarationSyntax UseExpressionBodyIfDesired( + Workspace workspace, ConversionOperatorDeclarationSyntax declaration) + { + if (declaration.ExpressionBody == null) + { + var preferExpressionBody = workspace.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedMethods).Value; + if (preferExpressionBody) + { + var expressionBody = CodeGenerationHelpers.TryConvertToExpressionBody(declaration.Body); + if (expressionBody != null) + { + return declaration.WithBody(null) + .WithExpressionBody(expressionBody) + .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)); + } + } + } + + return declaration; } private static SyntaxTokenList GenerateModifiers(IMethodSymbol method) diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/OperatorGenerator.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/OperatorGenerator.cs index 701d376683b228c576d7e63af48ed54e4648f255..75ed48aebb27e0cb95ed1bb6efb498e8ca6dc979 100644 --- a/src/Workspaces/CSharp/Portable/CodeGeneration/OperatorGenerator.cs +++ b/src/Workspaces/CSharp/Portable/CodeGeneration/OperatorGenerator.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using Microsoft.CodeAnalysis.CodeGeneration; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -16,10 +17,12 @@ internal static class OperatorGenerator internal static TypeDeclarationSyntax AddOperatorTo( TypeDeclarationSyntax destination, IMethodSymbol method, + Workspace workspace, CodeGenerationOptions options, IList availableIndices) { - var methodDeclaration = GenerateOperatorDeclaration(method, GetDestination(destination), options); + var methodDeclaration = GenerateOperatorDeclaration( + method, GetDestination(destination), workspace, options); var members = Insert(destination.Members, methodDeclaration, options, availableIndices, after: LastOperator); @@ -29,6 +32,7 @@ internal static class OperatorGenerator internal static OperatorDeclarationSyntax GenerateOperatorDeclaration( IMethodSymbol method, CodeGenerationDestination destination, + Workspace workspace, CodeGenerationOptions options) { var reusableSyntax = GetReuseableSyntaxNodeForSymbol(method, options); @@ -38,11 +42,32 @@ internal static class OperatorGenerator } var declaration = GenerateOperatorDeclarationWorker(method, destination, options); + declaration = UseExpressionBodyIfDesired(workspace, declaration); return AddAnnotationsTo(method, ConditionallyAddDocumentationCommentTo(declaration, method, options)); } + private static OperatorDeclarationSyntax UseExpressionBodyIfDesired(Workspace workspace, OperatorDeclarationSyntax declaration) + { + if (declaration.ExpressionBody == null) + { + var preferExpressionBody = workspace.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedMethods).Value; + if (preferExpressionBody) + { + var expressionBody = CodeGenerationHelpers.TryConvertToExpressionBody(declaration.Body); + if (expressionBody != null) + { + return declaration.WithBody(null) + .WithExpressionBody(expressionBody) + .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)); + } + } + } + + return declaration; + } + private static OperatorDeclarationSyntax GenerateOperatorDeclarationWorker( IMethodSymbol method, CodeGenerationDestination destination, diff --git a/src/Workspaces/CSharp/Portable/CodeStyle/CSharpCodeStyleOptions.cs b/src/Workspaces/CSharp/Portable/CodeStyle/CSharpCodeStyleOptions.cs index 3986a1b7db3c19ab1d81bb10dcd8f7b215b8e4ed..bccffb9dfce69e64f4f2a02f7a776deac6b96e8a 100644 --- a/src/Workspaces/CSharp/Portable/CodeStyle/CSharpCodeStyleOptions.cs +++ b/src/Workspaces/CSharp/Portable/CodeStyle/CSharpCodeStyleOptions.cs @@ -31,8 +31,20 @@ internal static class CSharpCodeStyleOptions nameof(CodeStyleOptions), nameof(PreferExpressionBodiedMethods), defaultValue: CodeStyleOptions.falseWithNoneEnforcement, storageLocations: new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferExpressionBodiedMethods)}")); + public static readonly Option> PreferExpressionBodiedOperators = new Option>( + nameof(CodeStyleOptions), nameof(PreferExpressionBodiedOperators), defaultValue: CodeStyleOptions.falseWithNoneEnforcement, + storageLocations: new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferExpressionBodiedOperators)}")); + public static readonly Option> PreferExpressionBodiedProperties = new Option>( nameof(CodeStyleOptions), nameof(PreferExpressionBodiedProperties), defaultValue: CodeStyleOptions.trueWithNoneEnforcement, storageLocations: new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferExpressionBodiedProperties)}")); + + public static readonly Option> PreferExpressionBodiedIndexers = new Option>( + nameof(CodeStyleOptions), nameof(PreferExpressionBodiedIndexers), defaultValue: CodeStyleOptions.trueWithNoneEnforcement, + storageLocations: new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferExpressionBodiedIndexers)}")); + + public static readonly Option> PreferExpressionBodiedAccessors = new Option>( + nameof(CodeStyleOptions), nameof(PreferExpressionBodiedAccessors), defaultValue: CodeStyleOptions.trueWithNoneEnforcement, + storageLocations: new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferExpressionBodiedAccessors)}")); } } \ No newline at end of file