2010-04-06 Jb Evain <jbevain@novell.com>
[mcs.git] / mcs / property.cs
bloba6109dc5f72aa483e0c577ceb265811df9d8d4f0
1 //
2 // property.cs: Property based handlers
3 //
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 // Martin Baulig (martin@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
7 //
8 // Dual licensed under the terms of the MIT X11 or GNU GPL
9 //
10 // Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
11 // Copyright 2004-2008 Novell, Inc
14 using System;
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;
22 using System.Text;
24 #if NET_2_1
25 using XmlElement = System.Object;
26 #else
27 using System.Xml;
28 #endif
30 using Mono.CompilerServices.SymbolWriter;
32 namespace Mono.CSharp
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 ())
48 return false;
50 if (!AttributeTester.IsClsCompliant (MemberType)) {
51 Report.Warning (3003, 1, Location, "Type of `{0}' is not CLS-compliant",
52 GetSignatureForError ());
54 return true;
60 // `set' and `get' accessors are represented with an Accessor.
61 //
62 public class Accessor {
64 // Null if the accessor is empty, or a Block if not
66 public const Modifiers AllowedModifiers =
67 Modifiers.PUBLIC |
68 Modifiers.PROTECTED |
69 Modifiers.INTERNAL |
70 Modifiers.PRIVATE;
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)
80 Block = b;
81 Attributes = attrs;
82 Location = loc;
83 Parameters = p;
84 ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, 0, loc, RootContext.ToplevelTypes.Compiler.Report);
88 public class PropertySpec : MemberSpec
90 PropertyInfo info;
92 public PropertySpec (MemberKind kind, IMemberDefinition definition, PropertyInfo info, Modifiers modifiers)
93 : base (kind, definition, info.Name, modifiers)
95 this.info = info;
98 public override Type DeclaringType {
99 get { return info.DeclaringType; }
102 public PropertyInfo MetaInfo {
103 get { return info; }
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);
135 if (IsDummy)
136 return null;
138 method_data = new MethodData (method, ModFlags, flags, this);
140 if (!method_data.Define (parent, method.GetFullName (MemberName), Report))
141 return null;
143 Spec = new MethodSpec (MemberKind.Method, this, method_data.MethodBuilder, ParameterInfo, ModFlags);
145 return method_data.MethodBuilder;
148 public override Type ReturnType {
149 get {
150 return method.MemberType;
154 public override ParametersCompiled ParameterInfo {
155 get {
156 return ParametersCompiled.EmptyReadOnlyParameters;
160 public override string[] ValidAttributeTargets {
161 get {
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);
193 return;
196 base.ApplyAttributeBuilder (a, cb, pa);
199 public override ParametersCompiled ParameterInfo {
200 get {
201 return parameters;
205 public override MethodBuilder Define (DeclSpace parent)
207 parameters.Resolve (this);
209 base.Define (parent);
211 if (IsDummy)
212 return null;
214 method_data = new MethodData (method, ModFlags, flags, this);
216 if (!method_data.Define (parent, method.GetFullName (MemberName), Report))
217 return null;
219 Spec = new MethodSpec (MemberKind.Method, this, method_data.MethodBuilder, ParameterInfo, ModFlags);
221 return method_data.MethodBuilder;
224 public override Type ReturnType {
225 get {
226 return TypeManager.void_type;
230 public override string[] ValidAttributeTargets {
231 get {
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,
252 string prefix)
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 {
273 get {
274 return AttributeTargets.Method;
278 public override bool IsClsComplianceRequired ()
280 return method.IsClsComplianceRequired ();
283 public virtual MethodBuilder Define (DeclSpace parent)
285 CheckForDuplications ();
287 if (IsDummy) {
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));
291 if (mi != null) {
292 Report.SymbolRelatedToPreviousError (mi);
293 Report.Error (551, Location, "Explicit interface implementation `{0}' is missing accessor `{1}'",
294 method.GetSignatureForError (), TypeManager.CSharpSignature (mi, true));
297 return null;
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;
308 } else {
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);
330 return null;
333 public bool HasCustomAccessModifier {
334 get {
335 return (ModFlags & Modifiers.PROPERTY_CUSTOM) != 0;
339 public PropertyBase Property {
340 get {
341 return method;
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;
358 Modifiers flags = 0;
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)
382 return true;
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 ();
406 return;
409 if (a.Type == pa.Dynamic) {
410 a.Error_MisusedDynamicAttribute ();
411 return;
414 PropertyBuilder.SetCustomAttribute (cb);
417 public override AttributeTargets AttributeTargets {
418 get {
419 return AttributeTargets.Property;
423 protected override void DoMemberTypeDependentChecks ()
425 base.DoMemberTypeDependentChecks ();
427 IsTypePermitted ();
428 #if MS_COMPATIBLE
429 if (MemberType.IsGenericParameter)
430 return;
431 #endif
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 ());
460 bool DefineGet ()
462 GetBuilder = Get.Define (Parent);
463 return (Get.IsDummy) ? true : GetBuilder != null;
466 bool DefineSet (bool define)
468 if (!define)
469 return true;
471 SetBuilder = Set.Define (Parent);
472 return (Set.IsDummy) ? true : SetBuilder != null;
475 protected bool DefineAccessors ()
477 return DefineSet (define_set_first) &&
478 DefineGet () &&
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);
489 if (!Get.IsDummy) {
490 PropertyBuilder.SetGetMethod (GetBuilder);
491 Parent.MemberCache.AddMember (GetBuilder, Get.Spec);
494 if (!Set.IsDummy) {
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)
510 return 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));
528 } else {
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));
543 } else {
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
568 // put the attribute
570 if (PropertyBuilder != null) {
571 if (OptAttributes != null)
572 OptAttributes.Emit ();
574 if (TypeManager.IsDynamicType (member_type)) {
575 PredefinedAttributes.Get.Dynamic.EmitAttribute (PropertyBuilder);
576 } else {
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 }));
588 if (!Get.IsDummy)
589 Get.Emit (Parent);
591 if (!Set.IsDummy)
592 Set.Emit (Parent);
594 base.Emit ();
597 /// <summary>
598 /// Tests whether accessors are not in collision with some method (CS0111)
599 /// </summary>
600 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
602 return Get.IsDuplicateImplementation (mc) || Set.IsDuplicateImplementation (mc);
605 public override bool IsUsed
607 get {
608 if (IsExplicitImpl)
609 return true;
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 {
624 get {
625 return attribute_targets;
630 // Represents header string for documentation comment.
632 public override string DocCommentHeader {
633 get { return "P:"; }
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)
648 this.property = p;
651 public override string GetSignatureForError ()
653 return property.GetSignatureForError ();
657 const Modifiers AllowedModifiers =
658 Modifiers.NEW |
659 Modifiers.PUBLIC |
660 Modifiers.PROTECTED |
661 Modifiers.INTERNAL |
662 Modifiers.PRIVATE |
663 Modifiers.STATIC |
664 Modifiers.SEALED |
665 Modifiers.OVERRIDE |
666 Modifiers.ABSTRACT |
667 Modifiers.UNSAFE |
668 Modifiers.EXTERN |
669 Modifiers.VIRTUAL;
671 const Modifiers AllowedInterfaceModifiers =
672 Modifiers.NEW;
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);
691 else
692 Get = new GetMethod (this, get_block);
694 if (set_block == null)
695 Set = new SetMethod (this);
696 else
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 ())
715 return;
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);
723 // Create get block
724 Get.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location);
725 Return r = new Return (fe, Location);
726 Get.Block.AddStatement (r);
728 // Create set block
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 ()
736 if (!base.Define ())
737 return false;
739 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
741 if ((Get.ModFlags & Modifiers.COMPILER_GENERATED) != 0)
742 CreateAutomaticProperty ();
744 if (!DefineAccessors ())
745 return false;
747 if (!CheckBase ())
748 return false;
750 DefineBuilders (MemberKind.Property, null);
751 TypeManager.RegisterProperty (PropertyBuilder, this);
752 return true;
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 ());
763 base.Emit ();
766 protected override PropertyInfo ResolveBaseProperty ()
768 return Parent.PartialContainer.BaseCache.FindMemberToOverride (
769 Parent.TypeBuilder, Name, ParametersCompiled.EmptyReadOnlyParameters, null, true) as PropertyInfo;
773 /// </summary>
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
778 /// </summary>
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;
794 string name;
796 Event my_event;
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;
809 this.name = name;
810 my_event = ev;
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
818 // regular.
820 public override MethodInfo GetAddMethod (bool nonPublic)
822 return add;
825 public override MethodInfo GetRemoveMethod (bool nonPublic)
827 return remove;
830 public override MethodInfo GetRaiseMethod (bool nonPublic)
832 return raise;
836 // These methods make "MyEventInfo" look like a Builder
838 public void SetRaiseMethod (MethodBuilder raiseMethod)
840 raise = raiseMethod;
841 MyBuilder.SetRaiseMethod (raiseMethod);
844 public void SetRemoveOnMethod (MethodBuilder removeMethod)
846 remove = removeMethod;
847 MyBuilder.SetRemoveOnMethod (removeMethod);
850 public void SetAddOnMethod (MethodBuilder addMethod)
852 add = 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
865 // EventBuilder !
866 return null;
869 public override object [] GetCustomAttributes (Type t, bool inherit)
871 // FIXME : Same here !
872 return null;
875 public override bool IsDefined (Type t, bool b)
877 return true;
880 public override EventAttributes Attributes {
881 get {
882 return attributes;
886 public override string Name {
887 get {
888 return name;
892 public override Type DeclaringType {
893 get {
894 return declaring_type;
898 public override Type ReflectedType {
899 get {
900 return reflected_type;
904 public Type EventType {
905 get {
906 return event_type;
910 public void SetUsed ()
912 if (my_event != null) {
913 // my_event.SetAssigned ();
914 my_event.SetIsUsed ();
919 /// <summary>
920 /// For case when event is declared like property (with add and remove accessors).
921 /// </summary>
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,
962 MemberName name,
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()
972 if (!base.Define ())
973 return false;
975 SetIsUsed ();
976 return true;
979 public override string[] ValidAttributeTargets {
980 get {
981 return attribute_targets;
986 /// <summary>
987 /// Event is declared like field.
988 /// </summary>
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,
1013 f_expr,
1014 block.GetParameterReference (ParameterInfo[0].Name, Location))));
1017 base.Emit (parent);
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);
1065 return;
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);
1073 return;
1076 base.ApplyAttributeBuilder (a, cb, pa);
1079 public override bool Define()
1081 if (!base.Define ())
1082 return false;
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) {
1090 SetIsUsed ();
1091 return true;
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)
1098 SetIsUsed ();
1100 if (Add.IsInterfaceImplementation)
1101 SetIsUsed ();
1103 BackingField = new Field (Parent,
1104 new TypeExpression (MemberType, Location),
1105 Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
1106 MemberName, null);
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 {
1117 get {
1118 return !IsInterface && (ModFlags & Modifiers.ABSTRACT) == 0;
1122 public override string[] ValidAttributeTargets {
1123 get {
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);
1174 return;
1177 base.ApplyAttributeBuilder (a, cb, pa);
1180 public override AttributeTargets AttributeTargets {
1181 get {
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))
1197 return null;
1199 MethodBuilder mb = method_data.MethodBuilder;
1200 ParameterInfo.ApplyAttributes (mb);
1201 Spec = new MethodSpec (MemberKind.Method, this, mb, ParameterInfo, method.ModFlags);
1203 return mb;
1206 public override Type ReturnType {
1207 get {
1208 return TypeManager.void_type;
1212 public override ObsoleteAttribute GetObsoleteAttribute ()
1214 return method.GetObsoleteAttribute ();
1217 public override string[] ValidAttributeTargets {
1218 get {
1219 return attribute_targets;
1223 public override ParametersCompiled ParameterInfo {
1224 get {
1225 return method.parameters;
1231 const Modifiers AllowedModifiers =
1232 Modifiers.NEW |
1233 Modifiers.PUBLIC |
1234 Modifiers.PROTECTED |
1235 Modifiers.INTERNAL |
1236 Modifiers.PRIVATE |
1237 Modifiers.STATIC |
1238 Modifiers.VIRTUAL |
1239 Modifiers.SEALED |
1240 Modifiers.OVERRIDE |
1241 Modifiers.UNSAFE |
1242 Modifiers.ABSTRACT |
1243 Modifiers.EXTERN;
1245 const Modifiers AllowedInterfaceModifiers =
1246 Modifiers.NEW;
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,
1257 name, attrs)
1261 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
1263 if ((a.HasSecurityAttribute)) {
1264 a.Error_InvalidSecurityParent ();
1265 return;
1268 EventBuilder.SetCustomAttribute (cb);
1271 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
1273 return Add.IsDuplicateImplementation (mc) || Remove.IsDuplicateImplementation (mc);
1276 public override AttributeTargets AttributeTargets {
1277 get {
1278 return AttributeTargets.Event;
1282 public override bool Define ()
1284 if (!base.Define ())
1285 return false;
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);
1294 if (!CheckBase ())
1295 return false;
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)
1314 return false;
1316 RemoveBuilder = Remove.Define (Parent);
1317 if (RemoveBuilder == null)
1318 return false;
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);
1334 return true;
1337 public override void Emit ()
1339 if (OptAttributes != null) {
1340 OptAttributes.Emit ();
1343 Add.Emit (Parent);
1344 Remove.Emit (Parent);
1346 base.Emit ();
1349 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
1351 MethodInfo mi = (MethodInfo) Parent.PartialContainer.BaseCache.FindBaseEvent (
1352 Parent.TypeBuilder, Name);
1354 if (mi == null)
1355 return null;
1357 AParametersCollection pd = TypeManager.GetParameterData (mi);
1358 base_ret_type = pd.Types [0];
1359 return mi;
1363 // Represents header string for documentation comment.
1365 public override string DocCommentHeader {
1366 get { return "E:"; }
1370 public class EventSpec : MemberSpec
1372 EventInfo info;
1374 public EventSpec (IMemberDefinition definition, EventInfo info, Modifiers modifiers, MethodSpec add, MethodSpec remove)
1375 : base (MemberKind.Event, definition, info.Name, modifiers)
1377 this.info = info;
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):
1411 base (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;
1432 return true;
1435 return false;
1438 public override ParametersCompiled ParameterInfo {
1439 get {
1440 return parameters;
1445 public class SetIndexerMethod: SetMethod
1447 public SetIndexerMethod (Indexer method):
1448 base (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;
1463 return true;
1466 return false;
1470 const Modifiers AllowedModifiers =
1471 Modifiers.NEW |
1472 Modifiers.PUBLIC |
1473 Modifiers.PROTECTED |
1474 Modifiers.INTERNAL |
1475 Modifiers.PRIVATE |
1476 Modifiers.VIRTUAL |
1477 Modifiers.SEALED |
1478 Modifiers.OVERRIDE |
1479 Modifiers.UNSAFE |
1480 Modifiers.EXTERN |
1481 Modifiers.ABSTRACT;
1483 const Modifiers AllowedInterfaceModifiers =
1484 Modifiers.NEW;
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);
1499 else
1500 Get = new GetIndexerMethod (this, get_block);
1502 if (set_block == null)
1503 Set = new SetIndexerMethod (this);
1504 else
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 ())
1516 return false;
1518 if (!DefineParameters (parameters))
1519 return false;
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 ();
1528 if (name == null)
1529 return false;
1531 ShortName = name;
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");
1537 return false;
1540 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
1541 Report.Error (609, indexer_attr.Location,
1542 "Cannot set the `IndexerName' attribute on an indexer marked override");
1543 return false;
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))
1556 return false;
1558 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
1560 if (!DefineAccessors ())
1561 return false;
1563 if (!CheckBase ())
1564 return false;
1566 DefineBuilders (MemberKind.Indexer, parameters.GetEmitTypes ());
1567 TypeManager.RegisterIndexer (PropertyBuilder, parameters);
1568 return true;
1571 public override bool EnableOverloadChecks (MemberCore overload)
1573 if (overload is Indexer) {
1574 caching_flags |= Flags.MethodOverloadsExist;
1575 return true;
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) {
1590 sb.Append ('.');
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 ())
1608 return false;
1610 parameters.VerifyClsCompliance (this);
1611 return true;