diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/ExpressionEvaluator.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/ExpressionEvaluator.cs index df533ada34..a9e659d03e 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/ExpressionEvaluator.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/ExpressionEvaluator.cs @@ -323,6 +323,30 @@ namespace Debugger return target.GetPropertyValue(pi, indexes.ToArray()); } + DebugType ResoleType(Expression expr) + { + string name = GetTypeName(expr); + if (name == null) + return null; + // TODO: Generic arguments + return DebugType.CreateFromDottedName(context.AppDomain, name); + } + + string GetTypeName(Expression expr) + { + if (expr is IdentifierExpression) { + return ((IdentifierExpression)expr).Identifier; + } else if (expr is MemberReferenceExpression) { + return GetTypeName(((MemberReferenceExpression)expr).TargetObject) + "." + ((MemberReferenceExpression)expr).MemberName; + } else if (expr is TypeReferenceExpression) { + TypeReference typeRef = ((TypeReferenceExpression)expr).TypeReference; + string genArity = typeRef.GenericTypes.Count > 0 ? "`" + typeRef.GenericTypes.Count : string.Empty; + return typeRef.Type + genArity; + } else { + return null; + } + } + public override object VisitInvocationExpression(InvocationExpression invocationExpression, object data) { Value target; @@ -330,8 +354,17 @@ namespace Debugger string methodName; MemberReferenceExpression memberRef = invocationExpression.TargetObject as MemberReferenceExpression; if (memberRef != null) { - target = Evaluate(memberRef.TargetObject); - targetType = GetDebugType(memberRef.TargetObject) ?? target.Type; + try { + // Instance + target = Evaluate(memberRef.TargetObject); + targetType = GetDebugType(memberRef.TargetObject) ?? target.Type; + } catch (GetValueException) { + // Static + target = null; + targetType = ResoleType(memberRef.TargetObject); + if (targetType == null) + throw; + } methodName = memberRef.MemberName; } else { IdentifierExpression ident = invocationExpression.TargetObject as IdentifierExpression; @@ -356,10 +389,10 @@ namespace Debugger foreach(Expression expr in invocationExpression.Arguments) { DebugType argType = GetDebugType(expr); if (argType == null) - throw new GetValueException("Multiple methods with name " + methodName + " found. Use explicit casts for arguments to select method overload."); + argType = Evaluate(expr).Type; argTypes.Add(argType); } - method = target.Type.GetMethod(methodName, argTypes.ToArray()); + method = targetType.GetMethod(methodName, argTypes.ToArray()); if (method == null) throw new GetValueException("Can not find overload with given types"); } @@ -367,7 +400,7 @@ namespace Debugger foreach(Expression expr in invocationExpression.Arguments) { args.Add(Evaluate(expr)); } - return target.InvokeMethod((DebugMethodInfo)method, args.ToArray()); + return Value.InvokeMethod(target, method, args.ToArray()); } public override object VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, object data) @@ -387,14 +420,25 @@ namespace Debugger public override object VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data) { - Value target = Evaluate(memberReferenceExpression.TargetObject); - DebugType targetType = GetDebugType(memberReferenceExpression.TargetObject) ?? target.Type; + Value target; + DebugType targetType; + try { + // Instance + target = Evaluate(memberReferenceExpression.TargetObject); + targetType = GetDebugType(memberReferenceExpression.TargetObject) ?? target.Type; + } catch (GetValueException) { + // Static + target = null; + targetType = ResoleType(memberReferenceExpression.TargetObject); + if (targetType == null) + throw; + } MemberInfo[] memberInfos = targetType.GetMember(memberReferenceExpression.MemberName, BindingFlagsAllDeclared); if (memberInfos.Length == 0) memberInfos = targetType.GetMember(memberReferenceExpression.MemberName, BindingFlagsAll); if (memberInfos.Length == 0) throw new GetValueException("Member \"" + memberReferenceExpression.MemberName + "\" not found"); - Value member = target.GetMemberValue(memberInfos[0]); + Value member = Value.GetMemberValue(target, memberInfos[0]); return member; } diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/ExpressionExtensionMethods.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/ExpressionExtensionMethods.cs index b1d504f2c9..83adc07fb6 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/ExpressionExtensionMethods.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/ExpressionExtensionMethods.cs @@ -27,7 +27,7 @@ namespace Debugger public static IndexerExpression AppendIndexer(this Expression expression, params int[] indices) { - IndexerExpression indexerExpr = new IndexerExpression(new ParenthesizedExpression(expression), new List()); + IndexerExpression indexerExpr = new IndexerExpression(Parenthesize(expression), new List()); foreach(int index in indices) { indexerExpr.Indexes.Add( new CastExpression( @@ -51,7 +51,7 @@ namespace Debugger target = new ParenthesizedExpression( new CastExpression( memberInfo.DeclaringType.ToTypeReference(), - new ParenthesizedExpression(expresion), + Parenthesize(expresion), CastType.Cast ) ); @@ -86,6 +86,17 @@ namespace Debugger throw new DebuggerException("Unknown member type " + memberInfo.GetType().FullName); } + static Expression Parenthesize(Expression expr) + { + if (expr is IdentifierExpression || + expr is MemberReferenceExpression || + expr is IndexerExpression || + expr is ParenthesizedExpression || + expr is PrimitiveExpression) + return expr; + return new ParenthesizedExpression(expr); + } + static List AddExplicitTypes(MethodInfo method, Expression[] args) { if (args.Length != method.GetParameters().Length) @@ -95,7 +106,7 @@ namespace Debugger typedArgs.Add( new CastExpression( method.GetParameters()[i].ParameterType.ToTypeReference(), - new ParenthesizedExpression(args[i]), + Parenthesize(args[i]), CastType.Cast ) ); diff --git a/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/ExpressionEvaluator.cs b/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/ExpressionEvaluator.cs index 6eff3f7081..cb6c9e896e 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/ExpressionEvaluator.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/ExpressionEvaluator.cs @@ -42,10 +42,15 @@ namespace Debugger.Tests.TestPrograms public static string StaticProperty { get { - return "static"; + return "static property"; } } + public static string StaticMethod() + { + return "static method"; + } + new public string Foo(int i) { return "derived Foo - int"; @@ -155,6 +160,7 @@ namespace Debugger.Tests { if (memberInfo.MemberType == MemberTypes.Field || memberInfo.MemberType == MemberTypes.Property) expressions.Add(new IdentifierExpression("myClass").AppendMemberReference((IDebugMemberInfo)memberInfo)); } + expressions.Add(new IdentifierExpression("myClass").AppendMemberReference((DebugMethodInfo)myClass.Type.GetMethod("StaticMethod"))); expressions.Add(new IdentifierExpression("myClass").AppendMemberReference((DebugMethodInfo)((DebugType)myClass.Type.BaseType).GetMethod("Foo", new string[] { "i" }), new PrimitiveExpression(1))); expressions.Add(new IdentifierExpression("myClass").AppendMemberReference((DebugMethodInfo)myClass.Type.GetMethod("Foo", new string[] { "i" }), new PrimitiveExpression(1))); expressions.Add(new IdentifierExpression("myClass").AppendMemberReference((DebugMethodInfo)myClass.Type.GetMethod("Foo", new string[] { "s" }), new PrimitiveExpression("a"))); @@ -197,7 +203,7 @@ namespace Debugger.Tests { mscorlib.dll (No symbols) ExpressionEvaluator.exe (Has symbols) - Break ExpressionEvaluator.cs:75,4-75,40 + Break ExpressionEvaluator.cs:80,4-80,40 b = 1 i = 4 @@ -245,17 +251,18 @@ namespace Debugger.Tests { flag = True !flag = False - ((Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass)(myClass)).name = "derived name" - Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass.StaticField = Error evaluating "Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass.StaticField": Identifier "Debugger" not found in this context - ((Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass)(myClass)).Name = "derived name" - ((Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass)(myClass)).SetterOnlyProperty = Error evaluating "((Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass)(myClass)).SetterOnlyProperty": Property does not have a get method - Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass.StaticProperty = Error evaluating "Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass.StaticProperty": Identifier "Debugger" not found in this context - ((Debugger.Tests.TestPrograms.ExpressionEvaluator.BaseClass)(myClass)).name = "base name" - Debugger.Tests.TestPrograms.ExpressionEvaluator.BaseClass.StaticField = Error evaluating "Debugger.Tests.TestPrograms.ExpressionEvaluator.BaseClass.StaticField": Identifier "Debugger" not found in this context - ((Debugger.Tests.TestPrograms.ExpressionEvaluator.BaseClass)(myClass)).Name = "base name" - ((Debugger.Tests.TestPrograms.ExpressionEvaluator.BaseClass)(myClass)).Foo((System.Int32)(1)) = "base Foo - int" - ((Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass)(myClass)).Foo((System.Int32)(1)) = "derived Foo - int" - ((Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass)(myClass)).Foo((System.String)("a")) = "derived Foo - string" + ((Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass)myClass).name = "derived name" + Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass.StaticField = "derived static field" + ((Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass)myClass).Name = "derived name" + ((Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass)myClass).SetterOnlyProperty = Error evaluating "((Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass)myClass).SetterOnlyProperty": Property does not have a get method + Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass.StaticProperty = "static property" + ((Debugger.Tests.TestPrograms.ExpressionEvaluator.BaseClass)myClass).name = "base name" + Debugger.Tests.TestPrograms.ExpressionEvaluator.BaseClass.StaticField = "base static field" + ((Debugger.Tests.TestPrograms.ExpressionEvaluator.BaseClass)myClass).Name = "base name" + Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass.StaticMethod() = "static method" + ((Debugger.Tests.TestPrograms.ExpressionEvaluator.BaseClass)myClass).Foo((System.Int32)1) = "base Foo - int" + ((Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass)myClass).Foo((System.Int32)1) = "derived Foo - int" + ((Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass)myClass).Foo((System.String)"a") = "derived Foo - string"