Skip to content
This repository was archived by the owner on Oct 4, 2021. It is now read-only.

Commit d5de970

Browse files
committed
[Debugger] Fixed tracking of current expressions in Watch Pad
This avoids scenarios where we clear the expressions list thereby losing all known expressions. Fixes https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1002638/
1 parent 452f8be commit d5de970

File tree

5 files changed

+125
-23
lines changed

5 files changed

+125
-23
lines changed

main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@
206206
<Compile Include="MonoDevelop.Debugger\ObjectValue\Mac\MacDebuggerObjectValueView.cs" />
207207
<Compile Include="MonoDevelop.Debugger\ObjectValue\Mac\MacDebuggerObjectTypeView.cs" />
208208
<Compile Include="MonoDevelop.Debugger\ObjectValue\Mac\MacDebuggerObjectPinView.cs" />
209+
<Compile Include="MonoDevelop.Debugger\ObjectValue\ExpressionEventArgs.cs" />
209210
</ItemGroup>
210211
<ItemGroup Condition="$(OS) != 'Windows_NT'">
211212
<Compile Include="MonoDevelop.Debugger.VSTextView\ExceptionCaught\ExceptionCaughtProvider.cs" />
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
//
2+
// ExpressionEventArgs.cs
3+
//
4+
// Author:
5+
// Jeffrey Stedfast <[email protected]>
6+
//
7+
// Copyright (c) 2019 Microsoft Corp.
8+
//
9+
// Permission is hereby granted, free of charge, to any person obtaining a copy
10+
// of this software and associated documentation files (the "Software"), to deal
11+
// in the Software without restriction, including without limitation the rights
12+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
// copies of the Software, and to permit persons to whom the Software is
14+
// furnished to do so, subject to the following conditions:
15+
//
16+
// The above copyright notice and this permission notice shall be included in
17+
// all copies or substantial portions of the Software.
18+
//
19+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
// THE SOFTWARE.
26+
27+
using System;
28+
29+
namespace MonoDevelop.Debugger
30+
{
31+
public class ExpressionEventArgs : EventArgs
32+
{
33+
public ExpressionEventArgs (string expression)
34+
{
35+
Expression = expression;
36+
}
37+
38+
public string Expression {
39+
get; private set;
40+
}
41+
}
42+
43+
public class ExpressionChangedEventArgs : EventArgs
44+
{
45+
public ExpressionChangedEventArgs (string oldExpression, string newExpression)
46+
{
47+
OldExpression = oldExpression;
48+
NewExpression = newExpression;
49+
}
50+
51+
public string OldExpression {
52+
get; private set;
53+
}
54+
55+
public string NewExpression {
56+
get; private set;
57+
}
58+
}
59+
}

main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValue/Mac/MacObjectValueTreeView.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -818,7 +818,7 @@ bool CanDelete (out bool enabled)
818818

