2
// ObjectValueAdaptor.cs
4
// Authors: Lluis Sanchez Gual <lluis@novell.com>
5
// Jeffrey Stedfast <jeff@xamarin.com>
7
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
8
// Copyright (c) 2012 Xamarin Inc. (http://www.xamarin.com)
10
// Permission is hereby granted, free of charge, to any person obtaining a copy
11
// of this software and associated documentation files (the "Software"), to deal
12
// in the Software without restriction, including without limitation the rights
13
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
// copies of the Software, and to permit persons to whom the Software is
15
// furnished to do so, subject to the following conditions:
17
// The above copyright notice and this permission notice shall be included in
18
// all copies or substantial portions of the Software.
20
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2
using System.Collections.Generic;
5
31
using System.Reflection;
32
using System.Diagnostics;
33
using System.Collections.Generic;
6
35
using Mono.Debugging.Client;
7
36
using Mono.Debugging.Backend;
8
using System.Diagnostics;
9
using System.Collections;
11
38
namespace Mono.Debugging.Evaluation
66
93
return CreateObjectValueImpl (ctx, source, path, obj, flags);
94
} catch (EvaluatorAbortedException ex) {
95
return ObjectValue.CreateFatalError (path.LastName, ex.Message, flags);
96
} catch (EvaluatorException ex) {
97
return ObjectValue.CreateFatalError (path.LastName, ex.Message, flags);
67
98
} catch (Exception ex) {
68
99
ctx.WriteDebuggerError (ex);
69
100
return ObjectValue.CreateFatalError (path.LastName, ex.Message, flags);
245
276
public abstract bool IsString (EvaluationContext ctx, object val);
246
277
public abstract bool IsArray (EvaluationContext ctx, object val);
247
278
public abstract bool IsEnum (EvaluationContext ctx, object val);
279
public abstract bool IsValueType (object type);
248
280
public abstract bool IsClass (object type);
249
281
public abstract object TryCast (EvaluationContext ctx, object val, object type);
251
283
public abstract object GetValueType (EvaluationContext ctx, object val);
252
public abstract string GetTypeName (EvaluationContext ctx, object val);
284
public abstract string GetTypeName (EvaluationContext ctx, object type);
253
285
public abstract object[] GetTypeArgs (EvaluationContext ctx, object type);
254
286
public abstract object GetBaseType (EvaluationContext ctx, object type);
288
public virtual bool IsNullableType (EvaluationContext ctx, object type)
290
return type != null && GetTypeName (ctx, type).StartsWith ("System.Nullable`1", StringComparison.Ordinal);
293
public virtual bool NullableHasValue (EvaluationContext ctx, object type, object obj)
295
ValueReference hasValue = GetMember (ctx, type, obj, "HasValue");
297
return (bool) hasValue.ObjectValue;
300
public virtual ValueReference NullableGetValue (EvaluationContext ctx, object type, object obj)
302
return GetMember (ctx, type, obj, "Value");
256
305
public virtual bool IsFlagsEnumType (EvaluationContext ctx, object type)
275
324
public object GetBaseType (EvaluationContext ctx, object type, bool includeObjectClass)
277
326
object bt = GetBaseType (ctx, type);
278
string tn = GetTypeName (ctx, bt);
327
string tn = bt != null ? GetTypeName (ctx, bt) : null;
279
328
if (!includeObjectClass && bt != null && (tn == "System.Object" || tn == "System.ValueType"))
309
358
return default (object);
361
public virtual bool IsTypeLoaded (EvaluationContext ctx, string typeName)
363
object t = GetType (ctx, typeName);
368
return IsTypeLoaded (ctx, t);
371
public virtual bool IsTypeLoaded (EvaluationContext ctx, object type)
312
376
public virtual object ForceLoadType (EvaluationContext ctx, string typeName)
314
return GetType (ctx, typeName);
378
object t = GetType (ctx, typeName);
380
if (t == null || IsTypeLoaded (ctx, t))
383
if (ForceLoadType (ctx, t))
389
public virtual bool ForceLoadType (EvaluationContext ctx, object type)
317
394
public abstract object CreateValue (EvaluationContext ctx, object value);
338
415
protected virtual ObjectValue CreateObjectValueImpl (EvaluationContext ctx, Mono.Debugging.Backend.IObjectValueSource source, ObjectPath path, object obj, ObjectValueFlags flags)
340
string typeName = obj != null ? GetValueTypeName (ctx, obj) : "";
417
object type = obj != null ? GetValueType (ctx, obj) : null;
418
string typeName = type != null ? GetTypeName (ctx, type) : "";
342
420
if (obj == null || IsNull (ctx, obj)) {
343
421
return ObjectValue.CreateNullObject (source, path, GetDisplayTypeName (typeName), flags);
349
427
return ObjectValue.CreateObject (source, path, GetDisplayTypeName (typeName), ctx.Evaluator.TargetObjectToExpression (ctx, obj), flags, null);
352
TypeDisplayData tdata = GetTypeDisplayData (ctx, GetValueType (ctx, obj));
354
EvaluationResult tvalue;
355
if (!string.IsNullOrEmpty (tdata.ValueDisplayString) && ctx.Options.AllowDisplayStringEvaluation)
356
tvalue = new EvaluationResult (EvaluateDisplayString (ctx, obj, tdata.ValueDisplayString));
358
tvalue = ctx.Evaluator.TargetObjectToExpression (ctx, obj);
430
EvaluationResult tvalue = null;
431
TypeDisplayData tdata = null;
361
if (!string.IsNullOrEmpty (tdata.TypeDisplayString) && ctx.Options.AllowDisplayStringEvaluation)
362
tname = EvaluateDisplayString (ctx, obj, tdata.TypeDisplayString);
434
if (IsNullableType (ctx, type)) {
435
if (NullableHasValue (ctx, type, obj)) {
436
ValueReference value = NullableGetValue (ctx, type, obj);
438
tdata = GetTypeDisplayData (ctx, value.Type);
441
tdata = GetTypeDisplayData (ctx, type);
442
tvalue = new EvaluationResult ("null");
364
445
tname = GetDisplayTypeName (typeName);
447
tdata = GetTypeDisplayData (ctx, type);
449
if (!string.IsNullOrEmpty (tdata.TypeDisplayString) && ctx.Options.AllowDisplayStringEvaluation)
450
tname = EvaluateDisplayString (ctx, obj, tdata.TypeDisplayString);
452
tname = GetDisplayTypeName (typeName);
455
if (tvalue == null) {
456
if (!string.IsNullOrEmpty (tdata.ValueDisplayString) && ctx.Options.AllowDisplayStringEvaluation)
457
tvalue = new EvaluationResult (EvaluateDisplayString (ctx, obj, tdata.ValueDisplayString));
459
tvalue = ctx.Evaluator.TargetObjectToExpression (ctx, obj);
366
462
ObjectValue oval = ObjectValue.CreateObject (source, path, tname, tvalue, flags, null);
367
463
if (!string.IsNullOrEmpty (tdata.NameDisplayString) && ctx.Options.AllowDisplayStringEvaluation)
368
464
oval.Name = EvaluateDisplayString (ctx, obj, tdata.NameDisplayString);
373
469
public ObjectValue[] GetObjectValueChildren (EvaluationContext ctx, IObjectSource objectSource, object obj, int firstItemIndex, int count)
375
471
return GetObjectValueChildren (ctx, objectSource, GetValueType (ctx, obj), obj, firstItemIndex, count, true);
388
484
if (IsPrimitive (ctx, obj))
389
485
return new ObjectValue[0];
487
if (IsNullableType (ctx, type)) {
488
if (NullableHasValue (ctx, type, obj)) {
489
ValueReference value = NullableGetValue (ctx, type, obj);
491
return GetObjectValueChildren (ctx, objectSource, value.Type, value.Value, firstItemIndex, count, dereferenceProxy);
493
return new ObjectValue[0];
391
497
bool showRawView = false;
393
499
// If there is a proxy, it has to show the members of the proxy
630
736
string partialWord = exp.Substring (i+1);
632
738
CompletionData data = new CompletionData ();
633
data.ExpressionLenght = partialWord.Length;
739
data.ExpressionLength = partialWord.Length;
635
741
// Local variables
637
743
foreach (ValueReference vc in GetLocalVariables (ctx))
638
if (vc.Name.StartsWith (partialWord))
744
if (vc.Name.StartsWith (partialWord, StringComparison.InvariantCulture))
639
745
data.Items.Add (new CompletionItem (vc.Name, vc.Flags));
643
749
foreach (ValueReference vc in GetParameters (ctx))
644
if (vc.Name.StartsWith (partialWord))
750
if (vc.Name.StartsWith (partialWord, StringComparison.InvariantCulture))
645
751
data.Items.Add (new CompletionItem (vc.Name, vc.Flags));
654
760
object type = GetEnclosingType (ctx);
656
762
foreach (ValueReference vc in GetMembers (ctx, null, type, thisobj != null ? thisobj.Value : null))
657
if (vc.Name.StartsWith (partialWord))
763
if (vc.Name.StartsWith (partialWord, StringComparison.InvariantCulture))
658
764
data.Items.Add (new CompletionItem (vc.Name, vc.Flags));
660
766
if (data.Items.Count > 0)
846
public virtual object GetParentType (EvaluationContext ctx, object type)
849
return ((Type) type).DeclaringType;
851
var name = GetTypeName (ctx, type);
852
int plus = name.LastIndexOf ('+');
854
return plus != -1 ? GetType (ctx, name.Substring (0, plus)) : null;
740
857
public virtual object CreateArray (EvaluationContext ctx, object type, object[] values)
816
933
public virtual object TargetObjectToObject (EvaluationContext ctx, object obj)
818
if (IsNull (ctx, obj)) {
935
if (IsNull (ctx, obj))
820
} else if (IsArray (ctx, obj)) {
938
if (IsArray (ctx, obj)) {
821
939
ICollectionAdaptor adaptor = CreateArrayAdaptor (ctx, obj);
822
940
string ename = GetDisplayTypeName (GetTypeName (ctx, adaptor.ElementType));
823
941
int[] dims = adaptor.GetDimensions ();
833
951
i = ename.IndexOf ('[', i);
835
953
return new EvaluationResult ("{" + ename.Substring (0, i) + tn + ename.Substring (i) + "}");
837
return new EvaluationResult ("{" + ename + tn + "}");
955
return new EvaluationResult ("{" + ename + tn + "}");
839
else if (IsEnum (ctx, obj)) {
958
if (IsEnum (ctx, obj)) {
840
959
object type = GetValueType (ctx, obj);
841
960
object longType = GetType (ctx, "System.Int64");
842
961
object c = Cast (ctx, obj, longType);
863
983
if (IsFlagsEnumType (ctx, type) && rest == 0 && composed.Length > 0)
864
984
return new EvaluationResult (composed, composedDisplay);
866
return new EvaluationResult (val.ToString ());
986
return new EvaluationResult (val.ToString ());
868
else if (GetValueTypeName (ctx, obj) == "System.Decimal") {
989
if (GetValueTypeName (ctx, obj) == "System.Decimal") {
869
990
string res = CallToString (ctx, obj);
870
991
// This returns the decimal formatted using the current culture. It has to be converted to invariant culture.
871
992
decimal dec = decimal.Parse (res);
872
993
res = dec.ToString (System.Globalization.CultureInfo.InvariantCulture);
873
994
return new EvaluationResult (res);
875
else if (IsClassInstance (ctx, obj)) {
997
if (IsClassInstance (ctx, obj)) {
876
998
TypeDisplayData tdata = GetTypeDisplayData (ctx, GetValueType (ctx, obj));
877
999
if (!string.IsNullOrEmpty (tdata.ValueDisplayString) && ctx.Options.AllowDisplayStringEvaluation)
878
1000
return new EvaluationResult (EvaluateDisplayString (ctx, obj, tdata.ValueDisplayString));
880
1002
// Return the type name
881
if (ctx.Options.AllowToStringCalls)
882
return new EvaluationResult ("{" + CallToString (ctx, obj) + "}");
1003
if (ctx.Options.AllowToStringCalls) {
1005
return new EvaluationResult ("{" + CallToString (ctx, obj) + "}");
1006
} catch (TimeOutException) {
1007
// ToString() timed out, fall back to default behavior.
884
1011
if (!string.IsNullOrEmpty (tdata.TypeDisplayString) && ctx.Options.AllowDisplayStringEvaluation)
885
1012
return new EvaluationResult ("{" + EvaluateDisplayString (ctx, obj, tdata.TypeDisplayString) + "}");
895
1022
if (obj == null)
897
1025
object res = TryConvert (ctx, obj, targetType);
898
1026
if (res != null)
901
throw new EvaluatorException ("Can't convert an object of type '{0}' to type '{1}'", GetValueTypeName (ctx, obj), GetTypeName (ctx, targetType));
1029
throw new EvaluatorException ("Can't convert an object of type '{0}' to type '{1}'", GetValueTypeName (ctx, obj), GetTypeName (ctx, targetType));
904
1032
public virtual object TryConvert (EvaluationContext ctx, object obj, object targetType)
911
1039
if (obj == null)
913
1042
object res = TryCast (ctx, obj, targetType);
914
1043
if (res != null)
917
throw new EvaluatorException ("Can't cast an object of type '{0}' to type '{1}'", GetValueTypeName (ctx, obj), GetTypeName (ctx, targetType));
1046
throw new EvaluatorException ("Can't cast an object of type '{0}' to type '{1}'", GetValueTypeName (ctx, obj), GetTypeName (ctx, targetType));
920
1049
public virtual string CallToString (EvaluationContext ctx, object obj)
991
1120
public string EvaluateDisplayString (EvaluationContext ctx, object obj, string exp)
993
1122
StringBuilder sb = new StringBuilder ();
1123
int i = exp.IndexOf ("{");
995
int i = exp.IndexOf ("{");
996
1126
while (i != -1 && i < exp.Length) {
997
1127
sb.Append (exp.Substring (last, i - last));
999
1130
int j = exp.IndexOf ("}", i);
1002
1134
string mem = exp.Substring (i, j - i).Trim ();
1003
1135
if (mem.Length == 0)