Skip to content

Commit bdf2e82

Browse files
committed
IObjectValueSource.SetValue now throws ValueModificationException if modification is failed instead of supressing the exception. This allows to show the error info to user at the call site (e.g. in message box).
ValueReference.SetValue() and ArrayElementGroup.SetValue() implementations unified and moved to ValueModificationUtil. (cherry picked from commit 316b7cc)
1 parent 29b6a90 commit bdf2e82

File tree

6 files changed

+231
-192
lines changed

6 files changed

+231
-192
lines changed

Mono.Debugging/Mono.Debugging.Backend/IObjectValueSource.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,19 @@
2828

2929
using System;
3030
using Mono.Debugging.Client;
31+
using Mono.Debugging.Evaluation;
3132

3233
namespace Mono.Debugging.Backend
3334
{
3435
public interface IObjectValueSource: IDebuggerBackendObject
3536
{
3637
ObjectValue[] GetChildren (ObjectPath path, int index, int count, EvaluationOptions options);
38+
39+
/// <summary>
40+
/// Updates the value with the result of evaluation of <paramref name="value"/> expression
41+
/// </summary>
42+
/// <exception cref="ValueModificationException" /> call site should catch this exception and show it to user in pretty way (e.g. in message box)
43+
/// All other exceptions indicate error and should be logged
3744
EvaluationResult SetValue (ObjectPath path, string value, EvaluationOptions options);
3845
ObjectValue GetValue (ObjectPath path, EvaluationOptions options);
3946

Mono.Debugging/Mono.Debugging.Evaluation/ArrayElementGroup.cs

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -277,37 +277,18 @@ public static string GetArrayDescription (int[] bounds)
277277

278278
return sb.ToString ();
279279
}
280-
281-
public EvaluationResult SetValue (ObjectPath path, string value, EvaluationOptions options)
280+
281+
EvaluationResult IObjectValueSource.SetValue (ObjectPath path, string value, EvaluationOptions options)
282282
{
283283
if (path.Length != 2)
284-
throw new NotSupportedException ();
284+
throw new InvalidOperationException (string.Format ("ObjectPath for array element is invalid: {0}", path));
285285

286286
int[] idx = StringToIndices (path [1]);
287-
288-
object val;
289-
try {
290-
EvaluationContext cctx = ctx.Clone ();
291-
EvaluationOptions ops = options ?? cctx.Options;
292-
ops.AllowMethodEvaluation = true;
293-
ops.AllowTargetInvoke = true;
294-
cctx.Options = ops;
295-
ValueReference var = ctx.Evaluator.Evaluate (ctx, value, array.ElementType);
296-
val = var.Value;
297-
val = ctx.Adapter.Convert (ctx, val, array.ElementType);
298-
array.SetElement (idx, val);
299-
} catch {
300-
val = array.GetElement (idx);
301-
}
302-
try {
303-
return ctx.Evaluator.TargetObjectToExpression (ctx, val);
304-
} catch (Exception ex) {
305-
ctx.WriteDebuggerError (ex);
306-
return new EvaluationResult ("? (" + ex.Message + ")");
307-
}
287+
var cctx = ctx.WithOptions (options);
288+
return ValueModificationUtil.ModifyValue (cctx, value, array.ElementType, newVal => array.SetElement (idx, newVal));
308289
}
309-
310-
public ObjectValue GetValue (ObjectPath path, EvaluationOptions options)
290+
291+
ObjectValue IObjectValueSource.GetValue (ObjectPath path, EvaluationOptions options)
311292
{
312293
if (path.Length != 2)
313294
throw new NotSupportedException ();
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System;
2+
3+
namespace Mono.Debugging.Evaluation
4+
{
5+
public class ValueModificationException : Exception
6+
{
7+
public ValueModificationException ()
8+
{
9+
}
10+
11+
public ValueModificationException (string message) : base (message)
12+
{
13+
}
14+
15+
public ValueModificationException (string message, Exception innerException) : base (message, innerException)
16+
{
17+
}
18+
}
19+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using System;
2+
using Mono.Debugging.Backend;
3+
4+
namespace Mono.Debugging.Evaluation
5+
{
6+
public static class ValueModificationUtil
7+
{
8+
internal static ValueReference EvaluateRightHandValue (EvaluationContext context, string value, object expectedType)
9+
{
10+
context.Options.AllowMethodEvaluation = true;
11+
context.Options.AllowTargetInvoke = true;
12+
try {
13+
return context.Evaluator.Evaluate (context, value, expectedType);
14+
} catch (Exception e) {
15+
throw new ValueModificationException(string.Format ("Cannot evaluate '{0}': {1}", value, e.Message), e);
16+
}
17+
}
18+
19+
internal static object ConvertRightHandValue (EvaluationContext context, object value, object expectedType)
20+
{
21+
try {
22+
return context.Adapter.Convert (context, value, expectedType);
23+
} catch (Exception e) {
24+
throw new ValueModificationException(string.Format ("Conversion error: {0}", e.Message), e);
25+
}
26+
}
27+
28+
internal static EvaluationResult ModifyValue (EvaluationContext context, string value, object expectedType, Action<object> valueSetter)
29+
{
30+
var rightHandValue = EvaluateRightHandValue (context, value, expectedType);
31+
32+
object val;
33+
try {
34+
val = rightHandValue.Value;
35+
} catch (Exception e) {
36+
throw new ValueModificationException(string.Format ("Cannot get real object of {0}", value), e);
37+
}
38+
var convertedValue = ConvertRightHandValue (context, val, expectedType);
39+
try {
40+
valueSetter (convertedValue);
41+
} catch (Exception e) {
42+
throw new ValueModificationException(string.Format ("Error while assigning new value to object: {0}", e.Message), e);
43+
}
44+
// don't wrap with try-catch it, this call normally should not throw exceptions produced by wrong user input.
45+
// If exception was occured this means something has gone wrong in we have to report it in log
46+
return context.Evaluator.TargetObjectToExpression (context, convertedValue);
47+
}
48+
49+
}
50+
}

Mono.Debugging/Mono.Debugging.Evaluation/ValueReference.cs

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -148,29 +148,9 @@ ObjectValue IObjectValueSource.GetValue (ObjectPath path, EvaluationOptions opti
148148

149149
EvaluationResult IObjectValueSource.SetValue (ObjectPath path, string value, EvaluationOptions options)
150150
{
151-
try {
152-
Context.WaitRuntimeInvokes ();
153-
154-
var ctx = GetContext (options);
155-
ctx.Options.AllowMethodEvaluation = true;
156-
ctx.Options.AllowTargetInvoke = true;
157-
158-
var vref = ctx.Evaluator.Evaluate (ctx, value, Type);
159-
var newValue = ctx.Adapter.Convert (ctx, vref.Value, Type);
160-
SetValue (ctx, newValue);
161-
} catch (Exception ex) {
162-
Context.WriteDebuggerError (ex);
163-
Context.WriteDebuggerOutput ("Value assignment failed: {0}: {1}\n", ex.GetType (), ex.Message);
164-
}
165-
166-
try {
167-
return Context.Evaluator.TargetObjectToExpression (Context, Value);
168-
} catch (Exception ex) {
169-
Context.WriteDebuggerError (ex);
170-
Context.WriteDebuggerOutput ("Value assignment failed: {0}: {1}\n", ex.GetType (), ex.Message);
171-
}
172-
173-
return null;
151+
Context.WaitRuntimeInvokes ();
152+
var ctx = GetContext (options);
153+
return ValueModificationUtil.ModifyValue (ctx, value, Type, newVal => SetValue (ctx, newVal));
174154
}
175155

176156
object IObjectValueSource.GetRawValue (ObjectPath path, EvaluationOptions options)

0 commit comments

Comments
 (0)