diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/TreeModel/StackFrameNode.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/TreeModel/StackFrameNode.cs index 78e3a7e3e5..f6df8750d2 100644 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/TreeModel/StackFrameNode.cs +++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/TreeModel/StackFrameNode.cs @@ -29,10 +29,10 @@ namespace Debugger.AddIn.TreeModel IEnumerable LazyGetChildNodes() { foreach(DebugParameterInfo par in stackFrame.MethodInfo.GetParameters()) { - yield return new ExpressionNode(ExpressionNode.GetImageForParameter(), par.Name, new IdentifierExpression(par.Name)); + yield return new ExpressionNode(ExpressionNode.GetImageForParameter(), par.Name, par.GetExpression()); } foreach(DebugLocalVariableInfo locVar in stackFrame.MethodInfo.GetLocalVariables()) { - yield return new ExpressionNode(ExpressionNode.GetImageForLocalVariable(), locVar.Name, new IdentifierExpression(locVar.Name)); + yield return new ExpressionNode(ExpressionNode.GetImageForLocalVariable(), locVar.Name, locVar.GetExpression()); } if (stackFrame.Thread.CurrentException != null) { yield return new ExpressionNode(null, "__exception", new IdentifierExpression("__exception")); diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/NRefactory/Ast/ExpressionExtensionMethods.cs b/src/AddIns/Misc/Debugger/Debugger.Core/NRefactory/Ast/ExpressionExtensionMethods.cs index e0336a4bee..96cdb36a80 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/NRefactory/Ast/ExpressionExtensionMethods.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/NRefactory/Ast/ExpressionExtensionMethods.cs @@ -23,6 +23,51 @@ namespace ICSharpCode.NRefactory.Ast return ExpressionEvaluator.Evaluate(expression, process); } + static M SetStaticType(this M expr, DebugType type) where M: INode + { + expr.UserData = type; + return expr; + } + + public static DebugType GetStaticType(this INode expr) + { + return expr.UserData as DebugType; + } + + public static Expression Parenthesize(this Expression expr) + { + if (expr is IdentifierExpression || + expr is MemberReferenceExpression || + expr is IndexerExpression || + expr is ParenthesizedExpression || + expr is PrimitiveExpression) + return expr; + return new ParenthesizedExpression(expr); + } + + public static Expression CastTo(this Expression expresion, DebugType castTo) + { + // No need to cast + if (expresion.GetStaticType() == castTo) + return expresion; + if (expresion is PrimitiveExpression) { + object val = ((PrimitiveExpression)expresion).Value; + if (val != null && val.GetType().FullName == castTo.FullName) + return expresion; + } + return new CastExpression(castTo.GetTypeReference(), expresion.Parenthesize(), CastType.Cast); + } + + public static Expression GetExpression(this DebugLocalVariableInfo locVar) + { + return new IdentifierExpression(locVar.Name).SetStaticType((DebugType)locVar.LocalType); + } + + public static Expression GetExpression(this DebugParameterInfo par) + { + return new IdentifierExpression(par.Name).SetStaticType((DebugType)par.ParameterType); + } + public static UnaryOperatorExpression AppendDereference(this Expression expression) { return new UnaryOperatorExpression(new ParenthesizedExpression(expression), UnaryOperatorType.Dereference); @@ -32,14 +77,13 @@ namespace ICSharpCode.NRefactory.Ast { IndexerExpression indexerExpr = new IndexerExpression(Parenthesize(expression), new List()); foreach(int index in indices) { - indexerExpr.Indexes.Add( - new CastExpression( - new TypeReference(typeof(int).FullName), - new PrimitiveExpression(index), - CastType.Cast - ) - ); + indexerExpr.Indexes.Add(new PrimitiveExpression(index)); } + DebugType staticType = expression.GetStaticType(); + if (staticType != null && staticType.IsArray) + indexerExpr.SetStaticType((DebugType)staticType.GetElementType()); + if (staticType != null && staticType.FullNameWithoutGenericArguments == typeof(List<>).FullName) + indexerExpr.SetStaticType((DebugType)staticType.GetGenericArguments()[0]); return indexerExpr; } @@ -51,26 +95,20 @@ namespace ICSharpCode.NRefactory.Ast memberInfo.DeclaringType.GetTypeReference() ); } else { - target = new ParenthesizedExpression( - new CastExpression( - memberInfo.DeclaringType.GetTypeReference(), - Parenthesize(expresion), - CastType.Cast - ) - ); + target = expresion.CastTo((DebugType)memberInfo.DeclaringType); } if (memberInfo is DebugFieldInfo) { if (args.Length > 0) throw new DebuggerException("No arguments expected for a field"); - return new MemberReferenceExpression(target, memberInfo.Name); + return new MemberReferenceExpression(target, memberInfo.Name).SetStaticType(memberInfo.MemberType); } if (memberInfo is MethodInfo) { return new InvocationExpression( new MemberReferenceExpression(target, memberInfo.Name), AddExplicitTypes((MethodInfo)memberInfo, args) - ); + ).SetStaticType(memberInfo.MemberType); } if (memberInfo is PropertyInfo) { @@ -81,38 +119,22 @@ namespace ICSharpCode.NRefactory.Ast return new IndexerExpression( target, AddExplicitTypes(propInfo.GetGetMethod() ?? propInfo.GetSetMethod(), args) - ); + ).SetStaticType(memberInfo.MemberType); } else { - return new MemberReferenceExpression(target, memberInfo.Name); + return new MemberReferenceExpression(target, memberInfo.Name).SetStaticType(memberInfo.MemberType); } } + 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) throw new DebuggerException("Incorrect number of arguments"); List typedArgs = new List(args.Length); for(int i = 0; i < args.Length; i++) { - typedArgs.Add( - new CastExpression( - method.GetParameters()[i].ParameterType.GetTypeReference(), - Parenthesize(args[i]), - CastType.Cast - ) - ); + typedArgs.Add(args[i].CastTo((DebugType)method.GetParameters()[i].ParameterType)); } return typedArgs; } @@ -174,9 +196,9 @@ namespace ICSharpCode.NRefactory.Ast InnerClassTypeReference innerRef = new InnerClassTypeReference(outterRef, name, genTypeRefs); innerRef.PointerNestingLevel = pointerNest; innerRef.RankSpecifier = arrayRanks.ToArray(); - return innerRef; + return innerRef.SetStaticType((DebugType)type); } else { - return new TypeReference(name, pointerNest, arrayRanks.ToArray(), genTypeRefs); + return new TypeReference(name, pointerNest, arrayRanks.ToArray(), genTypeRefs).SetStaticType((DebugType)type); } } @@ -248,6 +270,11 @@ namespace ICSharpCode.NRefactory.Ast public static DebugType ResolveType(this INode expr, Debugger.AppDomain appDomain) { + if (expr is TypeReference && expr.GetStaticType() != null) + return expr.GetStaticType(); + if (expr is TypeReferenceExpression && ((TypeReferenceExpression)expr).TypeReference.GetStaticType() != null) + return ((TypeReferenceExpression)expr).TypeReference.GetStaticType(); + TypeReference typeRef = NormalizeTypeReference(expr); List genTypeRefs; diff --git a/src/AddIns/Misc/Debugger/Debugger.Tests/Tests/ExpressionEvaluator_Tests.cs b/src/AddIns/Misc/Debugger/Debugger.Tests/Tests/ExpressionEvaluator_Tests.cs index 3c9063ac7e..302f4eac3e 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Tests/Tests/ExpressionEvaluator_Tests.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Tests/Tests/ExpressionEvaluator_Tests.cs @@ -209,15 +209,16 @@ namespace Debugger.Tests { // Test member hiding / overloading Value myClass = process.SelectedStackFrame.GetLocalVariableValue("myClass").GetPermanentReference(); + Expression myClassExpr = process.SelectedStackFrame.MethodInfo.GetLocalVariable("myClass").GetExpression(); List expressions = new List(); foreach(MemberInfo memberInfo in myClass.Type.GetFieldsAndNonIndexedProperties(DebugType.BindingFlagsAll)) { - expressions.Add(new IdentifierExpression("myClass").AppendMemberReference((IDebugMemberInfo)memberInfo)); + expressions.Add(myClassExpr.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"))); + expressions.Add(myClassExpr.AppendMemberReference((DebugMethodInfo)myClass.Type.GetMethod("StaticMethod"))); + expressions.Add(myClassExpr.AppendMemberReference((DebugMethodInfo)((DebugType)myClass.Type.BaseType).GetMethod("Foo", new string[] { "i" }), new PrimitiveExpression(1))); + expressions.Add(myClassExpr.AppendMemberReference((DebugMethodInfo)myClass.Type.GetMethod("Foo", new string[] { "i" }), new PrimitiveExpression(1))); + expressions.Add(myClassExpr.AppendMemberReference((DebugMethodInfo)myClass.Type.GetMethod("Foo", new string[] { "s" }), new PrimitiveExpression("a"))); foreach(Expression expr in expressions) { Eval(expr.PrettyPrint()); @@ -409,17 +410,17 @@ namespace Debugger.Tests { Debugger.Tests.ExpressionEvaluator_Tests.DerivedClass.ConstString = "const string" Debugger.Tests.ExpressionEvaluator_Tests.DerivedClass.ConstNull = null Debugger.Tests.ExpressionEvaluator_Tests.DerivedClass.ConstEnum = B - ((Debugger.Tests.ExpressionEvaluator_Tests.DerivedClass)myClass).name = "derived name" + myClass.name = "derived name" Debugger.Tests.ExpressionEvaluator_Tests.DerivedClass.StaticField = "derived static field" - ((Debugger.Tests.ExpressionEvaluator_Tests.DerivedClass)myClass).Name = "derived name" + myClass.Name = "derived name" Debugger.Tests.ExpressionEvaluator_Tests.DerivedClass.StaticProperty = "static property" ((Debugger.Tests.ExpressionEvaluator_Tests.BaseClass)myClass).name = "base name" Debugger.Tests.ExpressionEvaluator_Tests.BaseClass.StaticField = "base static field" ((Debugger.Tests.ExpressionEvaluator_Tests.BaseClass)myClass).Name = "base name" Debugger.Tests.ExpressionEvaluator_Tests.DerivedClass.StaticMethod() = "static method" - ((Debugger.Tests.ExpressionEvaluator_Tests.BaseClass)myClass).Foo((System.Int32)1) = "base Foo - int" - ((Debugger.Tests.ExpressionEvaluator_Tests.DerivedClass)myClass).Foo((System.Int32)1) = "derived Foo - int" - ((Debugger.Tests.ExpressionEvaluator_Tests.DerivedClass)myClass).Foo((System.String)"a") = "derived Foo - string" + ((Debugger.Tests.ExpressionEvaluator_Tests.BaseClass)myClass).Foo(1) = "base Foo - int" + myClass.Foo(1) = "derived Foo - int" + myClass.Foo("a") = "derived Foo - string" myClass.Foo(1.0) = "base Foo - double" myClass.Foo(myClass) = "derived Foo - object"