Add new test
[mono.git] / mcs / mcs / support.cs
1 //
2 // support.cs: Support routines to work around the fact that System.Reflection.Emit
3 // can not introspect types that are being constructed
4 //
5 // Author:
6 //   Miguel de Icaza (miguel@ximian.com)
7 //
8 // (C) 2001 Ximian, Inc (http://www.ximian.com)
9 //
10
11 using System;
12 using System.Text;
13 using System.Reflection;
14 using System.Collections;
15 using System.Reflection.Emit;
16
17 namespace Mono.CSharp {
18
19         public interface ParameterData {
20                 Type ParameterType (int pos);
21                 int  Count { get; }
22                 string ParameterDesc (int pos);
23                 Parameter.Modifier ParameterModifier (int pos);
24         }
25
26         public class ReflectionParameters : ParameterData {
27                 ParameterInfo [] pi;
28                 bool last_arg_is_params;
29                 
30                 public ReflectionParameters (ParameterInfo [] pi)
31                 {
32                         object [] a;
33                         
34                         this.pi = pi;
35
36                         int count = pi.Length-1;
37
38                         if (count > 0) {
39                                 a = pi [count].GetCustomAttributes (TypeManager.param_array_type, false);
40
41                                 if (a != null)
42                                         if (a.Length != 0)
43                                                 last_arg_is_params = true;
44                         } 
45                 }
46                        
47                 public Type ParameterType (int pos)
48                 {
49                         if (last_arg_is_params && pos >= pi.Length - 1)
50                                 return pi [pi.Length -1].ParameterType;
51                         else 
52                                 return pi [pos].ParameterType;
53                 }
54
55                 public string ParameterDesc (int pos)
56                 {
57                         StringBuilder sb = new StringBuilder ();
58
59                         if (pi [pos].IsOut)
60                                 sb.Append ("out ");
61
62                         if (pi [pos].IsIn)
63                                 sb.Append ("in ");
64
65                         if (pos >= pi.Length - 1 && last_arg_is_params)
66                                 sb.Append ("params ");
67                         
68                         sb.Append (TypeManager.CSharpName (ParameterType (pos)));
69
70                         return sb.ToString ();
71                         
72                 }
73
74                 public Parameter.Modifier ParameterModifier (int pos)
75                 {
76                         if (pos >= pi.Length - 1) 
77                                 if (last_arg_is_params)
78                                         return Parameter.Modifier.PARAMS;
79
80                         Type t = pi [pos].ParameterType;
81                         if (t.IsByRef)
82                                 return Parameter.Modifier.OUT;
83                         
84                         return Parameter.Modifier.NONE;
85                 }
86
87                 public int Count {
88                         get {
89                                 return pi.Length;
90                         }
91                 }
92                 
93         }
94
95         public class InternalParameters : ParameterData {
96                 Type [] param_types;
97
98                 Parameters parameters;
99                 
100                 public InternalParameters (Type [] param_types, Parameters parameters)
101                 {
102                         this.param_types = param_types;
103                         this.parameters = parameters;
104                 }
105
106                 public InternalParameters (TypeContainer tc, Parameters parameters)
107                         : this (parameters.GetParameterInfo (tc), parameters)
108                 {
109                 }
110
111                 public int Count {
112                         get {
113                                 if (param_types == null)
114                                         return 0;
115
116                                 return param_types.Length;
117                         }
118                 }
119
120                 public Type ParameterType (int pos)
121                 {
122                         if (param_types == null)
123                                 return null;
124
125                         Parameter [] fixed_pars = parameters.FixedParameters;
126                         if (fixed_pars != null){
127                                 int len = fixed_pars.Length;
128                                 if (pos < len)
129                                         return parameters.FixedParameters [pos].ParameterType;
130                                 else 
131                                         return parameters.ArrayParameter.ParameterType;
132                         } else
133                                 return parameters.ArrayParameter.ParameterType;
134                 }
135
136                 public string ParameterDesc (int pos)
137                 {
138                         string tmp = null;
139                         Parameter p;
140
141                         if (pos >= parameters.FixedParameters.Length)
142                                 p = parameters.ArrayParameter;
143                         else
144                                 p = parameters.FixedParameters [pos];
145                         
146                         if (p.ModFlags == Parameter.Modifier.REF)
147                                 tmp = "ref ";
148                         else if (p.ModFlags == Parameter.Modifier.OUT)
149                                 tmp = "out ";
150                         else if (p.ModFlags == Parameter.Modifier.PARAMS)
151                                 tmp = "params ";
152
153                         Type t = ParameterType (pos);
154
155                         return tmp + TypeManager.CSharpName (t);
156                 }
157
158                 public Parameter.Modifier ParameterModifier (int pos)
159                 {
160                         if (parameters.FixedParameters == null)
161                                 return parameters.ArrayParameter.ModFlags;
162                         
163                         if (pos >= parameters.FixedParameters.Length)
164                                 return parameters.ArrayParameter.ModFlags;
165                         else {
166                                 Parameter.Modifier m = parameters.FixedParameters [pos].ModFlags;
167
168                                 //
169                                 // We use a return value of "OUT" for "reference" parameters.
170                                 // both out and ref flags in the source map to reference parameters.
171                                 //
172                                 if (m == Parameter.Modifier.OUT || m == Parameter.Modifier.REF)
173                                         return Parameter.Modifier.OUT;
174                                 
175                                 return Parameter.Modifier.NONE;
176                         }
177                 }
178                 
179         }
180
181         class PtrHashtable : Hashtable {
182                 class PtrComparer : IComparer {
183                         public int Compare (object x, object y)
184                         {
185                                 if (x == y)
186                                         return 0;
187                                 else
188                                         return 1;
189                         }
190                 }
191                 
192                 public PtrHashtable ()
193                 {
194                         comparer = new PtrComparer ();
195                 }
196         }
197
198         //
199         // Compares member infos based on their name and
200         // also allows one argument to be a string
201         //
202         class MemberInfoCompare : IComparer {
203
204                 public int Compare (object a, object b)
205                 {
206                         if (a == null || b == null){
207                                 Console.WriteLine ("Invalid information passed");
208                                 throw new Exception ();
209                         }
210                         
211                         if (a is string)
212                                 return String.Compare ((string) a, ((MemberInfo)b).Name);
213
214                         if (b is string)
215                                 return String.Compare (((MemberInfo)a).Name, (string) b);
216
217                         return String.Compare (((MemberInfo)a).Name, ((MemberInfo)b).Name);
218                 }
219         }
220
221         struct Pair {
222                 public object First;
223                 public object Second;
224                 
225                 public Pair (object f, object s)
226                 {
227                         First = f;
228                         Second = s;
229                 }
230         }
231 }