5
// Mike Krüger <mkrueger@novell.com>
7
// Copyright (C) 2008 Novell, Inc (http://www.novell.com)
9
// Permission is hereby granted, free of charge, to any person obtaining
10
// a copy of this software and associated documentation files (the
11
// "Software"), to deal in the Software without restriction, including
12
// without limitation the rights to use, copy, modify, merge, publish,
13
// distribute, sublicense, and/or sell copies of the Software, and to
14
// permit persons to whom the Software is furnished to do so, subject to
15
// the following conditions:
17
// The above copyright notice and this permission notice shall be
18
// included in all copies or substantial portions of the Software.
20
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
using System.Collections.Generic;
32
using System.Collections.ObjectModel;
33
using System.Diagnostics;
35
namespace MonoDevelop.Projects.Dom
37
public class ReturnTypePart : IReturnTypePart
44
protected List<IReturnType> genericArguments = null;
45
static readonly ReadOnlyCollection<IReturnType> emptyGenericParameters = new ReadOnlyCollection<IReturnType> (new IReturnType [0]);
46
public System.Collections.ObjectModel.ReadOnlyCollection<IReturnType> GenericArguments {
48
if (genericArguments == null)
49
return emptyGenericParameters;
50
return genericArguments.AsReadOnly ();
53
public ReturnTypePart ()
57
public ReturnTypePart (string name, IEnumerable<IReturnType> typeParameters)
60
if (typeParameters != null)
61
this.genericArguments = new List<IReturnType> (typeParameters);
63
public ReturnTypePart (string baseName, string name, IEnumerable<ITypeParameter> typeParameters)
66
if (typeParameters != null) {
67
this.genericArguments = new List<IReturnType> ();
68
foreach (ITypeParameter para in typeParameters) {
69
this.genericArguments.Add (new DomReturnType (baseName + "." + para.Name));
74
public string ToInvariantString ()
76
if (genericArguments != null && genericArguments.Count > 0) {
77
StringBuilder result = new StringBuilder ();
80
for (int i = 0; i < genericArguments.Count; i++) {
83
result.Append (genericArguments[i].ToInvariantString ());
86
return result.ToString ();
91
public void AddTypeParameter (IReturnType type)
93
if (genericArguments == null)
94
genericArguments = new List<IReturnType> ();
95
this.genericArguments.Add (type);
99
public class DomReturnType : IReturnType
101
static readonly int[] zeroDimensions = new int[0];
102
static readonly int[] oneDimensions = new int[] { 1 };
104
List<IReturnTypePart> parts = new List<IReturnTypePart> ();
106
// TODO dom: free unused return types
107
static Dictionary<string, IReturnType> returnTypeCache;
109
public static readonly IReturnType Void;
110
public static readonly IReturnType Object;
111
public static readonly IReturnType Exception;
113
static DomReturnType ()
115
// Initialization is done here instead of using field initializers to
116
// ensure that the returnTypeCache dictionary us properly initialized
117
// when calling GetSharedReturnType.
119
returnTypeCache = new Dictionary<string, IReturnType> ();
121
Void = GetSharedReturnType ("System.Void");
122
Object = GetSharedReturnType ("System.Object");
123
Exception = GetSharedReturnType ("System.Exception");
126
public List<IReturnTypePart> Parts {
134
Debug.Assert (parts.Count > 0);
135
return parts[parts.Count - 1].Name;
138
Debug.Assert (parts.Count > 0);
139
parts[parts.Count - 1].Name = value;
143
public ReadOnlyCollection<IReturnType> GenericArguments {
145
Debug.Assert (parts.Count > 0);
146
return parts[parts.Count - 1].GenericArguments;
149
public void AddTypeParameter (IReturnType type)
151
Debug.Assert (parts.Count > 0);
152
parts[parts.Count - 1].AddTypeParameter (type);
155
protected string nspace;
156
protected int pointerNestingLevel;
157
protected int[] dimensions = null;
158
ReturnTypeModifiers modifiers;
160
public string FullName {
162
if (Parts.Count == 1)
163
return !String.IsNullOrEmpty (nspace) ? nspace + "." + Name : Name;
166
foreach (ReturnTypePart part in Parts) {
176
public string DecoratedFullName {
178
string dname = Namespace;
179
foreach (ReturnTypePart rpart in Parts) {
180
if (dname.Length > 0)
183
if (rpart.GenericArguments.Count > 0)
184
dname += "`" + rpart.GenericArguments.Count;
190
public static KeyValuePair<string, string> SplitFullName (string fullName)
192
if (String.IsNullOrEmpty (fullName))
193
return new KeyValuePair<string, string> ("", "");
194
int idx = fullName.LastIndexOf ('.');
196
return new KeyValuePair<string, string> (fullName.Substring (0, idx), fullName.Substring (idx + 1));
197
return new KeyValuePair<string, string> ("", fullName);
200
public ReturnTypeModifiers Modifiers {
202
return this.modifiers;
205
this.modifiers = value;
210
public string Namespace {
218
public int PointerNestingLevel {
220
return pointerNestingLevel;
223
pointerNestingLevel = value;
227
public int ArrayDimensions {
229
return dimensions != null ? dimensions.Length : 0;
232
List<int> curDimensions = new List<int> (dimensions ?? zeroDimensions);
233
if (curDimensions.Count > value)
234
curDimensions.RemoveRange (value, value - curDimensions.Count);
235
while (curDimensions.Count < value)
236
curDimensions.Add (0);
237
SetDimensions (curDimensions.ToArray ());
241
public bool IsNullable {
243
return (Modifiers & ReturnTypeModifiers.Nullable) == ReturnTypeModifiers.Nullable;
247
Modifiers |= ReturnTypeModifiers.Nullable;
249
Modifiers &= ~ReturnTypeModifiers.Nullable;
254
public bool IsByRef {
256
return (Modifiers & ReturnTypeModifiers.ByRef) == ReturnTypeModifiers.ByRef;
260
Modifiers |= ReturnTypeModifiers.ByRef;
262
Modifiers &= ~ReturnTypeModifiers.ByRef;
267
protected IType type;
268
public virtual IType Type {
277
public DomReturnType ()
279
this.parts.Add (new ReturnTypePart ());
282
internal DomReturnType (string ns, List<IReturnTypePart> parts)
288
public DomReturnType (IType type)
291
throw new ArgumentNullException ("type was null");
293
this.nspace = type is InstantiatedType ? ((InstantiatedType)type).UninstantiatedType.Namespace : type.Namespace;
294
IType curType = type;
296
if (curType is InstantiatedType) {
297
InstantiatedType instType = (InstantiatedType)curType;
298
this.parts.Insert (0, new ReturnTypePart (instType.UninstantiatedType.Name, instType.GenericParameters));
300
this.parts.Insert (0, new ReturnTypePart (curType.FullName, curType.Name, curType.TypeParameters));
301
curType = curType.DeclaringType;
302
} while (curType != null);
305
public override bool Equals (object obj)
307
DomReturnType type = obj as DomReturnType;
310
if (ArrayDimensions != type.ArrayDimensions)
312
for (int n=0; n<ArrayDimensions; n++) {
313
if (GetDimension (n) != type.GetDimension (n))
316
if (GenericArguments.Count != type.GenericArguments.Count)
318
for (int i = 0; i < GenericArguments.Count; i++) {
319
if (!GenericArguments[i].Equals (type.GenericArguments [i]))
323
return Name == type.Name &&
324
nspace == type.nspace &&
325
pointerNestingLevel == type.pointerNestingLevel &&
326
Modifiers == type.Modifiers;
329
public override int GetHashCode ()
331
return ToInvariantString ().GetHashCode ();
335
public int GetDimension (int arrayDimension)
337
if (dimensions == null || arrayDimension < 0 || arrayDimension >= dimensions.Length)
339
return this.dimensions [arrayDimension];
342
public void SetDimension (int arrayDimension, int dimension)
344
if (arrayDimension < 0 || arrayDimension >= ArrayDimensions)
347
// Avoid changing the shared dimension
348
if (dimensions == oneDimensions)
349
dimensions = new int [ArrayDimensions];
351
dimensions [arrayDimension] = dimension;
352
SetDimensions (dimensions);
355
public void SetDimensions (int[] arrayDimensions)
357
// Reuse common dimension constants to save memory
358
if (arrayDimensions == null)
360
else if (arrayDimensions != null && arrayDimensions.Length == 1 && arrayDimensions[0] == 1)
361
dimensions = oneDimensions;
363
dimensions = arrayDimensions;
366
public int[] GetDimensions ()
368
return dimensions ?? zeroDimensions;
371
public DomReturnType (string name) : this (name, false, new List<IReturnType> ())
375
public DomReturnType (string name, bool isNullable, IEnumerable<IReturnType> typeParameters)
377
KeyValuePair<string, string> splitted = SplitFullName (name);
378
this.nspace = splitted.Key;
379
this.parts.Add (new ReturnTypePart (splitted.Value, typeParameters));
380
this.IsNullable = isNullable;
383
public static IReturnType FromInvariantString (string invariantString)
385
return GetSharedReturnType (invariantString);
388
public static int num = 0;
389
string invariantString = null;
390
public string ToInvariantString ()
392
if (invariantString != null)
393
return invariantString;
394
StringBuilder result = new StringBuilder ();
395
result.Append (Namespace);
396
foreach (ReturnTypePart part in Parts) {
397
if (result.Length > 0)
399
result.Append (part.ToInvariantString ());
401
for (int i = 0; i < ArrayDimensions; i++) {
403
result.Append (new string (',', this.GetDimension (i)));
406
result.Append (new string ('*', this.PointerNestingLevel));
411
return invariantString = result.ToString ();
414
public S AcceptVisitor<T, S> (IDomVisitor<T, S> visitor, T data)
416
return visitor.Visit (this, data);
419
public override string ToString ()
421
StringBuilder genArgs = new StringBuilder ();
422
if (GenericArguments == null) {
423
genArgs.Append ("<null>");
425
genArgs.Append ("{");
426
foreach (object o in GenericArguments) {
427
if (genArgs.Length > 1)
428
genArgs.Append (", ");
429
genArgs.Append (o != null ? o.ToString () : "null");
431
genArgs.Append ("}");
434
return string.Format ("[DomReturnType:FullName={0}, PointerNestingLevel={1}, ArrayDimensions={2}, GenericArguments={3}, UnderlyingType={4}]",
439
Type == null ? "null" : Type.ToString ());
442
public static string ConvertToString (IReturnType type)
444
StringBuilder sb = new StringBuilder (DomType.GetInstantiatedTypeName (type.FullName, type.GenericArguments));
446
if (type.PointerNestingLevel > 0)
447
sb.Append (new String ('*', type.PointerNestingLevel));
449
if (type.ArrayDimensions > 0) {
450
for (int i = 0; i < type.ArrayDimensions; i++) {
455
return sb.ToString ();
458
#region shared return types
460
public static IReturnType GetSharedReturnType (string invariantString)
462
if (String.IsNullOrEmpty (invariantString))
464
lock (returnTypeCache) {
466
if (!returnTypeCache.TryGetValue (invariantString, out type)) {
467
DomReturnType newType = new DomReturnType (invariantString);
468
returnTypeCache[invariantString] = newType;
475
public static IReturnType GetSharedReturnType (IReturnType returnType)
477
if (returnType == null)
479
string invariantString = returnType.ToInvariantString();
480
lock (returnTypeCache) {
482
if (!returnTypeCache.TryGetValue (invariantString, out type)) {
483
returnTypeCache[invariantString] = returnType;