Пример #1
0
 public EmbeddedEvent(
     EventSymbolAdapter underlyingEvent,
     EmbeddedMethod adder,
     EmbeddedMethod remover
     ) : base(underlyingEvent, adder, remover, null)
 {
 }
Пример #2
0
        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;
        }
Пример #3
0
        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);
        }
Пример #5
0
        /// <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);
        }
Пример #6
0
 internal static EventSymbol FindExplicitlyImplementedEvent(
     this EventSymbol implementingEvent,
     TypeSymbol explicitInterfaceType,
     string interfaceEventName,
     ExplicitInterfaceSpecifierSyntax explicitInterfaceSpecifierSyntax,
     BindingDiagnosticBag diagnostics
     )
 {
     return((EventSymbol)FindExplicitlyImplementedMember(
                implementingEvent,
                explicitInterfaceType,
                interfaceEventName,
                explicitInterfaceSpecifierSyntax,
                diagnostics
                ));
 }
Пример #7
0
        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);
            }
        }
Пример #8
0
        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);
            }
        }
Пример #9
0
        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));
        }
Пример #10
0
 internal SynthesizedEventAccessorSymbol(
     SourceEventSymbol @event,
     bool isAdder,
     EventSymbol explicitlyImplementedEventOpt = null,
     string aliasQualifierOpt = null
     )
     : base(
         @event,
         null,
         @event.Locations,
         explicitlyImplementedEventOpt,
         aliasQualifierOpt,
         isAdder,
         isIterator: false,
         isNullableAnalysisEnabled: false
         )
 {
 }
Пример #11
0
        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));
        }
Пример #12
0
        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;
        }
Пример #14
0
        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);
        }
Пример #16
0
 internal SubstitutedEventSymbol(SubstitutedNamedTypeSymbol containingType, EventSymbol originalDefinition)
 {
     this.containingType     = containingType;
     this.originalDefinition = originalDefinition;
 }
Пример #17
0
 public TupleEventSymbol(TupleTypeSymbol container, EventSymbol underlyingEvent)
     : base(underlyingEvent)
 {
     _containingType = container;
 }
Пример #18
0
 public WrappedEventSymbol(EventSymbol underlyingEvent)
 {
     Debug.Assert((object)underlyingEvent != null);
     _underlyingEvent = underlyingEvent;
 }
Пример #19
0
 internal SubstitutedEventSymbol(SubstitutedNamedTypeSymbol containingType, EventSymbol originalDefinition)
     : base(originalDefinition)
 {
     Debug.Assert(originalDefinition.IsDefinition);
     _containingType = containingType;
 }
Пример #20
0
 public WrappedEventSymbol(EventSymbol underlyingEvent)
 {
     Debug.Assert((object)underlyingEvent != null);
     _underlyingEvent = underlyingEvent;
 }
        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();
        }
Пример #22
0
 /// <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);
 }
Пример #23
0
        /// <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&lt;EventHandler&gt;
        ///     (new Func&lt;EventHandler, EventRegistrationToken&gt;(@object.add), 
        ///      new Action&lt;EventRegistrationToken&gt;(@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);
        }
Пример #24
0
        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);
        }
Пример #27
0
        private SourceCustomEventAccessorSymbol CreateAccessorSymbol(AccessorDeclarationSyntax syntaxOpt,
            EventSymbol explicitlyImplementedEventOpt, string aliasQualifierOpt, DiagnosticBag diagnostics)
        {
            if (syntaxOpt == null)
            {
                return null;
            }

            return new SourceCustomEventAccessorSymbol(this, syntaxOpt, explicitlyImplementedEventOpt, aliasQualifierOpt, diagnostics);
        }
Пример #28
0
        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);
        }
Пример #29
0
        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());
        }
Пример #30
0
 internal SubstitutedEventSymbol(SubstitutedNamedTypeSymbol containingType, EventSymbol originalDefinition)
     : base(originalDefinition)
 {
     Debug.Assert(originalDefinition.IsDefinition);
     _containingType = containingType;
 }
 internal static MethodSymbol GetOwnOrInheritedAccessor(this EventSymbol @event, bool isAdder)
 {
     return(isAdder
         ? @event.GetOwnOrInheritedAddMethod()
         : @event.GetOwnOrInheritedRemoveMethod());
 }
Пример #32
0
 internal SynthesizedEventAccessorSymbol(SourceEventSymbol @event, bool isAdder, EventSymbol explicitlyImplementedEventOpt = null, string aliasQualifierOpt = null)
     : base(@event, null, @event.Locations, explicitlyImplementedEventOpt, aliasQualifierOpt, isAdder)
 {
 }
Пример #33
0
        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);
        }
Пример #34
0
 public TupleEventSymbol(TupleTypeSymbol container, EventSymbol underlyingEvent)
     : base(underlyingEvent)
 {
     _containingType = container;
 }
Пример #35
0
        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;
        }
Пример #36
0
        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);
 }
Пример #38
0
        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());
            }
        }
Пример #39
0
        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);
        }
Пример #41
0
        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;
            }
        }
Пример #43
0
 public EmbeddedEvent(EventSymbol underlyingEvent, EmbeddedMethod adder, EmbeddedMethod remover) :
     base(underlyingEvent, adder, remover, null)
 {
 }
Пример #44
0
        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;
 }