blob: a0e23cbcb60037e1c98efadeca98632625e1cb1b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.debug.ui;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.IVariable;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.ICodeAssist;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.ILocalVariable;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.debug.core.IJavaFieldVariable;
import org.eclipse.jdt.debug.core.IJavaStackFrame;
import org.eclipse.jdt.debug.core.IJavaThread;
import org.eclipse.jdt.debug.core.IJavaVariable;
import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin;
import org.eclipse.jdt.internal.debug.ui.actions.AbstractDisplayOptionsAction;
import org.eclipse.jdt.internal.ui.text.HTMLTextPresenter;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jdt.ui.PreferenceConstants;
import org.eclipse.jdt.ui.text.java.hover.IJavaEditorTextHover;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DefaultInformationControl;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IInformationControl;
import org.eclipse.jface.text.IInformationControlCreator;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextHoverExtension;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
public class JavaDebugHover implements IJavaEditorTextHover, ITextHoverExtension {
private IEditorPart fEditor;
/* (non-Javadoc)
* @see org.eclipse.jdt.ui.text.java.hover.IJavaEditorTextHover#setEditor(org.eclipse.ui.IEditorPart)
*/
public void setEditor(IEditorPart editor) {
fEditor = editor;
}
/* (non-Javadoc)
* @see org.eclipse.jface.text.ITextHover#getHoverRegion(org.eclipse.jface.text.ITextViewer, int)
*/
public IRegion getHoverRegion(ITextViewer textViewer, int offset) {
return JavaWordFinder.findWord(textViewer.getDocument(), offset);
}
/**
* Returns the stack frame in which to search for variables, or <code>null</code>
* if none.
*
* @return the stack frame in which to search for variables, or <code>null</code>
* if none
*/
protected IJavaStackFrame getFrame() {
IAdaptable adaptable = DebugUITools.getDebugContext();
if (adaptable != null) {
return (IJavaStackFrame)adaptable.getAdapter(IJavaStackFrame.class);
}
return null;
}
/* (non-Javadoc)
* @see org.eclipse.jface.text.ITextHover#getHoverInfo(org.eclipse.jface.text.ITextViewer, org.eclipse.jface.text.IRegion)
*/
public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) {
IJavaStackFrame frame = getFrame();
if (frame != null) {
ICodeAssist codeAssist = null;
if (fEditor != null) {
IEditorInput input = fEditor.getEditorInput();
Object element = JavaUI.getWorkingCopyManager().getWorkingCopy(input);
if (element == null) {
element = input.getAdapter(IClassFile.class);
}
if (element instanceof ICodeAssist) {
codeAssist = ((ICodeAssist)element);
}
}
if (codeAssist == null) {
return getRemoteHoverInfo(frame, textViewer, hoverRegion);
}
try {
IJavaElement[] resolve = codeAssist.codeSelect(hoverRegion.getOffset(), 0);
for (int i = 0; i < resolve.length; i++) {
IJavaElement javaElement = resolve[i];
if (javaElement instanceof IField) {
IField field = (IField)javaElement;
String typeSignature = Signature.createTypeSignature(field.getDeclaringType().getFullyQualifiedName(), true);
typeSignature = typeSignature.replace('.', '/');
IJavaFieldVariable fieldVariable = null;
if (frame.isStatic()) {
fieldVariable = frame.getDeclaringType().getField(field.getElementName());
} else {
fieldVariable = frame.getThis().getField(field.getElementName(), typeSignature);
}
if (fieldVariable != null) {
StringBuffer buf = new StringBuffer();
appendVariable(buf, fieldVariable);
return buf.toString();
}
break;
}
if (javaElement instanceof ILocalVariable) {
ILocalVariable var = (ILocalVariable)javaElement;
IJavaElement parent = var.getParent();
while (!(parent instanceof IMethod) && parent != null) {
parent = parent.getParent();
}
if (parent instanceof IMethod) {
IMethod method = (IMethod) parent;
boolean equal = false;
if (method.isBinary()) {
// compare resolved signatures
if (method.getSignature().equals(frame.getSignature())) {
equal = true;
}
} else {
// compare unresolved signatures
if (frame.getMethodName().equals(method.getElementName())
&& frame.getDeclaringTypeName().endsWith(method.getDeclaringType().getElementName())) {
equal = true;
}
}
if (equal) {
return generateHoverForLocal(frame, var.getElementName());
}
}
break;
}
}
} catch (CoreException e) {
JDIDebugPlugin.log(e);
}
}
return null;
}
/**
* Generate hover info via a variable search, if the java element is not avilable.
*/
private String getRemoteHoverInfo(IJavaStackFrame frame, ITextViewer textViewer, IRegion hoverRegion) {
if (frame != null) {
try {
IDocument document= textViewer.getDocument();
if (document != null) {
String variableName= document.get(hoverRegion.getOffset(), hoverRegion.getLength());
return generateHoverForLocal(frame, variableName);
}
} catch (BadLocationException x) {
}
}
return null;
}
private String generateHoverForLocal(IJavaStackFrame frame, String varName) {
StringBuffer buffer= new StringBuffer();
try {
IVariable variable= frame.findVariable(varName);
if (variable != null) {
appendVariable(buffer, variable);
}
} catch (DebugException x) {
if (x.getStatus().getCode() != IJavaThread.ERR_THREAD_NOT_SUSPENDED) {
JDIDebugUIPlugin.log(x);
}
}
if (buffer.length() > 0) {
return buffer.toString();
}
return null;
}
/**
* Append HTML for the given variable to the given buffer
*/
private static void appendVariable(StringBuffer buffer, IVariable variable) {
JDIModelPresentation modelPresentation = getModelPresentation();
buffer.append("<p><pre>"); //$NON-NLS-1$
buffer.append(modelPresentation.getVariableText((IJavaVariable) variable));
buffer.append("</pre></p>"); //$NON-NLS-1$
}
/**
* Returns a configured model presentation for use displaying variables.
*/
private static JDIModelPresentation getModelPresentation() {
JDIModelPresentation presentation = new JDIModelPresentation();
String viewId= IDebugUIConstants.ID_VARIABLE_VIEW;
String showDetails = AbstractDisplayOptionsAction.getStringPreferenceValue(viewId, IJDIPreferencesConstants.PREF_SHOW_DETAILS);
presentation.setAttribute(JDIModelPresentation.SHOW_DETAILS, showDetails);
String[][] booleanPrefs= {{IJDIPreferencesConstants.PREF_SHOW_HEX, JDIModelPresentation.SHOW_HEX_VALUES},
{IJDIPreferencesConstants.PREF_SHOW_CHAR, JDIModelPresentation.SHOW_CHAR_VALUES},
{IJDIPreferencesConstants.PREF_SHOW_UNSIGNED, JDIModelPresentation.SHOW_UNSIGNED_VALUES}};
for (int i = 0; i < booleanPrefs.length; i++) {
boolean preferenceValue = AbstractDisplayOptionsAction.getBooleanPreferenceValue(viewId, booleanPrefs[i][0]);
presentation.setAttribute(booleanPrefs[i][1], (preferenceValue ? Boolean.TRUE : Boolean.FALSE));
}
return presentation;
}
/* (non-Javadoc)
* @see org.eclipse.jface.text.ITextHoverExtension#getHoverControlCreator()
*/
public IInformationControlCreator getHoverControlCreator() {
if (PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_SHOW_TEXT_HOVER_AFFORDANCE)) { //$NON-NLS-1$
return new IInformationControlCreator() {
public IInformationControl createInformationControl(Shell parent) {
return new DefaultInformationControl(parent, SWT.NONE,
new HTMLTextPresenter(true),
DebugUIMessages.getString("JavaDebugHover.16")); //$NON-NLS-1$
}
};
}
return null;
}
}