File: Symbols\FieldSymbol.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.Generic
Imports System.Collections.Immutable
Imports System.Runtime.InteropServices
Imports System.Threading
Imports Microsoft.CodeAnalysis.Symbols
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports TypeKind = Microsoft.CodeAnalysis.TypeKind
 
Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
    ''' <summary>
    ''' Represents a member variable -- a variable declared as a member of a Class or Structure. 
    ''' </summary>
    Friend MustInherit Class FieldSymbol
        Inherits Symbol
        Implements IFieldSymbol, IFieldSymbolInternal
 
        ' !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        ' Changes to the public interface of this class should remain synchronized with the C# version.
        ' Do not make any changes to the public interface without making the corresponding change
        ' to the C# version.
        ' !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
        Friend Sub New()
        End Sub
 
        ''' <summary>
        ''' Get the original definition of this symbol. If this symbol is derived from another
        ''' symbol by (say) type substitution, this gets the original symbol, as it was defined
        ''' in source or metadata.
        ''' </summary>
        Public Overridable Shadows ReadOnly Property OriginalDefinition As FieldSymbol
            Get
                ' Default implements returns Me.
                Return Me
            End Get
        End Property
 
        Protected NotOverridable Overrides ReadOnly Property OriginalSymbolDefinition As Symbol
            Get
                Return Me.OriginalDefinition
            End Get
        End Property
 
        ''' <summary>
        ''' Gets the type of this variable.
        ''' </summary>
        Public MustOverride ReadOnly Property Type As TypeSymbol
 
        ''' <summary>
        ''' Gets a value indicating whether this instance has declared type. This means a field was declared with an AsClause
        ''' or in case of const fields with an AsClause whose type is not System.Object
        ''' </summary>
        ''' <value>
        ''' <c>true</c> if this instance has declared type; otherwise, <c>false</c>.
        ''' </value>
        Friend Overridable ReadOnly Property HasDeclaredType As Boolean
            Get
                Return True
            End Get
        End Property
 
        ''' <summary>
        ''' The list of custom modifiers, if any, associated with the member variable.
        ''' </summary>
        Public MustOverride ReadOnly Property CustomModifiers As ImmutableArray(Of CustomModifier)
 
        Public MustOverride ReadOnly Property IsRequired As Boolean
 
        ''' <summary>
        ''' If this variable serves as a backing variable for an automatically generated
        ''' property or event, returns that property or event. 
        ''' Otherwise returns Nothing.
        ''' Note, the set of possible associated symbols might be expanded in the future to 
        ''' reflect changes in the languages.
        ''' </summary>
        Public MustOverride ReadOnly Property AssociatedSymbol As Symbol
 
        ''' <summary>
        ''' Returns true if this variable was declared as ReadOnly 
        ''' </summary>
        Public MustOverride ReadOnly Property IsReadOnly As Boolean Implements IFieldSymbol.IsReadOnly
 
        ''' <summary>
        ''' Returns true if this field was declared as "const" (i.e. is a constant declaration), or
        ''' is an Enum member.
        ''' </summary>
        Public MustOverride ReadOnly Property IsConst As Boolean
 
        ''' <summary>
        ''' Gets a value indicating whether this instance is metadata constant. A field is considered to be 
        ''' metadata constant if the field value is a valid default value for a field.
        ''' </summary>
        ''' <value>
        ''' <c>true</c> if this instance is metadata constant; otherwise, <c>false</c>.
        ''' </value>
        Friend ReadOnly Property IsMetadataConstant As Boolean
            Get
                If Me.IsConst Then
                    Dim specialType = Me.Type.SpecialType
                    Return specialType <> Microsoft.CodeAnalysis.SpecialType.System_DateTime AndAlso specialType <> Microsoft.CodeAnalysis.SpecialType.System_Decimal
                End If
 
                Return False
            End Get
        End Property
 
        ''' <summary>
        ''' Gets a value indicating whether this instance is const, but not metadata constant. A field is considered to be 
        ''' const but not metadata constant if the const field's type is either Date or Decimal.
        ''' </summary>
        ''' <value>
        ''' <c>true</c> if this instance is metadata constant; otherwise, <c>false</c>.
        ''' </value>
        Friend ReadOnly Property IsConstButNotMetadataConstant As Boolean
            Get
                If Me.IsConst Then
                    Dim specialType = Me.Type.SpecialType
                    Return specialType = Microsoft.CodeAnalysis.SpecialType.System_DateTime OrElse specialType = Microsoft.CodeAnalysis.SpecialType.System_Decimal
                End If
 
                Return False
            End Get
        End Property
 
        ''' <summary>
        ''' Returns false if the field wasn't declared as "const", or constant value was omitted or erroneous.
        ''' True otherwise.
        ''' </summary>
        Public Overridable ReadOnly Property HasConstantValue As Boolean
            Get
                If Not Me.IsConst Then
                    Return False
                End If
 
                Dim value = GetConstantValue(ConstantFieldsInProgress.Empty)
                Return (value IsNot Nothing) AndAlso Not value.IsBad ' can be null in error scenarios
            End Get
        End Property
 
        ''' <summary>
        ''' If IsConst returns true, then returns the value of the constant or Enum member.
        ''' If IsConst return false, then returns Nothing.
        ''' </summary>
        Public Overridable ReadOnly Property ConstantValue As Object
            Get
                If Not IsConst Then
                    Return Nothing
                End If
 
                Dim value = GetConstantValue(ConstantFieldsInProgress.Empty)
                Return If(value IsNot Nothing, value.Value, Nothing) ' can be null in error scenarios
            End Get
        End Property
 
        ''' <summary>
        ''' Gets the constant value.
        ''' </summary>
        ''' <param name="inProgress">Used to detect dependencies between constant field values.</param>
        Friend MustOverride Function GetConstantValue(inProgress As ConstantFieldsInProgress) As ConstantValue
 
        ''' <summary>
        ''' Const fields do not (always) have to be declared with a given type. To get the inferred type determined from
        ''' the initialization this method should be called instead of "Type". For non const field this method returns the
        ''' declared type.
        ''' </summary>
        ''' <param name="inProgress">Used to detect dependencies between constant field values.</param><returns></returns>
        Friend Overridable Function GetInferredType(inProgress As ConstantFieldsInProgress) As TypeSymbol
            Return Type
        End Function
 
        Public NotOverridable Overrides ReadOnly Property Kind As SymbolKind
            Get
                Return SymbolKind.Field
            End Get
        End Property
 
        Friend Overrides Function Accept(Of TArgument, TResult)(visitor As VisualBasicSymbolVisitor(Of TArgument, TResult), arg As TArgument) As TResult
            Return visitor.VisitField(Me, arg)
        End Function
 
        Public NotOverridable Overrides ReadOnly Property IsMustOverride As Boolean
            Get
                Return False
            End Get
        End Property
 
        Public NotOverridable Overrides ReadOnly Property IsNotOverridable As Boolean
            Get
                Return False
            End Get
        End Property
 
        Public NotOverridable Overrides ReadOnly Property IsOverridable As Boolean
            Get
                Return False
            End Get
        End Property
 
        Public NotOverridable Overrides ReadOnly Property IsOverrides As Boolean
            Get
                Return False
            End Get
        End Property
 
        ''' <summary>
        '''  True if this symbol has a special name (metadata flag SpecialName is set).
        ''' </summary>
        Friend MustOverride ReadOnly Property HasSpecialName As Boolean
 
        ''' <summary>
        ''' True if RuntimeSpecialName metadata flag is set for this symbol.
        ''' </summary>
        Friend MustOverride ReadOnly Property HasRuntimeSpecialName As Boolean
 
        ''' <summary>
        ''' True if NotSerialized metadata flag is set for this symbol.
        ''' </summary>
        Friend MustOverride ReadOnly Property IsNotSerialized As Boolean
 
        ''' <summary>
        ''' Describes how the field is marshalled when passed to native code.
        ''' Null if no specific marshalling information is available for the field.
        ''' </summary>
        ''' <remarks>PE symbols don't provide this information and always return Nothing.</remarks>
        Friend MustOverride ReadOnly Property MarshallingInformation As MarshalPseudoCustomAttributeData
 
        ''' <summary>
        ''' Returns the marshalling type of this field, or 0 if marshalling information isn't available.
        ''' </summary>
        ''' <remarks>
        ''' By default this information is extracted from <see cref="MarshallingInformation"/> if available. 
        ''' Since the compiler does only need to know the marshalling type of symbols that aren't emitted 
        ''' PE symbols just decode the type from metadata and don't provide full marshalling information.
        ''' </remarks>
        Friend Overridable ReadOnly Property MarshallingType As UnmanagedType
            Get
                Dim info = MarshallingInformation
                Return If(info IsNot Nothing, info.UnmanagedType, CType(0, UnmanagedType))
            End Get
        End Property
 
        ''' <summary>
        ''' Offset assigned to the field when the containing type is laid out by the VM.
        ''' Nothing if unspecified.
        ''' </summary>
        Friend MustOverride ReadOnly Property TypeLayoutOffset As Integer?
 
        ''' <summary>
        ''' Get the "this" parameter for this field.  This is only valid for source fields.
        ''' </summary>
        Friend Overridable ReadOnly Property MeParameter As ParameterSymbol
            Get
                Throw ExceptionUtilities.Unreachable
            End Get
        End Property
 
        ''' <summary>
        ''' Returns true when field is a backing field for a captured frame pointer (typically "Me").
        ''' </summary>
        Friend Overridable ReadOnly Property IsCapturedFrame As Boolean
            Get
                Return False
            End Get
        End Property
 
        Friend Overrides Function GetUseSiteInfo() As UseSiteInfo(Of AssemblySymbol)
            If Me.IsDefinition Then
                Return New UseSiteInfo(Of AssemblySymbol)(PrimaryDependency)
            End If
 
            Return Me.OriginalDefinition.GetUseSiteInfo()
        End Function
 
        Friend Function CalculateUseSiteInfo() As UseSiteInfo(Of AssemblySymbol)
 
            Debug.Assert(IsDefinition)
 
            ' Check type.
            Dim useSiteInfo As UseSiteInfo(Of AssemblySymbol) = New UseSiteInfo(Of AssemblySymbol)(PrimaryDependency)
 
            If MergeUseSiteInfo(useSiteInfo, DeriveUseSiteInfoFromType(Me.Type)) Then
                Return useSiteInfo
            End If
 
            ' Check custom modifiers.
            Dim modifiersUseSiteInfo As UseSiteInfo(Of AssemblySymbol) = DeriveUseSiteInfoFromCustomModifiers(Me.CustomModifiers)
 
            If MergeUseSiteInfo(useSiteInfo, modifiersUseSiteInfo) Then
                Return useSiteInfo
            End If
 
            ' If the member is in an assembly with unified references, 
            ' we check if its definition depends on a type from a unified reference.
            If useSiteInfo.DiagnosticInfo Is Nothing AndAlso Me.ContainingModule.HasUnifiedReferences Then
                Dim unificationCheckedTypes As HashSet(Of TypeSymbol) = Nothing
 
                Dim errorInfo As DiagnosticInfo = If(Me.Type.GetUnificationUseSiteDiagnosticRecursive(Me, unificationCheckedTypes),
                                                     GetUnificationUseSiteDiagnosticRecursive(Me.CustomModifiers, Me, unificationCheckedTypes))
 
                If errorInfo IsNot Nothing Then
                    Debug.Assert(errorInfo.Severity = DiagnosticSeverity.Error)
                    useSiteInfo = New UseSiteInfo(Of AssemblySymbol)(errorInfo)
                End If
            End If
 
            Return useSiteInfo
        End Function
 
        ''' <summary>
        ''' Return error code that has highest priority while calculating use site error for this symbol. 
        ''' </summary>
        Protected Overrides Function IsHighestPriorityUseSiteError(code As Integer) As Boolean
            Return code = ERRID.ERR_UnsupportedField1 OrElse code = ERRID.ERR_UnsupportedCompilerFeature
        End Function
 
        Public NotOverridable Overrides ReadOnly Property HasUnsupportedMetadata As Boolean
            Get
                Dim info As DiagnosticInfo = GetUseSiteInfo().DiagnosticInfo
                Return info IsNot Nothing AndAlso (info.Code = ERRID.ERR_UnsupportedField1 OrElse info.Code = ERRID.ERR_UnsupportedCompilerFeature)
            End Get
        End Property
 
        Friend Overrides ReadOnly Property EmbeddedSymbolKind As EmbeddedSymbolKind
            Get
                Return Me.ContainingSymbol.EmbeddedSymbolKind
            End Get
        End Property
 
        ''' <summary>
        ''' Is this a field of a tuple type?
        ''' </summary>
        Public Overridable ReadOnly Property IsTupleField() As Boolean
            Get
                Return False
            End Get
        End Property
 
        ''' <summary>
        ''' Returns True when field symbol is not mapped directly to a field in the underlying tuple struct.
        ''' </summary>
        Public Overridable ReadOnly Property IsVirtualTupleField As Boolean
            Get
                Return False
            End Get
        End Property
 
        ''' <summary>
        ''' Returns true if this is a field representing a Default element like Item1, Item2...
        ''' </summary>
        Public Overridable ReadOnly Property IsDefaultTupleElement As Boolean
            Get
                Return False
            End Get
        End Property
 
        ''' <summary>
        ''' If this is a field of a tuple type, return corresponding underlying field from the
        ''' tuple underlying type. Otherwise, Nothing. In case of a malformed underlying type
        ''' the corresponding underlying field might be missing, return Nothing in this case too.
        ''' </summary>
        Public Overridable ReadOnly Property TupleUnderlyingField() As FieldSymbol
            Get
                Return Nothing
            End Get
        End Property
 
        ''' <summary>
        ''' If this field represents a tuple element, returns a corresponding default element field.
        ''' Otherwise returns Nothing
        ''' </summary>
        Public Overridable ReadOnly Property CorrespondingTupleField As FieldSymbol
            Get
                Return Nothing
            End Get
        End Property
 
        ''' <summary>
        ''' If this is a field representing a tuple element,
        ''' returns the index of the element (zero-based).
        ''' Otherwise returns -1
        ''' </summary>
        Public Overridable ReadOnly Property TupleElementIndex As Integer
            Get
                Return -1
            End Get
        End Property
 
        Friend Function AsMember(newOwner As NamedTypeSymbol) As FieldSymbol
            Debug.Assert(Me Is Me.OriginalDefinition)
            Debug.Assert(newOwner.OriginalDefinition Is Me.ContainingSymbol.OriginalDefinition)
            Return If(TypeSymbol.Equals(newOwner, Me.ContainingType, TypeCompareKind.ConsiderEverything),
                Me,
                DirectCast(DirectCast(newOwner, SubstitutedNamedType).GetMemberForDefinition(Me), FieldSymbol))
        End Function
 
#Region "IFieldSymbol"
 
        Private ReadOnly Property IFieldSymbol_AssociatedSymbol As ISymbol Implements IFieldSymbol.AssociatedSymbol
            Get
                Return Me.AssociatedSymbol
            End Get
        End Property
 
        Private ReadOnly Property IFieldSymbolInternal_Type As ITypeSymbolInternal Implements IFieldSymbolInternal.Type
            Get
                Return Me.Type
            End Get
        End Property
 
        Private ReadOnly Property IFieldSymbolInternal_AssociatedSymbol As ISymbolInternal Implements IFieldSymbolInternal.AssociatedSymbol
            Get
                Return Me.AssociatedSymbol
            End Get
        End Property
 
        Private ReadOnly Property IFieldSymbol_IsConst As Boolean Implements IFieldSymbol.IsConst
            Get
                Return Me.IsConst
            End Get
        End Property
 
        Private ReadOnly Property IFieldSymbol_IsVolatile As Boolean Implements IFieldSymbol.IsVolatile, IFieldSymbolInternal.IsVolatile
            Get
                Return False
            End Get
        End Property
 
        Private ReadOnly Property IFieldSymbol_IsRequired As Boolean Implements IFieldSymbol.IsRequired
            Get
                Return Me.IsRequired
            End Get
        End Property
 
        Private ReadOnly Property IFieldSymbol_IsFixedSizeBuffer As Boolean Implements IFieldSymbol.IsFixedSizeBuffer
            Get
                Return False
            End Get
        End Property
 
        Private ReadOnly Property IFieldSymbol_FixedSize As Integer Implements IFieldSymbol.FixedSize
            Get
                Return 0
            End Get
        End Property
 
        ''' <summary>
        ''' Returns the RefKind of the field. 
        ''' </summary>
        Private ReadOnly Property IFieldSymbol_RefKind As RefKind Implements IFieldSymbol.RefKind
            Get
                Return RefKind.None
            End Get
        End Property
 
        ''' <summary>
        ''' Custom modifiers associated with the ref modifier, or an empty array if there are none.
        ''' </summary>
        Private ReadOnly Property IFieldSymbol_RefCustomModifiers As ImmutableArray(Of CustomModifier) Implements IFieldSymbol.RefCustomModifiers
            Get
                Return ImmutableArray(Of CustomModifier).Empty
            End Get
        End Property
 
        Private ReadOnly Property IFieldSymbol_Type As ITypeSymbol Implements IFieldSymbol.Type
            Get
                Return Me.Type
            End Get
        End Property
 
        Private ReadOnly Property IFieldSymbol_NullableAnnotation As NullableAnnotation Implements IFieldSymbol.NullableAnnotation
            Get
                Return NullableAnnotation.None
            End Get
        End Property
 
        Private ReadOnly Property IFieldSymbol_HasConstantValue As Boolean Implements IFieldSymbol.HasConstantValue
            Get
                Return Me.HasConstantValue
            End Get
        End Property
 
        Private ReadOnly Property IFieldSymbol_ConstantValue As Object Implements IFieldSymbol.ConstantValue
            Get
                Return Me.ConstantValue
            End Get
        End Property
 
        Private ReadOnly Property IFieldSymbol_CustomModifiers As ImmutableArray(Of CustomModifier) Implements IFieldSymbol.CustomModifiers
            Get
                Return Me.CustomModifiers
            End Get
        End Property
 
        Private ReadOnly Property IFieldSymbol_OriginalDefinition As IFieldSymbol Implements IFieldSymbol.OriginalDefinition
            Get
                Return Me.OriginalDefinition
            End Get
        End Property
 
        Private ReadOnly Property IFieldSymbol_CorrespondingTupleField As IFieldSymbol Implements IFieldSymbol.CorrespondingTupleField
            Get
                Return Me.CorrespondingTupleField
            End Get
        End Property
 
        Private ReadOnly Property IFieldSymbol_HasExplicitTupleElementName As Boolean Implements IFieldSymbol.IsExplicitlyNamedTupleElement
            Get
                Return Not Me.IsImplicitlyDeclared
            End Get
        End Property
 
        Public Overrides Sub Accept(visitor As SymbolVisitor)
            visitor.VisitField(Me)
        End Sub
 
        Public Overrides Function Accept(Of TResult)(visitor As SymbolVisitor(Of TResult)) As TResult
            Return visitor.VisitField(Me)
        End Function
 
        Public Overrides Function Accept(Of TArgument, TResult)(visitor As SymbolVisitor(Of TArgument, TResult), argument As TArgument) As TResult
            Return visitor.VisitField(Me, argument)
        End Function
 
        Public Overrides Sub Accept(visitor As VisualBasicSymbolVisitor)
            visitor.VisitField(Me)
        End Sub
 
        Public Overrides Function Accept(Of TResult)(visitor As VisualBasicSymbolVisitor(Of TResult)) As TResult
            Return visitor.VisitField(Me)
        End Function
 
#End Region
 
    End Class
End Namespace