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