Browse Source

Basic support for static expressions.

Removed some extra parenthesis.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@5121 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 17 years ago
parent
commit
dd73b1fb64
  1. 56
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/ExpressionEvaluator.cs
  2. 17
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/ExpressionExtensionMethods.cs
  3. 33
      src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/ExpressionEvaluator.cs

56
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/ExpressionEvaluator.cs

@ -323,6 +323,30 @@ namespace Debugger
return target.GetPropertyValue(pi, indexes.ToArray()); 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) public override object VisitInvocationExpression(InvocationExpression invocationExpression, object data)
{ {
Value target; Value target;
@ -330,8 +354,17 @@ namespace Debugger
string methodName; string methodName;
MemberReferenceExpression memberRef = invocationExpression.TargetObject as MemberReferenceExpression; MemberReferenceExpression memberRef = invocationExpression.TargetObject as MemberReferenceExpression;
if (memberRef != null) { if (memberRef != null) {
try {
// Instance
target = Evaluate(memberRef.TargetObject); target = Evaluate(memberRef.TargetObject);
targetType = GetDebugType(memberRef.TargetObject) ?? target.Type; targetType = GetDebugType(memberRef.TargetObject) ?? target.Type;
} catch (GetValueException) {
// Static
target = null;
targetType = ResoleType(memberRef.TargetObject);
if (targetType == null)
throw;
}
methodName = memberRef.MemberName; methodName = memberRef.MemberName;
} else { } else {
IdentifierExpression ident = invocationExpression.TargetObject as IdentifierExpression; IdentifierExpression ident = invocationExpression.TargetObject as IdentifierExpression;
@ -356,10 +389,10 @@ namespace Debugger
foreach(Expression expr in invocationExpression.Arguments) { foreach(Expression expr in invocationExpression.Arguments) {
DebugType argType = GetDebugType(expr); DebugType argType = GetDebugType(expr);
if (argType == null) 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); argTypes.Add(argType);
} }
method = target.Type.GetMethod(methodName, argTypes.ToArray()); method = targetType.GetMethod(methodName, argTypes.ToArray());
if (method == null) if (method == null)
throw new GetValueException("Can not find overload with given types"); throw new GetValueException("Can not find overload with given types");
} }
@ -367,7 +400,7 @@ namespace Debugger
foreach(Expression expr in invocationExpression.Arguments) { foreach(Expression expr in invocationExpression.Arguments) {
args.Add(Evaluate(expr)); 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) public override object VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, object data)
@ -387,14 +420,25 @@ namespace Debugger
public override object VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data) public override object VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data)
{ {
Value target = Evaluate(memberReferenceExpression.TargetObject); Value target;
DebugType targetType = GetDebugType(memberReferenceExpression.TargetObject) ?? target.Type; 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); MemberInfo[] memberInfos = targetType.GetMember(memberReferenceExpression.MemberName, BindingFlagsAllDeclared);
if (memberInfos.Length == 0) if (memberInfos.Length == 0)
memberInfos = targetType.GetMember(memberReferenceExpression.MemberName, BindingFlagsAll); memberInfos = targetType.GetMember(memberReferenceExpression.MemberName, BindingFlagsAll);
if (memberInfos.Length == 0) if (memberInfos.Length == 0)
throw new GetValueException("Member \"" + memberReferenceExpression.MemberName + "\" not found"); throw new GetValueException("Member \"" + memberReferenceExpression.MemberName + "\" not found");
Value member = target.GetMemberValue(memberInfos[0]); Value member = Value.GetMemberValue(target, memberInfos[0]);
return member; return member;
} }

