public EmbeddedEvent( EventSymbolAdapter underlyingEvent, EmbeddedMethod adder, EmbeddedMethod remover ) : base(underlyingEvent, adder, remover, null) { }
private DiagnosticInfo _lazyUseSiteDiagnostic = CSDiagnosticInfo.EmptyErrorInfo; // Indicates unknown state. public RetargetingEventSymbol(RetargetingModuleSymbol retargetingModule, EventSymbol underlyingEvent) : base(underlyingEvent) { Debug.Assert((object)retargetingModule != null); Debug.Assert(!(underlyingEvent is RetargetingEventSymbol)); _retargetingModule = retargetingModule; }
private DiagnosticInfo lazyUseSiteDiagnostic = CSDiagnosticInfo.EmptyErrorInfo; // Indicates unknown state. public RetargetingEventSymbol(RetargetingModuleSymbol retargetingModule, EventSymbol underlyingEvent) { Debug.Assert((object)retargetingModule != null); Debug.Assert((object)underlyingEvent != null); Debug.Assert(!(underlyingEvent is RetargetingEventSymbol)); this.retargetingModule = retargetingModule; this.underlyingEvent = underlyingEvent; }
/// <summary> /// If the event has a RemoveMethod, return that. Otherwise check the overridden /// event, if any. Repeat for each overridden event. /// </summary> /// <remarks> /// This method exists to mimic the behavior of GetOwnOrInheritedSetMethod, but it /// should only ever look at the overridden event in error scenarios. /// </remarks> internal static MethodSymbol GetOwnOrInheritedRemoveMethod(this EventSymbol @event) { while ((object)@event != null) { MethodSymbol removeMethod = @event.RemoveMethod; if ((object)removeMethod != null) { return(removeMethod); } @event = @event.IsOverride ? @event.OverriddenEvent : null; } return(null); }
/// <summary> /// Accumulate diagnostics related to the variance safety of an interface event. /// </summary> private static void CheckEventVarianceSafety(EventSymbol @event, DiagnosticBag diagnostics) { if (SkipVarianceSafetyChecks(@event)) { return; } IsVarianceUnsafe( @event.Type, requireOutputSafety: false, requireInputSafety: true, context: @event, locationProvider: e => e.Locations[0], locationArg: @event, diagnostics: diagnostics); }
internal static EventSymbol FindExplicitlyImplementedEvent( this EventSymbol implementingEvent, TypeSymbol explicitInterfaceType, string interfaceEventName, ExplicitInterfaceSpecifierSyntax explicitInterfaceSpecifierSyntax, BindingDiagnosticBag diagnostics ) { return((EventSymbol)FindExplicitlyImplementedMember( implementingEvent, explicitInterfaceType, interfaceEventName, explicitInterfaceSpecifierSyntax, diagnostics )); }
protected static void CopyEventCustomModifiers(EventSymbol eventWithCustomModifiers, ref TypeSymbolWithAnnotations type, AssemblySymbol containingAssembly, Symbol nonNullTypesContext) { Debug.Assert((object)eventWithCustomModifiers != null); Debug.Assert(nonNullTypesContext != null); TypeSymbol overriddenEventType = eventWithCustomModifiers.Type.TypeSymbol; // We do an extra check before copying the type to handle the case where the overriding // event (incorrectly) has a different type than the overridden event. In such cases, // we want to retain the original (incorrect) type to avoid hiding the type given in source. if (type.TypeSymbol.Equals(overriddenEventType, TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds | TypeCompareKind.IgnoreDynamic)) { type = type.WithTypeAndModifiers(CustomModifierUtils.CopyTypeCustomModifiers(overriddenEventType, type.TypeSymbol, containingAssembly, nonNullTypesContext), eventWithCustomModifiers.Type.CustomModifiers); } }
internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, DiagnosticBag diagnostics) { base.AfterAddingTypeMembersChecks(conversions, diagnostics); if ((object)_explicitInterfaceType != null) { var explicitInterfaceSpecifier = this.ExplicitInterfaceSpecifier; RoslynDebug.Assert(explicitInterfaceSpecifier != null); _explicitInterfaceType.CheckAllConstraints(DeclaringCompilation, conversions, new SourceLocation(explicitInterfaceSpecifier.Name), diagnostics); } if (!_explicitInterfaceImplementations.IsEmpty) { // Note: we delayed nullable-related checks that could pull on NonNullTypes EventSymbol explicitlyImplementedEvent = _explicitInterfaceImplementations[0]; TypeSymbol.CheckNullableReferenceTypeMismatchOnImplementingMember(this.ContainingType, this, explicitlyImplementedEvent, isExplicit: true, diagnostics); } }
public override bool Equals(Symbol obj, TypeCompareKind compareKind) { EventSymbol other = obj as EventSymbol; if (ReferenceEquals(null, other)) { return(false); } if (ReferenceEquals(this, other)) { return(true); } // This checks if the events have the same definition and the type parameters on the containing types have been // substituted in the same way. return(TypeSymbol.Equals(this.ContainingType, other.ContainingType, compareKind) && ReferenceEquals(this.OriginalDefinition, other.OriginalDefinition)); }
internal SynthesizedEventAccessorSymbol( SourceEventSymbol @event, bool isAdder, EventSymbol explicitlyImplementedEventOpt = null, string aliasQualifierOpt = null ) : base( @event, null, @event.Locations, explicitlyImplementedEventOpt, aliasQualifierOpt, isAdder, isIterator: false, isNullableAnalysisEnabled: false ) { }
public sealed override bool Equals(object obj) { EventSymbol other = obj as EventSymbol; if (ReferenceEquals(null, other)) { return(false); } if (ReferenceEquals(this, other)) { return(true); } // This checks if the events have the same definition and the type parameters on the containing types have been // substituted in the same way. return(this.ContainingType == other.ContainingType && ReferenceEquals(this.OriginalDefinition, other.OriginalDefinition)); }
internal static void GetTypeOrReturnType(this Symbol symbol, out RefKind refKind, out TypeSymbol returnType, out ImmutableArray <CustomModifier> returnTypeCustomModifiers) { switch (symbol.Kind) { case SymbolKind.Field: FieldSymbol field = (FieldSymbol)symbol; refKind = RefKind.None; returnType = field.Type; returnTypeCustomModifiers = field.CustomModifiers; break; case SymbolKind.Method: MethodSymbol method = (MethodSymbol)symbol; refKind = method.RefKind; returnType = method.ReturnType; returnTypeCustomModifiers = method.ReturnTypeCustomModifiers; break; case SymbolKind.Property: PropertySymbol property = (PropertySymbol)symbol; refKind = property.RefKind; returnType = property.Type; returnTypeCustomModifiers = property.TypeCustomModifiers; break; case SymbolKind.Event: EventSymbol @event = (EventSymbol)symbol; refKind = RefKind.None; returnType = @event.Type; returnTypeCustomModifiers = ImmutableArray <CustomModifier> .Empty; break; case SymbolKind.Local: LocalSymbol local = (LocalSymbol)symbol; refKind = local.RefKind; returnType = local.Type; returnTypeCustomModifiers = ImmutableArray <CustomModifier> .Empty; break; default: throw ExceptionUtilities.UnexpectedValue(symbol.Kind); } }
public SourceEventAccessorSymbol( SourceEventSymbol @event, SyntaxReference syntaxReference, ImmutableArray <Location> locations, EventSymbol explicitlyImplementedEventOpt, string aliasQualifierOpt, bool isAdder, bool isIterator, bool isNullableAnalysisEnabled) : base(@event.containingType, syntaxReference, locations, isIterator) { _event = @event; string name; ImmutableArray <MethodSymbol> explicitInterfaceImplementations; if ((object)explicitlyImplementedEventOpt == null) { name = SourceEventSymbol.GetAccessorName(@event.Name, isAdder); explicitInterfaceImplementations = ImmutableArray <MethodSymbol> .Empty; } else { MethodSymbol implementedAccessor = isAdder ? explicitlyImplementedEventOpt.AddMethod : explicitlyImplementedEventOpt.RemoveMethod; string accessorName = (object)implementedAccessor != null ? implementedAccessor.Name : SourceEventSymbol.GetAccessorName(explicitlyImplementedEventOpt.Name, isAdder); name = ExplicitInterfaceHelpers.GetMemberName(accessorName, explicitlyImplementedEventOpt.ContainingType, aliasQualifierOpt); explicitInterfaceImplementations = (object)implementedAccessor == null ? ImmutableArray <MethodSymbol> .Empty : ImmutableArray.Create <MethodSymbol>(implementedAccessor); } _explicitInterfaceImplementations = explicitInterfaceImplementations; this.MakeFlags( isAdder ? MethodKind.EventAdd : MethodKind.EventRemove, @event.Modifiers, returnsVoid: false, // until we learn otherwise (in LazyMethodChecks). isExtensionMethod: false, isNullableAnalysisEnabled: isNullableAnalysisEnabled, isMetadataVirtualIgnoringModifiers: @event.IsExplicitInterfaceImplementation && (@event.Modifiers & DeclarationModifiers.Static) == 0); _name = GetOverriddenAccessorName(@event, isAdder) ?? name; }
internal EventSymbol GetLeastOverriddenEvent(NamedTypeSymbol accessingTypeOpt) { var accessingType = ((object)accessingTypeOpt == null ? this.ContainingType : accessingTypeOpt).OriginalDefinition; EventSymbol e = this; while (e.IsOverride && !e.HidesBaseEventsByName) { // NOTE: We might not be able to access the overridden event. For example, // // .assembly A // { // InternalsVisibleTo("B") // public class A { internal virtual event Action E { add; remove; } } // } // // .assembly B // { // InternalsVisibleTo("C") // public class B : A { internal override event Action E { add; remove; } } // } // // .assembly C // { // public class C : B { ... new B().E += null ... } // A.E is not accessible from here // } // // See InternalsVisibleToAndStrongNameTests: IvtVirtualCall1, IvtVirtualCall2, IvtVirtual_ParamsAndDynamic. EventSymbol overridden = e.OverriddenEvent; HashSet <DiagnosticInfo> useSiteDiagnostics = null; if ((object)overridden == null || !AccessCheck.IsSymbolAccessible(overridden, accessingType, ref useSiteDiagnostics)) { break; } e = overridden; } return(e); }
internal SourceCustomEventAccessorSymbol( SourceEventSymbol @event, AccessorDeclarationSyntax syntax, EventSymbol explicitlyImplementedEventOpt, string aliasQualifierOpt, bool isNullableAnalysisEnabled, DiagnosticBag diagnostics) : base(@event, syntax.GetReference(), ImmutableArray.Create(syntax.Keyword.GetLocation()), explicitlyImplementedEventOpt, aliasQualifierOpt, isAdder: syntax.Kind() == SyntaxKind.AddAccessorDeclaration, isIterator: SyntaxFacts.HasYieldOperations(syntax.Body), isNullableAnalysisEnabled: isNullableAnalysisEnabled) { Debug.Assert(syntax != null); Debug.Assert(syntax.Kind() == SyntaxKind.AddAccessorDeclaration || syntax.Kind() == SyntaxKind.RemoveAccessorDeclaration); CheckFeatureAvailabilityAndRuntimeSupport(syntax, this.Location, hasBody: true, diagnostics: diagnostics); if (syntax.Body != null || syntax.ExpressionBody != null) { if (IsExtern && !IsAbstract) { diagnostics.Add(ErrorCode.ERR_ExternHasBody, this.Location, this); } // Do not report error for IsAbstract && IsExtern. Dev10 reports CS0180 only // in that case ("member cannot be both extern and abstract"). } if (syntax.Modifiers.Count > 0) { diagnostics.Add(ErrorCode.ERR_NoModifiersOnAccessor, syntax.Modifiers[0].GetLocation()); } CheckForBlockAndExpressionBody( syntax.Body, syntax.ExpressionBody, syntax, diagnostics); }
internal SubstitutedEventSymbol(SubstitutedNamedTypeSymbol containingType, EventSymbol originalDefinition) { this.containingType = containingType; this.originalDefinition = originalDefinition; }
public TupleEventSymbol(TupleTypeSymbol container, EventSymbol underlyingEvent) : base(underlyingEvent) { _containingType = container; }
public WrappedEventSymbol(EventSymbol underlyingEvent) { Debug.Assert((object)underlyingEvent != null); _underlyingEvent = underlyingEvent; }
internal SubstitutedEventSymbol(SubstitutedNamedTypeSymbol containingType, EventSymbol originalDefinition) : base(originalDefinition) { Debug.Assert(originalDefinition.IsDefinition); _containingType = containingType; }
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(); }
/// <summary> /// There are two BadEventUsage error codes and this method decides which one should /// be used for a given event. /// </summary> private DiagnosticInfo GetBadEventUsageDiagnosticInfo(EventSymbol eventSymbol) { var leastOverridden = (EventSymbol)eventSymbol.GetLeastOverriddenMember(this.ContainingType); return leastOverridden.HasAssociatedField ? new CSDiagnosticInfo(ErrorCode.ERR_BadEventUsage, leastOverridden, leastOverridden.ContainingType) : new CSDiagnosticInfo(ErrorCode.ERR_BadEventUsageNoField, leastOverridden); }
/// <summary> /// If we have a WinRT type event, we need to encapsulate the adder call /// (which returns an EventRegistrationToken) with a call to /// WindowsRuntimeMarshal.AddEventHandler or RemoveEventHandler, but these /// require us to create a new Func representing the adder and another /// Action representing the Remover. /// /// The rewritten call looks something like: /// /// WindowsRuntimeMarshal.AddEventHandler<EventHandler> /// (new Func<EventHandler, EventRegistrationToken>(@object.add), /// new Action<EventRegistrationToken>(@object.remove), handler); /// /// Where @object is a compiler-generated local temp if needed. /// </summary> /// <remarks> /// TODO: use or delete isDynamic. /// </remarks> private BoundExpression RewriteWindowsRuntimeEventAssignmentOperator(SyntaxNode syntax, EventSymbol eventSymbol, EventAssignmentKind kind, bool isDynamic, BoundExpression rewrittenReceiverOpt, BoundExpression rewrittenArgument) { BoundAssignmentOperator tempAssignment = null; BoundLocal boundTemp = null; if (!eventSymbol.IsStatic && CanChangeValueBetweenReads(rewrittenReceiverOpt)) { boundTemp = _factory.StoreToTemp(rewrittenReceiverOpt, out tempAssignment); } NamedTypeSymbol tokenType = _factory.WellKnownType(WellKnownType.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationToken); NamedTypeSymbol marshalType = _factory.WellKnownType(WellKnownType.System_Runtime_InteropServices_WindowsRuntime_WindowsRuntimeMarshal); NamedTypeSymbol actionType = _factory.WellKnownType(WellKnownType.System_Action_T).Construct(tokenType); TypeSymbol eventType = eventSymbol.Type; BoundExpression delegateCreationArgument = boundTemp ?? rewrittenReceiverOpt ?? _factory.Type(eventType); BoundDelegateCreationExpression removeDelegate = new BoundDelegateCreationExpression( syntax: syntax, argument: delegateCreationArgument, methodOpt: eventSymbol.RemoveMethod, isExtensionMethod: false, type: actionType); BoundExpression clearCall = null; if (kind == EventAssignmentKind.Assignment) { MethodSymbol clearMethod; if (TryGetWellKnownTypeMember(syntax, WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_WindowsRuntimeMarshal__RemoveAllEventHandlers, out clearMethod)) { clearCall = MakeCall( syntax: syntax, rewrittenReceiver: null, method: clearMethod, rewrittenArguments: ImmutableArray.Create<BoundExpression>(removeDelegate), type: clearMethod.ReturnType); } else { clearCall = new BoundBadExpression(syntax, LookupResultKind.NotInvocable, ImmutableArray<Symbol>.Empty, ImmutableArray.Create<BoundNode>(removeDelegate), ErrorTypeSymbol.UnknownResultType); } } ImmutableArray<BoundExpression> marshalArguments; WellKnownMember helper; if (kind == EventAssignmentKind.Subtraction) { helper = WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_WindowsRuntimeMarshal__RemoveEventHandler_T; marshalArguments = ImmutableArray.Create<BoundExpression>(removeDelegate, rewrittenArgument); } else { NamedTypeSymbol func2Type = _factory.WellKnownType(WellKnownType.System_Func_T2).Construct(eventType, tokenType); BoundDelegateCreationExpression addDelegate = new BoundDelegateCreationExpression( syntax: syntax, argument: delegateCreationArgument, methodOpt: eventSymbol.AddMethod, isExtensionMethod: false, type: func2Type); helper = WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_WindowsRuntimeMarshal__AddEventHandler_T; marshalArguments = ImmutableArray.Create<BoundExpression>(addDelegate, removeDelegate, rewrittenArgument); } BoundExpression marshalCall; MethodSymbol marshalMethod; if (TryGetWellKnownTypeMember(syntax, helper, out marshalMethod)) { marshalMethod = marshalMethod.Construct(eventType); marshalCall = MakeCall( syntax: syntax, rewrittenReceiver: null, method: marshalMethod, rewrittenArguments: marshalArguments, type: marshalMethod.ReturnType); } else { marshalCall = new BoundBadExpression(syntax, LookupResultKind.NotInvocable, ImmutableArray<Symbol>.Empty, StaticCast<BoundNode>.From(marshalArguments), ErrorTypeSymbol.UnknownResultType); } // In this case, we don't need a sequence. if (boundTemp == null && clearCall == null) { return marshalCall; } ImmutableArray<LocalSymbol> tempSymbols = boundTemp == null ? ImmutableArray<LocalSymbol>.Empty : ImmutableArray.Create<LocalSymbol>(boundTemp.LocalSymbol); ArrayBuilder<BoundExpression> sideEffects = ArrayBuilder<BoundExpression>.GetInstance(2); //max size if (clearCall != null) sideEffects.Add(clearCall); if (tempAssignment != null) sideEffects.Add(tempAssignment); Debug.Assert(sideEffects.Any(), "Otherwise, we shouldn't be building a sequence"); return new BoundSequence(syntax, tempSymbols, sideEffects.ToImmutableAndFree(), marshalCall, marshalCall.Type); }
public override void VisitEvent(EventSymbol symbol) { _cancellationToken.ThrowIfCancellationRequested(); if (DoNotVisit(symbol)) return; Compliance compliance = GetDeclaredOrInheritedCompliance(symbol); // Rule 32 specifies the shapes of the accessor signatures. However, // even though WinRT events have a different shape, dev11 does not // report that they are non-compliant. // Rule 28 requires that the accessors "adhere to a special naming pattern". // We don't actually need to do anything here, because they automatically // will unless they override accessors from metadata - we don't check overrides - // or they explicitly implement interface accessors - we don't check non-public // members. if (!VisitTypeOrMember(symbol, compliance)) return; }
internal SourceCustomEventAccessorSymbol( SourceEventSymbol @event, AccessorDeclarationSyntax syntax, EventSymbol explicitlyImplementedEventOpt, string aliasQualifierOpt, DiagnosticBag diagnostics) : base(@event, syntax.GetReference(), syntax.Body.GetReferenceOrNull(), ImmutableArray.Create(syntax.Keyword.GetLocation())) { Debug.Assert(syntax != null); Debug.Assert(syntax.Kind == SyntaxKind.AddAccessorDeclaration || syntax.Kind == SyntaxKind.RemoveAccessorDeclaration); bool isAdder = syntax.Kind == SyntaxKind.AddAccessorDeclaration; string name; ImmutableArray<MethodSymbol> explicitInterfaceImplementations; if ((object)explicitlyImplementedEventOpt == null) { name = SourceEventSymbol.GetAccessorName(@event.Name, isAdder); explicitInterfaceImplementations = ImmutableArray<MethodSymbol>.Empty; } else { MethodSymbol implementedAccessor = isAdder ? explicitlyImplementedEventOpt.AddMethod : explicitlyImplementedEventOpt.RemoveMethod; string accessorName = (object)implementedAccessor != null ? implementedAccessor.Name : SourceEventSymbol.GetAccessorName(explicitlyImplementedEventOpt.Name, isAdder); name = ExplicitInterfaceHelpers.GetMemberName(accessorName, explicitlyImplementedEventOpt.ContainingType, aliasQualifierOpt); explicitInterfaceImplementations = (object)implementedAccessor == null ? ImmutableArray<MethodSymbol>.Empty : ImmutableArray.Create<MethodSymbol>(implementedAccessor); } this.explicitInterfaceImplementations = explicitInterfaceImplementations; this.name = name; this.flags = MakeFlags( isAdder ? MethodKind.EventAdd : MethodKind.EventRemove, @event.Modifiers, returnsVoid: false, // until we learn otherwise (in LazyMethodChecks). isExtensionMethod: false, isMetadataVirtualIgnoringModifiers: explicitInterfaceImplementations.Any()); if (@event.ContainingType.IsInterface) { diagnostics.Add(ErrorCode.ERR_EventPropertyInInterface, this.Location); } else { var bodyOpt = syntax.Body; if (bodyOpt != null) { if (IsExtern && !IsAbstract) { diagnostics.Add(ErrorCode.ERR_ExternHasBody, this.Location, this); } else if (IsAbstract && !IsExtern) { diagnostics.Add(ErrorCode.ERR_AbstractHasBody, this.Location, this); } // Do not report error for IsAbstract && IsExtern. Dev10 reports CS0180 only // in that case ("member cannot be both extern and abstract"). } } this.name = GetOverriddenAccessorName(@event, isAdder) ?? this.name; }
private static void CheckAccessorShape(MethodSymbol accessor, EventSymbol @event) { Assert.Same(@event, accessor.AssociatedSymbol); switch (accessor.MethodKind) { case MethodKind.EventAdd: Assert.Same(@event.AddMethod, accessor); break; case MethodKind.EventRemove: Assert.Same(@event.RemoveMethod, accessor); break; default: Assert.False(true, string.Format("Accessor {0} has unexpected MethodKind {1}", accessor, accessor.MethodKind)); break; } Assert.Equal(@event.IsAbstract, accessor.IsAbstract); Assert.Equal(@event.IsOverride, @accessor.IsOverride); Assert.Equal(@event.IsVirtual, @accessor.IsVirtual); Assert.Equal(@event.IsSealed, @accessor.IsSealed); Assert.Equal(@event.IsExtern, @accessor.IsExtern); Assert.Equal(SpecialType.System_Void, accessor.ReturnType.SpecialType); Assert.Equal(@event.Type, accessor.Parameters.Single().Type); }
private SourceCustomEventAccessorSymbol CreateAccessorSymbol(AccessorDeclarationSyntax syntaxOpt, EventSymbol explicitlyImplementedEventOpt, string aliasQualifierOpt, DiagnosticBag diagnostics) { if (syntaxOpt == null) { return null; } return new SourceCustomEventAccessorSymbol(this, syntaxOpt, explicitlyImplementedEventOpt, aliasQualifierOpt, diagnostics); }
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 sealed override TypeSymbolWithAnnotations GetFieldType(ConsList <FieldSymbol> fieldsBeingBound) { Debug.Assert(fieldsBeingBound != null); if (!_lazyType.IsNull) { return(_lazyType.ToType()); } var declarator = VariableDeclaratorNode; var fieldSyntax = GetFieldDeclaration(declarator); var typeSyntax = fieldSyntax.Declaration.Type; var compilation = this.DeclaringCompilation; var diagnostics = DiagnosticBag.GetInstance(); TypeSymbolWithAnnotations type; // When we have multiple declarators, we report the type diagnostics on only the first. DiagnosticBag diagnosticsForFirstDeclarator = DiagnosticBag.GetInstance(); Symbol associatedPropertyOrEvent = this.AssociatedSymbol; if ((object)associatedPropertyOrEvent != null && associatedPropertyOrEvent.Kind == SymbolKind.Event) { EventSymbol @event = (EventSymbol)associatedPropertyOrEvent; if (@event.IsWindowsRuntimeEvent) { NamedTypeSymbol tokenTableType = this.DeclaringCompilation.GetWellKnownType(WellKnownType.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationTokenTable_T); Binder.ReportUseSiteDiagnostics(tokenTableType, diagnosticsForFirstDeclarator, this.ErrorLocation); // CONSIDER: Do we want to guard against the possibility that someone has created their own EventRegistrationTokenTable<T> // type that has additional generic constraints? type = TypeSymbolWithAnnotations.Create(tokenTableType.Construct(ImmutableArray.Create(@event.Type))); } else { type = @event.Type; } } else { var binderFactory = compilation.GetBinderFactory(SyntaxTree); var binder = binderFactory.GetBinder(typeSyntax); binder = binder.WithContainingMemberOrLambda(this); if (!ContainingType.IsScriptClass) { type = binder.BindType(typeSyntax, diagnosticsForFirstDeclarator); } else { bool isVar; type = binder.BindTypeOrVarKeyword(typeSyntax, diagnostics, out isVar); Debug.Assert(!type.IsNull || isVar); if (isVar) { if (this.IsConst) { diagnosticsForFirstDeclarator.Add(ErrorCode.ERR_ImplicitlyTypedVariableCannotBeConst, typeSyntax.Location); } if (fieldsBeingBound.ContainsReference(this)) { diagnostics.Add(ErrorCode.ERR_RecursivelyTypedVariable, this.ErrorLocation, this); type = default; } else if (fieldSyntax.Declaration.Variables.Count > 1) { diagnosticsForFirstDeclarator.Add(ErrorCode.ERR_ImplicitlyTypedVariableMultipleDeclarator, typeSyntax.Location); } else if (this.IsConst && this.ContainingType.IsScriptClass) { // For const var in script, we won't try to bind the initializer (case below), as it can lead to an unbound recursion type = default; } else { fieldsBeingBound = new ConsList <FieldSymbol>(this, fieldsBeingBound); var initializerBinder = new ImplicitlyTypedFieldBinder(binder, fieldsBeingBound); var initializerOpt = initializerBinder.BindInferredVariableInitializer(diagnostics, RefKind.None, (EqualsValueClauseSyntax)declarator.Initializer, declarator); if (initializerOpt != null) { if ((object)initializerOpt.Type != null && !initializerOpt.Type.IsErrorType()) { type = TypeSymbolWithAnnotations.Create(nonNullTypesContext: this, initializerOpt.Type); } _lazyFieldTypeInferred = 1; } } if (type.IsNull) { type = TypeSymbolWithAnnotations.Create(nonNullTypesContext: this, binder.CreateErrorType("var")); } } } if (IsFixed) { type = TypeSymbolWithAnnotations.Create(new PointerTypeSymbol(type)); if (ContainingType.TypeKind != TypeKind.Struct) { diagnostics.Add(ErrorCode.ERR_FixedNotInStruct, ErrorLocation); } var elementType = ((PointerTypeSymbol)type.TypeSymbol).PointedAtType.TypeSymbol; int elementSize = elementType.FixedBufferElementSizeInBytes(); if (elementSize == 0) { var loc = typeSyntax.Location; diagnostics.Add(ErrorCode.ERR_IllegalFixedType, loc); } if (!binder.InUnsafeRegion) { diagnosticsForFirstDeclarator.Add(ErrorCode.ERR_UnsafeNeeded, declarator.Location); } } } // update the lazyType only if it contains value last seen by the current thread: if (_lazyType.InterlockedInitialize(type.WithModifiers(this.RequiredCustomModifiers))) { TypeChecks(type.TypeSymbol, diagnostics); // CONSIDER: SourceEventFieldSymbol would like to suppress these diagnostics. compilation.DeclarationDiagnostics.AddRange(diagnostics); bool isFirstDeclarator = fieldSyntax.Declaration.Variables[0] == declarator; if (isFirstDeclarator) { compilation.DeclarationDiagnostics.AddRange(diagnosticsForFirstDeclarator); } state.NotePartComplete(CompletionPart.Type); } diagnostics.Free(); diagnosticsForFirstDeclarator.Free(); return(_lazyType.ToType()); }
internal static MethodSymbol GetOwnOrInheritedAccessor(this EventSymbol @event, bool isAdder) { return(isAdder ? @event.GetOwnOrInheritedAddMethod() : @event.GetOwnOrInheritedRemoveMethod()); }
internal SynthesizedEventAccessorSymbol(SourceEventSymbol @event, bool isAdder, EventSymbol explicitlyImplementedEventOpt = null, string aliasQualifierOpt = null) : base(@event, null, @event.Locations, explicitlyImplementedEventOpt, aliasQualifierOpt, isAdder) { }
private BoundExpression MakeEventAccess( SyntaxNode syntax, BoundExpression rewrittenReceiver, EventSymbol eventSymbol, ConstantValue constantValueOpt, LookupResultKind resultKind, TypeSymbol type) { Debug.Assert(eventSymbol.HasAssociatedField); FieldSymbol fieldSymbol = eventSymbol.AssociatedField; Debug.Assert((object)fieldSymbol != null); if (!eventSymbol.IsWindowsRuntimeEvent) { return MakeFieldAccess(syntax, rewrittenReceiver, fieldSymbol, constantValueOpt, resultKind, type); } NamedTypeSymbol fieldType = (NamedTypeSymbol)fieldSymbol.Type; Debug.Assert(fieldType.Name == "EventRegistrationTokenTable"); // _tokenTable BoundFieldAccess fieldAccess = new BoundFieldAccess( syntax, fieldSymbol.IsStatic ? null : rewrittenReceiver, fieldSymbol, constantValueOpt: null) { WasCompilerGenerated = true }; BoundExpression getOrCreateCall; MethodSymbol getOrCreateMethod; if (TryGetWellKnownTypeMember(syntax, WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationTokenTable_T__GetOrCreateEventRegistrationTokenTable, out getOrCreateMethod)) { getOrCreateMethod = getOrCreateMethod.AsMember(fieldType); // EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable) getOrCreateCall = BoundCall.Synthesized( syntax, receiverOpt: null, method: getOrCreateMethod, arg0: fieldAccess); } else { getOrCreateCall = new BoundBadExpression(syntax, LookupResultKind.NotInvocable, ImmutableArray<Symbol>.Empty, ImmutableArray.Create<BoundNode>(fieldAccess), ErrorTypeSymbol.UnknownResultType); } PropertySymbol invocationListProperty; if (TryGetWellKnownTypeMember(syntax, WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationTokenTable_T__InvocationList, out invocationListProperty)) { MethodSymbol invocationListAccessor = invocationListProperty.GetMethod; if ((object)invocationListAccessor == null) { string accessorName = SourcePropertyAccessorSymbol.GetAccessorName(invocationListProperty.Name, getNotSet: true, isWinMdOutput: invocationListProperty.IsCompilationOutputWinMdObj()); _diagnostics.Add(new CSDiagnosticInfo(ErrorCode.ERR_MissingPredefinedMember, invocationListProperty.ContainingType, accessorName), syntax.Location); } else { invocationListAccessor = invocationListAccessor.AsMember(fieldType); return _factory.Call(getOrCreateCall, invocationListAccessor); } } return new BoundBadExpression(syntax, LookupResultKind.NotInvocable, ImmutableArray<Symbol>.Empty, ImmutableArray.Create<BoundNode>(getOrCreateCall), ErrorTypeSymbol.UnknownResultType); }
internal SourceCustomEventAccessorSymbol( SourceEventSymbol @event, AccessorDeclarationSyntax syntax, EventSymbol explicitlyImplementedEventOpt, string aliasQualifierOpt, DiagnosticBag diagnostics) : base(@event, syntax.GetReference(), syntax.Body.GetReferenceOrNull(), ImmutableArray.Create(syntax.Keyword.GetLocation())) { Debug.Assert(syntax != null); Debug.Assert(syntax.Kind == SyntaxKind.AddAccessorDeclaration || syntax.Kind == SyntaxKind.RemoveAccessorDeclaration); bool isAdder = syntax.Kind == SyntaxKind.AddAccessorDeclaration; string name; ImmutableArray <MethodSymbol> explicitInterfaceImplementations; if ((object)explicitlyImplementedEventOpt == null) { name = SourceEventSymbol.GetAccessorName(@event.Name, isAdder); explicitInterfaceImplementations = ImmutableArray <MethodSymbol> .Empty; } else { MethodSymbol implementedAccessor = isAdder ? explicitlyImplementedEventOpt.AddMethod : explicitlyImplementedEventOpt.RemoveMethod; string accessorName = (object)implementedAccessor != null ? implementedAccessor.Name : SourceEventSymbol.GetAccessorName(explicitlyImplementedEventOpt.Name, isAdder); name = ExplicitInterfaceHelpers.GetMemberName(accessorName, explicitlyImplementedEventOpt.ContainingType, aliasQualifierOpt); explicitInterfaceImplementations = (object)implementedAccessor == null ? ImmutableArray <MethodSymbol> .Empty : ImmutableArray.Create <MethodSymbol>(implementedAccessor); } this.explicitInterfaceImplementations = explicitInterfaceImplementations; this.name = name; this.flags = MakeFlags( isAdder ? MethodKind.EventAdd : MethodKind.EventRemove, @event.Modifiers, returnsVoid: false, // until we learn otherwise (in LazyMethodChecks). isExtensionMethod: false, isMetadataVirtualIgnoringModifiers: explicitInterfaceImplementations.Any()); if (@event.ContainingType.IsInterface) { diagnostics.Add(ErrorCode.ERR_EventPropertyInInterface, this.Location); } else { var bodyOpt = syntax.Body; if (bodyOpt != null) { if (IsExtern && !IsAbstract) { diagnostics.Add(ErrorCode.ERR_ExternHasBody, this.Location, this); } else if (IsAbstract && !IsExtern) { diagnostics.Add(ErrorCode.ERR_AbstractHasBody, this.Location, this); } // Do not report error for IsAbstract && IsExtern. Dev10 reports CS0180 only // in that case ("member cannot be both extern and abstract"). } } this.name = GetOverriddenAccessorName(@event, isAdder) ?? this.name; }
private static void VerifyWinRTEventShape(EventSymbol @event, CSharpCompilation compilation) { Assert.True(@event.IsWindowsRuntimeEvent); var eventType = @event.Type; var tokenType = compilation.GetWellKnownType(WellKnownType.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationToken); Assert.NotNull(tokenType); var voidType = compilation.GetSpecialType(SpecialType.System_Void); Assert.NotNull(voidType); var addMethod = @event.AddMethod; Assert.Equal(tokenType, addMethod.ReturnType); Assert.False(addMethod.ReturnsVoid); Assert.Equal(1, addMethod.ParameterCount); Assert.Equal(eventType, addMethod.ParameterTypes.Single()); var removeMethod = @event.RemoveMethod; Assert.Equal(voidType, removeMethod.ReturnType); Assert.True(removeMethod.ReturnsVoid); Assert.Equal(1, removeMethod.ParameterCount); Assert.Equal(tokenType, removeMethod.ParameterTypes.Single()); if (@event.HasAssociatedField) { var expectedFieldType = compilation.GetWellKnownType(WellKnownType.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationTokenTable_T).Construct(eventType); Assert.Equal(expectedFieldType, @event.AssociatedField.Type); } else { Assert.Null(@event.AssociatedField); } }
public virtual void VisitEvent(EventSymbol symbol) { DefaultVisit(symbol); }
public void ImplementInterfaceUsingNonVirtualEvent() { var text = @" interface I { event System.Action E; event System.Action F; event System.Action G; } class C : I { event System.Action I.E { add { } remove { } } public event System.Action F { add { } remove { } } public event System.Action G; } "; var compilation = CreateCompilationWithMscorlib(text); // This also forces computation of IsMetadataVirtual. compilation.VerifyDiagnostics( // (12,32): warning CS0067: The event 'C.G' is never used // public event System.Action G; Diagnostic(ErrorCode.WRN_UnreferencedEvent, "G").WithArguments("C.G")); const int numEvents = 3; var @interface = compilation.GlobalNamespace.GetMember<NamedTypeSymbol>("I"); var interfaceEvents = new EventSymbol[numEvents]; interfaceEvents[0] = @interface.GetMember<EventSymbol>("E"); interfaceEvents[1] = @interface.GetMember<EventSymbol>("F"); interfaceEvents[2] = @interface.GetMember<EventSymbol>("G"); var @class = compilation.GlobalNamespace.GetMember<NamedTypeSymbol>("C"); var classEvents = new EventSymbol[numEvents]; classEvents[0] = @class.GetEvent("I.E"); classEvents[1] = @class.GetMember<EventSymbol>("F"); classEvents[2] = @class.GetMember<EventSymbol>("G"); for (int i = 0; i < numEvents; i++) { var classEvent = classEvents[i]; var interfaceEvent = interfaceEvents[i]; Assert.Equal(classEvent, @class.FindImplementationForInterfaceMember(interfaceEvent)); Assert.Equal(classEvent.AddMethod, @class.FindImplementationForInterfaceMember(interfaceEvent.AddMethod)); Assert.Equal(classEvent.RemoveMethod, @class.FindImplementationForInterfaceMember(interfaceEvent.RemoveMethod)); Assert.True(classEvent.AddMethod.IsMetadataVirtual()); Assert.True(classEvent.RemoveMethod.IsMetadataVirtual()); } }
private bool ComputeIsWindowsRuntimeEvent() { // Interface events don't override or implement other events, so they only // depend the output kind. if (this.containingType.IsInterfaceType()) { return(this.IsCompilationOutputWinMdObj()); } // If you explicitly implement an event, then you're a WinRT event if and only if it's a WinRT event. ImmutableArray <EventSymbol> explicitInterfaceImplementations = this.ExplicitInterfaceImplementations; if (!explicitInterfaceImplementations.IsEmpty) { // If there could be more than one, we'd have to worry about conflicts, but that's impossible for source events. Debug.Assert(explicitInterfaceImplementations.Length == 1); // Don't have to worry about conflicting with the override rule, since explicit impls are never overrides (in source). Debug.Assert((object)this.OverriddenEvent == null); return(explicitInterfaceImplementations[0].IsWindowsRuntimeEvent); } // If you override an event, then you're a WinRT event if and only if it's a WinRT event. EventSymbol overriddenEvent = this.OverriddenEvent; if ((object)overriddenEvent != null) { return(overriddenEvent.IsWindowsRuntimeEvent); } // If you implicitly implement one or more interface events (for yourself, not for a derived type), // then you're a WinRT event if and only if at least one is a WinRT event. // // NOTE: it's possible that we returned false above even though we would have returned true // below. Whenever this occurs, we need to report a diagnostic (because an event can't be // both WinRT and non-WinRT), but we'll do that when we're checking interface implementations // (see SourceMemberContainerTypeSymbol.ComputeInterfaceImplementations). bool sawImplicitImplementation = false; foreach (NamedTypeSymbol @interface in this.containingType.InterfacesAndTheirBaseInterfacesNoUseSiteDiagnostics) { foreach (Symbol interfaceMember in @interface.GetMembers(this.Name)) { if (interfaceMember.Kind == SymbolKind.Event && //quick check (necessary, not sufficient) this == this.containingType.FindImplementationForInterfaceMember(interfaceMember)) //slow check (necessary and sufficient) { sawImplicitImplementation = true; if (((EventSymbol)interfaceMember).IsWindowsRuntimeEvent) { return(true); } } } } // If you implement one or more interface events and none of them are WinRT events, then you // are not a WinRT event. if (sawImplicitImplementation) { return(false); } // If you're not constrained by your relationships with other members, then you're a WinRT event // if and only if this compilation will produce a ".winmdobj" file. return(this.IsCompilationOutputWinMdObj()); }
internal SourceCustomEventSymbol(SourceMemberContainerTypeSymbol containingType, Binder binder, EventDeclarationSyntax syntax, DiagnosticBag diagnostics) : base(containingType, syntax, syntax.Modifiers, isFieldLike: false, interfaceSpecifierSyntaxOpt: syntax.ExplicitInterfaceSpecifier, nameTokenSyntax: syntax.Identifier, diagnostics: 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; if (syntax.AccessorList != null) { foreach (AccessorDeclarationSyntax accessor in syntax.AccessorList.Accessors) { bool checkBody = false; switch (accessor.Kind()) { case SyntaxKind.AddAccessorDeclaration: if (addSyntax == null) { addSyntax = accessor; checkBody = true; } else { diagnostics.Add(ErrorCode.ERR_DuplicateAccessor, accessor.Keyword.GetLocation()); } break; case SyntaxKind.RemoveAccessorDeclaration: if (removeSyntax == null) { removeSyntax = accessor; checkBody = true; } 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()); } if (checkBody && !IsAbstract && accessor.Body == null && accessor.ExpressionBody == null && accessor.SemicolonToken.Kind() == SyntaxKind.SemicolonToken) { diagnostics.Add(ErrorCode.ERR_AddRemoveMustHaveBody, accessor.SemicolonToken.GetLocation()); } } if (IsAbstract) { if (!syntax.AccessorList.OpenBraceToken.IsMissing) { diagnostics.Add(ErrorCode.ERR_AbstractEventHasAccessors, syntax.AccessorList.OpenBraceToken.GetLocation(), this); } } else if ((addSyntax == null || removeSyntax == null) && (!syntax.AccessorList.OpenBraceToken.IsMissing || !isExplicitInterfaceImplementation)) { diagnostics.Add(ErrorCode.ERR_EventNeedsBothAccessors, this.Locations[0], this); } } else if (isExplicitInterfaceImplementation && !IsAbstract) { diagnostics.Add(ErrorCode.ERR_ExplicitEventFieldImpl, this.Locations[0]); } if (isExplicitInterfaceImplementation && IsAbstract && syntax.AccessorList == null) { Debug.Assert(containingType.IsInterface); Binder.CheckFeatureAvailability(syntax, MessageID.IDS_DefaultInterfaceImplementation, diagnostics, this.Locations[0]); if (!ContainingAssembly.RuntimeSupportsDefaultInterfaceImplementation) { diagnostics.Add(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, this.Locations[0]); } _addMethod = new SynthesizedEventAccessorSymbol(this, isAdder: true, explicitlyImplementedEvent, aliasQualifierOpt); _removeMethod = new SynthesizedEventAccessorSymbol(this, isAdder: false, explicitlyImplementedEvent, aliasQualifierOpt); } else { _addMethod = CreateAccessorSymbol(addSyntax, explicitlyImplementedEvent, aliasQualifierOpt, diagnostics); _removeMethod = CreateAccessorSymbol(removeSyntax, explicitlyImplementedEvent, aliasQualifierOpt, diagnostics); } _explicitInterfaceImplementations = (object)explicitlyImplementedEvent == null ? ImmutableArray <EventSymbol> .Empty : ImmutableArray.Create <EventSymbol>(explicitlyImplementedEvent); }
private static void VerifyNormalEventShape(EventSymbol @event, CSharpCompilation compilation) { Assert.False(@event.IsWindowsRuntimeEvent); var eventType = @event.Type; var voidType = compilation.GetSpecialType(SpecialType.System_Void); Assert.NotNull(voidType); var addMethod = @event.AddMethod; Assert.Equal(voidType, addMethod.ReturnType); Assert.True(addMethod.ReturnsVoid); Assert.Equal(1, addMethod.ParameterCount); Assert.Equal(eventType, addMethod.ParameterTypes.Single()); var removeMethod = @event.RemoveMethod; Assert.Equal(voidType, removeMethod.ReturnType); Assert.True(removeMethod.ReturnsVoid); Assert.Equal(1, removeMethod.ParameterCount); Assert.Equal(eventType, removeMethod.ParameterTypes.Single()); if (@event.HasAssociatedField) { Assert.Equal(eventType, @event.AssociatedField.Type); } else { Assert.Null(@event.AssociatedField); } }
protected static void CopyEventCustomModifiers(EventSymbol eventWithCustomModifiers, ref TypeSymbol type) { Debug.Assert((object)eventWithCustomModifiers != null); TypeSymbol overriddenEventType = eventWithCustomModifiers.Type; // We do an extra check before copying the type to handle the case where the overriding // event (incorrectly) has a different type than the overridden event. In such cases, // we want to retain the original (incorrect) type to avoid hiding the type given in source. if (type.Equals(overriddenEventType, ignoreCustomModifiers: true, ignoreDynamic: false)) { type = overriddenEventType; } }
public EmbeddedEvent(EventSymbol underlyingEvent, EmbeddedMethod adder, EmbeddedMethod remover) : base(underlyingEvent, adder, remover, null) { }
protected static void CopyEventCustomModifiers(EventSymbol eventWithCustomModifiers, ref TypeSymbol type, AssemblySymbol containingAssembly) { Debug.Assert((object)eventWithCustomModifiers != null); TypeSymbol overriddenEventType = eventWithCustomModifiers.Type; // We do an extra check before copying the type to handle the case where the overriding // event (incorrectly) has a different type than the overridden event. In such cases, // we want to retain the original (incorrect) type to avoid hiding the type given in source. if (type.Equals(overriddenEventType, ignoreCustomModifiersAndArraySizesAndLowerBounds: true, ignoreDynamic: true)) { type = CustomModifierUtils.CopyTypeCustomModifiers(overriddenEventType, type, RefKind.None, containingAssembly); } }
public static int CustomModifierCount(this EventSymbol e) { return(e.Type.CustomModifierCount()); }
internal SubstitutedEventSymbol(SubstitutedNamedTypeSymbol containingType, EventSymbol originalDefinition) { _containingType = containingType; _originalDefinition = originalDefinition; }