2 // property.cs: Property based handlers
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 // Martin Baulig (martin@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
8 // Dual licensed under the terms of the MIT X11 or GNU GPL
10 // Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
11 // Copyright 2004-2008 Novell, Inc
15 using System
.Collections
.Generic
;
16 using System
.Reflection
;
17 using System
.Reflection
.Emit
;
18 using System
.Runtime
.CompilerServices
;
19 using System
.Runtime
.InteropServices
;
20 using System
.Security
;
21 using System
.Security
.Permissions
;
25 using XmlElement
= System
.Object
;
30 using Mono
.CompilerServices
.SymbolWriter
;
34 // It is used as a base class for all property based members
35 // This includes properties, indexers, and events
36 public abstract class PropertyBasedMember
: InterfaceMemberBase
38 public PropertyBasedMember (DeclSpace parent
, GenericMethod generic
,
39 FullNamedExpression type
, Modifiers mod
, Modifiers allowed_mod
,
40 MemberName name
, Attributes attrs
)
41 : base (parent
, generic
, type
, mod
, allowed_mod
, name
, attrs
)
45 protected override bool VerifyClsCompliance ()
47 if (!base.VerifyClsCompliance ())
50 if (!AttributeTester
.IsClsCompliant (MemberType
)) {
51 Report
.Warning (3003, 1, Location
, "Type of `{0}' is not CLS-compliant",
52 GetSignatureForError ());
60 // `set' and `get' accessors are represented with an Accessor.
62 public class Accessor
{
64 // Null if the accessor is empty, or a Block if not
66 public const Modifiers AllowedModifiers
=
72 public ToplevelBlock Block
;
73 public Attributes Attributes
;
74 public Location Location
;
75 public Modifiers ModFlags
;
76 public ParametersCompiled Parameters
;
78 public Accessor (ToplevelBlock b
, Modifiers mod
, Attributes attrs
, ParametersCompiled p
, Location loc
)
84 ModFlags
= ModifiersExtensions
.Check (AllowedModifiers
, mod
, 0, loc
, RootContext
.ToplevelTypes
.Compiler
.Report
);
88 public class PropertySpec
: MemberSpec
92 public PropertySpec (MemberKind kind
, IMemberDefinition definition
, PropertyInfo info
, Modifiers modifiers
)
93 : base (kind
, definition
, info
.Name
, modifiers
)
98 public override Type DeclaringType
{
99 get { return info.DeclaringType; }
102 public PropertyInfo MetaInfo
{
106 public Type PropertyType
{
107 get { return info.PropertyType; }
112 // Properties and Indexers both generate PropertyBuilders, we use this to share
113 // their common bits.
115 abstract public class PropertyBase
: PropertyBasedMember
{
117 public class GetMethod
: PropertyMethod
119 static string[] attribute_targets
= new string [] { "method", "return" }
;
121 public GetMethod (PropertyBase method
):
122 base (method
, "get_")
126 public GetMethod (PropertyBase method
, Accessor accessor
):
127 base (method
, accessor
, "get_")
131 public override MethodBuilder
Define (DeclSpace parent
)
133 base.Define (parent
);
138 method_data
= new MethodData (method
, ModFlags
, flags
, this);
140 if (!method_data
.Define (parent
, method
.GetFullName (MemberName
), Report
))
143 Spec
= new MethodSpec (MemberKind
.Method
, this, method_data
.MethodBuilder
, ParameterInfo
, ModFlags
);
145 return method_data
.MethodBuilder
;
148 public override Type ReturnType
{
150 return method
.MemberType
;
154 public override ParametersCompiled ParameterInfo
{
156 return ParametersCompiled
.EmptyReadOnlyParameters
;
160 public override string[] ValidAttributeTargets
{
162 return attribute_targets
;
167 public class SetMethod
: PropertyMethod
{
169 static string[] attribute_targets
= new string [] { "method", "param", "return" }
;
170 ImplicitParameter param_attr
;
171 protected ParametersCompiled parameters
;
173 public SetMethod (PropertyBase method
) :
174 base (method
, "set_")
176 parameters
= new ParametersCompiled (Compiler
,
177 new Parameter (method
.type_name
, "value", Parameter
.Modifier
.NONE
, null, Location
));
180 public SetMethod (PropertyBase method
, Accessor accessor
):
181 base (method
, accessor
, "set_")
183 this.parameters
= accessor
.Parameters
;
186 protected override void ApplyToExtraTarget (Attribute a
, CustomAttributeBuilder cb
, PredefinedAttributes pa
)
188 if (a
.Target
== AttributeTargets
.Parameter
) {
189 if (param_attr
== null)
190 param_attr
= new ImplicitParameter (method_data
.MethodBuilder
);
192 param_attr
.ApplyAttributeBuilder (a
, cb
, pa
);
196 base.ApplyAttributeBuilder (a
, cb
, pa
);
199 public override ParametersCompiled ParameterInfo
{
205 public override MethodBuilder
Define (DeclSpace parent
)
207 parameters
.Resolve (this);
209 base.Define (parent
);
214 method_data
= new MethodData (method
, ModFlags
, flags
, this);
216 if (!method_data
.Define (parent
, method
.GetFullName (MemberName
), Report
))
219 Spec
= new MethodSpec (MemberKind
.Method
, this, method_data
.MethodBuilder
, ParameterInfo
, ModFlags
);
221 return method_data
.MethodBuilder
;
224 public override Type ReturnType
{
226 return TypeManager
.void_type
;
230 public override string[] ValidAttributeTargets
{
232 return attribute_targets
;
237 static string[] attribute_targets
= new string [] { "property" }
;
239 public abstract class PropertyMethod
: AbstractPropertyEventMethod
241 protected readonly PropertyBase method
;
242 protected MethodAttributes flags
;
244 public PropertyMethod (PropertyBase method
, string prefix
)
245 : base (method
, prefix
)
247 this.method
= method
;
248 this.ModFlags
= method
.ModFlags
& (Modifiers
.STATIC
| Modifiers
.UNSAFE
);
251 public PropertyMethod (PropertyBase method
, Accessor accessor
,
253 : base (method
, accessor
, prefix
)
255 this.method
= method
;
256 this.ModFlags
= accessor
.ModFlags
| (method
.ModFlags
& (Modifiers
.STATIC
| Modifiers
.UNSAFE
));
258 if (accessor
.ModFlags
!= 0 && RootContext
.Version
== LanguageVersion
.ISO_1
) {
259 Report
.FeatureIsNotAvailable (Location
, "access modifiers on properties");
263 public override void ApplyAttributeBuilder (Attribute a
, CustomAttributeBuilder cb
, PredefinedAttributes pa
)
265 if (a
.IsInternalMethodImplAttribute
) {
266 method
.is_external_implementation
= true;
269 base.ApplyAttributeBuilder (a
, cb
, pa
);
272 public override AttributeTargets AttributeTargets
{
274 return AttributeTargets
.Method
;
278 public override bool IsClsComplianceRequired ()
280 return method
.IsClsComplianceRequired ();
283 public virtual MethodBuilder
Define (DeclSpace parent
)
285 CheckForDuplications ();
288 if (method
.InterfaceType
!= null && parent
.PartialContainer
.PendingImplementations
!= null) {
289 MethodInfo mi
= parent
.PartialContainer
.PendingImplementations
.IsInterfaceMethod (
290 MethodName
.Name
, method
.InterfaceType
, new MethodData (method
, ModFlags
, flags
, this));
292 Report
.SymbolRelatedToPreviousError (mi
);
293 Report
.Error (551, Location
, "Explicit interface implementation `{0}' is missing accessor `{1}'",
294 method
.GetSignatureForError (), TypeManager
.CSharpSignature (mi
, true));
300 TypeContainer container
= parent
.PartialContainer
;
303 // Check for custom access modifier
305 if ((ModFlags
& Modifiers
.AccessibilityMask
) == 0) {
306 ModFlags
|= method
.ModFlags
;
307 flags
= method
.flags
;
309 if (container
.Kind
== MemberKind
.Interface
)
310 Report
.Error (275, Location
, "`{0}': accessibility modifiers may not be used on accessors in an interface",
311 GetSignatureForError ());
313 if ((method
.ModFlags
& Modifiers
.ABSTRACT
) != 0 && (ModFlags
& Modifiers
.PRIVATE
) != 0) {
314 Report
.Error (442, Location
, "`{0}': abstract properties cannot have private accessors", GetSignatureForError ());
317 CheckModifiers (ModFlags
);
318 ModFlags
|= (method
.ModFlags
& (~Modifiers
.AccessibilityMask
));
319 ModFlags
|= Modifiers
.PROPERTY_CUSTOM
;
320 flags
= ModifiersExtensions
.MethodAttr (ModFlags
);
321 flags
|= (method
.flags
& (~MethodAttributes
.MemberAccessMask
));
324 CheckAbstractAndExtern (block
!= null);
325 CheckProtectedModifier ();
327 if (block
!= null && block
.IsIterator
)
328 Iterator
.CreateIterator (this, Parent
.PartialContainer
, ModFlags
, Compiler
);
333 public bool HasCustomAccessModifier
{
335 return (ModFlags
& Modifiers
.PROPERTY_CUSTOM
) != 0;
339 public PropertyBase Property
{
345 public override ObsoleteAttribute
GetObsoleteAttribute ()
347 return method
.GetObsoleteAttribute ();
350 public override string GetSignatureForError()
352 return method
.GetSignatureForError () + '.' + prefix
.Substring (0, 3);
355 void CheckModifiers (Modifiers modflags
)
357 modflags
&= Modifiers
.AccessibilityMask
;
359 Modifiers mflags
= method
.ModFlags
& Modifiers
.AccessibilityMask
;
361 if ((mflags
& Modifiers
.PUBLIC
) != 0) {
362 flags
|= Modifiers
.PROTECTED
| Modifiers
.INTERNAL
| Modifiers
.PRIVATE
;
364 else if ((mflags
& Modifiers
.PROTECTED
) != 0) {
365 if ((mflags
& Modifiers
.INTERNAL
) != 0)
366 flags
|= Modifiers
.PROTECTED
| Modifiers
.INTERNAL
;
368 flags
|= Modifiers
.PRIVATE
;
369 } else if ((mflags
& Modifiers
.INTERNAL
) != 0)
370 flags
|= Modifiers
.PRIVATE
;
372 if ((mflags
== modflags
) || (modflags
& (~flags
)) != 0) {
373 Report
.Error (273, Location
,
374 "The accessibility modifier of the `{0}' accessor must be more restrictive than the modifier of the property or indexer `{1}'",
375 GetSignatureForError (), method
.GetSignatureForError ());
379 protected bool CheckForDuplications ()
381 if ((caching_flags
& Flags
.MethodOverloadsExist
) == 0)
384 return Parent
.MemberCache
.CheckExistingMembersOverloads (this, Name
, ParameterInfo
, Report
);
388 public PropertyMethod Get
, Set
;
389 public PropertyBuilder PropertyBuilder
;
390 public MethodBuilder GetBuilder
, SetBuilder
;
392 protected bool define_set_first
= false;
394 public PropertyBase (DeclSpace parent
, FullNamedExpression type
, Modifiers mod_flags
,
395 Modifiers allowed_mod
, MemberName name
,
396 Attributes attrs
, bool define_set_first
)
397 : base (parent
, null, type
, mod_flags
, allowed_mod
, name
, attrs
)
399 this.define_set_first
= define_set_first
;
402 public override void ApplyAttributeBuilder (Attribute a
, CustomAttributeBuilder cb
, PredefinedAttributes pa
)
404 if (a
.HasSecurityAttribute
) {
405 a
.Error_InvalidSecurityParent ();
409 if (a
.Type
== pa
.Dynamic
) {
410 a
.Error_MisusedDynamicAttribute ();
414 PropertyBuilder
.SetCustomAttribute (cb
);
417 public override AttributeTargets AttributeTargets
{
419 return AttributeTargets
.Property
;
423 protected override void DoMemberTypeDependentChecks ()
425 base.DoMemberTypeDependentChecks ();
429 if (MemberType
.IsGenericParameter
)
433 if ((MemberType
.Attributes
& Class
.StaticClassAttribute
) == Class
.StaticClassAttribute
) {
434 Report
.Error (722, Location
, Error722
, TypeManager
.CSharpName (MemberType
));
438 protected override void DoMemberTypeIndependentChecks ()
440 base.DoMemberTypeIndependentChecks ();
443 // Accessors modifiers check
445 if ((Get
.ModFlags
& Modifiers
.AccessibilityMask
) != 0 &&
446 (Set
.ModFlags
& Modifiers
.AccessibilityMask
) != 0) {
447 Report
.Error (274, Location
, "`{0}': Cannot specify accessibility modifiers for both accessors of the property or indexer",
448 GetSignatureForError ());
451 if ((ModFlags
& Modifiers
.OVERRIDE
) == 0 &&
452 (Get
.IsDummy
&& (Set
.ModFlags
& Modifiers
.AccessibilityMask
) != 0) ||
453 (Set
.IsDummy
&& (Get
.ModFlags
& Modifiers
.AccessibilityMask
) != 0)) {
454 Report
.Error (276, Location
,
455 "`{0}': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor",
456 GetSignatureForError ());
462 GetBuilder
= Get
.Define (Parent
);
463 return (Get
.IsDummy
) ? true : GetBuilder
!= null;
466 bool DefineSet (bool define
)
471 SetBuilder
= Set
.Define (Parent
);
472 return (Set
.IsDummy
) ? true : SetBuilder
!= null;
475 protected bool DefineAccessors ()
477 return DefineSet (define_set_first
) &&
479 DefineSet (!define_set_first
);
482 protected void DefineBuilders (MemberKind kind
, Type
[] parameterTypes
)
484 // FIXME - PropertyAttributes.HasDefault ?
486 PropertyBuilder
= Parent
.TypeBuilder
.DefineProperty (
487 GetFullName (MemberName
), PropertyAttributes
.None
, MemberType
, parameterTypes
);
490 PropertyBuilder
.SetGetMethod (GetBuilder
);
491 Parent
.MemberCache
.AddMember (GetBuilder
, Get
.Spec
);
495 PropertyBuilder
.SetSetMethod (SetBuilder
);
496 Parent
.MemberCache
.AddMember (SetBuilder
, Set
.Spec
);
499 var spec
= new PropertySpec (kind
, this, PropertyBuilder
, ModFlags
);
500 Parent
.MemberCache
.AddMember (PropertyBuilder
, spec
);
503 protected abstract PropertyInfo
ResolveBaseProperty ();
505 // TODO: rename to Resolve......
506 protected override MethodInfo
FindOutBaseMethod (ref Type base_ret_type
)
508 PropertyInfo base_property
= ResolveBaseProperty ();
509 if (base_property
== null)
512 base_ret_type
= base_property
.PropertyType
;
513 MethodInfo get_accessor
= base_property
.GetGetMethod (true);
514 MethodInfo set_accessor
= base_property
.GetSetMethod (true);
515 MethodAttributes get_accessor_access
= 0, set_accessor_access
= 0;
518 // Check base property accessors conflict
520 if ((ModFlags
& (Modifiers
.OVERRIDE
| Modifiers
.NEW
)) == Modifiers
.OVERRIDE
) {
521 if (get_accessor
== null) {
522 if (Get
!= null && !Get
.IsDummy
) {
523 Report
.SymbolRelatedToPreviousError (base_property
);
524 Report
.Error (545, Location
,
525 "`{0}.get': cannot override because `{1}' does not have an overridable get accessor",
526 GetSignatureForError (), TypeManager
.GetFullNameSignature (base_property
));
529 get_accessor_access
= get_accessor
.Attributes
& MethodAttributes
.MemberAccessMask
;
531 if (!Get
.IsDummy
&& !CheckAccessModifiers (
532 ModifiersExtensions
.MethodAttr (Get
.ModFlags
) & MethodAttributes
.MemberAccessMask
, get_accessor_access
, get_accessor
))
533 Error_CannotChangeAccessModifiers (Get
.Location
, get_accessor
, get_accessor_access
, ".get");
536 if (set_accessor
== null) {
537 if (Set
!= null && !Set
.IsDummy
) {
538 Report
.SymbolRelatedToPreviousError (base_property
);
539 Report
.Error (546, Location
,
540 "`{0}.set': cannot override because `{1}' does not have an overridable set accessor",
541 GetSignatureForError (), TypeManager
.GetFullNameSignature (base_property
));
544 set_accessor_access
= set_accessor
.Attributes
& MethodAttributes
.MemberAccessMask
;
546 if (!Set
.IsDummy
&& !CheckAccessModifiers (
547 ModifiersExtensions
.MethodAttr (Set
.ModFlags
) & MethodAttributes
.MemberAccessMask
, set_accessor_access
, set_accessor
))
548 Error_CannotChangeAccessModifiers (Set
.Location
, set_accessor
, set_accessor_access
, ".set");
552 // When one accessor does not exist and property hides base one
553 // we need to propagate this upwards
554 if (set_accessor
== null)
555 set_accessor
= get_accessor
;
558 // Get the less restrictive access
560 return get_accessor_access
> set_accessor_access
? get_accessor
: set_accessor
;
563 public override void Emit ()
566 // The PropertyBuilder can be null for explicit implementations, in that
567 // case, we do not actually emit the ".property", so there is nowhere to
570 if (PropertyBuilder
!= null) {
571 if (OptAttributes
!= null)
572 OptAttributes
.Emit ();
574 if (TypeManager
.IsDynamicType (member_type
)) {
575 PredefinedAttributes
.Get
.Dynamic
.EmitAttribute (PropertyBuilder
);
577 var trans_flags
= TypeManager
.HasDynamicTypeUsed (member_type
);
578 if (trans_flags
!= null) {
579 var pa
= PredefinedAttributes
.Get
.DynamicTransform
;
580 if (pa
.Constructor
!= null || pa
.ResolveConstructor (Location
, TypeManager
.bool_type
.MakeArrayType ())) {
581 PropertyBuilder
.SetCustomAttribute (
582 new CustomAttributeBuilder (pa
.Constructor
, new object [] { trans_flags }
));
598 /// Tests whether accessors are not in collision with some method (CS0111)
600 public bool AreAccessorsDuplicateImplementation (MethodCore mc
)
602 return Get
.IsDuplicateImplementation (mc
) || Set
.IsDuplicateImplementation (mc
);
605 public override bool IsUsed
611 return Get
.IsUsed
| Set
.IsUsed
;
615 protected override void SetMemberName (MemberName new_name
)
617 base.SetMemberName (new_name
);
619 Get
.UpdateName (this);
620 Set
.UpdateName (this);
623 public override string[] ValidAttributeTargets
{
625 return attribute_targets
;
630 // Represents header string for documentation comment.
632 public override string DocCommentHeader
{
637 public class Property
: PropertyBase
639 public sealed class BackingField
: Field
641 readonly Property property
;
643 public BackingField (Property p
)
644 : base (p
.Parent
, p
.type_name
,
645 Modifiers
.BACKING_FIELD
| Modifiers
.COMPILER_GENERATED
| Modifiers
.PRIVATE
| (p
.ModFlags
& (Modifiers
.STATIC
| Modifiers
.UNSAFE
)),
646 new MemberName ("<" + p
.GetFullName (p
.MemberName
) + ">k__BackingField", p
.Location
), null)
651 public override string GetSignatureForError ()
653 return property
.GetSignatureForError ();
657 const Modifiers AllowedModifiers
=
660 Modifiers
.PROTECTED
|
671 const Modifiers AllowedInterfaceModifiers
=
674 public Property (DeclSpace parent
, FullNamedExpression type
, Modifiers mod
,
675 MemberName name
, Attributes attrs
, Accessor get_block
,
676 Accessor set_block
, bool define_set_first
)
677 : this (parent
, type
, mod
, name
, attrs
, get_block
, set_block
,
678 define_set_first
, null)
682 public Property (DeclSpace parent
, FullNamedExpression type
, Modifiers mod
,
683 MemberName name
, Attributes attrs
, Accessor get_block
,
684 Accessor set_block
, bool define_set_first
, Block current_block
)
685 : base (parent
, type
, mod
,
686 parent
.PartialContainer
.Kind
== MemberKind
.Interface
? AllowedInterfaceModifiers
: AllowedModifiers
,
687 name
, attrs
, define_set_first
)
689 if (get_block
== null)
690 Get
= new GetMethod (this);
692 Get
= new GetMethod (this, get_block
);
694 if (set_block
== null)
695 Set
= new SetMethod (this);
697 Set
= new SetMethod (this, set_block
);
699 if (!IsInterface
&& (mod
& (Modifiers
.ABSTRACT
| Modifiers
.EXTERN
)) == 0 &&
700 get_block
!= null && get_block
.Block
== null &&
701 set_block
!= null && set_block
.Block
== null) {
702 if (RootContext
.Version
<= LanguageVersion
.ISO_2
)
703 Report
.FeatureIsNotAvailable (Location
, "automatically implemented properties");
705 Get
.ModFlags
|= Modifiers
.COMPILER_GENERATED
;
706 Set
.ModFlags
|= Modifiers
.COMPILER_GENERATED
;
710 void CreateAutomaticProperty ()
712 // Create backing field
713 Field field
= new BackingField (this);
714 if (!field
.Define ())
717 Parent
.PartialContainer
.AddField (field
);
719 FieldExpr fe
= new FieldExpr (field
, Location
);
720 if ((field
.ModFlags
& Modifiers
.STATIC
) == 0)
721 fe
.InstanceExpression
= new CompilerGeneratedThis (fe
.Type
, Location
);
724 Get
.Block
= new ToplevelBlock (Compiler
, ParametersCompiled
.EmptyReadOnlyParameters
, Location
);
725 Return r
= new Return (fe
, Location
);
726 Get
.Block
.AddStatement (r
);
729 Set
.Block
= new ToplevelBlock (Compiler
, Set
.ParameterInfo
, Location
);
730 Assign a
= new SimpleAssign (fe
, new SimpleName ("value", Location
));
731 Set
.Block
.AddStatement (new StatementExpression (a
));
734 public override bool Define ()
739 flags
|= MethodAttributes
.HideBySig
| MethodAttributes
.SpecialName
;
741 if ((Get
.ModFlags
& Modifiers
.COMPILER_GENERATED
) != 0)
742 CreateAutomaticProperty ();
744 if (!DefineAccessors ())
750 DefineBuilders (MemberKind
.Property
, null);
751 TypeManager
.RegisterProperty (PropertyBuilder
, this);
755 public override void Emit ()
757 if (((Set
.ModFlags
| Get
.ModFlags
) & (Modifiers
.STATIC
| Modifiers
.COMPILER_GENERATED
)) == Modifiers
.COMPILER_GENERATED
&& Parent
.PartialContainer
.HasExplicitLayout
) {
758 Report
.Error (842, Location
,
759 "Automatically implemented property `{0}' cannot be used inside a type with an explicit StructLayout attribute",
760 GetSignatureForError ());
766 protected override PropertyInfo
ResolveBaseProperty ()
768 return Parent
.PartialContainer
.BaseCache
.FindMemberToOverride (
769 Parent
.TypeBuilder
, Name
, ParametersCompiled
.EmptyReadOnlyParameters
, null, true) as PropertyInfo
;
774 /// Gigantic workaround for lameness in SRE follows :
775 /// This class derives from EventInfo and attempts to basically
776 /// wrap around the EventBuilder so that FindMembers can quickly
777 /// return this in it search for members
779 public class MyEventBuilder
: EventInfo
{
782 // We use this to "point" to our Builder which is
783 // not really a MemberInfo
785 EventBuilder MyBuilder
;
788 // We "catch" and wrap these methods
790 MethodInfo raise
, remove, add;
792 EventAttributes attributes
;
793 Type declaring_type
, reflected_type
, event_type
;
798 public MyEventBuilder (Event ev
, TypeBuilder type_builder
, string name
, EventAttributes event_attr
, Type event_type
)
800 MyBuilder
= type_builder
.DefineEvent (name
, event_attr
, event_type
);
802 // And now store the values in our own fields.
804 declaring_type
= type_builder
;
806 reflected_type
= type_builder
;
808 attributes
= event_attr
;
811 this.event_type
= event_type
;
815 // Methods that you have to override. Note that you only need
816 // to "implement" the variants that take the argument (those are
817 // the "abstract" methods, the others (GetAddMethod()) are
820 public override MethodInfo
GetAddMethod (bool nonPublic
)
825 public override MethodInfo
GetRemoveMethod (bool nonPublic
)
830 public override MethodInfo
GetRaiseMethod (bool nonPublic
)
836 // These methods make "MyEventInfo" look like a Builder
838 public void SetRaiseMethod (MethodBuilder raiseMethod
)
841 MyBuilder
.SetRaiseMethod (raiseMethod
);
844 public void SetRemoveOnMethod (MethodBuilder removeMethod
)
846 remove = removeMethod
;
847 MyBuilder
.SetRemoveOnMethod (removeMethod
);
850 public void SetAddOnMethod (MethodBuilder addMethod
)
853 MyBuilder
.SetAddOnMethod (addMethod
);
856 public void SetCustomAttribute (CustomAttributeBuilder cb
)
858 MyBuilder
.SetCustomAttribute (cb
);
861 public override object [] GetCustomAttributes (bool inherit
)
863 // FIXME : There's nothing which can be seemingly done here because
864 // we have no way of getting at the custom attribute objects of the
869 public override object [] GetCustomAttributes (Type t
, bool inherit
)
871 // FIXME : Same here !
875 public override bool IsDefined (Type t
, bool b
)
880 public override EventAttributes Attributes
{
886 public override string Name
{
892 public override Type DeclaringType
{
894 return declaring_type
;
898 public override Type ReflectedType
{
900 return reflected_type
;
904 public Type EventType
{
910 public void SetUsed ()
912 if (my_event
!= null) {
913 // my_event.SetAssigned ();
914 my_event
.SetIsUsed ();
920 /// For case when event is declared like property (with add and remove accessors).
922 public class EventProperty
: Event
{
923 abstract class AEventPropertyAccessor
: AEventAccessor
925 protected AEventPropertyAccessor (EventProperty method
, Accessor accessor
, string prefix
)
926 : base (method
, accessor
, prefix
)
930 public override MethodBuilder
Define (DeclSpace ds
)
932 CheckAbstractAndExtern (block
!= null);
933 return base.Define (ds
);
936 public override string GetSignatureForError ()
938 return method
.GetSignatureForError () + "." + prefix
.Substring (0, prefix
.Length
- 1);
942 sealed class AddDelegateMethod
: AEventPropertyAccessor
944 public AddDelegateMethod (EventProperty method
, Accessor accessor
):
945 base (method
, accessor
, AddPrefix
)
950 sealed class RemoveDelegateMethod
: AEventPropertyAccessor
952 public RemoveDelegateMethod (EventProperty method
, Accessor accessor
):
953 base (method
, accessor
, RemovePrefix
)
959 static readonly string[] attribute_targets
= new string [] { "event" }
; // "property" target was disabled for 2.0 version
961 public EventProperty (DeclSpace parent
, FullNamedExpression type
, Modifiers mod_flags
,
963 Attributes attrs
, Accessor
add, Accessor
remove)
964 : base (parent
, type
, mod_flags
, name
, attrs
)
966 Add
= new AddDelegateMethod (this, add);
967 Remove
= new RemoveDelegateMethod (this, remove);
970 public override bool Define()
979 public override string[] ValidAttributeTargets
{
981 return attribute_targets
;
987 /// Event is declared like field.
989 public class EventField
: Event
{
990 abstract class EventFieldAccessor
: AEventAccessor
992 protected EventFieldAccessor (EventField method
, string prefix
)
993 : base (method
, prefix
)
997 public override void Emit (DeclSpace parent
)
999 if ((method
.ModFlags
& (Modifiers
.ABSTRACT
| Modifiers
.EXTERN
)) == 0) {
1000 if (parent
is Class
) {
1001 MethodBuilder mb
= method_data
.MethodBuilder
;
1002 mb
.SetImplementationFlags (mb
.GetMethodImplementationFlags () | MethodImplAttributes
.Synchronized
);
1005 var field_info
= ((EventField
) method
).BackingField
;
1006 FieldExpr f_expr
= new FieldExpr (field_info
, Location
);
1007 if ((method
.ModFlags
& Modifiers
.STATIC
) == 0)
1008 f_expr
.InstanceExpression
= new CompilerGeneratedThis (field_info
.Spec
.FieldType
, Location
);
1010 block
= new ToplevelBlock (Compiler
, ParameterInfo
, Location
);
1011 block
.AddStatement (new StatementExpression (
1012 new CompoundAssign (Operation
,
1014 block
.GetParameterReference (ParameterInfo
[0].Name
, Location
))));
1020 protected abstract Binary
.Operator Operation { get; }
1023 sealed class AddDelegateMethod
: EventFieldAccessor
1025 public AddDelegateMethod (EventField method
):
1026 base (method
, AddPrefix
)
1030 protected override Binary
.Operator Operation
{
1031 get { return Binary.Operator.Addition; }
1035 sealed class RemoveDelegateMethod
: EventFieldAccessor
1037 public RemoveDelegateMethod (EventField method
):
1038 base (method
, RemovePrefix
)
1042 protected override Binary
.Operator Operation
{
1043 get { return Binary.Operator.Subtraction; }
1048 static readonly string[] attribute_targets
= new string [] { "event", "field", "method" }
;
1049 static readonly string[] attribute_targets_interface
= new string[] { "event", "method" }
;
1051 public Field BackingField
;
1052 public Expression Initializer
;
1054 public EventField (DeclSpace parent
, FullNamedExpression type
, Modifiers mod_flags
, MemberName name
, Attributes attrs
)
1055 : base (parent
, type
, mod_flags
, name
, attrs
)
1057 Add
= new AddDelegateMethod (this);
1058 Remove
= new RemoveDelegateMethod (this);
1061 public override void ApplyAttributeBuilder (Attribute a
, CustomAttributeBuilder cb
, PredefinedAttributes pa
)
1063 if (a
.Target
== AttributeTargets
.Field
) {
1064 BackingField
.ApplyAttributeBuilder (a
, cb
, pa
);
1068 if (a
.Target
== AttributeTargets
.Method
) {
1069 int errors
= Report
.Errors
;
1070 Add
.ApplyAttributeBuilder (a
, cb
, pa
);
1071 if (errors
== Report
.Errors
)
1072 Remove
.ApplyAttributeBuilder (a
, cb
, pa
);
1076 base.ApplyAttributeBuilder (a
, cb
, pa
);
1079 public override bool Define()
1081 if (!base.Define ())
1084 if (Initializer
!= null && (ModFlags
& Modifiers
.ABSTRACT
) != 0) {
1085 Report
.Error (74, Location
, "`{0}': abstract event cannot have an initializer",
1086 GetSignatureForError ());
1089 if (!HasBackingField
) {
1094 // FIXME: We are unable to detect whether generic event is used because
1095 // we are using FieldExpr instead of EventExpr for event access in that
1096 // case. When this issue will be fixed this hack can be removed.
1097 if (TypeManager
.IsGenericType (MemberType
) || Parent
.IsGeneric
)
1100 if (Add
.IsInterfaceImplementation
)
1103 BackingField
= new Field (Parent
,
1104 new TypeExpression (MemberType
, Location
),
1105 Modifiers
.BACKING_FIELD
| Modifiers
.COMPILER_GENERATED
| Modifiers
.PRIVATE
| (ModFlags
& (Modifiers
.STATIC
| Modifiers
.UNSAFE
)),
1108 Parent
.PartialContainer
.AddField (BackingField
);
1109 BackingField
.Initializer
= Initializer
;
1110 BackingField
.ModFlags
&= ~Modifiers
.COMPILER_GENERATED
;
1112 // Call define because we passed fields definition
1113 return BackingField
.Define ();
1116 public bool HasBackingField
{
1118 return !IsInterface
&& (ModFlags
& Modifiers
.ABSTRACT
) == 0;
1122 public override string[] ValidAttributeTargets
{
1124 return HasBackingField
? attribute_targets
: attribute_targets_interface
;
1129 public abstract class Event
: PropertyBasedMember
{
1130 public abstract class AEventAccessor
: AbstractPropertyEventMethod
1132 protected readonly Event method
;
1133 ImplicitParameter param_attr
;
1135 static readonly string[] attribute_targets
= new string [] { "method", "param", "return" }
;
1137 public const string AddPrefix
= "add_";
1138 public const string RemovePrefix
= "remove_";
1140 protected AEventAccessor (Event method
, string prefix
)
1141 : base (method
, prefix
)
1143 this.method
= method
;
1144 this.ModFlags
= method
.ModFlags
;
1147 protected AEventAccessor (Event method
, Accessor accessor
, string prefix
)
1148 : base (method
, accessor
, prefix
)
1150 this.method
= method
;
1151 this.ModFlags
= method
.ModFlags
;
1154 public bool IsInterfaceImplementation
{
1155 get { return method_data.implementing != null; }
1158 public override void ApplyAttributeBuilder (Attribute a
, CustomAttributeBuilder cb
, PredefinedAttributes pa
)
1160 if (a
.IsInternalMethodImplAttribute
) {
1161 method
.is_external_implementation
= true;
1164 base.ApplyAttributeBuilder (a
, cb
, pa
);
1167 protected override void ApplyToExtraTarget (Attribute a
, CustomAttributeBuilder cb
, PredefinedAttributes pa
)
1169 if (a
.Target
== AttributeTargets
.Parameter
) {
1170 if (param_attr
== null)
1171 param_attr
= new ImplicitParameter (method_data
.MethodBuilder
);
1173 param_attr
.ApplyAttributeBuilder (a
, cb
, pa
);
1177 base.ApplyAttributeBuilder (a
, cb
, pa
);
1180 public override AttributeTargets AttributeTargets
{
1182 return AttributeTargets
.Method
;
1186 public override bool IsClsComplianceRequired ()
1188 return method
.IsClsComplianceRequired ();
1191 public virtual MethodBuilder
Define (DeclSpace parent
)
1193 method_data
= new MethodData (method
, method
.ModFlags
,
1194 method
.flags
| MethodAttributes
.HideBySig
| MethodAttributes
.SpecialName
, this);
1196 if (!method_data
.Define (parent
, method
.GetFullName (MemberName
), Report
))
1199 MethodBuilder mb
= method_data
.MethodBuilder
;
1200 ParameterInfo
.ApplyAttributes (mb
);
1201 Spec
= new MethodSpec (MemberKind
.Method
, this, mb
, ParameterInfo
, method
.ModFlags
);
1206 public override Type ReturnType
{
1208 return TypeManager
.void_type
;
1212 public override ObsoleteAttribute
GetObsoleteAttribute ()
1214 return method
.GetObsoleteAttribute ();
1217 public override string[] ValidAttributeTargets
{
1219 return attribute_targets
;
1223 public override ParametersCompiled ParameterInfo
{
1225 return method
.parameters
;
1231 const Modifiers AllowedModifiers
=
1234 Modifiers
.PROTECTED
|
1235 Modifiers
.INTERNAL
|
1240 Modifiers
.OVERRIDE
|
1242 Modifiers
.ABSTRACT
|
1245 const Modifiers AllowedInterfaceModifiers
=
1248 public AEventAccessor Add
, Remove
;
1249 public MyEventBuilder EventBuilder
;
1250 public MethodBuilder AddBuilder
, RemoveBuilder
;
1252 ParametersCompiled parameters
;
1254 protected Event (DeclSpace parent
, FullNamedExpression type
, Modifiers mod_flags
, MemberName name
, Attributes attrs
)
1255 : base (parent
, null, type
, mod_flags
,
1256 parent
.PartialContainer
.Kind
== MemberKind
.Interface
? AllowedInterfaceModifiers
: AllowedModifiers
,
1261 public override void ApplyAttributeBuilder (Attribute a
, CustomAttributeBuilder cb
, PredefinedAttributes pa
)
1263 if ((a
.HasSecurityAttribute
)) {
1264 a
.Error_InvalidSecurityParent ();
1268 EventBuilder
.SetCustomAttribute (cb
);
1271 public bool AreAccessorsDuplicateImplementation (MethodCore mc
)
1273 return Add
.IsDuplicateImplementation (mc
) || Remove
.IsDuplicateImplementation (mc
);
1276 public override AttributeTargets AttributeTargets
{
1278 return AttributeTargets
.Event
;
1282 public override bool Define ()
1284 if (!base.Define ())
1287 if (!TypeManager
.IsDelegateType (MemberType
)) {
1288 Report
.Error (66, Location
, "`{0}': event must be of a delegate type", GetSignatureForError ());
1291 parameters
= ParametersCompiled
.CreateFullyResolved (
1292 new Parameter (null, "value", Parameter
.Modifier
.NONE
, null, Location
), MemberType
);
1297 if (TypeManager
.delegate_combine_delegate_delegate
== null) {
1298 TypeManager
.delegate_combine_delegate_delegate
= TypeManager
.GetPredefinedMethod (
1299 TypeManager
.delegate_type
, "Combine", Location
,
1300 TypeManager
.delegate_type
, TypeManager
.delegate_type
);
1302 if (TypeManager
.delegate_remove_delegate_delegate
== null) {
1303 TypeManager
.delegate_remove_delegate_delegate
= TypeManager
.GetPredefinedMethod (
1304 TypeManager
.delegate_type
, "Remove", Location
,
1305 TypeManager
.delegate_type
, TypeManager
.delegate_type
);
1309 // Now define the accessors
1312 AddBuilder
= Add
.Define (Parent
);
1313 if (AddBuilder
== null)
1316 RemoveBuilder
= Remove
.Define (Parent
);
1317 if (RemoveBuilder
== null)
1320 EventBuilder
= new MyEventBuilder (this, Parent
.TypeBuilder
, Name
, EventAttributes
.None
, MemberType
);
1321 EventBuilder
.SetAddOnMethod (AddBuilder
);
1322 EventBuilder
.SetRemoveOnMethod (RemoveBuilder
);
1324 var spec
= new EventSpec (this, EventBuilder
, ModFlags
, Add
.Spec
, Remove
.Spec
) {
1325 EventType
= MemberType
1328 TypeManager
.RegisterEventField (EventBuilder
, spec
);
1330 Parent
.MemberCache
.AddMember (EventBuilder
, spec
);
1331 Parent
.MemberCache
.AddMember (AddBuilder
, Add
.Spec
);
1332 Parent
.MemberCache
.AddMember (RemoveBuilder
, Remove
.Spec
);
1337 public override void Emit ()
1339 if (OptAttributes
!= null) {
1340 OptAttributes
.Emit ();
1344 Remove
.Emit (Parent
);
1349 protected override MethodInfo
FindOutBaseMethod (ref Type base_ret_type
)
1351 MethodInfo mi
= (MethodInfo
) Parent
.PartialContainer
.BaseCache
.FindBaseEvent (
1352 Parent
.TypeBuilder
, Name
);
1357 AParametersCollection pd
= TypeManager
.GetParameterData (mi
);
1358 base_ret_type
= pd
.Types
[0];
1363 // Represents header string for documentation comment.
1365 public override string DocCommentHeader
{
1366 get { return "E:"; }
1370 public class EventSpec
: MemberSpec
1374 public EventSpec (IMemberDefinition definition
, EventInfo info
, Modifiers modifiers
, MethodSpec
add, MethodSpec
remove)
1375 : base (MemberKind
.Event
, definition
, info
.Name
, modifiers
)
1378 this.AccessorAdd
= add;
1379 this.AccessorRemove
= remove;
1381 // TODO MemberCache: Remove
1382 if (TypeManager
.IsBeingCompiled (info
))
1383 state
&= ~MemberSpec
.StateFlags
.Obsolete_Undetected
;
1386 public MethodSpec AccessorAdd { get; private set; }
1387 public MethodSpec AccessorRemove { get; private set; }
1389 public override Type DeclaringType
{
1390 get { return info.DeclaringType; }
1393 public Type EventType { get; set; }
1395 public bool IsAbstract
{
1396 get { return (Modifiers & Modifiers.ABSTRACT) != 0; }
1399 public EventInfo MetaInfo
{
1400 get { return info; }
1404 public class Indexer
: PropertyBase
1406 public class GetIndexerMethod
: GetMethod
1408 ParametersCompiled parameters
;
1410 public GetIndexerMethod (Indexer method
):
1413 this.parameters
= method
.parameters
;
1416 public GetIndexerMethod (PropertyBase method
, Accessor accessor
):
1417 base (method
, accessor
)
1419 parameters
= accessor
.Parameters
;
1422 public override MethodBuilder
Define (DeclSpace parent
)
1424 parameters
.Resolve (this);
1425 return base.Define (parent
);
1428 public override bool EnableOverloadChecks (MemberCore overload
)
1430 if (base.EnableOverloadChecks (overload
)) {
1431 overload
.caching_flags
|= Flags
.MethodOverloadsExist
;
1438 public override ParametersCompiled ParameterInfo
{
1445 public class SetIndexerMethod
: SetMethod
1447 public SetIndexerMethod (Indexer method
):
1450 parameters
= ParametersCompiled
.MergeGenerated (Compiler
, method
.parameters
, false, parameters
[0], null);
1453 public SetIndexerMethod (PropertyBase method
, Accessor accessor
):
1454 base (method
, accessor
)
1456 parameters
= method
.Get
.IsDummy
? accessor
.Parameters
: accessor
.Parameters
.Clone ();
1459 public override bool EnableOverloadChecks (MemberCore overload
)
1461 if (base.EnableOverloadChecks (overload
)) {
1462 overload
.caching_flags
|= Flags
.MethodOverloadsExist
;
1470 const Modifiers AllowedModifiers
=
1473 Modifiers
.PROTECTED
|
1474 Modifiers
.INTERNAL
|
1478 Modifiers
.OVERRIDE
|
1483 const Modifiers AllowedInterfaceModifiers
=
1486 public readonly ParametersCompiled parameters
;
1488 public Indexer (DeclSpace parent
, FullNamedExpression type
, MemberName name
, Modifiers mod
,
1489 ParametersCompiled parameters
, Attributes attrs
,
1490 Accessor get_block
, Accessor set_block
, bool define_set_first
)
1491 : base (parent
, type
, mod
,
1492 parent
.PartialContainer
.Kind
== MemberKind
.Interface
? AllowedInterfaceModifiers
: AllowedModifiers
,
1493 name
, attrs
, define_set_first
)
1495 this.parameters
= parameters
;
1497 if (get_block
== null)
1498 Get
= new GetIndexerMethod (this);
1500 Get
= new GetIndexerMethod (this, get_block
);
1502 if (set_block
== null)
1503 Set
= new SetIndexerMethod (this);
1505 Set
= new SetIndexerMethod (this, set_block
);
1508 protected override bool CheckForDuplications ()
1510 return Parent
.MemberCache
.CheckExistingMembersOverloads (this, GetFullName (MemberName
), parameters
, Report
);
1513 public override bool Define ()
1515 if (!base.Define ())
1518 if (!DefineParameters (parameters
))
1521 if (OptAttributes
!= null) {
1522 Attribute indexer_attr
= OptAttributes
.Search (PredefinedAttributes
.Get
.IndexerName
);
1523 if (indexer_attr
!= null) {
1524 // Remove the attribute from the list because it is not emitted
1525 OptAttributes
.Attrs
.Remove (indexer_attr
);
1527 string name
= indexer_attr
.GetIndexerAttributeValue ();
1533 if (IsExplicitImpl
) {
1534 Report
.Error (415, indexer_attr
.Location
,
1535 "The `IndexerName' attribute is valid only on an " +
1536 "indexer that is not an explicit interface member declaration");
1540 if ((ModFlags
& Modifiers
.OVERRIDE
) != 0) {
1541 Report
.Error (609, indexer_attr
.Location
,
1542 "Cannot set the `IndexerName' attribute on an indexer marked override");
1548 if (InterfaceType
!= null) {
1549 string base_IndexerName
= TypeManager
.IndexerPropertyName (InterfaceType
);
1550 if (base_IndexerName
!= Name
)
1551 ShortName
= base_IndexerName
;
1554 if (!Parent
.PartialContainer
.AddMember (this) ||
1555 !Parent
.PartialContainer
.AddMember (Get
) || !Parent
.PartialContainer
.AddMember (Set
))
1558 flags
|= MethodAttributes
.HideBySig
| MethodAttributes
.SpecialName
;
1560 if (!DefineAccessors ())
1566 DefineBuilders (MemberKind
.Indexer
, parameters
.GetEmitTypes ());
1567 TypeManager
.RegisterIndexer (PropertyBuilder
, parameters
);
1571 public override bool EnableOverloadChecks (MemberCore overload
)
1573 if (overload
is Indexer
) {
1574 caching_flags
|= Flags
.MethodOverloadsExist
;
1578 return base.EnableOverloadChecks (overload
);
1581 public override string GetDocCommentName (DeclSpace ds
)
1583 return DocUtil
.GetMethodDocCommentName (this, parameters
, ds
);
1586 public override string GetSignatureForError ()
1588 StringBuilder sb
= new StringBuilder (Parent
.GetSignatureForError ());
1589 if (MemberName
.Left
!= null) {
1591 sb
.Append (MemberName
.Left
.GetSignatureForError ());
1594 sb
.Append (".this");
1595 sb
.Append (parameters
.GetSignatureForError ().Replace ('(', '[').Replace (')', ']'));
1596 return sb
.ToString ();
1599 protected override PropertyInfo
ResolveBaseProperty ()
1601 return Parent
.PartialContainer
.BaseCache
.FindMemberToOverride (
1602 Parent
.TypeBuilder
, Name
, parameters
, null, true) as PropertyInfo
;
1605 protected override bool VerifyClsCompliance ()
1607 if (!base.VerifyClsCompliance ())
1610 parameters
.VerifyClsCompliance (this);