1) Moved the hasRecursion and the updateVariableList to PHPStackframe class.
authorrobekras <robekras>
Thu, 20 Oct 2005 19:28:23 +0000 (19:28 +0000)
committerrobekras <robekras>
Thu, 20 Oct 2005 19:28:23 +0000 (19:28 +0000)
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.

net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/model/PHPStackFrame.java

index a819140..e47f21d 100644 (file)
@@ -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
+        * <ul>
+        * <li> false if the PHPValue is not a child of itself
+        * <li> true if the PHPValue is
+        * </ul>
+        */
+       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:
+        * <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)
+       {
+               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();
        }