b94dc9caa5cef65050aa7c2e131e74bd0bdf8fd4
[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 {
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 MemberInfo [] 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                                 MemberInfo [] parent_mi;
263                                 
264                                 parent_mi = TypeContainer.FindMembers (
265                                         TypeBuilder.BaseType, mt, bf, filter, criteria);
266
267                                 if (parent_mi != null)
268                                         members.AddRange (parent_mi);
269                         }
270                         
271                         // The rest of the cases, if any, are unhandled at present.
272
273                         int count = members.Count;
274
275                         if (count > 0) {
276                                 MemberInfo [] mi = new MemberInfo [count];
277                                 members.CopyTo (mi, 0);
278                                 return mi;
279                         }
280
281                         return null;
282                 }
283
284                 //
285                 // Populates the methods in the interface
286                 //
287                 void PopulateMethod (TypeContainer parent, DeclSpace decl_space, InterfaceMethod im)
288                 {
289                         Type return_type = this.ResolveType (im.ReturnType, false, im.Location);
290                         Type [] arg_types = im.ParameterTypes (this);
291                         MethodBuilder mb;
292                         Parameter [] p;
293                         int i;
294
295                         if (return_type == null)
296                                 return;
297
298                         if (return_type.IsPointer && !UnsafeOK (this))
299                                 return;
300
301                         foreach (Type t in arg_types){
302
303                                 if (t == null)
304                                         return;
305                                 
306                                 if (t.IsPointer && !UnsafeOK (this))
307                                         return;
308                         }
309                         
310                         //
311                         // Create the method
312                         //
313                         mb = TypeBuilder.DefineMethod (
314                                 im.Name, interface_method_attributes,
315                                 return_type, arg_types);
316
317                         InternalParameters ip = new InternalParameters (arg_types, im.Parameters);
318                         
319                         if (!RegisterMethod (mb, ip, arg_types)) {
320                                 Error111 (im);
321                                 return;
322                         }
323
324                         //
325                         // Define each type attribute (in/out/ref) and
326                         // the argument names.
327                         //
328                         p = im.Parameters.FixedParameters;
329                         if (p != null){
330                                 for (i = 0; i < p.Length; i++)
331                                         mb.DefineParameter (i + 1, p [i].Attributes, p [i].Name);
332
333                                 if (i != arg_types.Length)
334                                         Console.WriteLine ("Implement the type definition for params");
335                         }
336
337                         EmitContext ec = new EmitContext (parent, decl_space, Location, null,
338                                                           return_type, ModFlags, false);
339
340                         if (im.OptAttributes != null)
341                                 Attribute.ApplyAttributes (ec, mb, im, im.OptAttributes, Location);
342                 }
343
344                 //
345                 // Populates the properties in the interface
346                 //
347                 void PopulateProperty (TypeContainer parent, DeclSpace decl_space, InterfaceProperty ip)
348                 {
349                         PropertyBuilder pb;
350                         MethodBuilder get = null, set = null;
351                         ip.Type = this.ResolveTypeExpr (ip.Type, false, ip.Location);
352                         Type prop_type = ip.Type.Type;
353                         Type [] setter_args = new Type [1];
354
355                         if (prop_type == null)
356                                 return;
357
358                         if (prop_type.IsPointer && !UnsafeOK (this))
359                                 return;
360                         
361                         setter_args [0] = prop_type;
362
363                         //
364                         // FIXME: properties are missing the following
365                         // flags: hidebysig newslot specialname
366                         //
367                         pb = TypeBuilder.DefineProperty (
368                                 ip.Name, PropertyAttributes.None,
369                                 prop_type, null);
370
371                         if (ip.HasGet){
372                                 get = TypeBuilder.DefineMethod (
373                                         "get_" + ip.Name, property_attributes ,
374                                         prop_type, null);
375
376                                 //
377                                 // HACK because System.Reflection.Emit is lame
378                                 //
379                                 Type [] null_types = null;
380                                 InternalParameters inp = new InternalParameters
381                                         (null_types, Parameters.GetEmptyReadOnlyParameters ());
382                                 
383                                 if (!RegisterMethod (get, inp, null)) {
384                                         Error111 (ip);
385                                         return;
386                                 }
387                                 
388                                 pb.SetGetMethod (get);
389                         }
390
391                         if (ip.HasSet){
392                                 setter_args [0] = prop_type;
393
394                                 set = TypeBuilder.DefineMethod (
395                                         "set_" + ip.Name, property_attributes,
396                                         TypeManager.void_type, setter_args);
397
398                                 set.DefineParameter (1, ParameterAttributes.None, "value");
399                                 pb.SetSetMethod (set);
400
401                                 //
402                                 // HACK because System.Reflection.Emit is lame
403                                 //
404                                 Parameter [] parms = new Parameter [1];
405                                 parms [0] = new Parameter (ip.Type, "value", Parameter.Modifier.NONE, null);
406                                 InternalParameters ipp = new InternalParameters (
407                                         this, new Parameters (parms, null, Location.Null));
408                                         
409                                 if (!RegisterMethod (set, ipp, setter_args)) {
410                                         Error111 (ip);
411                                         return;
412                                 }
413                         }
414
415                         EmitContext ec = new EmitContext (parent, decl_space, Location, null,
416                                                           null, ModFlags, false);
417
418                         if (ip.OptAttributes != null)
419                                 Attribute.ApplyAttributes (ec, pb, ip, ip.OptAttributes, Location);
420
421                         TypeManager.RegisterProperty (pb, get, set);
422                         property_builders.Add (pb);
423                 }
424
425                 //
426                 // Populates the events in the interface
427                 //
428                 void PopulateEvent (TypeContainer parent, DeclSpace decl_space, InterfaceEvent ie)
429                 {
430                         //
431                         // FIXME: We need to do this after delegates have been
432                         // declared or we declare them recursively.
433                         //
434                         MyEventBuilder eb;
435                         MethodBuilder add = null, remove = null;
436                         ie.Type = this.ResolveTypeExpr (ie.Type, false, ie.Location);
437                         Type event_type = ie.Type.Type;
438
439                         if (event_type == null)
440                                 return;
441
442                         if (event_type.IsPointer && !UnsafeOK (this))
443                                 return;
444
445                         Type [] parameters = new Type [1];
446                         parameters [0] = event_type;
447
448                         eb = new MyEventBuilder (TypeBuilder, ie.Name,
449                                                  EventAttributes.None, event_type);
450
451                         //
452                         // Now define the accessors
453                         //
454                         string add_name = "add_" + ie.Name;
455                         
456                         add = TypeBuilder.DefineMethod (
457                                 add_name, property_attributes, null, parameters);
458                         add.DefineParameter (1, ParameterAttributes.None, "value");
459                         eb.SetAddOnMethod (add);
460
461                         string remove_name = "remove_" + ie.Name;
462                         remove = TypeBuilder.DefineMethod (
463                                 remove_name, property_attributes, null, parameters);
464                         remove.DefineParameter (1, ParameterAttributes.None, "value");
465                         eb.SetRemoveOnMethod (remove);
466
467                         Parameter [] parms = new Parameter [1];
468                         parms [0] = new Parameter (ie.Type, "value", Parameter.Modifier.NONE, null);
469                         InternalParameters ip = new InternalParameters (
470                                 this, new Parameters (parms, null, Location.Null));
471
472                         if (!RegisterMethod (add, ip, parameters)) {
473                                 Error111 (ie);
474                                 return;
475                         }
476                         
477                         if (!RegisterMethod (remove, ip, parameters)) {
478                                 Error111 (ie);
479                                 return;
480                         }
481
482                         EmitContext ec = new EmitContext (parent, decl_space, Location, null,
483                                                           null, ModFlags, false);
484
485
486                         if (ie.OptAttributes != null)
487                                 Attribute.ApplyAttributes (ec, eb, ie, ie.OptAttributes, Location);
488
489                         TypeManager.RegisterEvent (eb, add, remove);
490                         event_builders.Add (eb);
491                 }
492
493                 //
494                 // Populates the indexers in the interface
495                 //
496                 void PopulateIndexer (TypeContainer parent, DeclSpace decl_space, InterfaceIndexer ii)
497                 {
498                         PropertyBuilder pb;
499                         ii.Type = this.ResolveTypeExpr (ii.Type, false, ii.Location);
500                         Type prop_type = ii.Type.Type;
501                         Type [] arg_types = ii.ParameterTypes (this);
502                         Type [] value_arg_types;
503
504                         if (prop_type == null)
505                                 return;
506
507                         if (prop_type.IsPointer && !UnsafeOK (this))
508                                 return;
509                         
510                         //
511                         // Sets up the extra invisible `value' argument for setters.
512                         // 
513                         if (arg_types != null){
514                                 int count = arg_types.Length;
515                                 value_arg_types = new Type [count + 1];
516
517                                 arg_types.CopyTo (value_arg_types, 0);
518                                 value_arg_types [count] = prop_type;
519
520                                 foreach (Type t in arg_types){
521                                         if (t.IsPointer && !UnsafeOK (this))
522                                                 return;
523                                 }
524                         } else {
525                                 value_arg_types = new Type [1];
526
527                                 value_arg_types [1] = prop_type;
528                         }
529
530                         EmitContext ec = new EmitContext (parent, decl_space, Location, null,
531                                                           null, ModFlags, false);
532
533                         IndexerName = Attribute.ScanForIndexerName (ec, ii.OptAttributes);
534                         if (IndexerName == null)
535                                 IndexerName = "Item";
536                         
537                         pb = TypeBuilder.DefineProperty (
538                                 IndexerName, PropertyAttributes.None,
539                                 prop_type, arg_types);
540                         
541                         MethodBuilder set_item = null, get_item = null;
542                         if (ii.HasGet){
543                                 Parameter [] p = ii.Parameters.FixedParameters;
544                                 
545                                 get_item = TypeBuilder.DefineMethod (
546                                         "get_" + IndexerName, property_attributes,
547                                         prop_type, arg_types);
548                                 pb.SetGetMethod (get_item);
549                                 //
550                                 // HACK because System.Reflection.Emit is lame
551                                 //
552                                 InternalParameters ip = new InternalParameters (
553                                         arg_types, ii.Parameters);
554                                 
555                                 if (!RegisterMethod (get_item, ip, arg_types)) {
556                                         Error111 (ii);
557                                         return;
558                                 }
559
560                                 if (p != null){
561                                         for (int i = 0; i < p.Length; i++)
562                                                 get_item.DefineParameter (
563                                                         i + 1,
564                                                         p [i].Attributes, p [i].Name);
565                                 }
566                         }
567
568                         if (ii.HasSet){
569                                 Parameter [] p = ii.Parameters.FixedParameters;
570                                 Parameter [] pv;
571                                 int i = 0;
572                                 
573                                 pv = new Parameter [p.Length + 1];
574                                 p.CopyTo (pv, 0);
575                                 pv [p.Length] = new Parameter (ii.Type, "value", Parameter.Modifier.NONE, null);
576                                 Parameters value_params = new Parameters (pv, null, Location.Null);
577                                 value_params.GetParameterInfo (decl_space);
578                                 
579                                 set_item = TypeBuilder.DefineMethod (
580                                         "set_" + IndexerName, property_attributes,
581                                         TypeManager.void_type, value_arg_types);
582                                 pb.SetSetMethod (set_item);
583                                 //
584                                 // HACK because System.Reflection.Emit is lame
585                                 //
586                                 InternalParameters ip = new InternalParameters (
587                                         value_arg_types, value_params);
588                                 if (!RegisterMethod (set_item, ip, value_arg_types)) {
589                                         Error111 (ii);
590                                         return;
591                                 }
592
593                                 if (p != null){
594                                         for (; i < p.Length; i++)
595                                                 set_item.DefineParameter (
596                                                         i + 1,
597                                                         p [i].Attributes, p [i].Name);
598                                 }
599                                 
600                                 set_item.DefineParameter (i + 1, ParameterAttributes.None, "value");
601                         }
602
603                         if (ii.OptAttributes != null)
604                                 Attribute.ApplyAttributes (ec, pb, ii, ii.OptAttributes, Location);
605
606                         property_builders.Add (pb);
607                 }
608
609                 /// <summary>
610                 ///   Performs the semantic analysis for all the interface members
611                 ///   that were declared
612                 /// </summary>
613                 bool SemanticAnalysis ()
614                 {
615                         Hashtable methods = new Hashtable ();
616
617                         
618                         if (defined_method != null){
619                                 foreach (InterfaceMethod im in defined_method){
620                                         string sig = im.GetSignature (this);
621                                         
622                                         //
623                                         // If there was an undefined Type on the signatures
624                                         // 
625                                         if (sig == null)
626                                                 continue;
627                                         
628                                         if (methods [sig] != null){
629                                                 Error111 (im);
630                                                 return false;
631                                         }
632                                 }
633                         }
634
635                         //
636                         // FIXME: Here I should check i
637                         // 
638                         return true;
639                 }
640
641                 Type GetInterfaceTypeByName (string name)
642                 {
643                         Type t = FindType (name);
644
645                         if (t == null)
646                                 return null;
647                         
648                         if (t.IsInterface)
649                                 return t;
650                                 
651                         string cause;
652                         
653                         if (t.IsValueType)
654                                 cause = "is a struct";
655                         else if (t.IsClass) 
656                                 cause = "is a class";
657                         else
658                                 cause = "Should not happen.";
659                         
660                         Report.Error (527, Location, "`"+name+"' " + cause +
661                                       ", need an interface instead");
662                         
663                         return null;
664                 }
665                 
666                 //
667                 // Returns the list of interfaces that this interface implements
668                 // Or null if it does not implement any interface.
669                 //
670                 // Sets the error boolean accoringly.
671                 //
672                 Type [] GetInterfaceBases (out bool error)
673                 {
674                         Type [] tbases;
675                         int i;
676
677                         error = false;
678                         if (Bases == null)
679                                 return null;
680                         
681                         tbases = new Type [Bases.Count];
682                         i = 0;
683
684                         foreach (string name in Bases){
685                                 Type t;
686
687                                 t = GetInterfaceTypeByName (name);
688                                 if (t == null){
689                                         error = true;
690                                         return null;
691                                 }
692
693                                 if (!Parent.AsAccessible (t, ModFlags))
694                                         Report.Error (61, Location,
695                                                       "Inconsistent accessibility: base interface `" +
696                                                       TypeManager.CSharpName (t) + "' is less " +
697                                                       "accessible than interface `" +
698                                                       Name + "'");
699
700                                 tbases [i++] = t;
701                         }
702                         
703                         return TypeManager.ExpandInterfaces (tbases);
704                 }
705                 
706                 //
707                 // <summary>
708                 //  Defines the Interface in the appropriate ModuleBuilder or TypeBuilder
709                 // </summary>
710                 //
711                 // TODO:
712                 //   Rework the way we recurse, because for recursive
713                 //   definitions of interfaces (A:B and B:A) we report the
714                 //   error twice, rather than once.  
715                 
716                 public override TypeBuilder DefineType ()
717                 {
718                         Type [] ifaces;
719                         bool error;
720
721                         if (TypeBuilder != null)
722                                 return TypeBuilder;
723                         
724                         if (InTransit)
725                                 return null;
726                         
727                         InTransit = true;
728                         
729                         ifaces = GetInterfaceBases (out error);
730
731                         if (error)
732                                 return null;
733
734                         if (IsTopLevel) {
735                                 ModuleBuilder builder = CodeGen.ModuleBuilder;
736
737                                 TypeBuilder = builder.DefineType (
738                                         Name,
739                                         InterfaceAttr,
740                                         (Type)null,   // Parent Type
741                                         ifaces);
742                                 RootContext.RegisterOrder (this);
743                         } else {
744                                 TypeBuilder builder = Parent.TypeBuilder;
745
746                                 TypeBuilder = builder.DefineNestedType (
747                                         Basename,
748                                         InterfaceAttr,
749                                         (Type) null, //parent type
750                                         ifaces);
751
752                                 TypeContainer tc = TypeManager.LookupTypeContainer (builder);
753                                 tc.RegisterOrder (this);
754                         }
755
756                         TypeManager.AddUserInterface (Name, TypeBuilder, this, ifaces);
757                         InTransit = false;
758                         
759                         return TypeBuilder;
760                 }
761
762                 //
763                 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
764                 // interface is consistent.  Either it is `Item' or it is the name defined by all the
765                 // indexers with the `IndexerName' attribute.
766                 //
767                 // Turns out that the IndexerNameAttribute is applied to each indexer,
768                 // but it is never emitted, instead a DefaultName attribute is attached
769                 // to the interface
770                 //
771                 void DefineIndexers (TypeContainer parent)
772                 {
773                         string interface_indexer_name = null;
774
775                         foreach (InterfaceIndexer ii in defined_indexer){
776
777                                 PopulateIndexer (parent, this, ii);
778
779                                 if (interface_indexer_name == null){
780                                         interface_indexer_name = IndexerName;
781                                         continue;
782                                 }
783                                 
784                                 if (IndexerName == interface_indexer_name)
785                                         continue;
786                                 
787                                 Report.Error (
788                                         668, "Two indexers have different names, " +
789                                         " you should use the same name for all your indexers");
790                         }
791                         if (interface_indexer_name == null)
792                                 interface_indexer_name = "Item";
793                         IndexerName = interface_indexer_name;
794                 }
795                 
796                 /// <summary>
797                 ///   Performs semantic analysis, and then generates the IL interfaces
798                 /// </summary>
799                 public override bool Define (TypeContainer parent)
800                 {
801                         if (!SemanticAnalysis ())
802                                 return false;
803
804                         if (defined_method != null){
805                                 foreach (InterfaceMethod im in defined_method)
806                                         PopulateMethod (parent, this, im);
807                         }
808
809                         if (defined_properties != null){
810                                 foreach (InterfaceProperty ip in defined_properties)
811                                         PopulateProperty (parent, this, ip);
812                         }
813
814                         if (defined_events != null)
815                                 foreach (InterfaceEvent ie in defined_events)
816                                         PopulateEvent (parent, this, ie);
817
818                         if (defined_indexer != null) {
819                                 DefineIndexers (parent);
820
821                                 CustomAttributeBuilder cb = EmitDefaultMemberAttr (
822                                         parent, IndexerName, ModFlags, Location);
823                                 if (cb != null)
824                                         TypeBuilder.SetCustomAttribute (cb);
825                         }
826                         
827                         return true;
828                 }
829
830                 public static CustomAttributeBuilder EmitDefaultMemberAttr (TypeContainer parent,
831                                                                             string name,
832                                                                             int flags,
833                                                                             Location loc)
834                 {
835                         EmitContext ec = new EmitContext (parent, loc, null, null, flags);
836
837                         Expression ml = Expression.MemberLookup (ec, TypeManager.default_member_type,
838                                                                  ".ctor", MemberTypes.Constructor,
839                                                                  BindingFlags.Public | BindingFlags.Instance,
840                                                                  Location.Null);
841                         
842                         if (!(ml is MethodGroupExpr)) {
843                                 Console.WriteLine ("Internal error !!!!");
844                                 return null;
845                         }
846                         
847                         MethodGroupExpr mg = (MethodGroupExpr) ml;
848
849                         MethodBase constructor = mg.Methods [0];
850
851                         string [] vals = { name };
852
853                         CustomAttributeBuilder cb = null;
854                         try {
855                                 cb = new CustomAttributeBuilder ((ConstructorInfo) constructor, vals);
856                         } catch {
857                                 Report.Warning (-100, "Can not set the indexer default member attribute");
858                         }
859
860                         return cb;
861                 }
862
863         }
864
865         public class InterfaceMemberBase {
866                 public readonly string Name;
867                 public readonly bool IsNew;
868                 public Attributes OptAttributes;
869                 
870                 public InterfaceMemberBase (string name, bool is_new, Attributes attrs)
871                 {
872                         Name = name;
873                         IsNew = is_new;
874                         OptAttributes = attrs;
875                 }
876         }
877         
878         public class InterfaceProperty : InterfaceMemberBase {
879                 public readonly bool HasSet;
880                 public readonly bool HasGet;
881                 public readonly Location Location;
882                 public Expression Type;
883                 
884                 public InterfaceProperty (Expression type, string name,
885                                           bool is_new, bool has_get, bool has_set,
886                                           Attributes attrs, Location loc)
887                         : base (name, is_new, attrs)
888                 {
889                         Type = type;
890                         HasGet = has_get;
891                         HasSet = has_set;
892                         Location = loc;
893                 }
894         }
895
896         public class InterfaceEvent : InterfaceMemberBase {
897                 public readonly Location Location;
898                 public Expression Type;
899                 
900                 public InterfaceEvent (Expression type, string name, bool is_new, Attributes attrs,
901                                        Location loc)
902                         : base (name, is_new, attrs)
903                 {
904                         Type = type;
905                         Location = loc;
906                 }
907         }
908         
909         public class InterfaceMethod : InterfaceMemberBase {
910                 public readonly Expression ReturnType;
911                 public readonly Parameters Parameters;
912                 public readonly Location Location;
913                 
914                 public InterfaceMethod (Expression return_type, string name, bool is_new, Parameters args,
915                                         Attributes attrs, Location l)
916                         : base (name, is_new, attrs)
917                 {
918                         this.ReturnType = return_type;
919                         this.Parameters = args;
920                         Location = l;
921                 }
922
923                 /// <summary>
924                 ///   Returns the signature for this interface method
925                 /// </summary>
926                 public string GetSignature (DeclSpace ds)
927                 {
928                         Type ret = ds.ResolveType (ReturnType, false, Location);
929                         string args = Parameters.GetSignature (ds);
930
931                         if ((ret == null) || (args == null))
932                                 return null;
933                         
934                         return (IsNew ? "new-" : "") + ret.FullName + "(" + args + ")";
935                 }
936
937                 public Type [] ParameterTypes (DeclSpace ds)
938                 {
939                         return Parameters.GetParameterInfo (ds);
940                 }
941         }
942
943         public class InterfaceIndexer : InterfaceMemberBase {
944                 public readonly bool HasGet, HasSet;
945                 public readonly Parameters Parameters;
946                 public readonly Location Location;
947                 public Expression Type;
948                 
949                 public InterfaceIndexer (Expression type, Parameters args, bool do_get, bool do_set,
950                                          bool is_new, Attributes attrs, Location loc)
951                         : base ("", is_new, attrs)
952                 {
953                         Type = type;
954                         Parameters = args;
955                         HasGet = do_get;
956                         HasSet = do_set;
957                         Location = loc;
958                 }
959
960                 public Type [] ParameterTypes (DeclSpace ds)
961                 {
962                         return Parameters.GetParameterInfo (ds);
963                 }
964         }
965 }