[System] Throw PlatformNotSupportedException if NetworkInformation.NetworkChange...
[mono-project.git] / mcs / mcs / property.cs
blob94e9b6baf043f36d20efd23bba912a6238f3b16f
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
12 // Copyright 2011 Xamarin Inc
15 using System;
16 using System.Collections.Generic;
17 using System.Text;
18 using Mono.CompilerServices.SymbolWriter;
20 #if NET_2_1
21 using XmlElement = System.Object;
22 #endif
24 #if STATIC
25 using IKVM.Reflection;
26 using IKVM.Reflection.Emit;
27 #else
28 using System.Reflection;
29 using System.Reflection.Emit;
30 #endif
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 protected PropertyBasedMember (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name, Attributes attrs)
39 : base (parent, type, mod, allowed_mod, name, attrs)
43 protected void CheckReservedNameConflict (string prefix, MethodSpec accessor)
45 string name;
46 AParametersCollection parameters;
47 if (accessor != null) {
48 name = accessor.Name;
49 parameters = accessor.Parameters;
50 } else {
51 name = prefix + ShortName;
52 if (IsExplicitImpl)
53 name = MemberName.Left + "." + name;
55 if (this is Indexer) {
56 parameters = ((Indexer) this).ParameterInfo;
57 if (prefix[0] == 's') {
58 var data = new IParameterData[parameters.Count + 1];
59 Array.Copy (parameters.FixedParameters, data, data.Length - 1);
60 data[data.Length - 1] = new ParameterData ("value", Parameter.Modifier.NONE);
61 var types = new TypeSpec[data.Length];
62 Array.Copy (parameters.Types, types, data.Length - 1);
63 types[data.Length - 1] = member_type;
65 parameters = new ParametersImported (data, types, false);
67 } else {
68 if (prefix[0] == 's')
69 parameters = ParametersCompiled.CreateFullyResolved (new[] { member_type });
70 else
71 parameters = ParametersCompiled.EmptyReadOnlyParameters;
75 var conflict = MemberCache.FindMember (Parent.Definition,
76 new MemberFilter (name, 0, MemberKind.Method, parameters, null),
77 BindingRestriction.DeclaredOnly | BindingRestriction.NoAccessors);
79 if (conflict != null) {
80 Report.SymbolRelatedToPreviousError (conflict);
81 Report.Error (82, Location, "A member `{0}' is already reserved", conflict.GetSignatureForError ());
85 protected override bool VerifyClsCompliance ()
87 if (!base.VerifyClsCompliance ())
88 return false;
90 if (!MemberType.IsCLSCompliant ()) {
91 Report.Warning (3003, 1, Location, "Type of `{0}' is not CLS-compliant",
92 GetSignatureForError ());
94 return true;
99 public class PropertySpec : MemberSpec, IInterfaceMemberSpec
101 PropertyInfo info;
102 TypeSpec memberType;
103 MethodSpec set, get;
105 public PropertySpec (MemberKind kind, TypeSpec declaringType, IMemberDefinition definition, TypeSpec memberType, PropertyInfo info, Modifiers modifiers)
106 : base (kind, declaringType, definition, modifiers)
108 this.info = info;
109 this.memberType = memberType;
112 #region Properties
114 public MethodSpec Get {
115 get {
116 return get;
118 set {
119 get = value;
120 get.IsAccessor = true;
124 public MethodSpec Set {
125 get {
126 return set;
128 set {
129 set = value;
130 set.IsAccessor = true;
134 public bool HasDifferentAccessibility {
135 get {
136 return HasGet && HasSet &&
137 (Get.Modifiers & Modifiers.AccessibilityMask) != (Set.Modifiers & Modifiers.AccessibilityMask);
141 public bool HasGet {
142 get {
143 return Get != null;
147 public bool HasSet {
148 get {
149 return Set != null;
153 public PropertyInfo MetaInfo {
154 get {
155 if ((state & StateFlags.PendingMetaInflate) != 0)
156 throw new NotSupportedException ();
158 return info;
162 public TypeSpec MemberType {
163 get {
164 return memberType;
168 #endregion
170 public override MemberSpec InflateMember (TypeParameterInflator inflator)
172 var ps = (PropertySpec) base.InflateMember (inflator);
173 ps.memberType = inflator.Inflate (memberType);
174 return ps;
177 public override List<MissingTypeSpecReference> ResolveMissingDependencies (MemberSpec caller)
179 return memberType.ResolveMissingDependencies (this);
184 // Properties and Indexers both generate PropertyBuilders, we use this to share
185 // their common bits.
187 abstract public class PropertyBase : PropertyBasedMember {
189 public class GetMethod : PropertyMethod
191 static readonly string[] attribute_targets = new string [] { "method", "return" };
193 internal const string Prefix = "get_";
195 public GetMethod (PropertyBase method, Modifiers modifiers, Attributes attrs, Location loc)
196 : base (method, Prefix, modifiers, attrs, loc)
200 public override void Define (TypeContainer parent)
202 base.Define (parent);
204 Spec = new MethodSpec (MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, ParameterInfo, ModFlags);
206 method_data = new MethodData (method, ModFlags, flags, this);
208 method_data.Define (parent.PartialContainer, method.GetFullName (MemberName));
211 public override TypeSpec ReturnType {
212 get {
213 return method.MemberType;
217 public override ParametersCompiled ParameterInfo {
218 get {
219 return ParametersCompiled.EmptyReadOnlyParameters;
223 public override string[] ValidAttributeTargets {
224 get {
225 return attribute_targets;
230 public class SetMethod : PropertyMethod {
232 static readonly string[] attribute_targets = new string[] { "method", "param", "return" };
234 internal const string Prefix = "set_";
236 protected ParametersCompiled parameters;
238 public SetMethod (PropertyBase method, Modifiers modifiers, ParametersCompiled parameters, Attributes attrs, Location loc)
239 : base (method, Prefix, modifiers, attrs, loc)
241 this.parameters = parameters;
244 protected override void ApplyToExtraTarget (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
246 if (a.Target == AttributeTargets.Parameter) {
247 parameters[parameters.Count - 1].ApplyAttributeBuilder (a, ctor, cdata, pa);
248 return;
251 base.ApplyToExtraTarget (a, ctor, cdata, pa);
254 public override ParametersCompiled ParameterInfo {
255 get {
256 return parameters;
260 public override void Define (TypeContainer parent)
262 parameters.Resolve (this);
264 base.Define (parent);
266 Spec = new MethodSpec (MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, ParameterInfo, ModFlags);
268 method_data = new MethodData (method, ModFlags, flags, this);
270 method_data.Define (parent.PartialContainer, method.GetFullName (MemberName));
273 public override TypeSpec ReturnType {
274 get {
275 return Parent.Compiler.BuiltinTypes.Void;
279 public override string[] ValidAttributeTargets {
280 get {
281 return attribute_targets;
286 static readonly string[] attribute_targets = new string[] { "property" };
288 public abstract class PropertyMethod : AbstractPropertyEventMethod
290 const Modifiers AllowedModifiers =
291 Modifiers.PUBLIC |
292 Modifiers.PROTECTED |
293 Modifiers.INTERNAL |
294 Modifiers.PRIVATE;
296 protected readonly PropertyBase method;
297 protected MethodAttributes flags;
299 public PropertyMethod (PropertyBase method, string prefix, Modifiers modifiers, Attributes attrs, Location loc)
300 : base (method, prefix, attrs, loc)
302 this.method = method;
303 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, modifiers, 0, loc, Report);
304 this.ModFlags |= (method.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE));
307 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
309 if (a.Type == pa.MethodImpl) {
310 method.is_external_implementation = a.IsInternalCall ();
313 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
316 public override AttributeTargets AttributeTargets {
317 get {
318 return AttributeTargets.Method;
322 public override bool IsClsComplianceRequired ()
324 return method.IsClsComplianceRequired ();
327 public virtual void Define (TypeContainer parent)
329 var container = parent.PartialContainer;
332 // Check for custom access modifier
334 if ((ModFlags & Modifiers.AccessibilityMask) == 0) {
335 ModFlags |= method.ModFlags;
336 flags = method.flags;
337 } else {
338 CheckModifiers (ModFlags);
339 ModFlags |= (method.ModFlags & (~Modifiers.AccessibilityMask));
340 ModFlags |= Modifiers.PROPERTY_CUSTOM;
342 if (container.Kind == MemberKind.Interface) {
343 Report.Error (275, Location, "`{0}': accessibility modifiers may not be used on accessors in an interface",
344 GetSignatureForError ());
345 } else if ((ModFlags & Modifiers.PRIVATE) != 0) {
346 if ((method.ModFlags & Modifiers.ABSTRACT) != 0) {
347 Report.Error (442, Location, "`{0}': abstract properties cannot have private accessors", GetSignatureForError ());
350 ModFlags &= ~Modifiers.VIRTUAL;
353 flags = ModifiersExtensions.MethodAttr (ModFlags) | MethodAttributes.SpecialName;
356 CheckAbstractAndExtern (block != null);
357 CheckProtectedModifier ();
359 if (block != null) {
360 if (block.IsIterator)
361 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags);
363 if (Compiler.Settings.WriteMetadataOnly)
364 block = null;
368 public bool HasCustomAccessModifier {
369 get {
370 return (ModFlags & Modifiers.PROPERTY_CUSTOM) != 0;
374 public PropertyBase Property {
375 get {
376 return method;
380 public override ObsoleteAttribute GetAttributeObsolete ()
382 return method.GetAttributeObsolete ();
385 public override string GetSignatureForError()
387 return method.GetSignatureForError () + "." + prefix.Substring (0, 3);
390 void CheckModifiers (Modifiers modflags)
392 if (!ModifiersExtensions.IsRestrictedModifier (modflags & Modifiers.AccessibilityMask, method.ModFlags & Modifiers.AccessibilityMask)) {
393 Report.Error (273, Location,
394 "The accessibility modifier of the `{0}' accessor must be more restrictive than the modifier of the property or indexer `{1}'",
395 GetSignatureForError (), method.GetSignatureForError ());
400 PropertyMethod get, set, first;
401 PropertyBuilder PropertyBuilder;
403 protected PropertyBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod_flags, Modifiers allowed_mod, MemberName name, Attributes attrs)
404 : base (parent, type, mod_flags, allowed_mod, name, attrs)
408 #region Properties
410 public override AttributeTargets AttributeTargets {
411 get {
412 return AttributeTargets.Property;
416 public PropertyMethod AccessorFirst {
417 get {
418 return first;
422 public PropertyMethod AccessorSecond {
423 get {
424 return first == get ? set : get;
428 public override Variance ExpectedMemberTypeVariance {
429 get {
430 return (get != null && set != null) ?
431 Variance.None : set == null ?
432 Variance.Covariant :
433 Variance.Contravariant;
437 public PropertyMethod Get {
438 get {
439 return get;
441 set {
442 get = value;
443 if (first == null)
444 first = value;
446 Parent.AddNameToContainer (get, get.MemberName.Basename);
450 public PropertyMethod Set {
451 get {
452 return set;
454 set {
455 set = value;
456 if (first == null)
457 first = value;
459 Parent.AddNameToContainer (set, set.MemberName.Basename);
463 public override string[] ValidAttributeTargets {
464 get {
465 return attribute_targets;
469 #endregion
471 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
473 if (a.HasSecurityAttribute) {
474 a.Error_InvalidSecurityParent ();
475 return;
478 if (a.Type == pa.Dynamic) {
479 a.Error_MisusedDynamicAttribute ();
480 return;
483 PropertyBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
486 void CheckMissingAccessor (MemberKind kind, ParametersCompiled parameters, bool get)
488 if (IsExplicitImpl) {
489 MemberFilter filter;
490 if (kind == MemberKind.Indexer)
491 filter = new MemberFilter (MemberCache.IndexerNameAlias, 0, kind, parameters, null);
492 else
493 filter = new MemberFilter (MemberName.Name, 0, kind, null, null);
495 var implementing = MemberCache.FindMember (InterfaceType, filter, BindingRestriction.DeclaredOnly) as PropertySpec;
497 if (implementing == null)
498 return;
500 var accessor = get ? implementing.Get : implementing.Set;
501 if (accessor != null) {
502 Report.SymbolRelatedToPreviousError (accessor);
503 Report.Error (551, Location, "Explicit interface implementation `{0}' is missing accessor `{1}'",
504 GetSignatureForError (), accessor.GetSignatureForError ());
509 protected override bool CheckOverrideAgainstBase (MemberSpec base_member)
511 var ok = base.CheckOverrideAgainstBase (base_member);
514 // Check base property accessors conflict
516 var base_prop = (PropertySpec) base_member;
517 if (Get == null) {
518 if ((ModFlags & Modifiers.SEALED) != 0 && base_prop.HasGet && !base_prop.Get.IsAccessible (this)) {
519 // TODO: Should be different error code but csc uses for some reason same
520 Report.SymbolRelatedToPreviousError (base_prop);
521 Report.Error (545, Location,
522 "`{0}': cannot override because `{1}' does not have accessible get accessor",
523 GetSignatureForError (), base_prop.GetSignatureForError ());
524 ok = false;
526 } else {
527 if (!base_prop.HasGet) {
528 if (ok) {
529 Report.SymbolRelatedToPreviousError (base_prop);
530 Report.Error (545, Get.Location,
531 "`{0}': cannot override because `{1}' does not have an overridable get accessor",
532 Get.GetSignatureForError (), base_prop.GetSignatureForError ());
533 ok = false;
535 } else if (Get.HasCustomAccessModifier || base_prop.HasDifferentAccessibility) {
536 if (!base_prop.Get.IsAccessible (this)) {
537 // Same as csc but it should be different error code
538 Report.Error (115, Get.Location, "`{0}' is marked as an override but no accessible `get' accessor found to override",
539 GetSignatureForError ());
540 ok = false;
541 } else if (!CheckAccessModifiers (Get, base_prop.Get)) {
542 Error_CannotChangeAccessModifiers (Get, base_prop.Get);
543 ok = false;
548 if (Set == null) {
549 if (base_prop.HasSet) {
550 if ((ModFlags & Modifiers.SEALED) != 0 && !base_prop.Set.IsAccessible (this)) {
551 // TODO: Should be different error code but csc uses for some reason same
552 Report.SymbolRelatedToPreviousError (base_prop);
553 Report.Error (546, Location,
554 "`{0}': cannot override because `{1}' does not have accessible set accessor",
555 GetSignatureForError (), base_prop.GetSignatureForError ());
556 ok = false;
559 if ((ModFlags & Modifiers.AutoProperty) != 0) {
560 Report.Error (8080, Location, "`{0}': Auto-implemented properties must override all accessors of the overridden property",
561 GetSignatureForError ());
562 ok = false;
565 } else {
566 if (!base_prop.HasSet) {
567 if (ok) {
568 Report.SymbolRelatedToPreviousError (base_prop);
569 Report.Error (546, Set.Location,
570 "`{0}': cannot override because `{1}' does not have an overridable set accessor",
571 Set.GetSignatureForError (), base_prop.GetSignatureForError ());
572 ok = false;
574 } else if (Set.HasCustomAccessModifier || base_prop.HasDifferentAccessibility) {
575 if (!base_prop.Set.IsAccessible (this)) {
576 // Same as csc but it should be different error code
577 Report.Error (115, Set.Location, "`{0}' is marked as an override but no accessible `set' accessor found to override",
578 GetSignatureForError ());
579 ok = false;
580 } else if (!CheckAccessModifiers (Set, base_prop.Set)) {
581 Error_CannotChangeAccessModifiers (Set, base_prop.Set);
582 ok = false;
587 if ((Set == null || !Set.HasCustomAccessModifier) && (Get == null || !Get.HasCustomAccessModifier)) {
588 if (!CheckAccessModifiers (this, base_prop)) {
589 Error_CannotChangeAccessModifiers (this, base_prop);
590 ok = false;
594 return ok;
597 protected override void DoMemberTypeDependentChecks ()
599 base.DoMemberTypeDependentChecks ();
601 IsTypePermitted ();
603 if (MemberType.IsStatic)
604 Error_StaticReturnType ();
607 protected override void DoMemberTypeIndependentChecks ()
609 base.DoMemberTypeIndependentChecks ();
612 // Accessors modifiers check
614 if (AccessorSecond != null) {
615 if ((Get.ModFlags & Modifiers.AccessibilityMask) != 0 && (Set.ModFlags & Modifiers.AccessibilityMask) != 0) {
616 Report.Error (274, Location, "`{0}': Cannot specify accessibility modifiers for both accessors of the property or indexer",
617 GetSignatureForError ());
619 } else if ((ModFlags & Modifiers.OVERRIDE) == 0 &&
620 ((Get == null && (Set.ModFlags & Modifiers.AccessibilityMask) != 0) || (Set == null && (Get.ModFlags & Modifiers.AccessibilityMask) != 0))) {
621 Report.Error (276, Location,
622 "`{0}': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor",
623 GetSignatureForError ());
627 protected bool DefineAccessors ()
629 first.Define (Parent);
630 if (AccessorSecond != null)
631 AccessorSecond.Define (Parent);
633 return true;
636 protected void DefineBuilders (MemberKind kind, ParametersCompiled parameters)
638 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
639 GetFullName (MemberName), PropertyAttributes.None,
640 #if !BOOTSTRAP_BASIC // Requires trunk version mscorlib
641 IsStatic ? 0 : CallingConventions.HasThis,
642 #endif
643 MemberType.GetMetaInfo (), null, null,
644 parameters.GetMetaInfo (), null, null);
646 PropertySpec spec;
647 if (kind == MemberKind.Indexer)
648 spec = new IndexerSpec (Parent.Definition, this, MemberType, parameters, PropertyBuilder, ModFlags);
649 else
650 spec = new PropertySpec (kind, Parent.Definition, this, MemberType, PropertyBuilder, ModFlags);
652 if (Get != null) {
653 spec.Get = Get.Spec;
654 Parent.MemberCache.AddMember (this, Get.Spec.Name, Get.Spec);
655 } else {
656 CheckMissingAccessor (kind, parameters, true);
659 if (Set != null) {
660 spec.Set = Set.Spec;
661 Parent.MemberCache.AddMember (this, Set.Spec.Name, Set.Spec);
662 } else {
663 CheckMissingAccessor (kind, parameters, false);
666 Parent.MemberCache.AddMember (this, PropertyBuilder.Name, spec);
669 public override void Emit ()
671 CheckReservedNameConflict (GetMethod.Prefix, get == null ? null : get.Spec);
672 CheckReservedNameConflict (SetMethod.Prefix, set == null ? null : set.Spec);
674 if (OptAttributes != null)
675 OptAttributes.Emit ();
677 if (member_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
678 Module.PredefinedAttributes.Dynamic.EmitAttribute (PropertyBuilder);
679 } else if (member_type.HasDynamicElement) {
680 Module.PredefinedAttributes.Dynamic.EmitAttribute (PropertyBuilder, member_type, Location);
683 ConstraintChecker.Check (this, member_type, type_expr.Location);
685 first.Emit (Parent);
686 if (AccessorSecond != null)
687 AccessorSecond.Emit (Parent);
689 base.Emit ();
692 public override bool IsUsed {
693 get {
694 if (IsExplicitImpl)
695 return true;
697 return Get.IsUsed | Set.IsUsed;
701 public override void PrepareEmit ()
703 AccessorFirst.PrepareEmit ();
704 if (AccessorSecond != null)
705 AccessorSecond.PrepareEmit ();
707 if (get != null) {
708 var method = Get.Spec.GetMetaInfo () as MethodBuilder;
709 if (method != null)
710 PropertyBuilder.SetGetMethod (method);
713 if (set != null) {
714 var method = Set.Spec.GetMetaInfo () as MethodBuilder;
715 if (method != null)
716 PropertyBuilder.SetSetMethod (method);
720 protected override void SetMemberName (MemberName new_name)
722 base.SetMemberName (new_name);
724 if (Get != null)
725 Get.UpdateName (this);
727 if (Set != null)
728 Set.UpdateName (this);
731 public override void WriteDebugSymbol (MonoSymbolFile file)
733 if (get != null)
734 get.WriteDebugSymbol (file);
736 if (set != null)
737 set.WriteDebugSymbol (file);
741 // Represents header string for documentation comment.
743 public override string DocCommentHeader {
744 get { return "P:"; }
748 public class Property : PropertyBase
750 public sealed class BackingFieldDeclaration : Field
752 readonly Property property;
753 const Modifiers DefaultModifiers = Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | Modifiers.DEBUGGER_HIDDEN;
755 public BackingFieldDeclaration (Property p, bool readOnly)
756 : base (p.Parent, p.type_expr, DefaultModifiers | (p.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
757 new MemberName ("<" + p.GetFullName (p.MemberName) + ">k__BackingField", p.Location), null)
759 this.property = p;
760 if (readOnly)
761 ModFlags |= Modifiers.READONLY;
764 public Property OriginalProperty {
765 get {
766 return property;
770 public override string GetSignatureForError ()
772 return property.GetSignatureForError ();
776 static readonly string[] attribute_target_auto = new string[] { "property", "field" };
778 public Property (TypeDefinition parent, FullNamedExpression type, Modifiers mod,
779 MemberName name, Attributes attrs)
780 : base (parent, type, mod,
781 parent.PartialContainer.Kind == MemberKind.Interface ? AllowedModifiersInterface :
782 parent.PartialContainer.Kind == MemberKind.Struct ? AllowedModifiersStruct :
783 AllowedModifiersClass,
784 name, attrs)
788 public BackingFieldDeclaration BackingField { get; private set; }
790 public Expression Initializer { get; set; }
792 public override void Accept (StructuralVisitor visitor)
794 visitor.Visit (this);
797 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
799 if (a.Target == AttributeTargets.Field) {
800 BackingField.ApplyAttributeBuilder (a, ctor, cdata, pa);
801 return;
804 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
807 void CreateAutomaticProperty ()
809 // Create backing field
810 BackingField = new BackingFieldDeclaration (this, Initializer == null && Set == null);
811 if (!BackingField.Define ())
812 return;
814 if (Initializer != null) {
815 BackingField.Initializer = Initializer;
816 Parent.RegisterFieldForInitialization (BackingField, new FieldInitializer (BackingField, Initializer, Location));
817 BackingField.ModFlags |= Modifiers.READONLY;
820 Parent.PartialContainer.Members.Add (BackingField);
822 FieldExpr fe = new FieldExpr (BackingField, Location);
823 if ((BackingField.ModFlags & Modifiers.STATIC) == 0)
824 fe.InstanceExpression = new CompilerGeneratedThis (Parent.CurrentType, Location);
827 // Create get block but we careful with location to
828 // emit only single sequence point per accessor. This allow
829 // to set a breakpoint on it even with no user code
831 Get.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location.Null);
832 Return r = new Return (fe, Get.Location);
833 Get.Block.AddStatement (r);
834 Get.ModFlags |= Modifiers.COMPILER_GENERATED;
836 // Create set block
837 if (Set != null) {
838 Set.Block = new ToplevelBlock (Compiler, Set.ParameterInfo, Location.Null);
839 Assign a = new SimpleAssign (fe, new SimpleName ("value", Location.Null), Location.Null);
840 Set.Block.AddStatement (new StatementExpression (a, Set.Location));
841 Set.ModFlags |= Modifiers.COMPILER_GENERATED;
845 public override bool Define ()
847 if (!base.Define ())
848 return false;
850 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
852 bool auto = AccessorFirst.Block == null && (AccessorSecond == null || AccessorSecond.Block == null) &&
853 (ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0;
855 if (Initializer != null) {
856 if (!auto)
857 Report.Error (8050, Location, "`{0}': Only auto-implemented properties can have initializers",
858 GetSignatureForError ());
860 if (IsInterface)
861 Report.Error (8052, Location, "`{0}': Properties inside interfaces cannot have initializers",
862 GetSignatureForError ());
864 if (Compiler.Settings.Version < LanguageVersion.V_6)
865 Report.FeatureIsNotAvailable (Compiler, Location, "auto-implemented property initializer");
868 if (auto) {
869 ModFlags |= Modifiers.AutoProperty;
870 if (Get == null) {
871 Report.Error (8051, Location, "Auto-implemented property `{0}' must have get accessor",
872 GetSignatureForError ());
873 return false;
876 if (Compiler.Settings.Version < LanguageVersion.V_3 && Initializer == null)
877 Report.FeatureIsNotAvailable (Compiler, Location, "auto-implemented properties");
879 CreateAutomaticProperty ();
882 if (!DefineAccessors ())
883 return false;
885 if (AccessorSecond == null) {
886 PropertyMethod pm;
887 if (AccessorFirst is GetMethod)
888 pm = new SetMethod (this, 0, ParametersCompiled.EmptyReadOnlyParameters, null, Location);
889 else
890 pm = new GetMethod (this, 0, null, Location);
892 Parent.AddNameToContainer (pm, pm.MemberName.Basename);
895 if (!CheckBase ())
896 return false;
898 DefineBuilders (MemberKind.Property, ParametersCompiled.EmptyReadOnlyParameters);
899 return true;
902 public override void Emit ()
904 if ((AccessorFirst.ModFlags & (Modifiers.STATIC | Modifiers.AutoProperty)) == Modifiers.AutoProperty && Parent.PartialContainer.HasExplicitLayout) {
905 Report.Error (842, Location,
906 "Automatically implemented property `{0}' cannot be used inside a type with an explicit StructLayout attribute",
907 GetSignatureForError ());
910 base.Emit ();
913 public override string[] ValidAttributeTargets {
914 get {
915 return Get != null && ((Get.ModFlags & Modifiers.COMPILER_GENERATED) != 0) ?
916 attribute_target_auto : base.ValidAttributeTargets;
921 /// <summary>
922 /// For case when event is declared like property (with add and remove accessors).
923 /// </summary>
924 public class EventProperty: Event {
925 public abstract class AEventPropertyAccessor : AEventAccessor
927 protected AEventPropertyAccessor (EventProperty method, string prefix, Attributes attrs, Location loc)
928 : base (method, prefix, attrs, loc)
932 public override void Define (TypeContainer ds)
934 CheckAbstractAndExtern (block != null);
935 base.Define (ds);
938 public override string GetSignatureForError ()
940 return method.GetSignatureForError () + "." + prefix.Substring (0, prefix.Length - 1);
944 public sealed class AddDelegateMethod: AEventPropertyAccessor
946 public AddDelegateMethod (EventProperty method, Attributes attrs, Location loc)
947 : base (method, AddPrefix, attrs, loc)
952 public sealed class RemoveDelegateMethod: AEventPropertyAccessor
954 public RemoveDelegateMethod (EventProperty method, Attributes attrs, Location loc)
955 : base (method, RemovePrefix, attrs, loc)
960 static readonly string[] attribute_targets = new string [] { "event" };
962 public EventProperty (TypeDefinition parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
963 : base (parent, type, mod_flags, name, attrs)
967 public override void Accept (StructuralVisitor visitor)
969 visitor.Visit (this);
972 public override bool Define()
974 if (!base.Define ())
975 return false;
977 SetIsUsed ();
978 return true;
981 public override string[] ValidAttributeTargets {
982 get {
983 return attribute_targets;
988 /// <summary>
989 /// Event is declared like field.
990 /// </summary>
991 public class EventField : Event
993 abstract class EventFieldAccessor : AEventAccessor
995 protected EventFieldAccessor (EventField method, string prefix)
996 : base (method, prefix, null, method.Location)
1000 protected abstract MethodSpec GetOperation (Location loc);
1002 public override void Emit (TypeDefinition parent)
1004 if ((method.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0 && !Compiler.Settings.WriteMetadataOnly) {
1005 block = new ToplevelBlock (Compiler, ParameterInfo, Location) {
1006 IsCompilerGenerated = true
1008 FabricateBodyStatement ();
1011 base.Emit (parent);
1014 void FabricateBodyStatement ()
1017 // Delegate obj1 = backing_field
1018 // do {
1019 // Delegate obj2 = obj1;
1020 // obj1 = Interlocked.CompareExchange (ref backing_field, Delegate.Combine|Remove(obj2, value), obj1);
1021 // } while ((object)obj1 != (object)obj2)
1024 var field_info = ((EventField) method).backing_field;
1025 FieldExpr f_expr = new FieldExpr (field_info, Location);
1026 if (!IsStatic)
1027 f_expr.InstanceExpression = new CompilerGeneratedThis (Parent.CurrentType, Location);
1029 var obj1 = LocalVariable.CreateCompilerGenerated (field_info.MemberType, block, Location);
1030 var obj2 = LocalVariable.CreateCompilerGenerated (field_info.MemberType, block, Location);
1032 block.AddStatement (new StatementExpression (new SimpleAssign (new LocalVariableReference (obj1, Location), f_expr)));
1034 var cond = new BooleanExpression (new Binary (Binary.Operator.Inequality,
1035 new Cast (new TypeExpression (Module.Compiler.BuiltinTypes.Object, Location), new LocalVariableReference (obj1, Location), Location),
1036 new Cast (new TypeExpression (Module.Compiler.BuiltinTypes.Object, Location), new LocalVariableReference (obj2, Location), Location)));
1038 var body = new ExplicitBlock (block, Location, Location);
1039 block.AddStatement (new Do (body, cond, Location, Location));
1041 body.AddStatement (new StatementExpression (
1042 new SimpleAssign (new LocalVariableReference (obj2, Location), new LocalVariableReference (obj1, Location))));
1044 var args_oper = new Arguments (2);
1045 args_oper.Add (new Argument (new LocalVariableReference (obj2, Location)));
1046 args_oper.Add (new Argument (block.GetParameterReference (0, Location)));
1048 var op_method = GetOperation (Location);
1050 var args = new Arguments (3);
1051 args.Add (new Argument (f_expr, Argument.AType.Ref));
1052 args.Add (new Argument (new Cast (
1053 new TypeExpression (field_info.MemberType, Location),
1054 new Invocation (MethodGroupExpr.CreatePredefined (op_method, op_method.DeclaringType, Location), args_oper),
1055 Location)));
1056 args.Add (new Argument (new LocalVariableReference (obj1, Location)));
1058 var cas = Module.PredefinedMembers.InterlockedCompareExchange_T.Get ();
1059 if (cas == null) {
1060 if (Module.PredefinedMembers.MonitorEnter_v4.Get () != null || Module.PredefinedMembers.MonitorEnter.Get () != null) {
1061 // Workaround for cripled (e.g. microframework) mscorlib without CompareExchange
1062 body.AddStatement (new Lock (
1063 block.GetParameterReference (0, Location),
1064 new StatementExpression (new SimpleAssign (
1065 f_expr, args [1].Expr, Location), Location), Location));
1066 } else {
1067 Module.PredefinedMembers.InterlockedCompareExchange_T.Resolve (Location);
1069 } else {
1070 body.AddStatement (new StatementExpression (new SimpleAssign (
1071 new LocalVariableReference (obj1, Location),
1072 new Invocation (MethodGroupExpr.CreatePredefined (cas, cas.DeclaringType, Location), args))));
1077 sealed class AddDelegateMethod: EventFieldAccessor
1079 public AddDelegateMethod (EventField method):
1080 base (method, AddPrefix)
1084 protected override MethodSpec GetOperation (Location loc)
1086 return Module.PredefinedMembers.DelegateCombine.Resolve (loc);
1090 sealed class RemoveDelegateMethod: EventFieldAccessor
1092 public RemoveDelegateMethod (EventField method):
1093 base (method, RemovePrefix)
1097 protected override MethodSpec GetOperation (Location loc)
1099 return Module.PredefinedMembers.DelegateRemove.Resolve (loc);
1104 static readonly string[] attribute_targets = new string [] { "event", "field", "method" };
1105 static readonly string[] attribute_targets_interface = new string[] { "event", "method" };
1107 Expression initializer;
1108 Field backing_field;
1109 List<FieldDeclarator> declarators;
1111 public EventField (TypeDefinition parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
1112 : base (parent, type, mod_flags, name, attrs)
1114 Add = new AddDelegateMethod (this);
1115 Remove = new RemoveDelegateMethod (this);
1118 #region Properties
1120 public List<FieldDeclarator> Declarators {
1121 get {
1122 return this.declarators;
1126 bool HasBackingField {
1127 get {
1128 return !IsInterface && (ModFlags & Modifiers.ABSTRACT) == 0;
1132 public Expression Initializer {
1133 get {
1134 return initializer;
1136 set {
1137 initializer = value;
1141 public override string[] ValidAttributeTargets {
1142 get {
1143 return HasBackingField ? attribute_targets : attribute_targets_interface;
1147 #endregion
1150 public override void Accept (StructuralVisitor visitor)
1152 visitor.Visit (this);
1155 public void AddDeclarator (FieldDeclarator declarator)
1157 if (declarators == null)
1158 declarators = new List<FieldDeclarator> (2);
1160 declarators.Add (declarator);
1162 Parent.AddNameToContainer (this, declarator.Name.Value);
1165 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1167 if (a.Target == AttributeTargets.Field) {
1168 backing_field.ApplyAttributeBuilder (a, ctor, cdata, pa);
1169 return;
1172 if (a.Target == AttributeTargets.Method) {
1173 int errors = Report.Errors;
1174 Add.ApplyAttributeBuilder (a, ctor, cdata, pa);
1175 if (errors == Report.Errors)
1176 Remove.ApplyAttributeBuilder (a, ctor, cdata, pa);
1177 return;
1180 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1183 public override bool Define()
1185 var mod_flags_src = ModFlags;
1187 if (!base.Define ())
1188 return false;
1190 if (declarators != null) {
1191 if ((mod_flags_src & Modifiers.DEFAULT_ACCESS_MODIFIER) != 0)
1192 mod_flags_src &= ~(Modifiers.AccessibilityMask | Modifiers.DEFAULT_ACCESS_MODIFIER);
1194 var t = new TypeExpression (MemberType, TypeExpression.Location);
1195 foreach (var d in declarators) {
1196 var ef = new EventField (Parent, t, mod_flags_src, new MemberName (d.Name.Value, d.Name.Location), OptAttributes);
1198 if (d.Initializer != null)
1199 ef.initializer = d.Initializer;
1201 ef.Define ();
1202 Parent.PartialContainer.Members.Add (ef);
1206 if (!HasBackingField) {
1207 SetIsUsed ();
1208 return true;
1211 backing_field = new Field (Parent,
1212 new TypeExpression (MemberType, Location),
1213 Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
1214 MemberName, null);
1216 Parent.PartialContainer.Members.Add (backing_field);
1217 backing_field.Initializer = Initializer;
1218 backing_field.ModFlags &= ~Modifiers.COMPILER_GENERATED;
1220 // Call define because we passed fields definition
1221 backing_field.Define ();
1223 // Set backing field for event fields
1224 spec.BackingField = backing_field.Spec;
1226 return true;
1230 public abstract class Event : PropertyBasedMember
1232 public abstract class AEventAccessor : AbstractPropertyEventMethod
1234 protected readonly Event method;
1235 readonly ParametersCompiled parameters;
1237 static readonly string[] attribute_targets = new string [] { "method", "param", "return" };
1239 public const string AddPrefix = "add_";
1240 public const string RemovePrefix = "remove_";
1242 protected AEventAccessor (Event method, string prefix, Attributes attrs, Location loc)
1243 : base (method, prefix, attrs, loc)
1245 this.method = method;
1246 this.ModFlags = method.ModFlags;
1247 this.parameters = ParametersCompiled.CreateImplicitParameter (method.TypeExpression, loc);
1250 public bool IsInterfaceImplementation {
1251 get { return method_data.implementing != null; }
1254 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1256 if (a.Type == pa.MethodImpl) {
1257 method.is_external_implementation = a.IsInternalCall ();
1260 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1263 protected override void ApplyToExtraTarget (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1265 if (a.Target == AttributeTargets.Parameter) {
1266 parameters[0].ApplyAttributeBuilder (a, ctor, cdata, pa);
1267 return;
1270 base.ApplyToExtraTarget (a, ctor, cdata, pa);
1273 public override AttributeTargets AttributeTargets {
1274 get {
1275 return AttributeTargets.Method;
1279 public override bool IsClsComplianceRequired ()
1281 return method.IsClsComplianceRequired ();
1284 public virtual void Define (TypeContainer parent)
1286 // Fill in already resolved event type to speed things up and
1287 // avoid confusing duplicate errors
1288 ((Parameter) parameters.FixedParameters[0]).Type = method.member_type;
1289 parameters.Types = new TypeSpec[] { method.member_type };
1291 method_data = new MethodData (method, method.ModFlags,
1292 method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this);
1294 if (!method_data.Define (parent.PartialContainer, method.GetFullName (MemberName)))
1295 return;
1297 if (Compiler.Settings.WriteMetadataOnly)
1298 block = null;
1300 Spec = new MethodSpec (MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, ParameterInfo, method.ModFlags);
1301 Spec.IsAccessor = true;
1304 public override TypeSpec ReturnType {
1305 get {
1306 return Parent.Compiler.BuiltinTypes.Void;
1310 public override ObsoleteAttribute GetAttributeObsolete ()
1312 return method.GetAttributeObsolete ();
1315 public MethodData MethodData {
1316 get {
1317 return method_data;
1321 public override string[] ValidAttributeTargets {
1322 get {
1323 return attribute_targets;
1327 public override ParametersCompiled ParameterInfo {
1328 get {
1329 return parameters;
1334 AEventAccessor add, remove;
1335 EventBuilder EventBuilder;
1336 protected EventSpec spec;
1338 protected Event (TypeDefinition parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
1339 : base (parent, type, mod_flags,
1340 parent.PartialContainer.Kind == MemberKind.Interface ? AllowedModifiersInterface :
1341 parent.PartialContainer.Kind == MemberKind.Struct ? AllowedModifiersStruct :
1342 AllowedModifiersClass,
1343 name, attrs)
1347 #region Properties
1349 public override AttributeTargets AttributeTargets {
1350 get {
1351 return AttributeTargets.Event;
1355 public AEventAccessor Add {
1356 get {
1357 return this.add;
1359 set {
1360 add = value;
1361 Parent.AddNameToContainer (value, value.MemberName.Basename);
1365 public override Variance ExpectedMemberTypeVariance {
1366 get {
1367 return Variance.Contravariant;
1371 public AEventAccessor Remove {
1372 get {
1373 return this.remove;
1375 set {
1376 remove = value;
1377 Parent.AddNameToContainer (value, value.MemberName.Basename);
1380 #endregion
1382 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1384 if ((a.HasSecurityAttribute)) {
1385 a.Error_InvalidSecurityParent ();
1386 return;
1389 EventBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
1392 protected override bool CheckOverrideAgainstBase (MemberSpec base_member)
1394 var ok = base.CheckOverrideAgainstBase (base_member);
1396 if (!CheckAccessModifiers (this, base_member)) {
1397 Error_CannotChangeAccessModifiers (this, base_member);
1398 ok = false;
1401 return ok;
1404 public override bool Define ()
1406 if (!base.Define ())
1407 return false;
1409 if (!MemberType.IsDelegate) {
1410 Report.Error (66, Location, "`{0}': event must be of a delegate type", GetSignatureForError ());
1413 if (!CheckBase ())
1414 return false;
1417 // Now define the accessors
1419 add.Define (Parent);
1420 remove.Define (Parent);
1422 EventBuilder = Parent.TypeBuilder.DefineEvent (GetFullName (MemberName), EventAttributes.None, MemberType.GetMetaInfo ());
1424 spec = new EventSpec (Parent.Definition, this, MemberType, ModFlags, Add.Spec, remove.Spec);
1426 Parent.MemberCache.AddMember (this, GetFullName (MemberName), spec);
1427 Parent.MemberCache.AddMember (this, Add.Spec.Name, Add.Spec);
1428 Parent.MemberCache.AddMember (this, Remove.Spec.Name, remove.Spec);
1430 return true;
1433 public override void Emit ()
1435 CheckReservedNameConflict (null, add.Spec);
1436 CheckReservedNameConflict (null, remove.Spec);
1438 if (OptAttributes != null) {
1439 OptAttributes.Emit ();
1442 ConstraintChecker.Check (this, member_type, type_expr.Location);
1444 Add.Emit (Parent);
1445 Remove.Emit (Parent);
1447 base.Emit ();
1450 public override void PrepareEmit ()
1452 base.PrepareEmit ();
1454 add.PrepareEmit ();
1455 remove.PrepareEmit ();
1457 EventBuilder.SetAddOnMethod (add.MethodData.MethodBuilder);
1458 EventBuilder.SetRemoveOnMethod (remove.MethodData.MethodBuilder);
1461 public override void WriteDebugSymbol (MonoSymbolFile file)
1463 add.WriteDebugSymbol (file);
1464 remove.WriteDebugSymbol (file);
1468 // Represents header string for documentation comment.
1470 public override string DocCommentHeader {
1471 get { return "E:"; }
1475 public class EventSpec : MemberSpec, IInterfaceMemberSpec
1477 MethodSpec add, remove;
1478 FieldSpec backing_field;
1480 public EventSpec (TypeSpec declaringType, IMemberDefinition definition, TypeSpec eventType, Modifiers modifiers, MethodSpec add, MethodSpec remove)
1481 : base (MemberKind.Event, declaringType, definition, modifiers)
1483 this.AccessorAdd = add;
1484 this.AccessorRemove = remove;
1485 this.MemberType = eventType;
1488 #region Properties
1490 public MethodSpec AccessorAdd {
1491 get {
1492 return add;
1494 set {
1495 add = value;
1499 public MethodSpec AccessorRemove {
1500 get {
1501 return remove;
1503 set {
1504 remove = value;
1508 public FieldSpec BackingField {
1509 get {
1510 return backing_field;
1512 set {
1513 backing_field = value;
1517 public TypeSpec MemberType { get; private set; }
1519 #endregion
1521 public override MemberSpec InflateMember (TypeParameterInflator inflator)
1523 var es = (EventSpec) base.InflateMember (inflator);
1524 es.MemberType = inflator.Inflate (MemberType);
1526 if (backing_field != null)
1527 es.backing_field = (FieldSpec) backing_field.InflateMember (inflator);
1529 return es;
1532 public override List<MissingTypeSpecReference> ResolveMissingDependencies (MemberSpec caller)
1534 return MemberType.ResolveMissingDependencies (this);
1538 public class Indexer : PropertyBase, IParametersMember
1540 public class GetIndexerMethod : GetMethod, IParametersMember
1542 ParametersCompiled parameters;
1544 public GetIndexerMethod (PropertyBase property, Modifiers modifiers, ParametersCompiled parameters, Attributes attrs, Location loc)
1545 : base (property, modifiers, attrs, loc)
1547 this.parameters = parameters;
1550 public override void Define (TypeContainer parent)
1552 // Disable reporting, parameters are resolved twice
1553 Report.DisableReporting ();
1554 try {
1555 parameters.Resolve (this);
1556 } finally {
1557 Report.EnableReporting ();
1560 base.Define (parent);
1563 public override ParametersCompiled ParameterInfo {
1564 get {
1565 return parameters;
1569 #region IParametersMember Members
1571 AParametersCollection IParametersMember.Parameters {
1572 get {
1573 return parameters;
1577 TypeSpec IInterfaceMemberSpec.MemberType {
1578 get {
1579 return ReturnType;
1583 #endregion
1586 public class SetIndexerMethod : SetMethod, IParametersMember
1588 public SetIndexerMethod (PropertyBase property, Modifiers modifiers, ParametersCompiled parameters, Attributes attrs, Location loc)
1589 : base (property, modifiers, parameters, attrs, loc)
1593 #region IParametersMember Members
1595 AParametersCollection IParametersMember.Parameters {
1596 get {
1597 return parameters;
1601 TypeSpec IInterfaceMemberSpec.MemberType {
1602 get {
1603 return ReturnType;
1607 #endregion
1610 const Modifiers AllowedModifiers =
1611 Modifiers.NEW |
1612 Modifiers.PUBLIC |
1613 Modifiers.PROTECTED |
1614 Modifiers.INTERNAL |
1615 Modifiers.PRIVATE |
1616 Modifiers.VIRTUAL |
1617 Modifiers.SEALED |
1618 Modifiers.OVERRIDE |
1619 Modifiers.UNSAFE |
1620 Modifiers.EXTERN |
1621 Modifiers.ABSTRACT;
1623 const Modifiers AllowedInterfaceModifiers =
1624 Modifiers.NEW;
1626 readonly ParametersCompiled parameters;
1628 public Indexer (TypeDefinition parent, FullNamedExpression type, MemberName name, Modifiers mod, ParametersCompiled parameters, Attributes attrs)
1629 : base (parent, type, mod,
1630 parent.PartialContainer.Kind == MemberKind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
1631 name, attrs)
1633 this.parameters = parameters;
1636 #region Properties
1638 AParametersCollection IParametersMember.Parameters {
1639 get {
1640 return parameters;
1644 public ParametersCompiled ParameterInfo {
1645 get {
1646 return parameters;
1650 #endregion
1653 public override void Accept (StructuralVisitor visitor)
1655 visitor.Visit (this);
1658 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1660 if (a.Type == pa.IndexerName) {
1661 // Attribute was copied to container
1662 return;
1665 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1668 protected override bool CheckForDuplications ()
1670 return Parent.MemberCache.CheckExistingMembersOverloads (this, parameters);
1673 public override bool Define ()
1675 if (!base.Define ())
1676 return false;
1678 if (!DefineParameters (parameters))
1679 return false;
1681 if (OptAttributes != null) {
1682 Attribute indexer_attr = OptAttributes.Search (Module.PredefinedAttributes.IndexerName);
1683 if (indexer_attr != null) {
1684 var compiling = indexer_attr.Type.MemberDefinition as TypeContainer;
1685 if (compiling != null)
1686 compiling.Define ();
1688 if (IsExplicitImpl) {
1689 Report.Error (415, indexer_attr.Location,
1690 "The `{0}' attribute is valid only on an indexer that is not an explicit interface member declaration",
1691 indexer_attr.Type.GetSignatureForError ());
1692 } else if ((ModFlags & Modifiers.OVERRIDE) != 0) {
1693 Report.Error (609, indexer_attr.Location,
1694 "Cannot set the `IndexerName' attribute on an indexer marked override");
1695 } else {
1696 string name = indexer_attr.GetIndexerAttributeValue ();
1698 if (!string.IsNullOrEmpty (name)) {
1699 SetMemberName (new MemberName (MemberName.Left, name, Location));
1705 if (InterfaceType != null) {
1706 string base_IndexerName = InterfaceType.MemberDefinition.GetAttributeDefaultMember ();
1707 if (base_IndexerName != ShortName) {
1708 SetMemberName (new MemberName (MemberName.Left, base_IndexerName, new TypeExpression (InterfaceType, Location), Location));
1712 Parent.AddNameToContainer (this, MemberName.Basename);
1714 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
1716 if (!DefineAccessors ())
1717 return false;
1719 if (!CheckBase ())
1720 return false;
1722 DefineBuilders (MemberKind.Indexer, parameters);
1723 return true;
1726 public override bool EnableOverloadChecks (MemberCore overload)
1728 if (overload is Indexer) {
1729 caching_flags |= Flags.MethodOverloadsExist;
1730 return true;
1733 return base.EnableOverloadChecks (overload);
1736 public override void Emit ()
1738 parameters.CheckConstraints (this);
1740 base.Emit ();
1743 public override string GetSignatureForError ()
1745 StringBuilder sb = new StringBuilder (Parent.GetSignatureForError ());
1746 if (MemberName.ExplicitInterface != null) {
1747 sb.Append (".");
1748 sb.Append (MemberName.ExplicitInterface.GetSignatureForError ());
1751 sb.Append (".this");
1752 sb.Append (parameters.GetSignatureForError ("[", "]", parameters.Count));
1753 return sb.ToString ();
1756 public override string GetSignatureForDocumentation ()
1758 return base.GetSignatureForDocumentation () + parameters.GetSignatureForDocumentation ();
1761 public override void PrepareEmit ()
1763 base.PrepareEmit ();
1764 parameters.ResolveDefaultValues (this);
1767 protected override bool VerifyClsCompliance ()
1769 if (!base.VerifyClsCompliance ())
1770 return false;
1772 parameters.VerifyClsCompliance (this);
1773 return true;
1777 public class IndexerSpec : PropertySpec, IParametersMember
1779 AParametersCollection parameters;
1781 public IndexerSpec (TypeSpec declaringType, IMemberDefinition definition, TypeSpec memberType, AParametersCollection parameters, PropertyInfo info, Modifiers modifiers)
1782 : base (MemberKind.Indexer, declaringType, definition, memberType, info, modifiers)
1784 this.parameters = parameters;
1787 #region Properties
1788 public AParametersCollection Parameters {
1789 get {
1790 return parameters;
1793 #endregion
1795 public override string GetSignatureForDocumentation ()
1797 return base.GetSignatureForDocumentation () + parameters.GetSignatureForDocumentation ();
1800 public override string GetSignatureForError ()
1802 return DeclaringType.GetSignatureForError () + ".this" + parameters.GetSignatureForError ("[", "]", parameters.Count);
1805 public override MemberSpec InflateMember (TypeParameterInflator inflator)
1807 var spec = (IndexerSpec) base.InflateMember (inflator);
1808 spec.parameters = parameters.Inflate (inflator);
1809 return spec;
1812 public override List<MissingTypeSpecReference> ResolveMissingDependencies (MemberSpec caller)
1814 var missing = base.ResolveMissingDependencies (caller);
1816 foreach (var pt in parameters.Types) {
1817 var m = pt.GetMissingDependencies (caller);
1818 if (m == null)
1819 continue;
1821 if (missing == null)
1822 missing = new List<MissingTypeSpecReference> ();
1824 missing.AddRange (m);
1827 return missing;