diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/expression/AbstractExpressionVMNode.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/expression/AbstractExpressionVMNode.java index f9ae608f3e3..b6043870bbc 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/expression/AbstractExpressionVMNode.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/expression/AbstractExpressionVMNode.java @@ -22,6 +22,7 @@ import org.eclipse.dd.dsf.datamodel.IDMContext; import org.eclipse.dd.dsf.debug.internal.ui.DsfDebugUIPlugin; import org.eclipse.dd.dsf.service.DsfSession; import org.eclipse.dd.dsf.ui.concurrent.ViewerDataRequestMonitor; +import org.eclipse.dd.dsf.ui.viewmodel.IVMContext; import org.eclipse.dd.dsf.ui.viewmodel.VMChildrenUpdate; import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMNode; import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider; @@ -29,31 +30,45 @@ import org.eclipse.debug.core.model.IExpression; import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate; /** - * + * Base class for VM Nodes which can be used in the expressions view. + *

+ * This base class uses the methods {@link #canParseExpression(IExpression)} and + * {@link #update(IChildrenUpdate[])} to implement the + * {@link IExpressionVMNode#update(IExpressionUpdate)} + * method. Two additional abstract protected methods need to be implemented + * by the sub-class as well. + *

*/ @SuppressWarnings("restriction") public abstract class AbstractExpressionVMNode extends AbstractDMVMNode implements IExpressionVMNode { - public AbstractExpressionVMNode(AbstractDMVMProvider provider, DsfSession session, Class dmcClassType) { super(provider, session, dmcClassType); } public void update(final IExpressionUpdate update) { if (!canParseExpression(update.getExpression())) { - update.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Invalid expression", null)); //$NON-NLS-1$ + // This method should not be called if canParseExpression() returns false. + // Return an internal error status. + update.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Cannot parse expression", null)); //$NON-NLS-1$ update.done(); return; } + // Retrieve the list of all elements from the sub-class. Then compare + // each returned element to the expression in the update, using + // testElementForExpression(). The element that matches the expression + // is returned to the client. + // If no matching element is found, the createInvalidExpressionVMContext() + // method is called to a special context. update(new IChildrenUpdate[] { new VMChildrenUpdate( update, -1, -1, new ViewerDataRequestMonitor>(getExecutor(), update) { @Override protected void handleSuccess() { if (getData().size() == 0) { - update.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "No contexts", null)); //$NON-NLS-1$ + update.setExpressionElement(createInvalidExpressionVMContext(update.getExpression())); update.done(); } else { final List elements = getData(); @@ -73,7 +88,7 @@ public abstract class AbstractExpressionVMNode extends AbstractDMVMNode } } if (!foundMatchingContext) { - update.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Context not found", null)); //$NON-NLS-1$ + update.setExpressionElement(createInvalidExpressionVMContext(update.getExpression())); } } else { update.setStatus(getStatus()); @@ -107,13 +122,57 @@ public abstract class AbstractExpressionVMNode extends AbstractDMVMNode } + /** + * Tests whether the given element matches the given expression. + * + * @param element Element to test against the given expression. + * @param expression Expression to use to check if the element is matching. + * @param rm The request monitor for the result. + */ @ConfinedToDsfExecutor("#getSession#getExecutor") protected void testElementForExpression(Object element, IExpression expression, final DataRequestMonitor rm) { rm.setData(false); rm.done(); } + /** + * Sets the given expression as the expression belonging to the given + * element. + *

+ * This base class creates VM context elements using the extending class's + * {@link #update(IChildrenUpdate[])} method. The element matching the + * expression is found using {@link #testElementForExpression(Object, IExpression, DataRequestMonitor)}. + * Once the matching element is found it needs to be linked to the expression + * so that it can be distinguished from other contexts created for identical + * but distinct expressions. This method accomplishes this task. Elements + * which are associated with expressions should use the expression object + * for implementation of {@link #equals(Object)} and {@link #hashCode()} + * methods. + *

+ * + * @param element + * @param expression + */ protected void associateExpression(Object element, IExpression expression) { } - + + /** + * Create a place holder for an invalid expression. If for a given expression, + * this VM node returns true from {@link #canParseExpression(IExpression)}, which + * indicates that the expression matches the node's expected format, but the node + * then is not able to find the element represented by the expression, then an + * "invalid" expression context needs to be created. + *

+ * This method can be overriden to provide a node-specific invalid expression + * context. + *

+ * + * @param expression Expression to create the context for. + * @return Returns a VM context object representing an invalid expression with + * + * @since 1.1 + */ + protected IVMContext createInvalidExpressionVMContext(IExpression expression) { + return new InvalidExpressionVMContext(this, expression); + } } diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/expression/ExpressionManagerVMNode.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/expression/ExpressionManagerVMNode.java index 986e8cf4c8f..fae5b8353db 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/expression/ExpressionManagerVMNode.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/expression/ExpressionManagerVMNode.java @@ -34,8 +34,6 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdat import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta; import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; -import org.eclipse.debug.ui.DebugUITools; -import org.eclipse.debug.ui.IDebugUIConstants; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.viewers.CellEditor; import org.eclipse.jface.viewers.ICellModifier; @@ -61,46 +59,6 @@ import org.eclipse.swt.widgets.Composite; public class ExpressionManagerVMNode extends AbstractVMNode implements IElementLabelProvider, IElementEditor { - - /** - * VMC of an expression object that failed to get parsed by any of the - * configured expression layout nodes. It is only used to display an - * error message in the view, and to allow the user to edit the - * expression. - */ - static class InvalidExpressionVMContext extends AbstractVMContext { - final private IExpression fExpression; - - public InvalidExpressionVMContext(ExpressionManagerVMNode node, IExpression expression) { - super(node); - fExpression = expression; - } - - @Override - @SuppressWarnings("unchecked") - public Object getAdapter(Class adapter) { - if (adapter.isAssignableFrom(fExpression.getClass())) { - return fExpression; - } else { - return super.getAdapter(adapter); - } - } - - public IExpression getExpression() { - return fExpression; - } - - @Override - public boolean equals(Object obj) { - return obj instanceof InvalidExpressionVMContext && ((InvalidExpressionVMContext)obj).fExpression.equals(fExpression); - } - - @Override - public int hashCode() { - return fExpression.hashCode(); - } - } - /** * VMC for a new expression object to be added. When user clicks on this node to * edit it, he will create a new expression. @@ -237,9 +195,7 @@ public class ExpressionManagerVMNode extends AbstractVMNode // The expression layout nodes are responsible for supplying label providers // for their VMCs. for (ILabelUpdate update : updates) { - if (update.getElement() instanceof InvalidExpressionVMContext) { - updateInvalidExpressionVMCLabel(update, (InvalidExpressionVMContext) update.getElement()); - } else if (update.getElement() instanceof NewExpressionVMC) { + if (update.getElement() instanceof NewExpressionVMC) { updateNewExpressionVMCLabel(update, (NewExpressionVMC) update.getElement()); } else { update.done(); @@ -247,33 +203,6 @@ public class ExpressionManagerVMNode extends AbstractVMNode } } - /** - * Updates the label for the InvalidExpressionVMC. - */ - private void updateInvalidExpressionVMCLabel(ILabelUpdate update, InvalidExpressionVMContext vmc) { - String[] columnIds = update.getColumnIds() != null ? - update.getColumnIds() : new String[] { IDebugVMConstants.COLUMN_ID__NAME }; - - for (int i = 0; i < columnIds.length; i++) { - if (IDebugVMConstants.COLUMN_ID__EXPRESSION.equals(columnIds[i])) { - update.setLabel(vmc.getExpression().getExpressionText(), i); - update.setImageDescriptor(DebugUITools.getImageDescriptor( IDebugUIConstants.IMG_OBJS_EXPRESSION ), i); - } else if (IDebugVMConstants.COLUMN_ID__NAME.equals(columnIds[i])) { - update.setLabel(vmc.getExpression().getExpressionText(), i); - update.setImageDescriptor(DebugUITools.getImageDescriptor( IDebugUIConstants.IMG_OBJS_EXPRESSION ), i); - } else if (IDebugVMConstants.COLUMN_ID__VALUE.equals(columnIds[i])) { - update.setLabel(MessagesForExpressionVM.ExpressionManagerLayoutNode__invalidExpression_valueColumn_label, i); - } else { - update.setLabel("", i); //$NON-NLS-1$ - } - update.setFontData(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0], i); - } - - - update.done(); - } - - /** * Updates the label for the NewExpressionVMC. */ diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/expression/InvalidExpressionVMContext.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/expression/InvalidExpressionVMContext.java new file mode 100644 index 00000000000..519548bd9e1 --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/expression/InvalidExpressionVMContext.java @@ -0,0 +1,88 @@ +package org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.expression; + +import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.IDebugVMConstants; +import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMContext; +import org.eclipse.dd.dsf.ui.viewmodel.IVMNode; +import org.eclipse.debug.core.model.IExpression; +import org.eclipse.debug.internal.ui.IInternalDebugUIConstants; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider; +import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate; +import org.eclipse.debug.ui.DebugUITools; +import org.eclipse.debug.ui.IDebugUIConstants; +import org.eclipse.jface.resource.JFaceResources; + +/** + * VMC of an expression object that failed to get parsed by any of the + * configured expression layout nodes. It is only used to display an + * error message in the view, and to allow the user to edit the + * expression. + *

+ * Note: VM Nodes using this invalid expression VM context should + * provide a cell modifier to edit the expressions. The cell modifier + * should subclass {@link WatchExpressionCellModifier}. + *

+ * + * @since 1.1 + */ +@SuppressWarnings("restriction") +public class InvalidExpressionVMContext extends AbstractVMContext implements IElementLabelProvider { + + final private IExpression fExpression; + + public InvalidExpressionVMContext(IVMNode node, IExpression expression) { + super(node); + fExpression = expression; + } + + @Override + @SuppressWarnings("unchecked") + public Object getAdapter(Class adapter) { + if (adapter.isAssignableFrom(fExpression.getClass())) { + return fExpression; + } else { + return super.getAdapter(adapter); + } + } + + public IExpression getExpression() { + return fExpression; + } + + @Override + public boolean equals(Object obj) { + return obj instanceof InvalidExpressionVMContext && ((InvalidExpressionVMContext)obj).fExpression.equals(fExpression); + } + + @Override + public int hashCode() { + return fExpression.hashCode(); + } + + /** + * Updates the label for the InvalidExpressionVMC. + */ + public void update(ILabelUpdate[] updates) { + for (ILabelUpdate update : updates) { + String[] columnIds = update.getColumnIds() != null ? + update.getColumnIds() : new String[] { IDebugVMConstants.COLUMN_ID__NAME }; + + for (int i = 0; i < columnIds.length; i++) { + if (IDebugVMConstants.COLUMN_ID__EXPRESSION.equals(columnIds[i])) { + update.setLabel(getExpression().getExpressionText(), i); + update.setImageDescriptor(DebugUITools.getImageDescriptor( IDebugUIConstants.IMG_OBJS_EXPRESSION ), i); + } else if (IDebugVMConstants.COLUMN_ID__NAME.equals(columnIds[i])) { + update.setLabel(getExpression().getExpressionText(), i); + update.setImageDescriptor(DebugUITools.getImageDescriptor( IDebugUIConstants.IMG_OBJS_EXPRESSION ), i); + } else if (IDebugVMConstants.COLUMN_ID__VALUE.equals(columnIds[i])) { + update.setLabel(MessagesForExpressionVM.ExpressionManagerLayoutNode__invalidExpression_valueColumn_label, i); + } else { + update.setLabel("", i); //$NON-NLS-1$ + } + update.setFontData(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0], i); + } + + update.done(); + } + } + +} \ No newline at end of file