提交 2ea3675b 编写于 作者: G Gen Lu

Merge pull request #8002 from genlu/CaseOperation

Make `ICase` an `IOperation`
......@@ -64,6 +64,10 @@ public override BoundNode Visit(BoundNode node)
if (operation != null)
{
this.nodes.Add(operation);
// Following operations are not bound node, therefore have to be added explicitly:
// 1. IArgument
// 2. IMemberInitializer
// 3. ICase
switch (operation.Kind)
{
case OperationKind.InvocationExpression:
......@@ -74,6 +78,9 @@ public override BoundNode Visit(BoundNode node)
nodes.AddRange(objCreationExp.ConstructorArguments);
nodes.AddRange(objCreationExp.MemberInitializers);
break;
case OperationKind.SwitchStatement:
nodes.AddRange(((ISwitchStatement)operation).Cases);
break;
}
}
return base.Visit(node);
......
......@@ -146,20 +146,50 @@ partial class BoundForEachStatement : IForEachLoopStatement
partial class BoundSwitchStatement : ISwitchStatement
{
private static readonly ConditionalWeakTable<BoundSwitchStatement, object> s_switchSectionsMappings =
new ConditionalWeakTable<BoundSwitchStatement, object>();
IExpression ISwitchStatement.Value => this.BoundExpression;
ImmutableArray<ICase> ISwitchStatement.Cases => this.SwitchSections.As<ICase>();
ImmutableArray<ICase> ISwitchStatement.Cases
{
get
{
return (ImmutableArray<ICase>) s_switchSectionsMappings.GetValue(this,
switchStatement =>
{
return switchStatement.SwitchSections.SelectAsArray(switchSection => (ICase)new SwitchSection(switchSection));
});
}
}
protected override OperationKind StatementKind => OperationKind.SwitchStatement;
}
partial class BoundSwitchSection : ICase
private class SwitchSection : ICase
{
public SwitchSection(BoundSwitchSection boundNode)
{
ImmutableArray<ICaseClause> ICase.Clauses => this.BoundSwitchLabels.As<ICaseClause>();
this.Body = boundNode.Statements.As<IStatement>();
this.Clauses = boundNode.BoundSwitchLabels.As<ICaseClause>();
this.IsInvalid = boundNode.HasErrors;
this.Syntax = boundNode.Syntax;
}
public ImmutableArray<IStatement> Body { get; }
public ImmutableArray<ICaseClause> Clauses { get; }
ImmutableArray<IStatement> ICase.Body => this.Statements.As<IStatement>();
public bool IsInvalid { get; }
protected override OperationKind StatementKind => OperationKind.SwitchSection;
public OperationKind Kind => OperationKind.SwitchSection;
public SyntaxNode Syntax { get; }
}
}
partial class BoundSwitchSection
{
protected override OperationKind StatementKind => OperationKind.None;
}
partial class BoundSwitchLabel : ISingleValueCaseClause
......
......@@ -70,7 +70,7 @@ public interface ISwitchStatement : IStatement
/// <summary>
/// Represents a C# case or VB Case statement.
/// </summary>
public interface ICase : IStatement
public interface ICase : IOperation
{
/// <summary>
/// Clauses of the case. For C# there is one clause per case, but for VB there can be multiple.
......
......@@ -37,6 +37,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Dim operation = TryCast(node, IOperation)
If operation IsNot Nothing Then
Me.nodes.Add(operation)
' Following operations are not bound node, therefore have to be added explicitly:
' 1. IArgument
' 2. IMemberInitializer
' 3. ICase
' 4. ICaseClause with CaseKind == CaseKind.Default (i.e. Case Else)
' 5. IEventAssignmentExpression
Select Case operation.Kind
Case OperationKind.InvocationExpression
Me.nodes.AddRange(DirectCast(operation, IInvocationExpression).ArgumentsInSourceOrder)
......@@ -44,15 +50,19 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Dim objectCreationExpression = DirectCast(operation, IObjectCreationExpression)
Me.nodes.AddRange(objectCreationExpression.ConstructorArguments)
Me.nodes.AddRange(objectCreationExpression.MemberInitializers)
Case OperationKind.SwitchSection
' "Case Else" clause is not a bound node, so it needs to be added explicitly.
Dim caseClauses = DirectCast(operation, ICase).Clauses
Case OperationKind.SwitchStatement
Dim switchStatement = DirectCast(operation, ISwitchStatement)
For Each caseBlock In switchStatement.Cases
Me.nodes.Add(caseBlock)
' "Case Else" clause needs to be added explicitly.
Dim caseClauses = caseBlock.Clauses
If caseClauses.IsSingle Then
Dim caseClause = caseClauses(0)
If caseClause.CaseKind = CaseKind.Default Then
Me.nodes.Add(caseClause)
End If
End If
Next
Case OperationKind.ExpressionStatement
Dim expression = DirectCast(operation, IExpressionStatement).Expression
If expression.Kind = OperationKind.EventAssignmentExpression Then
......
......@@ -64,9 +64,16 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Partial Class BoundSelectStatement
Implements ISwitchStatement
Private Shared ReadOnly s_caseBlocksMappings As New System.Runtime.CompilerServices.ConditionalWeakTable(Of BoundSelectStatement, Object)
Private ReadOnly Property ICases As ImmutableArray(Of ICase) Implements ISwitchStatement.Cases
Get
Return Me.CaseBlocks.As(Of ICase)()
Dim cases = s_caseBlocksMappings.GetValue(Me, Function(boundSelect)
Return boundSelect.CaseBlocks.SelectAsArray(Function(boundCaseBlock)
Return DirectCast(New CaseBlock(boundCaseBlock), ICase)
End Function)
End Function)
Return DirectCast(cases, ImmutableArray(Of ICase))
End Get
End Property
......@@ -79,40 +86,64 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Protected Overrides Function StatementKind() As OperationKind
Return OperationKind.SwitchStatement
End Function
End Class
Partial Class BoundCaseBlock
Private Class CaseBlock
Implements ICase
Private ReadOnly Property IBody As ImmutableArray(Of IStatement) Implements ICase.Body
Private ReadOnly _clauses As ImmutableArray(Of ICaseClause)
Private ReadOnly _body As ImmutableArray(Of IStatement)
Private ReadOnly _isInvalid As Boolean
Private ReadOnly _syntax As SyntaxNode
Public Sub New(boundCaseBlock As BoundCaseBlock)
' `CaseElseClauseSyntax` is bound to `BoundCaseStatement` with an empty list of case clauses,
' so we explicitly create an IOperation node for Case-Else clause to differentiate it from Case clause.
Dim caseStatement = boundCaseBlock.CaseStatement
If caseStatement.CaseClauses.IsEmpty AndAlso caseStatement.Syntax.Kind() = SyntaxKind.CaseElseStatement Then
_clauses = ImmutableArray.Create(Of ICaseClause)(New CaseElse(caseStatement))
Else
_clauses = caseStatement.CaseClauses.As(Of ICaseClause)()
End If
_body = ImmutableArray.Create(Of IStatement)(boundCaseBlock.Body)
_isInvalid = boundCaseBlock.HasErrors
_syntax = boundCaseBlock.Syntax
End Sub
Public ReadOnly Property Body As ImmutableArray(Of IStatement) Implements ICase.Body
Get
Return ImmutableArray.Create(Of IStatement)(Me.Body)
Return _body
End Get
End Property
Private Shared ReadOnly CaseElseMappings As New System.Runtime.CompilerServices.ConditionalWeakTable(Of BoundCaseStatement, Object)
Private ReadOnly Property IClauses As ImmutableArray(Of ICaseClause) Implements ICase.Clauses
Public ReadOnly Property Clauses As ImmutableArray(Of ICaseClause) Implements ICase.Clauses
Get
' `CaseElseClauseSyntax` is bound to `BoundCaseStatement` with an empty list of case clauses,
' so we explicitly create an IOperation node for Case-Else clause to differentiate it from Case clause.
If Me.CaseStatement.CaseClauses.IsEmpty AndAlso Me.CaseStatement.Syntax.Kind() = SyntaxKind.CaseElseStatement Then
Dim caseElse = CaseElseMappings.GetValue(Me.CaseStatement, Function(caseStatement) ImmutableArray.Create(Of ICaseClause)(New CaseElse(caseStatement)))
Return DirectCast(caseElse, ImmutableArray(Of ICaseClause))
End If
Return _clauses
End Get
End Property
Return Me.CaseStatement.CaseClauses.As(Of ICaseClause)()
Public ReadOnly Property IsInvalid As Boolean Implements IOperation.IsInvalid
Get
Return _isInvalid
End Get
End Property
Protected Overrides Function StatementKind() As OperationKind
Public ReadOnly Property Kind As OperationKind Implements IOperation.Kind
Get
Return OperationKind.SwitchSection
End Function
End Get
End Property
Public ReadOnly Property Syntax As SyntaxNode Implements IOperation.Syntax
Get
Return _syntax
End Get
End Property
Private Class CaseElse
Implements ISingleValueCaseClause
Private _boundCaseStatement As BoundCaseStatement
Private ReadOnly _boundCaseStatement As BoundCaseStatement
Public Sub New(boundCaseStatement As BoundCaseStatement)
_boundCaseStatement = boundCaseStatement
......@@ -156,11 +187,17 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Class
End Class
End Class
Partial Class BoundCaseBlock
Protected Overrides Function StatementKind() As OperationKind
Return OperationKind.None
End Function
End Class
Partial Class BoundCaseClause
Implements ICaseClause
Private ReadOnly Property IIsInvalid As Boolean Implements IOperation.IsInvalid
Get
Return Me.HasErrors
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册