' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. Imports System.Collections.Immutable Imports System.Globalization Imports System.Runtime.InteropServices Imports System.Threading Imports Microsoft.CodeAnalysis.PooledObjects Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.VisualBasic.Symbols Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Friend Class SourceEventSymbol Inherits EventSymbol Implements IAttributeTargetSymbol Private ReadOnly _containingType As SourceMemberContainerTypeSymbol Private ReadOnly _name As String Private ReadOnly _syntaxRef As SyntaxReference Private ReadOnly _location As Location Private ReadOnly _memberFlags As SourceMemberFlags Private ReadOnly _addMethod As MethodSymbol Private ReadOnly _removeMethod As MethodSymbol Private ReadOnly _raiseMethod As MethodSymbol Private ReadOnly _backingField As FieldSymbol ' Misc flags defining the state of this symbol (StateFlags) Private _lazyState As Integer Private Enum StateFlags As Integer IsTypeInferred = &H1 ' Bit value valid once m_lazyType is assigned. IsDelegateFromImplements = &H2 ' Bit value valid once m_lazyType is assigned. ReportedExplicitImplementationDiagnostics = &H4 SymbolDeclaredEvent = &H8 ' Bit value for generating SymbolDeclaredEvent End Enum Private _lazyType As TypeSymbol Private _lazyImplementedEvents As ImmutableArray(Of EventSymbol) Private _lazyDelegateParameters As ImmutableArray(Of ParameterSymbol) Private _lazyDocComment As String Private _lazyExpandedDocComment As String ' Attributes on event. Set once after construction. IsNull means not set. Private _lazyCustomAttributesBag As CustomAttributesBag(Of VisualBasicAttributeData) ''' ''' Indicates whether event created a new delegate type. ''' In such case the Type must be added to the members of the containing type ''' Friend ReadOnly Property IsTypeInferred As Boolean Get Dim unused = Type ' Ensure lazy state is computed. Return (_lazyState And StateFlags.IsTypeInferred) <> 0 End Get End Property Friend Sub New(containingType As SourceMemberContainerTypeSymbol, binder As Binder, syntax As EventStatementSyntax, blockSyntaxOpt As EventBlockSyntax, diagnostics As DiagnosticBag) Debug.Assert(containingType IsNot Nothing) Debug.Assert(syntax IsNot Nothing) _containingType = containingType ' Decode the flags. ' This will validate modifiers against container (i.e. Protected is invalid in a structure...) Dim modifiers = DecodeModifiers(syntax.Modifiers, containingType, binder, diagnostics) _memberFlags = modifiers.AllFlags Dim identifier = syntax.Identifier _name = identifier.ValueText ' Events cannot have type characters If identifier.GetTypeCharacter() <> TypeCharacter.None Then Binder.ReportDiagnostic(diagnostics, identifier, ERRID.ERR_TypecharNotallowed) End If Dim location = identifier.GetLocation() _location = location _syntaxRef = binder.GetSyntaxReference(syntax) binder = New LocationSpecificBinder(BindingLocation.EventSignature, Me, binder) If blockSyntaxOpt IsNot Nothing Then For Each accessorSyntax In blockSyntaxOpt.Accessors Dim accessor As CustomEventAccessorSymbol = BindEventAccessor(accessorSyntax, binder) Select Case (accessor.MethodKind) Case MethodKind.EventAdd If _addMethod Is Nothing Then _addMethod = accessor Else diagnostics.Add(ERRID.ERR_DuplicateAddHandlerDef, accessor.Locations(0)) End If Case MethodKind.EventRemove If _removeMethod Is Nothing Then _removeMethod = accessor Else diagnostics.Add(ERRID.ERR_DuplicateRemoveHandlerDef, accessor.Locations(0)) End If Case MethodKind.EventRaise If _raiseMethod Is Nothing Then _raiseMethod = accessor Else diagnostics.Add(ERRID.ERR_DuplicateRaiseEventDef, accessor.Locations(0)) End If Case Else Throw ExceptionUtilities.UnexpectedValue(accessor.MethodKind) End Select Next If _addMethod Is Nothing Then diagnostics.Add(ERRID.ERR_MissingAddHandlerDef1, location, Me) End If If _removeMethod Is Nothing Then diagnostics.Add(ERRID.ERR_MissingRemoveHandlerDef1, location, Me) End If If _raiseMethod Is Nothing Then diagnostics.Add(ERRID.ERR_MissingRaiseEventDef1, location, Me) End If Else ' Synthesize accessors _addMethod = New SynthesizedAddAccessorSymbol(containingType, Me) _removeMethod = New SynthesizedRemoveAccessorSymbol(containingType, Me) ' if this is a concrete class, add a backing field too If Not containingType.IsInterfaceType Then _backingField = New SynthesizedEventBackingFieldSymbol(Me, Me.Name & EVENT_VARIABLE_SUFFIX, Me.IsShared) End If End If End Sub Private Function ComputeType(diagnostics As DiagnosticBag, ByRef isTypeInferred As Boolean, ByRef isDelegateFromImplements As Boolean) As TypeSymbol Dim binder = CreateBinderForTypeDeclaration() Dim syntax = DirectCast(_syntaxRef.GetSyntax(), EventStatementSyntax) isTypeInferred = False isDelegateFromImplements = False Dim type As TypeSymbol ' TODO: why AsClause is not a SimpleAsClause in events? There can't be "As New" ' WinRT events require either an as-clause or an implements-clause. Dim requiresDelegateType As Boolean = syntax.ImplementsClause Is Nothing AndAlso Me.IsWindowsRuntimeEvent ' if there is an As clause we use its type as event's type If syntax.AsClause IsNot Nothing Then type = binder.DecodeIdentifierType(syntax.Identifier, syntax.AsClause, Nothing, diagnostics) If Not syntax.AsClause.AsKeyword.IsMissing Then If Not type.IsDelegateType Then Binder.ReportDiagnostic(diagnostics, syntax.AsClause.Type, ERRID.ERR_EventTypeNotDelegate) Else Dim invoke = DirectCast(type, NamedTypeSymbol).DelegateInvokeMethod If invoke Is Nothing Then Binder.ReportDiagnostic(diagnostics, syntax.AsClause.Type, ERRID.ERR_UnsupportedType1, type.Name) Else If Not invoke.IsSub Then Binder.ReportDiagnostic(diagnostics, syntax.AsClause.Type, ERRID.ERR_EventDelegatesCantBeFunctions) End If End If End If ElseIf requiresDelegateType Then ' This will always be a cascading diagnostic but, arguably, it does provide additional context ' and dev11 reports it. Binder.ReportDiagnostic(diagnostics, syntax.Identifier, ERRID.ERR_WinRTEventWithoutDelegate) End If Else If requiresDelegateType Then Binder.ReportDiagnostic(diagnostics, syntax.Identifier, ERRID.ERR_WinRTEventWithoutDelegate) End If Dim implementedEvents = ExplicitInterfaceImplementations ' when we have a match with interface event we should take the type from ' the implemented event. If Not implementedEvents.IsEmpty Then ' use the type of the first implemented event Dim implementedEventType = implementedEvents(0).Type ' all other implemented events must be of the same type as the first For i As Integer = 1 To implementedEvents.Length - 1 Dim implemented = implementedEvents(i) If Not implemented.Type.IsSameType(implementedEventType, TypeCompareKind.IgnoreTupleNames) Then Dim errLocation = GetImplementingLocation(implemented) Binder.ReportDiagnostic(diagnostics, errLocation, ERRID.ERR_MultipleEventImplMismatch3, Me, implemented, implemented.ContainingType) End If Next type = implementedEventType isDelegateFromImplements = True Else ' get event's type from the containing type Dim types = _containingType.GetTypeMembers(Me.Name & EVENT_DELEGATE_SUFFIX) Debug.Assert(Not types.IsDefault) type = Nothing For Each candidate In types If candidate.AssociatedSymbol Is Me Then type = candidate Exit For End If Next If type Is Nothing Then ' if we still do not know the type, get a temporary one (it is not a member of the containing class) type = New SynthesizedEventDelegateSymbol(Me._syntaxRef, _containingType) End If isTypeInferred = True End If End If If Not type.IsErrorType() Then AccessCheck.VerifyAccessExposureForMemberType(Me, syntax.Identifier, type, diagnostics, isDelegateFromImplements) End If Return type End Function Private Function ComputeImplementedEvents(diagnostics As DiagnosticBag) As ImmutableArray(Of EventSymbol) Dim syntax = DirectCast(_syntaxRef.GetSyntax(), EventStatementSyntax) Dim implementsClause = syntax.ImplementsClause If implementsClause IsNot Nothing Then Dim binder = CreateBinderForTypeDeclaration() If _containingType.IsInterfaceType Then Dim implementsKeyword = implementsClause.ImplementsKeyword ' // Interface events can't claim to implement anything Binder.ReportDiagnostic(diagnostics, implementsKeyword, ERRID.ERR_InterfaceEventCantUse1, implementsKeyword.ValueText) ElseIf IsShared AndAlso Not _containingType.IsModuleType Then ' // Implementing with shared events is illegal. Binder.ReportDiagnostic(diagnostics, syntax.Modifiers.First(SyntaxKind.SharedKeyword), ERRID.ERR_SharedOnProcThatImpl) Else ' if event is inferred, only signature needs to match ' otherwise event types must match exactly Return ProcessImplementsClause(Of EventSymbol)(implementsClause, Me, _containingType, binder, diagnostics) End If End If Return ImmutableArray(Of EventSymbol).Empty End Function ''' ''' Unless the type is inferred, check that all ''' implemented events have the same type. ''' Private Sub CheckExplicitImplementationTypes() If (_lazyState And (StateFlags.IsTypeInferred Or StateFlags.IsDelegateFromImplements Or StateFlags.ReportedExplicitImplementationDiagnostics)) <> 0 Then Return End If Dim diagnostics As DiagnosticBag = Nothing Dim type = Me.Type For Each implemented In ExplicitInterfaceImplementations If Not implemented.Type.IsSameType(type, TypeCompareKind.IgnoreTupleNames) Then If diagnostics Is Nothing Then diagnostics = DiagnosticBag.GetInstance() End If Dim errLocation = GetImplementingLocation(implemented) diagnostics.Add(ERRID.ERR_EventImplMismatch5, errLocation, {Me, implemented, implemented.ContainingType, type, implemented.Type}) End If Next If diagnostics IsNot Nothing Then ContainingSourceModule.AtomicSetFlagAndStoreDiagnostics(_lazyState, StateFlags.ReportedExplicitImplementationDiagnostics, 0, diagnostics, CompilationStage.Declare) diagnostics.Free() End If End Sub Friend Overrides ReadOnly Property DelegateParameters As ImmutableArray(Of ParameterSymbol) Get If _lazyDelegateParameters.IsDefault Then Dim syntax = DirectCast(_syntaxRef.GetSyntax(), EventStatementSyntax) If syntax.AsClause IsNot Nothing Then ' We can access use the base implementation which relies ' on the Type property since the type in "Event E As D" is explicit. _lazyDelegateParameters = MyBase.DelegateParameters Else ' Avoid using the base implementation since that relies ' on Type which is inferred, potentially from interface ' implementations which relies on DelegateParameters. Dim binder = CreateBinderForTypeDeclaration() Dim diagnostics = DiagnosticBag.GetInstance() ContainingSourceModule.AtomicStoreArrayAndDiagnostics( _lazyDelegateParameters, binder.DecodeParameterListOfDelegateDeclaration(Me, syntax.ParameterList, diagnostics), diagnostics, CompilationStage.Declare) diagnostics.Free() End If End If Return _lazyDelegateParameters End Get End Property Private Function BindEventAccessor(blockSyntax As AccessorBlockSyntax, binder As Binder) As CustomEventAccessorSymbol Dim syntax = blockSyntax.BlockStatement Debug.Assert(syntax.Modifiers.IsEmpty, "event accessors cannot have modifiers") ' Include modifiers from the containing event. Dim flags = Me._memberFlags If Me.IsImplementing Then flags = flags Or SourceMemberFlags.Overrides Or SourceMemberFlags.NotOverridable End If ' All event accessors are subs. Select Case blockSyntax.Kind Case SyntaxKind.AddHandlerAccessorBlock flags = flags Or SourceMemberFlags.MethodKindEventAdd Or SourceMemberFlags.MethodIsSub Case SyntaxKind.RemoveHandlerAccessorBlock flags = flags Or SourceMemberFlags.MethodKindEventRemove Or SourceMemberFlags.MethodIsSub Case SyntaxKind.RaiseEventAccessorBlock flags = flags Or SourceMemberFlags.MethodKindEventRaise Or SourceMemberFlags.MethodIsSub Case Else Throw ExceptionUtilities.UnexpectedValue(blockSyntax.Kind) End Select Dim location = syntax.GetLocation() ' Event symbols aren't affected if the output kind is winmd, mark false Dim method As New CustomEventAccessorSymbol( Me._containingType, Me, binder.GetAccessorName(Me.Name, flags.ToMethodKind(), isWinMd:=False), flags, binder.GetSyntaxReference(syntax), location) ' TODO: Handle custom modifiers, including modifiers. Return method End Function Private Function IsImplementing() As Boolean Return Not ExplicitInterfaceImplementations.IsEmpty End Function ''' ''' Helper method for accessors to get the overridden accessor methods. Should only be called by the ''' accessor method symbols. ''' Friend Function GetAccessorImplementations(kind As MethodKind) As ImmutableArray(Of MethodSymbol) Dim implementedEvents = ExplicitInterfaceImplementations Debug.Assert(Not implementedEvents.IsDefault) If implementedEvents.IsEmpty Then Return ImmutableArray(Of MethodSymbol).Empty Else Dim builder As ArrayBuilder(Of MethodSymbol) = ArrayBuilder(Of MethodSymbol).GetInstance() For Each implementedEvent In implementedEvents Dim accessor As MethodSymbol Select Case kind Case MethodKind.EventAdd accessor = implementedEvent.AddMethod Case MethodKind.EventRemove accessor = implementedEvent.RemoveMethod Case MethodKind.EventRaise accessor = implementedEvent.RaiseMethod Case Else Throw ExceptionUtilities.UnexpectedValue(kind) End Select If accessor IsNot Nothing Then builder.Add(accessor) End If Next Return builder.ToImmutableAndFree() End If End Function Public Overrides ReadOnly Property ContainingSymbol As Symbol Get Return _containingType End Get End Property Public Overrides ReadOnly Property ContainingType As NamedTypeSymbol Get Return _containingType End Get End Property Public ReadOnly Property ContainingSourceModule As SourceModuleSymbol Get Return _containingType.ContainingSourceModule End Get End Property Friend Overrides Function GetLexicalSortKey() As LexicalSortKey ' WARNING: this should not allocate memory! Return New LexicalSortKey(_location, Me.DeclaringCompilation) End Function Public Overrides ReadOnly Property Locations As ImmutableArray(Of Location) Get Return ImmutableArray.Create(_location) End Get End Property Public Overrides ReadOnly Property DeclaringSyntaxReferences As ImmutableArray(Of SyntaxReference) Get Return GetDeclaringSyntaxReferenceHelper(_syntaxRef) End Get End Property Friend NotOverridable Overrides Function IsDefinedInSourceTree(tree As SyntaxTree, definedWithinSpan As TextSpan?, Optional cancellationToken As CancellationToken = Nothing) As Boolean Dim eventBlock = Me._syntaxRef.GetSyntax(cancellationToken).Parent Return IsDefinedInSourceTree(eventBlock, tree, definedWithinSpan, cancellationToken) End Function Public Overrides ReadOnly Property Type As TypeSymbol Get If _lazyType Is Nothing Then Dim diagnostics = DiagnosticBag.GetInstance() Dim isTypeInferred = False Dim isDelegateFromImplements = False Dim eventType = ComputeType(diagnostics, isTypeInferred, isDelegateFromImplements) Dim newState = If(isTypeInferred, StateFlags.IsTypeInferred, 0) Or If(isDelegateFromImplements, StateFlags.IsDelegateFromImplements, 0) ThreadSafeFlagOperations.Set(_lazyState, newState) ContainingSourceModule.AtomicStoreReferenceAndDiagnostics(_lazyType, eventType, diagnostics, CompilationStage.Declare) diagnostics.Free() End If Return _lazyType End Get End Property Public Overrides ReadOnly Property Name As String Get Return _name End Get End Property Public Overrides ReadOnly Property AddMethod As MethodSymbol Get Return _addMethod End Get End Property Public Overrides ReadOnly Property RemoveMethod As MethodSymbol Get Return _removeMethod End Get End Property Public Overrides ReadOnly Property RaiseMethod As MethodSymbol Get Return _raiseMethod End Get End Property Friend Overrides ReadOnly Property AssociatedField As FieldSymbol Get Return _backingField End Get End Property Public Overrides ReadOnly Property ExplicitInterfaceImplementations As ImmutableArray(Of EventSymbol) Get If _lazyImplementedEvents.IsDefault Then Dim diagnostics = DiagnosticBag.GetInstance() ContainingSourceModule.AtomicStoreArrayAndDiagnostics(_lazyImplementedEvents, ComputeImplementedEvents(diagnostics), diagnostics, CompilationStage.Declare) diagnostics.Free() End If Return _lazyImplementedEvents End Get End Property Friend ReadOnly Property SyntaxReference As SyntaxReference Get Return Me._syntaxRef End Get End Property Public Overrides ReadOnly Property IsShared As Boolean Get Return (_memberFlags And SourceMemberFlags.Shared) <> 0 End Get End Property Public Overrides ReadOnly Property IsMustOverride As Boolean Get ' event can be MustOverride if it is defined in an interface Return (_memberFlags And SourceMemberFlags.MustOverride) <> 0 End Get End Property Public Overrides ReadOnly Property IsOverridable As Boolean Get Debug.Assert((_memberFlags And SourceMemberFlags.Overridable) = 0) Return False End Get End Property Public Overrides ReadOnly Property IsOverrides As Boolean Get Debug.Assert((_memberFlags And SourceMemberFlags.Overrides) = 0) Return False End Get End Property Public Overrides ReadOnly Property IsNotOverridable As Boolean Get Debug.Assert((_memberFlags And SourceMemberFlags.NotOverridable) = 0) Return False End Get End Property Public Overrides ReadOnly Property DeclaredAccessibility As Accessibility Get Return CType((_memberFlags And SourceMemberFlags.AccessibilityMask), Accessibility) End Get End Property Friend Overrides ReadOnly Property ShadowsExplicitly As Boolean Get Return (_memberFlags And SourceMemberFlags.Shadows) <> 0 End Get End Property Friend ReadOnly Property AttributeDeclarationSyntaxList As SyntaxList(Of AttributeListSyntax) Get Return DirectCast(_syntaxRef.GetSyntax, EventStatementSyntax).AttributeLists End Get End Property Public ReadOnly Property DefaultAttributeLocation As AttributeLocation Implements IAttributeTargetSymbol.DefaultAttributeLocation Get Return AttributeLocation.Event End Get End Property Friend NotOverridable Overrides ReadOnly Property ObsoleteAttributeData As ObsoleteAttributeData Get ' If there are no attributes then this symbol is not Obsolete. If (Not Me._containingType.AnyMemberHasAttributes) Then Return Nothing End If Dim lazyCustomAttributesBag = Me._lazyCustomAttributesBag If (lazyCustomAttributesBag IsNot Nothing AndAlso lazyCustomAttributesBag.IsEarlyDecodedWellKnownAttributeDataComputed) Then Dim data = DirectCast(_lazyCustomAttributesBag.EarlyDecodedWellKnownAttributeData, CommonEventEarlyWellKnownAttributeData) Return If(data IsNot Nothing, data.ObsoleteAttributeData, Nothing) End If Return ObsoleteAttributeData.Uninitialized End Get End Property ''' ''' Gets the attributes applied on this symbol. ''' Returns an empty array if there are no attributes. ''' ''' ''' NOTE: This method should always be kept as a NotOverridable method. ''' If you want to override attribute binding logic for a sub-class, then override method. ''' Public NotOverridable Overloads Overrides Function GetAttributes() As ImmutableArray(Of VisualBasicAttributeData) Return Me.GetAttributesBag().Attributes End Function Private Function GetAttributesBag() As CustomAttributesBag(Of VisualBasicAttributeData) If _lazyCustomAttributesBag Is Nothing OrElse Not _lazyCustomAttributesBag.IsSealed Then LoadAndValidateAttributes(OneOrMany.Create(Me.AttributeDeclarationSyntaxList), _lazyCustomAttributesBag) End If Return _lazyCustomAttributesBag End Function Friend Function GetDecodedWellKnownAttributeData() As EventWellKnownAttributeData Dim attributesBag As CustomAttributesBag(Of VisualBasicAttributeData) = Me._lazyCustomAttributesBag If attributesBag Is Nothing OrElse Not attributesBag.IsDecodedWellKnownAttributeDataComputed Then attributesBag = Me.GetAttributesBag() End If Return DirectCast(attributesBag.DecodedWellKnownAttributeData, EventWellKnownAttributeData) End Function Friend Overrides Function EarlyDecodeWellKnownAttribute(ByRef arguments As EarlyDecodeWellKnownAttributeArguments(Of EarlyWellKnownAttributeBinder, NamedTypeSymbol, AttributeSyntax, AttributeLocation)) As VisualBasicAttributeData Debug.Assert(arguments.AttributeType IsNot Nothing) Debug.Assert(Not arguments.AttributeType.IsErrorType()) Dim boundAttribute As VisualBasicAttributeData = Nothing Dim obsoleteData As ObsoleteAttributeData = Nothing If EarlyDecodeDeprecatedOrExperimentalOrObsoleteAttribute(arguments, boundAttribute, obsoleteData) Then If obsoleteData IsNot Nothing Then arguments.GetOrCreateData(Of CommonEventEarlyWellKnownAttributeData)().ObsoleteAttributeData = obsoleteData End If Return boundAttribute End If Return MyBase.EarlyDecodeWellKnownAttribute(arguments) End Function Friend Overrides Sub DecodeWellKnownAttribute(ByRef arguments As DecodeWellKnownAttributeArguments(Of AttributeSyntax, VisualBasicAttributeData, AttributeLocation)) Debug.Assert(arguments.AttributeSyntaxOpt IsNot Nothing) Dim attrData = arguments.Attribute If attrData.IsTargetAttribute(Me, AttributeDescription.TupleElementNamesAttribute) Then arguments.Diagnostics.Add(ERRID.ERR_ExplicitTupleElementNamesAttribute, arguments.AttributeSyntaxOpt.Location) End If If attrData.IsTargetAttribute(Me, AttributeDescription.NonSerializedAttribute) Then ' Although NonSerialized attribute is only applicable on fields we relax that restriction and allow application on events as well ' to allow making the backing field non-serializable. If Me.ContainingType.IsSerializable Then arguments.GetOrCreateData(Of EventWellKnownAttributeData).HasNonSerializedAttribute = True Else arguments.Diagnostics.Add(ERRID.ERR_InvalidNonSerializedUsage, arguments.AttributeSyntaxOpt.GetLocation()) End If ElseIf attrData.IsTargetAttribute(Me, AttributeDescription.SpecialNameAttribute) Then arguments.GetOrCreateData(Of EventWellKnownAttributeData).HasSpecialNameAttribute = True ElseIf attrData.IsTargetAttribute(Me, AttributeDescription.ExcludeFromCodeCoverageAttribute) Then arguments.GetOrCreateData(Of EventWellKnownAttributeData).HasExcludeFromCodeCoverageAttribute = True End If MyBase.DecodeWellKnownAttribute(arguments) End Sub Friend NotOverridable Overrides ReadOnly Property IsDirectlyExcludedFromCodeCoverage As Boolean Get Dim data = GetDecodedWellKnownAttributeData() Return data IsNot Nothing AndAlso data.HasExcludeFromCodeCoverageAttribute End Get End Property Friend Overrides ReadOnly Property HasSpecialName As Boolean Get Dim data = GetDecodedWellKnownAttributeData() Return data IsNot Nothing AndAlso data.HasSpecialNameAttribute End Get End Property Public Overrides Function GetDocumentationCommentXml(Optional preferredCulture As CultureInfo = Nothing, Optional expandIncludes As Boolean = False, Optional cancellationToken As CancellationToken = Nothing) As String If expandIncludes Then Return GetAndCacheDocumentationComment(Me, preferredCulture, expandIncludes, _lazyExpandedDocComment, cancellationToken) Else Return GetAndCacheDocumentationComment(Me, preferredCulture, expandIncludes, _lazyDocComment, cancellationToken) End If End Function Friend Shared Function DecodeModifiers(modifiers As SyntaxTokenList, container As SourceMemberContainerTypeSymbol, binder As Binder, diagBag As DiagnosticBag) As MemberModifiers ' Decode the flags. Dim eventModifiers = binder.DecodeModifiers(modifiers, SourceMemberFlags.AllAccessibilityModifiers Or SourceMemberFlags.Shadows Or SourceMemberFlags.Shared, ERRID.ERR_BadEventFlags1, Accessibility.Public, diagBag) eventModifiers = binder.ValidateEventModifiers(modifiers, eventModifiers, container, diagBag) Return eventModifiers End Function ' Get the location of the implements name for an explicit implemented event, for later error reporting. Friend Function GetImplementingLocation(implementedEvent As EventSymbol) As Location Dim eventSyntax = DirectCast(_syntaxRef.GetSyntax(), EventStatementSyntax) Dim syntaxTree = _syntaxRef.SyntaxTree If eventSyntax.ImplementsClause IsNot Nothing Then Dim binder = CreateBinderForTypeDeclaration() Dim implementingSyntax = FindImplementingSyntax(Of EventSymbol)(eventSyntax.ImplementsClause, Me, implementedEvent, _containingType, binder) Return implementingSyntax.GetLocation() End If Return If(Locations.FirstOrDefault(), NoLocation.Singleton) End Function Private Function CreateBinderForTypeDeclaration() As Binder Dim binder = BinderBuilder.CreateBinderForType(ContainingSourceModule, _syntaxRef.SyntaxTree, _containingType) Return New LocationSpecificBinder(BindingLocation.EventSignature, Me, binder) End Function Friend Overrides Sub GenerateDeclarationErrors(cancellationToken As CancellationToken) MyBase.GenerateDeclarationErrors(cancellationToken) Dim unusedType = Me.Type Dim unusedImplementations = Me.ExplicitInterfaceImplementations Me.CheckExplicitImplementationTypes() If DeclaringCompilation.EventQueue IsNot Nothing Then Me.ContainingSourceModule.AtomicSetFlagAndRaiseSymbolDeclaredEvent(_lazyState, StateFlags.SymbolDeclaredEvent, 0, Me) End If End Sub Public Overrides ReadOnly Property IsWindowsRuntimeEvent As Boolean Get ' The first implemented event wins - if the others disagree, we'll produce diagnostics. ' If no interface events are implemented, then the result is based on the output kind of the compilation. Dim implementedEvents As ImmutableArray(Of EventSymbol) = ExplicitInterfaceImplementations Return If(implementedEvents.Any, implementedEvents(0).IsWindowsRuntimeEvent, Me.IsCompilationOutputWinMdObj()) End Get End Property Friend Overrides Sub AddSynthesizedAttributes(compilationState As ModuleCompilationState, ByRef attributes As ArrayBuilder(Of SynthesizedAttributeData)) MyBase.AddSynthesizedAttributes(compilationState, attributes) If Me.Type.ContainsTupleNames() Then AddSynthesizedAttribute(attributes, DeclaringCompilation.SynthesizeTupleNamesAttribute(Type)) End If End Sub End Class End Namespace