}
public static IBreakpoint[] getBreakpoints() {
- return getBreakpointManager().getBreakpoints(IXDebugConstants.ID_PHP_DEBUG_MODEL);
+ return getBreakpointManager().getBreakpoints(IXDebugConstants.ID_PHP_BREAKPOINT_MODEL);
}
public static IBreakpointManager getBreakpointManager() {
} catch (IOException e) {
if (e instanceof EOFException == false) {
if (!fIsClosed) {
- e.printStackTrace();
+// e.printStackTrace();
}
}
return null;
*/
public interface IXDebugConstants {
/**
- * Unique identifier for the PHP debug model (value
+ * Unique identifier for the PHP debug model (value
* <code>et.sourceforge.phpeclipse.debug.</code>).
*/
public static final String ID_PHP_DEBUG_MODEL = "net.sourceforge.phpeclipse.xdebug.php";
-
+ public static final String ID_PHP_BREAKPOINT_MODEL = "net.sourceforge.phpeclipse.debug.core";
+
/**
* Launch configuration key. Value is a PHPProject name
* program. The path is a string representing a full path
- * to a perl program in the workspace.
+ * to a perl program in the workspace.
*/
public static final String ATTR_PHP_PROJECT = ID_PHP_DEBUG_MODEL + ".ATTR_PDA_PROFECT";
/**
* Launch configuration key. Value is a php program.
* The path is a string representing a relative path
- * to a php program in the project.
+ * to a php program in the project.
*/
public static final String ATTR_PHP_FILE = ID_PHP_DEBUG_MODEL + ".ATTR_PDA_FILE";
public static final String ATTR_PHP_IDE_ID = ID_PHP_DEBUG_MODEL + ".ATTR_PHP_IDE_ID";
public static final String ATTR_PHP_PATHMAP = ID_PHP_DEBUG_MODEL + ".ATTR_PHP_PATHMAP";
-}
\ No newline at end of file
+}
package net.sourceforge.phpeclipse.xdebug.php.launching;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
+import java.util.Map;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
import net.sourceforge.phpeclipse.xdebug.core.PathMapItem;
import net.sourceforge.phpeclipse.xdebug.php.model.XDebugStackFrame;
import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.model.IStackFrame;
import org.eclipse.debug.core.sourcelookup.AbstractSourceLookupParticipant;
import org.eclipse.debug.core.sourcelookup.ISourceContainer;
import org.eclipse.debug.internal.core.sourcelookup.SourceLookupMessages;
public class PHPSourceLookupParticipant extends AbstractSourceLookupParticipant {
+ private Map pathMap = null;
+ private boolean remoteDebug = true;
+ private IPath remoteSourcePath;
+ private String projectName;
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.sourcelookup.ISourceLookupParticipant#getSourceName(Object)
*/
public String getSourceName(Object object) throws CoreException {
if (object instanceof XDebugStackFrame) {
- return ((XDebugStackFrame) object).getSourceName();
+ return ((XDebugStackFrame) object).getFullSourceName();
}
return null;
}
+ /**
+ * @see org.eclipse.debug.core.model.ISourceLocator#getSourceElement(IStackFrame)
+ *
+ * Return the client side source filename for the server side source file.
+ * E.g. when cross debugging, the server side filename could be /var/www/index.php
+ * on the client side it is either a Eclipse_PHP_projectname\index.php (when it is a linked file)
+ *
+ *
+ * @param stackFrame The stackframe for which we want the client side source file name
+ * @return The filename as it appears on the client side
+ */
+ public Object getSourceElement (IStackFrame stackFrame) throws CoreException {
+ IPath projectPath;
+ IPath remotePath;
+ IPath path;
+ IPath localPath;
+ Iterator iterator;
+ String fileName;
+ //String file;
+ String local;
+ List pathMap;
+ PathMapItem pmi = null;
+
+ projectName = getDirector().getLaunchConfiguration().getAttribute (IXDebugConstants.ATTR_PHP_PROJECT, "");
+ pathMap = getDirector().getLaunchConfiguration().getAttribute(IXDebugConstants.ATTR_PHP_PATHMAP, (List) null);
+
+ fileName = ((XDebugStackFrame) stackFrame).getFullSourceName (); // Get the filename as it is submitted by XDebug
+ //file = "";
+
+ if (remoteDebug) { // Is it a remote debugging session
+ path = new Path (fileName); // Create a IPath object for the server side filename
+/*
+ if (!remoteSourcePath.isEmpty()) {
+ if (remoteSourcePath.isPrefixOf (path)) { // Is the server side filename with the remote source path
+ path = path.removeFirstSegments (remoteSourcePath.matchingFirstSegments (path)); // Remove the remote source path
+ //file = path.toString (); // The filename without the remote source path
+ projectPath = (PHPeclipsePlugin.getWorkspace().getRoot().getProject(projectName).getLocation()); // Get the absolute project path
+
+ return (projectPath.append (path)).toOSString (); // Return the filename as absolute client side path
+ }
+ }
+ else {
+*/
+ if (pathMap == null) { // Do we have path mapping (e.g. for cross platform debugging)
+ return fileName; // No, then return the filename as it given by DBG (the full server side path)
+ }
+
+ pmi = null;
+
+ for (int k = 0; k < pathMap.size(); k++) {
+ pmi = new PathMapItem ((String) pathMap.get(k));
+
+ local = pmi.getLocalPath ().toString(); //
+ localPath = new Path (pmi.getLocalPath().toString()); // Get the local/client side path of the mapping
+ remotePath = new Path (pmi.getRemotePath().toString()); // Get the remote/server side path of the mapping
+
+ if (remotePath.isPrefixOf (path)) { // Starts the remote/server side file path with the remote/server side mapping path
+ path = path.removeFirstSegments (remotePath.matchingFirstSegments (path)); // Remove the absolute path from filename
+
+ return path.toString ();
+/*
+ localPath = new Path (local); // Create new IPath object for the local/client side path
+ path = localPath.append (path); // Prepend the project relative path to filename
+
+ projectPath = (PHPeclipsePlugin.getWorkspace().getRoot().getProject(projectName).getLocation()); // Get the absolute project path
+
+// return path;
+ return (projectPath.append (path)).toString (); // Return the filename as absolute client side path
+*/
+ }
+ }
+// }
+
+ if (pathMap == null) { // Do we have path mapping (e.g. for cross platform debugging)
+ return fileName; // No, then return the filename as it given by DBG (the full server side path)
+ }
+
+ pmi = null;
+
+ for (int k = 0; k < pathMap.size(); k++) {
+ pmi = new PathMapItem((String) pathMap.get(k));
+
+ local = pmi.getLocalPath().toString(); // Get the local/client side path of the mapping
+ localPath = new Path (pmi.getLocalPath().toString()); // Get the local/client side path of the mapping
+ remotePath = new Path (pmi.getRemotePath().toString()); // Get the remote/server side path of the mapping
+
+ if (remotePath.isPrefixOf (path)) { // Starts the remote/server side file path with the remote/server side mapping path
+ path = path.removeFirstSegments (remotePath.matchingFirstSegments (path)); // Remove the absolute path from filename
+ localPath = new Path (local); // Create new IPath object for the local/client side path
+
+ return localPath.append (path).toOSString (); // Append the remote filename to the client side path (So we return the absolute path
+ // to the source file as the client side sees it.
+ }
+ }
+
+ return fileName;
+
+ } else { // no remote debug
+/*
+ IWorkspaceRoot root = PHPLaunchingPlugin.getWorkspace().getRoot();
+ Path filePath = new Path(fileName);
+
+ if (root.getFileForLocation(filePath) == null) {
+ IProject proj = root.getProject(projectName);
+ IFile[] files = root.findFilesForLocation(filePath);
+ for (int i = 0; i < files.length; i++) {
+ if (files[i].getProject().equals(proj)) {
+ fileName = proj.getFullPath().append(files[i].getProjectRelativePath()).toOSString();
+ break;
+ }
+ }
+ }
+*/
+ return fileName;
+ }
+ }
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.sourcelookup.ISourceLookupParticipant#findSourceElements(java.lang.Object)
*/
public Object[] findSourceElements(Object object) throws CoreException {
+ String name = null;
+
if (object == null) {
return new Object[] {};
}
results = new ArrayList();
}
- String name = getSourceName(object);
+ try {
+ name = (String) getSourceElement (stackFrame);
+ }
+ catch (CoreException e) {
+ }
+
if (name == null || name.length() == 0) {
return new Object[] {};
}
IPath sPath = new Path(stackFrame.getFullName().getPath());
List pathMap = getDirector().getLaunchConfiguration()
.getAttribute(IXDebugConstants.ATTR_PHP_PATHMAP, (List) null);
-
+
PathMapItem pmi = null;
for (int k = 0; k < pathMap.size(); k++) {
pmi = new PathMapItem((String) pathMap.get(k));
-
+
IPath local = new Path(pmi.getLocalPath().toString());
IPath remote = new Path(pmi.getRemotePath().toString());
-
+
if (remote.matchingFirstSegments(sPath) == remote.segmentCount()) {
sLocalPath = local;
}
}
} else {
-
+
}
String Type = stackFrame.getType();
multiStatus = new MultiStatus(DebugPlugin
.getUniqueIdentifier(), DebugPlugin.INTERNAL_ERROR,
new IStatus[] { single.getStatus() },
- SourceLookupMessages.DefaultSourceContainer_0/*CompositeSourceContainer_0*/,
+ SourceLookupMessages.DefaultSourceContainer_0,
null);
multiStatus.add(e.getStatus());
} else {
}
return EMPTY;
}
+
return results.toArray();
}
}
}
}
-}
\ No newline at end of file
+}
*/
package net.sourceforge.phpeclipse.xdebug.php.model;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.Vector;
import net.sourceforge.phpeclipse.xdebug.core.PHPDebugUtils;
import org.eclipse.debug.core.DebugException;
*/
public /*abstract*/ class XDebugAbstractValue extends XDebugElement implements IValue {
- private IVariable[] fVariables;
- private String fValueString;
- private String fTypeName;
- private boolean fhasChanged;
- protected String rowValue;
-
+ private String fValueString;
+ private String fTypeName;
+ private boolean fhasChanged;
+ protected String rowValue;
+ private boolean fSorted;
+ private Vector fVariables; // The children of this variable (other variables) if any
+
public XDebugAbstractValue(XDebugStackFrame frame, Node value) throws DebugException {
super(frame == null ? null : (XDebugTarget)frame.getDebugTarget());
- fTypeName = PHPDebugUtils.getAttributeValue(value, "type");
-
- fVariables = new IVariable[0];
+ fTypeName = PHPDebugUtils.getAttributeValue(value, "type");
+
+ fVariables = new Vector(); // Create an empty vector
+ fValueString = "";
+ rowValue = "";
+ fSorted = false;
- rowValue = "";
try {
rowValue = value.getFirstChild().getNodeValue();
} catch (NullPointerException e) {
rowValue = "";
}
}
-
+
public boolean hasChanged() {
return fhasChanged;
}
-
+
+ public void setChanged(boolean changed) {
+ fhasChanged = changed;
+ }
+
+ /**
+ *
+ * @param item
+ */
+ public Vector addVariable(Vector item) {
+ if (item != null) { // If there is something we want to add
+ fVariables.addAll(item);
+ fSorted = false;
+ }
+
+ return this.fVariables;
+ }
+
+ /**
+ *
+ * @param parent
+ */
+ public void setParent(XDebugVariable parent) {
+ if (!fVariables.isEmpty()) { // If we have child variables
+ Iterator iter = fVariables.iterator(); // Create an iterator for the children
+
+ while (iter.hasNext()) { // As long as we have children
+ ((XDebugVariable) iter.next()).setParent(parent); // Set all child's parent
+ }
+ }
+ }
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IValue#getReferenceTypeName()
*/
public String getReferenceTypeName() throws DebugException {
return fTypeName;
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IValue#getValueString()
*/
public String getValueString() throws DebugException {
return fValueString;
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IValue#isAllocated()
*/
public boolean isAllocated() throws DebugException {
return true;
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IValue#getVariables()
*/
public IVariable[] getVariables() throws DebugException {
+ return (XDebugVariable[]) getChildVariables().toArray(
+ new XDebugVariable[fVariables.size()]);
+ }
+
+ /**
+ *
+ */
+ public Vector getChildVariables() {
return fVariables;
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IValue#hasVariables()
*/
public boolean hasVariables() throws DebugException {
- return (fVariables.length > 0);
+ return (fVariables.size() != 0);
}
-
+
public boolean setValue(String expression) throws DebugException {
return true;
};
-
+
protected boolean verifyValue(String expression) {
return true;
}
-
+
protected boolean supportsValueModification() {
return false;
}
-
+
protected void setValueString(String valueString) {
fValueString = valueString;
}
protected void setChildren(IVariable[] newChildren) {
- fVariables = newChildren;
+ fVariables = new Vector (Arrays.asList(newChildren));
}
-}
\ No newline at end of file
+}
import java.net.MalformedURLException;
import java.net.URL;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Vector;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IDebugTarget;
import org.eclipse.debug.core.model.IRegisterGroup;
import org.eclipse.debug.core.model.IStackFrame;
import org.eclipse.debug.core.model.IThread;
* @author Axel
*
*/
-public class XDebugStackFrame extends XDebugElement implements IStackFrame {
- private XDebugThread fThread;
- private URL fName;
- private int fLineNumber;
- private int fLevel;
- private String fType;
- private String fWhere;
- private IVariable[] fVariables;
- private int fStepCount = 0;
-
+public class XDebugStackFrame extends XDebugElement implements IStackFrame, Comparable {
+ private XDebugThread fThread;
+ private URL fName;
+ private int fLineNumber;
+ private int fLevel;
+ private String fType;
+ private String fWhere;
+ private IVariable[] fVariables;
+ private int fStepCount = 0;
+ private boolean fUpToDate = false;
+ private Vector varList; // Variables list
+ private boolean fAvailable; // Needed when updating the stackframe list, shows whether the stackframe
+ // is within the list which was received from XDebug
+
/**
* Constructs a stack frame in the given thread with the given
* frame data.
- *
+ *
* @param thread
* @param data frame data
* @param id stack frame id (0 is the bottom of the stack)
*/
public XDebugStackFrame(XDebugThread thread, int id, String type, int lineNumber, String where, /*URL*/String filename) {
super(/*thread == null ? null : */(XDebugTarget) thread.getDebugTarget());
-
- fLevel = id;
- fThread = thread;
- fType = type;
- fLineNumber = lineNumber;
- fWhere = where;
-
+
+ this.fLevel = id;
+ this.fThread = thread;
+ this.fType = type;
+ this.fLineNumber = lineNumber;
+ this.fWhere = where;
+ this.varList = new Vector();
+
try {
- fName = new URL(filename);
+ fName = new URL(filename);
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
-
+
public void incrementStepCounter() {
fStepCount++;
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IStackFrame#getThread()
*/
public IThread getThread() {
return fThread;
}
-
- public IVariable[] getVariables() throws DebugException {
+
+ /**
+ * @see IAdaptable#getAdapter(Class)
+ */
+ public Object getAdapter(Class adapter) {
+ if (adapter == XDebugStackFrame.class) {
+ return this;
+ }
+
+ return super.getAdapter(adapter);
+ }
+
+ public IDebugTarget getDebugTarget() {
+ return this.getThread().getDebugTarget();
+ }
+
+ /**
+ *
+ */
+ private void resetHasChangedInfo(Vector varList) {
+ int n;
+ XDebugVariable var;
+ XDebugAbstractValue val;
+
+ for (n = 0; n < varList.size (); n++) { // For every variable in 'DBG list'
+ var = (XDebugVariable) varList.get(n); // Get the variable
+ val = (XDebugAbstractValue) var.getValue(); // Get the variable's value
+
+ try {
+ if (val.hasVariables()) { // Do we have other variables within the value
+ if (!hasRecursion(var)) { // Is this variable (value) branch recursive?
+ resetHasChangedInfo(val.getChildVariables()); // No, go into branch
+ }
+ }
+ } catch (DebugException e) { // That's, because of the hasVariables method
+ }
+
+ var.setValueChanged(false); // Reset the 'has changed' flag
+ }
+ }
+
+ /**
+ * Go up the tree of PHPVariables
+ * look whether the PHPValue is a reference to a parent PHPValue
+ *
+ * TODO Check where this recursion can come from.
+ * Whether this back reference is legal or a bug.
+ *
+ * Typically $GLOBALS contains $GLOBALS
+ *
+ * @param var
+ * @return
+ * <ul>
+ * <li> false if the PHPValue is not a child of itself
+ * <li> true if the PHPValue is
+ * </ul>
+ */
+ private boolean hasRecursion(XDebugVariable var) {
+ XDebugVariable parentVar;
+ XDebugAbstractValue val;
+
+ val = (XDebugAbstractValue) var.getValue(); // Get the PHPValue from the current PHPVariable
+
+ while (var != null) { // As long as we have PHPVariable
+ parentVar = var.getParent(); // Get the parent PHPVariable
+
+ if (parentVar != null) { // Is there a parent?
+ if (parentVar.getValue().equals(val)) { // Get the PHPValue for the parent PHPVariable and check
+ // whether it is the same
+ return true; // Return, if we have recursion
+ }
+ }
+
+ var = parentVar;
+ }
+
+ return false; // No recursion found
+ }
+
+ /**
+ * This method updates the 'static' variables list.
+ * It does a replication between the 'static' list (the variable list which
+ * is a member of this DBG interface object) and the DBG variable list
+ * (the list of variables which is received from PHP via DBG with the current suspend)
+ * Replication is done in the following way:
+ * <ul>
+ * <li> It looks for new variables within the DBG variables list and
+ * adds them to the 'static' list.
+ * <li> It looks for changed variables copies the current value to the variable within
+ * the 'static list' and mark these variables as 'hasChanged' (which uses the UI
+ * for showing the variable with a different color).
+ * <li> It looks for variables within the 'static' list, and removes them
+ * from the 'static' list in case the do not appear within the DBG list.
+ * </ul>
+ *
+ * @param varListOld The 'static' list of variables which are to be updated.
+ * @param varListNew The new list of (current) variables from DBG.
+ */
+ private void updateVariableList(Vector varListOld, Vector varListNew) {
+ XDebugVariable varOld; // The variable from the 'static' list
+ XDebugVariable varNew; // The variable from the DBG list
+ XDebugAbstractValue valOld; // The value of the current variable from 'static' list
+ XDebugAbstractValue valNew; // The value of the current variable from DBG list
+ int n; // Index for the DBG list
+ int o; // Index for the static list
+
+ // Add the variables (and childs) to the static list if they are new
+ // and update the values of variables which are already existend within
+ // the 'static' list.
+
+ for (n = 0; n < varListNew.size(); n++) { // For every variable in 'DBG list'
+ varNew = (XDebugVariable) varListNew.get(n); // Get the DBG variable
+
+ for (o = 0; o < varListOld.size(); o++) { // For every variable in static list
+ varOld = (XDebugVariable) varListOld.get(o); // Get the static variable
+
+ if (varNew.getName().equals(varOld.getName())) { // Did we found the variable within the 'static' list?
+ valOld = (XDebugAbstractValue) varOld.getValue(); // Get the value from 'static'
+ valNew = (XDebugAbstractValue) varNew.getValue(); // Get the value from DBG
+
+ try {
+ if (valOld.hasVariables() || // If the 'static' value has child variables
+ valNew.hasVariables()) { // or if the DBG value has child variables
+ if (!hasRecursion(varOld) &&
+ !hasRecursion(varNew)) { // Both branches should not have a recursion
+ updateVariableList(
+ valOld.getChildVariables(), // Update the variable list for the child variables
+ valNew.getChildVariables());
+ }
+ }
+
+ if (!valOld.getValueString().equals(
+ valNew.getValueString())) { // Has the value changed?
+ valOld.setValueString(valNew.getValueString()); // Yes, set the 'static' value (variable) to the new value
+ varOld.setValueChanged(true); // and set the 'has changed' flag, so that the variable view
+ // could show the user the changed status with a different
+ // color
+ }
+ } catch (DebugException e) { // That's, because of the hasVariables method
+ }
+
+ break; // Found the variable,
+ }
+ }
+
+ if (o == varListOld.size()) { // Did we found the variable within the static list?
+ varListOld.add(varNew); // No, then add the DBG variable to the static list
+ }
+ }
+
+ // Look for the variables we can remove from the 'static' list
+
+ for (o = 0; o < varListOld.size(); o++) { // For every variable in 'static' list
+ varOld = (XDebugVariable) varListOld.get(o); // Get the static variable
+
+ for (n = 0; n < varListNew.size(); n++) { // For all variables in 'DBG' list
+ varNew = (XDebugVariable) varListNew.get(n); // Get the variable from the 'DBG' list
+
+ if (varNew.getName().equals(varOld.getName())) { // Did we found the 'static' list variable within the 'DBG' list?
+ break; // Yes we found the variable, then leave the loop
+ }
+ }
+
+ if (n == varListNew.size()) { // Did not find the 'static' list variable within the 'DBG' list?
+ varListOld.remove(o--); // then remove the 'static' list variable from list
+ }
+ }
+ }
+
+ /**
+ *
+ * This function returns the array of PHPVariables for this stackframe
+ * The PHPVariables should not change (newly build up) between two steps
+ * (or breaks).
+ * A PHPVariable with the same name but with different object ID is
+ * handled as a new variable.
+ *
+ * @return The array of PHPVariables for this stackframe.
+ */
+
+ public synchronized IVariable[] getVariables() throws DebugException {
/* always read variables, poor performance
* but this fix bug #680.
* need to investigate on.
*/
-
- //if (fVariables == null) {
- Node dfl = ((XDebugTarget) getDebugTarget()).getLocalVariables(fLevel);
- Node dfg = ((XDebugTarget) getDebugTarget()).getGlobalVariables(fLevel);
- parseVariable(dfl, dfg);
- //}
- return fVariables;
+ if (!fUpToDate) {
+ Node dfl = ((XDebugTarget) getDebugTarget()).getLocalVariables(fLevel);
+ Node dfg = ((XDebugTarget) getDebugTarget()).getGlobalVariables(fLevel);
+ parseVariable(dfl, dfg);
+
+ Vector newVariables = new Vector (Arrays.asList(fVariables));
+ resetHasChangedInfo (varList);
+ updateVariableList (varList, newVariables);
+ fUpToDate = true;
+ Collections.sort (varList, new XDebugVariableComparator ());
+ }
+
+ return (IVariable[]) varList.toArray (new IVariable[varList.size()]);
}
-
+
private void parseVariable(Node localVariables, Node globalVariables) throws DebugException {
- NodeList property = localVariables.getChildNodes();
-
+ NodeList property = localVariables.getChildNodes();
NodeList propertyGlobal = globalVariables.getChildNodes();
-
+
fVariables = new IVariable[property.getLength() + propertyGlobal.getLength()];
-
+
int length = property.getLength();
for (int i = 0; i < length; i++) {
XDebugVariable var = new XDebugVariable(this, property.item(i));
fVariables[k + length] = var;
}
}
-
+
+ /**
+ *
+ */
+ private XDebugVariable findVariable(Vector varList, String varname) {
+ XDebugVariable variable;
+ XDebugAbstractValue value;
+ int i;
+
+ for (i = 0; i < varList.size(); i++) { // For all variables
+ variable = (XDebugVariable) varList.get(i); // Get the variable
+ value = (XDebugAbstractValue) variable.getValue(); // Get the value of the variable
+
+ try {
+ if (value.hasVariables()) { // Does the variable/value have children
+ if (!hasRecursion(variable)) { // Don't follow recursive variable/values
+ XDebugVariable var = findVariable(value.getChildVariables(), varname);
+
+ if (var != null) {
+ return var;
+ }
+ }
+ }
+
+ if (variable.getName().equals(varname)) {
+ return variable;
+ }
+ } catch (DebugException e) { // That's, because of the hasVariables method
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * This method is called from the UI (e.g. from PHPDebugHover
+ * to find the variable the mouse is pointing to)
+ *
+ * @param s The variable name we are looking for.
+ * @return
+ */
+ public IVariable findVariable(String s) throws DebugException {
+ if (!fUpToDate) {
+ getVariables();
+ }
+
+ return (findVariable(varList, s)); // Prefix the variable name with $
+ }
+
/*public void evaluateChange(IStackFrame OldStackFrame) throws DebugException {
IVariable[] OldVariable = ((XDebugStackFrame) OldStackFrame).getVariables();
for (int i = 0; i < fVariables.length; i++) {
((XDebugVariable) fVariables[i]).setChange(OldVariable[i]);
}
}*/
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IStackFrame#hasVariables()
*/
public boolean hasVariables() throws DebugException {
- /*return fVariables.length > 0;*/
- return true;
+ if (!fUpToDate) {
+ getVariables();
+ }
+
+ return (varList.size() > 0);
+ }
+
+ public int getLineNumber() {
+ return fLineNumber;
}
-
+
/* (non-Javadoc)
- * @see org.eclipse.debug.core.model.IStackFrame#getLineNumber()
+ *
*/
- public int getLineNumber() throws DebugException {
- return fLineNumber;
+ public void setLineNumber(int line) {
+ fLineNumber = line;
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IStackFrame#getCharStart()
*/
public int getCharStart() throws DebugException {
return -1;
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IStackFrame#getCharEnd()
*/
public int getCharEnd() throws DebugException {
return -1;
}
-
+
/* (non-Javadoc)fName
* @see org.eclipse.debug.core.model.IStackFrame#getName()
*/
public String getName() throws DebugException {
- return fName.toString()+"::"+fWhere+ " line: "+ fLineNumber;
+ return fName.toString() + "::" + fWhere + " line: " + fLineNumber;
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IStackFrame#getRegisterGroups()
*/
public IRegisterGroup[] getRegisterGroups() throws DebugException {
return null;
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IStackFrame#hasRegisterGroups()
*/
public boolean hasRegisterGroups() throws DebugException {
return false;
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IStep#canStepInto()
*/
public boolean canStepInto() {
return fThread.canStepInto();
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IStep#canStepOver()
*/
public boolean canStepOver() {
return fThread.canStepOver();
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IStep#canStepReturn()
*/
public boolean canStepReturn() {
return fThread.canStepReturn();
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IStep#isStepping()
*/
public boolean isStepping() {
return fThread.isStepping();
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IStep#stepInto()
*/
public void stepInto() throws DebugException {
fThread.stepInto();
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IStep#stepOver()
*/
public void stepOver() throws DebugException {
fThread.stepOver();
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IStep#stepReturn()
*/
public void stepReturn() throws DebugException {
fThread.stepReturn();
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.ISuspendResume#canResume()
*/
public boolean canResume() {
return fThread.canResume();
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.ISuspendResume#canSuspend()
*/
public boolean canSuspend() {
return fThread.canSuspend();
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.ISuspendResume#isSuspended()
*/
public boolean isSuspended() {
return fThread.isSuspended();
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.ISuspendResume#resume()
*/
public void resume() throws DebugException {
fThread.resume();
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.ISuspendResume#suspend()
*/
public void suspend() throws DebugException {
fThread.suspend();
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.ITerminate#canTerminate()
*/
public boolean canTerminate() {
return fThread.canTerminate();
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.ITerminate#isTerminated()
*/
public boolean isTerminated() {
return fThread.isTerminated();
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.ITerminate#terminate()
*/
public void terminate() throws DebugException {
fThread.terminate();
}
-
+
/**
* Returns the name of the source file this stack frame is associated
* with.
- *
+ *
* @return the name of the source file this stack frame is associated
* with. If the file associated with this frame does not exists, it returns null.
*/
if (fName == null) {
return null;
}
+
IPath a = new Path(fName.getFile());
+
return a.lastSegment();
}
+ public String getFullSourceName() {
+ if (fName == null) {
+ return null;
+ }
+
+ IPath a = new Path(fName.getFile());
+
+ return a.toString ();
+ }
+
public boolean isSameStackFrame(Object obj) {
boolean isSameStackFrame = false;
-
+
if (obj instanceof XDebugStackFrame) {
- XDebugStackFrame sf = (XDebugStackFrame)obj;
- isSameStackFrame = sf.getSourceName().equals(getSourceName()) &&
- sf.getType().equals(getType()) &&
- sf.getWhere().equals(getWhere()); //&&
+ XDebugStackFrame sf = (XDebugStackFrame) obj;
+
+ isSameStackFrame = sf.getSourceName ().equals (getSourceName ()) &&
+ sf.getType().equals (getType ()) &&
+ sf.getWhere().equals (getWhere ());
}
return isSameStackFrame;
}
-
- /* (non-Javadoc)
- * @see java.lang.Object#equals(java.lang.Object)
- */
- public boolean equals(Object obj) {
- if (obj instanceof XDebugStackFrame) {
- XDebugStackFrame sf = (XDebugStackFrame)obj;
- try {
- return sf.getSourceName().equals(new Path(fName.getFile()).lastSegment()) &&
- sf.getLineNumber() == fLineNumber &&
- sf.getLevel() == fLevel &&
- sf.getType().equals(fType) &&
- sf.getWhere().equals(fWhere);
- } catch (DebugException e) {
- }
- }
- return false;
- }
-
- /* (non-Javadoc)
- * @see java.lang.Object#hashCode()
- */
- public int hashCode() {
- return getSourceName().hashCode() + fLevel;
- }
-
public URL getFullName() {
return fName;
}
+ public void setFullName (URL name) {
+ fName = name;
+ }
+
public int getLevel() {
return fLevel;
}
+ public void setLevel(int level) {
+ this.fLevel = level;
+ }
+
+
public String getType() {
return fType;
}
public boolean setVariableValue(XDebugVariable variable, String expression) throws DebugException {
return ((XDebugTarget) getDebugTarget()).setVarValue("$" + variable.getName(), expression);
}
-
- public Node eval(String expression) throws DebugException {
- return ((XDebugTarget) getDebugTarget()).eval(expression);
+
+ public Node eval(String expression) throws DebugException {
+ return ((XDebugTarget) getDebugTarget()).eval(expression);
+ }
+
+ /**
+ *
+ */
+ public void setAvailable(boolean available) {
+ fAvailable = available;
+ }
+
+ /**
+ *
+ */
+ public boolean isAvailable() {
+ return fAvailable;
+ }
+
+ public void setUpToDate (boolean bValue) {
+ this.fUpToDate = bValue;
+ }
+
+ public void setDescription(String desc) {
+ this.fWhere = desc;
+ }
+
+ public String getDescription() {
+ return this.fWhere;
+ }
+
+ /**
+ * This function is needed when sorting the stackframes by their index numbers.
+ *
+ * @param obj The stackframe which this one is compared to.
+ * @return
+ * <ul>
+ * <li> -1 if the index of this stackframe is less.
+ * <li> 0 if the index of both stackframes are equal (should no happen).
+ * <li> 1 if the index of this stackframe is greater.
+ * </ul>
+ */
+ public int compareTo(Object obj) {
+ if (!(obj instanceof XDebugStackFrame)) {
+ throw new IllegalArgumentException ("A PHPStackFrame can only be compared with another PHPStackFrame");
+ }
+
+ int frameLevel = ((XDebugStackFrame) obj).getLevel ();
+
+ if (fLevel < frameLevel) {
+ return -1;
+ } else if (fLevel > frameLevel) {
+ return 1;
+ }
+ return 0;
}
-}
\ No newline at end of file
+}
/**
- *
+ *
*/
package net.sourceforge.phpeclipse.xdebug.php.model;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
import net.sourceforge.phpeclipse.xdebug.core.IPHPDebugEvent;
import net.sourceforge.phpeclipse.xdebug.core.IProxyEventListener;
import net.sourceforge.phpeclipse.xdebug.core.IXDebugPreferenceConstants;
import org.eclipse.debug.core.model.IMemoryBlock;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.core.model.IThread;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.model.IWorkbenchAdapter;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
*/
public class XDebugTarget extends XDebugElement implements IDebugTarget, IDebugEventSetListener, IProxyEventListener {
private IProcess fProcess;
-
+
private ILaunch fLaunch;
-
+
private int fDebugPort;
-
+
private boolean fSuspended = false;
-
+
private boolean fTerminated = false;
-
+
private XDebugThread fThread;
private IThread[] fThreads;
-
+
private XDebugConnection fDebugConnection;
private ResponseListener fResponseListener;
/**
* Constructs a new debug target in the given launch and waits until
* someone with the ideKey connects to the Debugproxy
- *
- *
+ *
+ *
* @param launch containing launch
* @param process process of the interpreter
- * @param ideKey
+ * @param ideKey
* @exception CoreException if unable to connect to host
- */
+ */
public XDebugTarget(ILaunch launch, IProcess process, String ideKey) throws CoreException {
fLaunch = launch;
fProcess = process;
fThread = null;
fThreads = new IThread[0];
fIdeKey = ideKey;
-
- fDebugPort = XDebugCorePlugin.getDefault().getPreferenceStore().getInt(IXDebugPreferenceConstants.DEBUGPORT_PREFERENCE);
+
+ fDebugPort = XDebugCorePlugin.getDefault().getPreferenceStore().getInt(IXDebugPreferenceConstants.DEBUGPORT_PREFERENCE);
if (fDebugPort == 0) {
fDebugPort = IXDebugPreferenceConstants.DEFAULT_DEBUGPORT;
}
-
+
DebugPlugin.getDefault().getBreakpointManager().addBreakpointListener(this);
DebugPlugin.getDefault().addDebugEventListener(this);
}
+ public Object getAdapter(Class arg0) {
+ if (IWorkbenchAdapter.class.equals(arg0)) {
+ return new IWorkbenchAdapter() {
+ public Object[] getChildren(Object o) {
+ Object[] children = null;
+ IThread[] threads = getThreads();
+ if (null != threads) {
+ children = new Object[threads.length];
+ for (int i = 0; i < threads.length; ++i)
+ children[i] = threads[i];
+ }
+ return children;
+ }
+
+ public ImageDescriptor getImageDescriptor(Object object) {
+ return null;
+ }
+
+ public String getLabel(Object o) {
+ String label = "(Unable to look up name... check error log)";
+ try {
+ label = getName();
+ } catch (DebugException x) {
+ PHPeclipsePlugin.log(label, x);
+ }
+ return label;
+ }
+
+ public Object getParent(Object o) {
+ return XDebugTarget.this.getLaunch();
+ }
+ };
+ }
+ else {
+ if (arg0 == XDebugElement.class) {
+ return this;
+ }
+
+ return super.getAdapter(arg0);
+ }
+ }
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IDebugTarget#getProcess()
*/
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IDebugTarget#getThreads()
*/
- public IThread[] getThreads() throws DebugException {
+ public IThread[] getThreads() {
return fThreads;
}
* @see org.eclipse.debug.core.model.IDebugTarget#supportsBreakpoint(org.eclipse.debug.core.model.IBreakpoint)
*/
public boolean supportsBreakpoint(IBreakpoint breakpoint) {
- if (breakpoint.getModelIdentifier().equals(IXDebugConstants.ID_PHP_DEBUG_MODEL)) {
+ if (breakpoint.getModelIdentifier().equals(IXDebugConstants.ID_PHP_BREAKPOINT_MODEL)) {
return true;
}
return false;
if(fTerminated) {
return;
}
-
+
if (XDebugCorePlugin.getDefault() != null) {
XDebugProxy proxy = XDebugCorePlugin.getDefault().getXDebugProxy();
proxy.removeProxyEventListener(this, fIdeKey);
-
+
System.out.println("XDebug.Target: ProxyEventlistener removed");
-
+
fTerminated = true;
fSuspended = false;
-
+
XDebugCorePlugin.getBreakpointManager().removeBreakpointListener(this);
fireEvent(new DebugEvent(this, DebugEvent.TERMINATE));
DebugPlugin.getDefault().removeDebugEventListener(this);
fThread.setBreakpoints(null);
resumed(DebugEvent.RESUME);
fDebugConnection.run();
- }
+ }
}
-
+
/**
* Notification the target has resumed for the given reason
- *
+ *
* @param detail reason for the resume
*/
private void resumed(int detail) {
fSuspended = false;
fThread.fireResumeEvent(detail);
}
-
+
/**
* Notification the target has suspended for the given reason
- *
+ *
* @param detail reason for the suspend
*/
public void suspended(int detail) {
fSuspended = true;
fThread.fireSuspendEvent(detail);
- }
-
+ }
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.ISuspendResume#suspend()
*/
* @see org.eclipse.debug.core.IBreakpointListener#breakpointAdded(org.eclipse.debug.core.model.IBreakpoint)
*/
public void breakpointAdded(IBreakpoint breakpoint) {
- IMarker marker = breakpoint.getMarker();
- IPath path = marker.getResource().getLocation();
- IPath cp = path.removeLastSegments(1);
- List pathMap = null;
+ IMarker marker = breakpoint.getMarker(); // Get the breakpoints marker info (It's the local workspace path)
+ IPath path = marker.getResource().getLocation(); // Get the full path + file for the given breakpoint (It's the local real path)
+ IPath cp = path.removeLastSegments(1); // Get the full path only (without the file name)
+ List pathMap = null;
+
try {
pathMap = fLaunch.getLaunchConfiguration().getAttribute(IXDebugConstants.ATTR_PHP_PATHMAP,(List)null);
} catch (CoreException e2) {
e2.printStackTrace();
}
- if (fDebugConnection != null)
- if (!fDebugConnection.isClosed()) {
- if (fProcess == null) {
- PathMapItem pmi = null;
- for (int i = 0; i < pathMap.size(); i++) {
- pmi = new PathMapItem((String) pathMap.get(i));
- IPath local = (IPath)pmi.getLocalPath().clone();
- local = local.makeAbsolute();
- int matchedSegments = local.segmentCount();
- if (local.matchingFirstSegments(cp) == matchedSegments) {
- IPath newPath = pmi.getRemotePath();
- newPath = newPath.append(path.removeFirstSegments(matchedSegments));
- newPath = newPath.makeAbsolute();
- if (supportsBreakpoint(breakpoint)) {
- try {
- if (breakpoint.isEnabled()) {
- if (marker != null) {
- int id = fDebugConnection.breakpointSet(newPath.toString(), ((ILineBreakpoint)breakpoint).getLineNumber(), marker.getAttribute(XDebugBreakpoint.HIT_COUNT,-1));
- XDebugResponse dr = getResponse(id);
-
- String bpid = dr.getAttributeValue("id");
-
- if (!"".equals(bpid))
- marker.setAttribute(XDebugLineBreakpoint.BREAKPOINT_ID,Integer.parseInt(bpid));
- }
+ if ((fDebugConnection != null) && // If there is a connection to XDebug
+ (!fDebugConnection.isClosed ()) && // and this connection is not closed
+ (fProcess == null)) { //
+ PathMapItem pmi = null;
+
+ for (int i = 0; i < pathMap.size(); i++) { // For every path map pair the user have set
+ pmi = new PathMapItem((String) pathMap.get(i)); // Get the path map pair
+ IPath local = (IPath)pmi.getLocalPath().clone(); // Get the local
+ local = local.makeAbsolute();
+ int matchedSegments = local.segmentCount();
+
+ if (local.matchingFirstSegments(cp) == matchedSegments) {
+ IPath newPath = pmi.getRemotePath();
+ newPath = newPath.append(path.removeFirstSegments(matchedSegments));
+ newPath = newPath.makeAbsolute();
+
+ if (supportsBreakpoint(breakpoint)) {
+ try {
+ if (breakpoint.isEnabled()) {
+ if (marker != null) {
+ int id = fDebugConnection.breakpointSet(newPath.toString(), ((ILineBreakpoint)breakpoint).getLineNumber(), marker.getAttribute(XDebugBreakpoint.HIT_COUNT,-1));
+ XDebugResponse dr = getResponse(id);
+
+ String bpid = dr.getAttributeValue("id");
+
+ if (!"".equals(bpid))
+ marker.setAttribute(XDebugLineBreakpoint.BREAKPOINT_ID,Integer.parseInt(bpid));
}
- } catch (DebugException e) {
- e.printStackTrace();
- } catch (CoreException e) {
- e.printStackTrace();
}
+ } catch (DebugException e) {
+ e.printStackTrace();
+ } catch (CoreException e) {
+ e.printStackTrace();
}
}
- }
- } else {
- if (supportsBreakpoint(breakpoint)) {
- try {
- if (breakpoint.isEnabled()) {
- if (marker != null) {
- int id = fDebugConnection.breakpointSet(path.toString(), ((ILineBreakpoint)breakpoint).getLineNumber(), marker.getAttribute(XDebugBreakpoint.HIT_COUNT,-1));
- XDebugResponse dr = getResponse(id);
- String bpid = dr.getAttributeValue("id");
-
- if (!"".equals(bpid))
- marker.setAttribute(XDebugLineBreakpoint.BREAKPOINT_ID,Integer.parseInt(bpid));
+ }
+ }
+ } else {
+ if (supportsBreakpoint(breakpoint)) {
+ try {
+ if (breakpoint.isEnabled()) {
+ if (marker != null) {
+ int id = fDebugConnection.breakpointSet (path.toString(),
+ ((ILineBreakpoint) breakpoint).getLineNumber(),
+ marker.getAttribute (XDebugBreakpoint.HIT_COUNT, -1));
+ XDebugResponse dr = getResponse(id);
+ String bpid = dr.getAttributeValue("id");
+
+ if (!"".equals(bpid)) {
+ marker.setAttribute(XDebugLineBreakpoint.BREAKPOINT_ID,Integer.parseInt(bpid));
}
}
- } catch (DebugException e) {
- e.printStackTrace();
- } catch (CoreException e) {
- e.printStackTrace();
}
+ } catch (DebugException e) {
+ e.printStackTrace();
+ } catch (CoreException e) {
+ e.printStackTrace();
}
}
}
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.IBreakpointListener#breakpointRemoved(org.eclipse.debug.core.model.IBreakpoint, org.eclipse.core.resources.IMarkerDelta)
*/
if (response2.getAttributeValue("success").equals("1") ) {
System.out.println("Set children to 1024 (hack)");
}
-
+
installDeferredBreakpoints();
try {
resume();
e.printStackTrace();
}
}
-
+
/**
* Install breakpoints that are already registered with the breakpoint
* manager.
breakpointAdded(breakpoints[i]);
}
}
-
+
/**
* Returns the current stack frames in the target.
- *
+ *
* @return the current stack frames in the target
* @throws DebugException if unable to perform the request
*/
XDebugResponse lastResponse = getResponse(id);
return lastResponse;
}
-
+
/**
* Single step the interpreter.
- *
+ *
* @throws DebugException if the request fails
*/
protected void step_over() throws DebugException {
resumed(DebugEvent.STEP_OVER);
fDebugConnection.stepOver();
}
-
+
/**
* Single step the interpreter.
- *
+ *
* @throws DebugException if the request fails
*/
protected void step_into() throws DebugException {
resumed(DebugEvent.STEP_INTO);
fDebugConnection.stepInto();
}
-
+
/**
* Single step the interpreter.
- *
+ *
* @throws DebugException if the request fails
*/
protected void step_out() throws DebugException {
resumed(DebugEvent.STEP_RETURN);
fDebugConnection.stepOut();
}
-
+
public boolean setVarValue(String name, String value) {
int id = fDebugConnection.setVarValue(name,value);
XDebugResponse response = getResponse(id);
-
+
if ((response.getAttributeValue("success")).equals("1")) {
return true;
} else {
return false;
}
}
-
+
public Node eval(String expression) throws DebugException {
Node evalProperty = null;
if (fDebugConnection != null) {
//Node evalProperty = new Node("");
//if (id > 0) {
XDebugResponse response = getResponse(id);
-
+
Node evalResponse = response.getParentNode();
/*Node*/ evalProperty = evalResponse.getFirstChild();
//} /*else {
-
+
//}*/
} else {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
Document doc = null;
-
+
try {
builder = factory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}*/
}
-
+
return evalProperty;
}
-
+
public void handleDebugEvents(DebugEvent[] events) {
for (int i = 0; i < events.length; i++) {
DebugEvent event = events[i];
-
+
if (fResponseListener != null) {
Object s = null;
s = event.getSource();
} else {
return;
}
-
+
if (event.getKind() == DebugEvent.MODEL_SPECIFIC) {
switch (event.getDetail()) {
case IPHPDebugEvent.BREAKPOINT_HIT:
XDebugResponse lastResponse = getResponse(id);
IBreakpoint breakpoint = breakpointHit(lastResponse.getParentNode());
-
+
if (breakpoint != null) {
fThread.setBreakpoints(new IBreakpoint[]{breakpoint});
fThread.incrementStepCounter();
}
}
}
-
+
public void stopped() {
if(fDebugConnection == null) {
return;
fDebugConnection = null;
fireEvent(new DebugEvent(this, DebugEvent.CHANGE, DebugEvent.CONTENT));
}
-
+
fThread.removeEventListeners();
fThread = null;
fThreads = new IThread[0];
}
-
+
public void handleProxyEvent(XDebugConnection connection) {
//System.out.println("* New Connection - XDebug.Target: " + fDebugConnection.getSessionID());
-
+
if (setDebugConnection(connection)) {
fThread = new XDebugThread(this);
fThreads = new IThread[] {fThread};
try {
started();
} catch( DebugException e ){
- e.printStackTrace();
+ e.printStackTrace();
}
}
}
fDebugConnection = connection;
fResponseListener = new ResponseListener(connection);
startListener();
-
+
return true;
} else {
connection.close();
-
+
return false;
}
}
-
+
/**
* @return Returns the fDebugConnection.
*/
public XDebugConnection getDebugConnection() {
return fDebugConnection;
- }
-
+ }
+
public void addProcess(IProcess p) {
fProcess = p;
public Node getLocalVariables(int level) throws DebugException {
int id = fDebugConnection.contextGet(level, 0);
XDebugResponse response = getResponse(id);
-
+
return response.getParentNode();
}
-
+
public Node getGlobalVariables(int level) throws DebugException {
int id = fDebugConnection.contextGet(level, 1);
XDebugResponse response = getResponse(id);
-
+
return response.getParentNode();
}
-
+
public void stop() {
fDebugConnection.stop();
}
-
+
protected IBreakpoint breakpointHit(Node node) {
Node child = node.getFirstChild();
if (child.getNodeName().equals("stack")) {
int lineNumber = Integer.parseInt(PHPDebugUtils.getAttributeValue(child, "lineno"));
- String filename = PHPDebugUtils.getAttributeValue(child, "filename");
+ String filename = PHPDebugUtils.getAttributeValue(child, "filename");
IBreakpoint[] breakpoints = XDebugCorePlugin.getBreakpoints();
for (int i = 0; i < breakpoints.length; i++) {
IBreakpoint breakpoint = breakpoints[i];
if (supportsBreakpoint(breakpoint)) {
if (breakpoint instanceof ILineBreakpoint) {
ILineBreakpoint lineBreakpoint = (ILineBreakpoint) breakpoint;
- try {
+ try {
if (breakpoint.isEnabled()) {
IMarker marker = breakpoint.getMarker();
if (marker != null) {
String endfilename;
-
+
if (getProcess() == null) {
- endfilename = marker.getResource().getLocation().lastSegment();
+ endfilename = marker.getResource().getLocation().lastSegment();
} else {
endfilename = marker.getResource().getLocation().toOSString();
}
-
+
int id = fDebugConnection.breakpointGet(marker.getAttribute(XDebugLineBreakpoint.BREAKPOINT_ID,-1));
XDebugResponse dr = getResponse(id);
-
+
Node hitCo = dr.getParentNode().getFirstChild();
int hitCount = 0;
if (hitCo.hasAttributes()) {
&& (lineBreakpoint.getLineNumber() == lineNumber) ) {
if (marker.getAttribute(XDebugLineBreakpoint.HIT_COUNT, 0) > 0) {
if (marker.getAttribute(XDebugLineBreakpoint.HIT_COUNT, 0) == hitCount) {
- return (breakpoint);
+ return (breakpoint);
}
} else {
return (breakpoint);
}
}
}
-
+
return null;
}
-
+
public void startListener() {
fResponseListener.schedule();
}
-
+
public void stopListener() {
fResponseListener.cancel();
}
return response;
}
-}
\ No newline at end of file
+}
*/
package net.sourceforge.phpeclipse.xdebug.php.model;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Vector;
+
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
import net.sourceforge.phpeclipse.xdebug.core.PHPDebugUtils;
import net.sourceforge.phpeclipse.xdebug.core.xdebug.XDebugResponse;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.core.model.IStackFrame;
import org.eclipse.debug.core.model.IThread;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.model.IWorkbenchAdapter;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
*/
public class XDebugThread extends XDebugElement implements IThread, IDebugEventSetListener {
private XDebugStackFrame[] fStackFrames;
-
- private IBreakpoint[] fBreakpoints;
-
- /* Whether this thread is stepping */
- private boolean fStepping = false;
- private boolean fTerminated = false;
-
- private int fStepCount = 0;
- private int fCurrentStepCount = 0;
-
+ private IBreakpoint[] fBreakpoints;
+
+ private boolean fStepping = false; // Whether this thread is stepping
+ private boolean fTerminated = false;
+
+ private int fStepCount = 0;
+ private int fCurrentStepCount = 0;
+
+ private Vector stackListOld = new Vector(); // The 'static' list of stack frames
+
/**
* Constructs a new thread for the given target
- *
+ *
* @param target VM
*/
public XDebugThread(XDebugTarget target) {
DebugPlugin.getDefault().addDebugEventListener(this);
fStackFrames = null;
}
-
+
+ /**
+ *
+ */
+ public void setStackFrames (XDebugStackFrame[] frames) {
+ this.fStackFrames = frames;
+ }
+
public void incrementStepCounter() {
fStepCount++;
}
+
+ /**
+ *
+ * @param arg0
+ * @return
+ */
+ public Object getAdapter (Class arg0) {
+ if (IWorkbenchAdapter.class.equals (arg0)) {
+ return new IWorkbenchAdapter() {
+ public Object[] getChildren(Object o) {
+ try {
+ return getStackFrames ();
+ } catch (DebugException x) {
+ PHPeclipsePlugin.log ("Unable to get stack frames.", x);
+ }
+
+ return new Object[0];
+ }
+
+ public ImageDescriptor getImageDescriptor(Object object) {
+ return null;
+ }
+
+ public String getLabel(Object o) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Object getParent(Object o) {
+ return getDebugTarget();
+ }
+ };
+ }
+ return super.getAdapter(arg0);
+ }
+
+ /**
+ * Reset the availability flag for all stackframes in the list.
+ *
+ * @param list The list of old stackframes
+ */
+ private void resetAvailability (Vector list) {
+ int i;
+
+ for (i = 0; i < list.size (); i++) {
+ ((XDebugStackFrame) list.get(i)).setAvailable (false); //
+ }
+ }
+
+ /**
+ * Check whether the new stackframe is in the list of old stackframes.
+ * Test for identical stackframe (identical means same description and same line number).
+ *
+ * @param stackFrameNew The stackframe to check whether he is already within the old stackframe list
+ * @param list The list of old stackframes
+ * @return
+ * - true if we have found the identical stackframe within the list
+ * - false if we did not find the identical stackframe within the list
+ */
+ private boolean isStackFrameInList (XDebugStackFrame stackFrameNew, Vector list) {
+ int i;
+ XDebugStackFrame stackFrameOld;
+
+ for (i = 0; i < list.size (); i++) {
+ stackFrameOld = (XDebugStackFrame) list.get (i); //
+
+ if (stackFrameNew.getFullName ().equals (stackFrameOld.getFullName ()) &&
+ stackFrameNew.getDescription ().equals (stackFrameOld.getDescription ()) &&
+ stackFrameNew.getLineNumber () == stackFrameOld.getLineNumber ()) { // Did we find the sent stackframe within the list of old stackframes?
+ stackFrameOld.setAvailable (true); // We found the new stackframe in the list of old stack frames
+ stackFrameOld.setLevel (stackFrameNew.getLevel ());
+ stackFrameOld.setUpToDate (false); // Need to update the variables
+
+ return true; // The stackframe was found in the list
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Check whether the new stackframe is in the list of old stackframes.
+ * Test for exact stackframe (exact means same description and same line number).
+ *
+ * @param stackFrameNew The stackframe to check whether he is already within the old stackframe list
+ * @param list The list of old stackframes
+ * @return
+ * - true if we have exactly this stackframe within the list
+ * - false if we did not find the exact stackframe within the list
+ */
+ private void markIdenticalStackFrames (Vector oldList, Vector newList) {
+ int i;
+ XDebugStackFrame stackFrameNew;
+
+ resetAvailability (oldList); // Reset the availability flag of the old stack frames
+ resetAvailability (newList); // Reset the availability flag of the old stack frames
+
+ for (i = 0; i < newList.size (); i++) { // For all stackList entries
+ stackFrameNew = (XDebugStackFrame) newList.get (i);
+
+ if (isStackFrameInList (stackFrameNew, oldList)) { // Is this stackframe in the list
+ stackFrameNew.setAvailable (true); //
+ //
+// break;
+ }
+ }
+ }
+
+ /**
+ *
+ * The stackList contains the currently read stackframes which were sent
+ * from DBG. The DBG interface holds a list of the active stack frames.
+ * This method replicates the 'static' stackframe list with the DBG stackframe list
+ * Replication is done in the following way:
+ * <ul>
+ * <li> It looks for new stackframes within the DBG stackframe list and
+ * adds them to the 'static' list.
+ * <li> It looks for stackframes within the 'static' list, and removes them
+ * from the 'static' list in case they do not appear within the DBG list.
+ * <li> It looks for stackframes which are already existent and replicates the
+ * line number and the index number.
+ * <li> At the end, the 'static' stackframe list has to be sorted by the stackframes
+ * index numbers.
+ * </ul>
+ *
+ * Removes the unused stackframes from the list, or adds stackframes which
+ * are not yet in the list.
+ *
+ *
+ * @param stackList
+ */
+ private void updateStackFrameList (Vector stackList) {
+ int i;
+ int n;
+ XDebugStackFrame stackFrameNew;
+ XDebugStackFrame stackFrameOld;
+ XDebugStackFrame[] newStackList;
+
+ markIdenticalStackFrames (stackListOld, stackList); // Check whether the newly send stack frames can be found in the list
+ // of old stack frames
+
+ for (i = 0; i < stackList.size (); i++) { // For all stackList entries
+ stackFrameNew = (XDebugStackFrame) stackList.get(i);
+
+ for (n = 0; n < stackListOld.size (); n++) { // For all StackFrames in the StackFrame list
+ stackFrameOld = (XDebugStackFrame) stackListOld.get (n); //
+
+ if (stackFrameOld.isAvailable ()) { // If this stack frame was already found in the new list skip it
+ continue;
+ }
+
+ if (stackFrameNew.getFullName ().equals (stackFrameOld.getFullName ()) && // Did we find the sent stackframe within the list of old stackframes?
+ stackFrameNew.getDescription ().equals (stackFrameOld.getDescription ())) {// Did we find the sent stackframe within the list of old stackframes?
+ stackFrameOld.setLineNumber (stackFrameNew.getLineNumber ());
+ stackFrameOld.setLevel (stackFrameNew.getLevel ());
+ stackFrameOld.setUpToDate (false); // Need to update the variables
+
+ stackFrameOld.setAvailable (true); // And mark this stack frame as available
+ stackFrameNew.setAvailable (true); // And mark this stack frame as available
+
+ break; // Yes, then break;
+ }
+ }
+
+ if (!stackFrameNew.isAvailable ()) { // Did not find the new stackframe within the list?
+ stackFrameNew.setAvailable (true); // Mark the stack frame as available and
+ stackListOld.add (stackFrameNew); // then add the new stackframe
+ }
+ }
+
+ // And now for removing unused stackframes from list
+
+ for (n = 0; n < stackListOld.size(); n++) {
+ stackFrameOld = (XDebugStackFrame) stackListOld.get(n);
+
+ if (!stackFrameOld.isAvailable()) {
+ stackListOld.remove(n--);
+ }
+ }
+
+ Collections.sort (stackListOld); // Sort the 'static' stackframe list by the stackframe index numbers.
+ //
+ newStackList = new XDebugStackFrame[stackListOld.size ()];
+ newStackList = (XDebugStackFrame[]) stackListOld.toArray (newStackList);
+
+// DBGStackList = newStackList;
+ fStackFrames = newStackList;
+ }
+
+
public IStackFrame[] getStackFrames() throws DebugException {
if (!isSuspended()) {
return new IStackFrame[0];
}
-
- if (fStepCount > fCurrentStepCount) {
- XDebugResponse dr = ((XDebugTarget) getDebugTarget()).getStackFrames();
- XDebugStackFrame[] newStackFrames = _getStackFrames(dr);
-
- /*if (fStackFrames != null) {
- if (newStackFrames.length >= fStackFrames.length) {
- int delta = newStackFrames.length - fStackFrames.length + 1;
-
- for (int i = fStackFrames.length - 1; i >= 0; i--) {
- if (fStackFrames[i].equals(newStackFrames[newStackFrames.length - delta])) {
- int b = 2; b++;
- //((XDebugStackFrame) newStackFrames[newStackFrames.length - delta]).evaluateChange((XDebugStackFrame) fStackFrames[i]);
- } else if (fStackFrames[i].isSameStackFrame(newStackFrames[newStackFrames.length - delta])) {
- int b = 2; b++;
- //((XDebugStackFrame) newStackFrames[newStackFrames.length - delta]).evaluateChange((XDebugStackFrame) fStackFrames[i]);
- }
-
- delta ++;
- }
- } else {
- fStackFrames = newStackFrames;
- }
- } else {
- fStackFrames = newStackFrames;
- }*/
- fCurrentStepCount++;
+ if (fStepCount > fCurrentStepCount) { // Do we need to update the list of stackframes
+ XDebugResponse dr = ((XDebugTarget) getDebugTarget()).getStackFrames(); // Get the stackframes list from XDebug
+ XDebugStackFrame[] newStackFrames = _getStackFrames(dr); // Parse the stackframes list
+
+ updateStackFrameList (new Vector (Arrays.asList(newStackFrames))); // update the 'static' list of stackframes
- fStackFrames = newStackFrames;
+ fCurrentStepCount++; //
}
return fStackFrames;
}
-
-
+
+
private XDebugStackFrame[] _getStackFrames(XDebugResponse lastResponse) {
if (lastResponse.isError()) {
return new XDebugStackFrame[0];
}
-
- Node response = lastResponse.getParentNode();
- NodeList frames = response.getChildNodes();
- XDebugStackFrame[] theFrames = new XDebugStackFrame[frames.getLength()];
-
+
+ Node response = lastResponse.getParentNode();
+ NodeList frames = response.getChildNodes();
+ XDebugStackFrame[] theFrames = new XDebugStackFrame[frames.getLength()];
+
for (int i = 0; i < frames.getLength(); i++) {
- Node stackNode = frames.item(i);
- String fileName=PHPDebugUtils.unescapeString(PHPDebugUtils.getAttributeValue(stackNode,"filename"));
- String lineNo = PHPDebugUtils.getAttributeValue(stackNode,"lineno");
-
- XDebugStackFrame frame = new XDebugStackFrame(this/*fThread*/, i, /*type*/PHPDebugUtils.getAttributeValue(stackNode,"type"), /*lineno*/Integer.parseInt(lineNo), /*where*/PHPDebugUtils.getAttributeValue(stackNode,"where"), fileName);
-
+ Node stackNode = frames.item(i);
+ String fileName = PHPDebugUtils.unescapeString(PHPDebugUtils.getAttributeValue(stackNode,"filename"));
+ String lineNo = PHPDebugUtils.getAttributeValue(stackNode,"lineno");
+
+ XDebugStackFrame frame = new XDebugStackFrame (this,
+ i,
+ PHPDebugUtils.getAttributeValue(stackNode,"type"),
+ Integer.parseInt(lineNo),
+ PHPDebugUtils.getAttributeValue(stackNode,"where"),
+ fileName);
+
frame.incrementStepCounter();
-
+
theFrames[i] = frame;
}
return theFrames;
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IThread#hasStackFrames()
*/
public boolean hasStackFrames() throws DebugException {
- return isSuspended();
+ if (fStackFrames == null) {
+ return false;
+ }
+
+ return fStackFrames.length > 0;
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IThread#getPriority()
*/
public int getPriority() throws DebugException {
return 0;
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IThread#getTopStackFrame()
*/
if (frames.length > 0) {
return frames[0];
}
-
- return null;
+
+ return null;
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IThread#getName()
*/
}
return fBreakpoints;
}
-
+
/**
* Sets the breakpoints this thread is suspended at, or <code>null</code>
* if none.
- *
+ *
* @param breakpoints the breakpoints this thread is suspended at, or <code>null</code>
* if none
*/
protected void setBreakpoints(IBreakpoint[] breakpoints) {
fBreakpoints = breakpoints;
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.ISuspendResume#canResume()
*/
public boolean canResume() {
return isSuspended();
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.ISuspendResume#canSuspend()
*/
public boolean canSuspend() {
return !isTerminated() && !isSuspended();
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.ISuspendResume#isSuspended()
*/
public boolean isSuspended() {
return getDebugTarget().isSuspended();
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.ISuspendResume#resume()
*/
fBreakpoints = null;
getDebugTarget().resume();
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.ISuspendResume#suspend()
*/
public void suspend() throws DebugException {
getDebugTarget().suspend();
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IStep#canStepInto()
*/
public boolean canStepInto() {
return isSuspended();
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IStep#canStepOver()
*/
public boolean canStepOver() {
return isSuspended();
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IStep#canStepReturn()
*/
((XDebugTarget) getDebugTarget()).getDebugConnection().stop();
fTerminated = true;
}
-
+
public void terminated() throws DebugException {
fTerminated = true;
}
/**
* Sets whether this thread is stepping
- *
+ *
* @param stepping whether stepping
*/
protected void setStepping(boolean stepping) {
public void handleDebugEvents(DebugEvent[] events) {
DebugEvent de = events[0];
- System.out.println(de.toString());
+ System.out.println(de.toString());
}
public void removeEventListeners() {
DebugPlugin.getDefault().removeDebugEventListener(this);
}
-
+
/**
* Fires a <code>RESUME</code> event for this element with
* the given detail.
- *
+ *
* @param detail event detail code
*/
public void fireResumeEvent(int detail) {
/**
* Fires a <code>SUSPEND</code> event for this element with
* the given detail.
- *
+ *
* @param detail event detail code
*/
- public void fireSuspendEvent(int detail) {
- fireEvent(new DebugEvent(this, DebugEvent.SUSPEND, detail));
+ public void fireSuspendEvent (int detail) {
+ fireEvent (new DebugEvent (this, DebugEvent.SUSPEND, detail));
}
-}
\ No newline at end of file
+}
* Window - Preferences - Java - Code Style - Code Templates
*/
public class XDebugVariable extends XDebugElement implements IVariable {
- private String fName;
- private XDebugStackFrame fFrame;
+ private String fName;
+ private XDebugStackFrame fFrame;
private XDebugAbstractValue fValue;
- private String fFacet;
+ private String fFacet;
+ private XDebugVariable fParent; // The parent variable (a back link)
+
/**
* Constructs a variable contained in the given stack frame
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IVariable#getValue()
*/
- public IValue getValue() throws DebugException {
+ public IValue getValue() {
return fValue;
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IVariable#getName()
*/
- public String getName() throws DebugException {
+ public String getName() {
return fName;
}
public void setValue(IValue value) throws DebugException {
}
+ /**
+ *
+ * @param changed This method is called after a suspend when the list of
+ * variables is updated, to mark that this variable has a changed
+ * value. The variable view will show this variable in
+ * a different color.
+ */
+ public void setValueChanged(boolean changed) {
+ fValue.setChanged(changed);
+ }
+
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IValueModification#supportsValueModification()
*/
public String getVisibility() {
return fFacet;
}
+
+ /**
+ *
+ */
+ public XDebugVariable getParent() {
+ return fParent;
+ }
+
+ /**
+ *
+ */
+ public void setParent(XDebugVariable parent) {
+ this.fParent = parent;
+ }
}
\ No newline at end of file
--- /dev/null
+package net.sourceforge.phpeclipse.xdebug.php.model;\r
+\r
+import java.util.Comparator;\r
+\r
+public class XDebugVariableComparator implements Comparator {\r
+\r
+ public int compare (Object arg0, Object arg1) {\r
+ XDebugVariable left = (XDebugVariable) arg0;\r
+ XDebugVariable right = (XDebugVariable) arg1;\r
+ \r
+ return left.getName ().compareTo (right.getName ());\r
+ }\r
+\r
+}\r