| package org.eclipse.dltk.internal.debug.ui; |
| |
| import java.util.HashMap; |
| |
| import org.eclipse.core.runtime.IAdaptable; |
| import org.eclipse.core.runtime.IConfigurationElement; |
| import org.eclipse.debug.core.DebugEvent; |
| import org.eclipse.debug.core.DebugException; |
| import org.eclipse.debug.core.DebugPlugin; |
| import org.eclipse.debug.core.model.IValue; |
| import org.eclipse.debug.ui.DebugUITools; |
| import org.eclipse.debug.ui.IDebugUIConstants; |
| import org.eclipse.debug.ui.IValueDetailListener; |
| import org.eclipse.dltk.core.DLTKCore; |
| import org.eclipse.dltk.core.SimpleDLTKExtensionManager; |
| import org.eclipse.dltk.core.SimpleDLTKExtensionManager.ElementInfo; |
| import org.eclipse.dltk.debug.core.eval.IScriptEvaluationCommand; |
| import org.eclipse.dltk.debug.core.model.IScriptStackFrame; |
| import org.eclipse.dltk.debug.core.model.IScriptThread; |
| import org.eclipse.dltk.debug.core.model.IScriptValue; |
| import org.eclipse.dltk.debug.ui.DLTKDebugUILanguageManager; |
| import org.eclipse.dltk.debug.ui.DLTKDebugUIPlugin; |
| import org.eclipse.dltk.debug.ui.IDLTKDebugUIPreferenceConstants; |
| import org.eclipse.dltk.debug.ui.ScriptDebugModelPresentation; |
| import org.eclipse.jface.util.IPropertyChangeListener; |
| import org.eclipse.jface.util.PropertyChangeEvent; |
| |
| public class ScriptDetailFormattersManager implements IPropertyChangeListener { |
| private static final String DEFAULT_FORMATTER_TYPE = "#DEFAULT#"; //$NON-NLS-1$ |
| private static final String ATTR_SNIPPET = "snippet"; //$NON-NLS-1$ |
| private static final String ATTR_TYPE = "type"; //$NON-NLS-1$ |
| private static final String ATTR_NATURE = "nature"; //$NON-NLS-1$ |
| private static final String SCRIPT_DETAIL_FORMATTER_EXTENSION = DLTKDebugUIPlugin.PLUGIN_ID |
| + ".scriptDetailFormatter"; //$NON-NLS-1$ |
| |
| private static HashMap<String, ScriptDetailFormattersManager> managerInstances = new HashMap<>(); |
| private static final String CANNOT_EVALUATE = Messages.ScriptDetailFormattersManager_cantEvaluateDetails; |
| private HashMap<String, DetailFormatter> formatters = new HashMap<>(); |
| private DetailFormatter defaultFormatter = null; |
| |
| /** |
| * Return the default detail formatters manager. |
| * |
| * @param natureId |
| * |
| * @return default detail formatters manager. |
| */ |
| static public ScriptDetailFormattersManager getDefault(String natureId) { |
| ScriptDetailFormattersManager instance = managerInstances.get(natureId); |
| if (instance == null) { |
| instance = new ScriptDetailFormattersManager(natureId); |
| managerInstances.put(natureId, instance); |
| } |
| return instance; |
| } |
| |
| private ScriptDetailFormattersManager(String natureId) { |
| populateDetailFormatters(natureId); |
| |
| DLTKDebugUILanguageManager.getLanguageToolkit(natureId) |
| .getPreferenceStore().addPropertyChangeListener(this); |
| } |
| |
| private void populateDetailFormatters(String natureId) { |
| SimpleDLTKExtensionManager manager = new SimpleDLTKExtensionManager( |
| SCRIPT_DETAIL_FORMATTER_EXTENSION); |
| ElementInfo[] infos = manager.getElementInfos(); |
| for (int i = 0; i < infos.length; i++) { |
| IConfigurationElement config = infos[i].getConfig(); |
| String nature = config.getAttribute(ATTR_NATURE); |
| if (natureId.equals(nature)) { |
| String code = config.getAttribute(ATTR_SNIPPET); |
| String type = config.getAttribute(ATTR_TYPE); |
| DetailFormatter formatter = new DetailFormatter(type, code, |
| true); |
| if (DEFAULT_FORMATTER_TYPE.equals(type)) { |
| setDefaultFormatter(formatter); |
| } else { |
| addFormatter(formatter); |
| } |
| } |
| } |
| } |
| |
| private String getValueText(IValue value) { |
| if (value instanceof IScriptValue) { |
| ScriptDebugModelPresentation presentation = DLTKDebugUIPlugin |
| .getDefault() |
| .getModelPresentation(value.getModelIdentifier()); |
| return presentation.getDetailPaneText((IScriptValue) value); |
| } |
| return null; |
| } |
| |
| public void computeValueDetail(final IScriptValue value, |
| final IScriptThread thread, final IValueDetailListener listener) { |
| if (thread == null || !thread.isSuspended()) { |
| listener.detailComputed(value, getValueText(value)); |
| return; |
| } |
| final DetailFormatter formatter = getDetailFormatter(value); |
| if (formatter == null || !formatter.isEnabled()) { |
| /* |
| * if the client doesn't define a formatter, or the engine doesn't |
| * support the 'eval' command, fall back to using the value returned |
| * in the 'property' response |
| */ |
| listener.detailComputed(value, getValueText(value)); |
| return; |
| } |
| final IScriptEvaluationCommand command = value |
| .createEvaluationCommand(formatter.getSnippet(), thread); |
| if (command == null) { |
| listener.detailComputed(value, getValueText(value)); |
| return; |
| } |
| command.asyncEvaluate(result -> { |
| if (result == null) |
| return; |
| |
| IScriptValue resultValue = result.getValue(); |
| if (resultValue != null) { |
| listener.detailComputed(value, getValueText(resultValue)); |
| } else { |
| try { |
| listener.detailComputed(value, |
| value.getValueString()/* CANNOT_EVALUATE */); |
| } catch (DebugException e) { |
| if (DLTKCore.DEBUG) { |
| e.printStackTrace(); |
| } |
| listener.detailComputed(value, CANNOT_EVALUATE); |
| } |
| } |
| }); |
| } |
| |
| public DetailFormatter getDetailFormatter(IScriptValue value) { |
| DetailFormatter formatter = formatters.get(value.getType().getName()); |
| if (formatter == null) |
| formatter = getDefaultFormatter(); |
| return formatter; |
| } |
| |
| private DetailFormatter getDefaultFormatter() { |
| return defaultFormatter; |
| } |
| |
| public void setDefaultFormatter(DetailFormatter formatter) { |
| defaultFormatter = formatter; |
| } |
| |
| public void addFormatter(DetailFormatter formatter) { |
| formatters.put(formatter.getTypeName(), formatter); |
| } |
| |
| public void removeFormatter(DetailFormatter formatter) { |
| formatters.remove(formatter.getTypeName()); |
| } |
| |
| @Override |
| public void propertyChange(PropertyChangeEvent event) { |
| String property = event.getProperty(); |
| if (handlesPropertyEvent(property)) { |
| // TODO: uncomment when supported |
| // populateDetailFormatters(natureId); |
| // cacheMap.clear(); |
| |
| /* |
| * fire a change event on it so the variables view will update for |
| * any formatter changes. |
| */ |
| IAdaptable selected = DebugUITools.getDebugContext(); |
| if (selected != null) { |
| IScriptStackFrame frame = selected |
| .getAdapter(IScriptStackFrame.class); |
| if (frame != null) { |
| DebugPlugin.getDefault() |
| .fireDebugEventSet(new DebugEvent[] { |
| new DebugEvent(frame, DebugEvent.CHANGE) }); |
| } |
| } |
| } |
| } |
| |
| private boolean handlesPropertyEvent(String property) { |
| // TODO: uncomment when supported |
| // if |
| // (IDLTKDebugUIPreferenceConstants.PREF_DETAIL_FORMATTERS_LIST.equals |
| // (property)) { |
| // return true; |
| // } |
| |
| if (IDLTKDebugUIPreferenceConstants.PREF_SHOW_DETAILS |
| .equals(property)) { |
| return true; |
| } |
| |
| if (IDebugUIConstants.PREF_MAX_DETAIL_LENGTH.equals(property)) { |
| return true; |
| } |
| |
| return false; |
| } |
| |
| } |