blob: d5a33c08cbce8a67e3f3002dc93af794ffae0e17 [file] [log] [blame]
/*******************************************************************************
* 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();
}
}