internal SourceFieldLikeEventSymbol(SourceMemberContainerTypeSymbol containingType, Binder binder, SyntaxTokenList modifiers, VariableDeclaratorSyntax declaratorSyntax, DiagnosticBag diagnostics) : base(containingType, declaratorSyntax, modifiers, isFieldLike: true, interfaceSpecifierSyntaxOpt: null, nameTokenSyntax: declaratorSyntax.Identifier, diagnostics: diagnostics) { _name = declaratorSyntax.Identifier.ValueText; var declaratorDiagnostics = DiagnosticBag.GetInstance(); var declarationSyntax = (VariableDeclarationSyntax)declaratorSyntax.Parent; _type = BindEventType(binder, declarationSyntax.Type, declaratorDiagnostics); // The runtime will not treat the accessors of this event as overrides or implementations // of those of another event unless both the signatures and the custom modifiers match. // Hence, in the case of overrides and *explicit* implementations (not possible for field-like // events), we need to copy the custom modifiers that are in the signatures of the // overridden/implemented event accessors. (From source, we know that there can only be one // overridden/implemented event, so there are no conflicts.) This is unnecessary for implicit // implementations because, if the custom modifiers don't match, we'll insert bridge methods // for the accessors (explicit implementations that delegate to the implicit implementations) // with the correct custom modifiers (see SourceMemberContainerTypeSymbol.SynthesizeInterfaceMemberImplementation). // If this event is an override, we may need to copy custom modifiers from // the overridden event (so that the runtime will recognize it as an override). // We check for this case here, while we can still modify the parameters and // return type without losing the appearance of immutability. if (this.IsOverride) { EventSymbol overriddenEvent = this.OverriddenEvent; if ((object)overriddenEvent != null) { CopyEventCustomModifiers(overriddenEvent, ref _type, ContainingAssembly); } } bool hasInitializer = declaratorSyntax.Initializer != null; bool inInterfaceType = containingType.IsInterfaceType(); if (hasInitializer) { if (inInterfaceType && !this.IsStatic) { diagnostics.Add(ErrorCode.ERR_InterfaceEventInitializer, this.Locations[0], this); } else if (this.IsAbstract) { diagnostics.Add(ErrorCode.ERR_AbstractEventInitializer, this.Locations[0], this); } } // NOTE: if there's an initializer in source, we'd better create a backing field, regardless of // whether or not the initializer is legal. if (hasInitializer || !(this.IsExtern || this.IsAbstract)) { _associatedField = MakeAssociatedField(declaratorSyntax); // Don't initialize this.type - we'll just use the type of the field (which is lazy and handles var) } if (!IsStatic && ContainingType.IsReadOnly) { diagnostics.Add(ErrorCode.ERR_FieldlikeEventsInRoStruct, this.Locations[0]); } if (inInterfaceType) { if (this.IsExtern || this.IsStatic) { if (!ContainingAssembly.RuntimeSupportsDefaultInterfaceImplementation) { diagnostics.Add(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, this.Locations[0]); } } else if (!this.IsAbstract) { diagnostics.Add(ErrorCode.ERR_EventNeedsBothAccessors, this.Locations[0], this); } } // Accessors will assume that Type is available. _addMethod = new SynthesizedFieldLikeEventAccessorSymbol(this, isAdder: true); _removeMethod = new SynthesizedFieldLikeEventAccessorSymbol(this, isAdder: false); if (declarationSyntax.Variables[0] == declaratorSyntax) { // Don't report these diagnostics for every declarator in this declaration. diagnostics.AddRange(declaratorDiagnostics); } declaratorDiagnostics.Free(); }
internal SourceCustomEventSymbol(SourceMemberContainerTypeSymbol containingType, Binder binder, EventDeclarationSyntax syntax, DiagnosticBag diagnostics) : base(containingType, syntax, syntax.Modifiers, syntax.ExplicitInterfaceSpecifier, syntax.Identifier, diagnostics) { ExplicitInterfaceSpecifierSyntax interfaceSpecifier = syntax.ExplicitInterfaceSpecifier; SyntaxToken nameToken = syntax.Identifier; bool isExplicitInterfaceImplementation = interfaceSpecifier != null; string aliasQualifierOpt; _name = ExplicitInterfaceHelpers.GetMemberNameAndInterfaceSymbol(binder, interfaceSpecifier, nameToken.ValueText, diagnostics, out _explicitInterfaceType, out aliasQualifierOpt); _type = BindEventType(binder, syntax.Type, diagnostics); var explicitlyImplementedEvent = this.FindExplicitlyImplementedEvent(_explicitInterfaceType, nameToken.ValueText, interfaceSpecifier, diagnostics); // The runtime will not treat the accessors of this event as overrides or implementations // of those of another event unless both the signatures and the custom modifiers match. // Hence, in the case of overrides and *explicit* implementations, we need to copy the custom // modifiers that are in the signatures of the overridden/implemented event accessors. // (From source, we know that there can only be one overridden/implemented event, so there // are no conflicts.) This is unnecessary for implicit implementations because, if the custom // modifiers don't match, we'll insert bridge methods for the accessors (explicit implementations // that delegate to the implicit implementations) with the correct custom modifiers // (see SourceNamedTypeSymbol.ImplementInterfaceMember). // Note: we're checking if the syntax indicates explicit implementation rather, // than if explicitInterfaceType is null because we don't want to look for an // overridden event if this is supposed to be an explicit implementation. if (!isExplicitInterfaceImplementation) { // If this event is an override, we may need to copy custom modifiers from // the overridden event (so that the runtime will recognize it as an override). // We check for this case here, while we can still modify the parameters and // return type without losing the appearance of immutability. if (this.IsOverride) { EventSymbol overriddenEvent = this.OverriddenEvent; if ((object)overriddenEvent != null) { CopyEventCustomModifiers(overriddenEvent, ref _type, ContainingAssembly); } } } else if ((object)explicitlyImplementedEvent != null) { CopyEventCustomModifiers(explicitlyImplementedEvent, ref _type, ContainingAssembly); } AccessorDeclarationSyntax addSyntax = null; AccessorDeclarationSyntax removeSyntax = null; foreach (AccessorDeclarationSyntax accessor in syntax.AccessorList.Accessors) { switch (accessor.Kind()) { case SyntaxKind.AddAccessorDeclaration: if (addSyntax == null || addSyntax.Keyword.Span.IsEmpty) { addSyntax = accessor; } break; case SyntaxKind.RemoveAccessorDeclaration: if (removeSyntax == null || removeSyntax.Keyword.Span.IsEmpty) { removeSyntax = accessor; } break; } } _addMethod = CreateAccessorSymbol(addSyntax, explicitlyImplementedEvent, aliasQualifierOpt, diagnostics); _removeMethod = CreateAccessorSymbol(removeSyntax, explicitlyImplementedEvent, aliasQualifierOpt, diagnostics); if (containingType.IsInterfaceType()) { if (addSyntax == null && removeSyntax == null) //NOTE: AND - different error code produced if one is present { // CONSIDER: we're matching dev10, but it would probably be more helpful to give // an error like ERR_EventPropertyInInterface. diagnostics.Add(ErrorCode.ERR_EventNeedsBothAccessors, this.Locations[0], this); } } else { if (addSyntax == null || removeSyntax == null) { diagnostics.Add(ErrorCode.ERR_EventNeedsBothAccessors, this.Locations[0], this); } } _explicitInterfaceImplementations = (object)explicitlyImplementedEvent == null ? ImmutableArray<EventSymbol>.Empty : ImmutableArray.Create<EventSymbol>(explicitlyImplementedEvent); }
internal SourceCustomEventSymbol(SourceMemberContainerTypeSymbol containingType, Binder binder, EventDeclarationSyntax syntax, DiagnosticBag diagnostics) : base(containingType, syntax, syntax.Modifiers, syntax.ExplicitInterfaceSpecifier, syntax.Identifier, diagnostics) { ExplicitInterfaceSpecifierSyntax interfaceSpecifier = syntax.ExplicitInterfaceSpecifier; SyntaxToken nameToken = syntax.Identifier; bool isExplicitInterfaceImplementation = interfaceSpecifier != null; string aliasQualifierOpt; _name = ExplicitInterfaceHelpers.GetMemberNameAndInterfaceSymbol(binder, interfaceSpecifier, nameToken.ValueText, diagnostics, out _explicitInterfaceType, out aliasQualifierOpt); _type = BindEventType(binder, syntax.Type, diagnostics); var explicitlyImplementedEvent = this.FindExplicitlyImplementedEvent(_explicitInterfaceType, nameToken.ValueText, interfaceSpecifier, diagnostics); this.FindExplicitlyImplementedMemberVerification(explicitlyImplementedEvent, diagnostics); // The runtime will not treat the accessors of this event as overrides or implementations // of those of another event unless both the signatures and the custom modifiers match. // Hence, in the case of overrides and *explicit* implementations, we need to copy the custom // modifiers that are in the signatures of the overridden/implemented event accessors. // (From source, we know that there can only be one overridden/implemented event, so there // are no conflicts.) This is unnecessary for implicit implementations because, if the custom // modifiers don't match, we'll insert bridge methods for the accessors (explicit implementations // that delegate to the implicit implementations) with the correct custom modifiers // (see SourceMemberContainerTypeSymbol.SynthesizeInterfaceMemberImplementation). // Note: we're checking if the syntax indicates explicit implementation rather, // than if explicitInterfaceType is null because we don't want to look for an // overridden event if this is supposed to be an explicit implementation. if (!isExplicitInterfaceImplementation) { // If this event is an override, we may need to copy custom modifiers from // the overridden event (so that the runtime will recognize it as an override). // We check for this case here, while we can still modify the parameters and // return type without losing the appearance of immutability. if (this.IsOverride) { EventSymbol overriddenEvent = this.OverriddenEvent; if ((object)overriddenEvent != null) { CopyEventCustomModifiers(overriddenEvent, ref _type, ContainingAssembly); } } } else if ((object)explicitlyImplementedEvent != null) { CopyEventCustomModifiers(explicitlyImplementedEvent, ref _type, ContainingAssembly); } AccessorDeclarationSyntax addSyntax = null; AccessorDeclarationSyntax removeSyntax = null; foreach (AccessorDeclarationSyntax accessor in syntax.AccessorList.Accessors) { switch (accessor.Kind()) { case SyntaxKind.AddAccessorDeclaration: if (addSyntax == null) { addSyntax = accessor; } else { diagnostics.Add(ErrorCode.ERR_DuplicateAccessor, accessor.Keyword.GetLocation()); } break; case SyntaxKind.RemoveAccessorDeclaration: if (removeSyntax == null) { removeSyntax = accessor; } else { diagnostics.Add(ErrorCode.ERR_DuplicateAccessor, accessor.Keyword.GetLocation()); } break; case SyntaxKind.GetAccessorDeclaration: case SyntaxKind.SetAccessorDeclaration: diagnostics.Add(ErrorCode.ERR_AddOrRemoveExpected, accessor.Keyword.GetLocation()); break; case SyntaxKind.UnknownAccessorDeclaration: // Don't need to handle UnknownAccessorDeclaration. An error will have // already been produced for it in the parser. break; default: throw ExceptionUtilities.UnexpectedValue(accessor.Kind()); } } _addMethod = CreateAccessorSymbol(addSyntax, explicitlyImplementedEvent, aliasQualifierOpt, diagnostics); _removeMethod = CreateAccessorSymbol(removeSyntax, explicitlyImplementedEvent, aliasQualifierOpt, diagnostics); if (containingType.IsInterfaceType()) { if (addSyntax == null && removeSyntax == null) //NOTE: AND - different error code produced if one is present { // CONSIDER: we're matching dev10, but it would probably be more helpful to give // an error like ERR_EventPropertyInInterface. diagnostics.Add(ErrorCode.ERR_EventNeedsBothAccessors, this.Locations[0], this); } } else { if (addSyntax == null || removeSyntax == null) { diagnostics.Add(ErrorCode.ERR_EventNeedsBothAccessors, this.Locations[0], this); } } _explicitInterfaceImplementations = (object)explicitlyImplementedEvent == null ? ImmutableArray <EventSymbol> .Empty : ImmutableArray.Create <EventSymbol>(explicitlyImplementedEvent); }
internal SourceFieldLikeEventSymbol(SourceMemberContainerTypeSymbol containingType, Binder binder, SyntaxTokenList modifiers, VariableDeclaratorSyntax declaratorSyntax, DiagnosticBag diagnostics) : base(containingType, declaratorSyntax, modifiers, null, declaratorSyntax.Identifier, diagnostics) { this.name = declaratorSyntax.Identifier.ValueText; var declaratorDiagnostics = DiagnosticBag.GetInstance(); var declarationSyntax = (VariableDeclarationSyntax)declaratorSyntax.Parent; this.type = BindEventType(binder, declarationSyntax.Type, declaratorDiagnostics); // The runtime will not treat the accessors of this event as overrides or implementations // of those of another event unless both the signatures and the custom modifiers match. // Hence, in the case of overrides and *explicit* implementations (not possible for field-like // events), we need to copy the custom modifiers that are in the signatures of the // overridden/implemented event accessors. (From source, we know that there can only be one // overridden/implemented event, so there are no conflicts.) This is unnecessary for implicit // implementations because, if the custom modifiers don't match, we'll insert bridge methods // for the accessors (explicit implementations that delegate to the implicit implementations) // with the correct custom modifiers (see SourceNamedTypeSymbol.ImplementInterfaceMember). // If this event is an override, we may need to copy custom modifiers from // the overridden event (so that the runtime will recognize it as an override). // We check for this case here, while we can still modify the parameters and // return type without losing the appearance of immutability. if (this.IsOverride) { EventSymbol overriddenEvent = this.OverriddenEvent; if ((object)overriddenEvent != null) { CopyEventCustomModifiers(overriddenEvent, ref this.type); } } bool hasInitializer = declaratorSyntax.Initializer != null; bool inInterfaceType = containingType.IsInterfaceType(); if (hasInitializer) { if (inInterfaceType) { diagnostics.Add(ErrorCode.ERR_InterfaceEventInitializer, this.Locations[0], this); } else if (this.IsAbstract) { diagnostics.Add(ErrorCode.ERR_AbstractEventInitializer, this.Locations[0], this); } } // NOTE: if there's an initializer in source, we'd better create a backing field, regardless of // whether or not the initializer is legal. if (hasInitializer || !(inInterfaceType || this.IsExtern || this.IsAbstract)) { this.associatedField = MakeAssociatedField(declaratorSyntax); // Don't initialize this.type - we'll just use the type of the field (which is lazy and handles var) } // Accessors will assume that Type is available. this.addMethod = new SynthesizedFieldLikeEventAccessorSymbol(this, isAdder: true); this.removeMethod = new SynthesizedFieldLikeEventAccessorSymbol(this, isAdder: false); if (declarationSyntax.Variables[0] == declaratorSyntax) { // Don't report these diagnostics for every declarator in this declaration. diagnostics.AddRange(declaratorDiagnostics); } declaratorDiagnostics.Free(); }