Spec describing Working Sets for Expressions
The existing Expressions view shows all expressions present in the workspace as a simple list. Sometimes the user has multiple projects in his workspace, and has created expressions for all of them. While debugging a single project, it is inconvenient to see all those expressions in the view which are not relevant for this project. The view tries to evaluate all expressions, and most of them fail with an error message.
Working sets give us an elegant way to group relevant expressions together, and show only those expressions which are applicable for the project being debugged currently.
The user can define working sets and assign expressions to each working set. He/she can assign the same expression to multiple working sets. Each expression view will use some or all of the working sets.
This spec is part of Bug 372181 https://bugs.eclipse.org/bugs/show_bug.cgi?id=372181
This spec has evolved through the discussion in the above bug.
Working sets for expressions will be implemented using the standard eclipse working set UI. The Expression View will have two menuitems:
- Select Working Sets
- Deselect Working Sets
User can define a working set and assign expressions to it. A default working set "Others (no working set)" will always be present. This will be used to display all expressions which are not specifically assigned to any working set. It is not allowed to delete this default working set.
Multiple Working Sets
IMO the biggest design decision is whether multiple working sets can be active at any one time, or only one. I've been arguing for allowing multiple so far since that's how other parts of Eclipse work, but reading through things again there's benefit in the simplicity of allowing only one. I'm not yet fully decided on this one.
The user can apply multiple working sets to an Expression view. Any expressions which are not a part of the working sets applied on the view will be filtered out. A viewer filter will be defined and applied to the Expression view. This filter will be added when cdt starts, similar to how pin and clone is started (see class ViewIDCounterManager).
We dont think the user needs to know what workingsets an expression is in. Project Explorer and Package Explorer also don't show that information. IMO the extra column would cause more trouble than value.
Any expression which has not been assigned to a working set, will be included in the default working set "Others (no working set)". All such unassigned expressions will always be displayed in the view.
Add new expression
New expressions can be added thru the following ways:
- Click the node "Add new expression" in the view, and type an expression inline.
- Click the view toolbar button "Create a new watch expression" and type an expression in the popup dialog.
- Drag a variable from the Variables View
- Drag a register from the Registers View
- Drag selected text from the C Editor
- Select text in the C Editor, right click -> Add new expression... and click OK in the popup dialog after reviewing the expression.
If the Expression view has no working sets selected, the new expression will be added to eclipse expression manager and will simply become visible in the view. This is the default behavior of platform.
If the view has a single working set applied, the new expression will be added to eclipse expression manager, as well as it will be added to the selected working set.
If the Expression view has multiple working sets selected, a new expression can be handled in the following manner:
- Add the new expression to all the selected working sets.
- Open a popup dialog with a textbox where the user can edit the expression, and a checkbox list of all selected working sets, with the first working set pre-checked. The user can then click OK and the new expression will be added to eclipse expression manager as well as the checked working sets.
- Create a dialog similar to the "Select default working set" dialog for breakpoints. If the view has multiple working sets, and no default working set, the first time a new expression is added, this dialog will open, prompting the user to select a default working set. The new expression will be added to this working set. Further new expressions will be added to this working set.
- Maintain a built in working set "Others (no working set)", which is not deletable. All expressions not assigned to any working set, will belong to this Others working set, and will be always visible in the Expression view. A new expression will always be added to Others working set, and from here can be assigned to any working set.
[Update, from comments 24 and 25]
All the current UI flows for adding a new expression to the Expression view will remain as they are. A new expression will always be assigned to the default working set "Others (no working set)". Since all expressions in the working set "Others" are always visible in the view, the new expression will also appear in the view.
When the user wants (later), he can select the new expression and right-click -> Assign to working set. If he assigns to a working set which is selected for the view, the new expression will remain visible. If he assigns to a working set which is not selected for this view, the new expression will disappear.
The platform currently allows duplicate expressions to be created. Is this a bug or a feature? If it is a bug, we need to add a patch to eclipse debug to prevent the user from adding duplicate expressions. Duplicate expressions do not impact performance, they just confuse the user.
[Update from comment 17]
For now, we have decided to keep the duplicates around, and let the user delete them himself when needed.
- When no working sets are applied to the view, show duplicate expressions as the user has entered them.
- When one or more working sets are selected in the view, filter out duplicate expressions. This is easier, because if an expression is present in two or more working sets, we have no way of knowing whether it is the same expression added to multiple working sets, or separate expressions added individually to each working set.
Assign an expression to a working set
The user can select an expression in the view, "Right-click > Assign Working Sets..." like JDT does in the Package Explorer. This workflow is a lot better than making assignments in a separate Workingset UI only.
Working Set subtrees
The Expression view can also implement the feature "Show Workingsets as Toplevel Elements" as in the Project Explorer. However, to implement this feature, we need to add a patch to the eclipse debug platform.
Import / Export of working sets
This is a mini feature which will also be supported via the addition of two menuitems on the Expression view menu. Import expressions Export expressions
For pinning a working set to an active debug context, user can select an expression and "right click -> Pin to <active debug context>". This menuitem will have two submenus, "Pin select expression", "Pin <working set name>". In this case, view will remain unpinned, but it will display only the following expressions:
- Expressions / working sets pinned to the <active debug context>, i.e. the
selection in the debug view
- Unpinned expressions
The view should have a toggle toobar button or menuitem which toggles the view between two states:
- Show expressions / working sets pinned to <active debug contex>
- Show all expressions / working sets.
When the user pins an expression to the <active debug context>, the view will automatically toggle its state to show only pinned expressions. If the user has selected an expression from "Others (no working set)", the right click -> "Pin to active debug context" menuitem will not have any submenus, i.e. "Others (no working set)" itself cannot be pinned.
An expression can be pinned to multiple <active debug contexts>, so if an expression is not visible in the view, because it is pinned to some other debug context, user can open a checkbox dialog where all expressions are displayed, with info about the debug context(s) they are currently pinned to. This dialog box will display the active debug context in the title area. Expressions already pinned to the active debug context will be pre-checked. The user can check any existing expressions, and click ok to pin them to the active debug context.
This pinning is independent of the feature "pin and clone", and both features can be used simultaneously.
Having pinned an expression, a good workflow is needed to add more predefined (but currently invisible) expressions to the pinned context.
An interesting approach would be using content assist for that: Click into an empty row, Ctrl+Space shows all predefined-but-invisible expressions; as I start typing, this is filtered down; pressing enter the predefined expression gets added to the pinned context. This would in fact work very much like a history of predefined expressions, and could also include expressions that were entered before but deleted later. The content assist popup could show multiple categories for that: Consider how the "Quick Access" box in the top right in Eclipse 4.2 works.
In addition to that, an "Add Expressions From..." UI would make sense, allowing to bring in multiple previously-defined expressions from other workingsets or external file(s) in a single step. Such an "Add From..." UI could benefit from incremental filtering (eg show me all that use variable "Foo" then select all those).
Also note that the filtered set of expressions-pinned-to-context creates another implicit workingset. So "convert pinned to workingset" would be an interesting gesture, just giving the currently-pinned a name.
The more I think about it, the more I like this "pin to context" idea. I could see a number of expressions which are only locally valid to not be assigned any workingset but only be shown inside pinned context; and others, which access global/static variables to be defined in named workingsets which are added to the pinned context.
Pinning: Link Mode
The pinning workflow could easily get confusing for users. Since there is already a pin concept for expressions view, adding another pinning concept to the view may be difficult for users to understand.
One altternative would be to add a concept of linked mode to the working sets. When in link mode:
- If user changes active debug context, the working sets would be automatically activated/de-activated
- If user selects/de-selects working sets, the view will record the selected working sets for the active context.
- If a user selects a working set for a parent context (e.g. thread), that working set will also be selected for its child contexts (e.g. stack frames).
[Update from comment 26]
There already exists a toolbar button "Pin to debug context" in the view. We can enhance this button to add a dropdown menu to it. The dropdown menu will have two menuitems:
- Pin view to debug context
- Pin working sets to debug context
Both menuitems will be "toggle menu items"
The second menuitem will be enabled only if the user has selected working sets for this view. Clicking this menuitem will associate the selected working sets with the active debug context, and also persist this association.
Now if the user selects a different debug context in the debug view, the view will realise that its pin state "pin working sets to debug context" has been toggled on. It will search its persistent state for a list of working sets associated with this debug context. If such a list is found, it will restore those working sets. If such a list is not found, the view has two options:
- Continue showing the previously selected working sets. This has the side effect that since the pin state "Pin working sets to debug context" is toggled on, the previously selected working sets will now be associated with this debug context also.
- Realise that no working sets are selected for this debug context, so deselect all working sets for the view, and show all expressions.
I prefer option 1.
The method serializing the active context will be to use the IElementMementoProvider. For an active context all elements in path of the active context (tree path in debug view) can be used to search selected working sets, this can be done in parallel and hence be fairly efficient.
Pinning and Mylyn