blob: 1084733ba033e860bbc6e32d377af5ad668de382 [file] [log] [blame]
package org.eclipse.jdt.internal.debug.ui;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import java.util.Map;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.debug.core.IJavaBreakpoint;
import org.eclipse.jdt.debug.core.IJavaLineBreakpoint;
import org.eclipse.jdt.debug.core.IJavaMethodBreakpoint;
import org.eclipse.jdt.debug.core.IJavaWatchpoint;
/**
* Utility class for Java breakpoints
*/
public class BreakpointUtils {
/**
* Marker attribute storing the handle id of the
* Java element associated with a Java breakpoint
*/
private static final String HANDLE_ID = JDIDebugUIPlugin.getUniqueIdentifier() + ".JAVA_ELEMENT_HANDLE_ID"; //$NON-NLS-1$
/**
* Marker attribute used to denote a run to line breakpoint
*/
private static final String RUN_TO_LINE = JDIDebugUIPlugin.getUniqueIdentifier() + ".run_to_line"; //$NON-NLS-1$
/**
* Marker attribute used to denote the start of the region within a Java
* member that the breakpoint is located within.
*/
private static final String MEMBER_START = JDIDebugUIPlugin.getUniqueIdentifier() + ".member_start"; //$NON-NLS-1$
/**
* Marker attribute used to denote the end of the region within a Java
* member that the breakpoint is located within.
*/
private static final String MEMBER_END = JDIDebugUIPlugin.getUniqueIdentifier() + ".member_end"; //$NON-NLS-1$
/**
* Returns the resource on which a breakpoint marker should
* be created for the given member. The resource returned is the
* associated file, or project in the case of a class file in
* a jar.
*
* @param member member in which a breakpoint is being created
* @return resource the resource on which a breakpoint marker
* should be created
* @exception CoreException if an exception occurs accessing the
* underlying resource or Java model elements
*/
public static IResource getBreakpointResource(IMember member) throws CoreException {
ICompilationUnit cu = member.getCompilationUnit();
if (cu != null && cu.isWorkingCopy()) {
member = (IMember)cu.getOriginal(member);
}
IResource res = member.getUnderlyingResource();
if (res == null) {
res = member.getJavaProject().getProject();
}
return res;
}
/**
* Returns the type that the given Java breakpoint refers to
*
* @param breakpoint Java breakpoint
* @return the type the breakpoint is associated with
* @exception CoreException if an exception occurs accessing
* the breakpoint or Java model
*/
public static IType getType(IJavaBreakpoint breakpoint) throws CoreException {
String handle = breakpoint.getMarker().getAttribute(HANDLE_ID, null);
if (handle != null) {
IJavaElement je = JavaCore.create(handle);
if (je != null) {
if (je instanceof IType) {
return (IType)je;
}
if (je instanceof IMember) {
return ((IMember)je).getDeclaringType();
}
}
}
return null;
}
/**
* Returns the member associated with the line number of
* the given breakpoint.
*
* @param breakpoint Java line breakpoint
* @return member at the given line number in the type
* associated with the breakpoint
* @exception CoreException if an exception occurs accessing
* the breakpoint
*/
public static IMember getMember(IJavaLineBreakpoint breakpoint) throws CoreException {
if (breakpoint instanceof IJavaMethodBreakpoint) {
return getMethod((IJavaMethodBreakpoint)breakpoint);
}
if (breakpoint instanceof IJavaWatchpoint) {
return getField((IJavaWatchpoint)breakpoint);
}
int start = breakpoint.getCharStart();
int end = breakpoint.getCharEnd();
IType type = getType(breakpoint);
if (start == -1 && end == -1) {
start= breakpoint.getMarker().getAttribute(MEMBER_START, -1);
end= breakpoint.getMarker().getAttribute(MEMBER_END, -1);
}
IMember member = null;
if ((type != null) && (end >= start) && (start >= 0)) {
try {
member= binSearch(type, start, end);
} catch (CoreException ce) {
JDIDebugUIPlugin.log(ce);
}
}
if (member == null) {
member= type;
}
return member;
}
/**
* Searches the given source range of the container for a member that is
* not the same as the given type.
*/
protected static IMember binSearch(IType type, int start, int end) throws JavaModelException {
IJavaElement je = getElementAt(type, start);
if (je != null && !je.equals(type)) {
return asMember(je);
}
if (end > start) {
je = getElementAt(type, end);
if (je != null && !je.equals(type)) {
return asMember(je);
}
int mid = ((end - start) / 2) + start;
if (mid > start) {
je = binSearch(type, start + 1, mid);
if (je == null) {
je = binSearch(type, mid + 1, end - 1);
}
return asMember(je);
}
}
return null;
}
/**
* Returns the given Java element if it is an
* <code>IMember</code>, otherwise <code>null</code>.
*
* @param element Java element
* @return the given element if it is a type member,
* otherwise <code>null</code>
*/
private static IMember asMember(IJavaElement element) {
if (element instanceof IMember) {
return (IMember)element;
} else {
return null;
}
}
/**
* Returns the element at the given position in the given type
*/
protected static IJavaElement getElementAt(IType type, int pos) throws JavaModelException {
if (type.isBinary()) {
return type.getClassFile().getElementAt(pos);
} else {
return type.getCompilationUnit().getElementAt(pos);
}
}
/**
* Adds attributes to the given attribute map:<ul>
* <li>Java element handle id</li>
* <li>Attributes defined by <code>JavaCore</code></li>
* </ul>
*
* @param attributes the attribute map to use
* @param element the Java element associated with the breakpoint
* @exception CoreException if an exception occurs configuring
* the marker
*/
public static void addJavaBreakpointAttributes(Map attributes, IJavaElement element) {
String handleId = element.getHandleIdentifier();
attributes.put(HANDLE_ID, handleId);
JavaCore.addJavaElementMarkerAttributes(attributes, element);
}
/**
* Adds attributes to the given attribute map:<ul>
* <li>Java element handle id</li>
* <li>Member start position</li>
* <li>Member end position</li>
* <li>Attributes defined by <code>JavaCore</code></li>
* </ul>
*
* @param attributes the attribute map to use
* @param element the Java element associated with the breakpoint
* @param memberStart the start position of the Java member that the breakpoint is positioned within
* @param memberEnd the end position of the Java member that the breakpoint is positioned within
* @exception CoreException if an exception occurs configuring
* the marker
*/
public static void addJavaBreakpointAttributesWithMemberDetails(Map attributes, IJavaElement element, int memberStart, int memberEnd) {
addJavaBreakpointAttributes(attributes, element);
attributes.put(MEMBER_START, new Integer(memberStart));
attributes.put(MEMBER_END, new Integer(memberEnd));
}
/**
* Adds attributes to the given attribute map to make the
* breakpoint a run-to-line breakpoint:<ul>
* <li>PERSISTED = false</li>
* <li>RUN_TO_LINE = true</li>
* </ul>
*
* @param attributes the attribute map to use
* @param element the Java element associated with the breakpoint
* @exception CoreException if an exception occurs configuring
* the marker
*/
public static void addRunToLineAttributes(Map attributes) {
attributes.put(IBreakpoint.PERSISTED, Boolean.FALSE);
attributes.put(RUN_TO_LINE, Boolean.TRUE);
}
/**
* Returns the method associated with the method entry
* breakpoint.
*
* @param breakpoint Java method entry breakpoint
* @return method
* @exception CoreException if an exception occurs accessing
* the breakpoint
*/
public static IMethod getMethod(IJavaMethodBreakpoint breakpoint) throws CoreException {
String handle = breakpoint.getMarker().getAttribute(HANDLE_ID, null);
if (handle != null) {
IJavaElement je = JavaCore.create(handle);
if (je != null) {
if (je instanceof IMethod) {
return (IMethod)je;
}
}
}
return null;
}
/**
* Returns the field associated with the watchpoint.
*
* @param breakpoint Java watchpoint
* @return field
* @exception CoreException if an exception occurs accessing
* the breakpoint
*/
public static IField getField(IJavaWatchpoint breakpoint) throws CoreException {
String handle = breakpoint.getMarker().getAttribute(HANDLE_ID, null);
if (handle != null) {
IJavaElement je = JavaCore.create(handle);
if (je != null) {
if (je instanceof IField) {
return (IField)je;
}
}
}
return null;
}
/**
* Returns whether the given breakpoint is a run to line
* breakpoint
*
* @param breakpoint line breakpoint
* @return whether the given breakpoint is a run to line
* breakpoint
*/
public static boolean isRunToLineBreakpoint(IJavaLineBreakpoint breakpoint) throws CoreException {
return breakpoint.getMarker().getAttribute(RUN_TO_LINE, false);
}
/**
* Returns whether the given breakpoint is a compilation
* problem breakpoint
*
* @param breakpoint breakpoint
* @return whether the given breakpoint is a run to line
* breakpoint
*/
public static boolean isProblemBreakpoint(IBreakpoint breakpoint) {
return breakpoint == JavaDebugOptionsManager.getDefault().getSuspendOnCompilationErrorBreakpoint();
}
}