[Pydev-cvs] org.python.pydev.debug/src/org/python/pydev/debug/model PyVariable.java,NONE,1.1 PyVaria
Brought to you by:
fabioz
Update of /cvsroot/pydev/org.python.pydev.debug/src/org/python/pydev/debug/model In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17261/src/org/python/pydev/debug/model Modified Files: XMLUtils.java PyThread.java PyStackFrame.java PyDebugTarget.java Added Files: PyVariable.java PyVariableCollection.java IVariableLocator.java Removed Files: ThreadListCommand.java StepCommand.java ThreadSuspendCommand.java AbstractDebuggerCommand.java ThreadKillCommand.java RemoteDebugger.java ThreadRunCommand.java VersionCommand.java Log Message: variables can now be displayed --- RemoteDebugger.java DELETED --- Index: PyThread.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev.debug/src/org/python/pydev/debug/model/PyThread.java,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** PyThread.java 28 Apr 2004 02:49:48 -0000 1.3 --- PyThread.java 5 May 2004 02:02:00 -0000 1.4 *************** *** 8,11 **** --- 8,12 ---- import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.Platform; + import org.eclipse.core.runtime.PlatformObject; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.ILaunch; *************** *** 14,35 **** import org.eclipse.debug.core.model.IStackFrame; import org.eclipse.debug.core.model.IThread; import org.eclipse.ui.views.tasklist.ITaskListResourceAdapter; /** * Represents python threads. ! * ! * */ ! public class PyThread implements IThread { private PyDebugTarget target; private String name; private String id; ! boolean isPydevThread; // true if this is a debugger thread, that can't be killed/suspended ! ! boolean isSuspended = false; ! boolean isStepping = false; ! IStackFrame[] stack; public PyThread(PyDebugTarget target, String name, String id) { this.target = target; --- 15,37 ---- import org.eclipse.debug.core.model.IStackFrame; import org.eclipse.debug.core.model.IThread; + import org.eclipse.ui.views.properties.IPropertySource; import org.eclipse.ui.views.tasklist.ITaskListResourceAdapter; + import org.python.pydev.debug.model.remote.*; /** * Represents python threads. ! * Stack global variables are associated with threads. */ ! public class PyThread extends PlatformObject implements IThread { private PyDebugTarget target; private String name; private String id; ! private boolean isPydevThread; // true if this is a debugger thread, that can't be killed/suspended + private boolean isSuspended = false; + private boolean isStepping = false; + private IStackFrame[] stack; + public PyThread(PyDebugTarget target, String name, String id) { this.target = target; *************** *** 38,42 **** isPydevThread = id.equals("-1"); // use a special id for pydev threads } ! /** * If a thread is entering a suspended state, pass in the stack --- 40,44 ---- isPydevThread = id.equals("-1"); // use a special id for pydev threads } ! /** * If a thread is entering a suspended state, pass in the stack *************** *** 45,51 **** isSuspended = state; this.stack = stack; - if (stack != null) - for (int i=0; i<stack.length; i++) - ((PyStackFrame)stack[i]).setThread(this); } --- 47,50 ---- *************** *** 83,90 **** public void terminate() throws DebugException { ! if (!isPydevThread) { ! RemoteDebugger d = target.getDebugger(); ! d.postCommand(new ThreadKillCommand(d, id)); ! } } --- 82,93 ---- public void terminate() throws DebugException { ! // this only kills a single thread, we usually want to kill ! // the whole app ! // if (!isPydevThread) { ! // RemoteDebugger d = target.getDebugger(); ! // d.postCommand(new ThreadKillCommand(d, id)); ! // } ! // else ! target.terminate(); } *************** *** 168,171 **** --- 171,182 ---- } + public PyStackFrame findStackFrameByID(String id) { + if (stack != null) + for (int i=0; i<stack.length; i++) + if (id.equals(((PyStackFrame)stack[i]).getId())) + return (PyStackFrame)stack[i]; + return null; + } + public IBreakpoint[] getBreakpoints() { // TODO Auto-generated method stub *************** *** 179,182 **** --- 190,195 ---- else if (adapter.equals(ITaskListResourceAdapter.class)) return null; + else if (adapter.equals(IPropertySource.class) || adapter.equals(ITaskListResourceAdapter.class)) + return super.getAdapter(adapter); else { System.err.println("PythonThread Need adapter " + adapter.toString()); *************** *** 184,188 **** } // ongoing, I do not fully understand all the interfaces they'd like me to support ! return null; } --- 197,201 ---- } // ongoing, I do not fully understand all the interfaces they'd like me to support ! return super.getAdapter(adapter); } --- NEW FILE: IVariableLocator.java --- /* * Author: atotic * Created on Apr 30, 2004 * License: Common Public License v1.0 */ package org.python.pydev.debug.model; /** * IVariableLocator knows how to produce location information * for CMD_GET_VARIABLE * * The location is specified as: * * thread_id, stack_frame, LOCAL|GLOBAL, attribute* */ public interface IVariableLocator { public String getPyDBLocation(); } --- ThreadRunCommand.java DELETED --- Index: PyStackFrame.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev.debug/src/org/python/pydev/debug/model/PyStackFrame.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** PyStackFrame.java 28 Apr 2004 02:49:48 -0000 1.2 --- PyStackFrame.java 5 May 2004 02:02:00 -0000 1.3 *************** *** 9,12 **** --- 9,13 ---- import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; + import org.eclipse.core.runtime.PlatformObject; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.ILaunch; *************** *** 16,19 **** --- 17,21 ---- import org.eclipse.debug.core.model.IThread; import org.eclipse.debug.core.model.IVariable; + import org.eclipse.ui.views.properties.IPropertySource; import org.eclipse.ui.views.tasklist.ITaskListResourceAdapter; import org.python.pydev.debug.core.PydevDebugPlugin; *************** *** 24,28 **** * Needs to integrate with the source locator */ ! public class PyStackFrame implements IStackFrame { private String name; --- 26,30 ---- * Needs to integrate with the source locator */ ! public class PyStackFrame extends PlatformObject implements IStackFrame { private String name; *************** *** 31,43 **** private IPath path; private int line; ! ! public PyStackFrame(String id, String name, IPath file, int line) { ! this.id = id; this.name = name; this.path = file; this.line = line; } public IPath getPath() { return path; --- 33,82 ---- private IPath path; private int line; ! private IVariable[] variables; ! private IVariableLocator localsLocator; ! private IVariableLocator globalsLocator; ! ! public PyStackFrame(PyThread in_thread, String in_id, String name, IPath file, int line) { ! this.id = in_id; this.name = name; this.path = file; this.line = line; + this.thread = in_thread; + localsLocator = new IVariableLocator() { + public String getPyDBLocation() { + return thread.getId() + "\t" + id + "\tLOCAL"; + } + }; + globalsLocator = new IVariableLocator() { + public String getPyDBLocation() { + return thread.getId() + "\t" + id + "\tGLOBAL"; + } + }; + } + + public String getId() { + return id; + } + + public IVariableLocator getLocalsLocator() { + return localsLocator; + } + + public IVariableLocator getGlobalLocator() { + return globalsLocator; + } + + public void setName(String name) { + this.name = name; } + public void setPath(IPath path) { + this.path = path; + } + public void setLine(int line) { + this.line = line; + } + public IPath getPath() { return path; *************** *** 47,63 **** return thread; } ! ! public void setThread(PyThread thread) { ! this.thread = thread; } public IVariable[] getVariables() throws DebugException { ! // TODO Auto-generated method stub ! return null; } public boolean hasVariables() throws DebugException { ! // TODO Auto-generated method stub ! return false; } --- 86,100 ---- return thread; } ! ! public void setVariables(IVariable[] locals) { ! this.variables = locals; } public IVariable[] getVariables() throws DebugException { ! return variables; } public boolean hasVariables() throws DebugException { ! return (variables != null); } *************** *** 76,79 **** --- 113,117 ---- public String getName() throws DebugException { return name + " [" + path.lastSegment() + ":" + Integer.toString(line) + "]"; + // return "(" + id + ")" + name + " [" + path.lastSegment() + ":" + Integer.toString(line) + "]"; } *************** *** 164,170 **** else if (adapter.equals(ITaskListResourceAdapter.class)) return null; // ongoing, I do not fully understand all the interfaces they'd like me to support System.err.println("PyStackFrame Need adapter " + adapter.toString()); ! return null; } --- 202,211 ---- else if (adapter.equals(ITaskListResourceAdapter.class)) return null; + else if (adapter.equals(IPropertySource.class) || + adapter.equals(ITaskListResourceAdapter.class)) + return super.getAdapter(adapter); // ongoing, I do not fully understand all the interfaces they'd like me to support System.err.println("PyStackFrame Need adapter " + adapter.toString()); ! return super.getAdapter(adapter); } *************** *** 196,199 **** return super.equals(obj); } - } --- 237,239 ---- --- ThreadListCommand.java DELETED --- --- ThreadSuspendCommand.java DELETED --- --- StepCommand.java DELETED --- Index: PyDebugTarget.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev.debug/src/org/python/pydev/debug/model/PyDebugTarget.java,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** PyDebugTarget.java 28 Apr 2004 02:49:48 -0000 1.3 --- PyDebugTarget.java 5 May 2004 02:02:00 -0000 1.4 *************** *** 13,18 **** --- 13,20 ---- import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; + import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; + import org.eclipse.core.runtime.PlatformObject; import org.eclipse.debug.core.DebugEvent; import org.eclipse.debug.core.DebugException; *************** *** 27,31 **** --- 29,35 ---- import org.eclipse.debug.core.model.IThread; import org.eclipse.ui.views.properties.IPropertySource; + import org.eclipse.ui.views.tasklist.ITaskListResourceAdapter; import org.python.pydev.debug.core.PydevDebugPlugin; + import org.python.pydev.debug.model.remote.*; /** *************** *** 33,39 **** * TODO Comment this class * Make sure we fire the right org.eclipse.debug.core.DebugEvents ! * What happens with debug events? LaunchViewEventHandlerL:: */ ! public class PyDebugTarget implements IDebugTarget, ILaunchListener { ILaunch launch; --- 37,43 ---- * TODO Comment this class * Make sure we fire the right org.eclipse.debug.core.DebugEvents ! * What happens with debug events? see LaunchViewEventHandler */ ! public class PyDebugTarget extends PlatformObject implements IDebugTarget, ILaunchListener { ILaunch launch; *************** *** 120,123 **** --- 124,128 ---- if (debugger != null) debugger.disconnect(); + threads = new IThread[0]; process.terminate(); } *************** *** 167,170 **** --- 172,177 ---- public IThread[] getThreads() throws DebugException { + if (debugger == null) + return null; if (threads == null) { ThreadListCommand cmd = new ThreadListCommand(debugger, this); *************** *** 225,231 **** } else if (adapter.equals(IPropertySource.class)) return launch.getAdapter(adapter); ! else ! System.err.println("Need adapter " + adapter.toString()); ! return null; } --- 232,239 ---- } else if (adapter.equals(IPropertySource.class)) return launch.getAdapter(adapter); ! else if (adapter.equals(ITaskListResourceAdapter.class)) ! return super.getAdapter(adapter); ! System.err.println("Need adapter " + adapter.toString()); ! return super.getAdapter(adapter); } *************** *** 251,255 **** } ! private void fireEvent(DebugEvent event) { DebugPlugin manager= DebugPlugin.getDefault(); if (manager != null) { --- 259,263 ---- } ! protected void fireEvent(DebugEvent event) { DebugPlugin manager= DebugPlugin.getDefault(); if (manager != null) { *************** *** 261,268 **** * @return an existing thread with a given id (null if none) */ ! private IThread findThreadByID(String thread_id) throws DebugException { for (int i = 0; i < threads.length; i++) if (thread_id.equals(((PyThread)threads[i]).getId())) ! return threads[i]; return null; } --- 269,276 ---- * @return an existing thread with a given id (null if none) */ ! protected PyThread findThreadByID(String thread_id) { for (int i = 0; i < threads.length; i++) if (thread_id.equals(((PyThread)threads[i]).getId())) ! return (PyThread)threads[i]; return null; } *************** *** 272,276 **** */ private void processThreadCreated(String payload) { ! IThread[] newThreads = XMLUtils.ThreadsFromXML(this, payload); if (threads == null) threads = newThreads; --- 280,291 ---- */ private void processThreadCreated(String payload) { ! ! IThread[] newThreads; ! try { ! newThreads = XMLUtils.ThreadsFromXML(this, payload); ! } catch (CoreException e) { ! PydevDebugPlugin.errorDialog("Error in processThreadCreated", e); ! return; ! } if (threads == null) threads = newThreads; *************** *** 291,377 **** // Remote this from our thread list private void processThreadKilled(String thread_id) { ! try { ! IThread threadToDelete = findThreadByID(thread_id); ! if (threadToDelete != null) { ! int j = 0; ! IThread[] newThreads = new IThread[threads.length - 1]; ! for (int i=0; i < threads.length; i++) ! if (threads[i] != threadToDelete) ! newThreads[j++] = threads[i]; ! threads = newThreads; ! fireEvent(new DebugEvent(threadToDelete, DebugEvent.TERMINATE)); ! } ! } catch (DebugException e) { ! PydevDebugPlugin.log(IStatus.ERROR, "Unexpected error thread kill", e); } } private void processThreadSuspended(String payload) { try { ! Object[] threadNstack = XMLUtils.XMLToStack(payload); ! PyThread t = (PyThread)findThreadByID((String)threadNstack[0]); ! int reason = DebugEvent.UNSPECIFIED; ! String stopReason = (String) threadNstack[1]; ! if (stopReason != null) { ! int stopReason_i = Integer.parseInt(stopReason); ! if (stopReason_i == AbstractDebuggerCommand.CMD_STEP_OVER || ! stopReason_i == AbstractDebuggerCommand.CMD_STEP_INTO || ! stopReason_i == AbstractDebuggerCommand.CMD_STEP_RETURN) ! reason = DebugEvent.STEP_END; ! else if (stopReason_i == AbstractDebuggerCommand.CMD_THREAD_SUSPEND) ! reason = DebugEvent.CLIENT_REQUEST; ! else { ! PydevDebugPlugin.log(IStatus.ERROR, "Unexpected reason for suspension", null); ! reason = DebugEvent.UNSPECIFIED; ! } ! } ! if (t != null) { ! t.setSuspended(true, (IStackFrame[])threadNstack[2]); ! if (reason == DebugEvent.STEP_END) ! System.out.println("need love"); ! fireEvent(new DebugEvent(t, DebugEvent.SUSPEND, reason)); } ! } catch (DebugException e) { ! PydevDebugPlugin.log(IStatus.ERROR, "Unexpected error thread suspended", e); } } static Pattern threadRunPattern = Pattern.compile("(\\d+)\\t(\\w*)"); private void processThreadRun(String payload) { ! try { ! String threadID = ""; ! int resumeReason = DebugEvent.UNSPECIFIED; ! Matcher m = threadRunPattern.matcher(payload); ! if (m.matches()) { ! threadID = m.group(1); ! try { ! int raw_reason = Integer.parseInt(m.group(2)); ! if (raw_reason == AbstractDebuggerCommand.CMD_STEP_OVER) ! resumeReason = DebugEvent.STEP_OVER; ! else if (raw_reason == AbstractDebuggerCommand.CMD_STEP_RETURN) ! resumeReason = DebugEvent.STEP_RETURN; ! else if (raw_reason == AbstractDebuggerCommand.CMD_STEP_INTO) ! resumeReason = DebugEvent.STEP_INTO; ! else if (raw_reason == AbstractDebuggerCommand.CMD_THREAD_RUN) ! resumeReason = DebugEvent.CLIENT_REQUEST; ! else { ! PydevDebugPlugin.log(IStatus.ERROR, "Unexpected resume reason code", null); ! resumeReason = DebugEvent.UNSPECIFIED; ! } } ! catch (NumberFormatException e) { ! // expected, when pydevd reports "None" resumeReason = DebugEvent.UNSPECIFIED; ! } } ! else ! PydevDebugPlugin.log(IStatus.ERROR, "Unexpected treadRun payload " + payload, null); ! ! PyThread t = (PyThread)findThreadByID(threadID); ! if (t != null) { ! t.setSuspended(false, null); ! fireEvent(new DebugEvent(t, DebugEvent.RESUME, resumeReason)); } ! } catch (DebugException e) { ! PydevDebugPlugin.log(IStatus.ERROR, "Unexpected error thread run", e); } } --- 306,388 ---- // Remote this from our thread list private void processThreadKilled(String thread_id) { ! IThread threadToDelete = findThreadByID(thread_id); ! if (threadToDelete != null) { ! int j = 0; ! IThread[] newThreads = new IThread[threads.length - 1]; ! for (int i=0; i < threads.length; i++) ! if (threads[i] != threadToDelete) ! newThreads[j++] = threads[i]; ! threads = newThreads; ! fireEvent(new DebugEvent(threadToDelete, DebugEvent.TERMINATE)); } } private void processThreadSuspended(String payload) { + Object[] threadNstack; try { ! threadNstack = XMLUtils.XMLToStack(this, payload); ! } catch (CoreException e) { ! PydevDebugPlugin.errorDialog("Error reading ThreadSuspended", e); ! return; ! } ! PyThread t = (PyThread)threadNstack[0]; ! int reason = DebugEvent.UNSPECIFIED; ! String stopReason = (String) threadNstack[1]; ! if (stopReason != null) { ! int stopReason_i = Integer.parseInt(stopReason); ! if (stopReason_i == AbstractDebuggerCommand.CMD_STEP_OVER || ! stopReason_i == AbstractDebuggerCommand.CMD_STEP_INTO || ! stopReason_i == AbstractDebuggerCommand.CMD_STEP_RETURN) ! reason = DebugEvent.STEP_END; ! else if (stopReason_i == AbstractDebuggerCommand.CMD_THREAD_SUSPEND) ! reason = DebugEvent.CLIENT_REQUEST; ! else { ! PydevDebugPlugin.log(IStatus.ERROR, "Unexpected reason for suspension", null); ! reason = DebugEvent.UNSPECIFIED; } ! } ! if (t != null) { ! t.setSuspended(true, (IStackFrame[])threadNstack[2]); ! fireEvent(new DebugEvent(t, DebugEvent.SUSPEND, reason)); } } static Pattern threadRunPattern = Pattern.compile("(\\d+)\\t(\\w*)"); + /** + * ThreadRun event processing + */ private void processThreadRun(String payload) { ! String threadID = ""; ! int resumeReason = DebugEvent.UNSPECIFIED; ! Matcher m = threadRunPattern.matcher(payload); ! if (m.matches()) { ! threadID = m.group(1); ! try { ! int raw_reason = Integer.parseInt(m.group(2)); ! if (raw_reason == AbstractDebuggerCommand.CMD_STEP_OVER) ! resumeReason = DebugEvent.STEP_OVER; ! else if (raw_reason == AbstractDebuggerCommand.CMD_STEP_RETURN) ! resumeReason = DebugEvent.STEP_RETURN; ! else if (raw_reason == AbstractDebuggerCommand.CMD_STEP_INTO) ! resumeReason = DebugEvent.STEP_INTO; ! else if (raw_reason == AbstractDebuggerCommand.CMD_THREAD_RUN) ! resumeReason = DebugEvent.CLIENT_REQUEST; ! else { ! PydevDebugPlugin.log(IStatus.ERROR, "Unexpected resume reason code", null); resumeReason = DebugEvent.UNSPECIFIED; ! } } ! catch (NumberFormatException e) { ! // expected, when pydevd reports "None" ! resumeReason = DebugEvent.UNSPECIFIED; } ! } ! else ! PydevDebugPlugin.log(IStatus.ERROR, "Unexpected treadRun payload " + payload, null); ! ! PyThread t = (PyThread)findThreadByID(threadID); ! if (t != null) { ! t.setSuspended(false, null); ! fireEvent(new DebugEvent(t, DebugEvent.RESUME, resumeReason)); } } --- VersionCommand.java DELETED --- --- ThreadKillCommand.java DELETED --- Index: XMLUtils.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev.debug/src/org/python/pydev/debug/model/XMLUtils.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** XMLUtils.java 27 Apr 2004 19:12:59 -0000 1.1 --- XMLUtils.java 5 May 2004 02:02:00 -0000 1.2 *************** *** 16,23 **** --- 16,27 ---- import javax.xml.parsers.SAXParserFactory; + import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; + import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.debug.core.model.IStackFrame; import org.eclipse.debug.core.model.IThread; + import org.eclipse.debug.core.model.IVariable; + import org.python.pydev.debug.core.PydevDebugPlugin; import org.xml.sax.Attributes; import org.xml.sax.SAXException; *************** *** 25,33 **** /** ! * Various utilities */ public class XMLUtils { static SAXParserFactory parserFactory = SAXParserFactory.newInstance(); /** * SAX parser for thread info --- 29,53 ---- /** ! * Translate XML protocol responses into Py structures. ! * ! * Things get more complex than I'd like when complex Py structures get built. */ public class XMLUtils { static SAXParserFactory parserFactory = SAXParserFactory.newInstance(); + + static SAXParser getSAXParser() throws CoreException { + SAXParser parser = null; + try { + synchronized(parserFactory) { + parser = parserFactory.newSAXParser(); + } + } catch (ParserConfigurationException e) { + throw new CoreException(PydevDebugPlugin.makeStatus(IStatus.ERROR, "Unexpected XML SAX error", e)); + } catch (SAXException e) { + throw new CoreException(PydevDebugPlugin.makeStatus(IStatus.ERROR, "Unexpected XML SAX error", e)); + } + return parser; + } /** * SAX parser for thread info *************** *** 58,68 **** * Creates IThread[] from the XML response */ ! static public IThread[] ThreadsFromXML(PyDebugTarget target, String payload) { IThread[] threads = null; try { ! SAXParser parser; ! synchronized(parserFactory) { ! parser = parserFactory.newSAXParser(); ! } XMLToThreadInfo info = new XMLToThreadInfo(target); parser.parse(new StringBufferInputStream(payload), info); --- 78,85 ---- * Creates IThread[] from the XML response */ ! static public IThread[] ThreadsFromXML(PyDebugTarget target, String payload) throws CoreException { IThread[] threads = null; try { ! SAXParser parser = getSAXParser(); XMLToThreadInfo info = new XMLToThreadInfo(target); parser.parse(new StringBufferInputStream(payload), info); *************** *** 72,110 **** while (it.hasNext()) threads[i++] = (IThread)it.next(); ! } catch (ParserConfigurationException e) { ! e.printStackTrace(); } catch (SAXException e) { ! e.printStackTrace(); } catch (IOException e) { ! e.printStackTrace(); } return threads; } static class XMLToStackInfo extends DefaultHandler { ! public String thread_id; public String stop_reason; public ArrayList stack = new ArrayList(); ! /* ! """ <xml> ! <thread id="id"/> ! <frame id="id" name="functionName " file="file" line="line"> ! */ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { ! if (qName.equals("thread")) { ! thread_id = attributes.getValue("id"); ! stop_reason = attributes.getValue("stop_reason"); ! } ! else if (qName.equals("frame")) { ! String name = attributes.getValue("name"); ! String id = attributes.getValue("id"); ! String file = attributes.getValue("file"); ! String line = attributes.getValue("line"); ! IPath filePath = new Path(file); ! stack.add(new PyStackFrame(id, name, filePath, Integer.parseInt(line))); ! } } } /** --- 89,210 ---- while (it.hasNext()) threads[i++] = (IThread)it.next(); ! } catch (CoreException e) { ! throw e; } catch (SAXException e) { ! throw new CoreException(PydevDebugPlugin.makeStatus(IStatus.ERROR, "Unexpected XML error", e)); } catch (IOException e) { ! throw new CoreException(PydevDebugPlugin.makeStatus(IStatus.ERROR, "Unexpected XML error", e)); } return threads; } + /** + * Creates a variable from XML attributes + * <var name="self" type="ObjectType" value="<DeepThread>"/> + */ + static PyVariable createVariable(PyDebugTarget target, IVariableLocator locator, Attributes attributes) { + PyVariable var; + String name = attributes.getValue("name"); + String type = attributes.getValue("type"); + String value = attributes.getValue("value"); + if (value != null) + value = URLDecoder.decode(value); + String isContainer = attributes.getValue("isContainer"); + if ("True".equals(isContainer)) + var = new PyVariableCollection(target, name, type, value, locator); + else + var = new PyVariable(target, name, type, value); + return var; + } + + /** + * XMLToStack SAX traverse + */ static class XMLToStackInfo extends DefaultHandler { ! public PyThread thread; public String stop_reason; public ArrayList stack = new ArrayList(); + public ArrayList locals; + public PyDebugTarget target; + PyStackFrame currentFrame; ! public XMLToStackInfo(PyDebugTarget target) { ! this.target = target; ! } ! ! private void startThread(Attributes attributes) throws SAXException { ! String target_id = attributes.getValue("id"); ! thread = target.findThreadByID(target_id); ! if (thread == null) ! throw new SAXException("Thread not found"); // can happen when debugger has been destroyed ! stop_reason = attributes.getValue("stop_reason"); ! } ! ! private void startFrame(Attributes attributes) { ! String name = attributes.getValue("name"); ! String id = attributes.getValue("id"); ! String file = attributes.getValue("file"); ! String line = attributes.getValue("line"); ! IPath filePath = new Path(file); ! // Try to recycle old stack objects ! currentFrame = thread.findStackFrameByID(id);; ! if (currentFrame == null) ! currentFrame = new PyStackFrame(thread, id, name, filePath, Integer.parseInt(line)); ! else { ! currentFrame.setName(name); ! currentFrame.setPath(filePath); ! currentFrame.setLine(Integer.parseInt(line)); ! } ! stack.add(currentFrame); ! } ! ! // local variables belong to the stack frame ! // when ! private void startVar(Attributes attributes) { ! if (locals == null) { ! locals = new ArrayList(); ! PyVariableCollection global = new PyVariableCollection(target, "Globals", "frame.f_global", "Global variables", currentFrame.getGlobalLocator()); ! locals.add(global); // locals always include global as the top ! } ! // create a local variable, and add it to locals ! PyVariable newLocal = createVariable(target, currentFrame.getLocalsLocator(), attributes); ! locals.add(newLocal); ! } ! ! ! /** ! * Assign stack frames to thread. ! * Assign global variables to thread ! * Assign local variables to stack frame ! */ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { ! /* ! <xml> ! <thread id="id"/> ! <frame id="id" name="functionName " file="file" line="line"> ! <var scope="local" name="self" type="ObjectType" value="<DeepThread>"/> ! </frame>* ! */ ! if (qName.equals("thread")) ! startThread(attributes); ! else if (qName.equals("frame")) ! startFrame(attributes); ! else if (qName.equals("var")) ! startVar(attributes); } + + public void endElement(String uri, String localName, String qName) + throws SAXException { + if (qName.equals("frame")) { + // when frame ends, we need to assign all the local variables + IVariable[] locArry = new IVariable[locals.size()]; + for (int i=0; i < locArry.length; i++) + locArry[i] = (IVariable)locals.get(i); + currentFrame.setVariables(locArry); + locals = null; + } + } + } /** *************** *** 112,125 **** * @return an array of [thread_id, stop_reason, IStackFrame[]] */ ! public static Object[] XMLToStack(String payload) { String thread_id; IStackFrame[] stack; Object[] retVal = new Object[3]; try { ! SAXParser parser; ! synchronized(parserFactory) { ! parser = parserFactory.newSAXParser(); ! } ! XMLToStackInfo info = new XMLToStackInfo(); parser.parse(new StringBufferInputStream(payload), info); stack = new IStackFrame[info.stack.size()]; --- 212,222 ---- * @return an array of [thread_id, stop_reason, IStackFrame[]] */ ! public static Object[] XMLToStack(PyDebugTarget target, String payload) throws CoreException { String thread_id; IStackFrame[] stack; Object[] retVal = new Object[3]; try { ! SAXParser parser = getSAXParser(); ! XMLToStackInfo info = new XMLToStackInfo(target); parser.parse(new StringBufferInputStream(payload), info); stack = new IStackFrame[info.stack.size()]; *************** *** 128,143 **** while (it.hasNext()) stack[i++] = (IStackFrame)it.next(); ! retVal[0] = info.thread_id; retVal[1] = info.stop_reason; retVal[2] = stack; ! } catch (ParserConfigurationException e) { ! e.printStackTrace(); } catch (SAXException e) { ! e.printStackTrace(); } catch (IOException e) { ! e.printStackTrace(); } return retVal; } } --- 225,283 ---- while (it.hasNext()) stack[i++] = (IStackFrame)it.next(); ! retVal[0] = info.thread; retVal[1] = info.stop_reason; retVal[2] = stack; ! } catch (CoreException e) { ! throw e; } catch (SAXException e) { ! throw new CoreException(PydevDebugPlugin.makeStatus(IStatus.ERROR, "Unexpected XML error", e)); } catch (IOException e) { ! throw new CoreException(PydevDebugPlugin.makeStatus(IStatus.ERROR, "Unexpected XML error", e)); } return retVal; } + + /** + * Processes CMD_GET_VARIABLE return + * + */ + static class XMLToVariableInfo extends DefaultHandler { + private PyDebugTarget target; + private IVariableLocator locator; + public ArrayList vars; + + public XMLToVariableInfo(PyDebugTarget target, IVariableLocator locator) { + this.target = target; + this.locator = locator; + vars = new ArrayList(); + } + + public void startElement(String uri, String localName, String qName, + Attributes attributes) throws SAXException { + // <var name="self" type="ObjectType" value="<DeepThread>"/> + // create a local variable, and add it to locals + if (qName.equals("var")) + vars.add(createVariable(target, locator, attributes)); + } + } + + public static PyVariable[] XMLToVariables(PyDebugTarget target, IVariableLocator locator, String payload) throws CoreException { + try { + SAXParser parser = getSAXParser(); + XMLToVariableInfo info = new XMLToVariableInfo(target, locator); + parser.parse(new StringBufferInputStream(payload), info); + PyVariable[] vars = new PyVariable[info.vars.size()]; + for (int i =0; i< info.vars.size(); i++) + vars[i] = (PyVariable)info.vars.get(i); + return vars; + } catch (CoreException e) { + throw e; + } catch (SAXException e) { + throw new CoreException(PydevDebugPlugin.makeStatus(IStatus.ERROR, "Unexpected XML error", e)); + } catch (IOException e) { + throw new CoreException(PydevDebugPlugin.makeStatus(IStatus.ERROR, "Unexpected XML error", e)); + } + } + } --- NEW FILE: PyVariableCollection.java --- /* * Author: atotic * Created on May 4, 2004 * License: Common Public License v1.0 */ package org.python.pydev.debug.model; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.debug.core.DebugEvent; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.model.IVariable; import org.python.pydev.debug.core.PydevDebugPlugin; import org.python.pydev.debug.model.remote.AbstractDebuggerCommand; import org.python.pydev.debug.model.remote.GetVariableCommand; import org.python.pydev.debug.model.remote.ICommandResponseListener; import org.python.pydev.debug.model.remote.RemoteDebugger; /** * * TODO Comment this class */ public class PyVariableCollection extends PyVariable implements ICommandResponseListener, IVariableLocator { IVariableLocator locator; PyVariable[] variables = new PyVariable[0]; IVariable[] waitVariables = null; int requestedVariables = 0; // Network request state: 0 did not request, 1 requested, 2 requested & arrived boolean fireChangeEvent = true; public PyVariableCollection(PyDebugTarget target, String name, String type, String value, IVariableLocator locator) { super(target, name, type, value); this.locator = locator; } public String getPyDBLocation() { return locator.getPyDBLocation() + "\t" + name; } private IVariable[] getWaitVariables() { if (waitVariables == null) { PyVariable waitVar = new PyVariable(target, "wait", "", "for network"); waitVariables = new IVariable[1]; waitVariables[0] = waitVar; } return waitVariables; } public void commandComplete(AbstractDebuggerCommand cmd) { try { String payload = ((GetVariableCommand) cmd).getResponse(); synchronized(variables) { variables = XMLUtils.XMLToVariables(target, this, payload); } } catch (CoreException e) { variables = new PyVariable[1]; variables[0] = new PyVariable(target, "Error", "pydev ERROR", "Could not resolve variable"); PydevDebugPlugin.log(IStatus.ERROR, "Error fetching a variable", e); } requestedVariables = 2; if (fireChangeEvent) target.fireEvent(new DebugEvent(this, DebugEvent.CHANGE, DebugEvent.STATE)); } public IVariable[] getVariables() throws DebugException { if (requestedVariables == 2) return variables; else if (requestedVariables == 1) return getWaitVariables(); RemoteDebugger dbg; dbg = target.getDebugger(); // send the command, and then busy-wait GetVariableCommand cmd = new GetVariableCommand(dbg, getPyDBLocation()); cmd.setCompletionListener(this); requestedVariables = 1; fireChangeEvent = false; // do not fire change event while we are waiting on response dbg.postCommand(cmd); try { // VariablesView does not deal well with children changing asynchronously. // it causes unneeded scrolling, because view preserves selection instead // of visibility. // I try to minimize the occurence here, by giving pydevd time to complete the // task before we are forced to do asynchronous notification. int i = 10; while (--i > 0 && requestedVariables != 2) Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } fireChangeEvent = true; if (requestedVariables == 2) return variables; else return getWaitVariables(); } public boolean hasVariables() throws DebugException { return true; } public String getReferenceTypeName() throws DebugException { return type; } } --- AbstractDebuggerCommand.java DELETED --- --- NEW FILE: PyVariable.java --- /* * Author: atotic * Created on Apr 28, 2004 * License: Common Public License v1.0 */ package org.python.pydev.debug.model; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.PlatformObject; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.model.IDebugTarget; import org.eclipse.debug.core.model.IValue; import org.eclipse.debug.core.model.IVariable; import org.eclipse.ui.views.properties.IPropertySource; import org.eclipse.ui.views.tasklist.ITaskListResourceAdapter; /** * * TODO Comment this class * */ public class PyVariable extends PlatformObject implements IVariable, IValue { protected String name; protected String type; protected String value; protected PyDebugTarget target; public PyVariable(PyDebugTarget target, String name, String type, String value) { this.value = value; this.name = name; this.type = type; this.target = target; } public IValue getValue() throws DebugException { return this; } public String getValueString() throws DebugException { if (value == null) return ""; if ("StringType".equals(type) || "UnicodeType".equals(type)) // quote the strings return "\"" + value + "\""; return value; } public String getName() throws DebugException { return name; } public String getModelIdentifier() { return target.getModelIdentifier(); } public IDebugTarget getDebugTarget() { return target; } public ILaunch getLaunch() { return target.getLaunch(); } /** * TODO valueChanging nterface has not been implemented yet. * When implemented, recently changed variables are shown in red. */ public boolean supportsValueModification() { return false; } public boolean hasValueChanged() throws DebugException { return false; } public void setValue(String expression) throws DebugException { } public void setValue(IValue value) throws DebugException { } public boolean verifyValue(String expression) throws DebugException { return false; } public boolean verifyValue(IValue value) throws DebugException { return false; } public Object getAdapter(Class adapter) { if (adapter.equals(ILaunch.class) || adapter.equals(IResource.class)) return target.getAdapter(adapter); else if (adapter.equals(IPropertySource.class) || adapter.equals(ITaskListResourceAdapter.class)) return super.getAdapter(adapter); // ongoing, I do not fully understand all the interfaces they'd like me to support System.err.println("PyVariable Need adapter " + adapter.toString()); return super.getAdapter(adapter); } public boolean isAllocated() throws DebugException { return true; } public IVariable[] getVariables() throws DebugException { return null; } public boolean hasVariables() throws DebugException { return false; } public String getReferenceTypeName() throws DebugException { return type; } } |