2 using System.Collections.Generic;
4 using System.Reflection;
6 using Mono.Cecil.Metadata;
8 namespace Mono.Debugger.Soft
10 public class MethodMirror : Mirror
14 TypeMirror declaring_type;
16 C.MethodDefinition meta;
17 ParameterInfoMirror[] param_info;
18 ParameterInfoMirror ret_param;
19 LocalVariable[] locals;
20 IList<Location> locations;
21 MethodBodyMirror body;
23 TypeMirror[] type_args;
25 internal MethodMirror (VirtualMachine vm, long id) : base (vm, id) {
31 name = vm.conn.Method_GetName (id);
36 public TypeMirror DeclaringType {
38 if (declaring_type == null)
39 declaring_type = vm.GetType (vm.conn.Method_GetDeclaringType (id));
40 return declaring_type;
44 public TypeMirror ReturnType {
46 return ReturnParameter.ParameterType;
51 public string FullName {
53 string type_namespace = DeclaringType.Namespace;
54 string type_name = DeclaringType.Name;
55 StringBuilder sb = new StringBuilder ();
56 sb.Append (ReturnType.Name);
58 if (type_namespace != String.Empty)
59 sb.Append (type_namespace + ".");
65 for (var i = 0; i < param_info.Length; i++) {
66 sb.Append(param_info[i].ParameterType.Name);
67 if (i != param_info.Length - 1)
71 return sb.ToString ();
75 MethodInfo GetInfo () {
77 info = vm.conn.Method_GetInfo (id);
82 public int MetadataToken {
84 return GetInfo ().token;
88 public MethodAttributes Attributes {
90 return (MethodAttributes) GetInfo ().attributes;
94 public bool IsPublic {
96 return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public;
99 public bool IsPrivate {
101 return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Private;
104 public bool IsFamily {
106 return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Family;
109 public bool IsAssembly {
111 return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Assembly;
114 public bool IsFamilyAndAssembly {
116 return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamANDAssem;
119 public bool IsFamilyOrAssembly {
121 return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamORAssem;
124 public bool IsStatic {
126 return (Attributes & MethodAttributes.Static) != 0;
129 public bool IsFinal {
131 return (Attributes & MethodAttributes.Final) != 0;
134 public bool IsVirtual {
136 return (Attributes & MethodAttributes.Virtual) != 0;
139 public bool IsHideBySig {
141 return (Attributes & MethodAttributes.HideBySig) != 0;
144 public bool IsAbstract {
146 return (Attributes & MethodAttributes.Abstract) != 0;
149 public bool IsSpecialName {
151 return (Attributes & MethodAttributes.SpecialName) != 0;
155 public bool IsConstructor {
157 int attr = (int)Attributes;
158 return ((attr & (int)MethodAttributes.RTSpecialName) != 0
159 && (Name == ".ctor"));
163 // Since protocol version 2.12
164 public bool IsGenericMethodDefinition {
166 vm.CheckProtocolVersion (2, 12);
167 return GetInfo ().is_gmd;
171 // Since protocol version 2.12
172 public bool IsGenericMethod {
174 vm.CheckProtocolVersion (2, 12);
175 return GetInfo ().is_generic_method;
179 public MethodImplAttributes GetMethodImplementationFlags() {
180 return (MethodImplAttributes)GetInfo ().iattributes;
183 public ParameterInfoMirror[] GetParameters () {
184 if (param_info == null) {
185 var pi = vm.conn.Method_GetParamInfo (id);
186 param_info = new ParameterInfoMirror [pi.param_count];
188 ret_param = new ParameterInfoMirror (this, -1, vm.GetType (pi.ret_type), null, ParameterAttributes.Retval);
191 for (int i = 0; i < pi.param_count; ++i) {
192 param_info [i] = new ParameterInfoMirror (this, i, vm.GetType (pi.param_types [i]), pi.param_names [i], 0);
199 public ParameterInfoMirror ReturnParameter {
201 if (ret_param == null)
207 public LocalVariable[] GetLocals () {
208 if (locals == null) {
210 LocalsInfo li = new LocalsInfo ();
212 li = vm.conn.Method_GetLocalsInfo (id);
213 } catch (CommandException) {
214 throw new ArgumentException ("Method doesn't have a body.");
216 // Add the arguments as well
217 var pi = vm.conn.Method_GetParamInfo (id);
219 locals = new LocalVariable [pi.param_count + li.names.Length];
221 for (int i = 0; i < pi.param_count; ++i)
222 locals [i] = new LocalVariable (vm, this, i, pi.param_types [i], pi.param_names [i], -1, -1, true);
224 for (int i = 0; i < li.names.Length; ++i)
225 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);
230 public LocalVariable GetLocal (string name) {
232 throw new ArgumentNullException ("name");
236 LocalVariable res = null;
237 for (int i = 0; i < locals.Length; ++i) {
238 if (locals [i].Name == name) {
240 throw new AmbiguousMatchException ("More that one local has the name '" + name + "'.");
248 public MethodBodyMirror GetMethodBody () {
250 MethodBodyInfo info = vm.conn.Method_GetBody (id);
252 body = new MethodBodyMirror (vm, this, info.il);
257 public MethodMirror GetGenericMethodDefinition () {
258 vm.CheckProtocolVersion (2, 12);
261 throw new InvalidOperationException ();
262 gmd = vm.GetMethod (info.gmd);
267 // Since protocol version 2.15
268 public TypeMirror[] GetGenericArguments () {
269 vm.CheckProtocolVersion (2, 15);
270 if (type_args == null)
271 type_args = vm.GetTypes (GetInfo ().type_args);
275 public IList<int> ILOffsets {
277 if (debug_info == null)
278 debug_info = vm.conn.Method_GetDebugInfo (id);
279 return Array.AsReadOnly (debug_info.il_offsets);
283 public IList<int> LineNumbers {
285 if (debug_info == null)
286 debug_info = vm.conn.Method_GetDebugInfo (id);
287 return Array.AsReadOnly (debug_info.line_numbers);
291 public string SourceFile {
293 if (debug_info == null)
294 debug_info = vm.conn.Method_GetDebugInfo (id);
295 return debug_info.source_files.Length > 0 ? debug_info.source_files [0].source_file : null;
299 public IList<Location> Locations {
301 if (locations == null) {
302 var il_offsets = ILOffsets;
303 var line_numbers = LineNumbers;
304 IList<Location> res = new Location [ILOffsets.Count];
305 for (int i = 0; i < il_offsets.Count; ++i)
306 res [i] = new Location (vm, this, -1, il_offsets [i], debug_info.source_files [i].source_file, line_numbers [i], 0, debug_info.source_files [i].hash);
313 internal int il_offset_to_line_number (int il_offset, out string src_file, out byte[] src_hash) {
314 if (debug_info == null)
315 debug_info = vm.conn.Method_GetDebugInfo (id);
317 // FIXME: Optimize this
320 for (int i = debug_info.il_offsets.Length - 1; i >= 0; --i) {
321 if (debug_info.il_offsets [i] <= il_offset) {
322 src_file = debug_info.source_files [i].source_file;
323 src_hash = debug_info.source_files [i].hash;
324 return debug_info.line_numbers [i];
330 public Location LocationAtILOffset (int il_offset) {
331 IList<Location> locs = Locations;
333 // FIXME: Optimize this
334 for (int i = locs.Count - 1; i >= 0; --i) {
335 if (locs [i].ILOffset <= il_offset)
342 public C.MethodDefinition Metadata {
345 meta = (C.MethodDefinition)DeclaringType.Assembly.Metadata.MainModule.LookupToken (MetadataToken);