File: Emit\NoPia\EmbeddedEvent.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 Microsoft.CodeAnalysis.Emit
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
 
#If Not DEBUG Then
Imports EventSymbolAdapter = Microsoft.CodeAnalysis.VisualBasic.Symbols.EventSymbol
#End If
 
Namespace Microsoft.CodeAnalysis.VisualBasic.Emit.NoPia
 
    Friend NotInheritable Class EmbeddedEvent
        Inherits EmbeddedTypesManager.CommonEmbeddedEvent
 
        Public Sub New(underlyingEvent As EventSymbolAdapter, adder As EmbeddedMethod, remover As EmbeddedMethod, caller As EmbeddedMethod)
            MyBase.New(underlyingEvent, adder, remover, caller)
        End Sub
 
        Protected Overrides Function GetCustomAttributesToEmit(moduleBuilder As PEModuleBuilder) As IEnumerable(Of VisualBasicAttributeData)
            Return UnderlyingEvent.AdaptedEventSymbol.GetCustomAttributesToEmit(moduleBuilder)
        End Function
 
        Protected Overrides ReadOnly Property IsRuntimeSpecial As Boolean
            Get
                Return UnderlyingEvent.AdaptedEventSymbol.HasRuntimeSpecialName
            End Get
        End Property
 
        Protected Overrides ReadOnly Property IsSpecialName As Boolean
            Get
                Return UnderlyingEvent.AdaptedEventSymbol.HasSpecialName
            End Get
        End Property
 
        Protected Overrides Function [GetType](moduleBuilder As PEModuleBuilder, syntaxNodeOpt As SyntaxNode, diagnostics As DiagnosticBag) As Cci.ITypeReference
            Return moduleBuilder.Translate(UnderlyingEvent.AdaptedEventSymbol.Type, syntaxNodeOpt, diagnostics)
        End Function
 
        Protected Overrides ReadOnly Property ContainingType As EmbeddedType
            Get
                Return AnAccessor.ContainingType
            End Get
        End Property
 
        Protected Overrides ReadOnly Property Visibility As Cci.TypeMemberVisibility
            Get
                Return UnderlyingEvent.AdaptedEventSymbol.MetadataVisibility
            End Get
        End Property
 
        Protected Overrides ReadOnly Property Name As String
            Get
                Return UnderlyingEvent.AdaptedEventSymbol.MetadataName
            End Get
        End Property
 
        Protected Overrides Sub EmbedCorrespondingComEventInterfaceMethodInternal(syntaxNodeOpt As SyntaxNode, diagnostics As DiagnosticBag, isUsedForComAwareEventBinding As Boolean)
            ' If the event happens to belong to a class with a ComEventInterfaceAttribute, there will also be
            ' a paired method living on its source interface. The ComAwareEventInfo class expects to find this 
            ' method through reflection. If we embed an event, therefore, we must ensure that the associated source
            ' interface method is also included, even if it is not otherwise referenced in the embedding project.
            Dim underlyingContainingType = ContainingType.UnderlyingNamedType
 
            For Each attrData In underlyingContainingType.AdaptedNamedTypeSymbol.GetAttributes()
                Dim signatureIndex As Integer = attrData.GetTargetAttributeSignatureIndex(AttributeDescription.ComEventInterfaceAttribute)
 
                If signatureIndex = 0 Then
                    Dim foundMatch = False
                    Dim sourceInterface As NamedTypeSymbol = Nothing
 
                    Dim errorInfo As DiagnosticInfo = attrData.ErrorInfo
                    If errorInfo IsNot Nothing Then
                        diagnostics.Add(errorInfo, If(syntaxNodeOpt?.Location, NoLocation.Singleton))
                    End If
 
                    If Not attrData.HasErrors Then
                        sourceInterface = TryCast(attrData.CommonConstructorArguments(0).ValueInternal, NamedTypeSymbol)
                        If sourceInterface IsNot Nothing Then
                            foundMatch = EmbedMatchingInterfaceMethods(sourceInterface, syntaxNodeOpt, diagnostics)
 
                            For Each source In sourceInterface.AllInterfacesNoUseSiteDiagnostics
                                If EmbedMatchingInterfaceMethods(source, syntaxNodeOpt, diagnostics) Then
                                    foundMatch = True
                                End If
                            Next
                        End If
                    End If
 
                    If Not foundMatch AndAlso isUsedForComAwareEventBinding Then
                        If sourceInterface Is Nothing Then
                            ' ERRID_SourceInterfaceMustBeInterface/ERR_MissingSourceInterface
                            EmbeddedTypesManager.ReportDiagnostic(diagnostics, ERRID.ERR_SourceInterfaceMustBeInterface, syntaxNodeOpt, underlyingContainingType.AdaptedNamedTypeSymbol, UnderlyingEvent.AdaptedEventSymbol)
                        Else
                            Dim useSiteInfo = CompoundUseSiteInfo(Of AssemblySymbol).DiscardedDependencies
                            sourceInterface.AllInterfacesWithDefinitionUseSiteDiagnostics(useSiteInfo)
                            diagnostics.Add(If(syntaxNodeOpt Is Nothing, NoLocation.Singleton, syntaxNodeOpt.GetLocation()), useSiteInfo.Diagnostics)
 
                            ' ERRID_EventNoPIANoBackingMember/ERR_MissingMethodOnSourceInterface
                            EmbeddedTypesManager.ReportDiagnostic(diagnostics, ERRID.ERR_EventNoPIANoBackingMember, syntaxNodeOpt, sourceInterface, UnderlyingEvent.AdaptedEventSymbol.MetadataName, UnderlyingEvent.AdaptedEventSymbol)
                        End If
                    End If
 
                    Exit For
                End If
            Next
        End Sub
 
        Private Function EmbedMatchingInterfaceMethods(sourceInterface As NamedTypeSymbol, syntaxNodeOpt As SyntaxNode, diagnostics As DiagnosticBag) As Boolean
            Dim foundMatch = False
            For Each m In sourceInterface.GetMembers(UnderlyingEvent.AdaptedEventSymbol.MetadataName)
                If m.Kind = SymbolKind.Method Then
                    TypeManager.EmbedMethodIfNeedTo(DirectCast(m, MethodSymbol).GetCciAdapter(), syntaxNodeOpt, diagnostics)
                    foundMatch = True
                End If
            Next
            Return foundMatch
        End Function
 
    End Class
 
End Namespace