internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, DiagnosticBag diagnostics) { base.AfterAddingTypeMembersChecks(conversions, diagnostics); if ((object)_explicitInterfaceType != null) { var explicitInterfaceSpecifier = this.ExplicitInterfaceSpecifier; Debug.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, explicitlyImplementedEvent, true, diagnostics); } }
public 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(TypeSymbol.Equals(this.ContainingType, other.ContainingType, TypeCompareKind.ConsiderEverything2) && ReferenceEquals(this.OriginalDefinition, other.OriginalDefinition)); }
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); }
public TupleEventSymbol(TupleTypeSymbol container, EventSymbol underlyingEvent) : base(underlyingEvent) { _containingType = container; }
internal static MethodSymbol GetOwnOrInheritedAccessor(this EventSymbol @event, bool isAdder) { return(isAdder ? @event.GetOwnOrInheritedAddMethod() : @event.GetOwnOrInheritedRemoveMethod()); }
internal SubstitutedEventSymbol(SubstitutedNamedTypeSymbol containingType, EventSymbol originalDefinition) : base(originalDefinition) { Debug.Assert(originalDefinition.IsDefinition); _containingType = containingType; }
public static int CustomModifierCount(this EventSymbol e) { return(e.Type.TypeSymbol.CustomModifierCount()); }
public WrappedEventSymbol(EventSymbol underlyingEvent) { Debug.Assert((object)underlyingEvent != null); _underlyingEvent = underlyingEvent; }
internal sealed override TypeSymbolWithAnnotations GetFieldType(ConsList <FieldSymbol> fieldsBeingBound) { Debug.Assert(fieldsBeingBound != null); if (!_lazyType.IsNull) { return(_lazyType.ToType()); } var declarator = VariableDeclarationNode; var fieldSyntax = GetFieldDeclaration(declarator); var typeSyntax = fieldSyntax.Declaration.Type; var compilation = this.DeclaringCompilation; var diagnostics = DiagnosticBag.GetInstance(); TypeSymbolWithAnnotations type = default; // 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.core_runtime_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(declarator); binder = binder.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.SuppressConstraintChecks, this); if (!ContainingType.IsScriptClass) { type = binder.BindType(typeSyntax, diagnosticsForFirstDeclarator); } else if (typeSyntax == null) { 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 (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(initializerOpt.Type); } _lazyFieldTypeInferred = 1; } } if (type.IsNull) { type = TypeSymbolWithAnnotations.Create(binder.CreateErrorType("var")); } } else { type = binder.BindType(typeSyntax, diagnostics); } if (IsFixedSizeBuffer) { 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); compilation.DeclarationDiagnostics.AddRange(diagnosticsForFirstDeclarator); state.NotePartComplete(CompletionPart.Type); } diagnostics.Free(); diagnosticsForFirstDeclarator.Free(); return(_lazyType.ToType()); }
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); }
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.Keys) { 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 SourceFieldLikeEventSymbol(SourceMemberContainerTypeSymbol containingType, Binder binder, SyntaxTokenList modifiers, VariableDeclarationSyntax declaratorSyntax, DiagnosticBag diagnostics) : base(containingType, declaratorSyntax, modifiers, null, declaratorSyntax.Identifier, 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) { 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)) { _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]); } // Accessors will assume that Type is available. _addMethod = new SynthesizedFieldLikeEventAccessorSymbol(this, isAdder: true); _removeMethod = new SynthesizedFieldLikeEventAccessorSymbol(this, isAdder: false); // Don't report these diagnostics for every declarator in this declaration. diagnostics.AddRange(declaratorDiagnostics); declaratorDiagnostics.Free(); }
internal SourceCustomEventAccessorSymbol( SourceEventSymbol @event, AccessorDeclarationSyntax syntax, EventSymbol explicitlyImplementedEventOpt, string aliasQualifierOpt, DiagnosticBag diagnostics) : base(@event, syntax.GetReference(), 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); } _explicitInterfaceImplementations = explicitInterfaceImplementations; _name = name; this.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 { if (syntax.Body != null || syntax.ExpressionBody != 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"). } } _name = GetOverriddenAccessorName(@event, isAdder) ?? _name; if (syntax.Modifiers.Count > 0) { diagnostics.Add(ErrorCode.ERR_NoModifiersOnAccessor, syntax.Modifiers[0].GetLocation()); } CheckForBlockAndExpressionBody( syntax.Body, syntax.ExpressionBody, syntax, diagnostics); }