Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Able to use expressions on the right of Flags Enum Operators. #14

Merged
merged 4 commits into from
Mar 8, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 55 additions & 7 deletions src/Compilers/VisualBasic/Portable/Binding/Binder_Expressions.vb
Original file line number Diff line number Diff line change
Expand Up @@ -3769,6 +3769,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
If IsFlagsEnum(DirectCast(original, INamedTypeSymbol)) Then
Return BindEnumFlagExpression(original, node, left, node, diagnostics)
Else
' Return BindEnumFlagExpression(original, node, left, node, diagnostics)
Return ReportDiagnosticAndProduceBadExpression(diagnostics, node, ERRID.ERR_MissingFlagsAttributeOnEnum, original.Name)
End If
' Else
Expand Down Expand Up @@ -3834,8 +3835,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
member As MemberAccessExpressionSyntax,
diagBag As DiagnosticBag
) As BoundExpression
Dim FlagName = member.Name.Identifier.ValueText
Return Bind_FlagsEnumOperation(FlagName, member, member.Expression, member.OperatorToken, member.Name, diagBag)
Dim EnumMember = TryCast(member.Expression, SimpleNameSyntax)
If EnumMember IsNot Nothing Then
Dim FlagName = EnumMember.Identifier.ValueText
Return Bind_FlagsEnumOperation_WithEnumMember(FlagName, member, EnumMember, member.OperatorToken, member.Name, diagBag)
Else
Return Bind_FlagsEnumOperation_WithExpression(member, member.Expression, member.OperatorToken, member.Name, diagBag)

End If
End Function

Private Function GetFlagsEnumOperationKind(node As SyntaxToken) As FlagsEnumOperatorKind
Expand All @@ -3845,11 +3852,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
SyntaxKind.ExclamationToken
Return FlagsEnumOperatorKind.IsSet
Case SyntaxKind.FlagsEnumSetToken : Return FlagsEnumOperatorKind.Set
Case SyntaxKind.FlagsEnumIsAnyToken : Return FlagsEnumOperatorKind.IsAny
End Select
Return FlagsEnumOperatorKind.None
End Function

