24 changed files with 900 additions and 916 deletions
@ -0,0 +1,328 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.IO; |
||||||
|
using System.Threading; |
||||||
|
|
||||||
|
namespace Debugger.Tests |
||||||
|
{ |
||||||
|
public class ExpressionEvaluatorVisitor_Tests |
||||||
|
{ |
||||||
|
public class BaseClass |
||||||
|
{ |
||||||
|
string name = "base name"; |
||||||
|
|
||||||
|
public string Name { |
||||||
|
get { return name; } |
||||||
|
} |
||||||
|
|
||||||
|
public static string StaticField = "base static field"; |
||||||
|
|
||||||
|
public string Foo(int i) |
||||||
|
{ |
||||||
|
return "base Foo - int"; |
||||||
|
} |
||||||
|
|
||||||
|
public string Foo(double d) |
||||||
|
{ |
||||||
|
return "base Foo - double"; |
||||||
|
} |
||||||
|
|
||||||
|
public string this[long i] { |
||||||
|
get { |
||||||
|
return "base indexer - long"; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public struct DBBool |
||||||
|
{ |
||||||
|
// The three possible DBBool values.
|
||||||
|
|
||||||
|
public static readonly DBBool Null = new DBBool(0); |
||||||
|
public static readonly DBBool False = new DBBool(-1); |
||||||
|
public static readonly DBBool True = new DBBool(1); |
||||||
|
|
||||||
|
// Private field that stores –1, 0, 1 for False, Null, True.
|
||||||
|
|
||||||
|
sbyte value; |
||||||
|
|
||||||
|
// Private instance constructor. The value parameter must be –1, 0, or 1.
|
||||||
|
|
||||||
|
DBBool(int value) { |
||||||
|
this.value = (sbyte)value; |
||||||
|
} |
||||||
|
|
||||||
|
// Properties to examine the value of a DBBool. Return true if this
|
||||||
|
// DBBool has the given value, false otherwise.
|
||||||
|
|
||||||
|
public bool IsNull { get { return value == 0; } } |
||||||
|
|
||||||
|
public bool IsFalse { get { return value < 0; } } |
||||||
|
|
||||||
|
public bool IsTrue { get { return value > 0; } } |
||||||
|
|
||||||
|
// Implicit conversion from bool to DBBool. Maps true to DBBool.True and
|
||||||
|
// false to DBBool.False.
|
||||||
|
|
||||||
|
public static implicit operator DBBool(bool x) { |
||||||
|
return x? True: False; |
||||||
|
} |
||||||
|
|
||||||
|
// Explicit conversion from DBBool to bool. Throws an exception if the
|
||||||
|
// given DBBool is Null, otherwise returns true or false.
|
||||||
|
|
||||||
|
public static explicit operator bool(DBBool x) { |
||||||
|
if (x.value == 0) throw new InvalidOperationException(); |
||||||
|
return x.value > 0; |
||||||
|
} |
||||||
|
|
||||||
|
// Equality operator. Returns Null if either operand is Null, otherwise
|
||||||
|
// returns True or False.
|
||||||
|
|
||||||
|
public static DBBool operator ==(DBBool x, DBBool y) { |
||||||
|
if (x.value == 0 || y.value == 0) return Null; |
||||||
|
return x.value == y.value? True: False; |
||||||
|
} |
||||||
|
|
||||||
|
// Inequality operator. Returns Null if either operand is Null, otherwise
|
||||||
|
// returns True or False.
|
||||||
|
|
||||||
|
public static DBBool operator !=(DBBool x, DBBool y) { |
||||||
|
if (x.value == 0 || y.value == 0) return Null; |
||||||
|
return x.value != y.value? True: False; |
||||||
|
} |
||||||
|
|
||||||
|
// Logical negation operator. Returns True if the operand is False, Null
|
||||||
|
// if the operand is Null, or False if the operand is True.
|
||||||
|
|
||||||
|
public static DBBool operator !(DBBool x) { |
||||||
|
return new DBBool(-x.value); |
||||||
|
} |
||||||
|
|
||||||
|
// Logical AND operator. Returns False if either operand is False,
|
||||||
|
// otherwise Null if either operand is Null, otherwise True.
|
||||||
|
|
||||||
|
public static DBBool operator &(DBBool x, DBBool y) { |
||||||
|
return new DBBool(x.value < y.value? x.value: y.value); |
||||||
|
} |
||||||
|
|
||||||
|
// Logical OR operator. Returns True if either operand is True, otherwise
|
||||||
|
// Null if either operand is Null, otherwise False.
|
||||||
|
|
||||||
|
public static DBBool operator |(DBBool x, DBBool y) { |
||||||
|
return new DBBool(x.value > y.value? x.value: y.value); |
||||||
|
} |
||||||
|
|
||||||
|
// Definitely true operator. Returns true if the operand is True, false
|
||||||
|
// otherwise.
|
||||||
|
|
||||||
|
public static bool operator true(DBBool x) { |
||||||
|
return x.value > 0; |
||||||
|
} |
||||||
|
|
||||||
|
// Definitely false operator. Returns true if the operand is False, false
|
||||||
|
// otherwise.
|
||||||
|
|
||||||
|
public static bool operator false(DBBool x) { |
||||||
|
return x.value < 0; |
||||||
|
} |
||||||
|
|
||||||
|
public override string ToString() { |
||||||
|
if (value > 0) return "DBBool.True"; |
||||||
|
if (value < 0) return "DBBool.False"; |
||||||
|
return "DBBool.Null"; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public class DerivedClass: BaseClass |
||||||
|
{ |
||||||
|
string name = "derived name"; |
||||||
|
|
||||||
|
new public string Name { |
||||||
|
get { return name; } |
||||||
|
} |
||||||
|
|
||||||
|
public char SetterOnlyProperty { set { ; } } |
||||||
|
|
||||||
|
new public static string StaticField = "derived static field"; |
||||||
|
public const int ConstInt = 42; |
||||||
|
public const string ConstString = "const string"; |
||||||
|
public const object ConstNull = null; |
||||||
|
public const MyEnum ConstEnum = MyEnum.B; |
||||||
|
|
||||||
|
public static string StaticProperty { |
||||||
|
get { |
||||||
|
return "static property"; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static string StaticMethod() |
||||||
|
{ |
||||||
|
return "static method"; |
||||||
|
} |
||||||
|
|
||||||
|
public string Foo(object o) |
||||||
|
{ |
||||||
|
return "derived Foo - object"; |
||||||
|
} |
||||||
|
|
||||||
|
new public string Foo(int i) |
||||||
|
{ |
||||||
|
return "derived Foo - int"; |
||||||
|
} |
||||||
|
|
||||||
|
public string Foo(string s) |
||||||
|
{ |
||||||
|
return "derived Foo - string"; |
||||||
|
} |
||||||
|
|
||||||
|
public string this[double d] { |
||||||
|
get { |
||||||
|
return "derived indexer - double"; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public string this[string s] { |
||||||
|
get { |
||||||
|
return "derived indexer - string"; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public string Convert(string s, double d) |
||||||
|
{ |
||||||
|
return "converted to " + s + " and " + d; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public enum MyEnum { A = 3, B = 6 }; |
||||||
|
|
||||||
|
string instanceField = "instance field value"; |
||||||
|
static string staticField = "static field value"; |
||||||
|
|
||||||
|
public class A<T> { |
||||||
|
public class B { |
||||||
|
public class C<U> { |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static void Main() |
||||||
|
{ |
||||||
|
new ExpressionEvaluatorVisitor_Tests().Fun("function argument"); |
||||||
|
} |
||||||
|
|
||||||
|
static bool WorkerThreadMoved = false; |
||||||
|
|
||||||
|
public unsafe void Fun(string arg) |
||||||
|
{ |
||||||
|
bool flag = true; |
||||||
|
byte b = 1; |
||||||
|
int i = 4; |
||||||
|
int* iPtr = &i; |
||||||
|
float pi = 3.14f; |
||||||
|
string hi = "hi"; |
||||||
|
string emptyString = ""; |
||||||
|
|
||||||
|
char[] array = "Hello".ToCharArray(); |
||||||
|
char[] array2 = "world".ToCharArray(); |
||||||
|
char[][] arrays = new char[][] {array, array2}; |
||||||
|
List<char> list = new List<char>(array); |
||||||
|
|
||||||
|
DerivedClass myClass = new DerivedClass(); |
||||||
|
BaseClass myClass2 = myClass; |
||||||
|
|
||||||
|
int*[][,] complexType1 = new int*[][,] { new int*[,] { { (int*)0xDA1D } } }; |
||||||
|
A<int>.B.C<char>[][,] complexType2 = new A<int>.B.C<char>[0][,]; |
||||||
|
|
||||||
|
// System.Threading.Thread bgWork = new System.Threading.Thread(
|
||||||
|
// delegate() { WorkerThreadMoved = true; }
|
||||||
|
// );
|
||||||
|
//
|
||||||
|
// System.Diagnostics.Debugger.Break();
|
||||||
|
// bgWork.Start();
|
||||||
|
// System.Threading.Thread.Sleep(100);
|
||||||
|
|
||||||
|
System.Diagnostics.Debugger.Break(); |
||||||
|
|
||||||
|
i++; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#if TEST_CODE
|
||||||
|
namespace Debugger.Tests |
||||||
|
{ |
||||||
|
using ICSharpCode.NRefactory; |
||||||
|
using ICSharpCode.NRefactory.CSharp; |
||||||
|
using ICSharpCode.NRefactory.Semantics; |
||||||
|
using ICSharpCode.NRefactory.TypeSystem; |
||||||
|
using ICSharpCode.SharpDevelop.Services; |
||||||
|
using NUnit.Framework; |
||||||
|
using Debugger.AddIn; |
||||||
|
using ICSharpCode.NRefactory.CSharp.Resolver; |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Description of ExpressionEvaluatorVisitor_Tests.
|
||||||
|
/// </summary>
|
||||||
|
public partial class DebuggerTests |
||||||
|
{ |
||||||
|
[Test] |
||||||
|
public void ExpressionEvaluatorVisitor_Tests() |
||||||
|
{ |
||||||
|
StartTest(); |
||||||
|
|
||||||
|
AssertEval("i", "4"); |
||||||
|
AssertEval("pi", "3.14f"); |
||||||
|
AssertEval("hi", "\"hi\""); |
||||||
|
AssertEval("i is int", "true"); |
||||||
|
AssertEval("i is string", "false"); |
||||||
|
// AssertEval("hi + i", "\"hi4\"");
|
||||||
|
// AssertEval("hi + 1", "\"hi1\"");
|
||||||
|
AssertEval("i > 2 ? i : i * 2", "4"); |
||||||
|
AssertEval("i < 2 ? i : i * 2", "8"); |
||||||
|
AssertEval("DBBool.True.IsTrue", "true"); |
||||||
|
// AssertEval("i < 2 ? i : i * 2", "8");
|
||||||
|
|
||||||
|
|
||||||
|
EndTest(false); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
void AssertEval(string expression, string expected) |
||||||
|
{ |
||||||
|
NUnit.Framework.Assert.AreEqual(expected, ExpressionEvaluationVisitor.FormatValue(EvalThread, Evaluate(CurrentStackFrame, EvalThread, expression, GetResource("ExpressionEvaluatorVisitor_Tests.cs")))); |
||||||
|
} |
||||||
|
|
||||||
|
static ResolveResult ResolveSnippet(string fileName, TextLocation location, string contextCode, string codeSnippet, ICompilation compilation) |
||||||
|
{ |
||||||
|
CSharpParser contextParser = new CSharpParser(); |
||||||
|
var cu = contextParser.Parse(contextCode, fileName); |
||||||
|
CSharpAstResolver contextResolver = new CSharpAstResolver(compilation, cu); |
||||||
|
var node = cu.GetNodeAt(location); |
||||||
|
CSharpResolver context; |
||||||
|
if (node != null) |
||||||
|
context = contextResolver.GetResolverStateAfter(node, CancellationToken.None); |
||||||
|
else |
||||||
|
context = new CSharpResolver(compilation); |
||||||
|
CSharpParser parser = new CSharpParser(); |
||||||
|
var expr = parser.ParseExpression(new StringReader(codeSnippet)); |
||||||
|
Assert.IsFalse(parser.HasErrors); |
||||||
|
CSharpAstResolver snippetResolver = new CSharpAstResolver(context, expr); |
||||||
|
return snippetResolver.Resolve(expr, CancellationToken.None); |
||||||
|
} |
||||||
|
|
||||||
|
static Value Evaluate(StackFrame frame, Thread evalThread, string code, string contextCode) |
||||||
|
{ |
||||||
|
if (frame == null || frame.NextStatement == null) |
||||||
|
throw new GetValueException("no stackframe available!"); |
||||||
|
var location = frame.NextStatement; |
||||||
|
var rr = ResolveSnippet(location.Filename, new TextLocation(location.StartLine, location.StartColumn), contextCode, code, frame.MethodInfo.DebugModule.Assembly.Compilation); |
||||||
|
return new ExpressionEvaluationVisitor(frame, evalThread, frame.MethodInfo.DebugModule.Assembly.Compilation).Convert(rr); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
#endif
|
||||||
@ -1,459 +0,0 @@ |
|||||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
|
||||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
|
||||||
|
|
||||||
using System; |
|
||||||
using System.Collections.Generic; |
|
||||||
|
|
||||||
namespace Debugger.Tests |
|
||||||
{ |
|
||||||
public class ExpressionEvaluator_Tests |
|
||||||
{ |
|
||||||
public class BaseClass |
|
||||||
{ |
|
||||||
string name = "base name"; |
|
||||||
|
|
||||||
public string Name { |
|
||||||
get { return name; } |
|
||||||
} |
|
||||||
|
|
||||||
public static string StaticField = "base static field"; |
|
||||||
|
|
||||||
public string Foo(int i) |
|
||||||
{ |
|
||||||
return "base Foo - int"; |
|
||||||
} |
|
||||||
|
|
||||||
public string Foo(double d) |
|
||||||
{ |
|
||||||
return "base Foo - double"; |
|
||||||
} |
|
||||||
|
|
||||||
public string this[long i] { |
|
||||||
get { |
|
||||||
return "base indexer - long"; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public class DerivedClass: BaseClass |
|
||||||
{ |
|
||||||
string name = "derived name"; |
|
||||||
|
|
||||||
new public string Name { |
|
||||||
get { return name; } |
|
||||||
} |
|
||||||
|
|
||||||
public char SetterOnlyProperty { set { ; } } |
|
||||||
|
|
||||||
new public static string StaticField = "derived static field"; |
|
||||||
public const int ConstInt = 42; |
|
||||||
public const string ConstString = "const string"; |
|
||||||
public const object ConstNull = null; |
|
||||||
public const MyEnum ConstEnum = MyEnum.B; |
|
||||||
|
|
||||||
public static string StaticProperty { |
|
||||||
get { |
|
||||||
return "static property"; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public static string StaticMethod() |
|
||||||
{ |
|
||||||
return "static method"; |
|
||||||
} |
|
||||||
|
|
||||||
public string Foo(object o) |
|
||||||
{ |
|
||||||
return "derived Foo - object"; |
|
||||||
} |
|
||||||
|
|
||||||
new public string Foo(int i) |
|
||||||
{ |
|
||||||
return "derived Foo - int"; |
|
||||||
} |
|
||||||
|
|
||||||
public string Foo(string s) |
|
||||||
{ |
|
||||||
return "derived Foo - string"; |
|
||||||
} |
|
||||||
|
|
||||||
public string this[double d] { |
|
||||||
get { |
|
||||||
return "derived indexer - double"; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public string this[string s] { |
|
||||||
get { |
|
||||||
return "derived indexer - string"; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public string Convert(string s, double d) |
|
||||||
{ |
|
||||||
return "converted to " + s + " and " + d; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public enum MyEnum { A = 3, B = 6 }; |
|
||||||
|
|
||||||
string instanceField = "instance field value"; |
|
||||||
static string staticField = "static field value"; |
|
||||||
|
|
||||||
public class A<T> { |
|
||||||
public class B { |
|
||||||
public class C<U> { |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public static void Main() |
|
||||||
{ |
|
||||||
new ExpressionEvaluator_Tests().Fun("function argument"); |
|
||||||
} |
|
||||||
|
|
||||||
static bool WorkerThreadMoved = false; |
|
||||||
|
|
||||||
public unsafe void Fun(string arg) |
|
||||||
{ |
|
||||||
bool flag = true; |
|
||||||
byte b = 1; |
|
||||||
int i = 4; |
|
||||||
int* iPtr = &i; |
|
||||||
float pi = 3.14f; |
|
||||||
string hi = "hi"; |
|
||||||
string emptyString = ""; |
|
||||||
|
|
||||||
char[] array = "Hello".ToCharArray(); |
|
||||||
char[] array2 = "world".ToCharArray(); |
|
||||||
char[][] arrays = new char[][] {array, array2}; |
|
||||||
List<char> list = new List<char>(array); |
|
||||||
|
|
||||||
DerivedClass myClass = new DerivedClass(); |
|
||||||
BaseClass myClass2 = myClass; |
|
||||||
|
|
||||||
int*[][,] complexType1 = new int*[][,] { new int*[,] { { (int*)0xDA1D } } }; |
|
||||||
A<int>.B.C<char>[][,] complexType2 = new A<int>.B.C<char>[0][,]; |
|
||||||
|
|
||||||
System.Threading.Thread bgWork = new System.Threading.Thread( |
|
||||||
delegate() { WorkerThreadMoved = true; } |
|
||||||
); |
|
||||||
|
|
||||||
System.Diagnostics.Debugger.Break(); |
|
||||||
bgWork.Start(); |
|
||||||
System.Threading.Thread.Sleep(100); |
|
||||||
System.Diagnostics.Debugger.Break(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
#if TEST_CODE
|
|
||||||
namespace Debugger.Tests { |
|
||||||
using Debugger.MetaData; |
|
||||||
using System.Reflection; |
|
||||||
using ICSharpCode.NRefactory; |
|
||||||
using ICSharpCode.NRefactory.Ast; |
|
||||||
using ICSharpCode.NRefactory.Visitors; |
|
||||||
using NUnit.Framework; |
|
||||||
|
|
||||||
public partial class DebuggerTests |
|
||||||
{ |
|
||||||
string expressionsInput = @"
|
|
||||||
b; i; *i; *iPtr; pi |
|
||||||
pi - 3; pi + b; i + b; (uint)2 - 3; ((uint)2 - 3).GetType() ; (ulong)2 - 3 ; (b + b).GetType() |
|
||||||
1 << 4; 7 << -1; 1 << (uint)2; 1.0 & 2.0; System.Int32.MaxValue + 1; (uint)2 - (uint)3; 1 / 0 |
|
||||||
hi + hi; hi + ''#''; hi + pi; hi + null; emptyString; '''' |
|
||||||
hi + ''#'' == ''hi#''; hi + ''#'' == (object) ''hi#''; hi == (string)null; hi == null; hi == 1; null == null |
|
||||||
|
|
||||||
(5 + 6) % (1 + 2); 3 % 2 == 1 |
|
||||||
15 & 255; 15 && 255; (ulong)1 + (long)1 /* invalid */ |
|
||||||
b + 3 == i; b + 4 == i |
|
||||||
true == true; true == false |
|
||||||
|
|
||||||
i = 10; -i; ++i; i++; +i; i += 1; ~i; i = 4 |
|
||||||
-(byte)1; (-(byte)1).GetType(); -(uint)1; (-(uint)1).GetType(); -(ulong)1 /* invalid */ |
|
||||||
-2147483648 /* int.MinValue */; (-2147483648).GetType(); -(-2147483648) |
|
||||||
-9223372036854775808 /* long.MinValue */; (-9223372036854775808).GetType(); -(-9223372036854775808) |
|
||||||
-1.0; ~1.0; !1; flag; !flag |
|
||||||
|
|
||||||
arg; instanceField; staticField |
|
||||||
|
|
||||||
array; arrays; array[1]; array[i]; array[i - 1] |
|
||||||
new char[3] |
|
||||||
new char[b] {'a'} |
|
||||||
new char[3] {'a', 'b', 'c'} |
|
||||||
new char[] {'a', 'b', 'c'} |
|
||||||
new char[][] { new char[] { 'a', 'b' }, new char[] { 'c', 'd' } } |
|
||||||
new char[5] {'a', 'b', 'c'} |
|
||||||
new char[1,2] |
|
||||||
new char[pi] |
|
||||||
list; list[1]; list[i]; hi[1]; ''abcd''[2] |
|
||||||
|
|
||||||
list.Add((char)42); list.Add((char)52); list |
|
||||||
list = new System.Collections.Generic.List<char>(array2); list |
|
||||||
|
|
||||||
(Debugger.Tests.ExpressionEvaluator_Tests.BaseClass)myClass |
|
||||||
(Debugger.Tests.ExpressionEvaluator_Tests.DerivedClass)myClass2 |
|
||||||
(string)i |
|
||||||
(string)hi |
|
||||||
(int)hi |
|
||||||
";
|
|
||||||
|
|
||||||
[NUnit.Framework.Test] |
|
||||||
[NUnit.Framework.Ignore("Test fails randomly (race condition)")] |
|
||||||
public void ExpressionEvaluator_Tests() |
|
||||||
{ |
|
||||||
StartTest(); |
|
||||||
this.CurrentStackFrame.StepOver(); |
|
||||||
this.CurrentStackFrame.StepOver(); // Start worker thread
|
|
||||||
|
|
||||||
EvalAll(expressionsInput); |
|
||||||
|
|
||||||
// Test member hiding / overloading
|
|
||||||
|
|
||||||
Value myClass = this.CurrentStackFrame.GetLocalVariableValue("myClass").GetPermanentReference(this.EvalThread); |
|
||||||
Expression myClassExpr = this.CurrentStackFrame.MethodInfo.GetLocalVariable(this.CurrentStackFrame.IP, "myClass").GetExpression(); |
|
||||||
|
|
||||||
List<Expression> expressions = new List<Expression>(); |
|
||||||
foreach(MemberInfo memberInfo in myClass.Type.GetFieldsAndNonIndexedProperties(DebugType.BindingFlagsAll)) { |
|
||||||
expressions.Add(myClassExpr.AppendMemberReference((IDebugMemberInfo)memberInfo)); |
|
||||||
} |
|
||||||
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()); |
|
||||||
} |
|
||||||
|
|
||||||
string input2 = @"
|
|
||||||
myClass.Foo(1.0) |
|
||||||
myClass.Foo(myClass) |
|
||||||
myClass.Foo(1) |
|
||||||
myClass.Foo(''abc'') |
|
||||||
myClass[1] |
|
||||||
myClass[(long)1] |
|
||||||
myClass[1.0] |
|
||||||
myClass[''abc''] |
|
||||||
myClass.Convert(1, 2) |
|
||||||
myClass.Convert(''abc'', 2) |
|
||||||
";
|
|
||||||
|
|
||||||
EvalAll(input2); |
|
||||||
|
|
||||||
// Test type round tripping
|
|
||||||
|
|
||||||
foreach(DebugLocalVariableInfo locVar in this.CurrentStackFrame.MethodInfo.GetLocalVariables()) { |
|
||||||
if (locVar.Name.StartsWith("complexType")) { |
|
||||||
TypeReference complexTypeRef = locVar.LocalType.GetTypeReference(); |
|
||||||
string code = "typeof(" + complexTypeRef.PrettyPrint() + ")"; |
|
||||||
TypeOfExpression complexTypeRefRT = (TypeOfExpression)ExpressionEvaluator.Parse(code, SupportedLanguage.CSharp); |
|
||||||
DebugType type = complexTypeRefRT.TypeReference.ResolveType(this.CurrentStackFrame.AppDomain); |
|
||||||
string status = locVar.LocalType.FullName == type.FullName ? "ok" : "fail"; |
|
||||||
ObjectDumpToString("TypeResulution", string.Format(" {0} = {1} ({2})", code, type.FullName, status)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Type equality
|
|
||||||
|
|
||||||
DebugLocalVariableInfo loc = this.CurrentStackFrame.MethodInfo.GetLocalVariable(this.CurrentStackFrame.IP, "list"); |
|
||||||
Type locType = loc.LocalType; |
|
||||||
Type valType = loc.GetValue(this.CurrentStackFrame).Type; |
|
||||||
ObjectDump("TypesIdentitcal", object.ReferenceEquals(locType, valType)); |
|
||||||
ObjectDump("TypesEqual", locType == valType); |
|
||||||
|
|
||||||
ObjectDump("WorkerThreadMoved", this.CurrentStackFrame.GetThisValue().GetMemberValue(this.EvalThread, "WorkerThreadMoved").AsString()); |
|
||||||
process.Continue(); |
|
||||||
ObjectDump("WorkerThreadMoved", this.CurrentStackFrame.GetThisValue().GetMemberValue(this.EvalThread, "WorkerThreadMoved").AsString()); |
|
||||||
|
|
||||||
EndTest(); |
|
||||||
} |
|
||||||
|
|
||||||
void EvalAll(string exprs) |
|
||||||
{ |
|
||||||
exprs = exprs.Replace("''", "\""); |
|
||||||
foreach(string line in exprs.Split('\n', ';')) { |
|
||||||
Eval(line.Trim()); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void Eval(string expr) |
|
||||||
{ |
|
||||||
string restultFmted; |
|
||||||
if (string.IsNullOrEmpty(expr)) { |
|
||||||
restultFmted = null; |
|
||||||
} else { |
|
||||||
try { |
|
||||||
Value result = ICSharpCode.NRefactory.Visitors.ExpressionEvaluator.Evaluate(expr, SupportedLanguage.CSharp, this.CurrentStackFrame); |
|
||||||
restultFmted = ICSharpCode.NRefactory.Visitors.ExpressionEvaluator.FormatValue(this.EvalThread, result); |
|
||||||
} catch (GetValueException e) { |
|
||||||
restultFmted = e.Message; |
|
||||||
} |
|
||||||
} |
|
||||||
if (restultFmted != null) { |
|
||||||
restultFmted = restultFmted.Replace("\0", "\\0"); |
|
||||||
ObjectDump("Eval", " " + expr + " = " + restultFmted + " "); |
|
||||||
} else { |
|
||||||
ObjectDump("Eval", " " + expr); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
#endif
|
|
||||||
|
|
||||||
#if EXPECTED_OUTPUT
|
|
||||||
<?xml version="1.0" encoding="utf-8"?> |
|
||||||
<DebuggerTests> |
|
||||||
<Test |
|
||||||
name="ExpressionEvaluator_Tests.cs"> |
|
||||||
<ProcessStarted /> |
|
||||||
<ModuleLoaded>mscorlib.dll (No symbols)</ModuleLoaded> |
|
||||||
<ModuleLoaded>ExpressionEvaluator_Tests.exe (Has symbols)</ModuleLoaded> |
|
||||||
<DebuggingPaused>Break ExpressionEvaluator_Tests.cs:143,4-143,40</DebuggingPaused> |
|
||||||
<DebuggingPaused>StepComplete ExpressionEvaluator_Tests.cs:144,4-144,19</DebuggingPaused> |
|
||||||
<DebuggingPaused>StepComplete ExpressionEvaluator_Tests.cs:145,4-145,39</DebuggingPaused> |
|
||||||
<Eval> </Eval> |
|
||||||
<Eval> b = 1 </Eval> |
|
||||||
<Eval> i = 4 </Eval> |
|
||||||
<Eval> *i = Target object is not a pointer </Eval> |
|
||||||
<Eval> *iPtr = 4 </Eval> |
|
||||||
<Eval> pi = 3.14 </Eval> |
|
||||||
<Eval> pi - 3 = 0.1400001 </Eval> |
|
||||||
<Eval> pi + b = 4.14 </Eval> |
|
||||||
<Eval> i + b = 5 </Eval> |
|
||||||
<Eval> (uint)2 - 3 = -1 </Eval> |
|
||||||
<Eval> ((uint)2 - 3).GetType() = System.Int64 </Eval> |
|
||||||
<Eval> (ulong)2 - 3 = Can not use the binary operator Subtract on types System.UInt64 and System.Int32 </Eval> |
|
||||||
<Eval> (b + b).GetType() = System.Int32 </Eval> |
|
||||||
<Eval> 1 << 4 = 16 </Eval> |
|
||||||
<Eval> 7 << -1 = -2147483648 </Eval> |
|
||||||
<Eval> 1 << (uint)2 = Can not use the binary operator ShiftLeft on types System.Int32 and System.UInt32 </Eval> |
|
||||||
<Eval> 1.0 & 2.0 = Can not use the binary operator BitwiseAnd on types System.Double and System.Double </Eval> |
|
||||||
<Eval> System.Int32.MaxValue + 1 = Arithmetic operation resulted in an overflow. </Eval> |
|
||||||
<Eval> (uint)2 - (uint)3 = Arithmetic operation resulted in an overflow. </Eval> |
|
||||||
<Eval> 1 / 0 = Attempted to divide by zero. </Eval> |
|
||||||
<Eval> hi + hi = "hihi" </Eval> |
|
||||||
<Eval> hi + "#" = "hi#" </Eval> |
|
||||||
<Eval> hi + pi = "hi3.14" </Eval> |
|
||||||
<Eval> hi + null = "hi" </Eval> |
|
||||||
<Eval> emptyString = "" </Eval> |
|
||||||
<Eval> "" = "" </Eval> |
|
||||||
<Eval> hi + "#" == "hi#" = True </Eval> |
|
||||||
<Eval> hi + "#" == (object) "hi#" = False </Eval> |
|
||||||
<Eval> hi == (string)null = False </Eval> |
|
||||||
<Eval> hi == null = False </Eval> |
|
||||||
<Eval> hi == 1 = Can not use the binary operator Equality on types System.String and System.Int32 </Eval> |
|
||||||
<Eval> null == null = True </Eval> |
|
||||||
<Eval> </Eval> |
|
||||||
<Eval> (5 + 6) % (1 + 2) = 2 </Eval> |
|
||||||
<Eval> 3 % 2 == 1 = True </Eval> |
|
||||||
<Eval> 15 & 255 = 15 </Eval> |
|
||||||
<Eval> 15 && 255 = Can not use the binary operator LogicalAnd on types System.Int32 and System.Int32 </Eval> |
|
||||||
<Eval> (ulong)1 + (long)1 /* invalid */ = Can not use the binary operator Add on types System.UInt64 and System.Int64 </Eval> |
|
||||||
<Eval> b + 3 == i = True </Eval> |
|
||||||
<Eval> b + 4 == i = False </Eval> |
|
||||||
<Eval> true == true = True </Eval> |
|
||||||
<Eval> true == false = False </Eval> |
|
||||||
<Eval> </Eval> |
|
||||||
<Eval> i = 10 = 10 </Eval> |
|
||||||
<Eval> -i = -10 </Eval> |
|
||||||
<Eval> ++i = 11 </Eval> |
|
||||||
<Eval> i++ = 11 </Eval> |
|
||||||
<Eval> +i = 12 </Eval> |
|
||||||
<Eval> i += 1 = 13 </Eval> |
|
||||||
<Eval> ~i = -14 </Eval> |
|
||||||
<Eval> i = 4 = 4 </Eval> |
|
||||||
<Eval> -(byte)1 = -1 </Eval> |
|
||||||
<Eval> (-(byte)1).GetType() = System.Int32 </Eval> |
|
||||||
<Eval> -(uint)1 = -1 </Eval> |
|
||||||
<Eval> (-(uint)1).GetType() = System.Int64 </Eval> |
|
||||||
<Eval> -(ulong)1 /* invalid */ = Can not use the unary operator Minus on type System.UInt64 </Eval> |
|
||||||
<Eval> -2147483648 /* int.MinValue */ = -2147483648 </Eval> |
|
||||||
<Eval> (-2147483648).GetType() = System.Int32 </Eval> |
|
||||||
<Eval> -(-2147483648) = Arithmetic operation resulted in an overflow. </Eval> |
|
||||||
<Eval> -9223372036854775808 /* long.MinValue */ = -9223372036854775808 </Eval> |
|
||||||
<Eval> (-9223372036854775808).GetType() = System.Int64 </Eval> |
|
||||||
<Eval> -(-9223372036854775808) = Arithmetic operation resulted in an overflow. </Eval> |
|
||||||
<Eval> -1.0 = -1 </Eval> |
|
||||||
<Eval> ~1.0 = Can not use the unary operator BitNot on type System.Double </Eval> |
|
||||||
<Eval> !1 = Can not use the unary operator Not on type System.Int32 </Eval> |
|
||||||
<Eval> flag = True </Eval> |
|
||||||
<Eval> !flag = False </Eval> |
|
||||||
<Eval> </Eval> |
|
||||||
<Eval> arg = "function argument" </Eval> |
|
||||||
<Eval> instanceField = "instance field value" </Eval> |
|
||||||
<Eval> staticField = "static field value" </Eval> |
|
||||||
<Eval> </Eval> |
|
||||||
<Eval> array = Char[] {'H', 'e', 'l', 'l', 'o'} </Eval> |
|
||||||
<Eval> arrays = Char[][] {Char[] {'H', 'e', 'l', 'l', 'o'}, Char[] {'w', 'o', 'r', 'l', 'd'}} </Eval> |
|
||||||
<Eval> array[1] = 'e' </Eval> |
|
||||||
<Eval> array[i] = 'o' </Eval> |
|
||||||
<Eval> array[i - 1] = 'l' </Eval> |
|
||||||
<Eval> new char[3] = Char[] {'\0', '\0', '\0'} </Eval> |
|
||||||
<Eval> new char[b] {'a'} = Char[] {'a'} </Eval> |
|
||||||
<Eval> new char[3] {'a', 'b', 'c'} = Char[] {'a', 'b', 'c'} </Eval> |
|
||||||
<Eval> new char[] {'a', 'b', 'c'} = Char[] {'a', 'b', 'c'} </Eval> |
|
||||||
<Eval> new char[][] { new char[] { 'a', 'b' }, new char[] { 'c', 'd' } } = Char[][] {Char[] {'a', 'b'}, Char[] {'c', 'd'}} </Eval> |
|
||||||
<Eval> new char[5] {'a', 'b', 'c'} = Incorrect initializer length </Eval> |
|
||||||
<Eval> new char[1,2] = Multi-dimensional arrays are not suppored </Eval> |
|
||||||
<Eval> new char[pi] = Integer expected </Eval> |
|
||||||
<Eval> list = List`1 {'H', 'e', 'l', 'l', 'o'} </Eval> |
|
||||||
<Eval> list[1] = 'e' </Eval> |
|
||||||
<Eval> list[i] = 'o' </Eval> |
|
||||||
<Eval> hi[1] = 'i' </Eval> |
|
||||||
<Eval> "abcd"[2] = 'c' </Eval> |
|
||||||
<Eval> </Eval> |
|
||||||
<Eval> list.Add((char)42)</Eval> |
|
||||||
<Eval> list.Add((char)52)</Eval> |
|
||||||
<Eval> list = List`1 {'H', 'e', 'l', 'l', 'o', '*', '4'} </Eval> |
|
||||||
<Eval> list = new System.Collections.Generic.List<char>(array2) = List`1 {'w', 'o', 'r', 'l', 'd'} </Eval> |
|
||||||
<Eval> list = List`1 {'w', 'o', 'r', 'l', 'd'} </Eval> |
|
||||||
<Eval> </Eval> |
|
||||||
<Eval> (Debugger.Tests.ExpressionEvaluator_Tests.BaseClass)myClass = Debugger.Tests.ExpressionEvaluator_Tests+DerivedClass </Eval> |
|
||||||
<Eval> (Debugger.Tests.ExpressionEvaluator_Tests.DerivedClass)myClass2 = Debugger.Tests.ExpressionEvaluator_Tests+DerivedClass </Eval> |
|
||||||
<Eval> (string)i = Can not cast System.Int32 to System.String </Eval> |
|
||||||
<Eval> (string)hi = "hi" </Eval> |
|
||||||
<Eval> (int)hi = Can not cast System.String to System.Int32 </Eval> |
|
||||||
<Eval> </Eval> |
|
||||||
<Eval> Debugger.Tests.ExpressionEvaluator_Tests.DerivedClass.ConstInt = 42 </Eval> |
|
||||||
<Eval> Debugger.Tests.ExpressionEvaluator_Tests.DerivedClass.ConstString = "const string" </Eval> |
|
||||||
<Eval> Debugger.Tests.ExpressionEvaluator_Tests.DerivedClass.ConstNull = null </Eval> |
|
||||||
<Eval> Debugger.Tests.ExpressionEvaluator_Tests.DerivedClass.ConstEnum = B </Eval> |
|
||||||
<Eval> myClass.name = "derived name" </Eval> |
|
||||||
<Eval> Debugger.Tests.ExpressionEvaluator_Tests.DerivedClass.StaticField = "derived static field" </Eval> |
|
||||||
<Eval> myClass.Name = "derived name" </Eval> |
|
||||||
<Eval> Debugger.Tests.ExpressionEvaluator_Tests.DerivedClass.StaticProperty = "static property" </Eval> |
|
||||||
<Eval> ((Debugger.Tests.ExpressionEvaluator_Tests.BaseClass)myClass).name = "base name" </Eval> |
|
||||||
<Eval> Debugger.Tests.ExpressionEvaluator_Tests.BaseClass.StaticField = "base static field" </Eval> |
|
||||||
<Eval> ((Debugger.Tests.ExpressionEvaluator_Tests.BaseClass)myClass).Name = "base name" </Eval> |
|
||||||
<Eval> Debugger.Tests.ExpressionEvaluator_Tests.DerivedClass.StaticMethod() = "static method" </Eval> |
|
||||||
<Eval> ((Debugger.Tests.ExpressionEvaluator_Tests.BaseClass)myClass).Foo(1) = "base Foo - int" </Eval> |
|
||||||
<Eval> myClass.Foo(1) = "derived Foo - int" </Eval> |
|
||||||
<Eval> myClass.Foo("a") = "derived Foo - string" </Eval> |
|
||||||
<Eval> </Eval> |
|
||||||
<Eval> myClass.Foo(1.0) = "base Foo - double" </Eval> |
|
||||||
<Eval> myClass.Foo(myClass) = "derived Foo - object" </Eval> |
|
||||||
<Eval> myClass.Foo(1) = "derived Foo - int" </Eval> |
|
||||||
<Eval> myClass.Foo("abc") = "derived Foo - string" </Eval> |
|
||||||
<Eval> myClass[1] = More then one applicable overload found: |
|
||||||
String Debugger.Tests.ExpressionEvaluator_Tests+DerivedClass.Item[Double d] |
|
||||||
String Debugger.Tests.ExpressionEvaluator_Tests+BaseClass.Item[Int64 i] </Eval> |
|
||||||
<Eval> myClass[(long)1] = "base indexer - long" </Eval> |
|
||||||
<Eval> myClass[1.0] = "derived indexer - double" </Eval> |
|
||||||
<Eval> myClass["abc"] = "derived indexer - string" </Eval> |
|
||||||
<Eval> myClass.Convert(1, 2) = Incorrect parameter type for 's'. Excpeted System.String, seen System.Int32 </Eval> |
|
||||||
<Eval> myClass.Convert("abc", 2) = "converted to abc and 2" </Eval> |
|
||||||
<Eval> </Eval> |
|
||||||
<TypeResulution> typeof(System.Int32*[][,]) = System.Int32*[,][] (ok)</TypeResulution> |
|
||||||
<TypeResulution> typeof(Debugger.Tests.ExpressionEvaluator_Tests.A<System.Int32>.B.C<System.Char>[][,]) = Debugger.Tests.ExpressionEvaluator_Tests+A`1+B+C`1[System.Int32,System.Char][,][] (ok)</TypeResulution> |
|
||||||
<TypesIdentitcal>True</TypesIdentitcal> |
|
||||||
<TypesEqual>True</TypesEqual> |
|
||||||
<WorkerThreadMoved>False</WorkerThreadMoved> |
|
||||||
<DebuggingPaused>Break ExpressionEvaluator_Tests.cs:146,4-146,40</DebuggingPaused> |
|
||||||
<WorkerThreadMoved>True</WorkerThreadMoved> |
|
||||||
<ProcessExited /> |
|
||||||
</Test> |
|
||||||
</DebuggerTests> |
|
||||||
#endif // EXPECTED_OUTPUT
|
|
||||||
Loading…
Reference in new issue