/*
* #%~
* org.overture.ide.debug
* %%
* Copyright (C) 2008 - 2014 Overture
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #~%
*/
package org.overture.ide.debug.internal.ui.viewers.update;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.IStackFrame;
import org.eclipse.debug.core.model.IThread;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
import org.eclipse.debug.internal.ui.viewers.provisional.AbstractModelProxy;
import org.eclipse.debug.internal.ui.viewers.update.ThreadEventHandler;
import org.overture.ide.debug.core.dbgp.IDbgpStatusInterpreterThreadState.InterpreterThreadStatus;
import org.overture.ide.debug.core.model.IVdmThread;
@SuppressWarnings({ "restriction" })
public class VdmThreadEventHandler extends ThreadEventHandler
{
/**
* Map of previous TOS per thread
*/
public final static boolean DEBUG = false;
private Map<IThread, IStackFrame> fLastTopFrame = new HashMap<IThread, IStackFrame>();
public VdmThreadEventHandler(AbstractModelProxy proxy)
{
super(proxy);
}
@Override
public synchronized void dispose()
{
fLastTopFrame.clear();
super.dispose();
}
@Override
protected void handleSuspend(DebugEvent event)
{
IThread thread = (IThread) event.getSource();
if (DEBUG)
{
System.out.println("handleSuspend " + thread);
}
// TODO temporary fix. Collapses all threads except the running one
if (!isRunning(thread))
{
fireDeltaUpdatingThread(thread, IModelDelta.COLLAPSE);
}
if (event.isEvaluation() || !isRunning(thread))
{
ModelDelta delta = buildRootDelta();
ModelDelta node = addPathToThread(delta, thread);
node = node.addNode(thread, IModelDelta.NO_CHANGE);
try
{
IStackFrame frame = thread.getTopStackFrame();
if (frame != null)
{
int flag = IModelDelta.NO_CHANGE;
if (event.getDetail() == DebugEvent.EVALUATION)
{
// explicit evaluations can change content
flag = flag | IModelDelta.CONTENT;
} else if (event.getDetail() == DebugEvent.EVALUATION_IMPLICIT)
{
// implicit evaluations can change state
flag = flag | IModelDelta.STATE;
}
node.addNode(frame, flag);
// fireDelta(delta);
}
} catch (DebugException e)
{
}
} else
{
queueSuspendedThread(event);
int extras = IModelDelta.STATE;
switch (event.getDetail())
{
case DebugEvent.BREAKPOINT:
// on breakpoint also position thread to be top element
extras = IModelDelta.EXPAND | IModelDelta.REVEAL;
break;
case DebugEvent.CLIENT_REQUEST:
extras = IModelDelta.EXPAND;
break;
}
fireDeltaUpdatingSelectedFrame(thread, IModelDelta.NO_CHANGE
| extras, event);
}
}
@Override
protected void handleResume(DebugEvent event)
{
IThread thread = removeSuspendedThread(event);
if (DEBUG)
{
System.out.println("handleResume " + thread);
}
fireDeltaAndClearTopFrame(thread, IModelDelta.STATE
| IModelDelta.CONTENT);// | IModelDelta.SELECT
thread = getNextSuspendedThread();
if (thread != null)
{
fireDeltaUpdatingSelectedFrame(thread, IModelDelta.NO_CHANGE, event);// | IModelDelta.REVEAL
}
}
private void fireDeltaUpdatingSelectedFrame(IThread thread, int flags,
DebugEvent event)
{
ModelDelta delta = buildRootDelta();
ModelDelta node = addPathToThread(delta, thread);
IStackFrame prev = null;
synchronized (this)
{
prev = (IStackFrame) fLastTopFrame.get(thread);
}
IStackFrame frame = null;
try
{
Object frameToSelect = event.getData();
if (frameToSelect == null
|| !(frameToSelect instanceof IStackFrame))
{
frame = thread.getTopStackFrame();
} else
{
frame = (IStackFrame) frameToSelect;
}
} catch (DebugException e)
{
}
int threadIndex = indexOf(thread);
int childCount = childCount(thread);
if (isEqual(frame, prev))
{
if (frame == null)
{
if (thread.isSuspended())
{
// no frames, but suspended - update & select
node = node.addNode(thread, threadIndex, flags
| IModelDelta.STATE | IModelDelta.SELECT, childCount);
}
} else
{
node = node.addNode(thread, threadIndex, flags, childCount);
}
} else
{
if (event.getDetail() == DebugEvent.STEP_END)
{
if (prev == null)
{
// see bug 166602 - expand the thread if this is a step end with no previous top frame
flags = flags | IModelDelta.EXPAND;
} else if (frame == null)
{
// there was a previous frame and current is null on a step: transient state
return;
}
}
node = node.addNode(thread, threadIndex, flags
| IModelDelta.CONTENT, childCount);
}
if (frame != null)
{
node.addNode(frame, indexOf(frame), IModelDelta.STATE
| IModelDelta.SELECT, childCount(frame));
}
synchronized (this)
{
if (!isDisposed())
{
fLastTopFrame.put(thread, frame);
}
}
fireDelta(delta);
}
// @Override
// protected void handleSuspend(DebugEvent event)
// {
// IThread thread = (IThread) event.getSource();
// if (thread instanceof IVdmThread)
// {
// if (((IVdmThread) thread).getInterpreterState().getState() == InterpreterThreadStatus.RUNNING)
// {
// //super.handleSuspend(new DebugEvent(event.getSource(), event.getKind(), DebugEvent.BREAKPOINT));
// return;
// } else
// {
// //super.handleSuspend(new DebugEvent(event.getSource(), DebugEvent.EVALUATION));
// return;
// }
//
// }
// super.handleSuspend(event);
// // IThread thread = (IThread) event.getSource();
// // System.out.println("handleSuspend "+thread);
// // if(thread instanceof IVdmThread)
// // {
// // if(((IVdmThread)thread).getInterpreterState().getState()==InterpreterThreadStatus.RUNNING)
// // {
// //
// //
// // if (event.isEvaluation()) {
// // ModelDelta delta = buildRootDelta();
// // ModelDelta node = addPathToThread(delta, thread);
// // node = node.addNode(thread, IModelDelta.NO_CHANGE);
// // try {
// // IStackFrame frame = thread.getTopStackFrame();
// // if (frame != null) {
// // int flag = IModelDelta.NO_CHANGE;
// // if (event.getDetail() == DebugEvent.EVALUATION) {
// // // explicit evaluations can change content
// // flag = flag | IModelDelta.CONTENT;
// // } else if (event.getDetail() == DebugEvent.EVALUATION_IMPLICIT) {
// // // implicit evaluations can change state
// // flag = flag | IModelDelta.STATE;
// // }
// // node.addNode(frame, flag);
// // fireDelta(delta);
// // }
// // } catch (DebugException e) {
// // }
// // } else {
// // queueSuspendedThread(event);
// // int extras = IModelDelta.STATE;
// // switch (event.getDetail()) {
// // case DebugEvent.BREAKPOINT:
// // // on breakpoint also position thread to be top element
// // extras = IModelDelta.EXPAND | IModelDelta.REVEAL;
// // break;
// // case DebugEvent.CLIENT_REQUEST:
// // extras = IModelDelta.EXPAND;
// // break;
// // }
// // fireDeltaUpdatingSelectedFrame(thread, IModelDelta.NO_CHANGE | extras, event);
// // } }else{
// // System.out.println("--- skipped");
// // fireDeltaAndClearTopFrame(thread, IModelDelta.COLLAPSE);
// // }
// // }
// }
// @Override
// protected void handleResume(DebugEvent event)
// {
// IThread thread = removeSuspendedThread(event);
// System.out.println("handleResume " + thread);
// fireDeltaAndClearTopFrame(thread, IModelDelta.STATE
// | IModelDelta.CONTENT);// | IModelDelta.SELECT
// thread = getNextSuspendedThread();
// if (thread != null) {
// fireDeltaUpdatingSelectedFrame(thread, IModelDelta.NO_CHANGE , event);//| IModelDelta.REVEAL
// }
// }
@Override
protected void handleChange(DebugEvent event)
{
// System.out.println("handleChange " + event.getSource());
//
IThread thread = (IThread) event.getSource();
if (DEBUG)
{
System.out.println("handleChange " + thread);
}
if (isRunning(thread))
{
IStackFrame frame = null;
try
{
frame = thread.getTopStackFrame();
int threadIndex = indexOf(thread);
ModelDelta delta = buildRootDelta();
ModelDelta node = addPathToThread(delta, thread);
int childCount = childCount(thread);
if (DEBUG)
{
System.out.println("child: " + childCount);
}
node = node.addNode(thread, threadIndex, IModelDelta.CONTENT
| IModelDelta.STATE | IModelDelta.SELECT, childCount);
if (frame != null)
{
node.addNode(frame, indexOf(frame), IModelDelta.STATE
| IModelDelta.SELECT, childCount(frame));
}
if (DEBUG)
{
System.out.println(delta);
}
fireDelta(delta);
} catch (DebugException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
} else
{
if (event.getDetail() == DebugEvent.STATE)
{
fireDeltaUpdatingThread((IThread) event.getSource(), IModelDelta.STATE);
} else
{
fireDeltaUpdatingThread((IThread) event.getSource(), IModelDelta.CONTENT);
}
}
// IThread thread = (IThread) event.getSource();
// if(thread instanceof IVdmThread)
// {
// if(((IVdmThread)thread).getInterpreterState().getState()==InterpreterThreadStatus.RUNNING)
// {
// System.out.println(((IVdmThread)thread).getInterpreterState());
// //fireDeltaUpdatingSelectedFrame2(thread,flags ,event);//new
// DebugEvent(event.getSource(),event.getKind(),DebugEvent.STEP_END));
// IStackFrame frame = null;
// try
// {
// frame = thread.getTopStackFrame();
// int threadIndex = indexOf(thread);
// ModelDelta delta = buildRootDelta();
// ModelDelta node = addPathToThread(delta, thread);
// int childCount = childCount(thread);
// System.out.println("child: "+childCount);
// node = node.addNode(thread, threadIndex, IModelDelta.CONTENT | IModelDelta.STATE | IModelDelta.SELECT,
// childCount);
// if (frame != null) {
// node.addNode(frame, indexOf(frame), IModelDelta.STATE | IModelDelta.SELECT, childCount(frame));
//
// }
// System.out.println(delta);
// fireDelta(delta);
// } catch (DebugException e)
// {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// }}
}
@Override
protected void handleCreate(DebugEvent event)
{
fireDeltaAndClearTopFrame((IThread) event.getSource(), IModelDelta.ADDED
| IModelDelta.STATE);
}
@Override
protected void handleLateSuspend(DebugEvent suspend, DebugEvent resume)
{
// IThread thread = queueSuspendedThread(suspend);
// if (suspend.isEvaluation() && suspend.getDetail() == DebugEvent.EVALUATION_IMPLICIT) {
// // late implicit evaluation - update thread and frame
// ModelDelta delta = buildRootDelta();
// ModelDelta node = addPathToThread(delta, thread);
// node = node.addNode(thread, IModelDelta.STATE);
// try {
// IStackFrame frame = thread.getTopStackFrame();
// if (frame != null) {
// node.addNode(frame, IModelDelta.STATE);
// fireDelta(delta);
// }
// } catch (DebugException e) {
// }
// } else {
// fireDeltaUpdatingSelectedFrame(thread, IModelDelta.STATE | IModelDelta.EXPAND, suspend);
// }
// super.handleLateSuspend(suspend, resume);
// IThread thread = queueSuspendedThread(suspend);
// System.out.println("handleLateSuspend "+thread);
// if (suspend.isEvaluation() && suspend.getDetail() == DebugEvent.EVALUATION_IMPLICIT) {
// // late implicit evaluation - update thread and frame
// ModelDelta delta = buildRootDelta();
// ModelDelta node = addPathToThread(delta, thread);
// node = node.addNode(thread, IModelDelta.STATE);
// try {
// IStackFrame frame = thread.getTopStackFrame();
// if (frame != null) {
// node.addNode(frame, IModelDelta.STATE);
// fireDelta(delta);
// }
// } catch (DebugException e) {
// }
// } else {
// fireDeltaUpdatingSelectedFrame(thread, IModelDelta.STATE | IModelDelta.EXPAND, suspend);
// }
}
// private void fireDeltaUpdatingSelectedFrame(IThread thread, int flags, DebugEvent event) {
// if(thread instanceof IVdmThread)
// {
// if(((IVdmThread)thread).getInterpreterState().getState()==InterpreterThreadStatus.RUNNING)
// {
// System.out.println(((IVdmThread)thread).getInterpreterState());
// //fireDeltaUpdatingSelectedFrame2(thread,flags ,event);//new
// DebugEvent(event.getSource(),event.getKind(),DebugEvent.STEP_END));
// IStackFrame frame = null;
// try
// {
// frame = thread.getTopStackFrame();
// int threadIndex = indexOf(thread);
// ModelDelta delta = buildRootDelta();
// ModelDelta node = addPathToThread(delta, thread);
// int childCount = childCount(thread);
// System.out.println("child: "+childCount);
// node = node.addNode(thread, threadIndex, flags | IModelDelta.STATE | IModelDelta.SELECT, childCount);
// if (frame != null) {
// node.addNode(frame, indexOf(frame), IModelDelta.STATE | IModelDelta.SELECT, childCount(frame));
//
// }
// System.out.println(delta);
// fireDelta(delta);
// } catch (DebugException e)
// {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// }else
// {
// // ModelDelta delta = buildRootDelta();
// // ModelDelta node = addPathToThread(delta, thread);
// // node = node.addNode(thread, IModelDelta.COLLAPSE);
// // fireDelta(delta);
// }
// }
// }
// private void fireDeltaUpdatingSelectedFrame2(IThread thread, int flags, DebugEvent event) {
// ModelDelta delta = buildRootDelta();
// ModelDelta node = addPathToThread(delta, thread);
// IStackFrame prev = null;
// synchronized (this) {
// prev = (IStackFrame) fLastTopFrame.get(thread);
// }
// IStackFrame frame = null;
// try {
// Object frameToSelect = event.getData();
// if (frameToSelect == null || !(frameToSelect instanceof IStackFrame)) {
// frame = thread.getTopStackFrame();
// } else {
// frame = (IStackFrame)frameToSelect;
// }
// } catch (DebugException e) {
// }
// int threadIndex = indexOf(thread);
// int childCount = childCount(thread);
// if (isEqual(frame, prev)) {
// if (frame == null) {
// if (thread.isSuspended()) {
// // no frames, but suspended - update & select
// node = node.addNode(thread, threadIndex, flags | IModelDelta.STATE | IModelDelta.SELECT, childCount);
// }
// } else {
// node = node.addNode(thread, threadIndex, flags, childCount);
// }
// } else {
// if (event.getDetail() == DebugEvent.STEP_END) {
// if (prev == null) {
// // see bug 166602 - expand the thread if this is a step end with no previous top frame
// flags = flags | IModelDelta.EXPAND;
// } else if (frame == null) {
// // there was a previous frame and current is null on a step: transient state
// return;
// }
// }
// node = node.addNode(thread, threadIndex, flags | IModelDelta.CONTENT, childCount);
// }
// if (frame != null) {
// node.addNode(frame, indexOf(frame), IModelDelta.STATE | IModelDelta.SELECT, childCount(frame));
//
// }
// synchronized (this) {
// if (!isDisposed()) {
// fLastTopFrame.put(thread, frame);
// }
// }
// System.out.println(delta);
// fireDelta(delta);
// }
//
private boolean isEqual(Object o1, Object o2)
{
if (o1 == o2)
{
return true;
}
if (o1 == null)
{
return false;
}
return o1.equals(o2);
}
// private void fireDeltaAndClearTopFrame(IThread thread, int flags)
// {
// ModelDelta delta = buildRootDelta();
// ModelDelta node = addPathToThread(delta, thread);
// node.addNode(thread, indexOf(thread), flags);
// synchronized (this)
// {
// fLastTopFrame.remove(thread);
// }
// fireDelta(delta);
// }
private void fireDeltaAndClearTopFrame(IThread thread, int flags)
{
ModelDelta delta = buildRootDelta();
ModelDelta node = addPathToThread(delta, thread);
node.addNode(thread, indexOf(thread), flags);
synchronized (this)
{
fLastTopFrame.remove(thread);
}
fireDelta(delta);
}
//
// //
private void fireDeltaUpdatingThread(IThread thread, int flags)
{
ModelDelta delta = buildRootDelta();
ModelDelta node = addPathToThread(delta, thread);
node = node.addNode(thread, flags);
fireDelta(delta);
}
public boolean isRunning(IThread thread)
{
if (thread instanceof IVdmThread)
{
IVdmThread t = (IVdmThread) thread;
return t.getInterpreterState() != null
&& t.getInterpreterState().getState() == InterpreterThreadStatus.RUNNING;
}
return false;
}
}