From 5c7e1e6b63994685405a3a64b0009074f0d65b0a Mon Sep 17 00:00:00 2001 From: robekras Date: Thu, 24 Aug 2006 18:31:14 +0000 Subject: [PATCH 1/1] 1) Made getVariables and evalBlock methods in PHPDBGInterface synchronized (At least for evalBlock this is absolutely necessary for eclipse 3.2 compatibility). 2) getVariables method returns an empty vector if socket is closed (avoiding exception). 3) updateStackFrameList improved to avoid rebuild of variables view when stepping through the current php file. 4) getAdapter in PHPDebugTarget calls super.getAdapter (for eclipse 3.2 compatibility) 5) hasVariables in PHPStackFrame return always true (for eclipse 3.2 compatibility) 6) Removed second sending of RESUME event in stepInto and stepOver (in PHPStackFrame). 7) getStackFrames (in PHPThread) returns the stackframes only if in suspended state (for eclipse 3.2 compatibility). 8) PHPWatchExpressionDelegateCode beautifying. --- .../phpdt/internal/debug/core/PHPDBGInterface.java | 116 ++++++++++++++++---- .../phpdt/internal/debug/core/PHPDBGProxy.java | 12 ++- .../internal/debug/core/model/PHPDebugTarget.java | 21 +++- .../internal/debug/core/model/PHPStackFrame.java | 58 ++++++++-- .../phpdt/internal/debug/core/model/PHPThread.java | 21 ++-- .../core/watch/PHPWatchExpressionDelegate.java | 60 ++++++---- 6 files changed, 212 insertions(+), 76 deletions(-) diff --git a/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGInterface.java b/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGInterface.java index 89ef3a2..0ae3bc0 100644 --- a/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGInterface.java +++ b/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGInterface.java @@ -179,7 +179,7 @@ public class PHPDBGInterface { PHPDBGFrame DBGFrame2; PHPDBGFrame DBGFrame3; int modNo; - + DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_REQUEST); DBGFrame1 = new PHPDBGFrame (PHPDBGBase.FRAME_BPS); DBGFrame2 = new PHPDBGFrame (PHPDBGBase.FRAME_RAWDATA); @@ -219,22 +219,21 @@ public class PHPDBGInterface { if (!condition.equals ("")) { // Do we have a condition for breakpoint rawCounter++; // Set to new ID DBGFrame1.addInt (rawCounter); // ID of condition - + DBGFrame3.addInt (rawCounter); // FRAME_RAWDATA ID DBGFrame3.addInt (condition.length() + 1); // length of rawdata (+ null char) DBGFrame3.addString (condition); // The break condition DBGFrame3.addChar ('\0'); // null char - DBGPacket.addFrame (DBGFrame3); // First add break condition + DBGPacket.addFrame (DBGFrame3); // First add break condition } else { DBGFrame1.addInt (0); // ID of condition is 0, because there is no condition } - DBGFrame1.addInt (bpno); // breakpoint number DBGFrame1.addInt (isunderhit); // is under hit - + DBGPacket.addFrame (DBGFrame1); // Second add command data if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG? @@ -419,7 +418,7 @@ public class PHPDBGInterface { * @param stack The stackframe for which we want the variables. * @return The array of variables */ - public Vector getVariables (PHPStackFrame stack) throws IOException, DebugException { + public synchronized Vector getVariables (PHPStackFrame stack) throws IOException, DebugException { PHPDBGPacket DBGPacket; PHPDBGFrame DBGFrame1; PHPDBGEvalString evalStr; @@ -433,7 +432,7 @@ public class PHPDBGInterface { DBGPacket.addFrame (DBGFrame1); // Add command data if (proxy.getSocket ().isClosed ()) { // Do we have a socket for DBG communication? - return null; // No, then leave here + return new Vector (); // No, then leave here with an empty vector } DBGPacket.sendPacket (os); // Send the request to DBG @@ -501,7 +500,7 @@ public class PHPDBGInterface { flushAllPackets(); } - public PHPVariable[] evalBlock(PHPStackFrame stack, String evalString) throws IOException, DebugException { + public synchronized PHPVariable[] evalBlock(PHPStackFrame stack, String evalString) throws IOException, DebugException { PHPDBGPacket DBGPacket= new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST); PHPDBGFrame DBGFrame1= new PHPDBGFrame(PHPDBGBase.FRAME_EVAL); PHPDBGFrame DBGFrame2= new PHPDBGFrame(PHPDBGBase.FRAME_RAWDATA); @@ -615,7 +614,7 @@ public class PHPDBGInterface { if ((int) framesInfo[nextFrame + 8 + toRead - 1] == 0) { // Is there a string termination at the end? return String.copyValueOf (framesInfo, nextFrame + 8, toRead - 1); // Then copy frame content to String without the \0 and return } - + return String.copyValueOf (framesInfo, nextFrame + 8, toRead); // Copy frame content to String and return } break; @@ -628,6 +627,75 @@ public class PHPDBGInterface { } /** + * 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++) { + ((PHPStackFrame) 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 (PHPStackFrame stackFrameNew, Vector list) { + int i; + PHPStackFrame stackFrameOld; + + for (i = 0; i < list.size (); i++) { + stackFrameOld = (PHPStackFrame) list.get (i); // + + if (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.setIndex (stackFrameNew.getIndex ()); + 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; + PHPStackFrame 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 = (PHPStackFrame) 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. @@ -637,10 +705,10 @@ public class PHPDBGInterface { *
  • It looks for new stackframes within the DBG stackframe list and * adds them to the 'static' list. *
  • It looks for stackframes within the 'static' list, and removes them - * from the 'static' list in case the do not appear within the DBG list. + * from the 'static' list in case they do not appear within the DBG list. *
  • It looks for stackframes which are already existent and replicates the * line number and the index number. - *
  • At the end the 'static' stackfram list has to be sorted by the stackframes + *
  • At the end, the 'static' stackframe list has to be sorted by the stackframes * index numbers. * * @@ -657,22 +725,32 @@ public class PHPDBGInterface { PHPStackFrame stackFrameOld; PHPStackFrame[] 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 = (PHPStackFrame) stackList.get(i); for (n = 0; n < stackListOld.size (); n++) { // For all StackFrames in the StackFrame list stackFrameOld = (PHPStackFrame) stackListOld.get (n); // - if (stackFrameNew.getDescription ().equals (stackFrameOld.getDescription ()) && - stackFrameNew.getLineNumber() == stackFrameOld.getLineNumber()) {// Did we find the sent stackframe within the list of old stackframes? + if (stackFrameOld.isAvailable ()) { // If this stack frame was already found in the new list skip it + continue; + } + + if (stackFrameNew.getDescription ().equals (stackFrameOld.getDescription ())) {// Did we find the sent stackframe within the list of old stackframes? stackFrameOld.setLineNumber (stackFrameNew.getLineNumber ()); stackFrameOld.setIndex (stackFrameNew.getIndex ()); + 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 (n == stackListOld.size ()) { // Did not find the new stackframe within the list + 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 } } @@ -682,13 +760,9 @@ public class PHPDBGInterface { for (n = 0; n < stackListOld.size (); n++) { // For all StackFrames in the StackFrame list stackFrameOld = (PHPStackFrame) stackListOld.get (n); // - for (i = 0; i < stackList.size (); i++) { // For all stackList entries - stackFrameNew = (PHPStackFrame) stackList.get (i); - - if (stackFrameNew.getDescription ().equals (stackFrameOld.getDescription ()) && - stackFrameNew.getLineNumber() == stackFrameOld.getLineNumber()) {// Did we find the sent stackframe within the list of old stackframes? - break; // Yes, then break; - } + i = 0; + if (!stackFrameOld.isAvailable ()) { + i = stackList.size (); } if (i == stackList.size ()) { // Did not find the old stackframe within the list of new ones diff --git a/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGProxy.java b/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGProxy.java index 77d751e..5c5b26b 100644 --- a/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGProxy.java +++ b/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGProxy.java @@ -176,6 +176,15 @@ public class PHPDBGProxy { } /** + * Get the DBG interface which is linked to this proxy + * + * @paran DBGInt The DGB interface which is linked with this proxy + */ + public PHPDBGInterface getDBGInterface () { + return DBGInt; + } + + /** * Give back a buffered input stream for the socket which is * linked with this proxy */ @@ -417,7 +426,8 @@ public class PHPDBGProxy { } /** - * + * Is called by the DebuggerRunner + * * @param debugTarget */ public void setDebugTarget (PHPDebugTarget debugTarget) { diff --git a/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/model/PHPDebugTarget.java b/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/model/PHPDebugTarget.java index 36d415b..afce149 100644 --- a/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/model/PHPDebugTarget.java +++ b/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/model/PHPDebugTarget.java @@ -29,6 +29,7 @@ import org.eclipse.debug.core.model.IBreakpoint; import org.eclipse.debug.core.model.IDebugTarget; import org.eclipse.debug.core.model.IMemoryBlock; import org.eclipse.debug.core.model.IProcess; +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; @@ -148,6 +149,10 @@ public class PHPDebugTarget extends PHPDebugElement implements IPHPDebugTarget, return PHPDebugCorePlugin.PLUGIN_ID; } + public IStackFrame[] getStackFrames () throws DebugException { + return (IStackFrame[]) this.phpDBGProxy.getDBGInterface ().getStackList (); + } + public IDebugTarget getDebugTarget() { return this; } @@ -239,12 +244,12 @@ public class PHPDebugTarget extends PHPDebugElement implements IPHPDebugTarget, public void breakpointChanged (IBreakpoint breakpoint, IMarkerDelta arg1) { PHPLineBreakpoint bp; bp = (PHPLineBreakpoint) breakpoint; - + try { - if (breakpoint.isEnabled () && // Check if breakpoint state changed from disabled to enabled + if (breakpoint.isEnabled () && // Check if breakpoint state changed from disabled to enabled !arg1.getAttribute ("org.eclipse.debug.core.enabled", false)) { this.getPHPDBGProxy().addBreakpoint(breakpoint); - } + } else if (!breakpoint.isEnabled () && // Check if breakpoint state changed from enabled to disabled arg1.getAttribute ("org.eclipse.debug.core.enabled", true)) { this.getPHPDBGProxy().removeBreakpoint(breakpoint); @@ -255,7 +260,7 @@ public class PHPDebugTarget extends PHPDebugElement implements IPHPDebugTarget, this.getPHPDBGProxy().addBreakpoint(breakpoint); // and then we add again (else DBG would have two breakpoints!). } else { - this.getPHPDBGProxy().removeBreakpoint(breakpoint); + this.getPHPDBGProxy().removeBreakpoint(breakpoint); } } else { // All other cases will terminate the debugger @@ -319,7 +324,13 @@ public class PHPDebugTarget extends PHPDebugElement implements IPHPDebugTarget, } }; } - return null; + else { + if (arg0 == PHPDebugElement.class) { + return this; + } + + return super.getAdapter(arg0); + } } public IProcess getProcess() { 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 1c5dcdd..dcd372e 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 @@ -41,7 +41,10 @@ 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; // The source file name with the full path on target/remote system - private boolean fUpToDate; // + private boolean fUpToDate; // Indicates whether the variable list within this stackframe is + // up-to-date + private boolean fAvailable; // Needed when updating the stackframe list, shows whether the stackframe + // is within the list which was received from dbg /** * @@ -111,6 +114,32 @@ public class PHPStackFrame extends PHPDebugElement implements IStackFrame, Compa /** * + */ + public void setAvailable (boolean available) { + fAvailable = available; + } + + /** + * + */ + public boolean isAvailable () { + return fAvailable; + } + + + /** + * @see IAdaptable#getAdapter(Class) + */ + public Object getAdapter(Class adapter) { + if (adapter == PHPStackFrame.class) { + return this; + } + + return super.getAdapter(adapter); + } + + /** + * * */ private void resetHasChangedInfo (Vector varList) { @@ -279,11 +308,6 @@ 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 - - //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)); @@ -352,7 +376,8 @@ public class PHPStackFrame extends PHPDebugElement implements IStackFrame, Compa * */ public boolean hasVariables () throws DebugException { - return (varList.size () > 0); + return true; + // return (varList.size () > 0); } public int getLineNumber() { @@ -448,9 +473,16 @@ public class PHPStackFrame extends PHPDebugElement implements IStackFrame, Compa thread.prepareForResume (DebugEvent.STEP_INTO); // Don't know why, but this is necessary this.getPHPDBGProxy ().readStepIntoEnd (PHPStackFrame.this); - - ev = new DebugEvent (this.getThread (), DebugEvent.RESUME, DebugEvent.STEP_INTO); - DebugPlugin.getDefault().fireDebugEventSet (new DebugEvent[] { ev }); + + // Commented out sending the RESUME event because it was already sent by prepareForResume. + // The second RESUME event leads only to a little flickering within the variables view. + // It is also not clear why this event was necessary in eclipse < 3.2 + // Also sending a SUSPEND event here leads to a total rebuild of the variables view. + // (eclipse 3.2 has a build in timeout of 500 ms which leads to a auto suspend, with + // no flickering... but why???) + // + //ev = new DebugEvent (this.getThread (), DebugEvent.RESUME, DebugEvent.STEP_INTO); + //DebugPlugin.getDefault().fireDebugEventSet (new DebugEvent[] { ev }); } /** @@ -464,8 +496,10 @@ public class PHPStackFrame extends PHPDebugElement implements IStackFrame, Compa thread.prepareForResume (DebugEvent.STEP_OVER); this.getPHPDBGProxy ().readStepOverEnd (PHPStackFrame.this) ; - ev = new DebugEvent (this.getThread (), DebugEvent.RESUME, DebugEvent.STEP_OVER); - DebugPlugin.getDefault ().fireDebugEventSet (new DebugEvent[] { ev }); + // See comment within the previous stepInto method. + // + //ev = new DebugEvent (this.getThread (), DebugEvent.RESUME, DebugEvent.STEP_OVER); + //DebugPlugin.getDefault ().fireDebugEventSet (new DebugEvent[] { ev }); } /** diff --git a/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/model/PHPThread.java b/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/model/PHPThread.java index 49a432e..94feaf9 100644 --- a/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/model/PHPThread.java +++ b/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/model/PHPThread.java @@ -94,7 +94,11 @@ public class PHPThread extends PHPDebugElement implements IThread { * */ public IStackFrame[] getStackFrames () throws DebugException { - return frames; + if (isSuspended()) { + return ((PHPDebugTarget)getDebugTarget()).getStackFrames(); + } else { + return new IStackFrame[0]; + } } public int getStackFramesSize () { @@ -166,7 +170,7 @@ public class PHPThread extends PHPDebugElement implements IThread { this.frames = null; // Reset the stackframes ev = new DebugEvent (this, DebugEvent.RESUME, de); // Create an event resume by stepping - DebugPlugin.getDefault ().fireDebugEventSet (new DebugEvent[] { ev }); // Fire the event + DebugPlugin.getDefault ().fireDebugEventSet (new DebugEvent[] { ev }); // Fire the event } /** @@ -308,22 +312,13 @@ public class PHPThread extends PHPDebugElement implements IThread { if (IWorkbenchAdapter.class.equals (arg0)) { return new IWorkbenchAdapter() { public Object[] getChildren(Object o) { - Object[] children = null; - try { - IStackFrame[] frames = getStackFrames(); - - if (null != frames) { - children = new Object[frames.length]; - for (int i = 0; i < frames.length; ++i) { - children[i] = frames[i]; - } - } + return getStackFrames (); } catch (DebugException x) { PHPeclipsePlugin.log ("Unable to get stack frames.", x); } - return children; + return new Object[0]; } public ImageDescriptor getImageDescriptor(Object object) { diff --git a/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/watch/PHPWatchExpressionDelegate.java b/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/watch/PHPWatchExpressionDelegate.java index 2c3964d..e37deff 100644 --- a/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/watch/PHPWatchExpressionDelegate.java +++ b/net.sourceforge.phpeclipse.debug.core/src/net/sourceforge/phpdt/internal/debug/core/watch/PHPWatchExpressionDelegate.java @@ -10,29 +10,41 @@ import org.eclipse.debug.core.model.IWatchExpressionDelegate; import org.eclipse.debug.core.model.IWatchExpressionListener; import org.eclipse.debug.core.model.IWatchExpressionResult; +/** + * + */ public class PHPWatchExpressionDelegate implements IWatchExpressionDelegate { - public void evaluateExpression(String expression, IDebugElement context, - IWatchExpressionListener listener) { - IWatchExpressionResult x; - PHPDBGProxy dbg=((PHPDebugTarget)context.getDebugTarget()).getPHPDBGProxy(); - PHPStackFrame s=null; - if(context instanceof PHPStackFrame) - s=(PHPStackFrame)context; - try{ - PHPVariable result[]=dbg.eval(s,expression); - if(result.length==0) - x=new PHPWatchExpressionResult(expression,null,null); - else - x=new PHPWatchExpressionResult(expression,result[0].getValue(),null); - } - catch(Exception e) - { - String[] s1=new String[1]; - s1[0]=e.toString(); - x=new PHPWatchExpressionResult(expression,null,s1); - } - listener.watchEvaluationFinished(x); - } - -} \ No newline at end of file + public void evaluateExpression (String expression, IDebugElement context, IWatchExpressionListener listener) { + IWatchExpressionResult x; + PHPDBGProxy dbg; + PHPStackFrame s; + + dbg = ((PHPDebugTarget) context.getDebugTarget ()).getPHPDBGProxy (); + s = null; + + if (context instanceof PHPStackFrame) { + s = (PHPStackFrame) context; + } + + try { + PHPVariable result[] = dbg.eval (s, expression); + + if (result.length == 0) { + x = new PHPWatchExpressionResult (expression, null, null); + } + else { + x = new PHPWatchExpressionResult (expression, result[0].getValue (), null); + } + } + catch (Exception e) { + String[] s1; + + s1 = new String[1]; + s1[0] = e.toString (); + x = new PHPWatchExpressionResult (expression, null, s1); + } + + listener.watchEvaluationFinished (x); + } +} -- 1.7.1