提交 6c85ce89 编写于 作者: A Abraham Hosch

Address comments, mostly strong-typing issues.

上级 a2520bae
......@@ -351,6 +351,7 @@
<Compile Include="Organizing\Organizers\StructDeclarationOrganizer.cs" />
<Compile Include="PopulateSwitch\CSharpPopulateSwitchCodeFixProvider.cs" />
<Compile Include="PopulateSwitch\CSharpPopulateSwitchDiagnosticAnalyzer.cs" />
<Compile Include="PopulateSwitch\CSharpPopulateSwitchHelperClass.cs" />
<Compile Include="RemoveUnnecessaryImports\CSharpRemoveUnnecessaryImportsService.cs" />
<Compile Include="RemoveUnnecessaryImports\CSharpRemoveUnnecessaryImportsService.Rewriter.cs" />
<Compile Include="ReplaceMethodWithProperty\CSharpReplaceMethodWithPropertyService.cs" />
......
using System.Collections.Generic;
using System.Composition;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.PopulateSwitch;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Simplification;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis.CSharp.CodeFixes.PopulateSwitch
{
[ExportCodeFixProvider(LanguageNames.CSharp, Name = PredefinedCodeFixProviderNames.PopulateSwitch), Shared]
[ExtensionOrder(After = PredefinedCodeFixProviderNames.ImplementInterface)]
internal class CSharpPopulateSwitchCodeFixProvider : AbstractPopulateSwitchCodeFixProvider<SwitchStatementSyntax>
internal class CSharpPopulateSwitchCodeFixProvider : AbstractPopulateSwitchCodeFixProvider<SwitchStatementSyntax, ExpressionSyntax, SwitchSectionSyntax>
{
protected override SyntaxNode GetSwitchStatementNode(SyntaxNode root, TextSpan span)
protected override SwitchStatementSyntax GetSwitchStatementNode(SyntaxNode root, TextSpan span)
{
var switchExpression = (ExpressionSyntax)root.FindNode(span);
return (SwitchStatementSyntax)switchExpression.Parent;
}
protected override SyntaxNode GetSwitchExpression(SwitchStatementSyntax switchStatement) => switchStatement.Expression;
protected override ExpressionSyntax GetSwitchExpression(SwitchStatementSyntax switchStatement) => switchStatement.Expression;
protected override int InsertPosition(List<SyntaxNode> sections) => sections.Count - 1;
protected override int InsertPosition(List<SwitchSectionSyntax> sections) => sections.Count - 1;
protected override List<SyntaxNode> GetSwitchSections(SwitchStatementSyntax switchStatement) => new List<SyntaxNode>(switchStatement.Sections);
protected override List<SwitchSectionSyntax> GetSwitchSections(SwitchStatementSyntax switchStatement) => new List<SwitchSectionSyntax>(switchStatement.Sections);
protected override SyntaxNode NewSwitchNode(SwitchStatementSyntax switchStatement, List<SyntaxNode> sections) =>
switchStatement.WithSections(SyntaxFactory.List(sections))
.WithAdditionalAnnotations(Formatter.Annotation, Simplifier.Annotation);
protected override SyntaxNode NewSwitchNode(SwitchStatementSyntax switchStatement, List<SwitchSectionSyntax> sections) =>
switchStatement.WithSections(SyntaxFactory.List(sections));
protected override List<SyntaxNode> GetCaseLabels(SwitchStatementSyntax switchStatement, out bool containsDefaultLabel)
{
containsDefaultLabel = false;
var caseLabels = new List<SyntaxNode>();
foreach (var section in switchStatement.Sections)
{
foreach (var label in section.Labels)
{
var caseLabel = label as CaseSwitchLabelSyntax;
if (caseLabel != null)
{
caseLabels.Add(caseLabel.Value);
}
if (label.IsKind(SyntaxKind.DefaultSwitchLabel))
{
containsDefaultLabel = true;
}
}
}
return caseLabels;
}
=> CSharpPopulateSwitchHelperClass.GetCaseLabels(switchStatement, out containsDefaultLabel);
}
}
......@@ -3,14 +3,14 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.Collections.Generic;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.CSharp.PopulateSwitch;
namespace Microsoft.CodeAnalysis.CSharp.Diagnostics.PopulateSwitch
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
internal sealed class CSharpPopulateSwitchDiagnosticAnalyzer : AbstractPopulateSwitchDiagnosticAnalyzerBase<SyntaxKind, SwitchStatementSyntax>
{
private static readonly ImmutableArray<SyntaxKind> s_kindsOfInterest = ImmutableArray.Create(SyntaxKind.SwitchStatement);
protected override ImmutableArray<SyntaxKind> SyntaxKindsOfInterest { get; } = s_kindsOfInterest;
protected override ImmutableArray<SyntaxKind> SyntaxKindsOfInterest { get; } = ImmutableArray.Create(SyntaxKind.SwitchStatement);
protected override SyntaxNode GetExpression(SwitchStatementSyntax switchBlock)
{
......@@ -18,28 +18,6 @@ protected override SyntaxNode GetExpression(SwitchStatementSyntax switchBlock)
}
protected override List<SyntaxNode> GetCaseLabels(SwitchStatementSyntax switchBlock, out bool hasDefaultCase)
{
hasDefaultCase = false;
var caseLabels = new List<SyntaxNode>();
foreach (var section in switchBlock.Sections)
{
foreach (var label in section.Labels)
{
if (label.IsKind(SyntaxKind.CaseSwitchLabel))
{
caseLabels.Add(((CaseSwitchLabelSyntax)label).Value);
}
if (label.IsKind(SyntaxKind.DefaultSwitchLabel))
{
hasDefaultCase = true;
}
}
}
return caseLabels;
}
=> CSharpPopulateSwitchHelperClass.GetCaseLabels(switchBlock, out hasDefaultCase);
}
}
using System.Collections.Generic;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Microsoft.CodeAnalysis.CSharp.PopulateSwitch
{
internal static class CSharpPopulateSwitchHelperClass
{
public static List<SyntaxNode> GetCaseLabels(SwitchStatementSyntax switchStatement, out bool containsDefaultLabel)
{
containsDefaultLabel = false;
var caseLabels = new List<SyntaxNode>();
foreach (var section in switchStatement.Sections)
{
foreach (var label in section.Labels)
{
var caseLabel = label as CaseSwitchLabelSyntax;
if (caseLabel != null)
{
caseLabels.Add(caseLabel.Value);
}
if (label.IsKind(SyntaxKind.DefaultSwitchLabel))
{
containsDefaultLabel = true;
}
}
}
return caseLabels;
}
}
}
\ No newline at end of file
......@@ -8,11 +8,16 @@
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Simplification;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis.CSharp.CodeFixes.PopulateSwitch
{
internal abstract class AbstractPopulateSwitchCodeFixProvider<TSwitchBlockSyntax> : CodeFixProvider where TSwitchBlockSyntax : SyntaxNode
internal abstract class AbstractPopulateSwitchCodeFixProvider<TSwitchBlockSyntax, TExpressionSyntax, TSwitchSectionSyntax> : CodeFixProvider
where TSwitchBlockSyntax : SyntaxNode
where TSwitchSectionSyntax : SyntaxNode
where TExpressionSyntax : SyntaxNode
{
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(IDEDiagnosticIds.PopulateSwitchDiagnosticId);
......@@ -20,35 +25,34 @@ internal abstract class AbstractPopulateSwitchCodeFixProvider<TSwitchBlockSyntax
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
{
var document = context.Document;
var span = context.Span;
var cancellationToken = context.CancellationToken;
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var node = GetSwitchStatementNode(root, span);
context.RegisterCodeFix(
new MyCodeAction(
FeaturesResources.AddMissingSwitchCases,
c => AddMissingSwitchLabelsAsync(document, root, (TSwitchBlockSyntax)node, cancellationToken)),
c => AddMissingSwitchLabelsAsync(context)),
context.Diagnostics);
}
protected abstract SyntaxNode GetSwitchExpression(TSwitchBlockSyntax switchBlock);
protected abstract TExpressionSyntax GetSwitchExpression(TSwitchBlockSyntax switchBlock);
protected abstract int InsertPosition(List<SyntaxNode> sections);
protected abstract int InsertPosition(List<TSwitchSectionSyntax> sections);
protected abstract List<SyntaxNode> GetSwitchSections(TSwitchBlockSyntax switchBlock);
protected abstract List<TSwitchSectionSyntax> GetSwitchSections(TSwitchBlockSyntax switchBlock);
protected abstract SyntaxNode NewSwitchNode(TSwitchBlockSyntax switchBlock, List<SyntaxNode> sections);
protected abstract SyntaxNode NewSwitchNode(TSwitchBlockSyntax switchBlock, List<TSwitchSectionSyntax> sections);
protected abstract SyntaxNode GetSwitchStatementNode(SyntaxNode root, TextSpan span);
protected abstract TSwitchBlockSyntax GetSwitchStatementNode(SyntaxNode root, TextSpan span);
protected abstract List<SyntaxNode> GetCaseLabels(TSwitchBlockSyntax switchBlock, out bool containsDefaultLabel);
private async Task<Document> AddMissingSwitchLabelsAsync(Document document, SyntaxNode root, TSwitchBlockSyntax switchNode, CancellationToken cancellationToken)
private async Task<Document> AddMissingSwitchLabelsAsync(CodeFixContext context)
{
var document = context.Document;
var span = context.Span;
var cancellationToken = context.CancellationToken;
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
var switchNode = GetSwitchStatementNode(root, span);
var enumType = (INamedTypeSymbol)model.GetTypeInfo(GetSwitchExpression(switchNode)).Type;
......@@ -65,7 +69,7 @@ private async Task<Document> AddMissingSwitchLabelsAsync(Document document, Synt
{
var caseLabel = generator.MemberAccessExpression(generator.TypeExpression(enumType), label);
var section = generator.SwitchSection(caseLabel, new List<SyntaxNode> { switchExitStatement });
var section = (TSwitchSectionSyntax)generator.SwitchSection(caseLabel, new List<SyntaxNode> { switchExitStatement });
// ensure that the new cases are above the last section if a default case exists, but below all other sections
if (containsDefaultLabel)
......@@ -80,10 +84,11 @@ private async Task<Document> AddMissingSwitchLabelsAsync(Document document, Synt
if (!containsDefaultLabel)
{
newSections.Add(generator.DefaultSwitchSection(statements));
newSections.Add((TSwitchSectionSyntax)generator.DefaultSwitchSection(statements));
}
var newNode = NewSwitchNode(switchNode, newSections);
var newNode = NewSwitchNode(switchNode, newSections)
.WithAdditionalAnnotations(Formatter.Annotation, Simplifier.Annotation);
var newRoot = root.ReplaceNode(switchNode, newNode);
return document.WithSyntaxRoot(newRoot);
......
......@@ -75,6 +75,8 @@ private bool SwitchIsFullyPopulated(SemanticModel model, TSwitchBlockSyntax node
var symbol = model.GetSymbolInfo(label).Symbol;
if (symbol == null)
{
// something is wrong with the label and the SemanticModel was unable to determine its symbol
// abort analyzer
return true;
}
......@@ -121,9 +123,6 @@ private bool TryPopulateSwitch(SemanticModel model, SyntaxNode node, out Diagnos
return true;
}
public DiagnosticAnalyzerCategory GetAnalyzerCategory()
{
return DiagnosticAnalyzerCategory.SemanticSpanAnalysis;
}
public DiagnosticAnalyzerCategory GetAnalyzerCategory() => DiagnosticAnalyzerCategory.SemanticSpanAnalysis;
}
}
......@@ -116,8 +116,8 @@
<Compile Include="CodeFixes\MoveToTopOfFile\MoveToTopOfFileCodeFixProvider.vb" />
<Compile Include="CodeFixes\OverloadBase\OverloadBaseCodeFixProvider.AddOverloads.vb" />
<Compile Include="CodeFixes\OverloadBase\OverloadBaseCodeFixProvider.vb" />
<Compile Include="CodeFixes\PopulateSwitch\VisualBasicPopulateSwitchCodeFixProvider.vb" />
<Compile Include="CodeFixes\PopulateSwitch\VisualBasicPopulateSwitchDiagnosticAnalyzer.vb" />
<Compile Include="PopulateSwitch\VisualBasicPopulateSwitchCodeFixProvider.vb" />
<Compile Include="PopulateSwitch\VisualBasicPopulateSwitchDiagnosticAnalyzer.vb" />
<Compile Include="CodeFixes\RemoveUnnecessaryCast\RemoveUnnecessaryCastCodeFixProvider.RemoveUnnecessaryCastFixAllProvider.vb" />
<Compile Include="CodeFixes\RemoveUnnecessaryCast\RemoveUnnecessaryCastCodeFixProvider.Rewriter.vb" />
<Compile Include="CodeFixes\RemoveUnnecessaryCast\RemoveUnnecessaryCastCodeFixProvider.vb" />
......@@ -369,6 +369,7 @@
<Compile Include="Organizing\Organizers\TypeBlockOrganizer.vb" />
<Compile Include="Organizing\VisualBasicOrganizerService.Rewriter.vb" />
<Compile Include="Organizing\VisualBasicOrganizerService.vb" />
<Compile Include="PopulateSwitch\VisualBasicPopulateSwitchHelperClass.vb" />
<Compile Include="RemoveUnnecessaryImports\VisualBasicRemoveUnnecessaryImportsService.Rewriter.vb" />
<Compile Include="RemoveUnnecessaryImports\VisualBasicRemoveUnnecessaryImportsService.vb" />
<Compile Include="RemoveUnnecessaryImports\VisualBasicRemoveUnnecessaryImportsService.Visitor.vb" />
......
......@@ -2,24 +2,21 @@
Imports System.Runtime.InteropServices
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.CSharp.CodeFixes.PopulateSwitch
Imports Microsoft.CodeAnalysis.Formatting
Imports Microsoft.CodeAnalysis.Simplification
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.PopulateSwitch
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.PopulateSwitch
<ExportCodeFixProvider(LanguageNames.VisualBasic, Name:=PredefinedCodeFixProviderNames.PopulateSwitch), [Shared]>
<ExtensionOrder(After:=PredefinedCodeFixProviderNames.AddOverloads)>
Partial Friend Class VisualBasicPopulateSwitchCodeFixProvider
Inherits AbstractPopulateSwitchCodeFixProvider(Of SelectBlockSyntax)
Inherits AbstractPopulateSwitchCodeFixProvider(Of SelectBlockSyntax, ExpressionSyntax, CaseBlockSyntax)
Protected Overrides Function GetSwitchExpression(selectBlock As SelectBlockSyntax) As SyntaxNode
Protected Overrides Function GetSwitchExpression(selectBlock As SelectBlockSyntax) As ExpressionSyntax
Return selectBlock.SelectStatement.Expression
End Function
Protected Overrides Function InsertPosition(sections As List(Of SyntaxNode)) As Integer
Protected Overrides Function InsertPosition(sections As List(Of CaseBlockSyntax)) As Integer
Dim cases = sections.OfType(Of CaseBlockSyntax).ToList()
Dim numOfBlocksWithNoStatementsWithElse = 0
......@@ -36,43 +33,21 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.PopulateSwitch
Return numOfBlocksWithNoStatementsWithElse
End Function
Protected Overrides Function GetSwitchSections(selectBlock As SelectBlockSyntax) As List(Of SyntaxNode)
Return New List(Of SyntaxNode)(selectBlock.CaseBlocks)
Protected Overrides Function GetSwitchSections(selectBlock As SelectBlockSyntax) As List(Of CaseBlockSyntax)
Return New List(Of CaseBlockSyntax)(selectBlock.CaseBlocks)
End Function
Protected Overrides Function NewSwitchNode(selectBlock As SelectBlockSyntax, sections As List(Of SyntaxNode)) As SyntaxNode
Return selectBlock.WithCaseBlocks(SyntaxFactory.List(sections)).WithAdditionalAnnotations(Formatter.Annotation, Simplifier.Annotation)
Protected Overrides Function NewSwitchNode(selectBlock As SelectBlockSyntax, sections As List(Of CaseBlockSyntax)) As SyntaxNode
Return selectBlock.WithCaseBlocks(SyntaxFactory.List(sections))
End Function
Protected Overrides Function GetSwitchStatementNode(root As SyntaxNode, span As TextSpan) As SyntaxNode
Protected Overrides Function GetSwitchStatementNode(root As SyntaxNode, span As TextSpan) As SelectBlockSyntax
Dim selectExpression = DirectCast(root.FindNode(span), ExpressionSyntax)
Return DirectCast(selectExpression.Parent.Parent, SelectBlockSyntax)
End Function
Protected Overrides Function GetCaseLabels(selectBlock As SelectBlockSyntax, <Out> ByRef containsDefaultLabel As Boolean) As List(Of SyntaxNode)
containsDefaultLabel = False
Dim caseLabels = New List(Of SyntaxNode)
For Each block In selectBlock.CaseBlocks
For Each caseSyntax In block.CaseStatement.Cases
Dim simpleCaseClause = TryCast(caseSyntax, SimpleCaseClauseSyntax)
If Not simpleCaseClause Is Nothing
caseLabels.Add(simpleCaseClause.Value)
Continue For
End If
If caseSyntax.IsKind(SyntaxKind.ElseCaseClause)
containsDefaultLabel = True
End If
Next
Next
Return caseLabels
Return VisualBasicPopulateSwitchHelperClass.GetCaseLabels(selectBlock, containsDefaultLabel)
End Function
End Class
End Namespace
\ No newline at end of file
......@@ -2,6 +2,7 @@
Imports System.Runtime.InteropServices
Imports Microsoft.CodeAnalysis.Diagnostics
Imports Microsoft.CodeAnalysis.Diagnostics.PopulateSwitch
Imports Microsoft.CodeAnalysis.VisualBasic.PopulateSwitch
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.Diagnostics.PopulateSwitch
......@@ -11,30 +12,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Diagnostics.PopulateSwitch
Inherits AbstractPopulateSwitchDiagnosticAnalyzerBase(Of SyntaxKind, SelectBlockSyntax)
Protected Overrides Function GetCaseLabels(selectBlock As SelectBlockSyntax, <Out> ByRef hasDefaultCase As Boolean) As List(Of SyntaxNode)
Dim caseLabels As New List(Of SyntaxNode)
hasDefaultCase = False
For Each block In selectBlock.CaseBlocks
For Each caseClause In block.CaseStatement.Cases
If caseClause.IsKind(SyntaxKind.SimpleCaseClause)
caseLabels.Add(DirectCast(caseClause, SimpleCaseClauseSyntax).Value)
End If
If caseClause.IsKind(SyntaxKind.ElseCaseClause)
hasDefaultCase = True
End If
Next
Next
Return caseLabels
Return VisualBasicPopulateSwitchHelperClass.GetCaseLabels(selectBlock, hasDefaultCase)
End Function
Private Shared ReadOnly s_kindsOfInterest As ImmutableArray(Of SyntaxKind) = ImmutableArray.Create(SyntaxKind.SelectBlock)
Protected Overrides ReadOnly Property SyntaxKindsOfInterest As ImmutableArray(Of SyntaxKind) = s_kindsOfInterest
Protected Overrides ReadOnly Property SyntaxKindsOfInterest As ImmutableArray(Of SyntaxKind) = ImmutableArray.Create(SyntaxKind.SelectBlock)
Protected Overrides Function GetExpression(selectBlock As SelectBlockSyntax) As SyntaxNode
Return selectBlock.SelectStatement.Expression
End Function
End Class
......
Imports System.Runtime.InteropServices
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.PopulateSwitch
Friend Module VisualBasicPopulateSwitchHelperClass
Public Function GetCaseLabels(selectBlock As SelectBlockSyntax, <Out> ByRef containsDefaultLabel As Boolean) As List(Of SyntaxNode)
containsDefaultLabel = False
Dim caseLabels = New List(Of SyntaxNode)
For Each block In selectBlock.CaseBlocks
For Each caseSyntax In block.CaseStatement.Cases
Dim simpleCaseClause = TryCast(caseSyntax, SimpleCaseClauseSyntax)
If Not simpleCaseClause Is Nothing
caseLabels.Add(simpleCaseClause.Value)
Continue For
End If
If caseSyntax.IsKind(SyntaxKind.ElseCaseClause)
containsDefaultLabel = True
End If
Next
Next
Return caseLabels
End Function
End Module
End Namespace
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册