X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2FMono.Debugger.Soft%2FMono.Debugger.Soft%2FTypeMirror.cs;h=e7baa44fae09943942b1353621458bebe76374b9;hb=3fb128ac0de7cca459098c2dc3359d81f5e48353;hp=d73b2df372cb3742ee9b557bc0515b88d48bb913;hpb=8ef4e4703172fd32ada3f74b22df5203b4683493;p=mono.git diff --git a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/TypeMirror.cs b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/TypeMirror.cs index d73b2df372c..e7baa44fae0 100644 --- a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/TypeMirror.cs +++ b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/TypeMirror.cs @@ -3,6 +3,9 @@ using System.Collections.Generic; using System.Reflection; using C = Mono.Cecil; using Mono.Cecil.Metadata; +#if NET_4_5 +using System.Threading.Tasks; +#endif namespace Mono.Debugger.Soft { @@ -20,9 +23,14 @@ namespace Mono.Debugger.Soft FieldInfoMirror[] fields; PropertyInfoMirror[] properties; TypeInfo info; - TypeMirror base_type, element_type; + TypeMirror base_type, element_type, gtd; TypeMirror[] nested; CustomAttributeDataMirror[] cattrs; + TypeMirror[] ifaces; + Dictionary iface_map; + TypeMirror[] type_args; + bool cached_base_type; + bool inited; internal const BindingFlags DefaultBindingFlags = BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance; @@ -34,13 +42,13 @@ namespace Mono.Debugger.Soft get { return GetInfo ().name; } - } + } public string Namespace { get { return GetInfo ().ns; } - } + } public AssemblyMirror Assembly { get { @@ -74,9 +82,9 @@ namespace Mono.Debugger.Soft public TypeMirror BaseType { get { - // FIXME: base_type could be null for object/interfaces - if (base_type == null) { + if (!cached_base_type) { base_type = vm.GetType (GetInfo ().base_type); + cached_base_type = true; } return base_type; } @@ -284,6 +292,25 @@ namespace Mono.Debugger.Soft } } + // Since protocol version 2.12 + public bool IsGenericTypeDefinition { + get { + vm.CheckProtocolVersion (2, 12); + GetInfo (); + return info.is_gtd; + } + } + + public bool IsGenericType { + get { + if (vm.Version.AtLeast (2, 12)) { + return GetInfo ().is_generic_type; + } else { + return Name.IndexOf ('`') != -1; + } + } + } + public TypeMirror GetElementType () { GetInfo (); if (element_type == null && info.element_type != 0) @@ -291,6 +318,25 @@ namespace Mono.Debugger.Soft return element_type; } + public TypeMirror GetGenericTypeDefinition () { + vm.CheckProtocolVersion (2, 12); + GetInfo (); + if (gtd == null) { + if (info.gtd == 0) + throw new InvalidOperationException (); + gtd = vm.GetType (info.gtd); + } + return gtd; + } + + // 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 string FullName { get { return GetInfo ().full_name; @@ -313,8 +359,26 @@ namespace Mono.Debugger.Soft switch (Name) { case "Byte": return "byte"; + case "Sbyte": + return "sbyte"; + case "Char": + return "char"; + case "UInt16": + return "ushort"; + case "Int16": + return "short"; + case "UInt32": + return "uint"; case "Int32": return "int"; + case "UInt64": + return "ulong"; + case "Int64": + return "long"; + case "Single": + return "float"; + case "Double": + return "double"; case "Boolean": return "bool"; default: @@ -325,6 +389,10 @@ namespace Mono.Debugger.Soft if (Namespace == "System") { string s = Name; switch (s) { + case "Decimal": + return "decimal"; + case "Object": + return "object"; case "String": return "string"; default: @@ -442,7 +510,7 @@ namespace Mono.Debugger.Soft return GetValues (new FieldInfoMirror [] { field }) [0]; } - public Value[] GetValues (IList fields) { + public Value[] GetValues (IList fields, ThreadMirror thread) { if (fields == null) throw new ArgumentNullException ("fields"); foreach (FieldInfoMirror f in fields) { @@ -454,7 +522,7 @@ namespace Mono.Debugger.Soft for (int i = 0; i < fields.Count; ++i) ids [i] = fields [i].Id; try { - return vm.DecodeValues (vm.conn.Type_GetValues (id, ids)); + return vm.DecodeValues (vm.conn.Type_GetValues (id, ids, thread != null ? thread.Id : 0)); } catch (CommandException ex) { if (ex.ErrorCode == ErrorCode.INVALID_FIELDID) throw new ArgumentException ("One of the fields is not valid for this type.", "fields"); @@ -463,6 +531,20 @@ namespace Mono.Debugger.Soft } } + public Value[] GetValues (IList fields) { + return GetValues (fields, null); + } + + /* + * Return the value of the [ThreadStatic] field FIELD on the thread THREAD. + */ + public Value GetValue (FieldInfoMirror field, ThreadMirror thread) { + if (thread == null) + throw new ArgumentNullException ("thread"); + CheckMirror (thread); + return GetValues (new FieldInfoMirror [] { field }, thread) [0]; + } + public void SetValues (IList fields, Value[] values) { if (fields == null) throw new ArgumentNullException ("fields"); @@ -508,7 +590,21 @@ namespace Mono.Debugger.Soft * have to be checked when placing breakpoints. */ public string[] GetSourceFiles () { - return vm.conn.Type_GetSourceFiles (id); + return GetSourceFiles (false); + } + + string[] source_files; + string[] source_files_full_path; + public string[] GetSourceFiles (bool returnFullPaths) { + string[] res = returnFullPaths ? source_files_full_path : source_files; + if (res == null) { + res = vm.conn.Type_GetSourceFiles (id, returnFullPaths); + if (returnFullPaths) + source_files_full_path = res; + else + source_files = res; + } + return res; } public C.TypeDefinition Metadata { @@ -516,7 +612,7 @@ namespace Mono.Debugger.Soft if (meta == null) { if (Assembly.Metadata == null || MetadataToken == 0) return null; - meta = (C.TypeDefinition)Assembly.Metadata.MainModule.LookupByToken (new MetadataToken (MetadataToken)); + meta = (C.TypeDefinition)Assembly.Metadata.MainModule.LookupToken (MetadataToken); } return meta; } @@ -592,26 +688,93 @@ namespace Mono.Debugger.Soft * used by the reflection-only functionality on .net. */ public CustomAttributeDataMirror[] GetCustomAttributes (bool inherit) { - return GetCAttrs (null, inherit); + return GetCustomAttrs (null, inherit); } public CustomAttributeDataMirror[] GetCustomAttributes (TypeMirror attributeType, bool inherit) { if (attributeType == null) throw new ArgumentNullException ("attributeType"); - return GetCAttrs (attributeType, inherit); + return GetCustomAttrs (attributeType, inherit); } - CustomAttributeDataMirror[] GetCAttrs (TypeMirror type, bool inherit) { - // FIXME: Handle inherit + void AppendCustomAttrs (IList attrs, TypeMirror type, bool inherit) + { + if (cattrs == null && Metadata != null && !Metadata.HasCustomAttributes) + cattrs = new CustomAttributeDataMirror [0]; + if (cattrs == null) { CattrInfo[] info = vm.conn.Type_GetCustomAttributes (id, 0, false); cattrs = CustomAttributeDataMirror.Create (vm, info); } - var res = new List (); - foreach (var attr in cattrs) + + foreach (var attr in cattrs) { if (type == null || attr.Constructor.DeclaringType == type) - res.Add (attr); - return res.ToArray (); + attrs.Add (attr); + } + + if (inherit && BaseType != null) + BaseType.AppendCustomAttrs (attrs, type, inherit); + } + + CustomAttributeDataMirror[] GetCustomAttrs (TypeMirror type, bool inherit) { + var attrs = new List (); + AppendCustomAttrs (attrs, type, inherit); + return attrs.ToArray (); + } + + public MethodMirror[] GetMethodsByNameFlags (string name, BindingFlags flags, bool ignoreCase) { + if (vm.conn.Version.AtLeast (2, 6)) { + long[] ids = vm.conn.Type_GetMethodsByNameFlags (id, name, (int)flags, ignoreCase); + MethodMirror[] m = new MethodMirror [ids.Length]; + for (int i = 0; i < ids.Length; ++i) + m [i] = vm.GetMethod (ids [i]); + return m; + } else { + if ((flags & BindingFlags.IgnoreCase) != 0) { + flags &= ~BindingFlags.IgnoreCase; + ignoreCase = true; + } + + if (flags == BindingFlags.Default) + flags = BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance|BindingFlags.Static; + + MethodAttributes access = (MethodAttributes) 0; + bool matchInstance = false; + bool matchStatic = false; + + if ((flags & BindingFlags.NonPublic) != 0) { + access |= MethodAttributes.Private; + flags &= ~BindingFlags.NonPublic; + } + if ((flags & BindingFlags.Public) != 0) { + access |= MethodAttributes.Public; + flags &= ~BindingFlags.Public; + } + if ((flags & BindingFlags.Instance) != 0) { + flags &= ~BindingFlags.Instance; + matchInstance = true; + } + if ((flags & BindingFlags.Static) != 0) { + flags &= ~BindingFlags.Static; + matchStatic = true; + } + + if ((int) flags != 0) + throw new NotImplementedException (); + + var res = new List (); + foreach (MethodMirror m in GetMethods ()) { + if ((m.Attributes & access) == (MethodAttributes) 0) + continue; + + if (!((matchStatic && m.IsStatic) || (matchInstance && !m.IsStatic))) + continue; + + if ((!ignoreCase && m.Name == name) || (ignoreCase && m.Name.Equals (name, StringComparison.CurrentCultureIgnoreCase))) + res.Add (m); + } + return res.ToArray (); + } } public Value InvokeMethod (ThreadMirror thread, MethodMirror method, IList arguments) { @@ -635,12 +798,91 @@ namespace Mono.Debugger.Soft return ObjectMirror.EndInvokeMethodInternal (asyncResult); } +#if NET_4_5 + public Task InvokeMethodAsync (ThreadMirror thread, MethodMirror method, IList arguments, InvokeOptions options = InvokeOptions.None) { + var tcs = new TaskCompletionSource (); + BeginInvokeMethod (thread, method, arguments, options, iar => + { + try { + tcs.SetResult (EndInvokeMethod (iar)); + } catch (OperationCanceledException) { + tcs.TrySetCanceled (); + } catch (Exception ex) { + tcs.TrySetException (ex); + } + }, null); + return tcs.Task; + } +#endif + public Value NewInstance (ThreadMirror thread, MethodMirror method, IList arguments) { return ObjectMirror.InvokeMethod (vm, thread, method, null, arguments, InvokeOptions.None); } public Value NewInstance (ThreadMirror thread, MethodMirror method, IList arguments, InvokeOptions options) { return ObjectMirror.InvokeMethod (vm, thread, method, null, arguments, options); - } + } + + // Since protocol version 2.11 + public TypeMirror[] GetInterfaces () { + if (ifaces == null) + ifaces = vm.GetTypes (vm.conn.Type_GetInterfaces (id)); + return ifaces; + } + + // Since protocol version 2.11 + public InterfaceMappingMirror GetInterfaceMap (TypeMirror interfaceType) { + if (interfaceType == null) + throw new ArgumentNullException ("interfaceType"); + if (!interfaceType.IsInterface) + throw new ArgumentException ("Argument must be an interface.", "interfaceType"); + if (IsInterface) + throw new ArgumentException ("'this' type cannot be an interface itself"); + + if (iface_map == null) { + // Query the info in bulk + GetInterfaces (); + var ids = new long [ifaces.Length]; + for (int i = 0; i < ifaces.Length; ++i) + ids [i] = ifaces [i].Id; + + var ifacemap = vm.conn.Type_GetInterfaceMap (id, ids); + + var imap = new Dictionary (); + for (int i = 0; i < ifacemap.Length; ++i) { + IfaceMapInfo info = ifacemap [i]; + + MethodMirror[] imethods = new MethodMirror [info.iface_methods.Length]; + for (int j = 0; j < info.iface_methods.Length; ++j) + imethods [j] = vm.GetMethod (info.iface_methods [j]); + + MethodMirror[] tmethods = new MethodMirror [info.iface_methods.Length]; + for (int j = 0; j < info.target_methods.Length; ++j) + tmethods [j] = vm.GetMethod (info.target_methods [j]); + + InterfaceMappingMirror map = new InterfaceMappingMirror (vm, this, vm.GetType (info.iface_id), imethods, tmethods); + + imap [map.InterfaceType] = map; + } + + iface_map = imap; + } + + InterfaceMappingMirror res; + if (!iface_map.TryGetValue (interfaceType, out res)) + throw new ArgumentException ("Interface not found", "interfaceType"); + return res; + } + + // Return whenever the type initializer of this type has ran + // Since protocol version 2.23 + public bool IsInitialized { + get { + vm.CheckProtocolVersion (2, 23); + if (!inited) + inited = vm.conn.Type_IsInitialized (id); + return inited; + } + } } }