819819
var selectedRows = SelectedRows;
820820
foreach (var row in selectedRows) {
821-
var item = (MacObjectValueNode)ItemAtRow ((nint)row);
821+
var item = (MacObjectValueNode) ItemAtRow ((nint) row);
822822

823823
if (!(item.Target.Parent is RootObjectValueNode)) {
824824
enabled = false;

main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValue/ObjectValueTreeViewController.cs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,9 @@ void RemoveValue (ObjectValueNode node)
300300
{
301301
UnregisterNode (node);
302302
OnEvaluationCompleted (node, new ObjectValueNode[0]);
303+
304+
if (AllowWatchExpressions && node.Parent is RootObjectValueNode)
305+
ExpressionRemoved?.Invoke (this, new ExpressionEventArgs (node.Name));
303306
}
304307

305308
// TODO: can we improve this
@@ -371,6 +374,10 @@ public bool GetNodeWasExpandedAtLastCheckpoint (ObjectValueNode node)
371374

372375
#region Expressions
373376

377+
public event EventHandler<ExpressionEventArgs> ExpressionAdded;
378+
public event EventHandler<ExpressionChangedEventArgs> ExpressionChanged;
379+
public event EventHandler<ExpressionEventArgs> ExpressionRemoved;
380+
374381
public void AddExpression (string expression)
375382
{
376383
if (!AllowWatchExpressions) {
@@ -381,6 +388,8 @@ public void AddExpression (string expression)
381388
LoggingService.LogInfo ("Evaluating expression '{0}'", expression);
382389
var node = Frame.EvaluateExpression (expression);
383390
AddValue (node);
391+
392+
ExpressionAdded?.Invoke (this, new ExpressionEventArgs (expression));
384393
}
385394

386395
public void AddExpressions (IList<string> expressions)
@@ -391,24 +400,34 @@ public void AddExpressions (IList<string> expressions)
391400
if (Frame != null) {
392401
var nodes = Frame.EvaluateExpressions (expressions);
393402
AddValues (nodes);
403+
404+
var expressionAdded = ExpressionAdded;
405+
if (expressionAdded != null) {
406+
foreach (var expression in expressions)
407+
expressionAdded (this, new ExpressionEventArgs (expression));
408+
}
394409
}
395410
}
396411

397412
bool EditExpression (ObjectValueNode node, string newExpression)
398413
{
399-
if (node.Name == newExpression)
414+
var oldExpression = node.Name;
415+
416+
if (oldExpression == newExpression)
400417
return false;
401418

402419
UnregisterNode (node);
403420
if (string.IsNullOrEmpty (newExpression)) {
404421
// we want the expression removed from the tree
405422
OnEvaluationCompleted (node, new ObjectValueNode[0]);
423+
ExpressionRemoved?.Invoke (this, new ExpressionEventArgs (oldExpression));
406424
return true;
407425
}
408426

409427
var expressionNode = Frame.EvaluateExpression (newExpression);
410428
RegisterNode (expressionNode);
411429
OnEvaluationCompleted (node, new ObjectValueNode[] { expressionNode });
430+
ExpressionChanged?.Invoke (this, new ExpressionChangedEventArgs (oldExpression, newExpression));
412431

413432
return true;
414433
}

main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/WatchPad.cs

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,11 @@ public class WatchPad : ObjectValuePad, IMementoCapable, ICustomXmlSerializer
4545

4646
public WatchPad () : base (true)
4747
{
48-
if (!UseNewTreeView) {
48+
if (UseNewTreeView) {
49+
controller.ExpressionAdded += OnExpressionAdded;
50+
controller.ExpressionChanged += OnExpressionChanged;
51+
controller.ExpressionRemoved += OnExpressionRemoved;
52+
} else {
4953
tree.EnableModelDragDest (DropTargets, Gdk.DragAction.Copy);
5054
tree.DragDataReceived += HandleDragDataReceived;
5155
}
@@ -80,19 +84,19 @@ public void AddWatch (string expression)
8084
}
8185
}
8286

83-
void SaveExpressions ()
84-
{
85-
expressions.Clear ();
86-
expressions.AddRange (controller.GetExpressions ());
87-
}
88-
8987
void RestoreExpressions ()
9088
{
91-
// remove the expressions because we're going to rebuild them
92-
controller.ClearAll ();
89+
controller.ExpressionAdded -= OnExpressionAdded;
90+
91+
try {
92+
// remove the expressions because we're going to rebuild them
93+
controller.ClearAll ();
9394

94-
// re-add the expressions which will reevaluate the expressions and repopulate the treeview
95-
controller.AddExpressions (expressions);
95+
// re-add the expressions which will reevaluate the expressions and repopulate the treeview
96+
controller.AddExpressions (expressions);
97+
} finally {
98+
controller.ExpressionAdded += OnExpressionAdded;
99+
}
96100
}
97101

98102
public override void OnUpdateFrame ()
@@ -114,24 +118,43 @@ public override void OnUpdateValues ()
114118
}
115119
}
116120

117-
protected override void OnDebuggerResumed (object s, EventArgs a)
121+
void OnExpressionAdded (object sender, ExpressionEventArgs e)
118122
{
119-
// base will clear the controller, which removes all values and expressions
123+
LoggingService.LogInfo ("Expression added: {0}", e.Expression);
124+
expressions.Add (e.Expression);
125+
}
120126

121-
if (UseNewTreeView && !IsInitialResume)
122-
SaveExpressions ();
127+
void OnExpressionChanged (object sender, ExpressionChangedEventArgs e)
128+
{
129+
LoggingService.LogInfo ("Expression changed: '{0}' -> '{1}'", e.OldExpression, e.NewExpression);
130+
int index = expressions.IndexOf (e.OldExpression);
123131

124-
base.OnDebuggerResumed (s, a);
132+
if (index != -1) {
133+
expressions[index] = e.NewExpression;
134+
} else {
135+
LoggingService.LogWarning ("Failed to find old expression: {0}", e.OldExpression);
136+
expressions.Add (e.NewExpression);
137+
}
125138
}
126139

127-
protected override void OnDebuggerStopped (object s, EventArgs a)
140+
void OnExpressionRemoved (object sender, ExpressionEventArgs e)
128141
{
129-
// base will clear the controller, which removes all values and expressions
142+
LoggingService.LogInfo ("Expression removed: {0}", e.Expression);
143+
if (!expressions.Remove (e.Expression))
144+
LoggingService.LogWarning ("Failed to remove expression: {0}", e.Expression);
145+
}
130146

131-
if (UseNewTreeView)
132-
SaveExpressions ();
147+
public override void Dispose ()
148+
{
149+
if (UseNewTreeView) {
150+
controller.ExpressionAdded -= OnExpressionAdded;
151+
controller.ExpressionChanged -= OnExpressionChanged;
152+
controller.ExpressionRemoved -= OnExpressionRemoved;
153+
} else {
154+
tree.DragDataReceived -= HandleDragDataReceived;
155+
}
133156

134-
base.OnDebuggerStopped (s, a);
157+
base.Dispose ();
135158
}
136159

137160
#region IMementoCapable implementation

0 commit comments

Comments
 (0)