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