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