File: Symbols\AnonymousTypes\PublicSymbols\AnonymousDelegate_TypePublicSymbol.vb
Web Access
Project: src\src\roslyn\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.Threading
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.Collections
Imports Microsoft.CodeAnalysis.PooledObjects
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax

Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
    Partial Friend NotInheritable Class AnonymousTypeManager

        Friend NotInheritable Class AnonymousDelegatePublicSymbol
            Inherits AnonymousTypeOrDelegatePublicSymbol

            Private ReadOnly _members As ImmutableArray(Of SynthesizedDelegateMethodSymbol)

            Public Sub New(manager As AnonymousTypeManager, typeDescr As AnonymousTypeDescriptor)
                MyBase.New(manager, typeDescr)

                Debug.Assert(typeDescr.IsImplicitlyDeclared)
                Debug.Assert(typeDescr.Parameters.Length > 0)
                Debug.Assert(typeDescr.Parameters.Last().Name Is AnonymousTypeDescriptor.FunctionReturnParameterName OrElse
                             typeDescr.Parameters.Last().Name Is AnonymousTypeDescriptor.SubReturnParameterName)

                Dim parameterDescriptors As ImmutableArray(Of AnonymousTypeField) = typeDescr.Parameters
                Dim returnType As TypeSymbol = If(parameterDescriptors.IsSubDescription(), DirectCast(manager.System_Void, TypeSymbol), parameterDescriptors.Last.Type)
                Dim parameters = ArrayBuilder(Of ParameterSymbol).GetInstance(parameterDescriptors.Length + 1)
                Dim i As Integer

                ' A delegate has the following members: (see CLI spec 13.6)
                ' (1) a method named Invoke with the specified signature
                Dim delegateInvoke = New SynthesizedDelegateMethodSymbol(WellKnownMemberNames.DelegateInvokeName,
                                                                         Me,
                                                                         SourceNamedTypeSymbol.DelegateCommonMethodFlags Or SourceMemberFlags.MethodKindDelegateInvoke,
                                                                         returnType)

                For i = 0 To parameterDescriptors.Length - 2
                    parameters.Add(ParameterFromField(delegateInvoke, parameterDescriptors(i), i))
                Next

                delegateInvoke.SetParameters(parameters.ToImmutable())
                parameters.Clear()

                ' (2) a constructor with argument types (object, System.IntPtr)
                Dim delegateCtor = New SynthesizedDelegateMethodSymbol(
                                                WellKnownMemberNames.InstanceConstructorName, Me,
                                                SourceNamedTypeSymbol.DelegateConstructorMethodFlags, manager.System_Void)
                delegateCtor.SetParameters(
                    ImmutableArray.Create(Of ParameterSymbol)(
                           New SynthesizedParameterSymbol(delegateCtor, manager.System_Object, 0,
                                                          False, StringConstants.DelegateConstructorInstanceParameterName),
                           New SynthesizedParameterSymbol(delegateCtor, manager.System_IntPtr, 1,
                                                          False, StringConstants.DelegateConstructorMethodParameterName)
                           ))

                Dim delegateBeginInvoke As SynthesizedDelegateMethodSymbol
                Dim delegateEndInvoke As SynthesizedDelegateMethodSymbol

                ' Don't add Begin/EndInvoke members to winmd compilations.
                ' Invoke must be the last member, regardless.
                If Me.IsCompilationOutputWinMdObj() Then
                    delegateBeginInvoke = Nothing
                    delegateEndInvoke = Nothing

                    parameters.Free()

                    _members = ImmutableArray.Create(delegateCtor, delegateInvoke)
                Else
                    ' (3) BeginInvoke
                    delegateBeginInvoke = New SynthesizedDelegateMethodSymbol(
                                                        WellKnownMemberNames.DelegateBeginInvokeName, Me,
                                                        SourceNamedTypeSymbol.DelegateCommonMethodFlags Or SourceMemberFlags.MethodKindOrdinary,
                                                        manager.System_IAsyncResult)

                    For i = 0 To parameterDescriptors.Length - 2
                        parameters.Add(ParameterFromField(delegateBeginInvoke, parameterDescriptors(i), i))
                    Next

                    parameters.Add(New SynthesizedParameterSymbol(delegateBeginInvoke, manager.System_AsyncCallback, i,
                                                                  False, StringConstants.DelegateMethodCallbackParameterName))
                    i += 1
                    parameters.Add(New SynthesizedParameterSymbol(delegateBeginInvoke, manager.System_Object, i,
                                                                  False, StringConstants.DelegateMethodInstanceParameterName))
                    delegateBeginInvoke.SetParameters(parameters.ToImmutable())
                    parameters.Clear()

                    ' and (4) EndInvoke methods
                    delegateEndInvoke = New SynthesizedDelegateMethodSymbol(
                                                        WellKnownMemberNames.DelegateEndInvokeName, Me,
                                                        SourceNamedTypeSymbol.DelegateCommonMethodFlags Or SourceMemberFlags.MethodKindOrdinary,
                                                        returnType)

                    Dim ordinal As Integer = 0
                    For i = 0 To parameterDescriptors.Length - 2
                        If parameterDescriptors(i).IsByRef Then
                            parameters.Add(ParameterFromField(delegateEndInvoke, parameterDescriptors(i), ordinal))
                            ordinal += 1
                        End If
                    Next

                    parameters.Add(New SynthesizedParameterSymbol(delegateEndInvoke, manager.System_IAsyncResult, ordinal,
                                                                  False, StringConstants.DelegateMethodResultParameterName))
                    delegateEndInvoke.SetParameters(parameters.ToImmutableAndFree())

                    _members = ImmutableArray.Create(delegateCtor, delegateBeginInvoke, delegateEndInvoke, delegateInvoke)
                End If

