Browse Source

Implement better value conversion in the evaluator.

newNRvisualizers
Siegfried Pammer 14 years ago
parent
commit
2857444c52
  1. 55
      src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionEvaluationVisitor.cs
  2. 2
      src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs
  3. 1
      src/AddIns/Debugger/Debugger.Tests/DebuggerTestsBase.cs
  4. 16
      src/AddIns/Debugger/Debugger.Tests/Tests/ExpressionEvaluatorVisitor_Tests.cs
  5. 1
      src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ICompilation.cs

55
src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionEvaluationVisitor.cs

@ -28,7 +28,29 @@ namespace Debugger.AddIn @@ -28,7 +28,29 @@ namespace Debugger.AddIn
{
public static ResolveResult ToResolveResult(this Value value, StackFrame context)
{
return new ConstantResolveResult(value.Type, value.PrimitiveValue);
return new ValueResolveResult(value);
}
}
public class ValueResolveResult : ResolveResult
{
Value value;
public ValueResolveResult(Value value) : base(value.Type)
{
this.value = value;
}
public Value Value {
get { return value; }
}
public override bool IsCompileTimeConstant {
get { return value.Type.IsKnownType(KnownTypeCode.String) || value.Type.IsPrimitiveType(); }
}
public override object ConstantValue {
get { return value.PrimitiveValue; }
}
}
@ -71,6 +93,11 @@ namespace Debugger.AddIn @@ -71,6 +93,11 @@ namespace Debugger.AddIn
throw new GetValueException("Unsupported language construct: " + result.GetType().Name);
}
Value Visit(ValueResolveResult result)
{
return result.Value;
}
Value Visit(ThisResolveResult result)
{
return context.GetThisValue(true);
@ -195,6 +222,8 @@ namespace Debugger.AddIn @@ -195,6 +222,8 @@ namespace Debugger.AddIn
Debug.Assert(operatorType != BinaryOperatorType.ConditionalAnd && operatorType != BinaryOperatorType.ConditionalOr && operatorType != BinaryOperatorType.NullCoalescing);
var lhs = Convert(result.Operands[0]).GetPermanentReference(evalThread);
var rhs = Convert(result.Operands[1]).GetPermanentReference(evalThread);
if (result.UserDefinedOperatorMethod != null)
return InvokeMethod(null, result.UserDefinedOperatorMethod, lhs, rhs);
var lhsRR = lhs.ToResolveResult(context);
var rhsRR = rhs.ToResolveResult(context);
CSharpResolver resolver = new CSharpResolver(debuggerTypeSystem).WithCheckForOverflow(checkForOverflow);
@ -206,7 +235,7 @@ namespace Debugger.AddIn @@ -206,7 +235,7 @@ namespace Debugger.AddIn
var method = debuggerTypeSystem.FindType(KnownTypeCode.String)
.GetMethods(m => m.Name == "Concat" && m.Parameters.Count == 2)
.Single(m => m.Parameters.All(p => p.Type.IsKnownType(KnownTypeCode.Object)));
return Value.InvokeMethod(evalThread, null, method, lhs, rhs);
return InvokeMethod(null, method, lhs, rhs);
}
throw new InvalidOperationException();
}
@ -225,9 +254,7 @@ namespace Debugger.AddIn @@ -225,9 +254,7 @@ namespace Debugger.AddIn
return lhs;
var rhs = Convert(result.Operands[1]);
var val = resolver.ResolveBinaryOperator(bitwiseOperatorType, lhs.ToResolveResult(context), rhs.ToResolveResult(context));
if (val.IsCompileTimeConstant)
return Convert(val);
throw new InvalidOperationException();
return Convert(val);
}
/// <remark
@ -292,6 +319,10 @@ namespace Debugger.AddIn @@ -292,6 +319,10 @@ namespace Debugger.AddIn
else if (result.Conversion.IsNumericConversion) {
var convVal = CSharpPrimitiveCast.Cast(ReflectionHelper.GetTypeCode(result.Type), val.PrimitiveValue, false);
return Eval.CreateValue(evalThread, convVal);
} else if (result.Conversion.IsUserDefined)
return InvokeMethod(null, result.Conversion.Method, val);
else if (result.Conversion.IsReferenceConversion && result.Conversion.IsImplicit) {
return val;
} else
throw new NotImplementedException();
}
@ -323,8 +354,10 @@ namespace Debugger.AddIn @@ -323,8 +354,10 @@ namespace Debugger.AddIn
usedMethod = (IMethod)importedMember;
} else
throw new GetValueException("Invoked member must be a method or property");
return Convert(result.TargetResult).InvokeMethod(evalThread, usedMethod, result.Arguments.Select(rr => Convert(rr)).ToArray());
Value target = null;
if (!usedMethod.IsStatic)
target = Convert(result.TargetResult);
return InvokeMethod(target, usedMethod, result.Arguments.Select(rr => Convert(rr)).ToArray());
}
Value Visit(NamespaceResolveResult result)
@ -332,6 +365,14 @@ namespace Debugger.AddIn @@ -332,6 +365,14 @@ namespace Debugger.AddIn
throw new GetValueException("Namespace not supported!");
}
Value InvokeMethod(Value thisValue, IMethod method, params Value[] arguments)
{
method = debuggerTypeSystem.Import(method);
if (method == null)
throw new GetValueException("Method not found!");
return Value.InvokeMethod(evalThread, thisValue, method, arguments);
}
public static string FormatValue(Thread evalThread, Value val)
{
if (val.IsNull) {

2
src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs

@ -601,7 +601,7 @@ namespace ICSharpCode.SharpDevelop.Services @@ -601,7 +601,7 @@ namespace ICSharpCode.SharpDevelop.Services
throw new GetValueException("no stackframe available!");
var location = CurrentStackFrame.NextStatement;
var fileName = new FileName(location.Filename);
var rr = SD.ParserService.ResolveSnippet(fileName, new TextLocation(location.StartLine, location.StartColumn), new ParseableFileContentFinder().Create(fileName), code, CurrentStackFrame.AppDomain.Compilation, System.Threading.CancellationToken.None);
var rr = SD.ParserService.ResolveSnippet(fileName, new TextLocation(location.StartLine, location.StartColumn), new ParseableFileContentFinder().Create(fileName), code, null, System.Threading.CancellationToken.None);
return new ExpressionEvaluationVisitor(CurrentStackFrame, EvalThread, CurrentStackFrame.AppDomain.Compilation).Convert(rr);
}

1
src/AddIns/Debugger/Debugger.Tests/DebuggerTestsBase.cs

@ -461,6 +461,7 @@ namespace Debugger.Tests @@ -461,6 +461,7 @@ namespace Debugger.Tests
compParams.TreatWarningsAsErrors = false;
compParams.IncludeDebugInformation = true;
compParams.ReferencedAssemblies.Add("System.dll");
compParams.ReferencedAssemblies.Add("System.Core.dll");
compParams.OutputAssembly = exeFilename;
compParams.CompilerOptions = "/unsafe /platform:x86 /target:winexe";
compParams.ReferencedAssemblies.Add(typeof(TestFixtureAttribute).Assembly.Location);

16
src/AddIns/Debugger/Debugger.Tests/Tests/ExpressionEvaluatorVisitor_Tests.cs

@ -5,6 +5,7 @@ using System; @@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Linq;
namespace Debugger.Tests
{
@ -227,6 +228,7 @@ namespace Debugger.Tests @@ -227,6 +228,7 @@ namespace Debugger.Tests
string hi = "hi";
string emptyString = "";
DBBool boo = DBBool.Null;
var enumerable = Enumerable.Empty<int>();
char[] array = "Hello".ToCharArray();
char[] array2 = "world".ToCharArray();
@ -265,12 +267,15 @@ namespace Debugger.Tests @@ -265,12 +267,15 @@ namespace Debugger.Tests
using NUnit.Framework;
using Debugger.AddIn;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
/// <summary>
/// Description of ExpressionEvaluatorVisitor_Tests.
/// </summary>
public partial class DebuggerTests
{
[Test]
public void ExpressionEvaluatorVisitor_Tests()
{
@ -287,6 +292,12 @@ namespace Debugger.Tests @@ -287,6 +292,12 @@ namespace Debugger.Tests
AssertEval("i < 2 ? i : i * 2", "8");
AssertEval("DBBool.True.IsTrue", "true");
AssertEval("i < 2 ? i : i * 2", "8");
AssertEval("DBBool.True || DBBool.Null", "DBBool.True");
AssertEval("DBBool.Null || DBBool.True", "DBBool.True");
AssertEval("DBBool.Null || DBBool.False", "DBBool.Null");
AssertEval("DBBool.False || DBBool.False", "DBBool.False");
AssertEval("array", "Char[] {'H', 'e', 'l', 'l', 'o'}");
AssertEval("array.ToList()", "List<Char> {'H', 'e', 'l', 'l', 'o'}");
EndTest(false);
}
@ -320,7 +331,10 @@ namespace Debugger.Tests @@ -320,7 +331,10 @@ namespace Debugger.Tests
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.AppDomain.Compilation);
var debuggerTypeSystem = frame.AppDomain.Compilation;
var compilation = new SimpleCompilation(debuggerTypeSystem.MainAssembly.UnresolvedAssembly, debuggerTypeSystem.ReferencedAssemblies.Select(a => a.UnresolvedAssembly));
var rr = ResolveSnippet(location.Filename, new TextLocation(location.StartLine, location.StartColumn),
contextCode, code, compilation);
return new ExpressionEvaluationVisitor(frame, evalThread, frame.AppDomain.Compilation).Convert(rr);
}
}

1
src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ICompilation.cs

@ -43,7 +43,6 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -43,7 +43,6 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// Gets the referenced assemblies.
/// This list does not include the main assembly.
/// </summary>
[ObsoleteAttribute("Use compilation.Assemblies.Where(asm != compilation.MainAssembly) instead.")]
IList<IAssembly> ReferencedAssemblies { get; }
/// <summary>

Loading…
Cancel
Save