Merge pull request #601 from knocte/sock_improvements
[mono.git] / mcs / class / Mono.Debugger.Soft / Mono.Debugger.Soft / CustomAttributeDataMirror.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Runtime.CompilerServices;
4 using System.Runtime.InteropServices;
5 using System.Reflection;
6 using System.Text;
7 using Mono.Cecil.Metadata;
8
9 namespace Mono.Debugger.Soft {
10
11         public sealed class CustomAttributeDataMirror {
12                 MethodMirror ctorInfo;
13                 IList<CustomAttributeTypedArgumentMirror> ctorArgs;
14                 IList<CustomAttributeNamedArgumentMirror> namedArgs;
15
16                 internal CustomAttributeDataMirror (MethodMirror ctorInfo, object [] ctorArgs, object [] namedArgs)
17                 {
18                         this.ctorInfo = ctorInfo;
19                         
20                         this.ctorArgs = Array.AsReadOnly<CustomAttributeTypedArgumentMirror> 
21                                 (ctorArgs != null ? UnboxValues<CustomAttributeTypedArgumentMirror> (ctorArgs) : new CustomAttributeTypedArgumentMirror [0]);
22                         
23                         this.namedArgs = Array.AsReadOnly<CustomAttributeNamedArgumentMirror> 
24                                 (namedArgs != null ? UnboxValues<CustomAttributeNamedArgumentMirror> (namedArgs) : new CustomAttributeNamedArgumentMirror [0]);
25                 }
26
27                 [ComVisible (true)]
28                 public MethodMirror Constructor {
29                         get {
30                                 return ctorInfo;
31                         }
32                 }
33
34                 [ComVisible (true)]
35                 public IList<CustomAttributeTypedArgumentMirror> ConstructorArguments {
36                         get {
37                                 return ctorArgs;
38                         }
39                 }
40
41                 public IList<CustomAttributeNamedArgumentMirror> NamedArguments {
42                         get {
43                                 return namedArgs;
44                         }
45                 }
46
47                 public override string ToString ()
48                 {
49                         StringBuilder sb = new StringBuilder ();
50
51                         sb.Append ("[" + ctorInfo.DeclaringType.FullName + "(");
52                         if (ctorArgs != null) {
53                                 for (int i = 0; i < ctorArgs.Count; i++) {
54                                         sb.Append (ctorArgs [i].ToString ());
55                                         if (i + 1 < ctorArgs.Count)
56                                                 sb.Append (", ");
57                                 }
58                         }
59
60                         if (namedArgs != null) {
61                                 if (namedArgs.Count > 0)
62                                         sb.Append (", ");
63                         
64                                 for (int j = 0; j < namedArgs.Count; j++) {
65                                         sb.Append (namedArgs [j].ToString ());
66                                         if (j + 1 < namedArgs.Count)
67                                                 sb.Append (", ");
68                                 }
69                         }
70                         sb.AppendFormat (")]");
71
72                         return sb.ToString ();
73                 }
74
75                 static T [] UnboxValues<T> (object [] values)
76                 {
77                         T [] retval = new T [values.Length];
78                         for (int i = 0; i < values.Length; i++)
79                                 retval [i] = (T) values [i];
80
81                         return retval;
82                 }
83
84                 /* 
85                  * Construct a normal object from the value, so accessing the cattr doesn't 
86                  * require remoting calls.
87                  */
88                 static CustomAttributeTypedArgumentMirror CreateArg (VirtualMachine vm, ValueImpl vi) {
89                         object val;
90
91                         /* Instead of receiving a mirror of the Type object, we receive the id of the type */
92                         if (vi.Type == (ElementType)ValueTypeId.VALUE_TYPE_ID_TYPE)
93                                 val = vm.GetType (vi.Id);
94                         else {
95                                 Value v = vm.DecodeValue (vi);
96                                 if (v is PrimitiveValue)
97                                         val = (v as PrimitiveValue).Value;
98                                 else if (v is StringMirror)
99                                         val = (v as StringMirror).Value;
100                                 else
101                                         // FIXME:
102                                         val = v;
103                         }
104                         return new CustomAttributeTypedArgumentMirror (null, val);
105                 }
106
107                 internal static CustomAttributeDataMirror[] Create (VirtualMachine vm, CattrInfo[] info) {
108                         var res = new CustomAttributeDataMirror [info.Length];
109                         for (int i = 0; i < info.Length; ++i) {
110                                 CattrInfo attr = info [i];
111                                 MethodMirror ctor = vm.GetMethod (attr.ctor_id);
112                                 var ctor_args = new object [attr.ctor_args.Length];
113                                 for (int j = 0; j < ctor_args.Length; ++j)
114                                         ctor_args [j] = CreateArg (vm, attr.ctor_args [j]);
115                                 var named_args = new object [attr.named_args.Length];
116                                 for (int j = 0; j < named_args.Length; ++j) {
117                                         CattrNamedArgInfo arg = attr.named_args [j];
118                                         CustomAttributeTypedArgumentMirror val;
119
120                                         val = CreateArg (vm, arg.value);
121
122                                         TypeMirror t = ctor.DeclaringType;
123                                         while (named_args [j] == null && t != null) {
124                                                 if (arg.is_property) {
125                                                         foreach (var prop in t.GetProperties ()) {
126                                                                 if (prop.Id == arg.id)
127                                                                         named_args [j] = new CustomAttributeNamedArgumentMirror (prop, null, val);
128                                                         }
129                                                 } else {
130                                                         foreach (var field in t.GetFields ()) {
131                                                                 if (field.Id == arg.id)
132                                                                         named_args [j] = new CustomAttributeNamedArgumentMirror (null, field, val);
133                                                         }
134                                                 }
135                                                 t = t.BaseType;
136                                         }
137                                         if (named_args [j] == null)
138                                                 throw new NotImplementedException ();
139                                 }
140                                 res [i] = new CustomAttributeDataMirror (ctor, ctor_args, named_args);
141                         }
142
143                         return res;
144                 }
145         }
146
147 }