From cbc57deb77de7eb79d01f0f464ddd4dee43d64a1 Mon Sep 17 00:00:00 2001 From: robekras Date: Thu, 20 Oct 2005 19:28:23 +0000 Subject: [PATCH] 1) Moved the hasRecursion and the updateVariableList to PHPStackframe class. 2) Introduced the fUpToDate flag for avoiding unnecessary variable reading from DBG. 3) Introduced new resetHasChangedInfo method. 4) Break recursion in findVariable. 5) Read the variables from DBG in findVariable if variable list is not up-to-date. That's necessary for the hover function, in case the variable tree is hidden. --- .../internal/debug/core/model/PHPStackFrame.java | 214 +++++++++++++++++++- 1 files changed, 203 insertions(+), 11 deletions(-) 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(); } -- 1.7.1