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;
25 CustomAttributeDataMirror[] cattrs;
27 internal const BindingFlags DefaultBindingFlags =
28 BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance;
30 internal TypeMirror (VirtualMachine vm, long id) : base (vm, id) {
35 return GetInfo ().name;
39 public string Namespace {
45 public AssemblyMirror Assembly {
48 ass = vm.GetAssembly (GetInfo ().assembly);
54 public ModuleMirror Module {
57 module = vm.GetModule (GetInfo ().module);
63 public int MetadataToken {
65 return GetInfo ().token;
69 public TypeAttributes Attributes {
71 return (TypeAttributes)GetInfo ().attributes;
75 public TypeMirror BaseType {
77 // FIXME: base_type could be null for object/interfaces
78 if (base_type == null) {
79 base_type = vm.GetType (GetInfo ().base_type);
85 public int GetArrayRank () {
88 throw new ArgumentException ("Type must be an array type.");
93 public bool IsAbstract {
95 return (Attributes & TypeAttributes.Abstract) != 0;
99 public bool IsAnsiClass {
101 return (Attributes & TypeAttributes.StringFormatMask)
102 == TypeAttributes.AnsiClass;
106 public bool IsArray {
108 return IsArrayImpl ();
112 public bool IsAutoClass {
114 return (Attributes & TypeAttributes.StringFormatMask) == TypeAttributes.AutoClass;
118 public bool IsAutoLayout {
120 return (Attributes & TypeAttributes.LayoutMask) == TypeAttributes.AutoLayout;
124 public bool IsByRef {
126 return IsByRefImpl ();
130 public bool IsClass {
139 public bool IsCOMObject {
141 return IsCOMObjectImpl ();
145 public bool IsContextful {
147 return IsContextfulImpl ();
153 return GetInfo ().is_enum;
157 public bool IsExplicitLayout {
159 return (Attributes & TypeAttributes.LayoutMask) == TypeAttributes.ExplicitLayout;
163 public bool IsImport {
165 return (Attributes & TypeAttributes.Import) != 0;
169 public bool IsInterface {
171 return (Attributes & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface;
175 public bool IsLayoutSequential {
177 return (Attributes & TypeAttributes.LayoutMask) == TypeAttributes.SequentialLayout;
181 public bool IsMarshalByRef {
183 return IsMarshalByRefImpl ();
187 public bool IsNestedAssembly {
189 return (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedAssembly;
193 public bool IsNestedFamANDAssem {
195 return (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamANDAssem;
199 public bool IsNestedFamily {
201 return (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamily;
205 public bool IsNestedFamORAssem {
207 return (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamORAssem;
211 public bool IsNestedPrivate {
213 return (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPrivate;
217 public bool IsNestedPublic {
219 return (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPublic;
223 public bool IsNotPublic {
225 return (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NotPublic;
229 public bool IsPointer {
231 return IsPointerImpl ();
235 public bool IsPrimitive {
237 return IsPrimitiveImpl ();
241 public bool IsPublic {
243 return (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public;
247 public bool IsSealed {
249 return (Attributes & TypeAttributes.Sealed) != 0;
253 public bool IsSerializable {
255 if ((Attributes & TypeAttributes.Serializable) != 0)
263 public bool IsSpecialName {
265 return (Attributes & TypeAttributes.SpecialName) != 0;
269 public bool IsUnicodeClass {
271 return (Attributes & TypeAttributes.StringFormatMask) == TypeAttributes.UnicodeClass;
275 public bool IsValueType {
277 return IsValueTypeImpl ();
281 public bool HasElementType {
283 return HasElementTypeImpl ();
287 public TypeMirror GetElementType () {
289 if (element_type == null && info.element_type != 0)
290 element_type = vm.GetType (info.element_type);
294 public string FullName {
296 return GetInfo ().full_name;
300 public string CSharpName {
303 if (GetArrayRank () == 1)
304 return GetElementType ().CSharpName + "[]";
307 for (int i = 0; i < GetArrayRank (); ++i)
309 return GetElementType ().CSharpName + "[" + ranks + "]";
324 // FIXME: Only do this for real corlib types
325 if (Namespace == "System") {
339 public MethodMirror[] GetMethods () {
340 if (methods == null) {
341 long[] ids = vm.conn.Type_GetMethods (id);
342 MethodMirror[] m = new MethodMirror [ids.Length];
343 for (int i = 0; i < ids.Length; ++i) {
344 m [i] = vm.GetMethod (ids [i]);
351 // FIXME: Sync this with Type
352 public MethodMirror GetMethod (string name) {
353 foreach (var m in GetMethods ())
359 public FieldInfoMirror[] GetFields () {
366 long[] ids = vm.conn.Type_GetFields (id, out names, out types, out attrs);
368 FieldInfoMirror[] res = new FieldInfoMirror [ids.Length];
369 for (int i = 0; i < res.Length; ++i)
370 res [i] = new FieldInfoMirror (this, ids [i], names [i], vm.GetType (types [i]), (FieldAttributes)attrs [i]);
376 public FieldInfoMirror GetField (string name) {
378 throw new ArgumentNullException ("name");
379 foreach (var f in GetFields ())
385 public TypeMirror[] GetNestedTypes ()
387 return GetNestedTypes (DefaultBindingFlags);
390 public TypeMirror[] GetNestedTypes (BindingFlags bindingAttr) {
394 // FIXME: bindingAttr
396 var arr = new TypeMirror [info.nested.Length];
397 for (int i = 0; i < arr.Length; ++i)
398 arr [i] = vm.GetType (info.nested [i]);
404 public PropertyInfoMirror[] GetProperties () {
405 return GetProperties (DefaultBindingFlags);
408 public PropertyInfoMirror[] GetProperties (BindingFlags bindingAttr) {
409 if (properties != null)
412 PropInfo[] info = vm.conn.Type_GetProperties (id);
414 PropertyInfoMirror[] res = new PropertyInfoMirror [info.Length];
415 for (int i = 0; i < res.Length; ++i)
416 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);
422 public PropertyInfoMirror GetProperty (string name) {
424 throw new ArgumentNullException ("name");
425 foreach (var p in GetProperties ())
431 public virtual bool IsAssignableFrom (TypeMirror c) {
433 throw new ArgumentNullException ("c");
437 // This is complex so do it in the debuggee
438 return vm.conn.Type_IsAssignableFrom (id, c.Id);
441 public Value GetValue (FieldInfoMirror field) {
442 return GetValues (new FieldInfoMirror [] { field }) [0];
445 public Value[] GetValues (IList<FieldInfoMirror> fields, ThreadMirror thread) {
447 throw new ArgumentNullException ("fields");
448 foreach (FieldInfoMirror f in fields) {
450 throw new ArgumentNullException ("field");
453 long[] ids = new long [fields.Count];
454 for (int i = 0; i < fields.Count; ++i)
455 ids [i] = fields [i].Id;
457 return vm.DecodeValues (vm.conn.Type_GetValues (id, ids, thread != null ? thread.Id : 0));
458 } catch (CommandException ex) {
459 if (ex.ErrorCode == ErrorCode.INVALID_FIELDID)
460 throw new ArgumentException ("One of the fields is not valid for this type.", "fields");
466 public Value[] GetValues (IList<FieldInfoMirror> fields) {
467 return GetValues (fields, null);
471 * Return the value of the [ThreadStatic] field FIELD on the thread THREAD.
473 public Value GetValue (FieldInfoMirror field, ThreadMirror thread) {
475 throw new ArgumentNullException ("thread");
476 CheckMirror (thread);
477 return GetValues (new FieldInfoMirror [] { field }, thread) [0];
480 public void SetValues (IList<FieldInfoMirror> fields, Value[] values) {
482 throw new ArgumentNullException ("fields");
484 throw new ArgumentNullException ("values");
485 foreach (FieldInfoMirror f in fields) {
487 throw new ArgumentNullException ("field");
490 foreach (Value v in values) {
492 throw new ArgumentNullException ("values");
495 long[] ids = new long [fields.Count];
496 for (int i = 0; i < fields.Count; ++i)
497 ids [i] = fields [i].Id;
499 vm.conn.Type_SetValues (id, ids, vm.EncodeValues (values));
500 } catch (CommandException ex) {
501 if (ex.ErrorCode == ErrorCode.INVALID_FIELDID)
502 throw new ArgumentException ("One of the fields is not valid for this type.", "fields");
508 public void SetValue (FieldInfoMirror field, Value value) {
509 SetValues (new FieldInfoMirror [] { field }, new Value [] { value });
512 public ObjectMirror GetTypeObject () {
513 return vm.GetObject (vm.conn.Type_GetObject (id));
517 * Return a list of source files without path info, where methods of
518 * this type are defined. Return an empty list if the information is not
520 * This can be used by a debugger to find out which types occur in a
521 * given source file, to filter the list of methods whose locations
522 * have to be checked when placing breakpoints.
524 public string[] GetSourceFiles () {
525 return GetSourceFiles (false);
528 string[] source_files;
529 string[] source_files_full_path;
530 public string[] GetSourceFiles (bool return_full_paths) {
531 string[] res = return_full_paths ? source_files_full_path : source_files;
533 res = vm.conn.Type_GetSourceFiles (id, return_full_paths);
534 if (return_full_paths)
535 source_files_full_path = res;
542 public C.TypeDefinition Metadata {
545 if (Assembly.Metadata == null || MetadataToken == 0)
547 meta = (C.TypeDefinition)Assembly.Metadata.MainModule.LookupToken (MetadataToken);
553 TypeInfo GetInfo () {
555 info = vm.conn.Type_GetInfo (id);
559 protected virtual TypeAttributes GetAttributeFlagsImpl () {
560 return (TypeAttributes)GetInfo ().attributes;
563 protected virtual bool HasElementTypeImpl () {
564 return IsArray || IsByRef || IsPointer;
567 protected virtual bool IsArrayImpl () {
568 return GetInfo ().rank > 0;
571 protected virtual bool IsByRefImpl () {
572 return GetInfo ().is_byref;
575 protected virtual bool IsCOMObjectImpl () {
579 protected virtual bool IsPointerImpl () {
580 return GetInfo ().is_pointer;
583 protected virtual bool IsPrimitiveImpl () {
584 return GetInfo ().is_primitive;
587 protected virtual bool IsValueTypeImpl ()
589 return GetInfo ().is_valuetype;
592 protected virtual bool IsContextfulImpl ()
598 protected virtual bool IsMarshalByRefImpl ()
604 // Same as Enum.GetUnderlyingType ()
605 public TypeMirror EnumUnderlyingType {
608 throw new ArgumentException ("Type is not an enum type.");
609 foreach (FieldInfoMirror f in GetFields ()) {
613 throw new NotImplementedException ();
618 * Creating the custom attributes themselves could modify the behavior of the
619 * debuggee, so we return objects similar to the CustomAttributeData objects
620 * used by the reflection-only functionality on .net.
622 public CustomAttributeDataMirror[] GetCustomAttributes (bool inherit) {
623 return GetCAttrs (null, inherit);
626 public CustomAttributeDataMirror[] GetCustomAttributes (TypeMirror attributeType, bool inherit) {
627 if (attributeType == null)
628 throw new ArgumentNullException ("attributeType");
629 return GetCAttrs (attributeType, inherit);
632 CustomAttributeDataMirror[] GetCAttrs (TypeMirror type, bool inherit) {
633 if (cattrs == null && Metadata != null && !Metadata.HasCustomAttributes)
634 cattrs = new CustomAttributeDataMirror [0];
636 // FIXME: Handle inherit
637 if (cattrs == null) {
638 CattrInfo[] info = vm.conn.Type_GetCustomAttributes (id, 0, false);
639 cattrs = CustomAttributeDataMirror.Create (vm, info);
641 var res = new List<CustomAttributeDataMirror> ();
642 foreach (var attr in cattrs)
643 if (type == null || attr.Constructor.DeclaringType == type)
645 return res.ToArray ();
648 public MethodMirror[] GetMethodsByNameFlags (string name, BindingFlags flags, bool ignoreCase) {
649 if (vm.conn.Version.AtLeast (2, 6)) {
650 long[] ids = vm.conn.Type_GetMethodsByNameFlags (id, name, (int)flags, ignoreCase);
651 MethodMirror[] m = new MethodMirror [ids.Length];
652 for (int i = 0; i < ids.Length; ++i)
653 m [i] = vm.GetMethod (ids [i]);
656 if (flags != (BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance|BindingFlags.NonPublic))
657 throw new NotImplementedException ();
658 var res = new List<MethodMirror> ();
659 foreach (MethodMirror m in GetMethods ()) {
660 if ((!ignoreCase && m.Name == name) || (ignoreCase && m.Name.Equals (name, StringComparison.CurrentCultureIgnoreCase)))
663 return res.ToArray ();
667 public Value InvokeMethod (ThreadMirror thread, MethodMirror method, IList<Value> arguments) {
668 return ObjectMirror.InvokeMethod (vm, thread, method, null, arguments, InvokeOptions.None);
671 public Value InvokeMethod (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options) {
672 return ObjectMirror.InvokeMethod (vm, thread, method, null, arguments, options);
675 [Obsolete ("Use the overload without the 'vm' argument")]
676 public IAsyncResult BeginInvokeMethod (VirtualMachine vm, ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options, AsyncCallback callback, object state) {
677 return ObjectMirror.BeginInvokeMethod (vm, thread, method, null, arguments, options, callback, state);
680 public IAsyncResult BeginInvokeMethod (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options, AsyncCallback callback, object state) {
681 return ObjectMirror.BeginInvokeMethod (vm, thread, method, null, arguments, options, callback, state);
684 public Value EndInvokeMethod (IAsyncResult asyncResult) {
685 return ObjectMirror.EndInvokeMethodInternal (asyncResult);
688 public Value NewInstance (ThreadMirror thread, MethodMirror method, IList<Value> arguments) {
689 return ObjectMirror.InvokeMethod (vm, thread, method, null, arguments, InvokeOptions.None);
692 public Value NewInstance (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options) {
693 return ObjectMirror.InvokeMethod (vm, thread, method, null, arguments, options);