blob: 5fbe2df0e29e56d5fb581145788d9a0bc9f2e74c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2018 R.Dvorak and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Radek Dvorak - initial API and implementation
*******************************************************************************/
package org.eclipse.m2m.qvt.oml.debug.core;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.core.model.IStackFrame;
import org.eclipse.debug.core.model.IThread;
import org.eclipse.m2m.qvt.oml.debug.core.vm.VMEventListener;
import org.eclipse.m2m.qvt.oml.debug.core.vm.VMStackFrame;
import org.eclipse.m2m.qvt.oml.debug.core.vm.protocol.VMEvent;
import org.eclipse.m2m.qvt.oml.debug.core.vm.protocol.VMResumeRequest;
import org.eclipse.m2m.qvt.oml.debug.core.vm.protocol.VMSuspendEvent;
public class QVTOThread extends QVTODebugElement implements IThread, VMEventListener {
private List<QVTOStackFrame> fFrames;
private List<VMStackFrame> fUnderlyingFrames;
private VMStackFrame fLastSuspendedFrame;
private boolean fIsStepping;
public QVTOThread(IQVTODebugTarget target) {
super(target);
fFrames = new ArrayList<QVTOStackFrame>();
fIsStepping = false;
target.addVMEventListener(this);
fireCreationEvent();
}
public boolean isDeferredExecution() {
// TODO
return false;
}
public boolean hasStackFrames() throws DebugException {
return isSuspended();
}
public IStackFrame[] getStackFrames() throws DebugException {
if(isSuspended()) {
if(fFrames.size() == 0) {
fillFrames();
}
}
return fFrames.toArray(new QVTOStackFrame[fFrames.size()]);
}
public int getPriority() throws DebugException {
return 0; // not it use at the moment //myWorker.getPriority();
}
public IStackFrame getTopStackFrame() throws DebugException {
if(!hasStackFrames()) {
return null;
}
IStackFrame[] frames = getStackFrames();
return frames.length > 0 ? frames[0] : null;
}
public String getName() throws DebugException {
// no underlying thread ID
return "QVTOThread"; //$NON-NLS-1$
}
public IBreakpoint[] getBreakpoints() {
IBreakpoint[] hostBreakpoints = new IBreakpoint[0];
// FIXME - add suspedendedBy(IBreakpoint); to be called by the debugger
return hostBreakpoints;
}
public boolean canResume() {
return isSuspended();
}
public boolean canSuspend() {
return !isSuspended();
}
public boolean isSuspended() {
return getDebugTarget().isSuspended();
}
public void resume() throws DebugException {
setStepping(false);
getDebugTarget().resume();
fireResumeEvent(DebugEvent.CLIENT_REQUEST);
}
public void suspend() throws DebugException {
getDebugTarget().suspend();
}
public boolean canStepInto() {
return isSuspended();
}
public void stepInto() throws DebugException {
if(!canStepInto()) {
return;
}
setStepping(true);
fireResumeEvent(DebugEvent.STEP_INTO);
getQVTODebugTarget().sendRequest(new VMResumeRequest(DebugEvent.STEP_INTO));
}
public boolean canStepOver() {
return isSuspended();
}
public void stepOver() throws DebugException {
if(!canStepOver()) {
return;
}
setStepping(true);
fireResumeEvent(DebugEvent.STEP_OVER);
getQVTODebugTarget().sendRequest(new VMResumeRequest(DebugEvent.STEP_OVER));
}
public boolean canStepReturn() {
return isSuspended();
}
public void stepReturn() throws DebugException {
if(!canStepReturn()) {
return;
}
setStepping(true);
fireResumeEvent(DebugEvent.STEP_RETURN);
getQVTODebugTarget().sendRequest(new VMResumeRequest(DebugEvent.STEP_RETURN));
}
public boolean isStepping() {
return fIsStepping;
}
private void setStepping(boolean isStepping) {
fIsStepping = isStepping;
}
public boolean canTerminate() {
return getDebugTarget().canTerminate();
}
public boolean isTerminated() {
return getDebugTarget().isTerminated();
}
public void terminate() throws DebugException {
getDebugTarget().terminate();
fFrames.clear();
}
public void handleEvent(VMEvent event) {
if(event instanceof VMSuspendEvent) {
VMSuspendEvent suspendEvent = (VMSuspendEvent) event;
if(!isStepping()) {
fFrames.clear();
} else {
VMStackFrame suspendedAtLocation = suspendEvent.stackFrames[0];
if(fLastSuspendedFrame != null && suspendedAtLocation != null &&
suspendedAtLocation.id == fLastSuspendedFrame.id && !fFrames.isEmpty()) {
fFrames.get(0).setLocation(suspendedAtLocation);
} else {
// stepped across stack frames since the last suspended
fFrames.clear();
}
}
fUnderlyingFrames = Arrays.asList(suspendEvent.stackFrames);
setStepping(false);
DebugEvent debugEvent = new DebugEvent(this, DebugEvent.SUSPEND, suspendEvent.detail);
debugEvent.setData(suspendEvent.location);
fireEvent(debugEvent);
}
}
private void fillFrames() {
if(fUnderlyingFrames == null) {
return;
}
for (VMStackFrame frame : fUnderlyingFrames) {
fFrames.add(new QVTOStackFrame(this, frame));
}
if(!fUnderlyingFrames.isEmpty()) {
fLastSuspendedFrame = fUnderlyingFrames.get(0);
}
}
}