internal SynthesizedStateMachineProperty( MethodSymbol interfacePropertyGetter, StateMachineTypeSymbol stateMachineType) { _name = ExplicitInterfaceHelpers.GetMemberName(interfacePropertyGetter.AssociatedSymbol.Name, interfacePropertyGetter.ContainingType, aliasQualifierOpt: null); var getterName = ExplicitInterfaceHelpers.GetMemberName(interfacePropertyGetter.Name, interfacePropertyGetter.ContainingType, aliasQualifierOpt: null); _getter = new SynthesizedStateMachineDebuggerHiddenMethod( getterName, interfacePropertyGetter, stateMachineType, associatedProperty: this, hasMethodBodyDependency: false); }
public static SourcePropertyAccessorSymbol CreateAccessorSymbol( NamedTypeSymbol containingType, SourcePropertySymbol property, DeclarationModifiers propertyModifiers, string propertyName, AccessorDeclarationSyntax syntax, PropertySymbol explicitlyImplementedPropertyOpt, string aliasQualifierOpt, bool isAutoPropertyAccessor, DiagnosticBag diagnostics) { Debug.Assert(syntax.Kind == SyntaxKind.GetAccessorDeclaration || syntax.Kind == SyntaxKind.SetAccessorDeclaration); bool isGetMethod = (syntax.Kind == SyntaxKind.GetAccessorDeclaration); bool isWinMd = property.IsCompilationOutputWinMdObj(); string name; ImmutableArray <MethodSymbol> explicitInterfaceImplementations; if ((object)explicitlyImplementedPropertyOpt == null) { name = GetAccessorName(propertyName, isGetMethod, isWinMd); explicitInterfaceImplementations = ImmutableArray <MethodSymbol> .Empty; } else { MethodSymbol implementedAccessor = isGetMethod ? explicitlyImplementedPropertyOpt.GetMethod : explicitlyImplementedPropertyOpt.SetMethod; string accessorName = (object)implementedAccessor != null ? implementedAccessor.Name : GetAccessorName(explicitlyImplementedPropertyOpt.MetadataName, isGetMethod, isWinMd); //Not name - could be indexer placeholder name = ExplicitInterfaceHelpers.GetMemberName(accessorName, explicitlyImplementedPropertyOpt.ContainingType, aliasQualifierOpt); explicitInterfaceImplementations = (object)implementedAccessor == null ? ImmutableArray <MethodSymbol> .Empty : ImmutableArray.Create <MethodSymbol>(implementedAccessor); } var methodKind = isGetMethod ? MethodKind.PropertyGet : MethodKind.PropertySet; return(new SourcePropertyAccessorSymbol( containingType, name, property, propertyModifiers, explicitInterfaceImplementations, syntax.Keyword.GetLocation(), syntax, methodKind, isAutoPropertyAccessor, diagnostics)); }
internal SynthesizedImplementationReadOnlyProperty( MethodSymbol interfaceMethod, NamedTypeSymbol implementingType, bool debuggerHidden = false) { this.propName = ExplicitInterfaceHelpers.GetMemberName(interfaceMethod.AssociatedSymbol.Name, interfaceMethod.ContainingType, aliasQualifierOpt: null); var getterName = ExplicitInterfaceHelpers.GetMemberName(interfaceMethod.Name, interfaceMethod.ContainingType, aliasQualifierOpt: null); getter = new SynthesizedImplementationMethod(interfaceMethod, implementingType, getterName, debuggerHidden, associatedProperty: this); }
internal SynthesizedStateMachineProperty( MethodSymbol interfacePropertyGetter, StateMachineTypeSymbol stateMachineType, bool debuggerHidden, bool hasMethodBodyDependency) { this.name = ExplicitInterfaceHelpers.GetMemberName(interfacePropertyGetter.AssociatedSymbol.Name, interfacePropertyGetter.ContainingType, aliasQualifierOpt: null); var getterName = ExplicitInterfaceHelpers.GetMemberName(interfacePropertyGetter.Name, interfacePropertyGetter.ContainingType, aliasQualifierOpt: null); this.getter = new SynthesizedStateMachineMethod( getterName, interfacePropertyGetter, stateMachineType, associatedProperty: this, debuggerHidden: debuggerHidden, generateDebugInfo: !debuggerHidden, hasMethodBodyDependency: hasMethodBodyDependency); }
internal SynthesizedStateMachineProperty( MethodSymbol interfacePropertyGetter, NamedTypeSymbol implementingType, bool debuggerHidden, bool hasMethodBodyDependency) { this.name = ExplicitInterfaceHelpers.GetMemberName(interfacePropertyGetter.AssociatedSymbol.Name, interfacePropertyGetter.ContainingType, aliasQualifierOpt: null); var getterName = ExplicitInterfaceHelpers.GetMemberName(interfacePropertyGetter.Name, interfacePropertyGetter.ContainingType, aliasQualifierOpt: null); getter = new SynthesizedStateMachineMethod( getterName, interfacePropertyGetter, implementingType, asyncKickoffMethod: null, associatedProperty: this, debuggerHidden: debuggerHidden, hasMethodBodyDependency: hasMethodBodyDependency); }
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; }
public static SourceOrdinaryMethodSymbol CreateMethodSymbol( NamedTypeSymbol containingType, Binder bodyBinder, MethodDeclarationSyntax syntax, DiagnosticBag diagnostics) { var interfaceSpecifier = syntax.ExplicitInterfaceSpecifier; var nameToken = syntax.Identifier; TypeSymbol explicitInterfaceType; string discardedAliasQualifier; var name = ExplicitInterfaceHelpers.GetMemberNameAndInterfaceSymbol(bodyBinder, interfaceSpecifier, nameToken.ValueText, diagnostics, out explicitInterfaceType, out discardedAliasQualifier); var location = new SourceLocation(nameToken); var methodKind = interfaceSpecifier == null ? MethodKind.Ordinary : MethodKind.ExplicitInterfaceImplementation; return(new SourceOrdinaryMethodSymbol(containingType, explicitInterfaceType, name, location, syntax, methodKind, diagnostics)); }
public int GetHashCode(Symbol member) { int hash = 1; if ((object)member != null) { hash = Hash.Combine((int)member.Kind, hash); if (_considerName) { #if XSHARP hash = Hash.Combine(ExplicitInterfaceHelpers.GetMemberNameWithoutInterfaceName(member.Name).ToUpper(), hash); // CaseInsensitive #else hash = Hash.Combine(ExplicitInterfaceHelpers.GetMemberNameWithoutInterfaceName(member.Name), hash); #endif // CONSIDER: could use interface type, but that might be quite expensive } if (_considerReturnType) { RefKind refKind; TypeSymbol returnType; ImmutableArray <CustomModifier> customModifiers_Ignored; member.GetTypeOrReturnType(out refKind, out returnType, out customModifiers_Ignored, out customModifiers_Ignored); hash = Hash.Combine((int)refKind, hash); if (member.GetMemberArity() == 0 && !_considerCustomModifiers) // If it is generic, then type argument might be in return type. { hash = Hash.Combine(returnType, hash); } } // CONSIDER: modify hash for constraints? hash = Hash.Combine(member.GetMemberArity(), hash); hash = Hash.Combine(member.GetParameterCount(), hash); } return(hash); }
public static SourceUserDefinedOperatorSymbol CreateUserDefinedOperatorSymbol( SourceMemberContainerTypeSymbol containingType, Binder bodyBinder, OperatorDeclarationSyntax syntax, bool isNullableAnalysisEnabled, BindingDiagnosticBag diagnostics) { var location = syntax.OperatorToken.GetLocation(); string name = OperatorFacts.OperatorNameFromDeclaration(syntax); if (SyntaxFacts.IsCheckedOperator(name)) { MessageID.IDS_FeatureCheckedUserDefinedOperators.CheckFeatureAvailability(diagnostics, syntax, syntax.CheckedKeyword.GetLocation()); } else if (!syntax.OperatorToken.IsMissing && syntax.CheckedKeyword.IsKind(SyntaxKind.CheckedKeyword)) { diagnostics.Add(ErrorCode.ERR_OperatorCantBeChecked, syntax.CheckedKeyword.GetLocation(), SyntaxFacts.GetText(SyntaxFacts.GetOperatorKind(name))); } if (name == WellKnownMemberNames.UnsignedRightShiftOperatorName) { MessageID.IDS_FeatureUnsignedRightShift.CheckFeatureAvailability(diagnostics, syntax, syntax.OperatorToken.GetLocation()); } var interfaceSpecifier = syntax.ExplicitInterfaceSpecifier; TypeSymbol explicitInterfaceType; name = ExplicitInterfaceHelpers.GetMemberNameAndInterfaceSymbol(bodyBinder, interfaceSpecifier, name, diagnostics, out explicitInterfaceType, aliasQualifierOpt: out _); var methodKind = interfaceSpecifier == null ? MethodKind.UserDefinedOperator : MethodKind.ExplicitInterfaceImplementation; return(new SourceUserDefinedOperatorSymbol( methodKind, containingType, explicitInterfaceType, name, location, syntax, isNullableAnalysisEnabled, diagnostics)); }
public int GetHashCode(Symbol member) { int hash = 1; if ((object)member != null) { hash = Hash.Combine((int)member.Kind, hash); if (_considerName) { hash = Hash.Combine(ExplicitInterfaceHelpers.GetMemberNameWithoutInterfaceName(member.Name), hash); // CONSIDER: could use interface type, but that might be quite expensive } if (_considerReturnType) { RefKind refKind; TypeSymbol returnType; ImmutableArray <CustomModifier> returnTypeCustomModifiers; ushort countOfCustomModifiersPrecedingByRef; member.GetTypeOrReturnType(out refKind, out returnType, out returnTypeCustomModifiers, out countOfCustomModifiersPrecedingByRef); hash = Hash.Combine((int)refKind, hash); if (member.GetMemberArity() == 0 && !_considerCustomModifiers) // If it is generic, then type argument might be in return type. { hash = Hash.Combine(returnType, hash); } } // CONSIDER: modify hash for constraints? hash = Hash.Combine(member.GetMemberArity(), hash); hash = Hash.Combine(member.GetParameterCount(), hash); } return(hash); }
public static SourceUserDefinedOperatorSymbol CreateUserDefinedOperatorSymbol( SourceMemberContainerTypeSymbol containingType, Binder bodyBinder, OperatorDeclarationSyntax syntax, bool isNullableAnalysisEnabled, BindingDiagnosticBag diagnostics) { var location = syntax.OperatorToken.GetLocation(); string name = OperatorFacts.OperatorNameFromDeclaration(syntax); var interfaceSpecifier = syntax.ExplicitInterfaceSpecifier; TypeSymbol explicitInterfaceType; name = ExplicitInterfaceHelpers.GetMemberNameAndInterfaceSymbol(bodyBinder, interfaceSpecifier, name, diagnostics, out explicitInterfaceType, aliasQualifierOpt: out _); var methodKind = interfaceSpecifier == null ? MethodKind.UserDefinedOperator : MethodKind.ExplicitInterfaceImplementation; return(new SourceUserDefinedOperatorSymbol( methodKind, containingType, explicitInterfaceType, name, location, syntax, isNullableAnalysisEnabled, diagnostics)); }
public SynthesizedImplementationMethod( MethodSymbol interfaceMethod, NamedTypeSymbol implementingType, string name = null, bool generateDebugInfo = true, PropertySymbol associatedProperty = null) { //it does not make sense to add methods to substituted types Debug.Assert(implementingType.IsDefinition); _name = name ?? ExplicitInterfaceHelpers.GetMemberName(interfaceMethod.Name, interfaceMethod.ContainingType, aliasQualifierOpt: null); _implementingType = implementingType; _generateDebugInfo = generateDebugInfo; _associatedProperty = associatedProperty; _explicitInterfaceImplementations = ImmutableArray.Create <MethodSymbol>(interfaceMethod); // alpha-rename to get the implementation's type parameters var typeMap = interfaceMethod.ContainingType.TypeSubstitution ?? TypeMap.Empty; typeMap.WithAlphaRename(interfaceMethod, this, out _typeParameters); _interfaceMethod = interfaceMethod.ConstructIfGeneric(_typeParameters.Cast <TypeParameterSymbol, TypeSymbol>()); _parameters = SynthesizedParameterSymbol.DeriveParameters(_interfaceMethod, this); }
public int GetHashCode(Symbol member) { int hash = 1; if ((object)member != null) { hash = Hash.Combine((int)member.Kind, hash); if (_considerName) { hash = Hash.Combine( ExplicitInterfaceHelpers.GetMemberNameWithoutInterfaceName(member.Name), hash ); // CONSIDER: could use interface type, but that might be quite expensive } if ( _considerReturnType && member.GetMemberArity() == 0 && (_typeComparison & TypeCompareKind.AllIgnoreOptions) == 0 ) // If it is generic, then type argument might be in return type. { hash = Hash.Combine(member.GetTypeOrReturnType().GetHashCode(), hash); } // CONSIDER: modify hash for constraints? if (member.Kind != SymbolKind.Field) { hash = Hash.Combine(member.GetMemberArity(), hash); hash = Hash.Combine(member.GetParameterCount(), hash); } } return(hash); }
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; }
public bool Equals(Symbol member1, Symbol member2) { if (ReferenceEquals(member1, member2)) { return(true); } if ((object)member1 == null || (object)member2 == null || member1.Kind != member2.Kind) { return(false); } bool sawInterfaceInName1 = false; bool sawInterfaceInName2 = false; if (_considerName) { string name1 = ExplicitInterfaceHelpers.GetMemberNameWithoutInterfaceName(member1.Name); string name2 = ExplicitInterfaceHelpers.GetMemberNameWithoutInterfaceName(member2.Name); sawInterfaceInName1 = name1 != member1.Name; sawInterfaceInName2 = name2 != member2.Name; if (name1 != name2) { return(false); } } // NB: up to, and including, this check, we have not actually forced the (type) parameters // to be expanded - we're only using the counts. if ((member1.GetMemberArity() != member2.GetMemberArity()) || (member1.GetParameterCount() != member2.GetParameterCount())) { return(false); } var typeMap1 = GetTypeMap(member1); var typeMap2 = GetTypeMap(member2); if (_considerReturnType && !HaveSameReturnTypes(member1, typeMap1, member2, typeMap2, _considerCustomModifiers, _ignoreDynamic, _ignoreTupleNames)) { return(false); } if (member1.GetParameterCount() > 0 && !HaveSameParameterTypes(member1.GetParameters(), typeMap1, member2.GetParameters(), typeMap2, _considerRefKindDifferences, _considerCustomModifiers, _ignoreDynamic, _ignoreTupleNames)) { return(false); } if (_considerCallingConvention) { if (GetCallingConvention(member1) != GetCallingConvention(member2)) { return(false); } } else { if (IsVarargMethod(member1) != IsVarargMethod(member2)) { return(false); } } if (_considerExplicitlyImplementedInterfaces) { if (sawInterfaceInName1 != sawInterfaceInName2) { return(false); } // The purpose of this check is to determine whether the interface parts of the member names agree, // but to do so using robust symbolic checks, rather than syntactic ones. Therefore, if neither member // name contains an interface name, this check is not relevant. // Phrased differently, the explicitly implemented interface is not part of the signature unless it's // part of the name. if (sawInterfaceInName1) { Debug.Assert(sawInterfaceInName2); // May avoid realizing interface members. if (member1.IsExplicitInterfaceImplementation() != member2.IsExplicitInterfaceImplementation()) { return(false); } // By comparing symbols, rather than syntax, we gain the flexibility of ignoring whitespace // and gracefully accepting multiple names for the same (or equivalent) types (e.g. "I<int>.M" // vs "I<System.Int32>.M"), but we lose the connection with the name. For example, in metadata, // a method name "I.M" could have nothing to do with "I" but explicitly implement interface "I2". // We will behave as if the method was really named "I2.M". Furthermore, in metadata, a method // can explicitly implement more than one interface method, in which case it doesn't really // make sense to pretend that all of them are part of the signature. var explicitInterfaceImplementations1 = member1.GetExplicitInterfaceImplementations(); var explicitInterfaceImplementations2 = member2.GetExplicitInterfaceImplementations(); if (!explicitInterfaceImplementations1.SetEquals(explicitInterfaceImplementations2, EqualityComparer <Symbol> .Default)) { return(false); } } } return(!_considerTypeConstraints || HaveSameConstraints(member1, typeMap1, member2, typeMap2)); }
private static SourcePropertySymbol Create( SourceMemberContainerTypeSymbol containingType, Binder binder, BasePropertyDeclarationSyntax syntax, string name, Location location, BindingDiagnosticBag diagnostics ) { GetAccessorDeclarations( syntax, diagnostics, out bool isAutoProperty, out bool hasAccessorList, out bool accessorsHaveImplementation, out bool isInitOnly, out var getSyntax, out var setSyntax ); var explicitInterfaceSpecifier = GetExplicitInterfaceSpecifier(syntax); SyntaxTokenList modifiersTokenList = GetModifierTokensSyntax(syntax); bool isExplicitInterfaceImplementation = explicitInterfaceSpecifier is object; var modifiers = MakeModifiers( containingType, modifiersTokenList, isExplicitInterfaceImplementation, isIndexer: syntax.Kind() == SyntaxKind.IndexerDeclaration, accessorsHaveImplementation: accessorsHaveImplementation, location, diagnostics, out _ ); bool isExpressionBodied = !hasAccessorList && GetArrowExpression(syntax) != null; binder = binder.WithUnsafeRegionIfNecessary(modifiersTokenList); TypeSymbol?explicitInterfaceType; string? aliasQualifierOpt; string memberName = ExplicitInterfaceHelpers.GetMemberNameAndInterfaceSymbol( binder, explicitInterfaceSpecifier, name, diagnostics, out explicitInterfaceType, out aliasQualifierOpt ); return(new SourcePropertySymbol( containingType, syntax, hasGetAccessor: getSyntax != null || isExpressionBodied, hasSetAccessor: setSyntax != null, isExplicitInterfaceImplementation, explicitInterfaceType, aliasQualifierOpt, modifiers, isAutoProperty: isAutoProperty, isExpressionBodied: isExpressionBodied, isInitOnly: isInitOnly, memberName, location, diagnostics )); }
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); }
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); }
public bool Equals(Symbol member1, Symbol member2) { if (ReferenceEquals(member1, member2)) { return(true); } if ((object)member1 == null || (object)member2 == null || member1.Kind != member2.Kind) { return(false); } bool sawInterfaceInName1 = false; bool sawInterfaceInName2 = false; if (_considerName) { string name1 = ExplicitInterfaceHelpers.GetMemberNameWithoutInterfaceName(member1.Name); string name2 = ExplicitInterfaceHelpers.GetMemberNameWithoutInterfaceName(member2.Name); sawInterfaceInName1 = name1 != member1.Name; sawInterfaceInName2 = name2 != member2.Name; if (name1 != name2) { return(false); } } // NB: up to, and including, this check, we have not actually forced the (type) parameters // to be expanded - we're only using the counts. int arity = member1.GetMemberArity(); if ((arity != member2.GetMemberArity()) || (member1.GetParameterCount() != member2.GetParameterCount())) { return(false); } TypeMap typeMap1; TypeMap typeMap2; if (arity > 0 && _useSpecialHandlingForNullableTypes) { // We need this special handling in order to avoid forcing resolution of nullable types // in signature of an overriding member while we are looking for a matching overridden member. // Doing the resolution in the original signature can send us into an infinite cycle because // constraints must be inherited from the member we are looking for. // It is important to ensure that the fact whether an indexed type parameter we are about to use // is a reference type is inherited from the corresponding type parameter of the possibly overridden // member (which is member2 when _useSpecialHandlingForNullableTypes is true). This will ensure // proper resolution for nullable types in substituted signature of member1, ensuring proper // comparison of types across both members. ArrayBuilder <TypeParameterSymbol> builder = ArrayBuilder <TypeParameterSymbol> .GetInstance(arity); var typeParameters2 = member2.GetMemberTypeParameters(); for (int i = arity - 1; i >= 0; i--) { builder.Add(IndexedTypeParameterSymbolForOverriding.GetTypeParameter(i, typeParameters2[i].IsValueType)); } var indexed = builder.ToImmutableAndFree(); typeMap1 = new TypeMap(member1.GetMemberTypeParameters(), indexed, true); typeMap2 = new TypeMap(typeParameters2, indexed, true); } else { typeMap1 = GetTypeMap(member1); typeMap2 = GetTypeMap(member2); } if (_considerReturnType && !HaveSameReturnTypes(member1, typeMap1, member2, typeMap2, _typeComparison)) { return(false); } if (member1.GetParameterCount() > 0 && !HaveSameParameterTypes(member1.GetParameters(), typeMap1, member2.GetParameters(), typeMap2, _considerRefKindDifferences, _typeComparison)) { return(false); } if (_considerCallingConvention) { if (GetCallingConvention(member1) != GetCallingConvention(member2)) { return(false); } } else { if (IsVarargMethod(member1) != IsVarargMethod(member2)) { return(false); } } if (_considerExplicitlyImplementedInterfaces) { if (sawInterfaceInName1 != sawInterfaceInName2) { return(false); } // The purpose of this check is to determine whether the interface parts of the member names agree, // but to do so using robust symbolic checks, rather than syntactic ones. Therefore, if neither member // name contains an interface name, this check is not relevant. // Phrased differently, the explicitly implemented interface is not part of the signature unless it's // part of the name. if (sawInterfaceInName1) { Debug.Assert(sawInterfaceInName2); // May avoid realizing interface members. if (member1.IsExplicitInterfaceImplementation() != member2.IsExplicitInterfaceImplementation()) { return(false); } // By comparing symbols, rather than syntax, we gain the flexibility of ignoring whitespace // and gracefully accepting multiple names for the same (or equivalent) types (e.g. "I<int>.M" // vs "I<System.Int32>.M"), but we lose the connection with the name. For example, in metadata, // a method name "I.M" could have nothing to do with "I" but explicitly implement interface "I2". // We will behave as if the method was really named "I2.M". Furthermore, in metadata, a method // can explicitly implement more than one interface method, in which case it doesn't really // make sense to pretend that all of them are part of the signature. var explicitInterfaceImplementations1 = member1.GetExplicitInterfaceImplementations(); var explicitInterfaceImplementations2 = member2.GetExplicitInterfaceImplementations(); if (!explicitInterfaceImplementations1.SetEquals(explicitInterfaceImplementations2, EqualityComparer <Symbol> .Default)) { return(false); } } } return(!_considerTypeConstraints || HaveSameConstraints(member1, typeMap1, member2, typeMap2)); }