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