X-Git-Url: http://git.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 a819140..e47f21d 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 @@ -40,6 +40,7 @@ public class PHPStackFrame extends PHPDebugElement implements IStackFrame, Compa private PHPVariable[] variables; // The array of variables TODO: better introduce a vector? private Vector varList = new Vector (); private String description; // + private boolean fUpToDate; // /** * @@ -59,6 +60,7 @@ public class PHPStackFrame extends PHPDebugElement implements IStackFrame, Compa this.thread = thread; this.description = desc; this.modno = modno; + this.fUpToDate = false; } /** @@ -75,6 +77,7 @@ public class PHPStackFrame extends PHPDebugElement implements IStackFrame, Compa this.index = index; this.file = file; this.thread = thread; + this.fUpToDate = false; } /** @@ -93,6 +96,177 @@ public class PHPStackFrame extends PHPDebugElement implements IStackFrame, Compa /** * + */ + 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 + * + */ + 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: + * + * + * @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). @@ -104,13 +278,18 @@ public class PHPStackFrame extends PHPDebugElement implements IStackFrame, Compa * @return The array of PHPVariables for this stackframe. */ public IVariable[] getVariables() throws DebugException { - //PHPVariable[] variablesNew; // The intermediate storage of the variable array we get from DBG proxy + 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 - varList = this.getPHPDBGProxy ().readVariables (this); - variables = (PHPVariable[]) varList.toArray (new PHPVariable[varList.size ()]); + 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 } @@ -129,10 +308,12 @@ public class PHPStackFrame extends PHPDebugElement implements IStackFrame, Compa try { if (value.hasVariables ()) { // Does the variable/value have children - variable = findVariable (value.getChildVariables (), varname); + if (!hasRecursion (variable)) { // Don't follow recursive variable/values + variable = findVariable (value.getChildVariables (), varname); - if (variable != null) { - return variable; + if (variable != null) { + return variable; + } } } else if ((variable.getName ()).equals (varname)) { // @@ -154,6 +335,14 @@ public class PHPStackFrame extends PHPDebugElement implements IStackFrame, Compa * @return */ 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 (findVariable (varList, s)); // Prefix the variable name with $ } @@ -161,11 +350,7 @@ public class PHPStackFrame extends PHPDebugElement implements IStackFrame, Compa * */ public boolean hasVariables () throws DebugException { - if (variables == null) { // Do we have a variables array? - return false; // No - } - - return variables.length > 0; // Is there something within the array? + return (varList.size () > 0); } public int getLineNumber() { @@ -247,6 +432,8 @@ public class PHPStackFrame extends PHPDebugElement implements IStackFrame, Compa 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); @@ -260,6 +447,8 @@ public class PHPStackFrame extends PHPDebugElement implements IStackFrame, Compa public void stepOver () throws DebugException { DebugEvent ev; + setUpToDate (false); + thread.prepareForResume (DebugEvent.STEP_OVER); this.getPHPDBGProxy ().readStepOverEnd (PHPStackFrame.this) ; @@ -273,6 +462,8 @@ public class PHPStackFrame extends PHPDebugElement implements IStackFrame, Compa public void stepReturn () throws DebugException { DebugEvent ev; + setUpToDate (false); + thread.prepareForResume (DebugEvent.STEP_RETURN); this.getPHPDBGProxy ().readStepReturnEnd (PHPStackFrame.this) ; @@ -294,6 +485,7 @@ public class PHPStackFrame extends PHPDebugElement implements IStackFrame, Compa } public void resume() throws DebugException { + setUpToDate (false); this.getThread().resume(); }