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.
PHPDBGFrame DBGFrame2;
PHPDBGFrame DBGFrame3;
int modNo;
-
+
DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_REQUEST);
DBGFrame1 = new PHPDBGFrame (PHPDBGBase.FRAME_BPS);
DBGFrame2 = new PHPDBGFrame (PHPDBGBase.FRAME_RAWDATA);
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?
* @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;
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
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);
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;
}
/**
+ * 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.
* <li> It looks for new stackframes within the DBG stackframe list and
* adds them to the 'static' list.
* <li> 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.
* <li> It looks for stackframes which are already existent and replicates the
* line number and the index number.
- * <li> At the end the 'static' stackfram list has to be sorted by the stackframes
+ * <li> At the end, the 'static' stackframe list has to be sorted by the stackframes
* index numbers.
* </ul>
*
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
}
}
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
}
/**
+ * 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
*/
}
/**
- *
+ * Is called by the DebuggerRunner
+ *
* @param debugTarget
*/
public void setDebugTarget (PHPDebugTarget debugTarget) {
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;
return PHPDebugCorePlugin.PLUGIN_ID;
}
+ public IStackFrame[] getStackFrames () throws DebugException {
+ return (IStackFrame[]) this.phpDBGProxy.getDBGInterface ().getStackList ();
+ }
+
public IDebugTarget getDebugTarget() {
return this;
}
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);
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
}
};
}
- return null;
+ else {
+ if (arg0 == PHPDebugElement.class) {
+ return this;
+ }
+
+ return super.getAdapter(arg0);
+ }
}
public IProcess getProcess() {
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
/**
*
/**
*
+ */
+ 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) {
* @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));
*
*/
public boolean hasVariables () throws DebugException {
- return (varList.size () > 0);
+ return true;
+ // return (varList.size () > 0);
}
public int getLineNumber() {
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 });
}
/**
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 });
}
/**
*
*/
public IStackFrame[] getStackFrames () throws DebugException {
- return frames;
+ if (isSuspended()) {
+ return ((PHPDebugTarget)getDebugTarget()).getStackFrames();
+ } else {
+ return new IStackFrame[0];
+ }
}
public int getStackFramesSize () {
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
}
/**
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) {
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);
+ }
+}