17
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) public static IndexerExpression AppendIndexer(this Expression expression, params int[] indices)
{ {
IndexerExpression indexerExpr = new IndexerExpression(new ParenthesizedExpression(expression), new List<Expression>()); IndexerExpression indexerExpr = new IndexerExpression(Parenthesize(expression), new List<Expression>());
foreach(int index in indices) { foreach(int index in indices) {
indexerExpr.Indexes.Add( indexerExpr.Indexes.Add(
new CastExpression( new CastExpression(
@ -51,7 +51,7 @@ namespace Debugger
target = new ParenthesizedExpression( target = new ParenthesizedExpression(
new CastExpression( new CastExpression(
memberInfo.DeclaringType.ToTypeReference(), memberInfo.DeclaringType.ToTypeReference(),
new ParenthesizedExpression(expresion), Parenthesize(expresion),
CastType.Cast CastType.Cast
) )
); );
@ -86,6 +86,17 @@ namespace Debugger
throw new DebuggerException("Unknown member type " + memberInfo.GetType().FullName); 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<Expression> AddExplicitTypes(MethodInfo method, Expression[] args) static List<Expression> AddExplicitTypes(MethodInfo method, Expression[] args)
{ {
if (args.Length != method.GetParameters().Length) if (args.Length != method.GetParameters().Length)
@ -95,7 +106,7 @@ namespace Debugger
typedArgs.Add( typedArgs.Add(
new CastExpression( new CastExpression(
method.GetParameters()[i].ParameterType.ToTypeReference(), method.GetParameters()[i].ParameterType.ToTypeReference(),
new ParenthesizedExpression(args[i]), Parenthesize(args[i]),
CastType.Cast CastType.Cast
) )
); );

33
src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/ExpressionEvaluator.cs

@ -42,10 +42,15 @@ namespace Debugger.Tests.TestPrograms
public static string StaticProperty { public static string StaticProperty {
get { get {
return "static"; return "static property";
} }
} }
public static string StaticMethod()
{
return "static method";
}
new public string Foo(int i) new public string Foo(int i)
{ {
return "derived Foo - int"; return "derived Foo - int";
@ -155,6 +160,7 @@ namespace Debugger.Tests {
if (memberInfo.MemberType == MemberTypes.Field || memberInfo.MemberType == MemberTypes.Property) if (memberInfo.MemberType == MemberTypes.Field || memberInfo.MemberType == MemberTypes.Property)
expressions.Add(new IdentifierExpression("myClass").AppendMemberReference((IDebugMemberInfo)memberInfo)); 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)((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[] { "i" }), new PrimitiveExpression(1)));
expressions.Add(new IdentifierExpression("myClass").AppendMemberReference((DebugMethodInfo)myClass.Type.GetMethod("Foo", new string[] { "s" }), new PrimitiveExpression("a"))); expressions.Add(new IdentifierExpression("myClass").AppendMemberReference((DebugMethodInfo)myClass.Type.GetMethod("Foo", new string[] { "s" }), new PrimitiveExpression("a")));
@ -197,7 +203,7 @@ namespace Debugger.Tests {
<ProcessStarted /> <ProcessStarted />
<ModuleLoaded>mscorlib.dll (No symbols)</ModuleLoaded> <ModuleLoaded>mscorlib.dll (No symbols)</ModuleLoaded>
<ModuleLoaded>ExpressionEvaluator.exe (Has symbols)</ModuleLoaded> <ModuleLoaded>ExpressionEvaluator.exe (Has symbols)</ModuleLoaded>
<DebuggingPaused>Break ExpressionEvaluator.cs:75,4-75,40</DebuggingPaused> <DebuggingPaused>Break ExpressionEvaluator.cs:80,4-80,40</DebuggingPaused>
<Eval> </Eval> <Eval> </Eval>
<Eval> b = 1 </Eval> <Eval> b = 1 </Eval>
<Eval> i = 4 </Eval> <Eval> i = 4 </Eval>
@ -245,17 +251,18 @@ namespace Debugger.Tests {
<Eval> flag = True </Eval> <Eval> flag = True </Eval>
<Eval> !flag = False </Eval> <Eval> !flag = False </Eval>
<Eval> </Eval> <Eval> </Eval>
<Eval> ((Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass)(myClass)).name = "derived name" </Eval> <Eval> ((Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass)myClass).name = "derived name" </Eval>
<Eval> Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass.StaticField = Error evaluating "Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass.StaticField": Identifier "Debugger" not found in this context </Eval> <Eval> Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass.StaticField = "derived static field" </Eval>
<Eval> ((Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass)(myClass)).Name = "derived name" </Eval> <Eval> ((Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass)myClass).Name = "derived name" </Eval>
<Eval> ((Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass)(myClass)).SetterOnlyProperty = Error evaluating "((Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass)(myClass)).SetterOnlyProperty": Property does not have a get method </Eval> <Eval> ((Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass)myClass).SetterOnlyProperty = Error evaluating "((Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass)myClass).SetterOnlyProperty": Property does not have a get method </Eval>
<Eval> Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass.StaticProperty = Error evaluating "Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass.StaticProperty": Identifier "Debugger" not found in this context </Eval> <Eval> Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass.StaticProperty = "static property" </Eval>
<Eval> ((Debugger.Tests.TestPrograms.ExpressionEvaluator.BaseClass)(myClass)).name = "base name" </Eval> <Eval> ((Debugger.Tests.TestPrograms.ExpressionEvaluator.BaseClass)myClass).name = "base name" </Eval>
<Eval> Debugger.Tests.TestPrograms.ExpressionEvaluator.BaseClass.StaticField = Error evaluating "Debugger.Tests.TestPrograms.ExpressionEvaluator.BaseClass.StaticField": Identifier "Debugger" not found in this context </Eval> <Eval> Debugger.Tests.TestPrograms.ExpressionEvaluator.BaseClass.StaticField = "base static field" </Eval>
<Eval> ((Debugger.Tests.TestPrograms.ExpressionEvaluator.BaseClass)(myClass)).Name = "base name" </Eval> <Eval> ((Debugger.Tests.TestPrograms.ExpressionEvaluator.BaseClass)myClass).Name = "base name" </Eval>
<Eval> ((Debugger.Tests.TestPrograms.ExpressionEvaluator.BaseClass)(myClass)).Foo((System.Int32)(1)) = "base Foo - int" </Eval> <Eval> Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass.StaticMethod() = "static method" </Eval>
<Eval> ((Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass)(myClass)).Foo((System.Int32)(1)) = "derived Foo - int" </Eval> <Eval> ((Debugger.Tests.TestPrograms.ExpressionEvaluator.BaseClass)myClass).Foo((System.Int32)1) = "base Foo - int" </Eval>
<Eval> ((Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass)(myClass)).Foo((System.String)("a")) = "derived Foo - string" </Eval> <Eval> ((Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass)myClass).Foo((System.Int32)1) = "derived Foo - int" </Eval>
<Eval> ((Debugger.Tests.TestPrograms.ExpressionEvaluator.DerivedClass)myClass).Foo((System.String)"a") = "derived Foo - string" </Eval>
<ProcessExited /> <ProcessExited />
</Test> </Test>
</DebuggerTests> </DebuggerTests>

Loading…
Cancel
Save