[runtime] Overwrite stacktrace for exception on re-throw. Fixes #1856.
[mono.git] / mcs / class / System / System.CodeDom / CodeTypeReference.cs
1 //
2 // System.CodeDom CodeTypeReferenceExpression Class implementation
3 //
4 // Author:
5 //   Daniel Stodden (stodden@in.tum.de)
6 //   Marek Safar (marek.safar@seznam.cz)
7 //
8 // (C) 2001 Ximian, Inc.
9 //
10
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 using System.Runtime.InteropServices;
33 using System.Text;
34
35 namespace System.CodeDom
36 {
37         [Serializable]
38         [ClassInterface(ClassInterfaceType.AutoDispatch)]
39         [ComVisible(true)]
40         public class CodeTypeReference : CodeObject
41         {
42                 private string baseType;
43                 private CodeTypeReference arrayElementType;
44                 private int arrayRank;
45                 private bool isInterface;
46                 //bool needsFixup;
47
48                 CodeTypeReferenceCollection typeArguments;
49                 CodeTypeReferenceOptions referenceOptions;
50
51                 //
52                 // Constructors
53                 //
54
55                 public CodeTypeReference ()
56                 {
57                 }
58
59                 [MonoTODO("We should parse basetype from right to left in 2.0 profile.")]
60                 public CodeTypeReference (string baseType)
61                 {
62                         Parse (baseType);
63                 }
64
65                 [MonoTODO("We should parse basetype from right to left in 2.0 profile.")]
66                 public CodeTypeReference (Type baseType)
67                 {
68                         if (baseType == null) {
69                                 throw new ArgumentNullException ("baseType");
70                         }
71
72                         if (baseType.IsGenericParameter) {
73                                 this.baseType = baseType.Name;
74                                 this.referenceOptions = CodeTypeReferenceOptions.GenericTypeParameter;
75                         }
76                         else if (baseType.IsGenericTypeDefinition)
77                                 this.baseType = baseType.FullName;
78                         else if (baseType.IsGenericType) {
79                                 this.baseType = baseType.GetGenericTypeDefinition ().FullName;
80                                 foreach (Type arg in baseType.GetGenericArguments ()) {
81                                         if (arg.IsGenericParameter)
82                                                 TypeArguments.Add (new CodeTypeReference (new CodeTypeParameter (arg.Name)));
83                                         else
84                                                 TypeArguments.Add (new CodeTypeReference (arg));
85                                 }
86                         }
87                         else if (baseType.IsArray) {
88                                 this.arrayRank = baseType.GetArrayRank ();
89                                 this.arrayElementType = new CodeTypeReference (baseType.GetElementType ());
90                                 this.baseType = arrayElementType.BaseType;
91                         } else {
92                                 Parse (baseType.FullName);
93                         }
94                         this.isInterface = baseType.IsInterface;
95                 }
96
97                 public CodeTypeReference( CodeTypeReference arrayElementType, int arrayRank )
98                 {
99                         this.baseType = null;
100                         this.arrayRank = arrayRank;
101                         this.arrayElementType = arrayElementType;
102                 }
103
104                 [MonoTODO("We should parse basetype from right to left in 2.0 profile.")]
105                 public CodeTypeReference( string baseType, int arrayRank )
106                         : this (new CodeTypeReference (baseType), arrayRank)
107                 {
108                 }
109
110                 public CodeTypeReference( CodeTypeParameter typeParameter ) :
111                         this (typeParameter.Name)
112                 {
113                         this.referenceOptions = CodeTypeReferenceOptions.GenericTypeParameter;
114                 }
115
116                 public CodeTypeReference( string typeName, CodeTypeReferenceOptions referenceOptions ) :
117                         this (typeName)
118                 {
119                         this.referenceOptions = referenceOptions;
120                 }
121
122                 public CodeTypeReference( Type type, CodeTypeReferenceOptions referenceOptions ) :
123                         this (type)
124                 {
125                         this.referenceOptions = referenceOptions;
126                 }
127
128                 public CodeTypeReference( string typeName, params CodeTypeReference[] typeArguments ) :
129                         this (typeName)
130                 {
131                         TypeArguments.AddRange (typeArguments);
132                         if (this.baseType.IndexOf ('`') < 0)
133                                 this.baseType += "`" + TypeArguments.Count;
134                 }
135
136                 //
137                 // Properties
138                 //
139
140                 public CodeTypeReference ArrayElementType
141                 {
142                         get {
143                                 return arrayElementType;
144                         }
145                         set {
146                                 arrayElementType = value;
147                         }
148                 }
149                 
150                 public int ArrayRank {
151                         get {
152                                 return arrayRank;
153                         }
154                         set {
155                                 arrayRank = value;
156                         }
157                 }
158
159                 public string BaseType {
160                         get {
161                                 if (arrayElementType != null && arrayRank > 0) {
162                                         return arrayElementType.BaseType;
163                                 }
164
165                                 if (baseType == null)
166                                         return String.Empty;
167
168                                 return baseType;
169                         }
170                         set {
171                                 baseType = value;
172                         }
173                 }
174
175                 internal bool IsInterface {
176                         get { return isInterface; }
177                 }
178
179                 private void Parse (string baseType)
180                 {
181                         if (baseType == null || baseType.Length == 0) {
182                                 this.baseType = typeof (void).FullName;
183                                 return;
184                         }
185
186                         int array_start = baseType.IndexOf ('[');
187                         if (array_start == -1) {
188                                 this.baseType = baseType;
189                                 return;
190                         }
191
192                         int array_end = baseType.LastIndexOf (']');
193                         if (array_end < array_start) {
194                                 this.baseType = baseType;
195                                 return;
196                         }
197
198                         int lastAngle = baseType.LastIndexOf ('>');
199                         if (lastAngle != -1 && lastAngle > array_end) {
200                                 this.baseType = baseType;
201                                 return;
202                         }
203                         
204                         string[] args = baseType.Substring (array_start + 1, array_end - array_start - 1).Split (',');
205
206                         if ((array_end - array_start) != args.Length) {
207                                 this.baseType = baseType.Substring (0, array_start);
208                                 int escapeCount = 0;
209                                 int scanPos = array_start;
210                                 StringBuilder tb = new StringBuilder();
211                                 while (scanPos < baseType.Length) {
212                                         char currentChar = baseType[scanPos];
213                                         
214                                         switch (currentChar) {
215                                                 case '[':
216                                                         if (escapeCount > 1 && tb.Length > 0) {
217                                                                 tb.Append (currentChar);
218                                                         }
219                                                         escapeCount++;
220                                                         break;
221                                                 case ']':
222                                                         escapeCount--;
223                                                         if (escapeCount > 1 && tb.Length > 0) {
224                                                                 tb.Append (currentChar);
225                                                         }
226
227                                                         if (tb.Length != 0 && (escapeCount % 2) == 0) {
228                                                                 TypeArguments.Add (tb.ToString ());
229                                                                 tb.Length = 0;
230                                                         }
231                                                         break;
232                                                 case ',':
233                                                         if (escapeCount > 1) {
234                                                                 // skip anything after the type name until we 
235                                                                 // reach the next separator
236                                                                 while (scanPos + 1 < baseType.Length) {
237                                                                         if (baseType[scanPos + 1] == ']') {
238                                                                                 break;
239                                                                         }
240                                                                         scanPos++;
241                                                                 }
242                                                         } else if (tb.Length > 0) {
243                                                                 CodeTypeReference typeArg = new CodeTypeReference (tb.ToString ());
244                                                                 TypeArguments.Add (typeArg);
245                                                                 tb.Length = 0;
246                                                         }
247                                                         break;
248                                                 default:
249                                                         tb.Append (currentChar);
250                                                         break;
251                                         }
252                                         scanPos++;
253                                 }
254                         } else {
255                                 arrayElementType = new CodeTypeReference (baseType.Substring (0, array_start));
256                                 arrayRank = args.Length;
257                         }
258                 }
259
260                 [ComVisible (false)]
261                 public CodeTypeReferenceOptions Options {
262                         get {
263                                 return referenceOptions;
264                         }
265                         set {
266                                 referenceOptions = value;
267                         }
268                 }
269
270                 [ComVisible (false)]
271                 public CodeTypeReferenceCollection TypeArguments {
272                         get {
273                                 if (typeArguments == null)
274                                         typeArguments = new CodeTypeReferenceCollection ();
275                                 return typeArguments;
276                         }
277                 }
278         }
279 }