Enable compound expressions with conversions in them.

上级 79fc0a89
...@@ -272,26 +272,23 @@ Namespace Microsoft.CodeAnalysis.Operations ...@@ -272,26 +272,23 @@ Namespace Microsoft.CodeAnalysis.Operations
End Function End Function
Private Function CreateBoundAssignmentOperatorOperation(boundAssignmentOperator As BoundAssignmentOperator) As IOperation Private Function CreateBoundAssignmentOperatorOperation(boundAssignmentOperator As BoundAssignmentOperator) As IOperation
Dim kind = GetAssignmentKind(boundAssignmentOperator) Dim assignmentInfo = GetAssignmentInfo(boundAssignmentOperator)
Dim isImplicit As Boolean = boundAssignmentOperator.WasCompilerGenerated Dim isImplicit As Boolean = boundAssignmentOperator.WasCompilerGenerated
If kind = OperationKind.CompoundAssignment Then If assignmentInfo.OperationKind = OperationKind.CompoundAssignment Then
' convert Right to IOperation temporarily. we do this to get right operand, operator method and etc
Dim temporaryRight = DirectCast(Create(boundAssignmentOperator.Right), IBinaryOperation)
Dim operatorKind As BinaryOperatorKind = temporaryRight.OperatorKind Dim operatorKind As BinaryOperatorKind = assignmentInfo.OperatorKind
Dim target As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(boundAssignmentOperator.Left)) Dim target As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(boundAssignmentOperator.Left))
' right now, parent of right operand is set to the temporary IOperation, reset the parent ' right now, parent of right operand is set to the temporary IOperation, reset the parent
' we basically need to do this since we skip BoundAssignmentOperator.Right from IOperation tree ' we basically need to do this since we skip BoundAssignmentOperator.Right from IOperation tree
Dim rightOperand = Operation.ResetParentOperation(temporaryRight.RightOperand) Dim value As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(assignmentInfo.RightNode))
Dim value As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() rightOperand)
Dim operatorMethod As IMethodSymbol = temporaryRight.OperatorMethod Dim operatorMethod As IMethodSymbol = assignmentInfo.OperatorMethod
Dim syntax As SyntaxNode = boundAssignmentOperator.Syntax Dim syntax As SyntaxNode = boundAssignmentOperator.Syntax
Dim type As ITypeSymbol = boundAssignmentOperator.Type Dim type As ITypeSymbol = boundAssignmentOperator.Type
Dim constantValue As [Optional](Of Object) = ConvertToOptional(boundAssignmentOperator.ConstantValueOpt) Dim constantValue As [Optional](Of Object) = ConvertToOptional(boundAssignmentOperator.ConstantValueOpt)
Dim isLifted As Boolean = boundAssignmentOperator.Type.IsNullableType() Dim isLifted As Boolean = boundAssignmentOperator.Type.IsNullableType()
Dim isChecked As Boolean = temporaryRight.IsChecked Dim isChecked As Boolean = assignmentInfo.IsChecked
Return New LazyCompoundAssignmentExpression(operatorKind, isLifted, isChecked, target, value, operatorMethod, _semanticModel, syntax, type, constantValue, isImplicit) Return New LazyCompoundAssignmentExpression(operatorKind, isLifted, isChecked, target, value, operatorMethod, _semanticModel, syntax, type, constantValue, isImplicit)
Else Else
Dim target As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(boundAssignmentOperator.Left)) Dim target As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(boundAssignmentOperator.Left))
......
...@@ -12,28 +12,127 @@ Namespace Microsoft.CodeAnalysis.Operations ...@@ -12,28 +12,127 @@ Namespace Microsoft.CodeAnalysis.Operations
Return If(value Is Nothing OrElse value.IsBad, New [Optional](Of Object)(), New [Optional](Of Object)(value.Value)) Return If(value Is Nothing OrElse value.IsBad, New [Optional](Of Object)(), New [Optional](Of Object)(value.Value))
End Function End Function
Private Shared Function GetAssignmentKind(value As BoundAssignmentOperator) As OperationKind Private Shared Function GetAssignmentInfo(value As BoundAssignmentOperator) As (OperationKind As OperationKind, OperatorKind As BinaryOperatorKind, IsChecked As Boolean, InConversion As Conversion, OutConversion As Conversion, RightNode As BoundExpression, OperatorMethod As IMethodSymbol)
Dim identityConversion = New Conversion(Conversions.Identity)
If value.LeftOnTheRightOpt IsNot Nothing Then If value.LeftOnTheRightOpt IsNot Nothing Then
Select Case value.Right.Kind Select Case value.Right.Kind
Case BoundKind.BinaryOperator Case BoundKind.BinaryOperator
Dim rightBinary As BoundBinaryOperator = DirectCast(value.Right, BoundBinaryOperator) Dim rightBinary As BoundBinaryOperator = DirectCast(value.Right, BoundBinaryOperator)
If rightBinary.Left Is value.LeftOnTheRightOpt Then If rightBinary.Left Is value.LeftOnTheRightOpt Then
Return OperationKind.CompoundAssignment Dim operatorKind = Helper.DeriveBinaryOperatorKind(rightBinary.OperatorKind, rightBinary.Left)
Return (OperationKind.CompoundAssignment,
operatorKind,
IsChecked:=rightBinary.Checked,
InConversion:=identityConversion,
OutConversion:=identityConversion,
RightNode:=rightBinary.Right,
OperatorMethod:=Nothing)
End If End If
Case BoundKind.UserDefinedBinaryOperator Case BoundKind.UserDefinedBinaryOperator
Dim rightOperatorBinary As BoundUserDefinedBinaryOperator = DirectCast(value.Right, BoundUserDefinedBinaryOperator) Dim rightOperatorBinary As BoundUserDefinedBinaryOperator = DirectCast(value.Right, BoundUserDefinedBinaryOperator)
Dim inConversion As Conversion = identityConversion
' It is not permissible to access the Left property of a BoundUserDefinedBinaryOperator unconditionally, Dim operatorMethod As IMethodSymbol = Nothing
' because that property can throw an exception if the operator expression is semantically invalid. If IsUserDefinedBinaryOperatorCompound(rightOperatorBinary, value.LeftOnTheRightOpt, inConversion, operatorMethod) Then
' get it through helper method Dim operatorKind = Helper.DeriveBinaryOperatorKind(rightOperatorBinary.OperatorKind, leftOpt:=Nothing)
Dim leftOperand = GetUserDefinedBinaryOperatorChildBoundNode(rightOperatorBinary, 0) Return (OperationKind.CompoundAssignment,
If leftOperand Is value.LeftOnTheRightOpt Then operatorKind,
Return OperationKind.CompoundAssignment IsChecked:=rightOperatorBinary.Checked,
inConversion,
OutConversion:=identityConversion,
RightNode:=GetUserDefinedBinaryOperatorChildBoundNode(rightOperatorBinary, 1),
operatorMethod)
End If
Case BoundKind.Conversion
' In this case, we could be in a scenario like this:
'
' Dim x, y As New Integer
' x /= y
'
' In this case, there will be a BoundConversion on top of the BoundBinaryOperator, and a BoundConversion on
' top of the left operand to the BoundBinaryOperator. The operand of the conversion on the left and the
' value of LeftOnTheRightOpt will be the same BoundCompoundAssignmentTargetPlaceholder
Dim rightConversion = DirectCast(value.Right, BoundConversion)
Dim outConversion = CreateConversion(rightConversion)
If rightConversion.Operand.Kind = BoundKind.BinaryOperator Then
Dim binaryOperator = DirectCast(rightConversion.Operand, BoundBinaryOperator)
' binaryOperator.Left must be a conversion or the TargetPlaceholder (in error cases). The Operand of the
' Conversion will be the same BoundCompoundAssignmentTargetPlaceholder as value.LeftOnTheRightOpt
If binaryOperator.Left Is value.LeftOnTheRightOpt OrElse
(binaryOperator.Left.Kind = BoundKind.Conversion AndAlso
DirectCast(binaryOperator.Left, BoundConversion).Operand Is value.LeftOnTheRightOpt) Then
Dim operatorKind = Helper.DeriveBinaryOperatorKind(binaryOperator.OperatorKind, binaryOperator.Left)
Return (OperationKind.CompoundAssignment,
operatorKind,
IsChecked:=binaryOperator.Checked,
InConversion:=identityConversion,
outConversion,
RightNode:=binaryOperator.Right,
OperatorMethod:=Nothing)
End If
ElseIf rightConversion.Operand.Kind = BoundKind.UserDefinedConversion OrElse
rightConversion.Operand.Kind = BoundKind.UserDefinedBinaryOperator Then
' In error scenarios, we can have a standard conversion on top of a UserDefinedBinaryOperator
Dim rightOperatorBinary = If(TryCast(rightConversion.Operand, BoundUserDefinedBinaryOperator),
TryCast(DirectCast(rightConversion.Operand, BoundUserDefinedConversion).Operand, BoundUserDefinedBinaryOperator))
If rightOperatorBinary IsNot Nothing Then
Dim inConversion As Conversion = identityConversion
Dim operatorMethod As IMethodSymbol = Nothing
If IsUserDefinedBinaryOperatorCompound(rightOperatorBinary, value.LeftOnTheRightOpt, inConversion, operatorMethod) Then
Dim operatorKind = Helper.DeriveBinaryOperatorKind(rightOperatorBinary.OperatorKind, leftOpt:=Nothing)
Return (OperationKind.CompoundAssignment,
operatorKind,
IsChecked:=rightOperatorBinary.Checked,
inConversion,
outConversion,
RightNode:=GetUserDefinedBinaryOperatorChildBoundNode(rightOperatorBinary, 1),
operatorMethod)
End If
End If
End If End If
End Select End Select
End If End If
Return OperationKind.SimpleAssignment Return (OperationKind.SimpleAssignment, OperatorKind:=Nothing, IsChecked:=False, InConversion:=identityConversion, OutConversion:=identityConversion, RightNode:=Nothing, OperatorMethod:=Nothing)
End Function
Private Shared Function IsUserDefinedBinaryOperatorCompound([operator] As BoundUserDefinedBinaryOperator,
leftOnTheRightOpt As BoundCompoundAssignmentTargetPlaceholder,
ByRef inConversion As Conversion,
ByRef operatorMethod As IMethodSymbol) As Boolean
' It is not permissible to access the Left property of a BoundUserDefinedBinaryOperator unconditionally,
' because that property can throw an exception if the operator expression is semantically invalid.
' get it through helper method
Dim leftOperand = GetUserDefinedBinaryOperatorChildBoundNode([operator], 0)
operatorMethod = If([operator].UnderlyingExpression.Kind = BoundKind.Call, [operator].Call.Method, Nothing)
If leftOperand Is leftOnTheRightOpt Then
Return True
ElseIf leftOperand.Kind = BoundKind.Conversion Then
' In this case, we might have a user-defined operator with an in-conversion on the left operand
' This can happen in the case when the user-defined operator returns the target type, but the left
' parameter does not accept the target type and it must be converted before use.
Dim leftConversion = DirectCast(leftOperand, BoundConversion)
If leftConversion.Operand.Kind = BoundKind.UserDefinedConversion Then
Dim userDefinedConversion = DirectCast(leftConversion.Operand, BoundUserDefinedConversion)
If userDefinedConversion.Operand Is leftOnTheRightOpt Then
inConversion = CreateConversion(leftConversion)
Return True
End If
End If
End If
Return False
End Function
Private Shared Function CreateConversion(boundConversion As BoundConversion) As Conversion
If boundConversion.Operand.Kind = BoundKind.UserDefinedConversion Then
Dim userDefinedConversion = DirectCast(boundConversion.Operand, BoundUserDefinedConversion)
Return New Conversion(New KeyValuePair(Of ConversionKind, MethodSymbol)(boundConversion.ConversionKind, userDefinedConversion.Call.Method))
Else
Return New Conversion(New KeyValuePair(Of ConversionKind, MethodSymbol)(boundConversion.ConversionKind, Nothing))
End If
End Function End Function
Private Function GetUserDefinedBinaryOperatorChild([operator] As BoundUserDefinedBinaryOperator, index As Integer) As IOperation Private Function GetUserDefinedBinaryOperatorChild([operator] As BoundUserDefinedBinaryOperator, index As Integer) As IOperation
...@@ -45,7 +144,7 @@ Namespace Microsoft.CodeAnalysis.Operations ...@@ -45,7 +144,7 @@ Namespace Microsoft.CodeAnalysis.Operations
Return OperationFactory.CreateInvalidExpression(_semanticModel, [operator].UnderlyingExpression.Syntax, ImmutableArray(Of IOperation).Empty, isImplicit) Return OperationFactory.CreateInvalidExpression(_semanticModel, [operator].UnderlyingExpression.Syntax, ImmutableArray(Of IOperation).Empty, isImplicit)
End Function End Function
Private Shared Function GetUserDefinedBinaryOperatorChildBoundNode([operator] As BoundUserDefinedBinaryOperator, index As Integer) As BoundNode Private Shared Function GetUserDefinedBinaryOperatorChildBoundNode([operator] As BoundUserDefinedBinaryOperator, index As Integer) As BoundExpression
If [operator].UnderlyingExpression.Kind = BoundKind.Call Then If [operator].UnderlyingExpression.Kind = BoundKind.Call Then
If index = 0 Then If index = 0 Then
Return [operator].Left Return [operator].Left
...@@ -176,10 +275,10 @@ Namespace Microsoft.CodeAnalysis.Operations ...@@ -176,10 +275,10 @@ Namespace Microsoft.CodeAnalysis.Operations
Return OperationFactory.CreateInvalidExpression(_semanticModel, parent.Syntax, ImmutableArray(Of IOperation).Empty, isImplicit) Return OperationFactory.CreateInvalidExpression(_semanticModel, parent.Syntax, ImmutableArray(Of IOperation).Empty, isImplicit)
End Function End Function
Private Shared Function GetChildOfBadExpressionBoundNode(parent As BoundNode, index As Integer) As BoundNode Private Shared Function GetChildOfBadExpressionBoundNode(parent As BoundNode, index As Integer) As BoundExpression
Dim badParent As BoundBadExpression = TryCast(parent, BoundBadExpression) Dim badParent As BoundBadExpression = TryCast(parent, BoundBadExpression)
If badParent?.ChildBoundNodes.Length > index Then If badParent?.ChildBoundNodes.Length > index Then
Dim child As BoundNode = badParent.ChildBoundNodes(index) Dim child As BoundExpression = badParent.ChildBoundNodes(index)
If child IsNot Nothing Then If child IsNot Nothing Then
Return child Return child
End If End If
......
...@@ -1220,24 +1220,14 @@ IBlockOperation (12 statements, 2 locals) (OperationKind.Block, Type: null) (Syn ...@@ -1220,24 +1220,14 @@ IBlockOperation (12 statements, 2 locals) (OperationKind.Block, Type: null) (Syn
ILocalReferenceOperation: y (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'y') ILocalReferenceOperation: y (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'y')
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'x /= y') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'x /= y')
Expression: Expression:
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32, IsImplicit) (Syntax: 'x /= y') ICompoundAssignmentOperation (BinaryOperatorKind.Divide, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'x /= y')
Left: Left:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x') ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x')
Right: Right:
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Int32, IsImplicit) (Syntax: 'x /= y') IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Double, IsImplicit) (Syntax: 'y')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: True, IsReference: False, IsUserDefined: False) (MethodSymbol: null) Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: True, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand: Operand:
IBinaryOperation (BinaryOperatorKind.Divide, Checked) (OperationKind.BinaryOperator, Type: System.Double, IsImplicit) (Syntax: 'x /= y') ILocalReferenceOperation: y (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'y')
Left:
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Double, IsImplicit) (Syntax: 'x')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: True, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand:
IOperation: (OperationKind.None, Type: null, IsImplicit) (Syntax: 'x')
Right:
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Double, IsImplicit) (Syntax: 'y')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: True, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand:
ILocalReferenceOperation: y (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'y')
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'x \= y') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'x \= y')
Expression: Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.IntegerDivide, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'x \= y') ICompoundAssignmentOperation (BinaryOperatorKind.IntegerDivide, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'x \= y')
...@@ -1247,44 +1237,24 @@ IBlockOperation (12 statements, 2 locals) (OperationKind.Block, Type: null) (Syn ...@@ -1247,44 +1237,24 @@ IBlockOperation (12 statements, 2 locals) (OperationKind.Block, Type: null) (Syn
ILocalReferenceOperation: y (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'y') ILocalReferenceOperation: y (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'y')
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'x ^= y') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'x ^= y')
Expression: Expression:
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32, IsImplicit) (Syntax: 'x ^= y') ICompoundAssignmentOperation (BinaryOperatorKind.Power, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'x ^= y')
Left: Left:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x') ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x')
Right: Right:
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Int32, IsImplicit) (Syntax: 'x ^= y') IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Double, IsImplicit) (Syntax: 'y')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: True, IsReference: False, IsUserDefined: False) (MethodSymbol: null) Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: True, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand: Operand:
IBinaryOperation (BinaryOperatorKind.Power, Checked) (OperationKind.BinaryOperator, Type: System.Double, IsImplicit) (Syntax: 'x ^= y') ILocalReferenceOperation: y (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'y')
Left:
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Double, IsImplicit) (Syntax: 'x')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: True, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand:
IOperation: (OperationKind.None, Type: null, IsImplicit) (Syntax: 'x')
Right:
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Double, IsImplicit) (Syntax: 'y')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: True, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand:
ILocalReferenceOperation: y (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'y')
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'x &= y') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'x &= y')
Expression: Expression:
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32, IsImplicit) (Syntax: 'x &= y') ICompoundAssignmentOperation (BinaryOperatorKind.Concatenate, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'x &= y')
Left: Left:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x') ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x')
Right: Right:
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Int32, IsImplicit) (Syntax: 'x &= y') IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.String, IsImplicit) (Syntax: 'y')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand: Operand:
IBinaryOperation (BinaryOperatorKind.Concatenate, Checked) (OperationKind.BinaryOperator, Type: System.String, IsImplicit) (Syntax: 'x &= y') ILocalReferenceOperation: y (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'y')
Left:
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.String, IsImplicit) (Syntax: 'x')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand:
IOperation: (OperationKind.None, Type: null, IsImplicit) (Syntax: 'x')
Right:
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.String, IsImplicit) (Syntax: 'y')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand:
ILocalReferenceOperation: y (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'y')
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'x <<= 2') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'x <<= 2')
Expression: Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.LeftShift, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'x <<= 2') ICompoundAssignmentOperation (BinaryOperatorKind.LeftShift, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'x <<= 2')
...@@ -1374,24 +1344,14 @@ IBlockOperation (12 statements, 2 locals) (OperationKind.Block, Type: null) (Syn ...@@ -1374,24 +1344,14 @@ IBlockOperation (12 statements, 2 locals) (OperationKind.Block, Type: null) (Syn
ILocalReferenceOperation: y (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'y') ILocalReferenceOperation: y (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'y')
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'x /= y') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'x /= y')
Expression: Expression:
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32, IsImplicit) (Syntax: 'x /= y') ICompoundAssignmentOperation (BinaryOperatorKind.Divide) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'x /= y')
Left: Left:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x') ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x')
Right: Right:
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Int32, IsImplicit) (Syntax: 'x /= y') IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Double, IsImplicit) (Syntax: 'y')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: True, IsReference: False, IsUserDefined: False) (MethodSymbol: null) Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: True, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand: Operand:
IBinaryOperation (BinaryOperatorKind.Divide) (OperationKind.BinaryOperator, Type: System.Double, IsImplicit) (Syntax: 'x /= y') ILocalReferenceOperation: y (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'y')
Left:
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Double, IsImplicit) (Syntax: 'x')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: True, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand:
IOperation: (OperationKind.None, Type: null, IsImplicit) (Syntax: 'x')
Right:
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Double, IsImplicit) (Syntax: 'y')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: True, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand:
ILocalReferenceOperation: y (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'y')
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'x \= y') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'x \= y')
Expression: Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.IntegerDivide) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'x \= y') ICompoundAssignmentOperation (BinaryOperatorKind.IntegerDivide) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'x \= y')
...@@ -1401,44 +1361,24 @@ IBlockOperation (12 statements, 2 locals) (OperationKind.Block, Type: null) (Syn ...@@ -1401,44 +1361,24 @@ IBlockOperation (12 statements, 2 locals) (OperationKind.Block, Type: null) (Syn
ILocalReferenceOperation: y (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'y') ILocalReferenceOperation: y (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'y')
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'x ^= y') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'x ^= y')
Expression: Expression:
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32, IsImplicit) (Syntax: 'x ^= y') ICompoundAssignmentOperation (BinaryOperatorKind.Power) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'x ^= y')
Left: Left:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x') ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x')
Right: Right:
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Int32, IsImplicit) (Syntax: 'x ^= y') IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Double, IsImplicit) (Syntax: 'y')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: True, IsReference: False, IsUserDefined: False) (MethodSymbol: null) Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: True, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand: Operand:
IBinaryOperation (BinaryOperatorKind.Power) (OperationKind.BinaryOperator, Type: System.Double, IsImplicit) (Syntax: 'x ^= y') ILocalReferenceOperation: y (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'y')
Left:
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Double, IsImplicit) (Syntax: 'x')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: True, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand:
IOperation: (OperationKind.None, Type: null, IsImplicit) (Syntax: 'x')
Right:
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Double, IsImplicit) (Syntax: 'y')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: True, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand:
ILocalReferenceOperation: y (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'y')
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'x &= y') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'x &= y')
Expression: Expression:
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32, IsImplicit) (Syntax: 'x &= y') ICompoundAssignmentOperation (BinaryOperatorKind.Concatenate) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'x &= y')
Left: Left:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x') ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x')
Right: Right:
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Int32, IsImplicit) (Syntax: 'x &= y') IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.String, IsImplicit) (Syntax: 'y')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand: Operand:
IBinaryOperation (BinaryOperatorKind.Concatenate) (OperationKind.BinaryOperator, Type: System.String, IsImplicit) (Syntax: 'x &= y') ILocalReferenceOperation: y (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'y')
Left:
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.String, IsImplicit) (Syntax: 'x')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand:
IOperation: (OperationKind.None, Type: null, IsImplicit) (Syntax: 'x')
Right:
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.String, IsImplicit) (Syntax: 'y')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand:
ILocalReferenceOperation: y (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'y')
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'x <<= 2') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'x <<= 2')
Expression: Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.LeftShift) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'x <<= 2') ICompoundAssignmentOperation (BinaryOperatorKind.LeftShift) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'x <<= 2')
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports Microsoft.CodeAnalysis.Test.Utilities
Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Semantics
Partial Public Class IOperationTests
Inherits SemanticModelTestBase
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub CompoundAssignmentOperation_UserDefinedOperatorInConversion()
Dim source = <![CDATA[
Module Module1
Sub Main()
Dim a As New C, x As New Integer
a += x'BIND:"a += x"
End Sub
Class C
Public Shared Widening Operator CType(i As Integer) As C
Return Nothing
End Operator
Public Shared Widening Operator CType(c As C) As Integer
Return 1
End Operator
Public Shared Operator +(c As Integer, i As C) As C
Return 0
End Operator
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'a += x')
Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperatorMethod: Function Module1.C.op_Addition(c As System.Int32, i As Module1.C) As Module1.C) (OperationKind.CompoundAssignment, Type: Module1.C, IsImplicit) (Syntax: 'a += x')
Left:
ILocalReferenceOperation: a (OperationKind.LocalReference, Type: Module1.C) (Syntax: 'a')
Right:
IConversionOperation (TryCast: False, Unchecked) (OperatorMethod: Function Module1.C.op_Implicit(i As System.Int32) As Module1.C) (OperationKind.Conversion, Type: Module1.C, IsImplicit) (Syntax: 'x')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: Function Module1.C.op_Implicit(i As System.Int32) As Module1.C)
Operand:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x')
]]>.Value
Dim expectedDiagnostics = String.Empty
VerifyOperationTreeAndDiagnosticsForTest(Of AssignmentStatementSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub CompoundAssignmentOperation_UserDefinedOperatorOutConversion()
Dim source = <![CDATA[
Module Module1
Sub Main()
Dim a As New C, x As New Integer
a += x'BIND:"a += x"
End Sub
Class C
Public Shared Widening Operator CType(i As Integer) As C
Return Nothing
End Operator
Public Shared Widening Operator CType(c As C) As Integer
Return 1
End Operator
Public Shared Operator +(c As C, i As Integer) As Integer
Return 0
End Operator
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'a += x')
Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperatorMethod: Function Module1.C.op_Addition(c As Module1.C, i As System.Int32) As System.Int32) (OperationKind.CompoundAssignment, Type: Module1.C, IsImplicit) (Syntax: 'a += x')
Left:
ILocalReferenceOperation: a (OperationKind.LocalReference, Type: Module1.C) (Syntax: 'a')
Right:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x')
]]>.Value
Dim expectedDiagnostics = String.Empty
VerifyOperationTreeAndDiagnosticsForTest(Of AssignmentStatementSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub CompoundAssignmentOperation_UserDefinedOperatorInOutConversion()
Dim source = <![CDATA[
Module Module1
Sub Main()
Dim a As New C, x As New Integer
a += x'BIND:"a += x"
End Sub
Class C
Public Shared Widening Operator CType(i As Integer) As C
Return Nothing
End Operator
Public Shared Widening Operator CType(c As C) As Integer
Return 1
End Operator
Public Shared Operator +(c As Integer, i As C) As Integer
Return 0
End Operator
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'a += x')
Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperatorMethod: Function Module1.C.op_Addition(c As System.Int32, i As Module1.C) As System.Int32) (OperationKind.CompoundAssignment, Type: Module1.C, IsImplicit) (Syntax: 'a += x')
Left:
ILocalReferenceOperation: a (OperationKind.LocalReference, Type: Module1.C) (Syntax: 'a')
Right:
IConversionOperation (TryCast: False, Unchecked) (OperatorMethod: Function Module1.C.op_Implicit(i As System.Int32) As Module1.C) (OperationKind.Conversion, Type: Module1.C, IsImplicit) (Syntax: 'x')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: Function Module1.C.op_Implicit(i As System.Int32) As Module1.C)
Operand:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x')
]]>.Value
Dim expectedDiagnostics = String.Empty
VerifyOperationTreeAndDiagnosticsForTest(Of AssignmentStatementSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub CompoundAssignmentExpression_BuiltInOperatorInOutConversion()
Dim source = <![CDATA[
Module Module1
Sub Main()
Dim x, y As New Integer
x /= y'BIND:"x /= y"
End Sub
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'x /= y')
Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Divide, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'x /= y')
Left:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x')
Right:
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Double, IsImplicit) (Syntax: 'y')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: True, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand:
ILocalReferenceOperation: y (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'y')
]]>.Value
Dim expectedDiagnostics = String.Empty
VerifyOperationTreeAndDiagnosticsForTest(Of AssignmentStatementSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub CompoundAssignmentExpression_InvalidNoOperator()
Dim source = <![CDATA[
Module Module1
Sub Main()
Dim a As New C, x As New Integer
a += x'BIND:"a += x"
End Sub
Class C
Public Shared Widening Operator CType(i As Integer) As C
Return Nothing
End Operator
Public Shared Widening Operator CType(c As C) As Integer
Return 1
End Operator
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid) (Syntax: 'a += x')
Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: Module1.C, IsInvalid, IsImplicit) (Syntax: 'a += x')
Left:
ILocalReferenceOperation: a (OperationKind.LocalReference, Type: Module1.C, IsInvalid) (Syntax: 'a')
Right:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'x')
]]>.Value
Dim expectedDiagnostics = <![CDATA[
BC30452: Operator '+' is not defined for types 'Module1.C' and 'Integer'.
a += x'BIND:"a += x"
~~~~~~
]]>.Value
VerifyOperationTreeAndDiagnosticsForTest(Of AssignmentStatementSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub CompoundAssignmentExpression_InvalidNoOutConversion()
Dim source = <![CDATA[
Module Module1
Sub Main()
Dim a As New C, x As New Integer
a += x'BIND:"a += x"
End Sub
Class C
Public Shared Widening Operator CType(c As C) As Integer
Return 1
End Operator
Public Shared Operator +(c As C, i As Integer) As Integer
Return 1
End Operator
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid) (Syntax: 'a += x')
Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperatorMethod: Function Module1.C.op_Addition(c As Module1.C, i As System.Int32) As System.Int32) (OperationKind.CompoundAssignment, Type: Module1.C, IsInvalid, IsImplicit) (Syntax: 'a += x')
Left:
ILocalReferenceOperation: a (OperationKind.LocalReference, Type: Module1.C, IsInvalid) (Syntax: 'a')
Right:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'x')
]]>.Value
Dim expectedDiagnostics = <![CDATA[
BC30311: Value of type 'Integer' cannot be converted to 'Module1.C'.
a += x'BIND:"a += x"
~~~~~~
]]>.Value
VerifyOperationTreeAndDiagnosticsForTest(Of AssignmentStatementSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub CompoundAssignmentExpression_InvalidNoInConversion()
Dim source = <![CDATA[
Module Module1
Sub Main()
Dim a As New C, x As New Integer
a += x'BIND:"a += x"
End Sub
Class C
Public Shared Widening Operator CType(c As Integer) As C
Return 1
End Operator
Public Shared Operator +(c As Integer, i As C) As Integer
Return 1
End Operator
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid) (Syntax: 'a += x')
Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: Module1.C, IsInvalid, IsImplicit) (Syntax: 'a += x')
Left:
ILocalReferenceOperation: a (OperationKind.LocalReference, Type: Module1.C, IsInvalid) (Syntax: 'a')
Right:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x')
]]>.Value
Dim expectedDiagnostics = <![CDATA[
BC30311: Value of type 'Module1.C' cannot be converted to 'Integer'.
a += x'BIND:"a += x"
~
BC42004: Expression recursively calls the containing Operator 'Public Shared Widening Operator CType(c As Integer) As Module1.C'.
Return 1
~
]]>.Value
VerifyOperationTreeAndDiagnosticsForTest(Of AssignmentStatementSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub CompoundAssignmentExpression_InvalidNoOperatorOrConversions()
Dim source = <![CDATA[
Module Module1
Sub Main()
Dim a As New C, x As New Integer
a += x'BIND:"a += x"
End Sub
Class C
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid) (Syntax: 'a += x')
Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: Module1.C, IsInvalid, IsImplicit) (Syntax: 'a += x')
Left:
ILocalReferenceOperation: a (OperationKind.LocalReference, Type: Module1.C, IsInvalid) (Syntax: 'a')
Right:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'x')
]]>.Value
Dim expectedDiagnostics = <![CDATA[
BC30452: Operator '+' is not defined for types 'Module1.C' and 'Integer'.
a += x'BIND:"a += x"
~~~~~~
]]>.Value
VerifyOperationTreeAndDiagnosticsForTest(Of AssignmentStatementSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
End Class
End Namespace
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册