X-Git-Url: http://secure.phpeclipse.com
diff --git a/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/model/PHPStackFrame.java b/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/model/PHPStackFrame.java
index 4130898..bbebc6a 100644
--- a/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/model/PHPStackFrame.java
+++ b/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/model/PHPStackFrame.java
@@ -11,6 +11,8 @@ Contributors:
**********************************************************************/
package net.sourceforge.phpdt.internal.debug.core.model;
+import java.util.Vector;
+
import net.sourceforge.phpdt.internal.debug.core.PHPDBGProxy;
import org.eclipse.debug.core.DebugEvent;
@@ -23,15 +25,22 @@ import org.eclipse.debug.core.model.IStackFrame;
import org.eclipse.debug.core.model.IThread;
import org.eclipse.debug.core.model.IVariable;
-public class PHPStackFrame extends PHPDebugElement implements IStackFrame {
+/**
+ *
+ * TODO Remove the variables array and use only the varList vector
+ * Have also to change hasVariables
+ */
+public class PHPStackFrame extends PHPDebugElement implements IStackFrame, Comparable{
private PHPThread thread; // The thread to which this stackframe belongs
private String file; // The file name???
private int lineNumber; //
private int index; //
private int modno; //
- private PHPVariable[] variables; // The array of variables
- private String description; //
+ private PHPVariable[] variables; // The array of variables TODO: better introduce a vector?
+ private Vector varList = new Vector ();
+ private String description; // The source file name with the full path on target/remote system
+ private boolean fUpToDate; //
/**
*
@@ -51,6 +60,7 @@ public class PHPStackFrame extends PHPDebugElement implements IStackFrame {
this.thread = thread;
this.description = desc;
this.modno = modno;
+ this.fUpToDate = false;
}
/**
@@ -67,6 +77,7 @@ public class PHPStackFrame extends PHPDebugElement implements IStackFrame {
this.index = index;
this.file = file;
this.thread = thread;
+ this.fUpToDate = false;
}
/**
@@ -85,6 +96,177 @@ public class PHPStackFrame extends PHPDebugElement implements IStackFrame {
/**
*
+ */
+ private void setUpToDate (boolean upToDate) {
+ fUpToDate = upToDate;
+ }
+
+ /**
+ *
+ */
+ private boolean isUpToDate () {
+ return fUpToDate;
+ }
+
+ /**
+ *
+ *
+ */
+ private void resetHasChangedInfo (Vector varList) {
+ int n;
+ PHPVariable var;
+ PHPValue val;
+
+ for (n = 0; n < varList.size (); n++) { // For every variable in 'DBG list'
+ var = (PHPVariable) varList.get (n); // Get the variable
+ val = (PHPValue) 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.
+ *
+ * @param var
+ * @return
+ *
+ * - false if the PHPValue is not a child of itself
+ *
- true if the PHPValue is
+ *
+ */
+ private boolean hasRecursion (PHPVariable var) {
+ PHPVariable parentVar;
+ PHPValue val;
+
+ val = (PHPValue) 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:
+ *
+ * - It looks for new variables within the DBG variables list and
+ * adds them to the 'static' list.
+ *
- 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).
+ *
- 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.
+ *
+ *
+ * @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)
+ {
+ PHPVariable varOld; // The variable from the 'static' list
+ PHPVariable varNew; // The variable from the DBG list
+ PHPValue valOld; // The value of the current variable from 'static' list
+ PHPValue 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 = (PHPVariable) varListNew.get (n); // Get the DBG variable
+
+ for (o = 0; o < varListOld.size (); o++) { // For every variable in static list
+ varOld = (PHPVariable) varListOld.get (o); // Get the static variable
+
+ if (varNew.getName ().equals (varOld.getName ())) { // Did we found the variable within the 'static' list?
+ valOld = (PHPValue) varOld.getValue (); // Get the value from 'static'
+ valNew = (PHPValue) 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 ());
+ }
+ }
+ else 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
+ }
+ //else {
+ // varOld.setValueChanged (false); // Reset the 'has changed' flag
+ //}
+ }
+ 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 = (PHPVariable) varListOld.get (o); // Get the static variable
+
+ for (n = 0; n < varListNew.size (); n++) { // For all variables in 'DBG' list
+ varNew = (PHPVariable) 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
+ o -= 1; // Adjust the 'static' list index
+ }
+ }
+ }
+
+
+ /**
+ *
* This function returns the array of PHPVariables for this stackframe
* The PHPVariables should not change (newly build up) between two steps
* (or breaks).
@@ -98,45 +280,77 @@ public class PHPStackFrame extends PHPDebugElement implements IStackFrame {
public IVariable[] getVariables() throws DebugException {
PHPVariable[] variablesNew; // The intermediate storage of the variable array we get from DBG proxy
- variablesNew = this.getPHPDBGProxy ().readVariables (this); // Get the variable array from DBG proxy
- variables = variablesNew; // Store the array the stackframes member variable
+ //variablesNew = this.getPHPDBGProxy ().readVariables (this); // Get the variable array from DBG proxy
+ //variables = variablesNew; // Store the array the stackframes member variable
+
+ if (!isUpToDate ()) {
+ resetHasChangedInfo (varList);
+ updateVariableList (varList, this.getPHPDBGProxy ().readVariables (this));
+ setUpToDate (true);
+
+ variables = (PHPVariable[]) varList.toArray (new PHPVariable[varList.size ()]);
+ }
return variables; // Give the array back to user interface
}
/**
- * TODO Is this really used (who calls this)
- * I think this method could be removed
*
- * @param s The variables name we are looking for.
- * @return
*/
- public IVariable findVariable (String s) throws DebugException {
- String name;
- int i;
-
- if (this.hasVariables ()) { // Does this stackframe have variables?
- name = "$" + s; // Prefix the variable name with $
-
- for (i = 0; i < variables.length; i++) { // For all variables
- if ((variables[i].getName ()).equals (name)) {
- return variables[i];
+ private PHPVariable findVariable (Vector varList, String varname) {
+ PHPVariable variable;
+ PHPValue value;
+ int i;
+
+ for (i = 0; i < varList.size (); i++) { // For all variables
+ variable = (PHPVariable) varList.get (i); // Get the variable
+ value = (PHPValue) 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
+ variable = findVariable (value.getChildVariables (), varname);
+
+ if (variable != null) {
+ return variable;
+ }
+ }
+ }
+ else 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 boolean hasVariables () throws DebugException {
- if (variables == null) { // Do we have a variables array?
- return false; // No
+ public IVariable findVariable (String s) throws DebugException {
+ if (!isUpToDate ()) {
+ resetHasChangedInfo (varList);
+ updateVariableList (varList, this.getPHPDBGProxy ().readVariables (this));
+ setUpToDate (true);
+
+ variables = (PHPVariable[]) varList.toArray (new PHPVariable[varList.size ()]);
}
- return variables.length > 0; // Is there something within the array?
+ return (findVariable (varList, s)); // Prefix the variable name with $
+ }
+
+ /**
+ *
+ */
+ public boolean hasVariables () throws DebugException {
+ return (varList.size () > 0);
}
public int getLineNumber() {
@@ -158,10 +372,20 @@ public class PHPStackFrame extends PHPDebugElement implements IStackFrame {
}
public String getName() {
- if(!this.getDescription().equals(""))
- return this.getDescription() + " [line: " + this.getLineNumber() + "]";
- else
- return this.getFileName() + " [line: " + this.getLineNumber() + "]";
+ StringBuffer name = new StringBuffer();
+
+ if (!this.getDescription().equals ("")) {
+ name.append (this.getDescription ());
+ }
+ else {
+ name.append (this.getFileName ());
+ }
+
+ name.append (" [line ");
+ name.append (this.getLineNumber ());
+ name.append ("]");
+
+ return name.toString();
}
public String getFileName() {
@@ -218,6 +442,8 @@ public class PHPStackFrame extends PHPDebugElement implements IStackFrame {
public void stepInto () throws DebugException {
DebugEvent ev;
+ setUpToDate (false);
+
thread.prepareForResume (DebugEvent.STEP_INTO); // Don't know why, but this is necessary
this.getPHPDBGProxy ().readStepIntoEnd (PHPStackFrame.this);
@@ -231,6 +457,8 @@ public class PHPStackFrame extends PHPDebugElement implements IStackFrame {
public void stepOver () throws DebugException {
DebugEvent ev;
+ setUpToDate (false);
+
thread.prepareForResume (DebugEvent.STEP_OVER);
this.getPHPDBGProxy ().readStepOverEnd (PHPStackFrame.this) ;
@@ -244,6 +472,8 @@ public class PHPStackFrame extends PHPDebugElement implements IStackFrame {
public void stepReturn () throws DebugException {
DebugEvent ev;
+ setUpToDate (false);
+
thread.prepareForResume (DebugEvent.STEP_RETURN);
this.getPHPDBGProxy ().readStepReturnEnd (PHPStackFrame.this) ;
@@ -265,6 +495,7 @@ public class PHPStackFrame extends PHPDebugElement implements IStackFrame {
}
public void resume() throws DebugException {
+ setUpToDate (false);
this.getThread().resume();
}
@@ -287,6 +518,10 @@ public class PHPStackFrame extends PHPDebugElement implements IStackFrame {
return index;
}
+ public void setIndex (int index) {
+ this.index = index;
+ }
+
public PHPDBGProxy getPHPDBGProxy() {
PHPDebugTarget DebugTarget;
@@ -302,4 +537,27 @@ public class PHPStackFrame extends PHPDebugElement implements IStackFrame {
public int getModNo() {
return modno;
}
+
+ /**
+ * This function is needed when sorting the stackframes by their index numbers.
+ *
+ * @param obj The stackframe which this one is compared to.
+ * @return
+ *
+ * - -1 if the index of this stackframe is less.
+ *
- 0 if the index of both stackfream is equal (should no happen).
+ *
- 1 if the index of this stackfram is greater.
+ *
+ */
+ public int compareTo (Object obj)
+ {
+ if (index < ((PHPStackFrame) obj).getIndex ()) {
+ return -1;
+ }
+ else if (index > ((PHPStackFrame) obj).getIndex ()) {
+ return 1;
+ }
+
+ return 0;
+ }
}