| /******************************************************************************* |
| * Copyright (c) 2000, 2015 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * QNX Software Systems - Mikhail Khodjaiants - Registers View (Bug 53640) |
| * Valentin Ciocoi - Bug 414994 Guard against out of bounds exception when handling escaped characters in DefaultLabelProvider |
| *******************************************************************************/ |
| package org.eclipse.debug.internal.ui; |
| |
| |
| import java.text.MessageFormat; |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| import org.eclipse.core.resources.IMarker; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IAdaptable; |
| import org.eclipse.debug.core.DebugException; |
| import org.eclipse.debug.core.DebugPlugin; |
| import org.eclipse.debug.core.ILaunch; |
| import org.eclipse.debug.core.ILaunchConfiguration; |
| import org.eclipse.debug.core.ILaunchConfigurationType; |
| import org.eclipse.debug.core.ILaunchDelegate; |
| import org.eclipse.debug.core.ILaunchManager; |
| import org.eclipse.debug.core.model.IBreakpoint; |
| import org.eclipse.debug.core.model.IDebugElement; |
| import org.eclipse.debug.core.model.IDebugTarget; |
| import org.eclipse.debug.core.model.IDisconnect; |
| import org.eclipse.debug.core.model.IExpression; |
| import org.eclipse.debug.core.model.ILineBreakpoint; |
| import org.eclipse.debug.core.model.IProcess; |
| import org.eclipse.debug.core.model.IRegister; |
| import org.eclipse.debug.core.model.IRegisterGroup; |
| import org.eclipse.debug.core.model.IStackFrame; |
| import org.eclipse.debug.core.model.ITerminate; |
| import org.eclipse.debug.core.model.IThread; |
| import org.eclipse.debug.core.model.IValue; |
| import org.eclipse.debug.core.model.IVariable; |
| import org.eclipse.debug.core.model.IWatchExpression; |
| import org.eclipse.debug.core.model.IWatchpoint; |
| import org.eclipse.debug.internal.core.IInternalDebugCoreConstants; |
| import org.eclipse.debug.internal.ui.launchConfigurations.LaunchShortcutExtension; |
| import org.eclipse.debug.internal.ui.views.variables.IndexedVariablePartition; |
| import org.eclipse.debug.ui.IDebugUIConstants; |
| import org.eclipse.jface.resource.ImageDescriptor; |
| import org.eclipse.jface.viewers.IBaseLabelProvider; |
| import org.eclipse.jface.viewers.ILabelProvider; |
| import org.eclipse.jface.viewers.ILabelProviderListener; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.ui.model.IWorkbenchAdapter; |
| |
| public class DefaultLabelProvider implements ILabelProvider { |
| |
| /** |
| * Maps image descriptors to images. |
| */ |
| private Map<ImageDescriptor, Image> fImages = new HashMap<>(); |
| |
| /** |
| * @see ILabelProvider#getImage(Object) |
| */ |
| @Override |
| public Image getImage(Object element) { |
| String key= getImageKey(element); |
| if (key == null && element instanceof ILaunch) { |
| return null; |
| } |
| if (key == null && element instanceof IAdaptable) { |
| IWorkbenchAdapter de= ((IAdaptable) element).getAdapter(IWorkbenchAdapter.class); |
| if (de != null) { |
| ImageDescriptor descriptor= de.getImageDescriptor(element); |
| if( descriptor != null) { |
| return getImage(descriptor); |
| } |
| } |
| return null; |
| } |
| if(element instanceof LaunchShortcutExtension) { |
| return getImage(((LaunchShortcutExtension)element).getImageDescriptor()); |
| } |
| return DebugPluginImages.getImage(key); |
| } |
| |
| /** |
| * Returns an image created from the given image descriptor or <code>null</code>. |
| * Caches and reuses images. |
| * |
| * @param descriptor image descriptor |
| * @return image or <code>null</code> |
| */ |
| private Image getImage(ImageDescriptor descriptor) { |
| Image image = fImages.get(descriptor); |
| if (image != null) { |
| return image; |
| } |
| image = descriptor.createImage(); |
| if (image != null) { |
| fImages.put(descriptor, image); |
| } |
| return image; |
| } |
| |
| /** |
| * Returns the key (<code>String</code>) of the default image |
| * appropriate for the given element or <code>null</code> |
| * if no default image is defined. |
| */ |
| public String getImageKey(Object element) { |
| if (element instanceof IDebugElement) { |
| // Group elements into debug elements and non-debug elements |
| // to reduce the number of instanceof checks performed |
| if (element instanceof IRegister) { |
| return IDebugUIConstants.IMG_OBJS_REGISTER; |
| } else if (element instanceof IRegisterGroup) { |
| return IDebugUIConstants.IMG_OBJS_REGISTER_GROUP; |
| } else if (element instanceof IVariable || element instanceof IValue) { |
| if (element instanceof IndexedVariablePartition) { |
| return IInternalDebugUIConstants.IMG_OBJS_ARRAY_PARTITION; |
| } |
| return IDebugUIConstants.IMG_OBJS_VARIABLE; |
| } else if (element instanceof IStackFrame) { |
| if (((IStackFrame)element).getThread().isSuspended()) { |
| return IDebugUIConstants.IMG_OBJS_STACKFRAME; |
| } |
| return IDebugUIConstants.IMG_OBJS_STACKFRAME_RUNNING; |
| } else if (element instanceof IThread) { |
| IThread thread = (IThread)element; |
| if (thread.isSuspended()) { |
| return IDebugUIConstants.IMG_OBJS_THREAD_SUSPENDED; |
| } else if (thread.isTerminated()) { |
| return IDebugUIConstants.IMG_OBJS_THREAD_TERMINATED; |
| } else { |
| return IDebugUIConstants.IMG_OBJS_THREAD_RUNNING; |
| } |
| } else if (element instanceof IDebugTarget) { |
| IDebugTarget target= (IDebugTarget) element; |
| if (target.isTerminated() || target.isDisconnected()) { |
| return IDebugUIConstants.IMG_OBJS_DEBUG_TARGET_TERMINATED; |
| } else if (target.isSuspended()) { |
| return IDebugUIConstants.IMG_OBJS_DEBUG_TARGET_SUSPENDED; |
| } else { |
| return IDebugUIConstants.IMG_OBJS_DEBUG_TARGET; |
| } |
| } else if (element instanceof IExpression) { |
| return IDebugUIConstants.IMG_OBJS_EXPRESSION; |
| } |
| } else { |
| if (element instanceof IMarker) { |
| return getMarkerImageKey((IMarker)element); |
| } else if (element instanceof IBreakpoint) { |
| return getBreakpointImageKey((IBreakpoint)element); |
| } else if (element instanceof IProcess) { |
| if (((IProcess) element).isTerminated()) { |
| return IDebugUIConstants.IMG_OBJS_OS_PROCESS_TERMINATED; |
| } |
| return IDebugUIConstants.IMG_OBJS_OS_PROCESS; |
| } else if (element instanceof ILaunch) { |
| // determine the image from the launch config type |
| ILaunch launch= (ILaunch)element; |
| ILaunchConfiguration configuration = launch.getLaunchConfiguration(); |
| if (configuration != null) { |
| try { |
| return configuration.getType().getIdentifier(); |
| } catch (CoreException e) { |
| DebugUIPlugin.log(e); |
| return null; |
| } |
| } |
| // if no config, use the old "mode" way |
| if (launch.getLaunchMode().equals(ILaunchManager.DEBUG_MODE)) { |
| return IDebugUIConstants.IMG_OBJS_LAUNCH_DEBUG; |
| } else if (launch.isTerminated()) { |
| return IDebugUIConstants.IMG_OBJS_LAUNCH_RUN_TERMINATED; |
| } else { |
| return IDebugUIConstants.IMG_OBJS_LAUNCH_RUN; |
| } |
| } else if (element instanceof ILaunchConfigurationType) { |
| return ((ILaunchConfigurationType)element).getIdentifier(); |
| } else if (element instanceof ILaunchConfiguration) { |
| try { |
| return ((ILaunchConfiguration)element).getType().getIdentifier(); |
| } catch (CoreException e) { |
| DebugUIPlugin.log(e); |
| return null; |
| } |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * @see ILabelProvider#getText(Object) |
| */ |
| @Override |
| public String getText(Object element) { |
| StringBuilder label= new StringBuilder(); |
| try { |
| // Group elements into debug elements and non-debug elements |
| // to reduce the number of instanceof checks performed |
| if (element instanceof IDebugElement) { |
| if (element instanceof IStackFrame) { |
| label.append(((IStackFrame)element).getName()); |
| } else if (element instanceof IndexedVariablePartition) { |
| label.append(((IndexedVariablePartition)element).getName()); |
| } else if (element instanceof IVariable) { |
| label.append(getVariableText((IVariable)element)); |
| } else if (element instanceof IThread) { |
| label.append(((IThread)element).getName()); |
| } else if (element instanceof IDebugTarget) { |
| label.append((((IDebugTarget)element).getName())); |
| } else if (element instanceof IExpression) { |
| label.append(getExpressionText((IExpression)element)); |
| } else if (element instanceof IRegisterGroup) { |
| label.append(getRegisterGroupText((IRegisterGroup)element)); |
| } else if (element instanceof IValue) { |
| label.append(((IValue)element).getValueString()); |
| } |
| } else { |
| if (element instanceof IMarker) { |
| label.append(getMarkerText((IMarker) element)); |
| } else if (element instanceof IBreakpoint) { |
| label.append(getBreakpointText((IBreakpoint)element)); |
| } else if (element instanceof IProcess) { |
| label.append(((IProcess) element).getLabel()); |
| } else if (element instanceof ILaunch) { |
| label.append(getLaunchText((ILaunch) element)); |
| } else if (element instanceof ILaunchConfiguration) { |
| label.append(((ILaunchConfiguration)element).getName()); |
| } else if (element instanceof ILaunchConfigurationType) { |
| label.append(((ILaunchConfigurationType)element).getName()); |
| } else if(element instanceof ILaunchDelegate) { |
| ILaunchDelegate delegate = (ILaunchDelegate) element; |
| String name = delegate.getName(); |
| if(name == null) { |
| name = delegate.getContributorName(); |
| } |
| label.append(name); |
| } else if(element instanceof LaunchShortcutExtension) { |
| label.append(((LaunchShortcutExtension)element).getLabel()); |
| } else if (element instanceof String) { |
| label.append(element); |
| } else { |
| label.append(getAdapterLabel(element)); |
| } |
| } |
| if (element instanceof ITerminate) { |
| if (((ITerminate) element).isTerminated()) { |
| String terminatedMessage= null; |
| if (element instanceof IProcess) { |
| IProcess process = (IProcess)element; |
| int exit = process.getExitValue(); |
| terminatedMessage = MessageFormat.format(DebugUIMessages.DefaultLabelProvider_16, new Object[] { Integer.valueOf(exit).toString() }); |
| } else { |
| terminatedMessage= DebugUIMessages.DefaultLabelProvider_1; |
| } |
| label.insert(0, terminatedMessage); |
| } |
| } else if (element instanceof IDisconnect) { |
| if (((IDisconnect) element).isDisconnected()) { |
| label.insert(0, DebugUIMessages.DefaultLabelProvider__disconnected__1); |
| } |
| } |
| } catch (DebugException e) { |
| DebugUIPlugin.log(e); |
| label.append(DebugUIMessages.DefaultLabelProvider__unknown__1); |
| } |
| return label.toString(); |
| } |
| |
| /** |
| * Returns default label for a breakpoint. |
| * |
| * @param breakpoint |
| * @return default label for a breakpoint |
| */ |
| private String getBreakpointText(IBreakpoint breakpoint) { |
| IResource resource = breakpoint.getMarker().getResource(); |
| StringBuilder label = new StringBuilder(); |
| if (resource != null) { |
| label.append(resource.getName()); |
| } |
| if (breakpoint instanceof ILineBreakpoint) { |
| try { |
| int lineNumber = ((ILineBreakpoint)breakpoint).getLineNumber(); |
| label.append(MessageFormat.format(DebugUIMessages.DefaultLabelProvider_17, new Object[] { Integer.toString(lineNumber) })); |
| } catch (CoreException e) { |
| } |
| } |
| return label.toString(); |
| } |
| |
| public String getAdapterLabel(Object object) { |
| if (object instanceof IAdaptable) { |
| IWorkbenchAdapter de= ((IAdaptable) object).getAdapter(IWorkbenchAdapter.class); |
| if (de != null) { |
| return de.getLabel(object); |
| } |
| } |
| return DebugUIMessages.DefaultLabelProvider__unknown__1; |
| } |
| |
| /** |
| * Used to render launch history items in the re-launch drop downs |
| */ |
| protected String getLaunchText(ILaunch launch) { |
| if (launch.getLaunchConfiguration() == null || (!launch.getLaunchConfiguration().exists() && !launch.getLaunchConfiguration().isWorkingCopy())) { |
| return DebugUIMessages.DefaultLabelProvider__unknown__1; |
| } |
| // new launch configuration |
| ILaunchConfiguration config = launch.getLaunchConfiguration(); |
| StringBuilder buff= new StringBuilder(config.getName()); |
| buff.append(" ["); //$NON-NLS-1$ |
| try { |
| buff.append(config.getType().getName()); |
| } catch (CoreException e) { |
| DebugUIPlugin.log(e); |
| } |
| buff.append("]"); //$NON-NLS-1$ |
| return buff.toString(); |
| } |
| |
| protected String getExpressionText(IExpression expression) { |
| if (expression instanceof IWatchExpression) { |
| return getWatchExpressionText((IWatchExpression) expression); |
| } |
| StringBuilder buffer= new StringBuilder(expression.getExpressionText()); |
| String valueString= null; |
| IValue value= expression.getValue(); |
| if (value != null) { |
| try { |
| valueString= value.getValueString(); |
| } catch (DebugException de) { |
| DebugUIPlugin.log(de); |
| } |
| } |
| if (valueString != null && valueString.length() > 0) { |
| buffer.append("= "); //$NON-NLS-1$ |
| buffer.append(valueString); |
| } |
| return buffer.toString(); |
| } |
| |
| /** |
| * @param expression |
| * @return |
| */ |
| protected String getWatchExpressionText(IWatchExpression expression) { |
| StringBuilder result= new StringBuilder(); |
| |
| String snippet = expression.getExpressionText().trim(); |
| StringBuilder snippetBuffer = new StringBuilder(); |
| if (snippet.length() > 30){ |
| snippetBuffer.append(snippet.substring(0, 15)); |
| snippetBuffer.append(DebugUIMessages.DefaultLabelProvider_0); |
| snippetBuffer.append(snippet.substring(snippet.length() - 15)); |
| } else { |
| snippetBuffer.append(snippet); |
| } |
| snippet = snippetBuffer.toString().replaceAll("[\n\r\t]+", " "); //$NON-NLS-1$//$NON-NLS-2$ |
| |
| result.append('"'); |
| result.append(snippet); |
| result.append('"'); |
| |
| if (expression.isPending()) { |
| result.append(DebugUIMessages.DefaultLabelProvider_12); |
| } else if (expression.hasErrors()) { |
| result.append(DebugUIMessages.DefaultLabelProvider_13); |
| } else { |
| IValue value= expression.getValue(); |
| if (value != null) { |
| String valueString= DebugUIPlugin.getModelPresentation().getText(value); |
| if (valueString.length() > 0) { |
| result.append(" = ").append(valueString); //$NON-NLS-1$ |
| } |
| } |
| } |
| if (!expression.isEnabled()) { |
| result.append(DebugUIMessages.DefaultLabelProvider_15); |
| } |
| return result.toString(); |
| } |
| |
| protected String getVariableText(IVariable variable) { |
| StringBuilder buffer= new StringBuilder(); |
| try { |
| IValue value = variable.getValue(); |
| buffer.append(variable.getName()); |
| buffer.append(" = "); //$NON-NLS-1$ |
| buffer.append(value.getValueString()); |
| } catch (DebugException de) { |
| DebugUIPlugin.log(de); |
| } |
| return buffer.toString(); |
| } |
| |
| protected String getRegisterGroupText(IRegisterGroup registerGroup) { |
| StringBuilder buffer= new StringBuilder(); |
| try { |
| buffer.append(registerGroup.getName()); |
| } catch (DebugException de) { |
| DebugUIPlugin.log(de); |
| } |
| return buffer.toString(); |
| } |
| |
| protected String getMarkerText(IMarker marker) { |
| try { |
| if (marker.exists() && marker.isSubtypeOf(IBreakpoint.BREAKPOINT_MARKER)) { |
| return DebugUIMessages.DefaultLabelProvider_Breakpoint_1; |
| } |
| } catch (CoreException e) { |
| DebugUIPlugin.log(e); |
| } |
| return IInternalDebugCoreConstants.EMPTY_STRING; |
| } |
| |
| protected String getMarkerImageKey(IMarker marker) { |
| try { |
| IBreakpoint breakpoint= DebugPlugin.getDefault().getBreakpointManager().getBreakpoint(marker); |
| if (breakpoint != null && marker.exists()) { |
| if (breakpoint.isEnabled()) { |
| return IDebugUIConstants.IMG_OBJS_BREAKPOINT; |
| } |
| return IDebugUIConstants.IMG_OBJS_BREAKPOINT_DISABLED; |
| } |
| } catch (CoreException e) { |
| } |
| return null; |
| } |
| |
| protected String getBreakpointImageKey(IBreakpoint breakpoint) { |
| if (breakpoint != null && breakpoint.getMarker().exists()) { |
| try { |
| boolean enabled = breakpoint.isEnabled(); |
| if (breakpoint instanceof IWatchpoint) { |
| IWatchpoint watchpoint = (IWatchpoint) breakpoint; |
| if (watchpoint.isAccess()) { |
| if (watchpoint.isModification()) { |
| //access and modification |
| if (enabled) { |
| return IDebugUIConstants.IMG_OBJS_WATCHPOINT; |
| } |
| return IDebugUIConstants.IMG_OBJS_WATCHPOINT_DISABLED; |
| } |
| if (enabled) { |
| return IDebugUIConstants.IMG_OBJS_ACCESS_WATCHPOINT; |
| } |
| return IDebugUIConstants.IMG_OBJS_ACCESS_WATCHPOINT_DISABLED; |
| } else if (watchpoint.isModification()) { |
| if (enabled) { |
| return IDebugUIConstants.IMG_OBJS_MODIFICATION_WATCHPOINT; |
| } |
| return IDebugUIConstants.IMG_OBJS_MODIFICATION_WATCHPOINT_DISABLED; |
| } else { |
| //neither access nor modification |
| return IDebugUIConstants.IMG_OBJS_WATCHPOINT_DISABLED; |
| } |
| } |
| if (enabled) { |
| return IDebugUIConstants.IMG_OBJS_BREAKPOINT; |
| } |
| return IDebugUIConstants.IMG_OBJS_BREAKPOINT_DISABLED; |
| } catch (CoreException e) { |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * @see IBaseLabelProvider#addListener(ILabelProviderListener) |
| */ |
| @Override |
| public void addListener(ILabelProviderListener listener) { |
| } |
| |
| /** |
| * @see IBaseLabelProvider#dispose() |
| */ |
| @Override |
| public void dispose() { |
| for (Image image : fImages.values()) { |
| image.dispose(); |
| } |
| fImages.clear(); |
| } |
| |
| /** |
| * @see IBaseLabelProvider#isLabelProperty(Object, String) |
| */ |
| @Override |
| public boolean isLabelProperty(Object element, String property) { |
| return false; |
| } |
| |
| /** |
| * @see IBaseLabelProvider#removeListener(ILabelProviderListener) |
| */ |
| @Override |
| public void removeListener(ILabelProviderListener listener) { |
| } |
| |
| /** |
| * Returns the given string with special chars in escaped sequences. |
| * |
| * @param label |
| * @return the given string with special chars in escaped sequences |
| * @since 3.3 |
| */ |
| public static String escapeSpecialChars(String string) { |
| if (string == null) { |
| return null; |
| } |
| StringBuilder escaped = new StringBuilder(); |
| for (int i = 0; i < string.length(); i++) { |
| char c = string.charAt(i); |
| switch (c) { |
| case '\b': |
| escaped.append("\\b"); //$NON-NLS-1$ |
| break; |
| case '\f': |
| escaped.append("\\f"); //$NON-NLS-1$ |
| break; |
| case '\n': |
| escaped.append("\\n"); //$NON-NLS-1$ |
| break; |
| case '\r': |
| escaped.append("\\r"); //$NON-NLS-1$ |
| break; |
| case '\t': |
| escaped.append("\\t"); //$NON-NLS-1$ |
| break; |
| case '\\': |
| escaped.append("\\\\"); //$NON-NLS-1$ |
| break; |
| default: |
| escaped.append(c); |
| break; |
| } |
| } |
| return escaped.toString(); |
| } |
| |
| /** |
| * Returns the string with escaped sequences replaced with single chars. |
| * |
| * @param string |
| * @return the string with escaped sequences replaced with single chars |
| * @since 3.3 |
| */ |
| public static String encodeEsacpedChars(String string) { |
| if (string == null) { |
| return null; |
| } |
| StringBuilder encoded = new StringBuilder(); |
| if (string.length() == 1) { |
| return string; |
| } |
| for (int i = 0; i < string.length(); i++) { |
| char c = string.charAt(i); |
| if (c == '\\' && (i + 1 < string.length())) { |
| switch (string.charAt(i+1)) { |
| case 'b': |
| c= '\b'; |
| i++; |
| break; |
| case 'f': |
| c= '\f'; |
| i++; |
| break; |
| case 'n': |
| c= '\n'; |
| i++; |
| break; |
| case 'r': |
| c= '\r'; |
| i++; |
| break; |
| case 't': |
| c= '\t'; |
| i++; |
| break; |
| case '\'': |
| c= '\''; |
| i++; |
| break; |
| case '\\': |
| c= '\\'; |
| i++; |
| break; |
| default : |
| break; |
| } |
| } |
| encoded.append(c); |
| } |
| return encoded.toString(); |
| } |
| } |
| |