2004-02-03 Marek Safar <marek.safar@seznam.cz>
[mono.git] / mcs / mcs / interface.cs
1 //
2 // interface.cs: Interface handler
3 //
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 //
6 // Licensed under the terms of the GNU GPL
7 //
8 // (C) 2001 Ximian, Inc (http://www.ximian.com)
9 //
10 #define CACHE
11 using System.Collections;
12 using System;
13 using System.IO;
14 using System.Reflection;
15 using System.Reflection.Emit;
16
17 namespace Mono.CSharp {
18
19         /// <summary>
20         ///   Interfaces
21         /// </summary>
22         public class Interface : DeclSpace, IMemberContainer {
23                 const MethodAttributes interface_method_attributes =
24                         MethodAttributes.Public |
25                         MethodAttributes.Abstract |
26                         MethodAttributes.HideBySig |
27                         MethodAttributes.NewSlot |
28                         MethodAttributes.Virtual;
29
30                 const MethodAttributes property_attributes =
31                         MethodAttributes.Public |
32                         MethodAttributes.Abstract |
33                         MethodAttributes.HideBySig |
34                         MethodAttributes.NewSlot |
35                         MethodAttributes.SpecialName |
36                         MethodAttributes.Virtual;
37                 
38                 ArrayList bases;
39                 
40                 ArrayList defined_method;
41                 ArrayList defined_indexer;
42                 ArrayList defined_events;
43                 ArrayList defined_properties;
44
45                 ArrayList method_builders;
46                 ArrayList property_builders;
47                 ArrayList event_builders;
48                 
49
50                 public string IndexerName;
51
52                 IMemberContainer parent_container;
53                 MemberCache member_cache;
54
55                 bool members_defined;
56
57                 // These will happen after the semantic analysis
58                 
59                 // Hashtable defined_indexers;
60                 // Hashtable defined_methods;
61                 
62                 /// <summary>
63                 ///   Modifiers allowed in a class declaration
64                 /// </summary>
65                 public const int AllowedModifiers =
66                         Modifiers.NEW       |
67                         Modifiers.PUBLIC    |
68                         Modifiers.PROTECTED |
69                         Modifiers.INTERNAL  |
70                         Modifiers.UNSAFE    |
71                         Modifiers.PRIVATE;
72
73                 public Interface (NamespaceEntry ns, TypeContainer parent, string name, int mod,
74                                   Attributes attrs, Location l)
75                         : base (ns, parent, name, attrs, l)
76                 {
77                         ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE, l);
78                         
79                         method_builders = new ArrayList ();
80                         property_builders = new ArrayList ();
81                         event_builders = new ArrayList ();
82                 }
83
84                 public AdditionResult AddMethod (InterfaceMethod imethod)
85                 {
86                         string name = imethod.Name;
87                         Object value = defined_names [name];
88
89                         if (value != null){
90                                 if (!(value is InterfaceMethod))
91                                         return AdditionResult.NameExists;
92                         } 
93
94                         if (defined_method == null)
95                                 defined_method = new ArrayList ();
96
97                         defined_method.Add (imethod);
98                         if (value == null)
99                                 DefineName (name, imethod);
100                         
101                         return AdditionResult.Success;
102                 }
103
104                 public AdditionResult AddProperty (InterfaceProperty iprop)
105                 {
106                         AdditionResult res;
107                         string name = iprop.Name;
108
109                         if ((res = IsValid (name, name)) != AdditionResult.Success)
110                                 return res;
111
112                         DefineName (name, iprop);
113
114                         if (defined_properties == null)
115                                 defined_properties = new ArrayList ();
116
117                         defined_properties.Add (iprop);
118                         return AdditionResult.Success;
119                 }
120
121                 public AdditionResult AddEvent (InterfaceEvent ievent)
122                 {
123                         string name = ievent.Name;
124                         AdditionResult res;
125                         
126                         if ((res = IsValid (name, name)) != AdditionResult.Success)
127                                 return res;
128
129                         DefineName (name, ievent);
130
131                         if (defined_events == null)
132                                 defined_events = new ArrayList ();
133
134                         defined_events.Add (ievent);
135                         return AdditionResult.Success;
136                 }
137
138                 public bool AddIndexer (InterfaceIndexer iindexer)
139                 {
140                         if (defined_indexer == null)
141                                 defined_indexer = new ArrayList ();
142                         
143                         defined_indexer.Add (iindexer);
144                         return true;
145                 }
146                 
147                 public ArrayList InterfaceMethods {
148                         get {
149                                 return defined_method;
150                         }
151                 }
152
153                 public ArrayList InterfaceProperties {
154                         get {
155                                 return defined_properties;
156                         }
157                 }
158
159                 public ArrayList InterfaceEvents {
160                         get {
161                                 return defined_events;
162                         }
163                 }
164
165                 public ArrayList InterfaceIndexers {
166                         get {
167                                 return defined_indexer;
168                         }
169                 }
170
171                 public ArrayList Bases {
172                         get {
173                                 return bases;
174                         }
175
176                         set {
177                                 bases = value;
178                         }
179                 }
180
181                 public virtual TypeAttributes InterfaceAttr {
182                         get {
183                                 TypeAttributes x = TypeAttributes.Interface | TypeAttributes.Abstract;
184
185                                 if (IsTopLevel == false) {
186                                         
187                                         if ((ModFlags & Modifiers.PROTECTED) != 0
188                                             && (ModFlags & Modifiers.INTERNAL) != 0)
189                                                 x |= TypeAttributes.NestedFamORAssem;
190                                         else if ((ModFlags & Modifiers.PROTECTED) != 0)
191                                                 x |= TypeAttributes.NestedFamily;
192                                         else if ((ModFlags & Modifiers.INTERNAL) != 0)
193                                                 x |= TypeAttributes.NestedAssembly;
194                                         else if ((ModFlags & Modifiers.PUBLIC) != 0)
195                                                 x |= TypeAttributes.NestedPublic;
196                                         else
197                                                 x |= TypeAttributes.NestedPrivate;
198                                 } else {
199                                         if ((ModFlags & Modifiers.PUBLIC) != 0)
200                                                 x |= TypeAttributes.Public;
201                                         else if ((ModFlags & Modifiers.PRIVATE) != 0)
202                                                 x |= TypeAttributes.NotPublic;
203                                 }
204                                 
205                                 if ((ModFlags & Modifiers.ABSTRACT) != 0)
206                                         x |= TypeAttributes.Abstract;
207                                 
208                                 if ((ModFlags & Modifiers.SEALED) != 0)
209                                         x |= TypeAttributes.Sealed;
210
211                                 return x;
212                         }
213                 }
214                 
215                 void Error111 (InterfaceMemberBase ib)
216                 {
217                         Report.Error (
218                                 111,
219                                 "Interface `" + Name + "' already contains a definition with the " +
220                                 "same return value and parameter types for member `" + ib.Name + "'");
221                 }
222
223                 bool RegisterMethod (MethodBase mb, InternalParameters ip, Type [] types)
224                 {
225                         if (!TypeManager.RegisterMethod (mb, ip, types))
226                                 return false;
227
228                         method_builders.Add (mb);
229                         return true;
230                 }
231
232                 //
233                 // This might trigger a definition of the methods.  This happens only
234                 // with Attributes, as Attribute classes are processed before interfaces.
235                 // Ideally, we should make everything just define recursively in terms
236                 // of its dependencies.
237                 //
238                 public MethodInfo [] GetMethods (TypeContainer container)
239                 {
240                         int n = 0;
241                         
242                         if (!members_defined){
243                                 if (DefineMembers (container))
244                                         n = method_builders.Count;
245                         } else
246                                 n = method_builders.Count;
247                         
248                         MethodInfo [] mi = new MethodInfo [n];
249                         
250                         method_builders.CopyTo (mi, 0);
251
252                         return mi;
253                 }
254
255                 // Hack around System.Reflection as found everywhere else
256                 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
257                                                         MemberFilter filter, object criteria)
258                 {
259                         ArrayList members = new ArrayList ();
260
261                         if ((mt & MemberTypes.Method) != 0) {
262                                 foreach (MethodBuilder mb in method_builders)
263                                         if (filter (mb, criteria))
264                                                 members.Add (mb);
265                         }
266
267                         if ((mt & MemberTypes.Property) != 0) {
268                                 foreach (PropertyBuilder pb in property_builders)
269                                         if (filter (pb, criteria))
270                                                 members.Add (pb);
271                         }
272
273                         if ((mt & MemberTypes.Event) != 0) {
274                                 foreach (MyEventBuilder eb in event_builders)
275                                         if (filter (eb, criteria))
276                                                 members.Add (eb);
277                         }
278
279                         if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
280                                 MemberList parent_mi;
281                                 
282                                 parent_mi = TypeContainer.FindMembers (
283                                         TypeBuilder.BaseType, mt, bf, filter, criteria);
284
285                                 members.AddRange (parent_mi);
286                         }
287
288                         return new MemberList (members);
289                 }
290
291                 public override MemberCache MemberCache {
292                         get {
293                                 return member_cache;
294                         }
295                 }
296
297                 //
298                 // Populates the methods in the interface
299                 //
300                 void PopulateMethod (TypeContainer parent, DeclSpace decl_space, InterfaceMethod im)
301                 {
302                         if (im.ReturnType == null)
303                                 return;
304
305                         Type return_type = im.ReturnType.Type;
306                         if (return_type == null)
307                                 return_type = this.ResolveType (im.ReturnType, false, im.Location);
308                         
309                         Type [] arg_types = im.ParameterTypes (this);
310                         MethodBuilder mb;
311
312                         if (return_type == null)
313                                 return;
314
315                         if (return_type.IsPointer && !UnsafeOK (this))
316                                 return;
317
318                         if (arg_types == null)
319                                 return;
320
321                         foreach (Type t in arg_types){
322
323                                 if (t == null)
324                                         return;
325                                 
326                                 if (t.IsPointer && !UnsafeOK (this))
327                                         return;
328                         }
329                         
330                         //
331                         // Create the method
332                         //
333                         mb = TypeBuilder.DefineMethod (
334                                 im.Name, interface_method_attributes,
335                                 return_type, arg_types);
336
337                         InternalParameters ip = new InternalParameters (arg_types, im.Parameters);
338
339                         if (!RegisterMethod (mb, ip, arg_types)) {
340                                 Error111 (im);
341                                 return;
342                         }
343
344                         //
345                         // Labelling of parameters is taken care of
346                         // during the Emit phase via
347                         // MethodCore.LabelParameters method so I am
348                         // removing the old code here.
349                         //
350                         
351                         im.Builder = mb;
352                         
353                 }
354
355                 //
356                 // Populates the properties in the interface
357                 //
358                 void PopulateProperty (TypeContainer parent, DeclSpace decl_space, InterfaceProperty ip)
359                 {
360                         PropertyBuilder pb;
361
362                         ip.Type = this.ResolveTypeExpr (ip.Type, false, ip.Location);
363                         if (ip.Type == null)
364                                 return;
365                         
366                         Type prop_type = ip.Type.Type;
367                         Type [] setter_args = new Type [1];
368
369                         if (prop_type == null)
370                                 return;
371
372                         if (prop_type.IsPointer && !UnsafeOK (this))
373                                 return;
374                         
375                         setter_args [0] = prop_type;
376
377                         //
378                         // FIXME: properties are missing the following
379                         // flags: hidebysig newslot specialname
380                         //
381                         pb = TypeBuilder.DefineProperty (
382                                 ip.Name, PropertyAttributes.None,
383                                 prop_type, null);
384
385                         MethodBuilder get = null, set = null;
386                         
387                         if (ip.HasGet){
388                                 get = TypeBuilder.DefineMethod (
389                                         "get_" + ip.Name, property_attributes ,
390                                         prop_type, null);
391
392                                 //
393                                 // HACK because System.Reflection.Emit is lame
394                                 //
395                                 Type [] null_types = null;
396                                 InternalParameters inp = new InternalParameters
397                                         (null_types, Parameters.EmptyReadOnlyParameters);
398                                 
399                                 if (!RegisterMethod (get, inp, null)) {
400                                         Error111 (ip);
401                                         return;
402                                 }
403                                 
404                                 pb.SetGetMethod (get);
405                         }
406
407                         if (ip.HasSet){
408                                 setter_args [0] = prop_type;
409
410                                 set = TypeBuilder.DefineMethod (
411                                         "set_" + ip.Name, property_attributes,
412                                         TypeManager.void_type, setter_args);
413
414                                 set.DefineParameter (1, ParameterAttributes.None, "value");
415                                 pb.SetSetMethod (set);
416
417                                 //
418                                 // HACK because System.Reflection.Emit is lame
419                                 //
420                                 Parameter [] parms = new Parameter [1];
421                                 parms [0] = new Parameter (ip.Type, "value", Parameter.Modifier.NONE, null);
422                                 InternalParameters ipp = new InternalParameters (
423                                         this, new Parameters (parms, null, Location.Null));
424                                         
425                                 if (!RegisterMethod (set, ipp, setter_args)) {
426                                         Error111 (ip);
427                                         return;
428                                 }
429                         }
430
431                         TypeManager.RegisterProperty (pb, get, set);
432                         property_builders.Add (pb);
433                         ip.Builder = pb;
434                         ip.GetBuilder = get;
435                         ip.SetBuilder = set;
436                 }
437
438                 //
439                 // Populates the events in the interface
440                 //
441                 void PopulateEvent (TypeContainer parent, DeclSpace decl_space, InterfaceEvent ie)
442                 {
443                         //
444                         // FIXME: We need to do this after delegates have been
445                         // declared or we declare them recursively.
446                         //
447                         MyEventBuilder eb;
448                         MethodBuilder add = null, remove = null;
449                         ie.Type = this.ResolveTypeExpr (ie.Type, false, ie.Location);
450                         if (ie.Type == null)
451                                 return;
452                         
453                         Type event_type = ie.Type.Type;
454
455                         if (event_type == null)
456                                 return;
457
458                         if (event_type.IsPointer && !UnsafeOK (this))
459                                 return;
460
461                         Type [] parameters = new Type [1];
462                         parameters [0] = event_type;
463
464                         eb = new MyEventBuilder (null, TypeBuilder, ie.Name,
465                                                  EventAttributes.None, event_type);
466
467                         //
468                         // Now define the accessors
469                         //
470                         string add_name = "add_" + ie.Name;
471                         
472                         add = TypeBuilder.DefineMethod (
473                                 add_name, property_attributes, null, parameters);
474                         add.DefineParameter (1, ParameterAttributes.None, "value");
475                         eb.SetAddOnMethod (add);
476
477                         string remove_name = "remove_" + ie.Name;
478                         remove = TypeBuilder.DefineMethod (
479                                 remove_name, property_attributes, null, parameters);
480                         remove.DefineParameter (1, ParameterAttributes.None, "value");
481                         eb.SetRemoveOnMethod (remove);
482
483                         Parameter [] parms = new Parameter [1];
484                         parms [0] = new Parameter (ie.Type, "value", Parameter.Modifier.NONE, null);
485                         InternalParameters ip = new InternalParameters (
486                                 this, new Parameters (parms, null, Location.Null));
487
488                         if (!RegisterMethod (add, ip, parameters)) {
489                                 Error111 (ie);
490                                 return;
491                         }
492                         
493                         if (!RegisterMethod (remove, ip, parameters)) {
494                                 Error111 (ie);
495                                 return;
496                         }
497
498                         TypeManager.RegisterEvent (eb, add, remove);
499                         event_builders.Add (eb);
500
501                         ie.Builder = eb;
502                 }
503
504                 //
505                 // Populates the indexers in the interface
506                 //
507                 void PopulateIndexer (TypeContainer parent, DeclSpace decl_space, InterfaceIndexer ii)
508                 {
509                         PropertyBuilder pb;
510                         ii.Type = this.ResolveTypeExpr (ii.Type, false, ii.Location);
511                         if (ii.Type == null)
512                                 return;
513                         
514                         Type prop_type = ii.Type.Type;
515                         Type [] arg_types = ii.ParameterTypes (this);
516                         Type [] value_arg_types;
517
518                         if (prop_type == null)
519                                 return;
520
521                         if (prop_type.IsPointer && !UnsafeOK (this))
522                                 return;
523                         
524                         //
525                         // Sets up the extra invisible `value' argument for setters.
526                         // 
527                         if (arg_types != null){
528                                 int count = arg_types.Length;
529                                 value_arg_types = new Type [count + 1];
530
531                                 arg_types.CopyTo (value_arg_types, 0);
532                                 value_arg_types [count] = prop_type;
533
534                                 foreach (Type t in arg_types){
535                                         if (t.IsPointer && !UnsafeOK (this))
536                                                 return;
537                                 }
538                         } else {
539                                 value_arg_types = new Type [1];
540
541                                 value_arg_types [1] = prop_type;
542                         }
543
544                         EmitContext ec = new EmitContext (parent, decl_space, Location, null,
545                                                           null, ModFlags, false);
546
547                         IndexerName = Attribute.ScanForIndexerName (ec, ii.OptAttributes);
548                         if (IndexerName == null)
549                                 IndexerName = "Item";
550                         
551                         pb = TypeBuilder.DefineProperty (
552                                 IndexerName, PropertyAttributes.None,
553                                 prop_type, arg_types);
554                         
555                         MethodBuilder set_item = null, get_item = null;
556                         if (ii.HasGet){
557                                 Parameter [] p = ii.Parameters.FixedParameters;
558                                 
559                                 get_item = TypeBuilder.DefineMethod (
560                                         "get_" + IndexerName, property_attributes,
561                                         prop_type, arg_types);
562                                 pb.SetGetMethod (get_item);
563                                 //
564                                 // HACK because System.Reflection.Emit is lame
565                                 //
566                                 InternalParameters ip = new InternalParameters (
567                                         arg_types, ii.Parameters);
568                                 
569                                 if (!RegisterMethod (get_item, ip, arg_types)) {
570                                         Error111 (ii);
571                                         return;
572                                 }
573
574                                 if (p != null){
575                                         for (int i = 0; i < p.Length; i++)
576                                                 get_item.DefineParameter (
577                                                         i + 1,
578                                                         p [i].Attributes, p [i].Name);
579                                 }
580                         }
581
582                         if (ii.HasSet){
583                                 Parameter [] p = ii.Parameters.FixedParameters;
584                                 Parameter [] pv;
585                                 int i = 0;
586                                 
587                                 pv = new Parameter [p.Length + 1];
588                                 p.CopyTo (pv, 0);
589                                 pv [p.Length] = new Parameter (ii.Type, "value", Parameter.Modifier.NONE, null);
590                                 Parameters value_params = new Parameters (pv, null, Location.Null);
591                                 value_params.GetParameterInfo (decl_space);
592                                 
593                                 set_item = TypeBuilder.DefineMethod (
594                                         "set_" + IndexerName, property_attributes,
595                                         TypeManager.void_type, value_arg_types);
596                                 pb.SetSetMethod (set_item);
597                                 //
598                                 // HACK because System.Reflection.Emit is lame
599                                 //
600                                 InternalParameters ip = new InternalParameters (
601                                         value_arg_types, value_params);
602                                 if (!RegisterMethod (set_item, ip, value_arg_types)) {
603                                         Error111 (ii);
604                                         return;
605                                 }
606
607                                 if (p != null){
608                                         for (; i < p.Length; i++)
609                                                 set_item.DefineParameter (
610                                                         i + 1,
611                                                         p [i].Attributes, p [i].Name);
612                                 }
613                                 
614                                 set_item.DefineParameter (i + 1, ParameterAttributes.None, "value");
615                         }
616
617                         property_builders.Add (pb);
618
619                         ii.Builder = pb;
620                         ii.GetBuilder = get_item;
621                         ii.SetBuilder = set_item;
622                 }
623
624                 /// <summary>
625                 ///   Performs the semantic analysis for all the interface members
626                 ///   that were declared
627                 /// </summary>
628                 bool SemanticAnalysis ()
629                 {
630                         Hashtable methods = new Hashtable ();
631
632                         
633                         if (defined_method != null){
634                                 foreach (InterfaceMethod im in defined_method){
635                                         string sig = im.GetSignature (this);
636                                         
637                                         //
638                                         // If there was an undefined Type on the signatures
639                                         // 
640                                         if (sig == null)
641                                                 continue;
642                                         
643                                         if (methods [sig] != null){
644                                                 Error111 (im);
645                                                 return false;
646                                         }
647                                 }
648                         }
649
650                         //
651                         // FIXME: Here I should check i
652                         // 
653                         return true;
654                 }
655
656                 TypeExpr GetInterfaceTypeByName (string name)
657                 {
658                         Type t = FindType (Location, name);
659
660                         if (t == null) {
661                                 Report.Error (246, Location, "The type or namespace `" + name +
662                                               "' could not be found");
663                                 return null;
664                         }
665                         
666                         if (t.IsInterface)
667                                 return new TypeExpression (t, Location);
668                                 
669                         string cause;
670                         
671                         if (t.IsValueType)
672                                 cause = "is a struct";
673                         else if (t.IsClass) 
674                                 cause = "is a class";
675                         else
676                                 cause = "Should not happen.";
677                         
678                         Report.Error (527, Location, "`"+name+"' " + cause +
679                                       ", need an interface instead");
680                         
681                         return null;
682                 }
683                 
684                 //
685                 // Returns the list of interfaces that this interface implements
686                 // Or null if it does not implement any interface.
687                 //
688                 // Sets the error boolean accoringly.
689                 //
690                 TypeExpr [] GetInterfaceBases (out bool error)
691                 {
692                         TypeExpr [] tbases;
693                         int i;
694
695                         error = false;
696                         if (Bases == null)
697                                 return null;
698                         
699                         tbases = new TypeExpr [Bases.Count];
700                         i = 0;
701
702                         foreach (string name in Bases){
703                                 TypeExpr t;
704
705                                 t = GetInterfaceTypeByName (name);
706                                 if (t == null){
707                                         error = true;
708                                         return null;
709                                 }
710
711                                 if (!t.AsAccessible (Parent, ModFlags))
712                                         Report.Error (61, Location,
713                                                       "Inconsistent accessibility: base interface `" +
714                                                       t.Name + "' is less accessible than interface `" +
715                                                       Name + "'");
716
717                                 tbases [i++] = t;
718                         }
719                         
720                         return TypeManager.ExpandInterfaces (tbases);
721                 }
722                 
723                 //
724                 // <summary>
725                 //  Defines the Interface in the appropriate ModuleBuilder or TypeBuilder
726                 // </summary>
727                 //
728                 // TODO:
729                 //   Rework the way we recurse, because for recursive
730                 //   definitions of interfaces (A:B and B:A) we report the
731                 //   error twice, rather than once.  
732                 
733                 public override TypeBuilder DefineType ()
734                 {
735                         TypeExpr [] ifaces;
736                         bool error;
737
738                         if (TypeBuilder != null)
739                                 return TypeBuilder;
740                         
741                         if (InTransit)
742                                 return null;
743                         
744                         InTransit = true;
745                         
746                         EmitContext ec = new EmitContext (this, this, Location, null, null,
747                                                           ModFlags, false);
748
749                         ifaces = GetInterfaceBases (out error);
750
751                         if (error)
752                                 return null;
753
754                         if (IsTopLevel) {
755                                 if (TypeManager.NamespaceClash (Name, Location))
756                                         return null;
757                                 
758                                 ModuleBuilder builder = CodeGen.ModuleBuilder;
759
760                                 TypeBuilder = builder.DefineType (
761                                         Name,
762                                         InterfaceAttr,
763                                         (Type)null,   // Parent Type
764                                         null);
765                                 RootContext.RegisterOrder (this);
766                         } else {
767                                 TypeBuilder builder = Parent.TypeBuilder;
768
769                                 TypeBuilder = builder.DefineNestedType (
770                                         Basename,
771                                         InterfaceAttr,
772                                         (Type) null, //parent type
773                                         null);
774
775                                 TypeContainer tc = TypeManager.LookupTypeContainer (builder);
776                                 tc.RegisterOrder (this);
777                         }
778
779                         if (ifaces != null) {
780                                 foreach (TypeExpr iface in ifaces) {
781                                         Type itype = iface.ResolveType (ec);
782                                         TypeBuilder.AddInterfaceImplementation (itype);
783                                 }
784                         }
785
786                         TypeManager.AddUserInterface (Name, TypeBuilder, this, ifaces);
787                         InTransit = false;
788
789                         return TypeBuilder;
790                 }
791
792                 //
793                 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
794                 // interface is consistent.  Either it is `Item' or it is the name defined by all the
795                 // indexers with the `IndexerName' attribute.
796                 //
797                 // Turns out that the IndexerNameAttribute is applied to each indexer,
798                 // but it is never emitted, instead a DefaultName attribute is attached
799                 // to the interface
800                 //
801                 void DefineIndexers (TypeContainer parent)
802                 {
803                         string interface_indexer_name = null;
804
805                         foreach (InterfaceIndexer ii in defined_indexer){
806
807                                 PopulateIndexer (parent, this, ii);
808
809                                 if (interface_indexer_name == null){
810                                         interface_indexer_name = IndexerName;
811                                         continue;
812                                 }
813                                 
814                                 if (IndexerName == interface_indexer_name)
815                                         continue;
816                                 
817                                 Report.Error (
818                                         668, "Two indexers have different names, " +
819                                         " you should use the same name for all your indexers");
820                         }
821                         if (interface_indexer_name == null)
822                                 interface_indexer_name = "Item";
823                         IndexerName = interface_indexer_name;
824                 }
825                 
826                 /// <summary>
827                 ///   Performs semantic analysis, and then generates the IL interfaces
828                 /// </summary>
829                 public override bool DefineMembers (TypeContainer parent)
830                 {
831                         if (members_defined)
832                                 return true;
833                         
834                         if (!SemanticAnalysis ())
835                                 return false;
836
837                         
838                         if (defined_method != null){
839                                 foreach (InterfaceMethod im in defined_method)
840                                         PopulateMethod (parent, this, im);
841                         }
842
843                         if (defined_properties != null){
844                                 foreach (InterfaceProperty ip in defined_properties)
845                                         PopulateProperty (parent, this, ip);
846                         }
847
848                         if (defined_events != null)
849                                 foreach (InterfaceEvent ie in defined_events)
850                                         PopulateEvent (parent, this, ie);
851
852                         if (defined_indexer != null) {
853                                 DefineIndexers (parent);
854
855                                 CustomAttributeBuilder cb = EmitDefaultMemberAttr (
856                                         parent, IndexerName, ModFlags, Location);
857                                 if (cb != null)
858                                         TypeBuilder.SetCustomAttribute (cb);
859                         }
860
861 #if CACHE
862                         if (TypeBuilder.BaseType != null)
863                                 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
864
865                         member_cache = new MemberCache (this);
866 #endif
867                         members_defined = true;
868                         return true;
869                 }
870
871
872                 //
873                 // In the case of Interfaces, there is nothing to do here
874                 //
875                 public override bool Define (TypeContainer parent)
876                 {
877                         return true;
878                 }
879
880                 /// <summary>
881                 ///   Applies all the attributes.
882                 /// </summary>
883                 public void Emit (TypeContainer tc)
884                 {
885                         if (OptAttributes != null) {
886                                 EmitContext ec = new EmitContext (tc, this, Location, null, null,
887                                                                   ModFlags, false);
888                                 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes);
889                         }
890
891                         // Now emit attributes for each interface member
892                         if (defined_method != null) {
893                                 foreach (InterfaceMethod im in defined_method) {
894                                         EmitContext ec = new EmitContext (tc, this, Location, null,
895                                                                           im.ReturnType.Type, ModFlags, false);
896   
897                                         MethodCore.LabelParameters (ec, im.Builder,
898                                                                     im.Parameters,
899                                                                     im.OptAttributes,
900                                                                     Location);
901                                         
902                                         if (im.OptAttributes != null)
903                                                 Attribute.ApplyAttributes (ec, im.Builder,
904                                                                            im, im.OptAttributes);
905                                         
906                                 }
907                         }
908
909                         if (defined_properties != null) {
910                                 foreach (InterfaceProperty ip in defined_properties) {
911                                         EmitContext ec = new EmitContext (tc, this, Location, null,
912                                                                           null, ModFlags, false);
913                                         
914                                         if (ip.OptAttributes != null)
915                                                 Attribute.ApplyAttributes (ec, ip.Builder, ip, ip.OptAttributes);
916
917                                         if (ip.GetAttributes != null)
918                                                 Attribute.ApplyAttributes (ec, ip.GetBuilder, ip, ip.GetAttributes);
919
920                                         if (ip.SetAttributes != null)
921                                                 Attribute.ApplyAttributes (ec, ip.SetBuilder, ip, ip.SetAttributes);
922                                 }
923                         }
924
925                         if (defined_events != null) {
926                                 foreach (InterfaceEvent ie in defined_events) {
927                                         EmitContext ec = new EmitContext (tc, this, Location, null,
928                                                                           null, ModFlags, false);
929                                         
930                                         if (ie.OptAttributes != null)
931                                                 Attribute.ApplyAttributes (ec, ie.Builder, ie, ie.OptAttributes);
932                                 }
933                         }
934
935                         if (defined_indexer != null) {
936                                 foreach (InterfaceIndexer ii in defined_indexer) {
937                                         EmitContext ec = new EmitContext (tc, this, Location, null,
938                                                                           null, ModFlags, false);
939
940                                         if (ii.OptAttributes != null)
941                                                 Attribute.ApplyAttributes (ec, ii.Builder, ii, ii.OptAttributes);
942                                         
943                                         if (ii.GetAttributes != null)
944                                                 Attribute.ApplyAttributes (ec, ii.GetBuilder, ii, ii.GetAttributes);
945                                         
946                                         if (ii.SetAttributes != null)
947                                                 Attribute.ApplyAttributes (ec, ii.SetBuilder, ii, ii.SetAttributes);
948                                 }
949                         }
950                 }
951
952                 public static CustomAttributeBuilder EmitDefaultMemberAttr (TypeContainer parent,
953                                                                             string name,
954                                                                             int flags,
955                                                                             Location loc)
956                 {
957                         EmitContext ec = new EmitContext (parent, loc, null, null, flags);
958
959                         Expression ml = Expression.MemberLookup (ec, TypeManager.default_member_type,
960                                                                  ".ctor", MemberTypes.Constructor,
961                                                                  BindingFlags.Public | BindingFlags.Instance,
962                                                                  Location.Null);
963                         
964                         MethodGroupExpr mg = (MethodGroupExpr) ml;
965
966                         MethodBase constructor = mg.Methods [0];
967
968                         string [] vals = { name };
969
970                         CustomAttributeBuilder cb = null;
971                         try {
972                                 cb = new CustomAttributeBuilder ((ConstructorInfo) constructor, vals);
973                         } catch {
974                                 Report.Warning (-100, "Can not set the indexer default member attribute");
975                         }
976
977                         return cb;
978                 }
979
980                 //
981                 // IMemberContainer
982                 //
983
984                 string IMemberContainer.Name {
985                         get {
986                                 return Name;
987                         }
988                 }
989
990                 Type IMemberContainer.Type {
991                         get {
992                                 return TypeBuilder;
993                         }
994                 }
995
996                 IMemberContainer IMemberContainer.Parent {
997                         get {
998                                 return parent_container;
999                         }
1000                 }
1001
1002                 MemberCache IMemberContainer.MemberCache {
1003                         get {
1004                                 return member_cache;
1005                         }
1006                 }
1007
1008                 bool IMemberContainer.IsInterface {
1009                         get {
1010                                 return true;
1011                         }
1012                 }
1013
1014                 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
1015                 {
1016                         // Interfaces only contain instance members.
1017                         if ((bf & BindingFlags.Instance) == 0)
1018                                 return MemberList.Empty;
1019                         if ((bf & BindingFlags.Public) == 0)
1020                                 return MemberList.Empty;
1021
1022                         ArrayList members = new ArrayList ();
1023
1024                         if ((mt & MemberTypes.Method) != 0)
1025                                 members.AddRange (method_builders);
1026
1027                         if ((mt & MemberTypes.Property) != 0)
1028                                 members.AddRange (property_builders);
1029
1030                         if ((mt & MemberTypes.Event) != 0)
1031                                 members.AddRange (event_builders);
1032
1033                         return new MemberList (members);
1034                 }
1035         }
1036
1037         public class InterfaceMemberBase {
1038                 public readonly string Name;
1039                 public readonly bool IsNew;
1040                 public Attributes OptAttributes;
1041                 
1042                 public InterfaceMemberBase (string name, bool is_new, Attributes attrs)
1043                 {
1044                         Name = name;
1045                         IsNew = is_new;
1046                         OptAttributes = attrs;
1047                 }
1048         }
1049         
1050         public class InterfaceProperty : InterfaceMemberBase {
1051                 public readonly bool HasSet;
1052                 public readonly bool HasGet;
1053                 public readonly Location Location;
1054                 public Expression Type;
1055                 public PropertyBuilder Builder;
1056                 public MethodBuilder GetBuilder;
1057                 public MethodBuilder SetBuilder;
1058                 public Attributes GetAttributes;
1059                 public Attributes SetAttributes;
1060                 
1061                 public InterfaceProperty (Expression type, string name,
1062                                           bool is_new, bool has_get, bool has_set,
1063                                           Attributes prop_attrs, Attributes get_attrs,
1064                                           Attributes set_attrs, Location loc)
1065                         : base (name, is_new, prop_attrs)
1066                 {
1067                         Type = type;
1068                         HasGet = has_get;
1069                         HasSet = has_set;
1070                         GetAttributes = get_attrs;
1071                         SetAttributes = set_attrs;
1072                         Location = loc;
1073                 }
1074         }
1075
1076         public class InterfaceEvent : InterfaceMemberBase {
1077                 public readonly Location Location;
1078                 public Expression Type;
1079                 public MyEventBuilder Builder;
1080                 
1081                 public InterfaceEvent (Expression type, string name, bool is_new, Attributes attrs,
1082                                        Location loc)
1083                         : base (name, is_new, attrs)
1084                 {
1085                         Type = type;
1086                         Location = loc;
1087                 }
1088         }
1089         
1090         public class InterfaceMethod : InterfaceMemberBase {
1091                 public Expression ReturnType;
1092                 public readonly Parameters Parameters;
1093                 public readonly Location Location;
1094                 public MethodBuilder Builder;
1095                 
1096                 public InterfaceMethod (Expression return_type, string name, bool is_new, Parameters args,
1097                                         Attributes attrs, Location l)
1098                         : base (name, is_new, attrs)
1099                 {
1100                         this.ReturnType = return_type;
1101                         this.Parameters = args;
1102                         Location = l;
1103                 }
1104
1105                 /// <summary>
1106                 ///   Returns the signature for this interface method
1107                 /// </summary>
1108                 public string GetSignature (DeclSpace ds)
1109                 {
1110                         ReturnType = ds.ResolveTypeExpr (ReturnType, false, Location);
1111                         if (ReturnType == null)
1112                                 return null;
1113                         
1114                         Type ret = ReturnType.Type;
1115                         string args = Parameters.GetSignature (ds);
1116
1117                         if ((ret == null) || (args == null))
1118                                 return null;
1119                         
1120                         return (IsNew ? "new-" : "") + ret.FullName + "(" + args + ")";
1121                 }
1122
1123                 public Type [] ParameterTypes (DeclSpace ds)
1124                 {
1125                         return Parameters.GetParameterInfo (ds);
1126                 }
1127         }
1128
1129         public class InterfaceIndexer : InterfaceMemberBase {
1130                 public readonly bool HasGet, HasSet;
1131                 public readonly Parameters Parameters;
1132                 public readonly Location Location;
1133                 public Expression Type;
1134                 public PropertyBuilder Builder;
1135                 public MethodBuilder GetBuilder;
1136                 public MethodBuilder SetBuilder;
1137                 public Attributes GetAttributes;
1138                 public Attributes SetAttributes;
1139                 
1140                 public InterfaceIndexer (Expression type, Parameters args, bool do_get, bool do_set,
1141                                          bool is_new, Attributes attrs,
1142                                          Attributes get_attrs, Attributes set_attrs,
1143                                          Location loc)
1144                         : base ("", is_new, attrs)
1145                 {
1146                         Type = type;
1147                         Parameters = args;
1148                         HasGet = do_get;
1149                         HasSet = do_set;
1150                         GetAttributes = get_attrs;
1151                         SetAttributes = set_attrs;
1152                         Location = loc;
1153                 }
1154
1155                 public Type [] ParameterTypes (DeclSpace ds)
1156                 {
1157                         return Parameters.GetParameterInfo (ds);
1158                 }
1159         }
1160 }