提交 17c8550e 编写于 作者: C CyrusNajmabadi

Share code between indexer and property genration.

上级 43a44043
......@@ -310,6 +310,7 @@
<Compile Include="Organizing\OrganizeUsingsTests.cs" />
<Compile Include="Structure\BlockSyntaxStructureTests.cs" />
<Compile Include="Structure\SwitchStatementStructureTests.cs" />
<Compile Include="UseExpressionBody\UseExpressionBodyForIndexerTests.cs" />
<Compile Include="UseExpressionBody\UseExpressionBodyForPropertiesTests.cs" />
<Compile Include="UseExpressionBody\UseExpressionBodyForConstructorsTests.cs" />
<Compile Include="UseExpressionBody\UseExpressionBodyForConversionOperatorsTests.cs" />
......
// 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 System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeStyle;
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 Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.UseExpressionBody
{
public class UseExpressionBodyForIndexersTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest
{
internal override Tuple<DiagnosticAnalyzer, CodeFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
=> new Tuple<DiagnosticAnalyzer, CodeFixProvider>(
new UseExpressionBodyForIndexersDiagnosticAnalyzer(),
new UseExpressionBodyForIndexersCodeFixProvider());
private static readonly Dictionary<OptionKey, object> UseExpressionBody =
new Dictionary<OptionKey, object>
{
{ CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CodeStyleOptions.trueWithNoneEnforcement },
{ CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.falseWithNoneEnforcement },
};
private static readonly Dictionary<OptionKey, object> UseBlockBody =
new Dictionary<OptionKey, object>
{
{ CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CodeStyleOptions.falseWithNoneEnforcement },
{ CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.falseWithNoneEnforcement }
};
private static readonly Dictionary<OptionKey, object> UseBlockBodyExceptAccessor =
new Dictionary<OptionKey, object>
{
{ CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CodeStyleOptions.falseWithNoneEnforcement },
{ CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CodeStyleOptions.trueWithNoneEnforcement }
};
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUseExpressionBody1()
{
await TestAsync(
@"class C
{
int this[int i] {
get {
[|return|] Bar();
}
}
}",
@"class C
{
int this[int i] => Bar();
}", options: UseExpressionBody);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestMissingWithSetter()
{
await TestMissingAsync(
@"class C
{
int this[int i] {
get {
[|return|] Bar();
}
set { }
}
}", options: UseExpressionBody);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestMissingOnSetter1()
{
await TestMissingAsync(
@"class C
{
int this[int i] {
set {
[|Bar|]();
}
}
}", options: UseExpressionBody);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUseExpressionBody3()
{
await TestAsync(
@"class C
{
int this[int i] {
get {
[|throw|] new NotImplementedException();
}
}
}",
@"class C
{
int this[int i] => throw new NotImplementedException();
}", options: UseExpressionBody);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUseExpressionBody4()
{
await TestAsync(
@"class C
{
int this[int i]
{
get
{
[|throw|] new NotImplementedException(); // comment
}
}
}",
@"class C
{
int this[int i] => throw new NotImplementedException(); // comment
}", compareTokens: false, options: UseExpressionBody);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUseBlockBody1()
{
await TestAsync(
@"class C
{
int this[int i] [|=>|] Bar();
}",
@"class C
{
int this[int i] {
get {
return Bar();
}
}
}", options: UseBlockBody);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUseBlockBodyIfAccessorWantExpression1()
{
await TestAsync(
@"class C
{
int this[int i] [|=>|] Bar();
}",
@"class C
{
int this[int i] {
get => Bar();
}
}", options: UseBlockBodyExceptAccessor);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUseBlockBody3()
{
await TestAsync(
@"class C
{
int this[int i] [|=>|] throw new NotImplementedException();
}",
@"class C
{
int this[int i] {
get {
throw new NotImplementedException();
}
}
}", options: UseBlockBody);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUseBlockBody4()
{
await TestAsync(
@"class C
{
int this[int i] [|=>|] throw new NotImplementedException(); // comment
}",
@"class C
{
int this[int i]
{
get
{
throw new NotImplementedException(); // comment
}
}
}", compareTokens: false, options: UseBlockBody);
}
}
}
\ No newline at end of file
......@@ -8,6 +8,7 @@
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Editing;
......@@ -157,6 +158,38 @@ private SyntaxToken GetFirstStatementSemicolon(BlockSyntax body)
}
}
protected TDeclaration WithAccessorList(
TDeclaration declaration, OptionSet options)
{
var expressionBody = GetExpressionBody(declaration);
var semicolonToken = GetSemicolonToken(declaration);
var preferExpressionBodiedAccessors = options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors).Value;
AccessorDeclarationSyntax accessor;
if (preferExpressionBodiedAccessors)
{
accessor = SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithExpressionBody(expressionBody)
.WithSemicolonToken(semicolonToken);
}
else
{
var block = expressionBody.ConvertToBlock(
GetSemicolonToken(declaration),
CreateReturnStatementForExpression(declaration));
accessor = SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration, block);
}
return WithAccessorList(declaration, SyntaxFactory.AccessorList(
SyntaxFactory.SingletonList(accessor)));
}
protected virtual TDeclaration WithAccessorList(TDeclaration declaration, AccessorListSyntax accessorListSyntax)
{
throw new NotImplementedException();
}
private class MyCodeAction : CodeAction.DocumentChangeAction
{
public MyCodeAction(string title, Func<CancellationToken, Task<Document>> createChangedDocument)
......
// 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.Composition;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Options;
namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody
{
......@@ -34,12 +36,24 @@ protected override IndexerDeclarationSyntax WithSemicolonToken(IndexerDeclaratio
protected override IndexerDeclarationSyntax WithExpressionBody(IndexerDeclarationSyntax declaration, ArrowExpressionClauseSyntax expressionBody)
=> declaration.WithExpressionBody(expressionBody);
protected override IndexerDeclarationSyntax WithAccessorList(IndexerDeclarationSyntax declaration, AccessorListSyntax accessorList)
=> declaration.WithAccessorList(accessorList);
protected override IndexerDeclarationSyntax WithBody(IndexerDeclarationSyntax declaration, BlockSyntax body)
=> body == null
? declaration.WithAccessorList(null)
: declaration.WithAccessorList(SyntaxFactory.AccessorList(
SyntaxFactory.SingletonList(SyntaxFactory.AccessorDeclaration(
SyntaxKind.GetAccessorDeclaration, body))));
{
if (body == null)
{
return declaration.WithAccessorList(null);
}
throw new InvalidOperationException();
}
protected override IndexerDeclarationSyntax WithGenerateBody(
IndexerDeclarationSyntax declaration, OptionSet options)
{
return WithAccessorList(declaration, options);
}
protected override bool CreateReturnStatementForExpression(IndexerDeclarationSyntax declaration) => true;
}
......
......@@ -38,6 +38,9 @@ protected override PropertyDeclarationSyntax WithSemicolonToken(PropertyDeclarat
protected override PropertyDeclarationSyntax WithExpressionBody(PropertyDeclarationSyntax declaration, ArrowExpressionClauseSyntax expressionBody)
=> declaration.WithExpressionBody(expressionBody);
protected override PropertyDeclarationSyntax WithAccessorList(PropertyDeclarationSyntax declaration, AccessorListSyntax accessorListSyntax)
=> declaration.WithAccessorList(accessorListSyntax);
protected override PropertyDeclarationSyntax WithBody(PropertyDeclarationSyntax declaration, BlockSyntax body)
{
if (body == null)
......@@ -45,37 +48,15 @@ protected override PropertyDeclarationSyntax WithBody(PropertyDeclarationSyntax
return declaration.WithAccessorList(null);
}
return declaration;
throw new InvalidOperationException();
}
protected override PropertyDeclarationSyntax WithGenerateBody(
PropertyDeclarationSyntax declaration, OptionSet options)
{
var expressionBody = GetExpressionBody(declaration);
var semicolonToken = GetSemicolonToken(declaration);
var preferExpressionBodiedAccessors = options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors).Value;
AccessorDeclarationSyntax accessor;
if (preferExpressionBodiedAccessors)
{
accessor = SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithExpressionBody(expressionBody)
.WithSemicolonToken(semicolonToken);
}
else
{
var block = expressionBody.ConvertToBlock(
GetSemicolonToken(declaration),
CreateReturnStatementForExpression(declaration));
accessor = SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration, block);
}
return declaration.WithAccessorList(SyntaxFactory.AccessorList(
SyntaxFactory.SingletonList(accessor)));
return WithAccessorList(declaration, options);
}
protected override bool CreateReturnStatementForExpression(PropertyDeclarationSyntax declaration) => true;
}
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册