/** * Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Eclipse Public License (EPL). * Please see the license.txt included with this distribution for details. * Any modifications to this file must keep this entire header intact. */ /* * Author: atotic * Created on Apr 21, 2004 */ 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.IBreakpoint; import org.eclipse.debug.core.model.IDebugTarget; 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.AbstractDebuggerCommand; import org.python.pydev.debug.model.remote.RunToLineCommand; import org.python.pydev.debug.model.remote.SetNextCommand; import org.python.pydev.debug.model.remote.StepCommand; import org.python.pydev.debug.model.remote.ThreadRunCommand; import org.python.pydev.debug.model.remote.ThreadSuspendCommand; /** * Represents python threads. * Stack global variables are associated with threads. */ public class PyThread extends PlatformObject implements IThread { private AbstractDebugTarget target; private String name; private String id; /** * true if this is a debugger thread, that can't be killed/suspended */ private boolean isPydevThread; private boolean isSuspended = false; private boolean isStepping = false; private IStackFrame[] stack; public PyThread(AbstractDebugTarget target, String name, String id) { this.target = target; this.name = name; this.id = id; isPydevThread = id.equals("-1"); // use a special id for pydev threads } /** * If a thread is entering a suspended state, pass in the stack */ public void setSuspended(boolean state, IStackFrame[] stack) { isSuspended = state; this.stack = stack; } public String getName() throws DebugException { return name + " - " + getId(); } public String getId() { return id; } public boolean isPydevThread() { return isPydevThread; } public int getPriority() throws DebugException { return 0; } public String getModelIdentifier() { return target.getModelIdentifier(); } public IDebugTarget getDebugTarget() { return target; } public ILaunch getLaunch() { return target.getLaunch(); } public boolean canTerminate() { return !isPydevThread && !isTerminated(); } public boolean isTerminated() { return target.isTerminated(); } public void terminate() throws DebugException { target.terminate(); } public boolean canResume() { return !isPydevThread && isSuspended && !isTerminated(); } public boolean canSuspend() { return !isPydevThread && !isSuspended && !isTerminated(); } public boolean isSuspended() { return isSuspended; } public void resume() throws DebugException { if (!isPydevThread) { stack = null; isStepping = false; target.postCommand(new ThreadRunCommand(target, id)); } } public void suspend() throws DebugException { if (!isPydevThread) { stack = null; target.postCommand(new ThreadSuspendCommand(target, id)); } } public boolean canStepInto() { return canResume(); } public boolean canStepOver() { return canResume(); } public boolean canStepReturn() { return canResume(); } public boolean isStepping() { return isStepping; } public void stepInto() throws DebugException { if (!isPydevThread) { isStepping = true; target.postCommand(new StepCommand(target, AbstractDebuggerCommand.CMD_STEP_INTO, id)); } } public void stepOver() throws DebugException { if (!isPydevThread) { isStepping = true; target.postCommand(new StepCommand(target, AbstractDebuggerCommand.CMD_STEP_OVER, id)); } } public void stepReturn() throws DebugException { if (!isPydevThread) { isStepping = true; target.postCommand(new StepCommand(target, AbstractDebuggerCommand.CMD_STEP_RETURN, id)); } } public void runToLine(int line, String funcName) { isStepping = true; target.postCommand(new RunToLineCommand(target, AbstractDebuggerCommand.CMD_RUN_TO_LINE, id, line, funcName)); } public void setNextStatement(int line, String funcName) { isStepping = true; target.postCommand(new SetNextCommand(target, AbstractDebuggerCommand.CMD_SET_NEXT_STATEMENT, id, line, funcName)); } public IStackFrame[] getStackFrames() throws DebugException { if (isSuspended && stack != null) { return stack; } return new IStackFrame[0]; } public boolean hasStackFrames() throws DebugException { return (stack != null && stack.length > 0); } public IStackFrame getTopStackFrame() { return stack == null ? null : stack[0]; } 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() { // should return breakpoint that caused this thread to suspend // not implementing this seems to cause no harm PyBreakpoint[] breaks = new PyBreakpoint[0]; return breaks; } public Object getAdapter(Class adapter) { AdapterDebug.print(this, adapter); if (adapter.equals(ILaunch.class) || adapter.equals(IResource.class)) { return target.getAdapter(adapter); } else if (adapter.equals(ITaskListResourceAdapter.class)) { return null; } else if (adapter.equals(IDebugTarget.class)) { return target; } else if (adapter.equals(org.eclipse.debug.ui.actions.IRunToLineTarget.class)) { return this.target.getRunToLineTarget(); } else if (adapter.equals(IPropertySource.class) || adapter.equals(ITaskListResourceAdapter.class) || adapter.equals(org.eclipse.debug.ui.actions.IToggleBreakpointsTarget.class) || adapter.equals(org.eclipse.ui.IContributorResourceAdapter.class) || adapter.equals(org.eclipse.ui.model.IWorkbenchAdapter.class) || adapter.equals(org.eclipse.ui.IActionFilter.class)) { return super.getAdapter(adapter); } //Platform.getAdapterManager().getAdapter(this, adapter); AdapterDebug.printDontKnow(this, adapter); // ongoing, I do not fully understand all the interfaces they'd like me to support return super.getAdapter(adapter); } @Override public String toString() { return "PyThread: " + this.id; } }