Private Function Bind_FlagsEnumOperation(
Private Function Bind_FlagsEnumOperation_WithEnumMember(
FlagName As String,
node As ExpressionSyntax,
EnumFlags As ExpressionSyntax,
Expand Down Expand Up @@ -3878,17 +3886,57 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
syntax:=node,
enumFlags:=bFlags, op,
enumFlag:=New BoundFieldAccess(EnumFlag, bFlags, eFlag, False, original),
type:=If(op = FlagsEnumOperatorKind.IsSet, GetSpecialType(SpecialType.System_Boolean, EnumFlag, diagBag), original)
type:=If(op = FlagsEnumOperatorKind.IsSet Or op = FlagsEnumOperatorKind.IsAny,
GetSpecialType(SpecialType.System_Boolean, EnumFlag, diagBag), original)
)
End Function

Private Function Bind_FlagsEnumOperation(
node As FlagsEnumOperationExpressionSyntax,
diagBag As DiagnosticBag
) As BoundExpression
Dim FlagName = node.EnumFlag?.Identifier.ValueText
FlagName = If(FlagName, String.Empty)
Return Bind_FlagsEnumOperation(FlagName,node,node.EnumFlags, node.OperatorToken, node.EnumFlag,diagBag)
Dim Sn = TryCast(node.EnumFlag, SimpleNameSyntax)
If Sn IsNot Nothing Then
Dim FlagName = Sn.Identifier.ValueText
FlagName = If(FlagName, String.Empty)
Return Bind_FlagsEnumOperation_WithEnumMember(FlagName, node, node.EnumFlags, node.OperatorToken, Sn, diagBag)
Else
Return Bind_FlagsEnumOperation_WithExpression(node, node.EnumFlags, node.OperatorToken, node.EnumFlag, diagBag)

End if
End Function

Private Function Bind_FlagsEnumOperation_WithExpression(
node As ExpressionSyntax,
EnumFlags As ExpressionSyntax,
opToken As SyntaxToken,
EnumFlag As ExpressionSyntax,
diagBag As DiagnosticBag
) As BoundExpression
Dim eFlag As FieldSymbol = Nothing
Dim bFlags = BindExpression(EnumFlags, diagBag)
Dim original = bFlags.Type.OriginalDefinition

If Not IsFlagsEnum(DirectCast(original, INamedTypeSymbol)) Then
Return ReportDiagnosticAndProduceBadExpression(diagBag, EnumFlags, ERRID.ERR_EnumNotExpression1)
End If

'If Not IsMemberOfThisEnum(original, FlagName, eFlag) Then
' Return ReportDiagnosticAndProduceBadExpression(diagBag, EnumFlag, ERRID.ERR_NameNotMember2, FlagName, original.Name)
'End If

Dim op As FlagsEnumOperatorKind = GetFlagsEnumOperationKind(opToken)
If op = FlagsEnumOperatorKind.None Then
Return ReportDiagnosticAndProduceBadExpression(diagBag, node, ERRID.ERR_NameNotMember2, "", original.Name)
End If

Return New BoundFlagsEnumOperationExpressionSyntax(
syntax:=node,
enumFlags:=bFlags, op,
enumFlag:=BindExpression(EnumFlag, diagBag),
type:=If(op = FlagsEnumOperatorKind.IsSet Or op = FlagsEnumOperatorKind.IsAny,
GetSpecialType(SpecialType.System_Boolean, EnumFlag, diagBag), original)
)
End Function

Private Shared Sub ReportNoDefaultProperty(expr As BoundExpression, diagnostics As DiagnosticBag)
Expand Down
1 change: 1 addition & 0 deletions src/Compilers/VisualBasic/Portable/Errors/Errors.vb
Original file line number Diff line number Diff line change
Expand Up @@ -2018,5 +2018,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
FEATURE_LeadingDigitSeparator
FEATURE_PrivateProtected
FEATURE_EnumFlagOperators
ERR_MissingEnumFlag
End Enum
End Namespace
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
' Definition of syntax model.
' Generated by a tool from SHA256 content 9CBCDCD8809BFC65618FC86B59B0CDA27BB9E4DBC6C54EA6BB45580D1F8EA11C
' Generated by a tool from SHA256 content B93F36ED2CA5105803BCB5550ED4F67E8CAC50FE811B4F34AA6E703694462A8C
' DO NOT HAND EDIT

Imports System.Collections.Generic
Expand Down Expand Up @@ -36607,9 +36607,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax

Friend ReadOnly _enumFlags as ExpressionSyntax
Friend ReadOnly _operatorToken as FlagsEnumOperatorSyntax
Friend ReadOnly _enumFlag as SimpleNameSyntax
Friend ReadOnly _enumFlag as ExpressionSyntax

Friend Sub New(ByVal kind As SyntaxKind, enumFlags As ExpressionSyntax, operatorToken As InternalSyntax.FlagsEnumOperatorSyntax, enumFlag As SimpleNameSyntax)
Friend Sub New(ByVal kind As SyntaxKind, enumFlags As ExpressionSyntax, operatorToken As InternalSyntax.FlagsEnumOperatorSyntax, enumFlag As ExpressionSyntax)
MyBase.New(kind)
MyBase._slotCount = 3

Expand All @@ -36619,12 +36619,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
End If
AdjustFlagsAndWidth(operatorToken)
Me._operatorToken = operatorToken
AdjustFlagsAndWidth(enumFlag)
Me._enumFlag = enumFlag
If enumFlag IsNot Nothing Then
AdjustFlagsAndWidth(enumFlag)
Me._enumFlag = enumFlag
End If

End Sub

Friend Sub New(ByVal kind As SyntaxKind, enumFlags As ExpressionSyntax, operatorToken As InternalSyntax.FlagsEnumOperatorSyntax, enumFlag As SimpleNameSyntax, context As ISyntaxFactoryContext)
Friend Sub New(ByVal kind As SyntaxKind, enumFlags As ExpressionSyntax, operatorToken As InternalSyntax.FlagsEnumOperatorSyntax, enumFlag As ExpressionSyntax, context As ISyntaxFactoryContext)
MyBase.New(kind)
MyBase._slotCount = 3
Me.SetFactoryContext(context)
Expand All @@ -36635,12 +36637,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
End If
AdjustFlagsAndWidth(operatorToken)
Me._operatorToken = operatorToken
AdjustFlagsAndWidth(enumFlag)
Me._enumFlag = enumFlag
If enumFlag IsNot Nothing Then
AdjustFlagsAndWidth(enumFlag)
Me._enumFlag = enumFlag
End If

End Sub

Friend Sub New(ByVal kind As SyntaxKind, ByVal errors as DiagnosticInfo(), ByVal annotations as SyntaxAnnotation(), enumFlags As ExpressionSyntax, operatorToken As InternalSyntax.FlagsEnumOperatorSyntax, enumFlag As SimpleNameSyntax)
Friend Sub New(ByVal kind As SyntaxKind, ByVal errors as DiagnosticInfo(), ByVal annotations as SyntaxAnnotation(), enumFlags As ExpressionSyntax, operatorToken As InternalSyntax.FlagsEnumOperatorSyntax, enumFlag As ExpressionSyntax)
MyBase.New(kind, errors, annotations)
MyBase._slotCount = 3

Expand All @@ -36650,8 +36654,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
End If
AdjustFlagsAndWidth(operatorToken)
Me._operatorToken = operatorToken
AdjustFlagsAndWidth(enumFlag)
Me._enumFlag = enumFlag
If enumFlag IsNot Nothing Then
AdjustFlagsAndWidth(enumFlag)
Me._enumFlag = enumFlag
End If

End Sub

Expand All @@ -36668,7 +36674,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
AdjustFlagsAndWidth(_operatorToken)
Me._operatorToken = _operatorToken
End If
Dim _enumFlag = DirectCast(reader.ReadValue(), SimpleNameSyntax)
Dim _enumFlag = DirectCast(reader.ReadValue(), ExpressionSyntax)
If _enumFlag isnot Nothing
AdjustFlagsAndWidth(_enumFlag)
Me._enumFlag = _enumFlag
Expand Down Expand Up @@ -36711,9 +36717,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
End Property

''' <summary>
''' The identifier after the "!" or "!+" or "!-" token.
''' The identifier after the "!", "!+", "!-" or "!/" token.
''' </summary>
Friend ReadOnly Property EnumFlag As InternalSyntax.SimpleNameSyntax
''' <remarks>
''' This child is optional. If it is not present, then Nothing is returned.
''' </remarks>
Friend ReadOnly Property EnumFlag As InternalSyntax.ExpressionSyntax
Get
Return Me._enumFlag
End Get
Expand Down Expand Up @@ -42131,7 +42140,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
If node._enumFlags IsNot newEnumFlags Then anyChanges = True
Dim newOperatorToken = DirectCast(Visit(node.OperatorToken), FlagsEnumOperatorSyntax)
If node._operatorToken IsNot newOperatorToken Then anyChanges = True
Dim newEnumFlag = DirectCast(Visit(node._enumFlag), SimpleNameSyntax)
Dim newEnumFlag = DirectCast(Visit(node._enumFlag), ExpressionSyntax)
If node._enumFlag IsNot newEnumFlag Then anyChanges = True

If anyChanges Then
Expand Down Expand Up @@ -54520,11 +54529,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
''' The expression on the left-hand-side of the "." or "!" token.
''' </param>
''' <param name="enumFlag">
''' The identifier after the "!" or "!+" or "!-" token.
''' The identifier after the "!", "!+", "!-" or "!/" token.
''' </param>
Friend Shared Function FlagsEnumOperationExpression(enumFlags As ExpressionSyntax, operatorToken As FlagsEnumOperatorSyntax, enumFlag As SimpleNameSyntax) As FlagsEnumOperationExpressionSyntax
Friend Shared Function FlagsEnumOperationExpression(enumFlags As ExpressionSyntax, operatorToken As FlagsEnumOperatorSyntax, enumFlag As ExpressionSyntax) As FlagsEnumOperationExpressionSyntax
Debug.Assert(operatorToken IsNot Nothing AndAlso SyntaxFacts.IsFlagsEnumOperationExpressionOperatorToken(operatorToken.Kind))
Debug.Assert(enumFlag IsNot Nothing)

Dim hash As Integer
Dim cached = SyntaxNodeCache.TryGetNode(SyntaxKind.FlagsEnumOperationExpression, enumFlags, operatorToken, enumFlag, hash)
Expand All @@ -54541,6 +54549,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
End Function


''' <param name="text">
''' The actual text of this token.
''' </param>
Friend Shared Function FlagsEnumIsAnyToken(text as String, leadingTrivia As GreenNode, trailingTrivia As GreenNode) As FlagsEnumOperatorSyntax
Debug.Assert(text IsNot Nothing)
Return New FlagsEnumOperatorSyntax(SyntaxKind.FlagsEnumIsAnyToken, text, leadingTrivia, trailingTrivia)
End Function


''' <param name="text">
''' The actual text of this token.
''' </param>
Expand Down Expand Up @@ -54570,8 +54587,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax

''' <param name="kind">
''' A <cref c="SyntaxKind"/> representing the specific kind of
''' FlagsEnumOperatorSyntax. One of FlagsEnumSetToken, FlagsEnumClearToken,
''' FlagsEnumIsSetToken.
''' FlagsEnumOperatorSyntax. One of FlagsEnumIsAnyToken, FlagsEnumSetToken,
''' FlagsEnumClearToken, FlagsEnumIsSetToken.
''' </param>
''' <param name="text">
''' The actual text of this token.
Expand Down Expand Up @@ -66663,11 +66680,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
''' The expression on the left-hand-side of the "." or "!" token.
''' </param>
''' <param name="enumFlag">
''' The identifier after the "!" or "!+" or "!-" token.
''' The identifier after the "!", "!+", "!-" or "!/" token.
''' </param>
Friend Function FlagsEnumOperationExpression(enumFlags As ExpressionSyntax, operatorToken As FlagsEnumOperatorSyntax, enumFlag As SimpleNameSyntax) As FlagsEnumOperationExpressionSyntax
Friend Function FlagsEnumOperationExpression(enumFlags As ExpressionSyntax, operatorToken As FlagsEnumOperatorSyntax, enumFlag As ExpressionSyntax) As FlagsEnumOperationExpressionSyntax
Debug.Assert(operatorToken IsNot Nothing AndAlso SyntaxFacts.IsFlagsEnumOperationExpressionOperatorToken(operatorToken.Kind))
Debug.Assert(enumFlag IsNot Nothing)

Dim hash As Integer
Dim cached = VisualBasicSyntaxNodeCache.TryGetNode(SyntaxKind.FlagsEnumOperationExpression, enumFlags, operatorToken, enumFlag, _factoryContext, hash)
Expand All @@ -66684,6 +66700,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
End Function


''' <param name="text">
''' The actual text of this token.
''' </param>
Friend Function FlagsEnumIsAnyToken(text as String, leadingTrivia As GreenNode, trailingTrivia As GreenNode) As FlagsEnumOperatorSyntax
Debug.Assert(text IsNot Nothing)
Return New FlagsEnumOperatorSyntax(SyntaxKind.FlagsEnumIsAnyToken, text, leadingTrivia, trailingTrivia, _factoryContext)
End Function


''' <param name="text">
''' The actual text of this token.
''' </param>
Expand Down Expand Up @@ -66713,8 +66738,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax

''' <param name="kind">
''' A <cref c="SyntaxKind"/> representing the specific kind of
''' FlagsEnumOperatorSyntax. One of FlagsEnumSetToken, FlagsEnumClearToken,
''' FlagsEnumIsSetToken.
''' FlagsEnumOperatorSyntax. One of FlagsEnumIsAnyToken, FlagsEnumSetToken,
''' FlagsEnumClearToken, FlagsEnumIsSetToken.
''' </param>
''' <param name="text">
''' The actual text of this token.
Expand Down
Loading