未验证 提交 a3b3d7be 编写于 作者: J Joey Robichaud 提交者: GitHub

Merge pull request #31648 from rik-smeets/add-expression-body-refactoring-local-functions

Include local functions in 'Use expression body' refactoring
// 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.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.UseExpressionBody;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.UseExpressionBody
{
public class UseExpressionBodyForLocalFunctionsAnalyzerTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest
{
internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace)
=> (new UseExpressionBodyDiagnosticAnalyzer(), new UseExpressionBodyCodeFixProvider());
private IDictionary<OptionKey, object> UseExpressionBody =>
Option(CSharpCodeStyleOptions.PreferExpressionBodiedLocalFunctions, CSharpCodeStyleOptions.WhenPossibleWithSilentEnforcement);
private IDictionary<OptionKey, object> UseExpressionBodyWhenOnSingleLine =>
Option(CSharpCodeStyleOptions.PreferExpressionBodiedLocalFunctions, CSharpCodeStyleOptions.WhenOnSingleLineWithSilentEnforcement);
private IDictionary<OptionKey, object> UseBlockBody =>
Option(CSharpCodeStyleOptions.PreferExpressionBodiedLocalFunctions, CSharpCodeStyleOptions.NeverWithSilentEnforcement);
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUseExpressionBody1()
{
await TestInRegularAndScriptAsync(
@"class C
{
void Goo()
{
void Bar()
{
[|Test|]();
}
}
}",
@"class C
{
void Goo()
{
void Bar() => Test();
}
}", options: UseExpressionBody);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUseExpressionBody2()
{
await TestInRegularAndScriptAsync(
@"class C
{
void Goo()
{
int Bar()
{
return [|Test|]();
}
}
}",
@"class C
{
void Goo()
{
int Bar() => Test();
}
}", options: UseExpressionBody);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUseExpressionBody3()
{
await TestInRegularAndScriptAsync(
@"class C
{
int Goo()
{
int Bar()
{
[|throw|] new NotImplementedException();
}
}
}",
@"class C
{
int Goo()
{
int Bar() => [|throw|] new NotImplementedException();
}
}", options: UseExpressionBody);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUseExpressionBody4()
{
await TestInRegularAndScriptAsync(
@"class C
{
int Goo()
{
int Bar()
{
[|throw|] new NotImplementedException(); // comment
}
}
}",
@"class C
{
int Goo()
{
int Bar() => [|throw|] new NotImplementedException(); // comment
}
}", options: UseExpressionBody);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUseExpressionBodyWhenOnSingleLineMissing()
{
await TestMissingInRegularAndScriptAsync(
@"class C
{
int Goo()
{
int Bar()
{
[|return|] 1 +
2 +
3;
}
}
}", new TestParameters(options: UseExpressionBodyWhenOnSingleLine));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUseExpressionBodyWhenOnSingleLine()
{
await TestInRegularAndScriptAsync(
@"class C
{
int Goo()
{
int Bar()
{
[|return|] 1 + 2 + 3;
}
}
}",
@"class C
{
int Goo()
{
int Bar() => 1 + 2 + 3;
}
}", options: UseExpressionBodyWhenOnSingleLine);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUseBlockBody1()
{
await TestInRegularAndScriptAsync(
@"class C
{
void Goo()
{
void Bar() => [|Test()|];
}
}",
@"class C
{
void Goo()
{
void Bar()
{
Test();
}
}
}", options: UseBlockBody);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUseBlockBody2()
{
await TestInRegularAndScriptAsync(
@"class C
{
int Goo()
{
int Bar() => [|Test|]();
}
}",
@"class C
{
int Goo()
{
int Bar()
{
return Test();
}
}
}", options: UseBlockBody);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUseBlockBody3()
{
await TestInRegularAndScriptAsync(
@"class C
{
int Goo()
{
int Bar() => [|throw|] new NotImplementedException();
}
}",
@"class C
{
int Goo()
{
int Bar()
{
throw new NotImplementedException();
}
}
}", options: UseBlockBody);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUseBlockBody4()
{
await TestInRegularAndScriptAsync(
@"class C
{
int Goo()
{
int Bar() => [|throw|] new NotImplementedException(); // comment
}
}",
@"class C
{
int Goo()
{
int Bar()
{
throw new NotImplementedException(); // comment
}
}
}", options: UseBlockBody);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestComments1()
{
await TestInRegularAndScriptAsync(
@"class C
{
void Goo()
{
void Bar()
{
// Comment
[|Test|]();
}
}
}",
@"class C
{
void Goo()
{
void Bar() =>
// Comment
Test();
}
}", options: UseExpressionBody);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestComments2()
{
await TestInRegularAndScriptAsync(
@"class C
{
int Goo()
{
int Bar()
{
// Comment
return [|Test|]();
}
}
}",
@"class C
{
int Goo()
{
int Bar() =>
// Comment
Test();
}
}", options: UseExpressionBody);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestComments3()
{
await TestInRegularAndScriptAsync(
@"class C
{
void Goo()
{
void Bar()
{
// Comment
throw [|Test|]();
}
}
}",
@"class C
{
void Goo()
{
void Bar() =>
// Comment
throw Test();
}
}", options: UseExpressionBody);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestComments4()
{
await TestInRegularAndScriptAsync(
@"class C
{
void Goo()
{
void Bar()
{
[|Test|](); // Comment
}
}
}",
@"class C
{
void Goo()
{
void Bar() => Test(); // Comment
}
}", options: UseExpressionBody);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestComments5()
{
await TestInRegularAndScriptAsync(
@"class C
{
int Goo()
{
int Bar()
{
return [|Test|](); // Comment
}
}
}",
@"class C
{
int Goo()
{
int Bar() => Test(); // Comment
}
}", options: UseExpressionBody);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestComments6()
{
await TestInRegularAndScriptAsync(
@"class C
{
void Goo()
{
void Bar()
{
throw [|Test|](); // Comment
}
}
}",
@"class C
{
void Goo()
{
void Bar() => throw Test(); // Comment
}
}", options: UseExpressionBody);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestDirectives1()
{
await TestInRegularAndScriptAsync(
@"
#define DEBUG
using System;
class Program
{
void Method()
{
void Bar()
{
#if DEBUG
[|Console|].WriteLine();
#endif
}
}
}",
@"
#define DEBUG
using System;
class Program
{
void Method()
{
void Bar() =>
#if DEBUG
Console.WriteLine();
#endif
}
}", options: UseExpressionBody);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestDirectives2()
{
await TestInRegularAndScriptAsync(
@"
#define DEBUG
using System;
class Program
{
void Method()
{
void Bar()
{
#if DEBUG
[|Console|].WriteLine(a);
#else
Console.WriteLine(b);
#endif
}
}
}",
@"
#define DEBUG
using System;
class Program
{
void Method()
{
void Bar() =>
#if DEBUG
Console.WriteLine(a);
#else
Console.WriteLine(b);
#endif
}
}", options: UseExpressionBody);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUseBlockBodyAsync1()
{
await TestInRegularAndScriptAsync(
@"using System.Threading.Tasks;
class C
{
async Task Goo()
{
async Task Bar() [|=>|] await Test();
}
Task Test() { }
}",
@"using System.Threading.Tasks;
class C
{
async Task Goo()
{
async Task Bar()
{
await Test();
}
}
Task Test() { }
}", options: UseBlockBody);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUseBlockBodyAsync2()
{
await TestInRegularAndScriptAsync(
@"using System.Threading.Tasks;
class C
{
async void Goo()
{
async void Bar() [|=>|] await Test();
}
Task Test() { }
}",
@"using System.Threading.Tasks;
class C
{
async void Goo()
{
async void Bar()
{
await Test();
}
}
Task Test() { }
}", options: UseBlockBody);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUseBlockBodyAsync3()
{
await TestInRegularAndScriptAsync(
@"using System.Threading.Tasks;
class C
{
async ValueTask Goo()
{
async ValueTask Test() [|=>|] await Bar();
}
Task Bar() { }
}",
@"using System.Threading.Tasks;
class C
{
async ValueTask Goo()
{
async ValueTask Test()
{
await Bar();
}
}
Task Bar() { }
}", options: UseBlockBody);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUseBlockBodyAsync4()
{
await TestInRegularAndScriptAsync(
@"using System.Threading.Tasks;
class C
{
async Task<int> Goo()
{
Task<int> Test() [|=>|] Bar();
}
Task<int> Bar() { }
}",
@"using System.Threading.Tasks;
class C
{
async Task<int> Goo()
{
Task<int> Test()
{
return Bar();
}
}
Task<int> Bar() { }
}", options: UseBlockBody);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUseBlockBodyAsync5()
{
await TestInRegularAndScriptAsync(
@"using System.Threading.Tasks;
class C
{
Task Goo()
{
Task Test() [|=>|] Bar();
}
Task Bar() { }
}",
@"using System.Threading.Tasks;
class C
{
Task Goo()
{
Task Test()
{
return Bar();
}
}
Task Bar() { }
}", options: UseBlockBody);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUseBlockBodyNestedLocalFunction()
{
await TestInRegularAndScriptAsync(
@"class C
{
void Goo()
{
void Bar()
{
void Test() => [|NestedTest()|];
}
}
}",
@"class C
{
void Goo()
{
void Bar()
{
void Test()
{
NestedTest();
}
}
}
}", options: UseBlockBody);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUseExpressionBodyNestedLocalFunction()
{
await TestInRegularAndScriptAsync(
@"class C
{
void Goo()
{
void Bar()
{
void Test()
{
[|NestedTest()|];
}
}
}
}",
@"class C
{
void Goo()
{
void Bar()
{
void Test() => NestedTest();
}
}
}", options: UseExpressionBody);
}
}
}
// 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.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.UseExpressionBody;
using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeRefactorings;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.UseExpressionBody
{
public class UseExpressionBodyForLocalFunctionsRefactoringTests : AbstractCSharpCodeActionTest
{
protected override CodeRefactoringProvider CreateCodeRefactoringProvider(Workspace workspace, TestParameters parameters)
=> new UseExpressionBodyCodeRefactoringProvider();
private IDictionary<OptionKey, object> UseExpressionBody =>
Option(CSharpCodeStyleOptions.PreferExpressionBodiedLocalFunctions, CSharpCodeStyleOptions.WhenPossibleWithSilentEnforcement);
private IDictionary<OptionKey, object> UseExpressionBodyDisabledDiagnostic =>
Option(CSharpCodeStyleOptions.PreferExpressionBodiedLocalFunctions, new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.WhenPossible, NotificationOption.None));
private IDictionary<OptionKey, object> UseBlockBody =>
Option(CSharpCodeStyleOptions.PreferExpressionBodiedLocalFunctions, CSharpCodeStyleOptions.NeverWithSilentEnforcement);
private IDictionary<OptionKey, object> UseBlockBodyDisabledDiagnostic =>
Option(CSharpCodeStyleOptions.PreferExpressionBodiedLocalFunctions, new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.Never, NotificationOption.None));
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestNotOfferedIfUserPrefersExpressionBodiesAndInBlockBody()
{
await TestMissingAsync(
@"class C
{
void Goo()
{
void Bar()
{
[||]Test();
}
}
}", parameters: new TestParameters(options: UseExpressionBody));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersExpressionBodiesWithoutDiagnosticAndInBlockBody()
{
await TestInRegularAndScript1Async(
@"class C
{
void Goo()
{
void Bar()
{
[||]Test();
}
}
}",
@"class C
{
void Goo()
{
void Bar() => Test();
}
}", parameters: new TestParameters(options: UseExpressionBodyDisabledDiagnostic));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersBlockBodiesAndInBlockBody()
{
await TestInRegularAndScript1Async(
@"class C
{
void Goo()
{
void Bar()
{
[||]Test();
}
}
}",
@"class C
{
void Goo()
{
void Bar() => Test();
}
}", parameters: new TestParameters(options: UseBlockBody));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestNotOfferedIfUserPrefersBlockBodiesAndInExpressionBody()
{
await TestMissingAsync(
@"class C
{
void Goo()
{
void Bar() => [||]Test();
}
}", parameters: new TestParameters(options: UseBlockBody));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersBlockBodiesWithoutDiagnosticAndInExpressionBody()
{
await TestInRegularAndScript1Async(
@"class C
{
void Goo()
{
void Bar() => [||]Test();
}
}",
@"class C
{
void Goo()
{
void Bar()
{
Test();
}
}
}", parameters: new TestParameters(options: UseBlockBodyDisabledDiagnostic));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersExpressionBodiesAndInExpressionBody()
{
await TestInRegularAndScript1Async(
@"class C
{
void Goo()
{
void Bar() => [||]Test();
}
}",
@"class C
{
void Goo()
{
void Bar()
{
Test();
}
}
}", parameters: new TestParameters(options: UseExpressionBody));
}
}
}
......@@ -84,7 +84,8 @@ internal class CSharpCodeCleanupService : ICodeCleanupService
IDEDiagnosticIds.UseExpressionBodyForOperatorsDiagnosticId,
IDEDiagnosticIds.UseExpressionBodyForPropertiesDiagnosticId,
IDEDiagnosticIds.UseExpressionBodyForIndexersDiagnosticId,
IDEDiagnosticIds.UseExpressionBodyForAccessorsDiagnosticId)),
IDEDiagnosticIds.UseExpressionBodyForAccessorsDiagnosticId,
IDEDiagnosticIds.UseExpressionBodyForLocalFunctionsDiagnosticId)),
(CSharpFeaturesResources.Apply_inline_out_variable_preferences,
CodeCleanupOptions.ApplyInlineOutVariablePreferences,
......
// 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.Collections.Immutable;
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 UseExpressionBodyForLocalFunctionHelper :
UseExpressionBodyHelper<LocalFunctionStatementSyntax>
{
public static readonly UseExpressionBodyForLocalFunctionHelper Instance = new UseExpressionBodyForLocalFunctionHelper();
private UseExpressionBodyForLocalFunctionHelper()
: base(IDEDiagnosticIds.UseExpressionBodyForLocalFunctionsDiagnosticId,
new LocalizableResourceString(nameof(FeaturesResources.Use_expression_body_for_local_functions), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
new LocalizableResourceString(nameof(FeaturesResources.Use_block_body_for_local_functions), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
CSharpCodeStyleOptions.PreferExpressionBodiedLocalFunctions,
ImmutableArray.Create(SyntaxKind.LocalFunctionStatement))
{
}
protected override BlockSyntax GetBody(LocalFunctionStatementSyntax statement)
=> statement.Body;
protected override ArrowExpressionClauseSyntax GetExpressionBody(LocalFunctionStatementSyntax statement)
=> statement.ExpressionBody;
protected override SyntaxToken GetSemicolonToken(LocalFunctionStatementSyntax statement)
=> statement.SemicolonToken;
protected override LocalFunctionStatementSyntax WithSemicolonToken(LocalFunctionStatementSyntax statement, SyntaxToken token)
=> statement.WithSemicolonToken(token);
protected override LocalFunctionStatementSyntax WithExpressionBody(LocalFunctionStatementSyntax statement, ArrowExpressionClauseSyntax expressionBody)
=> statement.WithExpressionBody(expressionBody);
protected override LocalFunctionStatementSyntax WithBody(LocalFunctionStatementSyntax statement, BlockSyntax body)
=> statement.WithBody(body);
protected override bool CreateReturnStatementForExpression(
SemanticModel semanticModel, LocalFunctionStatementSyntax statement)
{
if (statement.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' local function.
var symbol = semanticModel.GetDeclaredSymbol(statement);
return symbol is IMethodSymbol methodSymbol &&
methodSymbol.ReturnType is INamedTypeSymbol namedType &&
namedType.Arity != 0;
}
return !statement.ReturnType.IsVoid();
}
}
}
......@@ -33,6 +33,7 @@ internal abstract class UseExpressionBodyHelper
UseExpressionBodyForMethodsHelper.Instance,
UseExpressionBodyForOperatorsHelper.Instance,
UseExpressionBodyForPropertiesHelper.Instance,
UseExpressionBodyForAccessorsHelper.Instance);
UseExpressionBodyForAccessorsHelper.Instance,
UseExpressionBodyForLocalFunctionHelper.Instance);
}
}
......@@ -99,6 +99,9 @@ internal static class IDEDiagnosticIds
public const string ValueAssignedIsUnusedDiagnosticId = "IDE0059";
public const string UnusedParameterDiagnosticId = "IDE0060";
// Conceptually belongs with IDE0021-IDE0027 & IDE0053, but is here because it was added later
public const string UseExpressionBodyForLocalFunctionsDiagnosticId = "IDE0061";
// Analyzer error Ids
public const string AnalyzerChangedId = "IDE1001";
public const string AnalyzerDependencyConflictId = "IDE1002";
......
......@@ -4059,6 +4059,15 @@ internal class FeaturesResources {
}
}
/// <summary>
/// Looks up a localized string similar to Use block body for local functions.
/// </summary>
internal static string Use_block_body_for_local_functions {
get {
return ResourceManager.GetString("Use_block_body_for_local_functions", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Use block body for methods.
/// </summary>
......@@ -4167,6 +4176,15 @@ internal class FeaturesResources {
}
}
/// <summary>
/// Looks up a localized string similar to Use expression body for local functions.
/// </summary>
internal static string Use_expression_body_for_local_functions {
get {
return ResourceManager.GetString("Use_expression_body_for_local_functions", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Use expression body for methods.
/// </summary>
......
......@@ -1595,4 +1595,10 @@ This version used in: {2}</value>
<data name="Remove_unused_parameter_0_its_initial_value_is_never_used" xml:space="preserve">
<value>Remove unused parameter '{0}', its initial value is never used</value>
</data>
<data name="Use_block_body_for_local_functions" xml:space="preserve">
<value>Use block body for local functions</value>
</data>
<data name="Use_expression_body_for_local_functions" xml:space="preserve">
<value>Use expression body for local functions</value>
</data>
</root>
\ No newline at end of file
......@@ -292,6 +292,11 @@
<target state="new">Use block body for lambda expressions</target>
<note />
</trans-unit>
<trans-unit id="Use_block_body_for_local_functions">
<source>Use block body for local functions</source>
<target state="new">Use block body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Use_compound_assignment">
<source>Use compound assignment</source>
<target state="new">Use compound assignment</target>
......@@ -312,6 +317,11 @@
<target state="new">Use expression body for lambda expressions</target>
<note />
</trans-unit>
<trans-unit id="Use_expression_body_for_local_functions">
<source>Use expression body for local functions</source>
<target state="new">Use expression body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Use_index_operator">
<source>Use index operator</source>
<target state="new">Use index operator</target>
......
......@@ -292,6 +292,11 @@
<target state="new">Use block body for lambda expressions</target>
<note />
</trans-unit>
<trans-unit id="Use_block_body_for_local_functions">
<source>Use block body for local functions</source>
<target state="new">Use block body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Use_compound_assignment">
<source>Use compound assignment</source>
<target state="new">Use compound assignment</target>
......@@ -312,6 +317,11 @@
<target state="new">Use expression body for lambda expressions</target>
<note />
</trans-unit>
<trans-unit id="Use_expression_body_for_local_functions">
<source>Use expression body for local functions</source>
<target state="new">Use expression body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Use_index_operator">
<source>Use index operator</source>
<target state="new">Use index operator</target>
......
......@@ -292,6 +292,11 @@
<target state="new">Use block body for lambda expressions</target>
<note />
</trans-unit>
<trans-unit id="Use_block_body_for_local_functions">
<source>Use block body for local functions</source>
<target state="new">Use block body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Use_compound_assignment">
<source>Use compound assignment</source>
<target state="new">Use compound assignment</target>
......@@ -312,6 +317,11 @@
<target state="new">Use expression body for lambda expressions</target>
<note />
</trans-unit>
<trans-unit id="Use_expression_body_for_local_functions">
<source>Use expression body for local functions</source>
<target state="new">Use expression body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Use_index_operator">
<source>Use index operator</source>
<target state="new">Use index operator</target>
......
......@@ -292,6 +292,11 @@
<target state="new">Use block body for lambda expressions</target>
<note />
</trans-unit>
<trans-unit id="Use_block_body_for_local_functions">
<source>Use block body for local functions</source>
<target state="new">Use block body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Use_compound_assignment">
<source>Use compound assignment</source>
<target state="new">Use compound assignment</target>
......@@ -312,6 +317,11 @@
<target state="new">Use expression body for lambda expressions</target>
<note />
</trans-unit>
<trans-unit id="Use_expression_body_for_local_functions">
<source>Use expression body for local functions</source>
<target state="new">Use expression body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Use_index_operator">
<source>Use index operator</source>
<target state="new">Use index operator</target>
......
......@@ -292,6 +292,11 @@
<target state="new">Use block body for lambda expressions</target>
<note />
</trans-unit>
<trans-unit id="Use_block_body_for_local_functions">
<source>Use block body for local functions</source>
<target state="new">Use block body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Use_compound_assignment">
<source>Use compound assignment</source>
<target state="new">Use compound assignment</target>
......@@ -312,6 +317,11 @@
<target state="new">Use expression body for lambda expressions</target>
<note />
</trans-unit>
<trans-unit id="Use_expression_body_for_local_functions">
<source>Use expression body for local functions</source>
<target state="new">Use expression body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Use_index_operator">
<source>Use index operator</source>
<target state="new">Use index operator</target>
......
......@@ -292,6 +292,11 @@
<target state="new">Use block body for lambda expressions</target>
<note />
</trans-unit>
<trans-unit id="Use_block_body_for_local_functions">
<source>Use block body for local functions</source>
<target state="new">Use block body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Use_compound_assignment">
<source>Use compound assignment</source>
<target state="new">Use compound assignment</target>
......@@ -312,6 +317,11 @@
<target state="new">Use expression body for lambda expressions</target>
<note />
</trans-unit>
<trans-unit id="Use_expression_body_for_local_functions">
<source>Use expression body for local functions</source>
<target state="new">Use expression body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Use_index_operator">
<source>Use index operator</source>
<target state="new">Use index operator</target>
......
......@@ -292,6 +292,11 @@
<target state="new">Use block body for lambda expressions</target>
<note />
</trans-unit>
<trans-unit id="Use_block_body_for_local_functions">
<source>Use block body for local functions</source>
<target state="new">Use block body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Use_compound_assignment">
<source>Use compound assignment</source>
<target state="new">Use compound assignment</target>
......@@ -312,6 +317,11 @@
<target state="new">Use expression body for lambda expressions</target>
<note />
</trans-unit>
<trans-unit id="Use_expression_body_for_local_functions">
<source>Use expression body for local functions</source>
<target state="new">Use expression body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Use_index_operator">
<source>Use index operator</source>
<target state="new">Use index operator</target>
......
......@@ -292,6 +292,11 @@
<target state="new">Use block body for lambda expressions</target>
<note />
</trans-unit>
<trans-unit id="Use_block_body_for_local_functions">
<source>Use block body for local functions</source>
<target state="new">Use block body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Use_compound_assignment">
<source>Use compound assignment</source>
<target state="new">Use compound assignment</target>
......@@ -312,6 +317,11 @@
<target state="new">Use expression body for lambda expressions</target>
<note />
</trans-unit>
<trans-unit id="Use_expression_body_for_local_functions">
<source>Use expression body for local functions</source>
<target state="new">Use expression body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Use_index_operator">
<source>Use index operator</source>
<target state="new">Use index operator</target>
......
......@@ -292,6 +292,11 @@
<target state="new">Use block body for lambda expressions</target>
<note />
</trans-unit>
<trans-unit id="Use_block_body_for_local_functions">
<source>Use block body for local functions</source>
<target state="new">Use block body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Use_compound_assignment">
<source>Use compound assignment</source>
<target state="new">Use compound assignment</target>
......@@ -312,6 +317,11 @@
<target state="new">Use expression body for lambda expressions</target>
<note />
</trans-unit>
<trans-unit id="Use_expression_body_for_local_functions">
<source>Use expression body for local functions</source>
<target state="new">Use expression body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Use_index_operator">
<source>Use index operator</source>
<target state="new">Use index operator</target>
......
......@@ -292,6 +292,11 @@
<target state="new">Use block body for lambda expressions</target>
<note />
</trans-unit>
<trans-unit id="Use_block_body_for_local_functions">
<source>Use block body for local functions</source>
<target state="new">Use block body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Use_compound_assignment">
<source>Use compound assignment</source>
<target state="new">Use compound assignment</target>
......@@ -312,6 +317,11 @@
<target state="new">Use expression body for lambda expressions</target>
<note />
</trans-unit>
<trans-unit id="Use_expression_body_for_local_functions">
<source>Use expression body for local functions</source>
<target state="new">Use expression body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Use_index_operator">
<source>Use index operator</source>
<target state="new">Use index operator</target>
......
......@@ -292,6 +292,11 @@
<target state="new">Use block body for lambda expressions</target>
<note />
</trans-unit>
<trans-unit id="Use_block_body_for_local_functions">
<source>Use block body for local functions</source>
<target state="new">Use block body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Use_compound_assignment">
<source>Use compound assignment</source>
<target state="new">Use compound assignment</target>
......@@ -312,6 +317,11 @@
<target state="new">Use expression body for lambda expressions</target>
<note />
</trans-unit>
<trans-unit id="Use_expression_body_for_local_functions">
<source>Use expression body for local functions</source>
<target state="new">Use expression body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Use_index_operator">
<source>Use index operator</source>
<target state="new">Use index operator</target>
......
......@@ -292,6 +292,11 @@
<target state="new">Use block body for lambda expressions</target>
<note />
</trans-unit>
<trans-unit id="Use_block_body_for_local_functions">
<source>Use block body for local functions</source>
<target state="new">Use block body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Use_compound_assignment">
<source>Use compound assignment</source>
<target state="new">Use compound assignment</target>
......@@ -312,6 +317,11 @@
<target state="new">Use expression body for lambda expressions</target>
<note />
</trans-unit>
<trans-unit id="Use_expression_body_for_local_functions">
<source>Use expression body for local functions</source>
<target state="new">Use expression body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Use_index_operator">
<source>Use index operator</source>
<target state="new">Use index operator</target>
......
......@@ -292,6 +292,11 @@
<target state="new">Use block body for lambda expressions</target>
<note />
</trans-unit>
<trans-unit id="Use_block_body_for_local_functions">
<source>Use block body for local functions</source>
<target state="new">Use block body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Use_compound_assignment">
<source>Use compound assignment</source>
<target state="new">Use compound assignment</target>
......@@ -312,6 +317,11 @@
<target state="new">Use expression body for lambda expressions</target>
<note />
</trans-unit>
<trans-unit id="Use_expression_body_for_local_functions">
<source>Use expression body for local functions</source>
<target state="new">Use expression body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Use_index_operator">
<source>Use index operator</source>
<target state="new">Use index operator</target>
......
......@@ -1006,6 +1006,45 @@ void Method()
//]
}
}
";
private const string s_preferExpressionBodyForLocalFunctions = @"
using System;
//[
class Customer
{
private int Age;
public int GetAge()
{
return GetAgeLocal();
int GetAgeLocal() => this.Age;
}
}
//]
";
private const string s_preferBlockBodyForLocalFunctions = @"
using System;
//[
class Customer
{
private int Age;
public int GetAge()
{
return GetAgeLocal();
int GetAgeLocal()
{
return this.Age;
}
}
}
//]
";
private static readonly string s_preferReadonly = $@"
......@@ -1511,6 +1550,13 @@ private void AddExpressionBodyOptions(OptionSet optionSet, string expressionPref
enumValues,
new[] { s_preferBlockBodyForLambdas, s_preferExpressionBodyForLambdas, s_preferExpressionBodyForLambdas },
this, optionSet, expressionPreferencesGroupTitle, expressionBodyPreferences));
CodeStyleItems.Add(new EnumCodeStyleOptionViewModel<ExpressionBodyPreference>(
CSharpCodeStyleOptions.PreferExpressionBodiedLocalFunctions,
ServicesVSResources.Use_expression_body_for_local_functions,
enumValues,
new[] { s_preferBlockBodyForLocalFunctions, s_preferExpressionBodyForLocalFunctions, s_preferExpressionBodyForLocalFunctions },
this, optionSet, expressionPreferencesGroupTitle, expressionBodyPreferences));
}
private void AddUnusedValueOptions(OptionSet optionSet, string expressionPreferencesGroupTitle)
......
......@@ -2859,6 +2859,15 @@ internal class ServicesVSResources {
}
}
/// <summary>
/// Looks up a localized string similar to Use expression body for local functions.
/// </summary>
internal static string Use_expression_body_for_local_functions {
get {
return ResourceManager.GetString("Use_expression_body_for_local_functions", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Use expression body for methods.
/// </summary>
......
......@@ -1120,4 +1120,7 @@ I agree to all of the foregoing:</value>
<data name="Value_returned_by_invocation_is_implicitly_ignored" xml:space="preserve">
<value>Value returned by invocation is implicitly ignored</value>
</data>
<data name="Use_expression_body_for_local_functions" xml:space="preserve">
<value>Use expression body for local functions</value>
</data>
</root>
\ No newline at end of file
......@@ -147,6 +147,11 @@
<target state="new">Use expression body for lambdas</target>
<note />
</trans-unit>
<trans-unit id="Use_expression_body_for_local_functions">
<source>Use expression body for local functions</source>
<target state="new">Use expression body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Value_assigned_here_is_never_used">
<source>Value assigned here is never used</source>
<target state="new">Value assigned here is never used</target>
......
......@@ -147,6 +147,11 @@
<target state="new">Use expression body for lambdas</target>
<note />
</trans-unit>
<trans-unit id="Use_expression_body_for_local_functions">
<source>Use expression body for local functions</source>
<target state="new">Use expression body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Value_assigned_here_is_never_used">
<source>Value assigned here is never used</source>
<target state="new">Value assigned here is never used</target>
......
......@@ -147,6 +147,11 @@
<target state="new">Use expression body for lambdas</target>
<note />
</trans-unit>
<trans-unit id="Use_expression_body_for_local_functions">
<source>Use expression body for local functions</source>
<target state="new">Use expression body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Value_assigned_here_is_never_used">
<source>Value assigned here is never used</source>
<target state="new">Value assigned here is never used</target>
......
......@@ -147,6 +147,11 @@
<target state="new">Use expression body for lambdas</target>
<note />
</trans-unit>
<trans-unit id="Use_expression_body_for_local_functions">
<source>Use expression body for local functions</source>
<target state="new">Use expression body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Value_assigned_here_is_never_used">
<source>Value assigned here is never used</source>
<target state="new">Value assigned here is never used</target>
......
......@@ -147,6 +147,11 @@
<target state="new">Use expression body for lambdas</target>
<note />
</trans-unit>
<trans-unit id="Use_expression_body_for_local_functions">
<source>Use expression body for local functions</source>
<target state="new">Use expression body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Value_assigned_here_is_never_used">
<source>Value assigned here is never used</source>
<target state="new">Value assigned here is never used</target>
......
......@@ -147,6 +147,11 @@
<target state="new">Use expression body for lambdas</target>
<note />
</trans-unit>
<trans-unit id="Use_expression_body_for_local_functions">
<source>Use expression body for local functions</source>
<target state="new">Use expression body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Value_assigned_here_is_never_used">
<source>Value assigned here is never used</source>
<target state="new">Value assigned here is never used</target>
......
......@@ -147,6 +147,11 @@
<target state="new">Use expression body for lambdas</target>
<note />
</trans-unit>
<trans-unit id="Use_expression_body_for_local_functions">
<source>Use expression body for local functions</source>
<target state="new">Use expression body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Value_assigned_here_is_never_used">
<source>Value assigned here is never used</source>
<target state="new">Value assigned here is never used</target>
......
......@@ -147,6 +147,11 @@
<target state="new">Use expression body for lambdas</target>
<note />
</trans-unit>
<trans-unit id="Use_expression_body_for_local_functions">
<source>Use expression body for local functions</source>
<target state="new">Use expression body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Value_assigned_here_is_never_used">
<source>Value assigned here is never used</source>
<target state="new">Value assigned here is never used</target>
......
......@@ -147,6 +147,11 @@
<target state="new">Use expression body for lambdas</target>
<note />
</trans-unit>
<trans-unit id="Use_expression_body_for_local_functions">
<source>Use expression body for local functions</source>
<target state="new">Use expression body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Value_assigned_here_is_never_used">
<source>Value assigned here is never used</source>
<target state="new">Value assigned here is never used</target>
......
......@@ -147,6 +147,11 @@
<target state="new">Use expression body for lambdas</target>
<note />
</trans-unit>
<trans-unit id="Use_expression_body_for_local_functions">
<source>Use expression body for local functions</source>
<target state="new">Use expression body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Value_assigned_here_is_never_used">
<source>Value assigned here is never used</source>
<target state="new">Value assigned here is never used</target>
......
......@@ -147,6 +147,11 @@
<target state="new">Use expression body for lambdas</target>
<note />
</trans-unit>
<trans-unit id="Use_expression_body_for_local_functions">
<source>Use expression body for local functions</source>
<target state="new">Use expression body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Value_assigned_here_is_never_used">
<source>Value assigned here is never used</source>
<target state="new">Value assigned here is never used</target>
......
......@@ -147,6 +147,11 @@
<target state="new">Use expression body for lambdas</target>
<note />
</trans-unit>
<trans-unit id="Use_expression_body_for_local_functions">
<source>Use expression body for local functions</source>
<target state="new">Use expression body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Value_assigned_here_is_never_used">
<source>Value assigned here is never used</source>
<target state="new">Value assigned here is never used</target>
......
......@@ -147,6 +147,11 @@
<target state="new">Use expression body for lambdas</target>
<note />
</trans-unit>
<trans-unit id="Use_expression_body_for_local_functions">
<source>Use expression body for local functions</source>
<target state="new">Use expression body for local functions</target>
<note />
</trans-unit>
<trans-unit id="Value_assigned_here_is_never_used">
<source>Value assigned here is never used</source>
<target state="new">Value assigned here is never used</target>
......
......@@ -88,6 +88,7 @@ csharp_style_expression_bodied_accessors = true:silent
csharp_style_expression_bodied_constructors = false:silent
csharp_style_expression_bodied_indexers = true:silent
csharp_style_expression_bodied_lambdas = true:silent
csharp_style_expression_bodied_local_functions = false:silent
csharp_style_expression_bodied_methods = false:silent
csharp_style_expression_bodied_operators = false:silent
csharp_style_expression_bodied_properties = true:silent
......@@ -245,6 +246,7 @@ csharp_style_expression_bodied_accessors = true:silent
csharp_style_expression_bodied_constructors = false:silent
csharp_style_expression_bodied_indexers = true:silent
csharp_style_expression_bodied_lambdas = true:silent
csharp_style_expression_bodied_local_functions = false:silent
csharp_style_expression_bodied_methods = false:silent
csharp_style_expression_bodied_operators = false:silent
csharp_style_expression_bodied_properties = true:silent
......
......@@ -156,6 +156,16 @@ private static Option<T> CreateOption<T>(OptionGroup group, string name, T defau
GetExpressionBodyPreferenceEditorConfigString),
new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferExpressionBodiedLambdas)}")});
public static readonly Option<CodeStyleOption<ExpressionBodyPreference>> PreferExpressionBodiedLocalFunctions = CreateOption(
CSharpCodeStyleOptionGroups.ExpressionBodiedMembers, nameof(PreferExpressionBodiedLocalFunctions),
defaultValue: NeverWithSilentEnforcement,
storageLocations: new OptionStorageLocation[] {
new EditorConfigStorageLocation<CodeStyleOption<ExpressionBodyPreference>>(
"csharp_style_expression_bodied_local_functions",
s => ParseExpressionBodyPreference(s, NeverWithSilentEnforcement),
GetExpressionBodyPreferenceEditorConfigString),
new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferExpressionBodiedLocalFunctions)}")});
public static readonly Option<CodeStyleOption<bool>> PreferBraces = CreateOption(
CSharpCodeStyleOptionGroups.CodeBlockPreferences, nameof(PreferBraces),
defaultValue: CodeStyleOptions.TrueWithSilentEnforcement,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册