Browse Source

use GetValueException instead of others in ExpressionEvaluationVisitor

implement support for equality comparison
pull/341/head
Siegfried Pammer 12 years ago
parent
commit
4be2da1692
  1. 55
      src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionEvaluationVisitor.cs
  2. 20
      src/AddIns/Debugger/Debugger.AddIn/Pads/AutoCompleteTextBox.cs
  3. 5
      src/AddIns/Debugger/Debugger.AddIn/Pads/DebuggerDotCompletion.cs
  4. 7
      src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs

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

@ -29,6 +29,7 @@ using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.Utils; using ICSharpCode.NRefactory.Utils;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Services; using ICSharpCode.SharpDevelop.Services;
namespace Debugger.AddIn namespace Debugger.AddIn
@ -239,7 +240,7 @@ namespace Debugger.AddIn
var val = resolver.ResolveUnaryOperator(operatorType, operand); var val = resolver.ResolveUnaryOperator(operatorType, operand);
if (val.IsCompileTimeConstant) if (val.IsCompileTimeConstant)
return Convert(val); return Convert(val);
throw new InvalidOperationException(); throw new GetValueException("Operator {0} is not supported for {1}!", operatorType, new CSharpAmbience().ConvertType(operand.Type));
} }
Value VisitBinaryOperator(OperatorResolveResult result, BinaryOperatorType operatorType, bool checkForOverflow = false) Value VisitBinaryOperator(OperatorResolveResult result, BinaryOperatorType operatorType, bool checkForOverflow = false)
@ -256,14 +257,41 @@ namespace Debugger.AddIn
var val = resolver.ResolveBinaryOperator(operatorType, lhsRR, rhsRR); var val = resolver.ResolveBinaryOperator(operatorType, lhsRR, rhsRR);
if (val.IsCompileTimeConstant) if (val.IsCompileTimeConstant)
return Convert(val); return Convert(val);
if (operatorType == BinaryOperatorType.Add && switch (operatorType) {
(lhsRR.Type.IsKnownType(KnownTypeCode.String) || rhsRR.Type.IsKnownType(KnownTypeCode.String))) { case BinaryOperatorType.Equality:
case BinaryOperatorType.InEquality:
bool equality = (operatorType == BinaryOperatorType.Equality);
if (lhsRR.Type.IsKnownType(KnownTypeCode.String) && rhsRR.Type.IsKnownType(KnownTypeCode.String)) {
if (lhs.IsNull || rhs.IsNull) {
bool bothNull = lhs.IsNull && rhs.IsNull;
return Eval.CreateValue(evalThread, equality ? bothNull : !bothNull);
} else {
bool equal = (string)lhs.PrimitiveValue == (string)rhs.PrimitiveValue;
return Eval.CreateValue(evalThread, equality ? equal : !equal);
}
}
if (lhsRR.Type.IsReferenceType != false && rhsRR.Type.IsReferenceType != false) {
// Reference comparison
if (lhs.IsNull || rhs.IsNull) {
bool bothNull = lhs.IsNull && rhs.IsNull;
return Eval.CreateValue(evalThread, equality ? bothNull : !bothNull);
} else {
bool equal = lhs.Address == rhs.Address;
return Eval.CreateValue(evalThread, equality ? equal : !equal);
}
}
goto default;
case BinaryOperatorType.Add:
if (lhsRR.Type.IsKnownType(KnownTypeCode.String) || rhsRR.Type.IsKnownType(KnownTypeCode.String)) {
var method = debuggerTypeSystem.FindType(KnownTypeCode.String) var method = debuggerTypeSystem.FindType(KnownTypeCode.String)
.GetMethods(m => m.Name == "Concat" && m.Parameters.Count == 2) .GetMethods(m => m.Name == "Concat" && m.Parameters.Count == 2)
.Single(m => m.Parameters.All(p => p.Type.IsKnownType(KnownTypeCode.Object))); .Single(m => m.Parameters.All(p => p.Type.IsKnownType(KnownTypeCode.Object)));
return InvokeMethod(null, method, lhs, rhs); return InvokeMethod(null, method, lhs, rhs);
} }
throw new InvalidOperationException(); goto default;
default:
throw new GetValueException("Operator {0} is not supported for {1} and {2}!", operatorType, new CSharpAmbience().ConvertType(lhsRR.Type), new CSharpAmbience().ConvertType(rhsRR.Type));
}
} }
Value VisitConditionalOperator(OperatorResolveResult result, BinaryOperatorType bitwiseOperatorType) Value VisitConditionalOperator(OperatorResolveResult result, BinaryOperatorType bitwiseOperatorType)
@ -357,7 +385,7 @@ namespace Debugger.AddIn
return val; return val;
if (result.Conversion.IsNullLiteralConversion) if (result.Conversion.IsNullLiteralConversion)
return val; return val;
throw new NotImplementedException(string.Format("conversion '{0}' not implemented!", result.Conversion)); throw new GetValueException("conversion '{0}' not implemented!", result.Conversion);
} }
Value Visit(LocalResolveResult result) Value Visit(LocalResolveResult result)
@ -455,12 +483,21 @@ namespace Debugger.AddIn
public class ResolveResultPrettyPrinter public class ResolveResultPrettyPrinter
{ {
public ResolveResultPrettyPrinter() ResolveResultPrettyPrinter()
{ {
}
public static string Print(ResolveResult result)
{
try {
return new ResolveResultPrettyPrinter().PrintInternal(result);
} catch (NotImplementedException ex) {
SD.Log.Warn(ex);
return "";
}
} }
public string Print(ResolveResult result) string PrintInternal(ResolveResult result)
{ {
if (result == null) if (result == null)
return ""; return "";
@ -486,7 +523,7 @@ namespace Debugger.AddIn
string Visit(MemberResolveResult result) string Visit(MemberResolveResult result)
{ {
string text = Print(result.TargetResult); string text = PrintInternal(result.TargetResult);
if (!string.IsNullOrWhiteSpace(text)) if (!string.IsNullOrWhiteSpace(text))
text += "."; text += ".";
return text + result.Member.Name; return text + result.Member.Name;
@ -553,7 +590,7 @@ namespace Debugger.AddIn
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.Append(Print(result.TargetResult)); sb.Append(PrintInternal(result.TargetResult));
sb.Append('.'); sb.Append('.');
sb.Append(result.Member.Name); sb.Append(result.Member.Name);

20
src/AddIns/Debugger/Debugger.AddIn/Pads/AutoCompleteTextBox.cs

@ -20,6 +20,7 @@ using System;
using System.Text; using System.Text;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Threading; using System.Windows.Threading;
@ -102,6 +103,7 @@ namespace Debugger.AddIn.Pads.Controls
this.editor.TextArea.TextEntered += editor_TextArea_TextEntered; this.editor.TextArea.TextEntered += editor_TextArea_TextEntered;
this.Content = this.editor.TextArea; this.Content = this.editor.TextArea;
this.messageView = new ToolTip { PlacementTarget = this, Placement = PlacementMode.Bottom, StaysOpen = true };
HorizontalContentAlignment = HorizontalAlignment.Stretch; HorizontalContentAlignment = HorizontalAlignment.Stretch;
VerticalContentAlignment = VerticalAlignment.Stretch; VerticalContentAlignment = VerticalAlignment.Stretch;
@ -119,9 +121,11 @@ namespace Debugger.AddIn.Pads.Controls
} }
} }
ToolTip messageView;
void editor_TextArea_TextEntered(object sender, TextCompositionEventArgs e) void editor_TextArea_TextEntered(object sender, TextCompositionEventArgs e)
{ {
if (e.Text != ".") return; if (e.Text == ".") {
DebuggerCompletionContext context = null; DebuggerCompletionContext context = null;
StackFrame frame = WindowsDebugger.CurrentStackFrame; StackFrame frame = WindowsDebugger.CurrentStackFrame;
if (frame == null) { if (frame == null) {
@ -135,6 +139,20 @@ namespace Debugger.AddIn.Pads.Controls
var binding = DebuggerDotCompletion.PrepareDotCompletion(editor.Text.Substring(0, editor.CaretOffset), context); var binding = DebuggerDotCompletion.PrepareDotCompletion(editor.Text.Substring(0, editor.CaretOffset), context);
if (binding == null) return; if (binding == null) return;
binding.HandleKeyPressed(editorAdapter, '.'); binding.HandleKeyPressed(editorAdapter, '.');
} else {
// TODO : implement automated error checking CSharpParser.ParseExpression does not report useful error messages.
// Error[] errors;
// if (!DebuggerDotCompletion.CheckSyntax(Text, out errors)) {
// StringBuilder output = new StringBuilder();
// foreach (var error in errors) {
// output.AppendLine(error.Message + " at " + error.Region.Begin);
// }
// messageView.Content = output.ToString();
// messageView.IsOpen = true;
// } else {
// messageView.IsOpen = false;
// }
}
} }
public void FocusEditor() public void FocusEditor()

5
src/AddIns/Debugger/Debugger.AddIn/Pads/DebuggerDotCompletion.cs

@ -33,11 +33,12 @@ namespace Debugger.AddIn.Pads.Controls
{ {
static class DebuggerDotCompletion static class DebuggerDotCompletion
{ {
public static bool CheckSyntax(string expression) public static bool CheckSyntax(string expression, out Error[] errors)
{ {
var p = new CSharpParser(); var p = new CSharpParser();
p.ParseExpression(expression); p.ParseExpression(expression);
return !p.Errors.Any(); errors = p.Errors.ToArray();
return !errors.Any();
} }
public static ICodeCompletionBinding PrepareDotCompletion(string expressionToComplete, DebuggerCompletionContext context) public static ICodeCompletionBinding PrepareDotCompletion(string expressionToComplete, DebuggerCompletionContext context)

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

@ -629,12 +629,7 @@ namespace ICSharpCode.SharpDevelop.Services
if (resolveResult == null) if (resolveResult == null)
return; return;
if (resolveResult is LocalResolveResult || resolveResult is MemberResolveResult) { if (resolveResult is LocalResolveResult || resolveResult is MemberResolveResult) {
string text = string.Empty; string text = ResolveResultPrettyPrinter.Print(resolveResult);
try {
text = new ResolveResultPrettyPrinter().Print(resolveResult);
} catch (NotImplementedException ex) {
SD.Log.Warn(ex);
}
Func<Value> getValue = delegate { Func<Value> getValue = delegate {
ExpressionEvaluationVisitor eval = new ExpressionEvaluationVisitor(CurrentStackFrame, EvalThread, CurrentStackFrame.AppDomain.Compilation); ExpressionEvaluationVisitor eval = new ExpressionEvaluationVisitor(CurrentStackFrame, EvalThread, CurrentStackFrame.AppDomain.Compilation);
return eval.Convert(resolveResult); return eval.Convert(resolveResult);

Loading…
Cancel
Save