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