提交 62bba7f8 编写于 作者: C CyrusNajmabadi

Expose 'use expression body' as an analyzer and a refactoring.

上级 daa671d9
......@@ -96,18 +96,34 @@
<Compile Include="UpgradeProject\CSharpUpgradeProjectCodeFixProvider.cs" />
<Compile Include="UseCoalesceExpression\CSharpUseCoalesceExpressionForNullableDiagnosticAnalyzer.cs" />
<Compile Include="UseCoalesceExpression\CSharpUseCoalesceExpressionDiagnosticAnalyzer.cs" />
<Compile Include="UseExpressionBody\Accessors\UseExpressionBodyForAccessorsCodeFixProvider.cs" />
<Compile Include="UseExpressionBody\Accessors\UseExpressionBodyForAccessorsDiagnosticAnalyzer.cs" />
<Compile Include="UseExpressionBody\Indexers\UseExpressionBodyForIndexersCodeFixProvider.cs" />
<Compile Include="UseExpressionBody\Indexers\UseExpressionBodyForIndexersDiagnosticAnalyzer.cs" />
<Compile Include="UseExpressionBody\Properties\UseExpressionBodyForPropertiesCodeFixProvider.cs" />
<Compile Include="UseExpressionBody\Properties\UseExpressionBodyForPropertiesDiagnosticAnalyzer.cs" />
<Compile Include="UseExpressionBody\Operators\UseExpressionBodyForConversionOperatorsCodeFixProvider.cs" />
<Compile Include="UseExpressionBody\Operators\UseExpressionBodyForConversionOperatorsDiagnosticAnalyzer.cs" />
<Compile Include="UseExpressionBody\Constructors\UseExpressionBodyForConstructorsDiagnosticAnalyzer.cs" />
<Compile Include="UseExpressionBody\Operators\UseExpressionBodyForOperatorsDiagnosticAnalyzer.cs" />
<Compile Include="UseExpressionBody\Constructors\UseExpressionBodyForConstructorsCodeFixProvider.cs" />
<Compile Include="UseExpressionBody\Operators\UseExpressionBodyForOperatorsCodeFixProvider.cs" />
<Compile Include="UseExpressionBody\CodeRefactoringProviders\AbstractUseExpressionBodyCodeRefactoringProvider.cs" />
<Compile Include="UseExpressionBody\Analyzers\AbstractUseExpressionBodyDiagnosticAnalyzer.cs" />
<Compile Include="UseExpressionBody\CodeFixProviders\UseExpressionBodyForAccessorsCodeFixProvider.cs" />
<Compile Include="UseExpressionBody\Analyzers\UseExpressionBodyForAccessorsDiagnosticAnalyzer.cs" />
<Compile Include="UseExpressionBody\CodeRefactoringProviders\UseExpressionBodyForAccessorsCodeRefactoringProvider.cs" />
<Compile Include="UseExpressionBody\CodeRefactoringProviders\UseExpressionBodyForConstructorsCodeRefactoringProvider.cs" />
<Compile Include="UseExpressionBody\CodeRefactoringProviders\UseExpressionBodyForConversionOperatorsCodeRefactoringProvider.cs" />
<Compile Include="UseExpressionBody\CodeRefactoringProviders\UseExpressionBodyForIndexersCodeRefactoringProvider.cs" />
<Compile Include="UseExpressionBody\CodeRefactoringProviders\UseExpressionBodyForMethodsCodeRefactoringProvider.cs" />
<Compile Include="UseExpressionBody\CodeRefactoringProviders\UseExpressionBodyForOperatorsCodeRefactoringProvider.cs" />
<Compile Include="UseExpressionBody\CodeRefactoringProviders\UseExpressionBodyForPropertiesCodeRefactoringProvider.cs" />
<Compile Include="UseExpressionBody\Helpers\UseExpressionBodyForConstructorsHelper.cs" />
<Compile Include="UseExpressionBody\Helpers\UseExpressionBodyForAccessorsHelper.cs" />
<Compile Include="UseExpressionBody\CodeFixProviders\UseExpressionBodyForIndexersCodeFixProvider.cs" />
<Compile Include="UseExpressionBody\Helpers\UseExpressionBodyForIndexersHelper.cs" />
<Compile Include="UseExpressionBody\Analyzers\UseExpressionBodyForIndexersDiagnosticAnalyzer.cs" />
<Compile Include="UseExpressionBody\Helpers\UseExpressionBodyForMethodsHelper.cs" />
<Compile Include="UseExpressionBody\Helpers\UseExpressionBodyForConversionOperatorsHelper.cs" />
<Compile Include="UseExpressionBody\Helpers\UseExpressionBodyForOperatorsHelper.cs" />
<Compile Include="UseExpressionBody\CodeFixProviders\UseExpressionBodyForPropertiesCodeFixProvider.cs" />
<Compile Include="UseExpressionBody\Helpers\UseExpressionBodyForPropertiesHelper.cs" />
<Compile Include="UseExpressionBody\Analyzers\UseExpressionBodyForPropertiesDiagnosticAnalyzer.cs" />
<Compile Include="UseExpressionBody\CodeFixProviders\UseExpressionBodyForConversionOperatorsCodeFixProvider.cs" />
<Compile Include="UseExpressionBody\Analyzers\UseExpressionBodyForConversionOperatorsDiagnosticAnalyzer.cs" />
<Compile Include="UseExpressionBody\Analyzers\UseExpressionBodyForConstructorsDiagnosticAnalyzer.cs" />
<Compile Include="UseExpressionBody\Analyzers\UseExpressionBodyForOperatorsDiagnosticAnalyzer.cs" />
<Compile Include="UseExpressionBody\CodeFixProviders\UseExpressionBodyForConstructorsCodeFixProvider.cs" />
<Compile Include="UseExpressionBody\CodeFixProviders\UseExpressionBodyForOperatorsCodeFixProvider.cs" />
<Compile Include="AddBraces\CSharpAddBracesCodeFixProvider.cs" />
<Compile Include="AddBraces\CSharpAddBracesDiagnosticAnalyzer.cs" />
<Compile Include="UseCollectionInitializer\CSharpUseCollectionInitializerCodeFixProvider.cs" />
......@@ -403,10 +419,10 @@
<Compile Include="Structure\Providers\SwitchStatementStructureProvider.cs" />
<Compile Include="InlineDeclaration\CSharpInlineDeclarationCodeFixProvider.cs" />
<Compile Include="InlineDeclaration\CSharpInlineDeclarationDiagnosticAnalyzer.cs" />
<Compile Include="UseExpressionBody\Methods\UseExpressionBodyForMethodsCodeFixProvider.cs" />
<Compile Include="UseExpressionBody\Methods\UseExpressionBodyForMethodsDiagnosticAnalyzer.cs" />
<Compile Include="UseExpressionBody\AbstractUseExpressionBodyCodeFixProvider.cs" />
<Compile Include="UseExpressionBody\AbstractUseExpressionBodyDiagnosticAnalyzer.cs" />
<Compile Include="UseExpressionBody\CodeFixProviders\UseExpressionBodyForMethodsCodeFixProvider.cs" />
<Compile Include="UseExpressionBody\Analyzers\UseExpressionBodyForMethodsDiagnosticAnalyzer.cs" />
<Compile Include="UseExpressionBody\CodeFixProviders\AbstractUseExpressionBodyCodeFixProvider.cs" />
<Compile Include="UseExpressionBody\Helpers\AbstractUseExpressionBodyHelper.cs" />
<Compile Include="UseObjectInitializer\CSharpUseObjectInitializerCodeFixProvider.cs" />
<Compile Include="SignatureHelp\TupleConstructionSignatureHelpProvider.cs" />
<Compile Include="UseThrowExpression\CSharpUseThrowExpressionDiagnosticAnalyzer.cs" />
......@@ -488,7 +504,9 @@
<ItemGroup>
<Compile Include="CodeFixes\SpellCheck\CSharpSpellCheckCodeFixProvider.cs" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<Folder Include="UseExpressionBody\Indexers\" />
</ItemGroup>
<Import Project="..\..\..\Compilers\CSharp\CSharpAnalyzerDriver\CSharpAnalyzerDriver.projitems" Label="Shared" />
<Import Project="..\..\..\..\build\Targets\Imports.targets" />
</Project>
\ No newline at end of file
......@@ -3,9 +3,6 @@
using System;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Options;
......@@ -16,24 +13,19 @@ internal abstract class AbstractUseExpressionBodyDiagnosticAnalyzer<TDeclaration
where TDeclaration : SyntaxNode
{
private readonly ImmutableArray<SyntaxKind> _syntaxKinds;
private readonly Option<CodeStyleOption<ExpressionBodyPreference>> _option;
private readonly LocalizableString _expressionBodyTitle;
private readonly LocalizableString _blockBodyTitle;
public override bool OpenFileOnly(Workspace workspace) => false;
private readonly AbstractUseExpressionBodyHelper<TDeclaration> _helper;
protected AbstractUseExpressionBodyDiagnosticAnalyzer(
string diagnosticId,
LocalizableString expressionBodyTitle,
LocalizableString blockBodyTitle,
ImmutableArray<SyntaxKind> syntaxKinds,
Option<CodeStyleOption<ExpressionBodyPreference>> option)
: base(diagnosticId, expressionBodyTitle)
AbstractUseExpressionBodyHelper<TDeclaration> helper)
: base(diagnosticId, helper.UseExpressionBodyTitle)
{
_syntaxKinds = syntaxKinds;
_option = option;
_expressionBodyTitle = expressionBodyTitle;
_blockBodyTitle = blockBodyTitle;
_helper = helper;
}
public override DiagnosticAnalyzerCategory GetAnalyzerCategory() => DiagnosticAnalyzerCategory.SemanticDocumentAnalysis;
......@@ -59,114 +51,43 @@ private void AnalyzeSyntax(SyntaxNodeAnalysisContext context)
}
}
internal virtual Diagnostic AnalyzeSyntax(OptionSet optionSet, TDeclaration declaration)
private Diagnostic AnalyzeSyntax(OptionSet optionSet, TDeclaration declaration)
{
// Note: we will always offer to convert a block to an expression-body (and vice versa)
// if possible. All the user preference does is determine if we show them anything in
// the UI (i.e. suggestion dots, or a squiggle) to let them know that they can make the
// change.
//
// This way, users can turn off the option so they don't get notified, but they can still
// make the transformation on a case by case basis.
//
// Note: if we decide to hide any adornments, then we also broaden the location where the
// fix is available. That way the user can go to any place in the member and choose to
// convert it. Otherwise, they'd have no idea what the 'right' location was to invoke
// the conversion.
//
// Also, if the diagnostic is hidden, we'll lower the priority of the code action. We
// always want it to be available. But we don't want it to override issues that are
// actually being reported in the UI.
var preferExpressionBodiedOption = optionSet.GetOption(_option);
var expressionBody = GetExpressionBody(declaration);
if (expressionBody == null)
var preferExpressionBodiedOption = optionSet.GetOption(_helper.Option);
var severity = preferExpressionBodiedOption.Notification.Value;
if (_helper.CanOfferUseExpressionBody(optionSet, declaration, forAnalyzer: true))
{
// They don't have an expression body. See if we can convert into one.
// If so, offer the conversion (with the proper severity depending on their options).
var options = declaration.SyntaxTree.Options;
var body = GetBody(declaration);
if (body.TryConvertToExpressionBody(options, ExpressionBodyPreference.WhenOnSingleLine, out var expressionWhenOnSingleLine, out var semicolonWhenOnSingleLine))
{
// See if it can be converted to an expression and is on a single line. If so,
// we'll show the diagnostic if either 'use expression body' preference is set.
var severity =
preferExpressionBodiedOption.Value == ExpressionBodyPreference.WhenOnSingleLine || preferExpressionBodiedOption.Value == ExpressionBodyPreference.WhenPossible
? preferExpressionBodiedOption.Notification.Value
: DiagnosticSeverity.Hidden;
return GetDiagnostic(declaration, severity);
}
if (body.TryConvertToExpressionBody(options, ExpressionBodyPreference.WhenPossible, out var expressionWhenPossible, out var semicolonWhenPossible))
{
// It wasn't an expression that was on a single line. But it was something we
// could convert to an expression body. We'll show the diagnostic only if
// the option to report when possible is set.
var severity =
preferExpressionBodiedOption.Value == ExpressionBodyPreference.WhenPossible
? preferExpressionBodiedOption.Notification.Value
: DiagnosticSeverity.Hidden;
return GetDiagnostic(declaration, severity);
}
// Can't be converted.
return null;
var location = severity == DiagnosticSeverity.Hidden
? declaration.GetLocation()
: _helper.GetBody(declaration).Statements[0].GetLocation();
var additionalLocations = ImmutableArray.Create(declaration.GetLocation());
return Diagnostic.Create(
CreateDescriptorWithTitle(_helper.UseExpressionBodyTitle, severity, GetCustomTags(severity)),
location, additionalLocations: additionalLocations);
}
else
{
// They have an expression body. These can always be converted into blocks.
// Offer to convert this to a block, with the appropriate severity based
// on their options.
var severity = preferExpressionBodiedOption.Value != ExpressionBodyPreference.Never
? DiagnosticSeverity.Hidden
: preferExpressionBodiedOption.Notification.Value;
if (_helper.CanOfferUseBlockBody(optionSet, declaration, forAnalyzer: true))
{
// They have an expression body. Create a diagnostic to conver it to a block
// if they don't want expression bodies for this member.
var location = severity == DiagnosticSeverity.Hidden
? declaration.GetLocation()
: expressionBody.GetLocation();
: _helper.GetExpressionBody(declaration).GetLocation();
var additionalLocations = ImmutableArray.Create(declaration.GetLocation());
return Diagnostic.Create(
CreateDescriptorWithTitle(_blockBodyTitle, severity, GetCustomTags(severity)),
CreateDescriptorWithTitle(_helper.UseBlockBodyTitle, severity, GetCustomTags(severity)),
location, additionalLocations: additionalLocations);
}
}
private Diagnostic GetDiagnostic(TDeclaration declaration, DiagnosticSeverity severity)
{
var location = severity == DiagnosticSeverity.Hidden
? declaration.GetLocation()
: GetBody(declaration).Statements[0].GetLocation();
var additionalLocations = ImmutableArray.Create(declaration.GetLocation());
return Diagnostic.Create(
CreateDescriptorWithTitle(_expressionBodyTitle, severity, GetCustomTags(severity)),
location, additionalLocations: additionalLocations);
return null;
}
private static string[] GetCustomTags(DiagnosticSeverity severity)
=> severity == DiagnosticSeverity.Hidden
? new[] { WellKnownDiagnosticTags.NotConfigurable }
: Array.Empty<string>();
protected static BlockSyntax GetBodyFromSingleGetAccessor(AccessorListSyntax accessorList)
{
if (accessorList != null &&
accessorList.Accessors.Count == 1 &&
accessorList.Accessors[0].AttributeLists.Count == 0 &&
accessorList.Accessors[0].IsKind(SyntaxKind.GetAccessorDeclaration))
{
return accessorList.Accessors[0].Body;
}
return null;
}
protected abstract BlockSyntax GetBody(TDeclaration declaration);
protected abstract ArrowExpressionClauseSyntax GetExpressionBody(TDeclaration declaration);
}
}
\ No newline at end of file
// 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.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
internal class UseExpressionBodyForAccessorsDiagnosticAnalyzer :
AbstractUseExpressionBodyDiagnosticAnalyzer<AccessorDeclarationSyntax>
{
private readonly UseExpressionBodyForPropertiesDiagnosticAnalyzer propertyAnalyzer = new UseExpressionBodyForPropertiesDiagnosticAnalyzer();
private readonly UseExpressionBodyForIndexersDiagnosticAnalyzer indexerAnalyzer = new UseExpressionBodyForIndexersDiagnosticAnalyzer();
public UseExpressionBodyForAccessorsDiagnosticAnalyzer()
: base(IDEDiagnosticIds.UseExpressionBodyForAccessorsDiagnosticId,
ImmutableArray.Create(SyntaxKind.GetAccessorDeclaration, SyntaxKind.SetAccessorDeclaration),
new UseExpressionBodyForAccessorsHelper())
{
}
}
}
\ No newline at end of file
// 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.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
......@@ -13,17 +12,9 @@ internal class UseExpressionBodyForConstructorsDiagnosticAnalyzer :
{
public UseExpressionBodyForConstructorsDiagnosticAnalyzer()
: base(IDEDiagnosticIds.UseExpressionBodyForConstructorsDiagnosticId,
new LocalizableResourceString(nameof(FeaturesResources.Use_expression_body_for_constructors), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
new LocalizableResourceString(nameof(FeaturesResources.Use_block_body_for_constructors), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
ImmutableArray.Create(SyntaxKind.ConstructorDeclaration),
CSharpCodeStyleOptions.PreferExpressionBodiedConstructors)
new UseExpressionBodyForConstructorsHelper())
{
}
protected override BlockSyntax GetBody(ConstructorDeclarationSyntax declaration)
=> declaration.Body;
protected override ArrowExpressionClauseSyntax GetExpressionBody(ConstructorDeclarationSyntax declaration)
=> declaration.ExpressionBody;
}
}
\ No newline at end of file
// 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.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
......@@ -13,17 +12,9 @@ internal class UseExpressionBodyForConversionOperatorsDiagnosticAnalyzer :
{
public UseExpressionBodyForConversionOperatorsDiagnosticAnalyzer()
: base(IDEDiagnosticIds.UseExpressionBodyForConversionOperatorsDiagnosticId,
new LocalizableResourceString(nameof(FeaturesResources.Use_expression_body_for_operators), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
new LocalizableResourceString(nameof(FeaturesResources.Use_block_body_for_operators), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
ImmutableArray.Create(SyntaxKind.ConversionOperatorDeclaration),
CSharpCodeStyleOptions.PreferExpressionBodiedOperators)
new UseExpressionBodyForConversionOperatorsHelper())
{
}
protected override BlockSyntax GetBody(ConversionOperatorDeclarationSyntax declaration)
=> declaration.Body;
protected override ArrowExpressionClauseSyntax GetExpressionBody(ConversionOperatorDeclarationSyntax declaration)
=> declaration.ExpressionBody;
}
}
\ No newline at end of file
// 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.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
......@@ -13,17 +12,9 @@ internal class UseExpressionBodyForIndexersDiagnosticAnalyzer :
{
public UseExpressionBodyForIndexersDiagnosticAnalyzer()
: base(IDEDiagnosticIds.UseExpressionBodyForIndexersDiagnosticId,
new LocalizableResourceString(nameof(FeaturesResources.Use_expression_body_for_indexers), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
new LocalizableResourceString(nameof(FeaturesResources.Use_block_body_for_indexers), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
ImmutableArray.Create(SyntaxKind.IndexerDeclaration),
CSharpCodeStyleOptions.PreferExpressionBodiedIndexers)
UseExpressionBodyForIndexersHelper.Instance)
{
}
protected override BlockSyntax GetBody(IndexerDeclarationSyntax declaration)
=> GetBodyFromSingleGetAccessor(declaration.AccessorList);
protected override ArrowExpressionClauseSyntax GetExpressionBody(IndexerDeclarationSyntax declaration)
=> declaration.ExpressionBody;
}
}
\ No newline at end of file
// 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.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
......@@ -13,17 +12,9 @@ internal class UseExpressionBodyForMethodsDiagnosticAnalyzer :
{
public UseExpressionBodyForMethodsDiagnosticAnalyzer()
: base(IDEDiagnosticIds.UseExpressionBodyForMethodsDiagnosticId,
new LocalizableResourceString(nameof(FeaturesResources.Use_expression_body_for_methods), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
new LocalizableResourceString(nameof(FeaturesResources.Use_block_body_for_methods), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
ImmutableArray.Create(SyntaxKind.MethodDeclaration),
CSharpCodeStyleOptions.PreferExpressionBodiedMethods)
new UseExpressionBodyForMethodsHelper())
{
}
protected override BlockSyntax GetBody(MethodDeclarationSyntax declaration)
=> declaration.Body;
protected override ArrowExpressionClauseSyntax GetExpressionBody(MethodDeclarationSyntax declaration)
=> declaration.ExpressionBody;
}
}
\ No newline at end of file
// 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.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
......@@ -13,17 +12,9 @@ internal class UseExpressionBodyForOperatorsDiagnosticAnalyzer :
{
public UseExpressionBodyForOperatorsDiagnosticAnalyzer()
: base(IDEDiagnosticIds.UseExpressionBodyForOperatorsDiagnosticId,
new LocalizableResourceString(nameof(FeaturesResources.Use_expression_body_for_operators), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
new LocalizableResourceString(nameof(FeaturesResources.Use_block_body_for_operators), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
ImmutableArray.Create(SyntaxKind.OperatorDeclaration),
CSharpCodeStyleOptions.PreferExpressionBodiedOperators)
new UseExpressionBodyForOperatorsHelper())
{
}
protected override BlockSyntax GetBody(OperatorDeclarationSyntax declaration)
=> declaration.Body;
protected override ArrowExpressionClauseSyntax GetExpressionBody(OperatorDeclarationSyntax declaration)
=> declaration.ExpressionBody;
}
}
\ No newline at end of file
// 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.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
......@@ -13,17 +12,9 @@ internal class UseExpressionBodyForPropertiesDiagnosticAnalyzer :
{
public UseExpressionBodyForPropertiesDiagnosticAnalyzer()
: base(IDEDiagnosticIds.UseExpressionBodyForPropertiesDiagnosticId,
new LocalizableResourceString(nameof(FeaturesResources.Use_expression_body_for_properties), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
new LocalizableResourceString(nameof(FeaturesResources.Use_block_body_for_properties), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
ImmutableArray.Create(SyntaxKind.PropertyDeclaration),
CSharpCodeStyleOptions.PreferExpressionBodiedProperties)
UseExpressionBodyForPropertiesHelper.Instance)
{
}
protected override BlockSyntax GetBody(PropertyDeclarationSyntax declaration)
=> GetBodyFromSingleGetAccessor(declaration.AccessorList);
protected override ArrowExpressionClauseSyntax GetExpressionBody(PropertyDeclarationSyntax declaration)
=> declaration.ExpressionBody;
}
}
\ No newline at end of file
// 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.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody
{
internal abstract partial class AbstractUseExpressionBodyCodeFixProvider<TDeclaration> :
SyntaxEditorBasedCodeFixProvider
where TDeclaration : SyntaxNode
{
private readonly AbstractUseExpressionBodyHelper<TDeclaration> _helper;
public sealed override ImmutableArray<string> FixableDiagnosticIds { get; }
protected AbstractUseExpressionBodyCodeFixProvider(
string diagnosticId,
AbstractUseExpressionBodyHelper<TDeclaration> helper)
{
FixableDiagnosticIds = ImmutableArray.Create(diagnosticId);
_helper = helper;
}
protected override bool IncludeDiagnosticDuringFixAll(Diagnostic diagnostic)
=> diagnostic.Severity != DiagnosticSeverity.Hidden;
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
{
var diagnostic = context.Diagnostics.First();
var documentOptionSet = await context.Document.GetOptionsAsync(context.CancellationToken).ConfigureAwait(false);
var priority = diagnostic.Severity == DiagnosticSeverity.Hidden
? CodeActionPriority.Low
: CodeActionPriority.Medium;
context.RegisterCodeFix(
new MyCodeAction(diagnostic.GetMessage(), priority, c => FixAsync(context.Document, diagnostic, c)),
diagnostic);
}
protected override async Task FixAllAsync(
Document document, ImmutableArray<Diagnostic> diagnostics,
SyntaxEditor editor, CancellationToken cancellationToken)
{
var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
foreach (var diagnostic in diagnostics)
{
cancellationToken.ThrowIfCancellationRequested();
AddEdits(editor, diagnostic, options, cancellationToken);
}
}
private void AddEdits(
SyntaxEditor editor, Diagnostic diagnostic,
OptionSet options, CancellationToken cancellationToken)
{
var declarationLocation = diagnostic.AdditionalLocations[0];
var declaration = (TDeclaration)declarationLocation.FindNode(cancellationToken);
var updatedDeclaration = _helper.Update(declaration, options)
.WithAdditionalAnnotations(Formatter.Annotation);
editor.ReplaceNode(declaration, updatedDeclaration);
}
private class MyCodeAction : CodeAction.DocumentChangeAction
{
internal override CodeActionPriority Priority { get; }
public MyCodeAction(string title, CodeActionPriority priority, Func<CancellationToken, Task<Document>> createChangedDocument)
: base(title, createChangedDocument)
{
this.Priority = priority;
}
}
}
}
\ No newline at end of file
......@@ -13,31 +13,8 @@ internal class UseExpressionBodyForAccessorsCodeFixProvider : AbstractUseExpress
{
public UseExpressionBodyForAccessorsCodeFixProvider()
: base(IDEDiagnosticIds.UseExpressionBodyForAccessorsDiagnosticId,
CSharpCodeStyleOptions.PreferExpressionBodiedAccessors,
FeaturesResources.Use_expression_body_for_accessors,
FeaturesResources.Use_block_body_for_accessors)
new UseExpressionBodyForAccessorsHelper())
{
}
protected override SyntaxToken GetSemicolonToken(AccessorDeclarationSyntax declaration)
=> declaration.SemicolonToken;
protected override ArrowExpressionClauseSyntax GetExpressionBody(AccessorDeclarationSyntax declaration)
=> declaration.ExpressionBody;
protected override BlockSyntax GetBody(AccessorDeclarationSyntax declaration)
=> declaration.Body;
protected override AccessorDeclarationSyntax WithSemicolonToken(AccessorDeclarationSyntax declaration, SyntaxToken token)
=> declaration.WithSemicolonToken(token);
protected override AccessorDeclarationSyntax WithExpressionBody(AccessorDeclarationSyntax declaration, ArrowExpressionClauseSyntax expressionBody)
=> declaration.WithExpressionBody(expressionBody);
protected override AccessorDeclarationSyntax WithBody(AccessorDeclarationSyntax declaration, BlockSyntax body)
=> declaration.WithBody(body);
protected override bool CreateReturnStatementForExpression(AccessorDeclarationSyntax declaration)
=> declaration.IsKind(SyntaxKind.GetAccessorDeclaration);
}
}
\ No newline at end of file
// 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.Composition;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody
{
[ExportCodeFixProvider(LanguageNames.CSharp), Shared]
internal class UseExpressionBodyForConstructorsCodeFixProvider : AbstractUseExpressionBodyCodeFixProvider<ConstructorDeclarationSyntax>
{
public UseExpressionBodyForConstructorsCodeFixProvider()
: base(IDEDiagnosticIds.UseExpressionBodyForConstructorsDiagnosticId,
new UseExpressionBodyForConstructorsHelper())
{
}
}
}
\ No newline at end of file
// 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.Composition;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody
{
[ExportCodeFixProvider(LanguageNames.CSharp), Shared]
internal class UseExpressionBodyForConversionOperatorsCodeFixProvider : AbstractUseExpressionBodyCodeFixProvider<ConversionOperatorDeclarationSyntax>
{
public UseExpressionBodyForConversionOperatorsCodeFixProvider()
: base(IDEDiagnosticIds.UseExpressionBodyForConversionOperatorsDiagnosticId,
new UseExpressionBodyForConversionOperatorsHelper())
{
}
}
}
\ No newline at end of file
// 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
{
[ExportCodeFixProvider(LanguageNames.CSharp), Shared]
internal class UseExpressionBodyForIndexersCodeFixProvider : AbstractUseExpressionBodyCodeFixProvider<IndexerDeclarationSyntax>
{
public UseExpressionBodyForIndexersCodeFixProvider()
: base(IDEDiagnosticIds.UseExpressionBodyForIndexersDiagnosticId,
UseExpressionBodyForIndexersHelper.Instance)
{
}
}
}
\ No newline at end of file
// 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.Composition;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody
{
[ExportCodeFixProvider(LanguageNames.CSharp), Shared]
internal class UseExpressionBodyForMethodsCodeFixProvider : AbstractUseExpressionBodyCodeFixProvider<MethodDeclarationSyntax>
{
public UseExpressionBodyForMethodsCodeFixProvider()
: base(IDEDiagnosticIds.UseExpressionBodyForMethodsDiagnosticId,
new UseExpressionBodyForMethodsHelper())
{
}
}
}
\ No newline at end of file
// 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.Composition;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody
{
[ExportCodeFixProvider(LanguageNames.CSharp), Shared]
internal class UseExpressionBodyForOperatorsCodeFixProvider : AbstractUseExpressionBodyCodeFixProvider<OperatorDeclarationSyntax>
{
public UseExpressionBodyForOperatorsCodeFixProvider()
: base(IDEDiagnosticIds.UseExpressionBodyForOperatorsDiagnosticId,
new UseExpressionBodyForOperatorsHelper())
{
}
}
}
\ No newline at end of file
// 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.Composition;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody
{
[ExportCodeFixProvider(LanguageNames.CSharp), Shared]
internal class UseExpressionBodyForPropertiesCodeFixProvider : AbstractUseExpressionBodyCodeFixProvider<PropertyDeclarationSyntax>
{
public UseExpressionBodyForPropertiesCodeFixProvider()
: base(IDEDiagnosticIds.UseExpressionBodyForPropertiesDiagnosticId,
UseExpressionBodyForPropertiesHelper.Instance)
{
}
}
}
\ No newline at end of file
// 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.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Options;
namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody
{
internal abstract class AbstractUseExpressionBodyCodeRefactoringProvider<TDeclaration> :
CodeRefactoringProvider
where TDeclaration : SyntaxNode
{
private readonly AbstractUseExpressionBodyHelper<TDeclaration> _helper;
protected AbstractUseExpressionBodyCodeRefactoringProvider(
AbstractUseExpressionBodyHelper<TDeclaration> helper)
{
_helper = helper;
}
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
{
if (context.Span.Length > 0)
{
return;
}
var position = context.Span.Start;
var document = context.Document;
var cancellationToken = context.CancellationToken;
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var node = root.FindToken(position).Parent;
if (node == null)
{
return;
}
var containingLambda = node.FirstAncestorOrSelf<LambdaExpressionSyntax>();
if (containingLambda != null &&
node.AncestorsAndSelf().Contains(containingLambda.Body))
{
// don't offer inside a lambda. Lambdas can be quite large, and it will be very noisy
// inside the body of one to be offering to use a block/expression body for the containing
// class member.
return;
}
var declaration = node.FirstAncestorOrSelf<TDeclaration>();
if (declaration == null)
{
return;
}
var optionSet = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
if (_helper.CanOfferUseExpressionBody(optionSet, declaration, forAnalyzer: false))
{
context.RegisterRefactoring(new MyCodeAction(
_helper.UseExpressionBodyTitle.ToString(),
c => UpdateDocumentAsync(document, root, declaration, optionSet, c)));
}
if (_helper.CanOfferUseBlockBody(optionSet, declaration, forAnalyzer: false))
{
context.RegisterRefactoring(new MyCodeAction(
_helper.UseBlockBodyTitle.ToString(),
c => UpdateDocumentAsync(document, root, declaration, optionSet, c)));
}
}
private Task<Document> UpdateDocumentAsync(
Document document, SyntaxNode root, TDeclaration declaration,
DocumentOptionSet options, CancellationToken cancellationToken)
{
var updatedDeclaration = _helper.Update(declaration, options)
.WithAdditionalAnnotations(Formatter.Annotation);
var newRoot = root.ReplaceNode(declaration, updatedDeclaration);
return Task.FromResult(document.WithSyntaxRoot(newRoot));
}
private class MyCodeAction : CodeAction.DocumentChangeAction
{
public MyCodeAction(string title, Func<CancellationToken, Task<Document>> createChangedDocument)
: base(title, createChangedDocument)
{
}
}
}
}
\ No newline at end of file
// 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.Composition;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody
{
[ExportCodeRefactoringProvider(LanguageNames.CSharp), Shared]
internal class UseExpressionBodyForAccessorsCodeRefactoringProvider : AbstractUseExpressionBodyCodeRefactoringProvider<AccessorDeclarationSyntax>
{
public UseExpressionBodyForAccessorsCodeRefactoringProvider()
: base(new UseExpressionBodyForAccessorsHelper())
{
}
}
}
\ No newline at end of file
// 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.Composition;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody
{
[ExportCodeRefactoringProvider(LanguageNames.CSharp), Shared]
internal class UseExpressionBodyForConstructorsCodeRefactoringProvider : AbstractUseExpressionBodyCodeRefactoringProvider<ConstructorDeclarationSyntax>
{
public UseExpressionBodyForConstructorsCodeRefactoringProvider()
: base(new UseExpressionBodyForConstructorsHelper())
{
}
}
}
\ No newline at end of file
// 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.Composition;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody
{
[ExportCodeRefactoringProvider(LanguageNames.CSharp), Shared]
internal class UseExpressionBodyForConversionOperatorsCodeRefactoringProvider : AbstractUseExpressionBodyCodeRefactoringProvider<ConversionOperatorDeclarationSyntax>
{
public UseExpressionBodyForConversionOperatorsCodeRefactoringProvider()
: base(new UseExpressionBodyForConversionOperatorsHelper())
{
}
}
}
\ No newline at end of file
// 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.Composition;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody
{
[ExportCodeRefactoringProvider(LanguageNames.CSharp), Shared]
internal class UseExpressionBodyForIndexersCodeRefactoringProvider : AbstractUseExpressionBodyCodeRefactoringProvider<IndexerDeclarationSyntax>
{
public UseExpressionBodyForIndexersCodeRefactoringProvider()
: base(UseExpressionBodyForIndexersHelper.Instance)
{
}
}
}
\ No newline at end of file
// 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.Composition;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody
{
[ExportCodeRefactoringProvider(LanguageNames.CSharp), Shared]
internal class UseExpressionBodyForMethodsCodeRefactoringProvider : AbstractUseExpressionBodyCodeRefactoringProvider<MethodDeclarationSyntax>
{
public UseExpressionBodyForMethodsCodeRefactoringProvider()
: base(new UseExpressionBodyForMethodsHelper())
{
}
}
}
\ No newline at end of file
// 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.Composition;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody
{
[ExportCodeRefactoringProvider(LanguageNames.CSharp), Shared]
internal class UseExpressionBodyForOperatorsCodeRefactoringProvider : AbstractUseExpressionBodyCodeRefactoringProvider<OperatorDeclarationSyntax>
{
public UseExpressionBodyForOperatorsCodeRefactoringProvider()
: base(new UseExpressionBodyForOperatorsHelper())
{
}
}
}
\ No newline at end of file
// 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.Composition;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody
{
[ExportCodeRefactoringProvider(LanguageNames.CSharp), Shared]
internal class UseExpressionBodyForPropertiesCodeRefactoringProvider : AbstractUseExpressionBodyCodeRefactoringProvider<PropertyDeclarationSyntax>
{
public UseExpressionBodyForPropertiesCodeRefactoringProvider()
: base(UseExpressionBodyForPropertiesHelper.Instance)
{
}
}
}
\ No newline at end of file
// 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.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody
{
internal abstract partial class AbstractUseExpressionBodyCodeFixProvider<TDeclaration> :
SyntaxEditorBasedCodeFixProvider
/// <summary>
/// Helper class that allows us to share lots of logic between the diagnostic analyzer and the
/// code refactoring provider. Those can't share a common base class due to their own inheritance
/// requirements with <see cref="DiagnosticAnalyzer"/> and <see cref="CodeRefactoringProvider"/>.
/// </summary>
internal abstract class AbstractUseExpressionBodyHelper<TDeclaration>
where TDeclaration : SyntaxNode
{
private readonly Option<CodeStyleOption<ExpressionBodyPreference>> _option;
private readonly string _useExpressionBodyTitle;
private readonly string _useBlockBodyTitle;
public sealed override ImmutableArray<string> FixableDiagnosticIds { get; }
protected AbstractUseExpressionBodyCodeFixProvider(
string diagnosticId,
Option<CodeStyleOption<ExpressionBodyPreference>> option,
string useExpressionBodyTitle,
string useBlockBodyTitle)
public readonly Option<CodeStyleOption<ExpressionBodyPreference>> Option;
public readonly LocalizableString UseExpressionBodyTitle;
public readonly LocalizableString UseBlockBodyTitle;
protected AbstractUseExpressionBodyHelper(
LocalizableString useExpressionBodyTitle,
LocalizableString useBlockBodyTitle,
Option<CodeStyleOption<ExpressionBodyPreference>> option)
{
FixableDiagnosticIds = ImmutableArray.Create(diagnosticId);
_option = option;
_useExpressionBodyTitle = useExpressionBodyTitle;
_useBlockBodyTitle = useBlockBodyTitle;
Option = option;
UseExpressionBodyTitle = useExpressionBodyTitle;
UseBlockBodyTitle = useBlockBodyTitle;
}
protected override bool IncludeDiagnosticDuringFixAll(Diagnostic diagnostic)
=> diagnostic.Severity != DiagnosticSeverity.Hidden;
public abstract BlockSyntax GetBody(TDeclaration declaration);
public abstract ArrowExpressionClauseSyntax GetExpressionBody(TDeclaration declaration);
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
protected static BlockSyntax GetBodyFromSingleGetAccessor(AccessorListSyntax accessorList)
{
var diagnostic = context.Diagnostics.First();
var documentOptionSet = await context.Document.GetOptionsAsync(context.CancellationToken).ConfigureAwait(false);
var priority = diagnostic.Severity == DiagnosticSeverity.Hidden
? CodeActionPriority.Low
: CodeActionPriority.Medium;
if (accessorList != null &&
accessorList.Accessors.Count == 1 &&
accessorList.Accessors[0].AttributeLists.Count == 0 &&
accessorList.Accessors[0].IsKind(SyntaxKind.GetAccessorDeclaration))
{
return accessorList.Accessors[0].Body;
}
context.RegisterCodeFix(
new MyCodeAction(diagnostic.GetMessage(), priority, c => FixAsync(context.Document, diagnostic, c)),
diagnostic);
return null;
}
protected override async Task FixAllAsync(
Document document, ImmutableArray<Diagnostic> diagnostics,
SyntaxEditor editor, CancellationToken cancellationToken)
public virtual bool CanOfferUseExpressionBody(
OptionSet optionSet, TDeclaration declaration, bool forAnalyzer)
{
var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
var preference = optionSet.GetOption(this.Option).Value;
var userPrefersExpressionBodies = preference != ExpressionBodyPreference.Never;
foreach (var diagnostic in diagnostics)
// If the user likes expression bodies, then we offer expression bodies from the diagnostic analyzer.
// If the user does not like expression bodies then we offer expression bodies from the refactoring provider.
if (userPrefersExpressionBodies == forAnalyzer)
{
cancellationToken.ThrowIfCancellationRequested();
AddEdits(editor, diagnostic, options, cancellationToken);
var expressionBody = this.GetExpressionBody(declaration);
if (expressionBody == null)
{
// They don't have an expression body. See if we could convert the block they
// have into one.
var options = declaration.SyntaxTree.Options;
var body = this.GetBody(declaration);
if (body.TryConvertToExpressionBody(options, preference,
out var expressionWhenOnSingleLine, out var semicolonWhenOnSingleLine))
{
return true;
}
}
}
return false;
}
private void AddEdits(
SyntaxEditor editor, Diagnostic diagnostic,
OptionSet options, CancellationToken cancellationToken)
public virtual bool CanOfferUseBlockBody(
OptionSet optionSet, TDeclaration declaration, bool forAnalyzer)
{
var declarationLocation = diagnostic.AdditionalLocations[0];
var declaration = (TDeclaration)declarationLocation.FindNode(cancellationToken);
var preference = optionSet.GetOption(this.Option).Value;
var userPrefersBlockBodies = preference == ExpressionBodyPreference.Never;
var updatedDeclaration = this.Update(declaration, options)
.WithAdditionalAnnotations(Formatter.Annotation);
// If the user likes block bodies, then we offer block bodies from the diagnostic analyzer.
// If the user does not like block bodies then we offer block bodies from the refactoring provider.
if (userPrefersBlockBodies == forAnalyzer)
{
// If we have an expression body, we can always convert it to a block body.
return this.GetExpressionBody(declaration) != null;
}
editor.ReplaceNode(declaration, updatedDeclaration);
return false;
}
private TDeclaration Update(TDeclaration declaration, OptionSet options)
public TDeclaration Update(TDeclaration declaration, OptionSet options)
{
var preferExpressionBody = GetBody(declaration) != null;
if (preferExpressionBody)
......@@ -116,8 +128,6 @@ private TDeclaration Update(TDeclaration declaration, OptionSet options)
protected abstract bool CreateReturnStatementForExpression(TDeclaration declaration);
protected abstract SyntaxToken GetSemicolonToken(TDeclaration declaration);
protected abstract ArrowExpressionClauseSyntax GetExpressionBody(TDeclaration declaration);
protected abstract BlockSyntax GetBody(TDeclaration declaration);
protected abstract TDeclaration WithSemicolonToken(TDeclaration declaration, SyntaxToken token);
protected abstract TDeclaration WithExpressionBody(TDeclaration declaration, ArrowExpressionClauseSyntax expressionBody);
......@@ -166,16 +176,5 @@ protected virtual TDeclaration WithAccessorList(TDeclaration declaration, Access
{
throw new NotImplementedException();
}
private class MyCodeAction : CodeAction.DocumentChangeAction
{
internal override CodeActionPriority Priority { get; }
public MyCodeAction(string title, CodeActionPriority priority, Func<CancellationToken, Task<Document>> createChangedDocument)
: base(title, createChangedDocument)
{
this.Priority = priority;
}
}
}
}
\ No newline at end of file
// 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.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
......@@ -8,54 +9,92 @@
namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
internal class UseExpressionBodyForAccessorsDiagnosticAnalyzer :
AbstractUseExpressionBodyDiagnosticAnalyzer<AccessorDeclarationSyntax>
internal class UseExpressionBodyForAccessorsHelper :
AbstractUseExpressionBodyHelper<AccessorDeclarationSyntax>
{
private readonly UseExpressionBodyForPropertiesDiagnosticAnalyzer propertyAnalyzer = new UseExpressionBodyForPropertiesDiagnosticAnalyzer();
private readonly UseExpressionBodyForIndexersDiagnosticAnalyzer indexerAnalyzer = new UseExpressionBodyForIndexersDiagnosticAnalyzer();
public UseExpressionBodyForAccessorsDiagnosticAnalyzer()
: base(IDEDiagnosticIds.UseExpressionBodyForAccessorsDiagnosticId,
new LocalizableResourceString(nameof(FeaturesResources.Use_expression_body_for_accessors), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
public UseExpressionBodyForAccessorsHelper()
: base(new LocalizableResourceString(nameof(FeaturesResources.Use_expression_body_for_accessors), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
new LocalizableResourceString(nameof(FeaturesResources.Use_block_body_for_accessors), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
ImmutableArray.Create(SyntaxKind.GetAccessorDeclaration, SyntaxKind.SetAccessorDeclaration),
CSharpCodeStyleOptions.PreferExpressionBodiedAccessors)
{
}
protected override BlockSyntax GetBody(AccessorDeclarationSyntax declaration)
public override BlockSyntax GetBody(AccessorDeclarationSyntax declaration)
=> declaration.Body;
protected override ArrowExpressionClauseSyntax GetExpressionBody(AccessorDeclarationSyntax declaration)
public override ArrowExpressionClauseSyntax GetExpressionBody(AccessorDeclarationSyntax declaration)
=> declaration.ExpressionBody;
internal override Diagnostic AnalyzeSyntax(OptionSet optionSet, AccessorDeclarationSyntax accessor)
public override bool CanOfferUseExpressionBody(
OptionSet optionSet, AccessorDeclarationSyntax accessor, bool forAnalyzer)
{
// We don't want to double report. So don't report a diagnostic if the property/indexer
// analyzer is going to report a diagnostic here.
var grandParent = accessor.Parent.Parent;
if (grandParent.IsKind(SyntaxKind.PropertyDeclaration))
{
var propertyDeclaration = (PropertyDeclarationSyntax)grandParent;
var diagnostic = propertyAnalyzer.AnalyzeSyntax(optionSet, propertyDeclaration);
if (diagnostic != null && diagnostic.Severity != DiagnosticSeverity.Hidden)
if (UseExpressionBodyForPropertiesHelper.Instance.CanOfferUseExpressionBody(
optionSet, propertyDeclaration, forAnalyzer))
{
return null;
return false;
}
}
else if (grandParent.IsKind(SyntaxKind.IndexerDeclaration))
{
var indexerDeclaration = (IndexerDeclarationSyntax)grandParent;
var diagnostic = indexerAnalyzer.AnalyzeSyntax(optionSet, indexerDeclaration);
if (diagnostic != null && diagnostic.Severity != DiagnosticSeverity.Hidden)
if (UseExpressionBodyForIndexersHelper.Instance.CanOfferUseExpressionBody(
optionSet, indexerDeclaration, forAnalyzer))
{
return null;
return false;
}
}
return base.AnalyzeSyntax(optionSet, accessor);
return base.CanOfferUseExpressionBody(optionSet, accessor, forAnalyzer);
}
public override bool CanOfferUseBlockBody(
OptionSet optionSet, AccessorDeclarationSyntax accessor, bool forAnalyzer)
{
var grandParent = accessor.Parent.Parent;
if (grandParent.IsKind(SyntaxKind.PropertyDeclaration))
{
var propertyDeclaration = (PropertyDeclarationSyntax)grandParent;
if (UseExpressionBodyForPropertiesHelper.Instance.CanOfferUseBlockBody(
optionSet, propertyDeclaration, forAnalyzer))
{
return false;
}
}
else if (grandParent.IsKind(SyntaxKind.IndexerDeclaration))
{
var indexerDeclaration = (IndexerDeclarationSyntax)grandParent;
if (UseExpressionBodyForIndexersHelper.Instance.CanOfferUseBlockBody(
optionSet, indexerDeclaration, forAnalyzer))
{
return false;
}
}
return base.CanOfferUseBlockBody(optionSet, accessor, forAnalyzer);
}
protected override SyntaxToken GetSemicolonToken(AccessorDeclarationSyntax declaration)
=> declaration.SemicolonToken;
protected override AccessorDeclarationSyntax WithSemicolonToken(AccessorDeclarationSyntax declaration, SyntaxToken token)
=> declaration.WithSemicolonToken(token);
protected override AccessorDeclarationSyntax WithExpressionBody(AccessorDeclarationSyntax declaration, ArrowExpressionClauseSyntax expressionBody)
=> declaration.WithExpressionBody(expressionBody);
protected override AccessorDeclarationSyntax WithBody(AccessorDeclarationSyntax declaration, BlockSyntax body)
=> declaration.WithBody(body);
protected override bool CreateReturnStatementForExpression(AccessorDeclarationSyntax declaration)
=> declaration.IsKind(SyntaxKind.GetAccessorDeclaration);
}
}
\ No newline at end of file
// 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.Composition;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody
{
[ExportCodeFixProvider(LanguageNames.CSharp), Shared]
internal class UseExpressionBodyForConstructorsCodeFixProvider : AbstractUseExpressionBodyCodeFixProvider<ConstructorDeclarationSyntax>
internal class UseExpressionBodyForConstructorsHelper :
AbstractUseExpressionBodyHelper<ConstructorDeclarationSyntax>
{
public UseExpressionBodyForConstructorsCodeFixProvider()
: base(IDEDiagnosticIds.UseExpressionBodyForConstructorsDiagnosticId,
CSharpCodeStyleOptions.PreferExpressionBodiedConstructors,
FeaturesResources.Use_expression_body_for_constructors,
FeaturesResources.Use_block_body_for_constructors)
public UseExpressionBodyForConstructorsHelper()
: base(new LocalizableResourceString(nameof(FeaturesResources.Use_expression_body_for_constructors), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
new LocalizableResourceString(nameof(FeaturesResources.Use_block_body_for_constructors), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
CSharpCodeStyleOptions.PreferExpressionBodiedConstructors)
{
}
protected override SyntaxToken GetSemicolonToken(ConstructorDeclarationSyntax declaration)
=> declaration.SemicolonToken;
public override BlockSyntax GetBody(ConstructorDeclarationSyntax declaration)
=> declaration.Body;
protected override ArrowExpressionClauseSyntax GetExpressionBody(ConstructorDeclarationSyntax declaration)
public override ArrowExpressionClauseSyntax GetExpressionBody(ConstructorDeclarationSyntax declaration)
=> declaration.ExpressionBody;
protected override BlockSyntax GetBody(ConstructorDeclarationSyntax declaration)
=> declaration.Body;
protected override SyntaxToken GetSemicolonToken(ConstructorDeclarationSyntax declaration)
=> declaration.SemicolonToken;
protected override ConstructorDeclarationSyntax WithSemicolonToken(ConstructorDeclarationSyntax declaration, SyntaxToken token)
=> declaration.WithSemicolonToken(token);
......
// 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.Composition;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody
{
[ExportCodeFixProvider(LanguageNames.CSharp), Shared]
internal class UseExpressionBodyForConversionOperatorsCodeFixProvider : AbstractUseExpressionBodyCodeFixProvider<ConversionOperatorDeclarationSyntax>
internal class UseExpressionBodyForConversionOperatorsHelper :
AbstractUseExpressionBodyHelper<ConversionOperatorDeclarationSyntax>
{
public UseExpressionBodyForConversionOperatorsCodeFixProvider()
: base(IDEDiagnosticIds.UseExpressionBodyForConversionOperatorsDiagnosticId,
CSharpCodeStyleOptions.PreferExpressionBodiedOperators,
FeaturesResources.Use_expression_body_for_operators,
FeaturesResources.Use_block_body_for_operators)
public UseExpressionBodyForConversionOperatorsHelper()
: base(new LocalizableResourceString(nameof(FeaturesResources.Use_expression_body_for_operators), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
new LocalizableResourceString(nameof(FeaturesResources.Use_block_body_for_operators), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
CSharpCodeStyleOptions.PreferExpressionBodiedOperators)
{
}
protected override SyntaxToken GetSemicolonToken(ConversionOperatorDeclarationSyntax declaration)
=> declaration.SemicolonToken;
public override BlockSyntax GetBody(ConversionOperatorDeclarationSyntax declaration)
=> declaration.Body;
protected override ArrowExpressionClauseSyntax GetExpressionBody(ConversionOperatorDeclarationSyntax declaration)
public override ArrowExpressionClauseSyntax GetExpressionBody(ConversionOperatorDeclarationSyntax declaration)
=> declaration.ExpressionBody;
protected override BlockSyntax GetBody(ConversionOperatorDeclarationSyntax declaration)
=> declaration.Body;
protected override SyntaxToken GetSemicolonToken(ConversionOperatorDeclarationSyntax declaration)
=> declaration.SemicolonToken;
protected override ConversionOperatorDeclarationSyntax WithSemicolonToken(ConversionOperatorDeclarationSyntax declaration, SyntaxToken token)
=> declaration.WithSemicolonToken(token);
......@@ -40,5 +36,4 @@ protected override ConversionOperatorDeclarationSyntax WithBody(ConversionOperat
protected override bool CreateReturnStatementForExpression(ConversionOperatorDeclarationSyntax declaration)
=> true;
}
}
\ No newline at end of file
// 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
{
[ExportCodeFixProvider(LanguageNames.CSharp), Shared]
internal class UseExpressionBodyForIndexersCodeFixProvider : AbstractUseExpressionBodyCodeFixProvider<IndexerDeclarationSyntax>
internal class UseExpressionBodyForIndexersHelper :
AbstractUseExpressionBodyHelper<IndexerDeclarationSyntax>
{
public UseExpressionBodyForIndexersCodeFixProvider()
: base(IDEDiagnosticIds.UseExpressionBodyForIndexersDiagnosticId,
CSharpCodeStyleOptions.PreferExpressionBodiedIndexers,
FeaturesResources.Use_expression_body_for_indexers,
FeaturesResources.Use_block_body_for_indexers)
public static readonly UseExpressionBodyForIndexersHelper Instance = new UseExpressionBodyForIndexersHelper();
private UseExpressionBodyForIndexersHelper()
: base(new LocalizableResourceString(nameof(FeaturesResources.Use_expression_body_for_indexers), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
new LocalizableResourceString(nameof(FeaturesResources.Use_block_body_for_indexers), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
CSharpCodeStyleOptions.PreferExpressionBodiedIndexers)
{
}
protected override SyntaxToken GetSemicolonToken(IndexerDeclarationSyntax declaration)
=> declaration.SemicolonToken;
public override BlockSyntax GetBody(IndexerDeclarationSyntax declaration)
=> GetBodyFromSingleGetAccessor(declaration.AccessorList);
protected override ArrowExpressionClauseSyntax GetExpressionBody(IndexerDeclarationSyntax declaration)
public override ArrowExpressionClauseSyntax GetExpressionBody(IndexerDeclarationSyntax declaration)
=> declaration.ExpressionBody;
protected override BlockSyntax GetBody(IndexerDeclarationSyntax declaration)
=> declaration.AccessorList?.Accessors[0].Body;
protected override SyntaxToken GetSemicolonToken(IndexerDeclarationSyntax declaration)
=> declaration.SemicolonToken;
protected override IndexerDeclarationSyntax WithSemicolonToken(IndexerDeclarationSyntax declaration, SyntaxToken token)
=> declaration.WithSemicolonToken(token);
......
// 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.Composition;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody
{
[ExportCodeFixProvider(LanguageNames.CSharp), Shared]
internal class UseExpressionBodyForMethodsCodeFixProvider : AbstractUseExpressionBodyCodeFixProvider<MethodDeclarationSyntax>
internal class UseExpressionBodyForMethodsHelper :
AbstractUseExpressionBodyHelper<MethodDeclarationSyntax>
{
public UseExpressionBodyForMethodsCodeFixProvider()
: base(IDEDiagnosticIds.UseExpressionBodyForMethodsDiagnosticId,
CSharpCodeStyleOptions.PreferExpressionBodiedMethods,
FeaturesResources.Use_expression_body_for_methods,
FeaturesResources.Use_block_body_for_methods)
public UseExpressionBodyForMethodsHelper()
: base(new LocalizableResourceString(nameof(FeaturesResources.Use_expression_body_for_methods), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
new LocalizableResourceString(nameof(FeaturesResources.Use_block_body_for_methods), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
CSharpCodeStyleOptions.PreferExpressionBodiedMethods)
{
}
protected override SyntaxToken GetSemicolonToken(MethodDeclarationSyntax declaration)
=> declaration.SemicolonToken;
public override BlockSyntax GetBody(MethodDeclarationSyntax declaration)
=> declaration.Body;
protected override ArrowExpressionClauseSyntax GetExpressionBody(MethodDeclarationSyntax declaration)
public override ArrowExpressionClauseSyntax GetExpressionBody(MethodDeclarationSyntax declaration)
=> declaration.ExpressionBody;
protected override BlockSyntax GetBody(MethodDeclarationSyntax declaration)
=> declaration.Body;
protected override SyntaxToken GetSemicolonToken(MethodDeclarationSyntax declaration)
=> declaration.SemicolonToken;
protected override MethodDeclarationSyntax WithSemicolonToken(MethodDeclarationSyntax declaration, SyntaxToken token)
=> declaration.WithSemicolonToken(token);
......@@ -41,5 +37,4 @@ protected override MethodDeclarationSyntax WithBody(MethodDeclarationSyntax decl
protected override bool CreateReturnStatementForExpression(MethodDeclarationSyntax declaration)
=> !declaration.ReturnType.IsVoid();
}
}
\ No newline at end of file
// 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.Composition;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody
{
[ExportCodeFixProvider(LanguageNames.CSharp), Shared]
internal class UseExpressionBodyForOperatorsCodeFixProvider : AbstractUseExpressionBodyCodeFixProvider<OperatorDeclarationSyntax>
internal class UseExpressionBodyForOperatorsHelper :
AbstractUseExpressionBodyHelper<OperatorDeclarationSyntax>
{
public UseExpressionBodyForOperatorsCodeFixProvider()
: base(IDEDiagnosticIds.UseExpressionBodyForOperatorsDiagnosticId,
CSharpCodeStyleOptions.PreferExpressionBodiedOperators,
FeaturesResources.Use_expression_body_for_operators,
FeaturesResources.Use_block_body_for_operators)
public UseExpressionBodyForOperatorsHelper()
: base(new LocalizableResourceString(nameof(FeaturesResources.Use_expression_body_for_operators), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
new LocalizableResourceString(nameof(FeaturesResources.Use_block_body_for_operators), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
CSharpCodeStyleOptions.PreferExpressionBodiedOperators)
{
}
protected override SyntaxToken GetSemicolonToken(OperatorDeclarationSyntax declaration)
=> declaration.SemicolonToken;
public override BlockSyntax GetBody(OperatorDeclarationSyntax declaration)
=> declaration.Body;
protected override ArrowExpressionClauseSyntax GetExpressionBody(OperatorDeclarationSyntax declaration)
public override ArrowExpressionClauseSyntax GetExpressionBody(OperatorDeclarationSyntax declaration)
=> declaration.ExpressionBody;
protected override BlockSyntax GetBody(OperatorDeclarationSyntax declaration)
=> declaration.Body;
protected override SyntaxToken GetSemicolonToken(OperatorDeclarationSyntax declaration)
=> declaration.SemicolonToken;
protected override OperatorDeclarationSyntax WithSemicolonToken(OperatorDeclarationSyntax declaration, SyntaxToken token)
=> declaration.WithSemicolonToken(token);
......@@ -40,5 +36,4 @@ protected override OperatorDeclarationSyntax WithBody(OperatorDeclarationSyntax
protected override bool CreateReturnStatementForExpression(OperatorDeclarationSyntax declaration)
=> true;
}
}
\ No newline at end of file
// 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.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Options;
namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody
{
[ExportCodeFixProvider(LanguageNames.CSharp), Shared]
internal class UseExpressionBodyForPropertiesCodeFixProvider : AbstractUseExpressionBodyCodeFixProvider<PropertyDeclarationSyntax>
internal class UseExpressionBodyForPropertiesHelper :
AbstractUseExpressionBodyHelper<PropertyDeclarationSyntax>
{
public UseExpressionBodyForPropertiesCodeFixProvider()
: base(IDEDiagnosticIds.UseExpressionBodyForPropertiesDiagnosticId,
CSharpCodeStyleOptions.PreferExpressionBodiedProperties,
FeaturesResources.Use_expression_body_for_properties,
FeaturesResources.Use_block_body_for_properties)
public static readonly UseExpressionBodyForPropertiesHelper Instance = new UseExpressionBodyForPropertiesHelper();
private UseExpressionBodyForPropertiesHelper()
: base(new LocalizableResourceString(nameof(FeaturesResources.Use_expression_body_for_properties), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
new LocalizableResourceString(nameof(FeaturesResources.Use_block_body_for_properties), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
CSharpCodeStyleOptions.PreferExpressionBodiedProperties)
{
}
protected override SyntaxToken GetSemicolonToken(PropertyDeclarationSyntax declaration)
=> declaration.SemicolonToken;
public override BlockSyntax GetBody(PropertyDeclarationSyntax declaration)
=> GetBodyFromSingleGetAccessor(declaration.AccessorList);
protected override ArrowExpressionClauseSyntax GetExpressionBody(PropertyDeclarationSyntax declaration)
public override ArrowExpressionClauseSyntax GetExpressionBody(PropertyDeclarationSyntax declaration)
=> declaration.ExpressionBody;
protected override BlockSyntax GetBody(PropertyDeclarationSyntax declaration)
=> declaration.AccessorList?.Accessors[0].Body;
protected override SyntaxToken GetSemicolonToken(PropertyDeclarationSyntax declaration)
=> declaration.SemicolonToken;
protected override PropertyDeclarationSyntax WithSemicolonToken(PropertyDeclarationSyntax declaration, SyntaxToken token)
=> declaration.WithSemicolonToken(token);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册