File: Symbols\Source\SourceEnumConstantSymbol.vb
Web Access
Project: src\src\Compilers\VisualBasic\Portable\Microsoft.CodeAnalysis.VisualBasic.vbproj (Microsoft.CodeAnalysis.VisualBasic)
' Licensed to the .NET Foundation under one or more agreements.
' The .NET Foundation licenses this file to you under the MIT license.
' See the LICENSE file in the project root for more information.
 
Imports System.Collections.Immutable
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
 
Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
 
    ''' <summary>
    ''' Represents enum constant field in source.
    ''' </summary>
    Friend MustInherit Class SourceEnumConstantSymbol
        Inherits SourceFieldSymbol
 
        Private _constantTuple As EvaluatedConstant
 
        Public Shared Function CreateExplicitValuedConstant(containingEnum As SourceNamedTypeSymbol, bodyBinder As Binder, syntax As EnumMemberDeclarationSyntax, diagnostics As BindingDiagnosticBag) As SourceEnumConstantSymbol
            Dim initializer = syntax.Initializer
            Debug.Assert(initializer IsNot Nothing)
            Return New ExplicitValuedEnumConstantSymbol(containingEnum, bodyBinder, syntax, initializer, diagnostics)
        End Function
 
        Public Shared Function CreateImplicitValuedConstant(containingEnum As SourceNamedTypeSymbol, bodyBinder As Binder, syntax As EnumMemberDeclarationSyntax, otherConstant As SourceEnumConstantSymbol, otherConstantOffset As Integer, diagnostics As BindingDiagnosticBag) As SourceEnumConstantSymbol
            If otherConstant Is Nothing Then
                Debug.Assert(otherConstantOffset = 0)
                Return New ZeroValuedEnumConstantSymbol(containingEnum, bodyBinder, syntax, diagnostics)
            Else
                Debug.Assert(otherConstantOffset > 0)
                Return New ImplicitValuedEnumConstantSymbol(containingEnum, bodyBinder, syntax, otherConstant, CType(otherConstantOffset, UInteger), diagnostics)
            End If
        End Function
 
        Protected Sub New(containingEnum As SourceNamedTypeSymbol, bodyBinder As Binder, syntax As EnumMemberDeclarationSyntax, diagnostics As BindingDiagnosticBag)
            MyBase.New(containingEnum,
                       bodyBinder.GetSyntaxReference(syntax),
                       name:=syntax.Identifier.ValueText,
                       memberFlags:=SourceMemberFlags.Const Or SourceMemberFlags.Shared Or SourceMemberFlags.AccessibilityPublic)
 
            If IdentifierComparison.Equals(Me.Name, WellKnownMemberNames.EnumBackingFieldName) Then
                diagnostics.Add(ERRID.ERR_ClashWithReservedEnumMember1, syntax.Identifier.GetLocation(), Me.Name)
            End If
        End Sub
 
        Friend NotOverridable Overrides ReadOnly Property DeclarationSyntax As VisualBasicSyntaxNode
            Get
                Return Syntax
            End Get
        End Property
 
        Friend NotOverridable Overrides ReadOnly Property GetAttributeDeclarations As OneOrMany(Of SyntaxList(Of AttributeListSyntax))
            Get
                Return OneOrMany.Create(DirectCast(Syntax, EnumMemberDeclarationSyntax).AttributeLists)
            End Get
        End Property
 
        Public NotOverridable Overrides ReadOnly Property Locations As ImmutableArray(Of Location)
            Get
                Return ImmutableArray.Create(DirectCast(Syntax, EnumMemberDeclarationSyntax).Identifier.GetLocation())
            End Get
        End Property
 
        Public NotOverridable Overrides ReadOnly Property Type As TypeSymbol
            Get
                Return ContainingType
            End Get
        End Property
 
        Protected NotOverridable Overrides Function GetLazyConstantTuple() As EvaluatedConstant
            Return _constantTuple
        End Function
 
        Friend NotOverridable Overrides Function GetConstantValue(inProgress As ConstantFieldsInProgress) As ConstantValue
            Return GetConstantValueImpl(inProgress)
        End Function
 
        Protected NotOverridable Overrides Sub SetLazyConstantTuple(constantTuple As EvaluatedConstant, diagnostics As BindingDiagnosticBag)
            Dim sourceModule = DirectCast(Me.ContainingModule, SourceModuleSymbol)
            sourceModule.AtomicStoreReferenceAndDiagnostics(_constantTuple, constantTuple, diagnostics)
        End Sub
 
        Friend Overrides ReadOnly Property MeParameter As ParameterSymbol
            Get
                Return Nothing
            End Get
        End Property
 
        Protected MustOverride Overrides Function MakeConstantTuple(dependencies As ConstantFieldsInProgress.Dependencies, diagnostics As BindingDiagnosticBag) As EvaluatedConstant
 
        ' There are implementations for:
        ' 1) enum constant that is zero
        ' 2) enum constant that has explicit value
        ' 3) enum constant that has a value incrementally dependent on another enum constant
#Region "Concrete constant symbol implementations"
 
        Private NotInheritable Class ZeroValuedEnumConstantSymbol
            Inherits SourceEnumConstantSymbol
 
            Public Sub New(containingEnum As SourceNamedTypeSymbol, bodyBinder As Binder, syntax As EnumMemberDeclarationSyntax, diagnostics As BindingDiagnosticBag)
                MyBase.New(containingEnum, bodyBinder, syntax, diagnostics)
            End Sub
 
            Protected Overrides Function MakeConstantTuple(dependencies As ConstantFieldsInProgress.Dependencies, diagnostics As BindingDiagnosticBag) As EvaluatedConstant
                Dim underlyingType = ContainingType.EnumUnderlyingType
                Return New EvaluatedConstant(Microsoft.CodeAnalysis.ConstantValue.Default(underlyingType.SpecialType), underlyingType)
            End Function
        End Class
 
        Private NotInheritable Class ExplicitValuedEnumConstantSymbol
            Inherits SourceEnumConstantSymbol
 
            Private ReadOnly _equalsValueNodeRef As SyntaxReference
 
            Public Sub New(containingEnum As SourceNamedTypeSymbol, bodyBinder As Binder, syntax As EnumMemberDeclarationSyntax, initializer As EqualsValueSyntax, diagnostics As BindingDiagnosticBag)
                MyBase.New(containingEnum, bodyBinder, syntax, diagnostics)
                Me._equalsValueNodeRef = bodyBinder.GetSyntaxReference(initializer)
            End Sub
 
            Protected Overrides Function MakeConstantTuple(dependencies As ConstantFieldsInProgress.Dependencies, diagnostics As BindingDiagnosticBag) As EvaluatedConstant
                Return ConstantValueUtils.EvaluateFieldConstant(Me, Me._equalsValueNodeRef, dependencies, diagnostics)
            End Function
        End Class
 
        Private NotInheritable Class ImplicitValuedEnumConstantSymbol
            Inherits SourceEnumConstantSymbol
 
            Private ReadOnly _otherConstant As SourceEnumConstantSymbol
            Private ReadOnly _otherConstantOffset As UInteger
 
            Public Sub New(containingEnum As SourceNamedTypeSymbol, bodyBinder As Binder, syntax As EnumMemberDeclarationSyntax, otherConstant As SourceEnumConstantSymbol, otherConstantOffset As UInteger, diagnostics As BindingDiagnosticBag)
                MyBase.New(containingEnum, bodyBinder, syntax, diagnostics)
                Debug.Assert(otherConstant IsNot Nothing)
                Debug.Assert(otherConstantOffset > 0)
                Me._otherConstant = otherConstant
                Me._otherConstantOffset = otherConstantOffset
            End Sub
 
            Protected Overrides Function MakeConstantTuple(dependencies As ConstantFieldsInProgress.Dependencies, diagnostics As BindingDiagnosticBag) As EvaluatedConstant
#If DEBUG Then
                Debug.Assert(dependencies IsNot Nothing)
#End If
                Dim value As ConstantValue = Microsoft.CodeAnalysis.ConstantValue.Bad
                Dim otherValue = _otherConstant.GetConstantValue(New ConstantFieldsInProgress(Me, dependencies))
                If Not otherValue.IsBad Then
                    Dim overflowKind = EnumConstantHelper.OffsetValue(otherValue, _otherConstantOffset, value)
                    If overflowKind = EnumOverflowKind.OverflowReport Then
                        diagnostics.Add(ERRID.ERR_ExpressionOverflow1, Locations(0), Me)
                    End If
                End If
 
                Return New EvaluatedConstant(value, Type)
            End Function
        End Class
 
#End Region
 
    End Class
End Namespace