Merge pull request #601 from knocte/sock_improvements
[mono.git] / mcs / class / Mono.Debugger.Soft / Mono.Debugger.Soft / MethodMirror.cs
index d28352a97160893dd88b4ce6d759e19ca16afb34..ac97cb02fb43742c806aedec74020c48f04d6e00 100644 (file)
@@ -14,11 +14,14 @@ namespace Mono.Debugger.Soft
                TypeMirror declaring_type;
                DebugInfo debug_info;
                C.MethodDefinition meta;
+               CustomAttributeDataMirror[] cattrs;
                ParameterInfoMirror[] param_info;
                ParameterInfoMirror ret_param;
                LocalVariable[] locals;
                IList<Location> locations;
                MethodBodyMirror body;
+               MethodMirror gmd;
+               TypeMirror[] type_args;
 
                internal MethodMirror (VirtualMachine vm, long id) : base (vm, id) {
                }
@@ -29,7 +32,7 @@ namespace Mono.Debugger.Soft
                                        name = vm.conn.Method_GetName (id);
                                return name;
                        }
-           }
+               }
 
                public TypeMirror DeclaringType {
                        get {
@@ -37,7 +40,7 @@ namespace Mono.Debugger.Soft
                                        declaring_type = vm.GetType (vm.conn.Method_GetDeclaringType (id));
                                return declaring_type;
                        }
-           }
+               }
 
                public TypeMirror ReturnType {
                        get {
@@ -61,31 +64,64 @@ namespace Mono.Debugger.Soft
                                sb.Append(" ");
                                sb.Append("(");
                                for (var i = 0; i < param_info.Length; i++) {
-                                       sb.Append(param_info[i].Name);
+                                       sb.Append(param_info[i].ParameterType.Name);
                                        if (i != param_info.Length - 1)
                                                sb.Append(", ");
                                }
                                sb.Append(")");
                                return sb.ToString ();
                        }
-           }
+               }
+
+               /*
+                * Creating the custom attributes themselves could modify the behavior of the
+                * debuggee, so we return objects similar to the CustomAttributeData objects
+                * used by the reflection-only functionality on .net.
+                * Since protocol version 2.21
+                */
+               public CustomAttributeDataMirror[] GetCustomAttributes (bool inherit) {
+                       return GetCAttrs (null, inherit);
+               }
 
-               void GetInfo () {
+               /* Since protocol version 2.21 */
+               public CustomAttributeDataMirror[] GetCustomAttributes (TypeMirror attributeType, bool inherit) {
+                       if (attributeType == null)
+                               throw new ArgumentNullException ("attributeType");
+                       return GetCAttrs (attributeType, inherit);
+               }
+
+               CustomAttributeDataMirror[] GetCAttrs (TypeMirror type, bool inherit) {
+                       if (cattrs == null && meta != null && !Metadata.HasCustomAttributes)
+                               cattrs = new CustomAttributeDataMirror [0];
+
+                       // FIXME: Handle inherit
+                       if (cattrs == null) {
+                               CattrInfo[] info = vm.conn.Method_GetCustomAttributes (id, 0, false);
+                               cattrs = CustomAttributeDataMirror.Create (vm, info);
+                       }
+                       var res = new List<CustomAttributeDataMirror> ();
+                       foreach (var attr in cattrs)
+                               if (type == null || attr.Constructor.DeclaringType == type)
+                                       res.Add (attr);
+                       return res.ToArray ();
+               }
+
+               MethodInfo GetInfo () {
                        if (info == null)
                                info = vm.conn.Method_GetInfo (id);
+                       
+                       return info;
                }
 
                public int MetadataToken {
                        get {
-                               GetInfo ();
-                               return info.token;
+                               return GetInfo ().token;
                        }
                }
 
                public MethodAttributes Attributes {
                        get {
-                               GetInfo ();
-                               return (MethodAttributes)info.attributes;
+                               return (MethodAttributes) GetInfo ().attributes;
                        }
                }
 
@@ -158,7 +194,27 @@ namespace Mono.Debugger.Soft
                        }
                }
 
