File: Lowering\StateMachineRewriter\SynthesizedStateMachineMethod.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.PooledObjects
Imports Microsoft.CodeAnalysis.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Emit
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
 
Namespace Microsoft.CodeAnalysis.VisualBasic
    ''' <summary>
    ''' This class represents a type symbol for compiler generated implementation methods,
    ''' the method being implemented is passed as a parameter and is used to build
    ''' implementation method's parameters, return value type, etc...
    ''' </summary>
    Friend MustInherit Class SynthesizedStateMachineMethod
        Inherits SynthesizedMethod
        Implements ISynthesizedMethodBodyImplementationSymbol
 
        Private ReadOnly _interfaceMethod As MethodSymbol
        Private ReadOnly _parameters As ImmutableArray(Of ParameterSymbol)
        Private ReadOnly _locations As ImmutableArray(Of Location)
        Private ReadOnly _accessibility As Accessibility
        Private ReadOnly _generateDebugInfo As Boolean
        Private ReadOnly _hasMethodBodyDependency As Boolean
        Private ReadOnly _associatedProperty As PropertySymbol
 
        Protected Sub New(stateMachineType As StateMachineTypeSymbol,
                          name As String,
                          interfaceMethod As MethodSymbol,
                          syntax As SyntaxNode,
                          declaredAccessibility As Accessibility,
                          generateDebugInfo As Boolean,
                          hasMethodBodyDependency As Boolean,
                          Optional associatedProperty As PropertySymbol = Nothing)
 
            MyBase.New(syntax, stateMachineType, name, isShared:=False)
 
            Me._locations = ImmutableArray.Create(syntax.GetLocation())
            Me._accessibility = declaredAccessibility
            Me._generateDebugInfo = generateDebugInfo
            Me._hasMethodBodyDependency = hasMethodBodyDependency
 
            Debug.Assert(Not interfaceMethod.IsGenericMethod)
            Me._interfaceMethod = interfaceMethod
 
            Dim params(Me._interfaceMethod.ParameterCount - 1) As ParameterSymbol
            For i = 0 To params.Length - 1
                Dim curParam = Me._interfaceMethod.Parameters(i)
                Debug.Assert(Not curParam.IsOptional)
                Debug.Assert(Not curParam.HasExplicitDefaultValue)
                params(i) = SynthesizedMethod.WithNewContainerAndType(Me, curParam.Type, curParam)
            Next
            Me._parameters = params.AsImmutableOrNull()
 
            Me._associatedProperty = associatedProperty
        End Sub
 
        Public ReadOnly Property StateMachineType As StateMachineTypeSymbol
            Get
                Return DirectCast(ContainingSymbol, StateMachineTypeSymbol)
            End Get
        End Property
 
        Friend Overrides ReadOnly Property TypeMap As TypeSubstitution
            Get
                Return Nothing
            End Get
        End Property
 
        Public Overrides ReadOnly Property TypeArguments As ImmutableArray(Of TypeSymbol)
            Get
                Return ImmutableArray(Of TypeSymbol).Empty
            End Get
        End Property
 
        Public Overrides ReadOnly Property Locations As ImmutableArray(Of Location)
            Get
                Return Me._locations
            End Get
        End Property
 
        Public Overrides ReadOnly Property Parameters As ImmutableArray(Of ParameterSymbol)
            Get
                Return Me._parameters
            End Get
        End Property
 
        Public Overrides ReadOnly Property ReturnType As TypeSymbol
            Get
                Return Me._interfaceMethod.ReturnType
            End Get
        End Property
 
        Public Overrides ReadOnly Property IsShared As Boolean
            Get
                Return False
            End Get
        End Property
 
        Public Overrides ReadOnly Property IsSub As Boolean
            Get
                Return Me._interfaceMethod.IsSub
            End Get
        End Property
 
        Public Overrides ReadOnly Property IsVararg As Boolean
            Get
                Return Me._interfaceMethod.IsVararg
            End Get
 
        End Property
 
        Public Overrides ReadOnly Property Arity As Integer
            Get
                Return 0
            End Get
        End Property
 
        Public Overrides ReadOnly Property DeclaredAccessibility As Accessibility
            Get
                Return Me._accessibility
            End Get
        End Property
 
        Friend Overrides ReadOnly Property ParameterCount As Integer
            Get
                Return Me._parameters.Length
            End Get
        End Property
 
        Friend Overrides ReadOnly Property HasSpecialName As Boolean
            Get
                Return False
            End Get
        End Property
 
        Public Overrides ReadOnly Property ExplicitInterfaceImplementations As ImmutableArray(Of MethodSymbol)
            Get
                Return ImmutableArray.Create(Me._interfaceMethod)
            End Get
        End Property
 
        Public Overrides ReadOnly Property AssociatedSymbol As Symbol
            Get
                Return Me._associatedProperty
            End Get
        End Property
 
        Friend Overrides Function IsMetadataNewSlot(Optional ignoreInterfaceImplementationChanges As Boolean = False) As Boolean
            Return True
        End Function
 
        Friend Overrides ReadOnly Property GenerateDebugInfoImpl As Boolean
            Get
                Return Me._generateDebugInfo
            End Get
        End Property
 
        Friend Overrides Function CalculateLocalSyntaxOffset(localPosition As Integer, localTree As SyntaxTree) As Integer
            Return Me.StateMachineType.KickoffMethod.CalculateLocalSyntaxOffset(localPosition, localTree)
        End Function
 
        Public ReadOnly Property HasMethodBodyDependency As Boolean Implements ISynthesizedMethodBodyImplementationSymbol.HasMethodBodyDependency
            Get
                Return _hasMethodBodyDependency
            End Get
        End Property
 
        Public ReadOnly Property Method As IMethodSymbolInternal Implements ISynthesizedMethodBodyImplementationSymbol.Method
            Get
                Return StateMachineType.KickoffMethod
            End Get
        End Property
    End Class
 
    ''' <summary>
    ''' Represents a state machine MoveNext method.
    ''' Handles special behavior around inheriting some attributes from the original async/iterator method.
    ''' </summary>
    Friend NotInheritable Class SynthesizedStateMachineMoveNextMethod
        Inherits SynthesizedStateMachineMethod
 
        Private _attributes As ImmutableArray(Of VisualBasicAttributeData)
 
        Friend Sub New(stateMachineType As StateMachineTypeSymbol,
                       interfaceMethod As MethodSymbol,
                       syntax As SyntaxNode,
                       declaredAccessibility As Accessibility)
            MyBase.New(stateMachineType, WellKnownMemberNames.MoveNextMethodName, interfaceMethod, syntax, declaredAccessibility, generateDebugInfo:=True, hasMethodBodyDependency:=True)
        End Sub
 
        Friend Overrides Sub AddSynthesizedAttributes(moduleBuilder As PEModuleBuilder, ByRef attributes As ArrayBuilder(Of SynthesizedAttributeData))
            MyBase.AddSynthesizedAttributes(moduleBuilder, attributes)
 
            Debug.Assert(WellKnownMembers.IsSynthesizedAttributeOptional(WellKnownMember.System_Runtime_CompilerServices_CompilerGeneratedAttribute__ctor))
            Dim compilation = Me.DeclaringCompilation
            AddSynthesizedAttribute(attributes, compilation.TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_CompilerGeneratedAttribute__ctor))
        End Sub
 
        Public Overrides Function GetAttributes() As ImmutableArray(Of VisualBasicAttributeData)
            If _attributes.IsDefault Then
                Debug.Assert(MyBase.GetAttributes().Length = 0)
 
                Dim builder As ArrayBuilder(Of VisualBasicAttributeData) = Nothing
 
                ' Inherit some attributes from the kickoff method
                Dim kickoffMethod = StateMachineType.KickoffMethod
                For Each attribute In kickoffMethod.GetAttributes()
                    If attribute.IsTargetAttribute(AttributeDescription.DebuggerHiddenAttribute) OrElse
                       attribute.IsTargetAttribute(AttributeDescription.DebuggerNonUserCodeAttribute) OrElse
                       attribute.IsTargetAttribute(AttributeDescription.DebuggerStepperBoundaryAttribute) OrElse
                       attribute.IsTargetAttribute(AttributeDescription.DebuggerStepThroughAttribute) Then
                        If builder Is Nothing Then
                            builder = ArrayBuilder(Of VisualBasicAttributeData).GetInstance(4) ' only 4 different attributes are inherited at the moment
                        End If
 
                        builder.Add(attribute)
                    End If
                Next
 
                ImmutableInterlocked.InterlockedCompareExchange(_attributes,
                                                                If(builder Is Nothing, ImmutableArray(Of VisualBasicAttributeData).Empty, builder.ToImmutableAndFree()),
                                                                Nothing)
            End If
 
            Return _attributes
        End Function
    End Class
 
    ''' <summary>
    ''' Represents a state machine method other than a MoveNext method.
    ''' All such methods are considered non-user code. 
    ''' </summary>
    Friend NotInheritable Class SynthesizedStateMachineDebuggerNonUserCodeMethod
        Inherits SynthesizedStateMachineMethod
 
        Friend Sub New(stateMachineType As StateMachineTypeSymbol,
                       name As String,
                       interfaceMethod As MethodSymbol,
                       syntax As SyntaxNode,
                       declaredAccessibility As Accessibility,
                       hasMethodBodyDependency As Boolean,
                       Optional associatedProperty As PropertySymbol = Nothing)
            MyBase.New(stateMachineType, name, interfaceMethod, syntax, declaredAccessibility, generateDebugInfo:=False,
                       hasMethodBodyDependency:=hasMethodBodyDependency, associatedProperty:=associatedProperty)
        End Sub
 
        Friend Overrides Sub AddSynthesizedAttributes(moduleBuilder As PEModuleBuilder, ByRef attributes As ArrayBuilder(Of SynthesizedAttributeData))
            MyBase.AddSynthesizedAttributes(moduleBuilder, attributes)
 
            Debug.Assert(WellKnownMembers.IsSynthesizedAttributeOptional(WellKnownMember.System_Diagnostics_DebuggerNonUserCodeAttribute__ctor))
            Dim compilation = Me.DeclaringCompilation
            AddSynthesizedAttribute(attributes, compilation.SynthesizeDebuggerNonUserCodeAttribute())
        End Sub
    End Class
 
End Namespace