2010-04-06 Jb Evain <jbevain@novell.com>
[mcs.git] / class / Mono.Debugger.Soft / Mono.Debugger.Soft / MethodMirror.cs
blob71d3ba3365a20918c5e5715115f0fc5922ef8618
1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4 using System.Reflection;
5 using C = Mono.Cecil;
6 using Mono.Cecil.Metadata;
8 namespace Mono.Debugger.Soft
10 public class MethodMirror : Mirror
12 string name;
13 MethodInfo info;
14 TypeMirror declaring_type;
15 DebugInfo debug_info;
16 C.MethodDefinition meta;
17 ParameterInfoMirror[] param_info;
18 ParameterInfoMirror ret_param;
19 LocalVariable[] locals;
20 IList<Location> locations;
21 MethodBodyMirror body;
23 internal MethodMirror (VirtualMachine vm, long id) : base (vm, id) {
26 public string Name {
27 get {
28 if (name == null)
29 name = vm.conn.Method_GetName (id);
30 return name;
34 public TypeMirror DeclaringType {
35 get {
36 if (declaring_type == null)
37 declaring_type = vm.GetType (vm.conn.Method_GetDeclaringType (id));
38 return declaring_type;
42 public TypeMirror ReturnType {
43 get {
44 return ReturnParameter.ParameterType;
48 // FIXME:
49 public string FullName {
50 get {
51 string type_namespace = DeclaringType.Namespace;
52 string type_name = DeclaringType.Name;
53 StringBuilder sb = new StringBuilder ();
54 sb.Append (ReturnType.Name);
55 sb.Append (' ');
56 if (type_namespace == String.Empty)
57 sb.Append (type_name + ":" + Name + " ()");
58 else
59 sb.Append (type_namespace + "." + type_name + ":" + Name + " ()");
60 return sb.ToString ();
64 void GetInfo () {
65 if (info == null)
66 info = vm.conn.Method_GetInfo (id);
69 public int MetadataToken {
70 get {
71 GetInfo ();
72 return info.token;
76 public MethodAttributes Attributes {
77 get {
78 GetInfo ();
79 return (MethodAttributes)info.attributes;
83 public bool IsPublic {
84 get {
85 return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public;
88 public bool IsPrivate {
89 get {
90 return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Private;
93 public bool IsFamily {
94 get {
95 return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Family;
98 public bool IsAssembly {
99 get {
100 return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Assembly;
103 public bool IsFamilyAndAssembly {
104 get {
105 return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamANDAssem;
108 public bool IsFamilyOrAssembly {
109 get {
110 return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamORAssem;
113 public bool IsStatic {
114 get {
115 return (Attributes & MethodAttributes.Static) != 0;
118 public bool IsFinal {
119 get {
120 return (Attributes & MethodAttributes.Final) != 0;
123 public bool IsVirtual {
124 get {
125 return (Attributes & MethodAttributes.Virtual) != 0;
128 public bool IsHideBySig {
129 get {
130 return (Attributes & MethodAttributes.HideBySig) != 0;
133 public bool IsAbstract {
134 get {
135 return (Attributes & MethodAttributes.Abstract) != 0;
138 public bool IsSpecialName {
139 get {
140 return (Attributes & MethodAttributes.SpecialName) != 0;
144 public bool IsConstructor {
145 get {
146 int attr = (int)Attributes;
147 return ((attr & (int)MethodAttributes.RTSpecialName) != 0
148 && (Name == ".ctor"));
152 public ParameterInfoMirror[] GetParameters () {
153 if (param_info == null) {
154 var pi = vm.conn.Method_GetParamInfo (id);
155 param_info = new ParameterInfoMirror [pi.param_count];
156 // Return
157 ret_param = new ParameterInfoMirror (this, -1, vm.GetType (pi.ret_type), null, ParameterAttributes.Retval);
158 // FIXME: this
159 // FIXME: Attributes
160 for (int i = 0; i < pi.param_count; ++i) {
161 param_info [i] = new ParameterInfoMirror (this, i, vm.GetType (pi.param_types [i]), pi.param_names [i], 0);
165 return param_info;
168 public ParameterInfoMirror ReturnParameter {
169 get {
170 if (ret_param == null)
171 GetParameters ();
172 return ret_param;
176 public LocalVariable[] GetLocals () {
177 if (locals == null) {
178 var li = vm.conn.Method_GetLocalsInfo (id);
179 // Add the arguments as well
180 var pi = vm.conn.Method_GetParamInfo (id);
182 locals = new LocalVariable [pi.param_count + li.names.Length];
184 for (int i = 0; i < pi.param_count; ++i)
185 locals [i] = new LocalVariable (vm, this, i, pi.param_types [i], pi.param_names [i], -1, -1, true);
187 for (int i = 0; i < li.names.Length; ++i)
188 locals [i + pi.param_count] = new LocalVariable (vm, this, i, li.types [i], li.names [i], li.live_range_start [i], li.live_range_end [i], false);
190 return locals;
193 public LocalVariable GetLocal (string name) {
194 if (name == null)
195 throw new ArgumentNullException ("name");
197 GetLocals ();
199 LocalVariable res = null;
200 for (int i = 0; i < locals.Length; ++i) {
201 if (locals [i].Name == name) {
202 if (res != null)
203 throw new AmbiguousMatchException ("More that one local has the name '" + name + "'.");
204 res = locals [i];
208 return res;
211 public MethodBodyMirror GetMethodBody () {
212 if (body == null) {
213 MethodBodyInfo info = vm.conn.Method_GetBody (id);
215 body = new MethodBodyMirror (vm, this, info.il);
217 return body;
220 public IList<int> ILOffsets {
221 get {
222 if (debug_info == null)
223 debug_info = vm.conn.Method_GetDebugInfo (id);
224 return Array.AsReadOnly (debug_info.il_offsets);
228 public IList<int> LineNumbers {
229 get {
230 if (debug_info == null)
231 debug_info = vm.conn.Method_GetDebugInfo (id);
232 return Array.AsReadOnly (debug_info.line_numbers);
236 public string SourceFile {
237 get {
238 if (debug_info == null)
239 debug_info = vm.conn.Method_GetDebugInfo (id);
240 return debug_info.filename;
244 public IList<Location> Locations {
245 get {
246 if (locations == null) {
247 var il_offsets = ILOffsets;
248 var line_numbers = LineNumbers;
249 IList<Location> res = new Location [ILOffsets.Count];
250 for (int i = 0; i < il_offsets.Count; ++i)
251 res [i] = new Location (vm, this, -1, il_offsets [i], SourceFile, line_numbers [i], 0);
252 locations = res;
254 return locations;
258 internal int il_offset_to_line_number (int il_offset) {
259 if (debug_info == null)
260 debug_info = vm.conn.Method_GetDebugInfo (id);
262 // FIXME: Optimize this
263 for (int i = debug_info.il_offsets.Length - 1; i >= 0; --i) {
264 if (debug_info.il_offsets [i] <= il_offset)
265 return debug_info.line_numbers [i];
267 return -1;
270 public Location LocationAtILOffset (int il_offset) {
271 IList<Location> locs = Locations;
273 // FIXME: Optimize this
274 for (int i = locs.Count - 1; i >= 0; --i) {
275 if (locs [i].ILOffset <= il_offset)
276 return locs [i];
279 return null;
282 public C.MethodDefinition Metadata {
283 get {
284 if (meta == null)
285 meta = (C.MethodDefinition)DeclaringType.Assembly.Metadata.MainModule.LookupByToken (new MetadataToken (MetadataToken));
286 return meta;