2 using System.Collections.Generic;
3 using System.Reflection;
5 using Mono.Cecil.Metadata;
7 namespace Mono.Debugger.Soft
10 * Represents a type in the remote virtual machine.
11 * It might be better to make this a subclass of Type, but that could be
12 * difficult as some of our methods like GetMethods () return Mirror objects.
14 public class TypeMirror : Mirror
16 MethodMirror[] methods;
19 C.TypeDefinition meta;
20 FieldInfoMirror[] fields;
21 PropertyInfoMirror[] properties;
23 TypeMirror base_type, element_type, gtd;
25 CustomAttributeDataMirror[] cattrs;
27 Dictionary<TypeMirror, InterfaceMappingMirror> iface_map;
28 TypeMirror[] type_args;
30 internal const BindingFlags DefaultBindingFlags =
31 BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance;
33 internal TypeMirror (VirtualMachine vm, long id) : base (vm, id) {
38 return GetInfo ().name;
42 public string Namespace {
48 public AssemblyMirror Assembly {
51 ass = vm.GetAssembly (GetInfo ().assembly);
57 public ModuleMirror Module {
60 module = vm.GetModule (GetInfo ().module);
66 public int MetadataToken {
68 return GetInfo ().token;
72 public TypeAttributes Attributes {
74 return (TypeAttributes)GetInfo ().attributes;
78 public TypeMirror BaseType {
80 // FIXME: base_type could be null for object/interfaces
81 if (base_type == null) {
82 base_type = vm.GetType (GetInfo ().base_type);
88 public int GetArrayRank () {
91 throw new ArgumentException ("Type must be an array type.");
96 public bool IsAbstract {
98 return (Attributes & TypeAttributes.Abstract) != 0;
102 public bool IsAnsiClass {
104 return (Attributes & TypeAttributes.StringFormatMask)
105 == TypeAttributes.AnsiClass;
109 public bool IsArray {
111 return IsArrayImpl ();
115 public bool IsAutoClass {
117 return (Attributes & TypeAttributes.StringFormatMask) == TypeAttributes.AutoClass;
121 public bool IsAutoLayout {
123 return (Attributes & TypeAttributes.LayoutMask) == TypeAttributes.AutoLayout;
127 public bool IsByRef {
129 return IsByRefImpl ();
133 public bool IsClass {
142 public bool IsCOMObject {
144 return IsCOMObjectImpl ();
148 public bool IsContextful {
150 return IsContextfulImpl ();
156 return GetInfo ().is_enum;
160 public bool IsExplicitLayout {
162 return (Attributes & TypeAttributes.LayoutMask) == TypeAttributes.ExplicitLayout;
166 public bool IsImport {
168 return (Attributes & TypeAttributes.Import) != 0;
172 public bool IsInterface {
174 return (Attributes & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface;
178 public bool IsLayoutSequential {
180 return (Attributes & TypeAttributes.LayoutMask) == TypeAttributes.SequentialLayout;
184 public bool IsMarshalByRef {
186 return IsMarshalByRefImpl ();
190 public bool IsNestedAssembly {
192 return (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedAssembly;
196 public bool IsNestedFamANDAssem {
198 return (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamANDAssem;
202 public bool IsNestedFamily {
204 return (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamily;
208 public bool IsNestedFamORAssem {
210 return (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamORAssem;
214 public bool IsNestedPrivate {
216 return (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPrivate;
220 public bool IsNestedPublic {
222 return (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPublic;
226 public bool IsNotPublic {
228 return (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NotPublic;
232 public bool IsPointer {
234 return IsPointerImpl ();
238 public bool IsPrimitive {
240 return IsPrimitiveImpl ();
244 public bool IsPublic {
246 return (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public;
250 public bool IsSealed {
252 return (Attributes & TypeAttributes.Sealed) != 0;
256 public bool IsSerializable {
258 if ((Attributes & TypeAttributes.Serializable) != 0)
266 public bool IsSpecialName {
268 return (Attributes & TypeAttributes.SpecialName) != 0;
272 public bool IsUnicodeClass {
274 return (Attributes & TypeAttributes.StringFormatMask) == TypeAttributes.UnicodeClass;
278 public bool IsValueType {
280 return IsValueTypeImpl ();
284 public bool HasElementType {
286 return HasElementTypeImpl ();
290 // Since protocol version 2.12
291 public bool IsGenericTypeDefinition {
293 vm.CheckProtocolVersion (2, 12);
299 public bool IsGenericType {
301 if (vm.Version.AtLeast (2, 12)) {
302 return GetInfo ().is_generic_type;
304 return Name.IndexOf ('`') != -1;
309 public TypeMirror GetElementType () {
311 if (element_type == null && info.element_type != 0)
312 element_type = vm.GetType (info.element_type);
316 public TypeMirror GetGenericTypeDefinition () {
317 vm.CheckProtocolVersion (2, 12);
321 throw new InvalidOperationException ();
322 gtd = vm.GetType (info.gtd);
327 // Since protocol version 2.15
328 public TypeMirror[] GetGenericArguments () {
329 vm.CheckProtocolVersion (2, 15);
330 if (type_args == null)
331 type_args = vm.GetTypes (GetInfo ().type_args);
335 public string FullName {
337 return GetInfo ().full_name;
341 public string CSharpName {
344 if (GetArrayRank () == 1)
345 return GetElementType ().CSharpName + "[]";
348 for (int i = 0; i < GetArrayRank (); ++i)
350 return GetElementType ().CSharpName + "[" + ranks + "]";
365 // FIXME: Only do this for real corlib types
366 if (Namespace == "System") {
380 public MethodMirror[] GetMethods () {
381 if (methods == null) {
382 long[] ids = vm.conn.Type_GetMethods (id);
383 MethodMirror[] m = new MethodMirror [ids.Length];
384 for (int i = 0; i < ids.Length; ++i) {
385 m [i] = vm.GetMethod (ids [i]);
392 // FIXME: Sync this with Type
393 public MethodMirror GetMethod (string name) {
394 foreach (var m in GetMethods ())
400 public FieldInfoMirror[] GetFields () {
407 long[] ids = vm.conn.Type_GetFields (id, out names, out types, out attrs);
409 FieldInfoMirror[] res = new FieldInfoMirror [ids.Length];
410 for (int i = 0; i < res.Length; ++i)
411 res [i] = new FieldInfoMirror (this, ids [i], names [i], vm.GetType (types [i]), (FieldAttributes)attrs [i]);
417 public FieldInfoMirror GetField (string name) {
419 throw new ArgumentNullException ("name");
420 foreach (var f in GetFields ())
426 public TypeMirror[] GetNestedTypes ()
428 return GetNestedTypes (DefaultBindingFlags);
431 public TypeMirror[] GetNestedTypes (BindingFlags bindingAttr) {
435 // FIXME: bindingAttr
437 var arr = new TypeMirror [info.nested.Length];
438 for (int i = 0; i < arr.Length; ++i)
439 arr [i] = vm.GetType (info.nested [i]);
445 public PropertyInfoMirror[] GetProperties () {
446 return GetProperties (DefaultBindingFlags);
449 public PropertyInfoMirror[] GetProperties (BindingFlags bindingAttr) {
450 if (properties != null)
453 PropInfo[] info = vm.conn.Type_GetProperties (id);
455 PropertyInfoMirror[] res = new PropertyInfoMirror [info.Length];
456 for (int i = 0; i < res.Length; ++i)
457 res [i] = new PropertyInfoMirror (this, info [i].id, info [i].name, vm.GetMethod (info [i].get_method), vm.GetMethod (info [i].set_method), (PropertyAttributes)info [i].attrs);
463 public PropertyInfoMirror GetProperty (string name) {
465 throw new ArgumentNullException ("name");
466 foreach (var p in GetProperties ())
472 public virtual bool IsAssignableFrom (TypeMirror c) {
474 throw new ArgumentNullException ("c");
478 // This is complex so do it in the debuggee
479 return vm.conn.Type_IsAssignableFrom (id, c.Id);
482 public Value GetValue (FieldInfoMirror field) {
483 return GetValues (new FieldInfoMirror [] { field }) [0];
486 public Value[] GetValues (IList<FieldInfoMirror> fields, ThreadMirror thread) {
488 throw new ArgumentNullException ("fields");
489 foreach (FieldInfoMirror f in fields) {
491 throw new ArgumentNullException ("field");
494 long[] ids = new long [fields.Count];
495 for (int i = 0; i < fields.Count; ++i)
496 ids [i] = fields [i].Id;
498 return vm.DecodeValues (vm.conn.Type_GetValues (id, ids, thread != null ? thread.Id : 0));
499 } catch (CommandException ex) {
500 if (ex.ErrorCode == ErrorCode.INVALID_FIELDID)
501 throw new ArgumentException ("One of the fields is not valid for this type.", "fields");
507 public Value[] GetValues (IList<FieldInfoMirror> fields) {
508 return GetValues (fields, null);
512 * Return the value of the [ThreadStatic] field FIELD on the thread THREAD.
514 public Value GetValue (FieldInfoMirror field, ThreadMirror thread) {
516 throw new ArgumentNullException ("thread");
517 CheckMirror (thread);
518 return GetValues (new FieldInfoMirror [] { field }, thread) [0];
521 public void SetValues (IList<FieldInfoMirror> fields, Value[] values) {
523 throw new ArgumentNullException ("fields");
525 throw new ArgumentNullException ("values");
526 foreach (FieldInfoMirror f in fields) {
528 throw new ArgumentNullException ("field");
531 foreach (Value v in values) {
533 throw new ArgumentNullException ("values");
536 long[] ids = new long [fields.Count];
537 for (int i = 0; i < fields.Count; ++i)
538 ids [i] = fields [i].Id;
540 vm.conn.Type_SetValues (id, ids, vm.EncodeValues (values));
541 } catch (CommandException ex) {
542 if (ex.ErrorCode == ErrorCode.INVALID_FIELDID)
543 throw new ArgumentException ("One of the fields is not valid for this type.", "fields");
549 public void SetValue (FieldInfoMirror field, Value value) {
550 SetValues (new FieldInfoMirror [] { field }, new Value [] { value });
553 public ObjectMirror GetTypeObject () {
554 return vm.GetObject (vm.conn.Type_GetObject (id));
558 * Return a list of source files without path info, where methods of
559 * this type are defined. Return an empty list if the information is not
561 * This can be used by a debugger to find out which types occur in a
562 * given source file, to filter the list of methods whose locations
563 * have to be checked when placing breakpoints.
565 public string[] GetSourceFiles () {
566 return GetSourceFiles (false);
569 string[] source_files;
570 string[] source_files_full_path;
571 public string[] GetSourceFiles (bool return_full_paths) {
572 string[] res = return_full_paths ? source_files_full_path : source_files;
574 res = vm.conn.Type_GetSourceFiles (id, return_full_paths);
575 if (return_full_paths)
576 source_files_full_path = res;
583 public C.TypeDefinition Metadata {
586 if (Assembly.Metadata == null || MetadataToken == 0)
588 meta = (C.TypeDefinition)Assembly.Metadata.MainModule.LookupToken (MetadataToken);
594 TypeInfo GetInfo () {
596 info = vm.conn.Type_GetInfo (id);
600 protected virtual TypeAttributes GetAttributeFlagsImpl () {
601 return (TypeAttributes)GetInfo ().attributes;
604 protected virtual bool HasElementTypeImpl () {
605 return IsArray || IsByRef || IsPointer;
608 protected virtual bool IsArrayImpl () {
609 return GetInfo ().rank > 0;
612 protected virtual bool IsByRefImpl () {
613 return GetInfo ().is_byref;
616 protected virtual bool IsCOMObjectImpl () {
620 protected virtual bool IsPointerImpl () {
621 return GetInfo ().is_pointer;
624 protected virtual bool IsPrimitiveImpl () {
625 return GetInfo ().is_primitive;
628 protected virtual bool IsValueTypeImpl ()
630 return GetInfo ().is_valuetype;
633 protected virtual bool IsContextfulImpl ()
639 protected virtual bool IsMarshalByRefImpl ()
645 // Same as Enum.GetUnderlyingType ()
646 public TypeMirror EnumUnderlyingType {
649 throw new ArgumentException ("Type is not an enum type.");
650 foreach (FieldInfoMirror f in GetFields ()) {
654 throw new NotImplementedException ();
659 * Creating the custom attributes themselves could modify the behavior of the
660 * debuggee, so we return objects similar to the CustomAttributeData objects
661 * used by the reflection-only functionality on .net.
663 public CustomAttributeDataMirror[] GetCustomAttributes (bool inherit) {
664 return GetCAttrs (null, inherit);
667 public CustomAttributeDataMirror[] GetCustomAttributes (TypeMirror attributeType, bool inherit) {
668 if (attributeType == null)
669 throw new ArgumentNullException ("attributeType");
670 return GetCAttrs (attributeType, inherit);
673 CustomAttributeDataMirror[] GetCAttrs (TypeMirror type, bool inherit) {
674 if (cattrs == null && Metadata != null && !Metadata.HasCustomAttributes)
675 cattrs = new CustomAttributeDataMirror [0];
677 // FIXME: Handle inherit
678 if (cattrs == null) {
679 CattrInfo[] info = vm.conn.Type_GetCustomAttributes (id, 0, false);
680 cattrs = CustomAttributeDataMirror.Create (vm, info);
682 var res = new List<CustomAttributeDataMirror> ();
683 foreach (var attr in cattrs)
684 if (type == null || attr.Constructor.DeclaringType == type)
686 return res.ToArray ();
689 public MethodMirror[] GetMethodsByNameFlags (string name, BindingFlags flags, bool ignoreCase) {
690 if (vm.conn.Version.AtLeast (2, 6)) {
691 long[] ids = vm.conn.Type_GetMethodsByNameFlags (id, name, (int)flags, ignoreCase);
692 MethodMirror[] m = new MethodMirror [ids.Length];
693 for (int i = 0; i < ids.Length; ++i)
694 m [i] = vm.GetMethod (ids [i]);
697 if ((flags & BindingFlags.IgnoreCase) != 0) {
698 flags &= ~BindingFlags.IgnoreCase;
702 if (flags == BindingFlags.Default)
703 flags = BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance|BindingFlags.Static;
705 MethodAttributes access = (MethodAttributes) 0;
706 bool matchInstance = false;
707 bool matchStatic = false;
709 if ((flags & BindingFlags.NonPublic) != 0) {
710 access |= MethodAttributes.Private;
711 flags &= ~BindingFlags.NonPublic;
713 if ((flags & BindingFlags.Public) != 0) {
714 access |= MethodAttributes.Public;
715 flags &= ~BindingFlags.Public;
717 if ((flags & BindingFlags.Instance) != 0) {
718 flags &= ~BindingFlags.Instance;
719 matchInstance = true;
721 if ((flags & BindingFlags.Static) != 0) {
722 flags &= ~BindingFlags.Static;
726 if ((int) flags != 0)
727 throw new NotImplementedException ();
729 var res = new List<MethodMirror> ();
730 foreach (MethodMirror m in GetMethods ()) {
731 if ((m.Attributes & access) == (MethodAttributes) 0)
734 if (!((matchStatic && m.IsStatic) || (matchInstance && !m.IsStatic)))
737 if ((!ignoreCase && m.Name == name) || (ignoreCase && m.Name.Equals (name, StringComparison.CurrentCultureIgnoreCase)))
740 return res.ToArray ();
744 public Value InvokeMethod (ThreadMirror thread, MethodMirror method, IList<Value> arguments) {
745 return ObjectMirror.InvokeMethod (vm, thread, method, null, arguments, InvokeOptions.None);
748 public Value InvokeMethod (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options) {
749 return ObjectMirror.InvokeMethod (vm, thread, method, null, arguments, options);
752 [Obsolete ("Use the overload without the 'vm' argument")]
753 public IAsyncResult BeginInvokeMethod (VirtualMachine vm, ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options, AsyncCallback callback, object state) {
754 return ObjectMirror.BeginInvokeMethod (vm, thread, method, null, arguments, options, callback, state);
757 public IAsyncResult BeginInvokeMethod (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options, AsyncCallback callback, object state) {
758 return ObjectMirror.BeginInvokeMethod (vm, thread, method, null, arguments, options, callback, state);
761 public Value EndInvokeMethod (IAsyncResult asyncResult) {
762 return ObjectMirror.EndInvokeMethodInternal (asyncResult);
765 public Value NewInstance (ThreadMirror thread, MethodMirror method, IList<Value> arguments) {
766 return ObjectMirror.InvokeMethod (vm, thread, method, null, arguments, InvokeOptions.None);
769 public Value NewInstance (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options) {
770 return ObjectMirror.InvokeMethod (vm, thread, method, null, arguments, options);
773 // Since protocol version 2.11
774 public TypeMirror[] GetInterfaces () {
776 ifaces = vm.GetTypes (vm.conn.Type_GetInterfaces (id));
780 // Since protocol version 2.11
781 public InterfaceMappingMirror GetInterfaceMap (TypeMirror interfaceType) {
782 if (interfaceType == null)
783 throw new ArgumentNullException ("interfaceType");
784 if (!interfaceType.IsInterface)
785 throw new ArgumentException ("Argument must be an interface.", "interfaceType");
787 throw new ArgumentException ("'this' type cannot be an interface itself");
789 if (iface_map == null) {
790 // Query the info in bulk
792 var ids = new long [ifaces.Length];
793 for (int i = 0; i < ifaces.Length; ++i)
794 ids [i] = ifaces [i].Id;
796 var ifacemap = vm.conn.Type_GetInterfaceMap (id, ids);
798 var imap = new Dictionary<TypeMirror, InterfaceMappingMirror> ();
799 for (int i = 0; i < ifacemap.Length; ++i) {
800 IfaceMapInfo info = ifacemap [i];
802 MethodMirror[] imethods = new MethodMirror [info.iface_methods.Length];
803 for (int j = 0; j < info.iface_methods.Length; ++j)
804 imethods [j] = vm.GetMethod (info.iface_methods [j]);
806 MethodMirror[] tmethods = new MethodMirror [info.iface_methods.Length];
807 for (int j = 0; j < info.target_methods.Length; ++j)
808 tmethods [j] = vm.GetMethod (info.target_methods [j]);
810 InterfaceMappingMirror map = new InterfaceMappingMirror (vm, this, vm.GetType (info.iface_id), imethods, tmethods);
812 imap [map.InterfaceType] = map;
818 InterfaceMappingMirror res;
819 if (!iface_map.TryGetValue (interfaceType, out res))
820 throw new ArgumentException ("Interface not found", "interfaceType");