-           public ParameterInfoMirror[] GetParameters () {
+               // Since protocol version 2.12
+               public bool IsGenericMethodDefinition {
+                       get {
+                               vm.CheckProtocolVersion (2, 12);
+                               return GetInfo ().is_gmd;
+                       }
+               }
+
+               // Since protocol version 2.12
+               public bool IsGenericMethod {
+                       get {
+                               vm.CheckProtocolVersion (2, 12);
+                               return GetInfo ().is_generic_method;
+                       }
+               }
+
+               public MethodImplAttributes GetMethodImplementationFlags() {
+                       return (MethodImplAttributes)GetInfo ().iattributes;
+               }
+
+               public ParameterInfoMirror[] GetParameters () {
                        if (param_info == null) {
                                var pi = vm.conn.Method_GetParamInfo (id);
                                param_info = new ParameterInfoMirror [pi.param_count];
@@ -174,7 +230,7 @@ namespace Mono.Debugger.Soft
                        return param_info;
                }
 
-           public ParameterInfoMirror ReturnParameter {
+               public ParameterInfoMirror ReturnParameter {
                        get {
                                if (ret_param == null)
                                        GetParameters ();
@@ -184,7 +240,13 @@ namespace Mono.Debugger.Soft
 
                public LocalVariable[] GetLocals () {
                        if (locals == null) {
-                               var li = vm.conn.Method_GetLocalsInfo (id);
+                               LocalsInfo li = new LocalsInfo ();
+                               try {
+                                       li = vm.conn.Method_GetLocalsInfo (id);
+                               } catch (CommandException) {
+                                       throw new AbsentInformationException ();
+                               }
+
                                // Add the arguments as well
                                var pi = vm.conn.Method_GetParamInfo (id);
 
@@ -221,18 +283,36 @@ namespace Mono.Debugger.Soft
                        if (body == null) {
                                MethodBodyInfo info = vm.conn.Method_GetBody (id);
 
-                               body = new MethodBodyMirror (vm, this, info.il);
+                               body = new MethodBodyMirror (vm, this, info);
                        }
                        return body;
                }
 
+               public MethodMirror GetGenericMethodDefinition () {
+                       vm.CheckProtocolVersion (2, 12);
+                       if (gmd == null) {
+                               if (info.gmd == 0)
+                                       throw new InvalidOperationException ();
+                               gmd = vm.GetMethod (info.gmd);
+                       }
+                       return gmd;
+               }
+
+               // Since protocol version 2.15
+               public TypeMirror[] GetGenericArguments () {
+                       vm.CheckProtocolVersion (2, 15);
+                       if (type_args == null)
+                               type_args = vm.GetTypes (GetInfo ().type_args);
+                       return type_args;
+               }
+
                public IList<int> ILOffsets {
                        get {
                                if (debug_info == null)
                                        debug_info = vm.conn.Method_GetDebugInfo (id);
                                return Array.AsReadOnly (debug_info.il_offsets);
                        }
-           }
+               }
 
                public IList<int> LineNumbers {
                        get {
@@ -240,15 +320,15 @@ namespace Mono.Debugger.Soft
                                        debug_info = vm.conn.Method_GetDebugInfo (id);
                                return Array.AsReadOnly (debug_info.line_numbers);
                        }
-           }
+               }
 
                public string SourceFile {
                        get {
                                if (debug_info == null)
                                        debug_info = vm.conn.Method_GetDebugInfo (id);
-                               return debug_info.filename;
+                               return debug_info.source_files.Length > 0 ? debug_info.source_files [0].source_file : null;
                        }
-           }
+               }
 
                public IList<Location> Locations {
                        get {
@@ -257,24 +337,31 @@ namespace Mono.Debugger.Soft
                                        var line_numbers = LineNumbers;
                                        IList<Location> res = new Location [ILOffsets.Count];
                                        for (int i = 0; i < il_offsets.Count; ++i)
-                                               res [i] = new Location (vm, this, -1, il_offsets [i], SourceFile, line_numbers [i], 0);
+                                               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);
                                        locations = res;
                                }
                                return locations;
                        }
                }                               
 
-               internal int il_offset_to_line_number (int il_offset) {
+               internal int il_offset_to_line_number (int il_offset, out string src_file, out byte[] src_hash, out int column_number) {
                        if (debug_info == null)
                                debug_info = vm.conn.Method_GetDebugInfo (id);
 
                        // FIXME: Optimize this
+                       src_file = null;
+                       src_hash = null;
+                       column_number = 0;
                        for (int i = debug_info.il_offsets.Length - 1; i >= 0; --i) {
-                               if (debug_info.il_offsets [i] <= il_offset)
+                               if (debug_info.il_offsets [i] <= il_offset) {
+                                       src_file = debug_info.source_files [i].source_file;
+                                       src_hash = debug_info.source_files [i].hash;
+                                       column_number = debug_info.column_numbers [i];
                                        return debug_info.line_numbers [i];
+                               }
                        }
                        return -1;
-           }
+               }
 
                public Location LocationAtILOffset (int il_offset) {
                        IList<Location> locs = Locations;
@@ -295,5 +382,5 @@ namespace Mono.Debugger.Soft
                                return meta;
                        }
                }
-    }
+       }
 }