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 CustomAttributeDataMirror[] cattrs;
18 ParameterInfoMirror[] param_info;
19 ParameterInfoMirror ret_param;
20 LocalVariable[] locals;
21 IList<Location> locations;
22 MethodBodyMirror body;
24 TypeMirror[] type_args;
26 internal MethodMirror (VirtualMachine vm, long id) : base (vm, id) {
32 name = vm.conn.Method_GetName (id);
37 public TypeMirror DeclaringType {
39 if (declaring_type == null)
40 declaring_type = vm.GetType (vm.conn.Method_GetDeclaringType (id));
41 return declaring_type;
45 public TypeMirror ReturnType {
47 return ReturnParameter.ParameterType;
52 public string FullName {
54 string type_namespace = DeclaringType.Namespace;
55 string type_name = DeclaringType.Name;
56 StringBuilder sb = new StringBuilder ();
57 sb.Append (ReturnType.Name);
59 if (type_namespace != String.Empty)
60 sb.Append (type_namespace + ".");
66 for (var i = 0; i < param_info.Length; i++) {
67 sb.Append(param_info[i].ParameterType.Name);
68 if (i != param_info.Length - 1)
72 return sb.ToString ();
77 * Creating the custom attributes themselves could modify the behavior of the
78 * debuggee, so we return objects similar to the CustomAttributeData objects
79 * used by the reflection-only functionality on .net.
80 * Since protocol version 2.21
82 public CustomAttributeDataMirror[] GetCustomAttributes (bool inherit) {
83 return GetCAttrs (null, inherit);
86 /* Since protocol version 2.21 */
87 public CustomAttributeDataMirror[] GetCustomAttributes (TypeMirror attributeType, bool inherit) {
88 if (attributeType == null)
89 throw new ArgumentNullException ("attributeType");
90 return GetCAttrs (attributeType, inherit);
93 CustomAttributeDataMirror[] GetCAttrs (TypeMirror type, bool inherit) {
94 if (cattrs == null && meta != null && !Metadata.HasCustomAttributes)
95 cattrs = new CustomAttributeDataMirror [0];
97 // FIXME: Handle inherit
99 CattrInfo[] info = vm.conn.Method_GetCustomAttributes (id, 0, false);
100 cattrs = CustomAttributeDataMirror.Create (vm, info);
102 var res = new List<CustomAttributeDataMirror> ();
103 foreach (var attr in cattrs)
104 if (type == null || attr.Constructor.DeclaringType == type)
106 return res.ToArray ();
109 MethodInfo GetInfo () {
111 info = vm.conn.Method_GetInfo (id);
116 public int MetadataToken {
118 return GetInfo ().token;
122 public MethodAttributes Attributes {
124 return (MethodAttributes) GetInfo ().attributes;
128 public bool IsPublic {
130 return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public;
133 public bool IsPrivate {
135 return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Private;
138 public bool IsFamily {
140 return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Family;
143 public bool IsAssembly {
145 return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Assembly;
148 public bool IsFamilyAndAssembly {
150 return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamANDAssem;
153 public bool IsFamilyOrAssembly {
155 return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamORAssem;
158 public bool IsStatic {
160 return (Attributes & MethodAttributes.Static) != 0;
163 public bool IsFinal {
165 return (Attributes & MethodAttributes.Final) != 0;
168 public bool IsVirtual {
170 return (Attributes & MethodAttributes.Virtual) != 0;
173 public bool IsHideBySig {
175 return (Attributes & MethodAttributes.HideBySig) != 0;
178 public bool IsAbstract {
180 return (Attributes & MethodAttributes.Abstract) != 0;
183 public bool IsSpecialName {
185 return (Attributes & MethodAttributes.SpecialName) != 0;
189 public bool IsConstructor {
191 int attr = (int)Attributes;
192 return ((attr & (int)MethodAttributes.RTSpecialName) != 0
193 && (Name == ".ctor"));
197 // Since protocol version 2.12
198 public bool IsGenericMethodDefinition {
200 vm.CheckProtocolVersion (2, 12);
201 return GetInfo ().is_gmd;
205 // Since protocol version 2.12
206 public bool IsGenericMethod {
208 vm.CheckProtocolVersion (2, 12);
209 return GetInfo ().is_generic_method;
213 public MethodImplAttributes GetMethodImplementationFlags() {
214 return (MethodImplAttributes)GetInfo ().iattributes;
217 public ParameterInfoMirror[] GetParameters () {
218 if (param_info == null) {
219 var pi = vm.conn.Method_GetParamInfo (id);
220 param_info = new ParameterInfoMirror [pi.param_count];
222 ret_param = new ParameterInfoMirror (this, -1, vm.GetType (pi.ret_type), null, ParameterAttributes.Retval);
225 for (int i = 0; i < pi.param_count; ++i) {
226 param_info [i] = new ParameterInfoMirror (this, i, vm.GetType (pi.param_types [i]), pi.param_names [i], 0);
233 public ParameterInfoMirror ReturnParameter {
235 if (ret_param == null)
241 public LocalVariable[] GetLocals () {
242 if (locals == null) {
243 LocalsInfo li = new LocalsInfo ();
245 li = vm.conn.Method_GetLocalsInfo (id);
246 } catch (CommandException) {
247 throw new AbsentInformationException ();
250 // Add the arguments as well
251 var pi = vm.conn.Method_GetParamInfo (id);
253 locals = new LocalVariable [pi.param_count + li.names.Length];
255 for (int i = 0; i < pi.param_count; ++i)
256 locals [i] = new LocalVariable (vm, this, i, pi.param_types [i], pi.param_names [i], -1, -1, true);
258 for (int i = 0; i < li.names.Length; ++i)
259 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);
264 public LocalVariable GetLocal (string name) {
266 throw new ArgumentNullException ("name");
270 LocalVariable res = null;
271 for (int i = 0; i < locals.Length; ++i) {
272 if (locals [i].Name == name) {
274 throw new AmbiguousMatchException ("More that one local has the name '" + name + "'.");
282 public MethodBodyMirror GetMethodBody () {
284 MethodBodyInfo info = vm.conn.Method_GetBody (id);
286 body = new MethodBodyMirror (vm, this, info);
291 public MethodMirror GetGenericMethodDefinition () {
292 vm.CheckProtocolVersion (2, 12);
295 throw new InvalidOperationException ();
296 gmd = vm.GetMethod (info.gmd);
301 // Since protocol version 2.15
302 public TypeMirror[] GetGenericArguments () {
303 vm.CheckProtocolVersion (2, 15);
304 if (type_args == null)
305 type_args = vm.GetTypes (GetInfo ().type_args);
309 public IList<int> ILOffsets {
311 if (debug_info == null)
312 debug_info = vm.conn.Method_GetDebugInfo (id);
313 return Array.AsReadOnly (debug_info.il_offsets);
317 public IList<int> LineNumbers {
319 if (debug_info == null)
320 debug_info = vm.conn.Method_GetDebugInfo (id);
321 return Array.AsReadOnly (debug_info.line_numbers);
325 public string SourceFile {
327 if (debug_info == null)
328 debug_info = vm.conn.Method_GetDebugInfo (id);
329 return debug_info.source_files.Length > 0 ? debug_info.source_files [0].source_file : null;
333 public IList<Location> Locations {
335 if (locations == null) {
336 var il_offsets = ILOffsets;
337 var line_numbers = LineNumbers;
338 IList<Location> res = new Location [ILOffsets.Count];
339 for (int i = 0; i < il_offsets.Count; ++i)
340 res [i] = new Location (vm, this, -1, il_offsets [i], debug_info.source_files [i].source_file, line_numbers [i], debug_info.column_numbers [i], debug_info.source_files [i].hash);
347 internal int il_offset_to_line_number (int il_offset, out string src_file, out byte[] src_hash, out int column_number) {
348 if (debug_info == null)
349 debug_info = vm.conn.Method_GetDebugInfo (id);
351 // FIXME: Optimize this
355 for (int i = debug_info.il_offsets.Length - 1; i >= 0; --i) {
356 if (debug_info.il_offsets [i] <= il_offset) {
357 src_file = debug_info.source_files [i].source_file;
358 src_hash = debug_info.source_files [i].hash;
359 column_number = debug_info.column_numbers [i];
360 return debug_info.line_numbers [i];
366 public Location LocationAtILOffset (int il_offset) {
367 IList<Location> locs = Locations;
369 // FIXME: Optimize this
370 for (int i = locs.Count - 1; i >= 0; --i) {
371 if (locs [i].ILOffset <= il_offset)
378 public C.MethodDefinition Metadata {
381 meta = (C.MethodDefinition)DeclaringType.Assembly.Metadata.MainModule.LookupToken (MetadataToken);