#If DEBUG Then
                For Each m In _members
                    Debug.Assert(m IsNot Nothing)
                Next
#End If
            End Sub

            Public Overrides ReadOnly Property TypeKind As TypeKind
                Get
                    Return TypeKind.Delegate
                End Get
            End Property

            Friend Overrides ReadOnly Property IsInterface As Boolean
                Get
                    Return False
                End Get
            End Property

            Private Shared Function ParameterFromField(container As SynthesizedDelegateMethodSymbol, field As AnonymousTypeField, ordinal As Integer) As ParameterSymbol
                Return New SynthesizedParameterWithLocationSymbol(container, field.Type, ordinal, field.IsByRef, field.Name, field.Location)
            End Function

            Public Overrides Function GetMembers() As ImmutableArray(Of Symbol)
                Return StaticCast(Of Symbol).From(_members)
            End Function

            Friend Overrides Function InternalSubstituteTypeParameters(substitution As TypeSubstitution) As TypeWithModifiers
                Dim newDescriptor As New AnonymousTypeDescriptor
                If Not Me.TypeDescriptor.SubstituteTypeParametersIfNeeded(substitution, newDescriptor) Then
                    Return New TypeWithModifiers(Me)
                End If

                Return New TypeWithModifiers(Me.Manager.ConstructAnonymousDelegateSymbol(newDescriptor))
            End Function

            Public Overrides Function MapToImplementationSymbol() As NamedTypeSymbol
                Return Me.Manager.ConstructAnonymousDelegateImplementationSymbol(Me)
            End Function

            Friend Overrides Function MakeAcyclicBaseType(diagnostics As BindingDiagnosticBag) As NamedTypeSymbol
                Return Manager.System_MulticastDelegate
            End Function

            Friend Overrides Function MakeAcyclicInterfaces(diagnostics As BindingDiagnosticBag) As ImmutableArray(Of NamedTypeSymbol)
                Return ImmutableArray(Of NamedTypeSymbol).Empty
            End Function

            Public Overrides ReadOnly Property DelegateInvokeMethod As MethodSymbol
                Get
                    ' In both regular and winmd, the last member is invoke
                    Return _members(_members.Length - 1)
                End Get
            End Property

        End Class

    End Class
End Namespace