Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.CSharp-5.5.0/Parser/mcs/property.cs @ 15682

Last change on this file since 15682 was 11700, checked in by jkarder, 10 years ago

#2077: created branch and added first version

File size: 48.5 KB
Line 
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
13//
14
15using System;
16using System.Collections.Generic;
17using System.Text;
18using Mono.CompilerServices.SymbolWriter;
19
20#if NET_2_1
21using XmlElement = System.Object;
22#endif
23
24#if STATIC
25using IKVM.Reflection;
26using IKVM.Reflection.Emit;
27#else
28using System.Reflection;
29using System.Reflection.Emit;
30#endif
31
32namespace Mono.CSharp
33{
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
37  {
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)
40    {
41    }
42
43    protected void CheckReservedNameConflict (string prefix, MethodSpec accessor)
44    {
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;
54
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;
64
65            parameters = new ParametersImported (data, types, false);
66          }
67        } else {
68          if (prefix[0] == 's')
69            parameters = ParametersCompiled.CreateFullyResolved (new[] { member_type });
70          else
71            parameters = ParametersCompiled.EmptyReadOnlyParameters;
72        }
73      }
74
75      var conflict = MemberCache.FindMember (Parent.Definition,
76        new MemberFilter (name, 0, MemberKind.Method, parameters, null),
77        BindingRestriction.DeclaredOnly | BindingRestriction.NoAccessors);
78
79      if (conflict != null) {
80        Report.SymbolRelatedToPreviousError (conflict);
81        Report.Error (82, Location, "A member `{0}' is already reserved", conflict.GetSignatureForError ());
82      }
83    }
84
85    public abstract void PrepareEmit ();
86
87    protected override bool VerifyClsCompliance ()
88    {
89      if (!base.VerifyClsCompliance ())
90        return false;
91
92      if (!MemberType.IsCLSCompliant ()) {
93        Report.Warning (3003, 1, Location, "Type of `{0}' is not CLS-compliant",
94          GetSignatureForError ());
95      }
96      return true;
97    }
98
99  }
100
101  public class PropertySpec : MemberSpec, IInterfaceMemberSpec
102  {
103    PropertyInfo info;
104    TypeSpec memberType;
105    MethodSpec set, get;
106
107    public PropertySpec (MemberKind kind, TypeSpec declaringType, IMemberDefinition definition, TypeSpec memberType, PropertyInfo info, Modifiers modifiers)
108      : base (kind, declaringType, definition, modifiers)
109    {
110      this.info = info;
111      this.memberType = memberType;
112    }
113
114    #region Properties
115
116    public MethodSpec Get {
117      get {
118        return get;
119      }
120      set {
121        get = value;
122        get.IsAccessor = true;
123      }
124    }
125
126    public MethodSpec Set {
127      get {
128        return set;
129      }
130      set {
131        set = value;
132        set.IsAccessor = true;
133      }
134    }
135
136    public bool HasDifferentAccessibility {
137      get {
138        return HasGet && HasSet &&
139          (Get.Modifiers & Modifiers.AccessibilityMask) != (Set.Modifiers & Modifiers.AccessibilityMask);
140      }
141    }
142
143    public bool HasGet {
144      get {
145        return Get != null;
146      }
147    }
148
149    public bool HasSet {
150      get {
151        return Set != null;
152      }
153    }
154
155    public PropertyInfo MetaInfo {
156      get {
157        if ((state & StateFlags.PendingMetaInflate) != 0)
158          throw new NotSupportedException ();
159
160        return info;
161      }
162    }
163
164    public TypeSpec MemberType {
165      get {
166        return memberType;
167      }
168    }
169
170    #endregion
171
172    public override MemberSpec InflateMember (TypeParameterInflator inflator)
173    {
174      var ps = (PropertySpec) base.InflateMember (inflator);
175      ps.memberType = inflator.Inflate (memberType);
176      return ps;
177    }
178
179    public override List<MissingTypeSpecReference> ResolveMissingDependencies (MemberSpec caller)
180    {
181      return memberType.ResolveMissingDependencies (this);
182    }
183  }
184
185  //
186  // Properties and Indexers both generate PropertyBuilders, we use this to share
187  // their common bits.
188  //
189  abstract public class PropertyBase : PropertyBasedMember {
190
191    public class GetMethod : PropertyMethod
192    {
193      static readonly string[] attribute_targets = new string [] { "method", "return" };
194
195      internal const string Prefix = "get_";
196
197      public GetMethod (PropertyBase method, Modifiers modifiers, Attributes attrs, Location loc)
198        : base (method, Prefix, modifiers, attrs, loc)
199      {
200      }
201
202      public override void Define (TypeContainer parent)
203      {
204        base.Define (parent);
205
206        Spec = new MethodSpec (MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, ParameterInfo, ModFlags);
207
208        method_data = new MethodData (method, ModFlags, flags, this);
209
210        method_data.Define (parent.PartialContainer, method.GetFullName (MemberName));
211      }
212
213      public override TypeSpec ReturnType {
214        get {
215          return method.MemberType;
216        }
217      }
218
219      public override ParametersCompiled ParameterInfo {
220        get {
221          return ParametersCompiled.EmptyReadOnlyParameters;
222        }
223      }
224
225      public override string[] ValidAttributeTargets {
226        get {
227          return attribute_targets;
228        }
229      }
230    }
231
232    public class SetMethod : PropertyMethod {
233
234      static readonly string[] attribute_targets = new string[] { "method", "param", "return" };
235
236      internal const string Prefix = "set_";
237
238      protected ParametersCompiled parameters;
239
240      public SetMethod (PropertyBase method, Modifiers modifiers, ParametersCompiled parameters, Attributes attrs, Location loc)
241        : base (method, Prefix, modifiers, attrs, loc)
242      {
243        this.parameters = parameters;
244      }
245
246      protected override void ApplyToExtraTarget (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
247      {
248        if (a.Target == AttributeTargets.Parameter) {
249          parameters[0].ApplyAttributeBuilder (a, ctor, cdata, pa);
250          return;
251        }
252
253        base.ApplyToExtraTarget (a, ctor, cdata, pa);
254      }
255
256      public override ParametersCompiled ParameterInfo {
257          get {
258              return parameters;
259          }
260      }
261
262      public override void Define (TypeContainer parent)
263      {
264        parameters.Resolve (this);
265       
266        base.Define (parent);
267
268        Spec = new MethodSpec (MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, ParameterInfo, ModFlags);
269
270        method_data = new MethodData (method, ModFlags, flags, this);
271
272        method_data.Define (parent.PartialContainer, method.GetFullName (MemberName));
273      }
274
275      public override TypeSpec ReturnType {
276        get {
277          return Parent.Compiler.BuiltinTypes.Void;
278        }
279      }
280
281      public override string[] ValidAttributeTargets {
282        get {
283          return attribute_targets;
284        }
285      }
286    }
287
288    static readonly string[] attribute_targets = new string[] { "property" };
289
290    public abstract class PropertyMethod : AbstractPropertyEventMethod
291    {
292      const Modifiers AllowedModifiers =
293        Modifiers.PUBLIC |
294        Modifiers.PROTECTED |
295        Modifiers.INTERNAL |
296        Modifiers.PRIVATE;
297   
298      protected readonly PropertyBase method;
299      protected MethodAttributes flags;
300
301      public PropertyMethod (PropertyBase method, string prefix, Modifiers modifiers, Attributes attrs, Location loc)
302        : base (method, prefix, attrs, loc)
303      {
304        this.method = method;
305        this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, modifiers, 0, loc, Report);
306        this.ModFlags |= (method.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE));
307      }
308
309      public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
310      {
311        if (a.Type == pa.MethodImpl) {
312          method.is_external_implementation = a.IsInternalCall ();
313        }
314
315        base.ApplyAttributeBuilder (a, ctor, cdata, pa);
316      }
317
318      public override AttributeTargets AttributeTargets {
319        get {
320          return AttributeTargets.Method;
321        }
322      }
323
324      public override bool IsClsComplianceRequired ()
325      {
326        return method.IsClsComplianceRequired ();
327      }
328
329      public virtual void Define (TypeContainer parent)
330      {
331        var container = parent.PartialContainer;
332
333        //
334        // Check for custom access modifier
335        //
336        if ((ModFlags & Modifiers.AccessibilityMask) == 0) {
337          ModFlags |= method.ModFlags;
338          flags = method.flags;
339        } else {
340          if (container.Kind == MemberKind.Interface)
341            Report.Error (275, Location, "`{0}': accessibility modifiers may not be used on accessors in an interface",
342              GetSignatureForError ());
343          else if ((method.ModFlags & Modifiers.ABSTRACT) != 0 && (ModFlags & Modifiers.PRIVATE) != 0) {
344            Report.Error (442, Location, "`{0}': abstract properties cannot have private accessors", GetSignatureForError ());
345          }
346
347          CheckModifiers (ModFlags);
348          ModFlags |= (method.ModFlags & (~Modifiers.AccessibilityMask));
349          ModFlags |= Modifiers.PROPERTY_CUSTOM;
350          flags = ModifiersExtensions.MethodAttr (ModFlags);
351          flags |= (method.flags & (~MethodAttributes.MemberAccessMask));
352        }
353
354        CheckAbstractAndExtern (block != null);
355        CheckProtectedModifier ();
356
357        if (block != null) {
358          if (block.IsIterator)
359            Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags);
360
361          if (Compiler.Settings.WriteMetadataOnly)
362            block = null;
363        }
364      }
365
366      public bool HasCustomAccessModifier {
367        get {
368          return (ModFlags & Modifiers.PROPERTY_CUSTOM) != 0;
369        }
370      }
371
372      public PropertyBase Property {
373        get {
374          return method;
375        }
376      }
377
378      public override ObsoleteAttribute GetAttributeObsolete ()
379      {
380        return method.GetAttributeObsolete ();
381      }
382
383      public override string GetSignatureForError()
384      {
385        return method.GetSignatureForError () + "." + prefix.Substring (0, 3);
386      }
387
388      void CheckModifiers (Modifiers modflags)
389      {
390        if (!ModifiersExtensions.IsRestrictedModifier (modflags & Modifiers.AccessibilityMask, method.ModFlags & Modifiers.AccessibilityMask)) {
391          Report.Error (273, Location,
392            "The accessibility modifier of the `{0}' accessor must be more restrictive than the modifier of the property or indexer `{1}'",
393            GetSignatureForError (), method.GetSignatureForError ());
394        }
395      }
396    }
397
398    PropertyMethod get, set, first;
399    PropertyBuilder PropertyBuilder;
400
401    protected PropertyBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod_flags, Modifiers allowed_mod, MemberName name, Attributes attrs)
402      : base (parent, type, mod_flags, allowed_mod, name, attrs)
403    {
404    }
405
406    #region Properties
407
408    public override AttributeTargets AttributeTargets {
409      get {
410        return AttributeTargets.Property;
411      }
412    }
413
414    public PropertyMethod AccessorFirst {
415      get {
416        return first;
417      }
418    }
419
420    public PropertyMethod AccessorSecond {
421      get {
422        return first == get ? set : get;
423      }
424    }
425
426    public override Variance ExpectedMemberTypeVariance {
427      get {
428        return (get != null && set != null) ?
429          Variance.None : set == null ?
430          Variance.Covariant :
431          Variance.Contravariant;
432      }
433    }
434
435    public PropertyMethod Get {
436      get {
437        return get;
438      }
439      set {
440        get = value;
441        if (first == null)
442          first = value;
443
444        Parent.AddNameToContainer (get, get.MemberName.Basename);
445      }
446    }
447
448    public PropertyMethod Set {
449      get {
450        return set;
451      }
452      set {
453        set = value;
454        if (first == null)
455          first = value;
456
457        Parent.AddNameToContainer (set, set.MemberName.Basename);
458      }
459    }
460
461    public override string[] ValidAttributeTargets {
462      get {
463        return attribute_targets;
464      }
465    }
466
467    #endregion
468
469    public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
470    {
471      if (a.HasSecurityAttribute) {
472        a.Error_InvalidSecurityParent ();
473        return;
474      }
475
476      if (a.Type == pa.Dynamic) {
477        a.Error_MisusedDynamicAttribute ();
478        return;
479      }
480
481      PropertyBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
482    }
483
484    void CheckMissingAccessor (MemberKind kind, ParametersCompiled parameters, bool get)
485    {
486      if (IsExplicitImpl) {
487        MemberFilter filter;
488        if (kind == MemberKind.Indexer)
489          filter = new MemberFilter (MemberCache.IndexerNameAlias, 0, kind, parameters, null);
490        else
491          filter = new MemberFilter (MemberName.Name, 0, kind, null, null);
492
493        var implementing = MemberCache.FindMember (InterfaceType, filter, BindingRestriction.DeclaredOnly) as PropertySpec;
494
495        if (implementing == null)
496          return;
497
498        var accessor = get ? implementing.Get : implementing.Set;
499        if (accessor != null) {
500          Report.SymbolRelatedToPreviousError (accessor);
501          Report.Error (551, Location, "Explicit interface implementation `{0}' is missing accessor `{1}'",
502            GetSignatureForError (), accessor.GetSignatureForError ());
503        }
504      }
505    }
506
507    protected override bool CheckOverrideAgainstBase (MemberSpec base_member)
508    {
509      var ok = base.CheckOverrideAgainstBase (base_member);
510
511      //
512      // Check base property accessors conflict
513      //
514      var base_prop = (PropertySpec) base_member;
515      if (Get == null) {
516        if ((ModFlags & Modifiers.SEALED) != 0 && base_prop.HasGet && !base_prop.Get.IsAccessible (this)) {
517          // TODO: Should be different error code but csc uses for some reason same
518          Report.SymbolRelatedToPreviousError (base_prop);
519          Report.Error (545, Location,
520            "`{0}': cannot override because `{1}' does not have accessible get accessor",
521            GetSignatureForError (), base_prop.GetSignatureForError ());
522          ok = false;
523        }
524      } else {
525        if (!base_prop.HasGet) {
526          if (ok) {
527            Report.SymbolRelatedToPreviousError (base_prop);
528            Report.Error (545, Get.Location,
529              "`{0}': cannot override because `{1}' does not have an overridable get accessor",
530              Get.GetSignatureForError (), base_prop.GetSignatureForError ());
531            ok = false;
532          }
533        } else if (Get.HasCustomAccessModifier || base_prop.HasDifferentAccessibility) {
534          if (!CheckAccessModifiers (Get, base_prop.Get)) {
535            Error_CannotChangeAccessModifiers (Get, base_prop.Get);
536            ok = false;
537          }
538        }
539      }
540
541      if (Set == null) {
542        if ((ModFlags & Modifiers.SEALED) != 0 && base_prop.HasSet && !base_prop.Set.IsAccessible (this)) {
543          // TODO: Should be different error code but csc uses for some reason same
544          Report.SymbolRelatedToPreviousError (base_prop);
545          Report.Error (546, Location,
546            "`{0}': cannot override because `{1}' does not have accessible set accessor",
547            GetSignatureForError (), base_prop.GetSignatureForError ());
548          ok = false;
549        }
550      } else {
551        if (!base_prop.HasSet) {
552          if (ok) {
553            Report.SymbolRelatedToPreviousError (base_prop);
554            Report.Error (546, Set.Location,
555              "`{0}': cannot override because `{1}' does not have an overridable set accessor",
556              Set.GetSignatureForError (), base_prop.GetSignatureForError ());
557            ok = false;
558          }
559        } else if (Set.HasCustomAccessModifier || base_prop.HasDifferentAccessibility) {
560          if (!CheckAccessModifiers (Set, base_prop.Set)) {
561            Error_CannotChangeAccessModifiers (Set, base_prop.Set);
562            ok = false;
563          }
564        }
565      }
566
567      if ((Set == null || !Set.HasCustomAccessModifier) && (Get == null || !Get.HasCustomAccessModifier)) {
568        if (!CheckAccessModifiers (this, base_prop)) {
569          Error_CannotChangeAccessModifiers (this, base_prop);
570          ok = false;
571        }
572      }
573
574      return ok;
575    }
576
577    protected override void DoMemberTypeDependentChecks ()
578    {
579      base.DoMemberTypeDependentChecks ();
580
581      IsTypePermitted ();
582
583      if (MemberType.IsStatic)
584        Error_StaticReturnType ();
585    }
586
587    protected override void DoMemberTypeIndependentChecks ()
588    {
589      base.DoMemberTypeIndependentChecks ();
590
591      //
592      // Accessors modifiers check
593      //
594      if (AccessorSecond != null) {
595        if ((Get.ModFlags & Modifiers.AccessibilityMask) != 0 && (Set.ModFlags & Modifiers.AccessibilityMask) != 0) {
596          Report.Error (274, Location, "`{0}': Cannot specify accessibility modifiers for both accessors of the property or indexer",
597            GetSignatureForError ());
598        }
599      } else if ((ModFlags & Modifiers.OVERRIDE) == 0 &&
600        (Get == null && (Set.ModFlags & Modifiers.AccessibilityMask) != 0) ||
601        (Set == null && (Get.ModFlags & Modifiers.AccessibilityMask) != 0)) {
602        Report.Error (276, Location,
603                "`{0}': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor",
604                GetSignatureForError ());
605      }
606    }
607
608    protected bool DefineAccessors ()
609    {
610      first.Define (Parent);
611      if (AccessorSecond != null)
612        AccessorSecond.Define (Parent);
613
614      return true;
615    }
616
617    protected void DefineBuilders (MemberKind kind, ParametersCompiled parameters)
618    {
619      PropertyBuilder = Parent.TypeBuilder.DefineProperty (
620        GetFullName (MemberName), PropertyAttributes.None,
621#if !BOOTSTRAP_BASIC  // Requires trunk version mscorlib
622        IsStatic ? 0 : CallingConventions.HasThis,
623#endif
624        MemberType.GetMetaInfo (), null, null,
625        parameters.GetMetaInfo (), null, null);
626
627      PropertySpec spec;
628      if (kind == MemberKind.Indexer)
629        spec = new IndexerSpec (Parent.Definition, this, MemberType, parameters, PropertyBuilder, ModFlags);
630      else
631        spec = new PropertySpec (kind, Parent.Definition, this, MemberType, PropertyBuilder, ModFlags);
632
633      if (Get != null) {
634        spec.Get = Get.Spec;
635        Parent.MemberCache.AddMember (this, Get.Spec.Name, Get.Spec);
636      } else {
637        CheckMissingAccessor (kind, parameters, true);
638      }
639
640      if (Set != null) {
641        spec.Set = Set.Spec;
642        Parent.MemberCache.AddMember (this, Set.Spec.Name, Set.Spec);
643      } else {
644        CheckMissingAccessor (kind, parameters, false);
645      }
646
647      Parent.MemberCache.AddMember (this, PropertyBuilder.Name, spec);
648    }
649
650    public override void Emit ()
651    {
652      CheckReservedNameConflict (GetMethod.Prefix, get == null ? null : get.Spec);
653      CheckReservedNameConflict (SetMethod.Prefix, set == null ? null : set.Spec);
654
655      if (OptAttributes != null)
656        OptAttributes.Emit ();
657
658      if (member_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
659        Module.PredefinedAttributes.Dynamic.EmitAttribute (PropertyBuilder);
660      } else if (member_type.HasDynamicElement) {
661        Module.PredefinedAttributes.Dynamic.EmitAttribute (PropertyBuilder, member_type, Location);
662      }
663
664      ConstraintChecker.Check (this, member_type, type_expr.Location);
665
666      first.Emit (Parent);
667      if (AccessorSecond != null)
668        AccessorSecond.Emit (Parent);
669
670      base.Emit ();
671    }
672
673    public override bool IsUsed {
674      get {
675        if (IsExplicitImpl)
676          return true;
677
678        return Get.IsUsed | Set.IsUsed;
679      }
680    }
681
682    public override void PrepareEmit ()
683    {
684      AccessorFirst.PrepareEmit ();
685      if (AccessorSecond != null)
686        AccessorSecond.PrepareEmit ();
687
688      if (get != null) {
689        var method = Get.Spec.GetMetaInfo () as MethodBuilder;
690        if (method != null)
691          PropertyBuilder.SetGetMethod (method);
692      }
693
694      if (set != null) {
695        var method = Set.Spec.GetMetaInfo () as MethodBuilder;
696        if (method != null)
697          PropertyBuilder.SetSetMethod (method);
698      }
699    }
700
701    protected override void SetMemberName (MemberName new_name)
702    {
703      base.SetMemberName (new_name);
704
705      if (Get != null)
706        Get.UpdateName (this);
707
708      if (Set != null)
709        Set.UpdateName (this);
710    }
711
712    public override void WriteDebugSymbol (MonoSymbolFile file)
713    {
714      if (get != null)
715        get.WriteDebugSymbol (file);
716
717      if (set != null)
718        set.WriteDebugSymbol (file);
719    }
720
721    //
722    //   Represents header string for documentation comment.
723    //
724    public override string DocCommentHeader {
725      get { return "P:"; }
726    }
727  }
728     
729  public class Property : PropertyBase
730  {
731    public sealed class BackingField : Field
732    {
733      readonly Property property;
734      const Modifiers DefaultModifiers = Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | Modifiers.DEBUGGER_HIDDEN;
735
736      public BackingField (Property p, bool readOnly)
737        : base (p.Parent, p.type_expr, DefaultModifiers | (p.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
738        new MemberName ("<" + p.GetFullName (p.MemberName) + ">k__BackingField", p.Location), null)
739      {
740        this.property = p;
741        if (readOnly)
742          ModFlags |= Modifiers.READONLY;
743      }
744
745      public Property OriginalProperty {
746        get {
747          return property;
748        }
749      }
750
751      public override string GetSignatureForError ()
752      {
753        return property.GetSignatureForError ();
754      }
755    }
756
757    static readonly string[] attribute_target_auto = new string[] { "property", "field" };
758
759    Field backing_field;
760
761    public Property (TypeDefinition parent, FullNamedExpression type, Modifiers mod,
762         MemberName name, Attributes attrs)
763      : base (parent, type, mod,
764        parent.PartialContainer.Kind == MemberKind.Interface ? AllowedModifiersInterface :
765        parent.PartialContainer.Kind == MemberKind.Struct ? AllowedModifiersStruct :
766        AllowedModifiersClass,
767        name, attrs)
768    {
769    }
770
771    public Expression Initializer { get; set; }
772
773    public override void Accept (StructuralVisitor visitor)
774    {
775      visitor.Visit (this);
776    }
777
778    public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
779    {
780      if (a.Target == AttributeTargets.Field) {
781        backing_field.ApplyAttributeBuilder (a, ctor, cdata, pa);
782        return;
783      }
784
785      base.ApplyAttributeBuilder (a, ctor, cdata, pa);
786    }
787
788    void CreateAutomaticProperty ()
789    {
790      // Create backing field
791      backing_field = new BackingField (this, Initializer != null && Set == null);
792      if (!backing_field.Define ())
793        return;
794
795      if (Initializer != null) {
796        backing_field.Initializer = Initializer;
797        Parent.RegisterFieldForInitialization (backing_field, new FieldInitializer (backing_field, Initializer, Location));
798        backing_field.ModFlags |= Modifiers.READONLY;
799      }
800
801      Parent.PartialContainer.Members.Add (backing_field);
802
803      FieldExpr fe = new FieldExpr (backing_field, Location);
804      if ((backing_field.ModFlags & Modifiers.STATIC) == 0)
805        fe.InstanceExpression = new CompilerGeneratedThis (Parent.CurrentType, Location);
806
807      //
808      // Create get block but we careful with location to
809      // emit only single sequence point per accessor. This allow
810      // to set a breakpoint on it even with no user code
811      //
812      Get.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location.Null);
813      Return r = new Return (fe, Get.Location);
814      Get.Block.AddStatement (r);
815      Get.ModFlags |= Modifiers.COMPILER_GENERATED;
816
817      // Create set block
818      if (Set != null) {
819        Set.Block = new ToplevelBlock (Compiler, Set.ParameterInfo, Location.Null);
820        Assign a = new SimpleAssign (fe, new SimpleName ("value", Location.Null), Location.Null);
821        Set.Block.AddStatement (new StatementExpression (a, Set.Location));
822        Set.ModFlags |= Modifiers.COMPILER_GENERATED;
823      }
824    }
825   
826    public override bool Define ()
827    {
828      if (!base.Define ())
829        return false;
830
831      flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
832
833      bool auto = AccessorFirst.Block == null && (AccessorSecond == null || AccessorSecond.Block == null) &&
834        (ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0;
835
836      if (Initializer != null) {
837        if (!auto)
838          Report.Error (8050, Location, "`{0}': Only auto-implemented properties can have initializers",
839            GetSignatureForError ());
840
841        if (IsInterface)
842          Report.Error (8053, Location, "`{0}': Properties inside interfaces cannot have initializers",
843            GetSignatureForError ());
844
845        if (Compiler.Settings.Version < LanguageVersion.V_6)
846          Report.FeatureIsNotAvailable (Compiler, Location, "auto-implemented property initializer");
847      }
848
849      if (auto) {
850        if (Get == null) {
851          Report.Error (8052, Location, "Auto-implemented property `{0}' must have get accessor",
852            GetSignatureForError ());
853          return false;
854        }
855
856        if (Initializer == null && AccessorSecond == null) {
857          Report.Error (8051, Location, "Auto-implemented property `{0}' must have set accessor or initializer",
858            GetSignatureForError ());
859        }
860
861        if (Compiler.Settings.Version < LanguageVersion.V_3 && Initializer == null)
862          Report.FeatureIsNotAvailable (Compiler, Location, "auto-implemented properties");
863
864        CreateAutomaticProperty ();
865      }
866
867      if (!DefineAccessors ())
868        return false;
869
870      if (AccessorSecond == null) {
871        PropertyMethod pm;
872        if (AccessorFirst is GetMethod)
873          pm = new SetMethod (this, 0, ParametersCompiled.EmptyReadOnlyParameters, null, Location);
874        else
875          pm = new GetMethod (this, 0, null, Location);
876
877        Parent.AddNameToContainer (pm, pm.MemberName.Basename);
878      }
879
880      if (!CheckBase ())
881        return false;
882
883      DefineBuilders (MemberKind.Property, ParametersCompiled.EmptyReadOnlyParameters);
884      return true;
885    }
886
887    public override void Emit ()
888    {
889      if ((AccessorFirst.ModFlags & (Modifiers.STATIC | Modifiers.COMPILER_GENERATED)) == Modifiers.COMPILER_GENERATED && Parent.PartialContainer.HasExplicitLayout) {
890        Report.Error (842, Location,
891          "Automatically implemented property `{0}' cannot be used inside a type with an explicit StructLayout attribute",
892          GetSignatureForError ());
893      }
894
895      base.Emit ();
896    }
897
898    public override string[] ValidAttributeTargets {
899      get {
900        return Get != null && ((Get.ModFlags & Modifiers.COMPILER_GENERATED) != 0) ?
901          attribute_target_auto : base.ValidAttributeTargets;
902      }
903    }
904  }
905
906  /// <summary>
907  /// For case when event is declared like property (with add and remove accessors).
908  /// </summary>
909  public class EventProperty: Event {
910    public abstract class AEventPropertyAccessor : AEventAccessor
911    {
912      protected AEventPropertyAccessor (EventProperty method, string prefix, Attributes attrs, Location loc)
913        : base (method, prefix, attrs, loc)
914      {
915      }
916
917      public override void Define (TypeContainer ds)
918      {
919        CheckAbstractAndExtern (block != null);
920        base.Define (ds);
921      }
922     
923      public override string GetSignatureForError ()
924      {
925        return method.GetSignatureForError () + "." + prefix.Substring (0, prefix.Length - 1);
926      }
927    }
928
929    public sealed class AddDelegateMethod: AEventPropertyAccessor
930    {
931      public AddDelegateMethod (EventProperty method, Attributes attrs, Location loc)
932        : base (method, AddPrefix, attrs, loc)
933      {
934      }
935    }
936
937    public sealed class RemoveDelegateMethod: AEventPropertyAccessor
938    {
939      public RemoveDelegateMethod (EventProperty method, Attributes attrs, Location loc)
940        : base (method, RemovePrefix, attrs, loc)
941      {
942      }
943    }
944
945    static readonly string[] attribute_targets = new string [] { "event" };
946
947    public EventProperty (TypeDefinition parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
948      : base (parent, type, mod_flags, name, attrs)
949    {
950    }
951
952    public override void Accept (StructuralVisitor visitor)
953    {
954      visitor.Visit (this);
955    }
956   
957    public override bool Define()
958    {
959      if (!base.Define ())
960        return false;
961
962      SetIsUsed ();
963      return true;
964    }
965
966    public override string[] ValidAttributeTargets {
967      get {
968        return attribute_targets;
969      }
970    }
971  }
972
973  /// <summary>
974  /// Event is declared like field.
975  /// </summary>
976  public class EventField : Event
977  {
978    abstract class EventFieldAccessor : AEventAccessor
979    {
980      protected EventFieldAccessor (EventField method, string prefix)
981        : base (method, prefix, null, method.Location)
982      {
983      }
984
985      protected abstract MethodSpec GetOperation (Location loc);
986
987      public override void Emit (TypeDefinition parent)
988      {
989        if ((method.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0 && !Compiler.Settings.WriteMetadataOnly) {
990          block = new ToplevelBlock (Compiler, ParameterInfo, Location) {
991            IsCompilerGenerated = true
992          };
993          FabricateBodyStatement ();
994        }
995
996        base.Emit (parent);
997      }
998
999      void FabricateBodyStatement ()
1000      {
1001        //
1002        // Delegate obj1 = backing_field
1003        // do {
1004        //   Delegate obj2 = obj1;
1005        //   obj1 = Interlocked.CompareExchange (ref backing_field, Delegate.Combine|Remove(obj2, value), obj1);
1006        // } while ((object)obj1 != (object)obj2)
1007        //
1008
1009        var field_info = ((EventField) method).backing_field;
1010        FieldExpr f_expr = new FieldExpr (field_info, Location);
1011        if (!IsStatic)
1012          f_expr.InstanceExpression = new CompilerGeneratedThis (Parent.CurrentType, Location);
1013
1014        var obj1 = LocalVariable.CreateCompilerGenerated (field_info.MemberType, block, Location);
1015        var obj2 = LocalVariable.CreateCompilerGenerated (field_info.MemberType, block, Location);
1016
1017        block.AddStatement (new StatementExpression (new SimpleAssign (new LocalVariableReference (obj1, Location), f_expr)));
1018
1019        var cond = new BooleanExpression (new Binary (Binary.Operator.Inequality,
1020          new Cast (new TypeExpression (Module.Compiler.BuiltinTypes.Object, Location), new LocalVariableReference (obj1, Location), Location),
1021          new Cast (new TypeExpression (Module.Compiler.BuiltinTypes.Object, Location), new LocalVariableReference (obj2, Location), Location)));
1022
1023        var body = new ExplicitBlock (block, Location, Location);
1024        block.AddStatement (new Do (body, cond, Location, Location));
1025
1026        body.AddStatement (new StatementExpression (
1027          new SimpleAssign (new LocalVariableReference (obj2, Location), new LocalVariableReference (obj1, Location))));
1028
1029        var args_oper = new Arguments (2);
1030        args_oper.Add (new Argument (new LocalVariableReference (obj2, Location)));
1031        args_oper.Add (new Argument (block.GetParameterReference (0, Location)));
1032
1033        var op_method = GetOperation (Location);
1034
1035        var args = new Arguments (3);
1036        args.Add (new Argument (f_expr, Argument.AType.Ref));
1037        args.Add (new Argument (new Cast (
1038          new TypeExpression (field_info.MemberType, Location),
1039          new Invocation (MethodGroupExpr.CreatePredefined (op_method, op_method.DeclaringType, Location), args_oper),
1040          Location)));
1041        args.Add (new Argument (new LocalVariableReference (obj1, Location)));
1042
1043        var cas = Module.PredefinedMembers.InterlockedCompareExchange_T.Get ();
1044        if (cas == null) {
1045          if (Module.PredefinedMembers.MonitorEnter_v4.Get () != null || Module.PredefinedMembers.MonitorEnter.Get () != null) {
1046            // Workaround for cripled (e.g. microframework) mscorlib without CompareExchange
1047            body.AddStatement (new Lock (
1048              block.GetParameterReference (0, Location),
1049              new StatementExpression (new SimpleAssign (
1050                f_expr, args [1].Expr, Location), Location), Location));
1051          } else {
1052            Module.PredefinedMembers.InterlockedCompareExchange_T.Resolve (Location);
1053          }
1054        } else {
1055          body.AddStatement (new StatementExpression (new SimpleAssign (
1056            new LocalVariableReference (obj1, Location),
1057            new Invocation (MethodGroupExpr.CreatePredefined (cas, cas.DeclaringType, Location), args))));
1058        }
1059      }
1060    }
1061
1062    sealed class AddDelegateMethod: EventFieldAccessor
1063    {
1064      public AddDelegateMethod (EventField method):
1065        base (method, AddPrefix)
1066      {
1067      }
1068
1069      protected override MethodSpec GetOperation (Location loc)
1070      {
1071        return Module.PredefinedMembers.DelegateCombine.Resolve (loc);
1072      }
1073    }
1074
1075    sealed class RemoveDelegateMethod: EventFieldAccessor
1076    {
1077      public RemoveDelegateMethod (EventField method):
1078        base (method, RemovePrefix)
1079      {
1080      }
1081
1082      protected override MethodSpec GetOperation (Location loc)
1083      {
1084        return Module.PredefinedMembers.DelegateRemove.Resolve (loc);
1085      }
1086    }
1087
1088
1089    static readonly string[] attribute_targets = new string [] { "event", "field", "method" };
1090    static readonly string[] attribute_targets_interface = new string[] { "event", "method" };
1091
1092    Expression initializer;
1093    Field backing_field;
1094    List<FieldDeclarator> declarators;
1095
1096    public EventField (TypeDefinition parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
1097      : base (parent, type, mod_flags, name, attrs)
1098    {
1099      Add = new AddDelegateMethod (this);
1100      Remove = new RemoveDelegateMethod (this);
1101    }
1102
1103    #region Properties
1104
1105    public List<FieldDeclarator> Declarators {
1106      get {
1107        return this.declarators;
1108      }
1109    }
1110
1111    bool HasBackingField {
1112      get {
1113        return !IsInterface && (ModFlags & Modifiers.ABSTRACT) == 0;
1114      }
1115    }
1116
1117    public Expression Initializer {
1118      get {
1119        return initializer;
1120      }
1121      set {
1122        initializer = value;
1123      }
1124    }
1125
1126    public override string[] ValidAttributeTargets {
1127      get {
1128        return HasBackingField ? attribute_targets : attribute_targets_interface;
1129      }
1130    }
1131
1132    #endregion
1133
1134   
1135    public override void Accept (StructuralVisitor visitor)
1136    {
1137      visitor.Visit (this);
1138    }
1139
1140    public void AddDeclarator (FieldDeclarator declarator)
1141    {
1142      if (declarators == null)
1143        declarators = new List<FieldDeclarator> (2);
1144
1145      declarators.Add (declarator);
1146
1147      Parent.AddNameToContainer (this, declarator.Name.Value);
1148    }
1149
1150    public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1151    {
1152      if (a.Target == AttributeTargets.Field) {
1153        backing_field.ApplyAttributeBuilder (a, ctor, cdata, pa);
1154        return;
1155      }
1156
1157      if (a.Target == AttributeTargets.Method) {
1158        int errors = Report.Errors;
1159        Add.ApplyAttributeBuilder (a, ctor, cdata, pa);
1160        if (errors == Report.Errors)
1161          Remove.ApplyAttributeBuilder (a, ctor, cdata, pa);
1162        return;
1163      }
1164
1165      base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1166    }
1167
1168    public override bool Define()
1169    {
1170      var mod_flags_src = ModFlags;
1171
1172      if (!base.Define ())
1173        return false;
1174
1175      if (declarators != null) {
1176        if ((mod_flags_src & Modifiers.DEFAULT_ACCESS_MODIFIER) != 0)
1177          mod_flags_src &= ~(Modifiers.AccessibilityMask | Modifiers.DEFAULT_ACCESS_MODIFIER);
1178
1179        var t = new TypeExpression (MemberType, TypeExpression.Location);
1180        foreach (var d in declarators) {
1181          var ef = new EventField (Parent, t, mod_flags_src, new MemberName (d.Name.Value, d.Name.Location), OptAttributes);
1182
1183          if (d.Initializer != null)
1184            ef.initializer = d.Initializer;
1185
1186          ef.Define ();
1187          Parent.PartialContainer.Members.Add (ef);
1188        }
1189      }
1190
1191      if (!HasBackingField) {
1192        SetIsUsed ();
1193        return true;
1194      }
1195
1196      backing_field = new Field (Parent,
1197        new TypeExpression (MemberType, Location),
1198        Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
1199        MemberName, null);
1200
1201      Parent.PartialContainer.Members.Add (backing_field);
1202      backing_field.Initializer = Initializer;
1203      backing_field.ModFlags &= ~Modifiers.COMPILER_GENERATED;
1204
1205      // Call define because we passed fields definition
1206      backing_field.Define ();
1207
1208      // Set backing field for event fields
1209      spec.BackingField = backing_field.Spec;
1210
1211      return true;
1212    }
1213  }
1214
1215  public abstract class Event : PropertyBasedMember
1216  {
1217    public abstract class AEventAccessor : AbstractPropertyEventMethod
1218    {
1219      protected readonly Event method;
1220      readonly ParametersCompiled parameters;
1221
1222      static readonly string[] attribute_targets = new string [] { "method", "param", "return" };
1223
1224      public const string AddPrefix = "add_";
1225      public const string RemovePrefix = "remove_";
1226
1227      protected AEventAccessor (Event method, string prefix, Attributes attrs, Location loc)
1228        : base (method, prefix, attrs, loc)
1229      {
1230        this.method = method;
1231        this.ModFlags = method.ModFlags;
1232        this.parameters = ParametersCompiled.CreateImplicitParameter (method.TypeExpression, loc);
1233      }
1234
1235      public bool IsInterfaceImplementation {
1236        get { return method_data.implementing != null; }
1237      }
1238
1239      public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1240      {
1241        if (a.Type == pa.MethodImpl) {
1242          method.is_external_implementation = a.IsInternalCall ();
1243        }
1244
1245        base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1246      }
1247
1248      protected override void ApplyToExtraTarget (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1249      {
1250        if (a.Target == AttributeTargets.Parameter) {
1251          parameters[0].ApplyAttributeBuilder (a, ctor, cdata, pa);
1252          return;
1253        }
1254
1255        base.ApplyToExtraTarget (a, ctor, cdata, pa);
1256      }
1257
1258      public override AttributeTargets AttributeTargets {
1259        get {
1260          return AttributeTargets.Method;
1261        }
1262      }
1263
1264      public override bool IsClsComplianceRequired ()
1265      {
1266        return method.IsClsComplianceRequired ();
1267      }
1268
1269      public virtual void Define (TypeContainer parent)
1270      {
1271        // Fill in already resolved event type to speed things up and
1272        // avoid confusing duplicate errors
1273        ((Parameter) parameters.FixedParameters[0]).Type = method.member_type;
1274        parameters.Types = new TypeSpec[] { method.member_type };
1275
1276        method_data = new MethodData (method, method.ModFlags,
1277          method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this);
1278
1279        if (!method_data.Define (parent.PartialContainer, method.GetFullName (MemberName)))
1280          return;
1281
1282        if (Compiler.Settings.WriteMetadataOnly)
1283          block = null;
1284
1285        Spec = new MethodSpec (MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, ParameterInfo, method.ModFlags);
1286        Spec.IsAccessor = true;
1287      }
1288
1289      public override TypeSpec ReturnType {
1290        get {
1291          return Parent.Compiler.BuiltinTypes.Void;
1292        }
1293      }
1294
1295      public override ObsoleteAttribute GetAttributeObsolete ()
1296      {
1297        return method.GetAttributeObsolete ();
1298      }
1299
1300      public MethodData MethodData {
1301        get {
1302          return method_data;
1303        }
1304      }
1305
1306      public override string[] ValidAttributeTargets {
1307        get {
1308          return attribute_targets;
1309        }
1310      }
1311
1312      public override ParametersCompiled ParameterInfo {
1313        get {
1314          return parameters;
1315        }
1316      }
1317    }
1318
1319    AEventAccessor add, remove;
1320    EventBuilder EventBuilder;
1321    protected EventSpec spec;
1322
1323    protected Event (TypeDefinition parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
1324      : base (parent, type, mod_flags,
1325        parent.PartialContainer.Kind == MemberKind.Interface ? AllowedModifiersInterface :
1326        parent.PartialContainer.Kind == MemberKind.Struct ? AllowedModifiersStruct :
1327        AllowedModifiersClass,
1328        name, attrs)
1329    {
1330    }
1331
1332    #region Properties
1333
1334    public override AttributeTargets AttributeTargets {
1335      get {
1336        return AttributeTargets.Event;
1337      }
1338    }
1339
1340    public AEventAccessor Add {
1341      get {
1342        return this.add;
1343      }
1344      set {
1345        add = value;
1346        Parent.AddNameToContainer (value, value.MemberName.Basename);
1347      }
1348    }
1349
1350    public override Variance ExpectedMemberTypeVariance {
1351      get {
1352        return Variance.Contravariant;
1353      }
1354    }
1355
1356    public AEventAccessor Remove {
1357      get {
1358        return this.remove;
1359      }
1360      set {
1361        remove = value;
1362        Parent.AddNameToContainer (value, value.MemberName.Basename);
1363      }
1364    }
1365    #endregion
1366
1367    public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1368    {
1369      if ((a.HasSecurityAttribute)) {
1370        a.Error_InvalidSecurityParent ();
1371        return;
1372      }
1373
1374      EventBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
1375    }
1376
1377    protected override bool CheckOverrideAgainstBase (MemberSpec base_member)
1378    {
1379      var ok = base.CheckOverrideAgainstBase (base_member);
1380
1381      if (!CheckAccessModifiers (this, base_member)) {
1382        Error_CannotChangeAccessModifiers (this, base_member);
1383        ok = false;
1384      }
1385
1386      return ok;
1387    }
1388
1389    public override bool Define ()
1390    {
1391      if (!base.Define ())
1392        return false;
1393
1394      if (!MemberType.IsDelegate) {
1395        Report.Error (66, Location, "`{0}': event must be of a delegate type", GetSignatureForError ());
1396      }
1397
1398      if (!CheckBase ())
1399        return false;
1400
1401      //
1402      // Now define the accessors
1403      //
1404      add.Define (Parent);
1405      remove.Define (Parent);
1406
1407      EventBuilder = Parent.TypeBuilder.DefineEvent (GetFullName (MemberName), EventAttributes.None, MemberType.GetMetaInfo ());
1408
1409      spec = new EventSpec (Parent.Definition, this, MemberType, ModFlags, Add.Spec, remove.Spec);
1410
1411      Parent.MemberCache.AddMember (this, GetFullName (MemberName), spec);
1412      Parent.MemberCache.AddMember (this, Add.Spec.Name, Add.Spec);
1413      Parent.MemberCache.AddMember (this, Remove.Spec.Name, remove.Spec);
1414
1415      return true;
1416    }
1417
1418    public override void Emit ()
1419    {
1420      CheckReservedNameConflict (null, add.Spec);
1421      CheckReservedNameConflict (null, remove.Spec);
1422
1423      if (OptAttributes != null) {
1424        OptAttributes.Emit ();
1425      }
1426
1427      ConstraintChecker.Check (this, member_type, type_expr.Location);
1428
1429      Add.Emit (Parent);
1430      Remove.Emit (Parent);
1431
1432      base.Emit ();
1433    }
1434
1435    public override void PrepareEmit ()
1436    {
1437      add.PrepareEmit ();
1438      remove.PrepareEmit ();
1439
1440      EventBuilder.SetAddOnMethod (add.MethodData.MethodBuilder);
1441      EventBuilder.SetRemoveOnMethod (remove.MethodData.MethodBuilder);
1442    }
1443
1444    public override void WriteDebugSymbol (MonoSymbolFile file)
1445    {
1446      add.WriteDebugSymbol (file);
1447      remove.WriteDebugSymbol (file);
1448    }
1449
1450    //
1451    //   Represents header string for documentation comment.
1452    //
1453    public override string DocCommentHeader {
1454      get { return "E:"; }
1455    }
1456  }
1457
1458  public class EventSpec : MemberSpec, IInterfaceMemberSpec
1459  {
1460    MethodSpec add, remove;
1461    FieldSpec backing_field;
1462
1463    public EventSpec (TypeSpec declaringType, IMemberDefinition definition, TypeSpec eventType, Modifiers modifiers, MethodSpec add, MethodSpec remove)
1464      : base (MemberKind.Event, declaringType, definition, modifiers)
1465    {
1466      this.AccessorAdd = add;
1467      this.AccessorRemove = remove;
1468      this.MemberType = eventType;
1469    }
1470
1471    #region Properties
1472
1473    public MethodSpec AccessorAdd {
1474      get {
1475        return add;
1476      }
1477      set {
1478        add = value;
1479      }
1480    }
1481
1482    public MethodSpec AccessorRemove {
1483      get {
1484        return remove;
1485      }
1486      set {
1487        remove = value;
1488      }
1489    }
1490
1491    public FieldSpec BackingField {
1492      get {
1493        return backing_field;
1494      }
1495      set {
1496        backing_field = value;
1497      }
1498    }
1499
1500    public TypeSpec MemberType { get; private set; }
1501
1502    #endregion
1503
1504    public override MemberSpec InflateMember (TypeParameterInflator inflator)
1505    {
1506      var es = (EventSpec) base.InflateMember (inflator);
1507      es.MemberType = inflator.Inflate (MemberType);
1508
1509      if (backing_field != null)
1510        es.backing_field = (FieldSpec) backing_field.InflateMember (inflator);
1511
1512      return es;
1513    }
1514
1515    public override List<MissingTypeSpecReference> ResolveMissingDependencies (MemberSpec caller)
1516    {
1517      return MemberType.ResolveMissingDependencies (this);
1518    }
1519  }
1520 
1521  public class Indexer : PropertyBase, IParametersMember
1522  {
1523    public class GetIndexerMethod : GetMethod, IParametersMember
1524    {
1525      ParametersCompiled parameters;
1526
1527      public GetIndexerMethod (PropertyBase property, Modifiers modifiers, ParametersCompiled parameters, Attributes attrs, Location loc)
1528        : base (property, modifiers, attrs, loc)
1529      {
1530        this.parameters = parameters;
1531      }
1532
1533      public override void Define (TypeContainer parent)
1534      {
1535        // Disable reporting, parameters are resolved twice
1536        Report.DisableReporting ();
1537        try {
1538          parameters.Resolve (this);
1539        } finally {
1540          Report.EnableReporting ();
1541        }
1542
1543        base.Define (parent);
1544      }
1545
1546      public override ParametersCompiled ParameterInfo {
1547        get {
1548          return parameters;
1549        }
1550      }
1551
1552      #region IParametersMember Members
1553
1554      AParametersCollection IParametersMember.Parameters {
1555        get {
1556          return parameters;
1557        }
1558      }
1559
1560      TypeSpec IInterfaceMemberSpec.MemberType {
1561        get {
1562          return ReturnType;
1563        }
1564      }
1565
1566      #endregion
1567    }
1568
1569    public class SetIndexerMethod : SetMethod, IParametersMember
1570    {
1571      public SetIndexerMethod (PropertyBase property, Modifiers modifiers, ParametersCompiled parameters, Attributes attrs, Location loc)
1572        : base (property, modifiers, parameters, attrs, loc)
1573      {
1574      }
1575
1576      #region IParametersMember Members
1577
1578      AParametersCollection IParametersMember.Parameters {
1579        get {
1580          return parameters;
1581        }
1582      }
1583
1584      TypeSpec IInterfaceMemberSpec.MemberType {
1585        get {
1586          return ReturnType;
1587        }
1588      }
1589
1590      #endregion
1591    }
1592
1593    const Modifiers AllowedModifiers =
1594      Modifiers.NEW |
1595      Modifiers.PUBLIC |
1596      Modifiers.PROTECTED |
1597      Modifiers.INTERNAL |
1598      Modifiers.PRIVATE |
1599      Modifiers.VIRTUAL |
1600      Modifiers.SEALED |
1601      Modifiers.OVERRIDE |
1602      Modifiers.UNSAFE |
1603      Modifiers.EXTERN |
1604      Modifiers.ABSTRACT;
1605
1606    const Modifiers AllowedInterfaceModifiers =
1607      Modifiers.NEW;
1608
1609    readonly ParametersCompiled parameters;
1610
1611    public Indexer (TypeDefinition parent, FullNamedExpression type, MemberName name, Modifiers mod, ParametersCompiled parameters, Attributes attrs)
1612      : base (parent, type, mod,
1613        parent.PartialContainer.Kind == MemberKind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
1614        name, attrs)
1615    {
1616      this.parameters = parameters;
1617    }
1618
1619    #region Properties
1620
1621    AParametersCollection IParametersMember.Parameters {
1622      get {
1623        return parameters;
1624      }
1625    }
1626
1627    public ParametersCompiled ParameterInfo {
1628      get {
1629        return parameters;
1630      }
1631    }
1632
1633    #endregion
1634
1635   
1636    public override void Accept (StructuralVisitor visitor)
1637    {
1638      visitor.Visit (this);
1639    }
1640
1641    public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1642    {
1643      if (a.Type == pa.IndexerName) {
1644        // Attribute was copied to container
1645        return;
1646      }
1647
1648      base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1649    }
1650
1651    protected override bool CheckForDuplications ()
1652    {
1653      return Parent.MemberCache.CheckExistingMembersOverloads (this, parameters);
1654    }
1655   
1656    public override bool Define ()
1657    {
1658      if (!base.Define ())
1659        return false;
1660
1661      if (!DefineParameters (parameters))
1662        return false;
1663
1664      if (OptAttributes != null) {
1665        Attribute indexer_attr = OptAttributes.Search (Module.PredefinedAttributes.IndexerName);
1666        if (indexer_attr != null) {
1667          var compiling = indexer_attr.Type.MemberDefinition as TypeContainer;
1668          if (compiling != null)
1669            compiling.Define ();
1670
1671          if (IsExplicitImpl) {
1672            Report.Error (415, indexer_attr.Location,
1673              "The `{0}' attribute is valid only on an indexer that is not an explicit interface member declaration",
1674              indexer_attr.Type.GetSignatureForError ());
1675          } else if ((ModFlags & Modifiers.OVERRIDE) != 0) {
1676            Report.Error (609, indexer_attr.Location,
1677              "Cannot set the `IndexerName' attribute on an indexer marked override");
1678          } else {
1679            string name = indexer_attr.GetIndexerAttributeValue ();
1680
1681            if (!string.IsNullOrEmpty (name)) {
1682              SetMemberName (new MemberName (MemberName.Left, name, Location));
1683            }
1684          }
1685        }
1686      }
1687
1688      if (InterfaceType != null) {
1689        string base_IndexerName = InterfaceType.MemberDefinition.GetAttributeDefaultMember ();
1690        if (base_IndexerName != ShortName) {
1691          SetMemberName (new MemberName (MemberName.Left, base_IndexerName, new TypeExpression (InterfaceType, Location), Location));
1692        }
1693      }
1694
1695      Parent.AddNameToContainer (this, MemberName.Basename);
1696
1697      flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
1698     
1699      if (!DefineAccessors ())
1700        return false;
1701
1702      if (!CheckBase ())
1703        return false;
1704
1705      DefineBuilders (MemberKind.Indexer, parameters);
1706      return true;
1707    }
1708
1709    public override bool EnableOverloadChecks (MemberCore overload)
1710    {
1711      if (overload is Indexer) {
1712        caching_flags |= Flags.MethodOverloadsExist;
1713        return true;
1714      }
1715
1716      return base.EnableOverloadChecks (overload);
1717    }
1718
1719    public override void Emit ()
1720    {
1721      parameters.CheckConstraints (this);
1722
1723      base.Emit ();
1724    }
1725
1726    public override string GetSignatureForError ()
1727    {
1728      StringBuilder sb = new StringBuilder (Parent.GetSignatureForError ());
1729      if (MemberName.ExplicitInterface != null) {
1730        sb.Append (".");
1731        sb.Append (MemberName.ExplicitInterface.GetSignatureForError ());
1732      }
1733
1734      sb.Append (".this");
1735      sb.Append (parameters.GetSignatureForError ("[", "]", parameters.Count));
1736      return sb.ToString ();
1737    }
1738
1739    public override string GetSignatureForDocumentation ()
1740    {
1741      return base.GetSignatureForDocumentation () + parameters.GetSignatureForDocumentation ();
1742    }
1743
1744    protected override bool VerifyClsCompliance ()
1745    {
1746      if (!base.VerifyClsCompliance ())
1747        return false;
1748
1749      parameters.VerifyClsCompliance (this);
1750      return true;
1751    }
1752  }
1753
1754  public class IndexerSpec : PropertySpec, IParametersMember
1755  {
1756    AParametersCollection parameters;
1757
1758    public IndexerSpec (TypeSpec declaringType, IMemberDefinition definition, TypeSpec memberType, AParametersCollection parameters, PropertyInfo info, Modifiers modifiers)
1759      : base (MemberKind.Indexer, declaringType, definition, memberType, info, modifiers)
1760    {
1761      this.parameters = parameters;
1762    }
1763
1764    #region Properties
1765    public AParametersCollection Parameters {
1766      get {
1767        return parameters;
1768      }
1769    }
1770    #endregion
1771
1772    public override string GetSignatureForDocumentation ()
1773    {
1774      return base.GetSignatureForDocumentation () + parameters.GetSignatureForDocumentation ();
1775    }
1776
1777    public override string GetSignatureForError ()
1778    {
1779      return DeclaringType.GetSignatureForError () + ".this" + parameters.GetSignatureForError ("[", "]", parameters.Count);
1780    }
1781
1782    public override MemberSpec InflateMember (TypeParameterInflator inflator)
1783    {
1784      var spec = (IndexerSpec) base.InflateMember (inflator);
1785      spec.parameters = parameters.Inflate (inflator);
1786      return spec;
1787    }
1788
1789    public override List<MissingTypeSpecReference> ResolveMissingDependencies (MemberSpec caller)
1790    {
1791      var missing = base.ResolveMissingDependencies (caller);
1792
1793      foreach (var pt in parameters.Types) {
1794        var m = pt.GetMissingDependencies (caller);
1795        if (m == null)
1796          continue;
1797
1798        if (missing == null)
1799          missing = new List<MissingTypeSpecReference> ();
1800
1801        missing.AddRange (m);
1802      }
1803
1804      return missing;
1805    }
1806  }
1807}
Note: See TracBrowser for help on using the repository browser.