mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Bug 241133: [source lookup] Optimize source lookup.
This commit is contained in:
parent
bbe916cd1a
commit
4c747c78ad
3 changed files with 443 additions and 200 deletions
|
@ -22,6 +22,7 @@ import java.util.concurrent.TimeUnit;
|
||||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||||
import org.eclipse.dd.dsf.concurrent.DsfExecutor;
|
import org.eclipse.dd.dsf.concurrent.DsfExecutor;
|
||||||
import org.eclipse.dd.dsf.concurrent.DsfRunnable;
|
import org.eclipse.dd.dsf.concurrent.DsfRunnable;
|
||||||
|
import org.eclipse.dd.dsf.concurrent.IDsfStatusConstants;
|
||||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||||
import org.eclipse.dd.dsf.datamodel.AbstractDMEvent;
|
import org.eclipse.dd.dsf.datamodel.AbstractDMEvent;
|
||||||
import org.eclipse.dd.dsf.datamodel.DMContexts;
|
import org.eclipse.dd.dsf.datamodel.DMContexts;
|
||||||
|
@ -64,7 +65,7 @@ public final class SteppingController implements IStepQueueManager
|
||||||
* The depth of the step queue. In other words, the maximum number of steps
|
* The depth of the step queue. In other words, the maximum number of steps
|
||||||
* that are queued before the step queue manager is throwing them away.
|
* that are queued before the step queue manager is throwing them away.
|
||||||
*/
|
*/
|
||||||
public final static int STEP_QUEUE_DEPTH = 1;
|
public final static int STEP_QUEUE_DEPTH = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The maximum delay (in milliseconds) between steps when synchronized
|
* The maximum delay (in milliseconds) between steps when synchronized
|
||||||
|
@ -101,8 +102,11 @@ public final class SteppingController implements IStepQueueManager
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class StepRequest {
|
private static class StepRequest {
|
||||||
|
IExecutionDMContext fContext;
|
||||||
StepType fStepType;
|
StepType fStepType;
|
||||||
StepRequest(StepType type) {
|
boolean inProgress = false;
|
||||||
|
StepRequest(IExecutionDMContext execCtx, StepType type) {
|
||||||
|
fContext = execCtx;
|
||||||
fStepType = type;
|
fStepType = type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -187,6 +191,13 @@ public final class SteppingController implements IStepQueueManager
|
||||||
fSynchronizedStepping = enable;
|
fSynchronizedStepping = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return whether synchronized stepping is enabled.
|
||||||
|
*/
|
||||||
|
public boolean isSynchronizedSteppingEnabled() {
|
||||||
|
return fSynchronizedStepping;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configure the minimum time (in milliseconds) to wait between steps.
|
* Configure the minimum time (in milliseconds) to wait between steps.
|
||||||
*
|
*
|
||||||
|
@ -346,7 +357,7 @@ public final class SteppingController implements IStepQueueManager
|
||||||
* context.
|
* context.
|
||||||
*/
|
*/
|
||||||
public int getPendingStepCount(IExecutionDMContext execCtx) {
|
public int getPendingStepCount(IExecutionDMContext execCtx) {
|
||||||
List<StepRequest> stepQueue = fStepQueues.get(execCtx);
|
List<StepRequest> stepQueue = getStepQueue(execCtx);
|
||||||
if (stepQueue == null) return 0;
|
if (stepQueue == null) return 0;
|
||||||
return stepQueue.size();
|
return stepQueue.size();
|
||||||
}
|
}
|
||||||
|
@ -357,38 +368,28 @@ public final class SteppingController implements IStepQueueManager
|
||||||
* @param stepType Type of step to execute.
|
* @param stepType Type of step to execute.
|
||||||
*/
|
*/
|
||||||
public void enqueueStep(final IExecutionDMContext execCtx, final StepType stepType) {
|
public void enqueueStep(final IExecutionDMContext execCtx, final StepType stepType) {
|
||||||
if (shouldDelayStep(execCtx)) {
|
if (!shouldDelayStep(execCtx) || doCanEnqueueStep(execCtx, stepType)) {
|
||||||
if (doCanEnqueueStep(execCtx, stepType)) {
|
|
||||||
doEnqueueStep(execCtx, stepType);
|
doEnqueueStep(execCtx, stepType);
|
||||||
if (!getRunControl().isStepping(execCtx)) {
|
|
||||||
processStepQueue(execCtx);
|
processStepQueue(execCtx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
getRunControl().canStep(
|
|
||||||
execCtx, stepType, new DataRequestMonitor<Boolean>(getExecutor(), null) {
|
|
||||||
@Override
|
|
||||||
protected void handleCompleted() {
|
|
||||||
if (isSuccess() && getData()) {
|
|
||||||
if (isSteppingDisabled(execCtx)) {
|
|
||||||
doEnqueueStep(execCtx, stepType);
|
|
||||||
} else {
|
|
||||||
doStep(execCtx, stepType);
|
|
||||||
}
|
|
||||||
} else if (doCanEnqueueStep(execCtx, stepType)) {
|
|
||||||
doEnqueueStep(execCtx, stepType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void doStep(final IExecutionDMContext execCtx, final StepType stepType) {
|
private void doStep(final IExecutionDMContext execCtx, final StepType stepType) {
|
||||||
if (fSynchronizedStepping) {
|
if (fSynchronizedStepping) {
|
||||||
disableStepping(execCtx);
|
disableStepping(execCtx);
|
||||||
}
|
}
|
||||||
updateLastStepTime(execCtx);
|
updateLastStepTime(execCtx);
|
||||||
getRunControl().step(execCtx, stepType, new RequestMonitor(getExecutor(), null));
|
getRunControl().step(execCtx, stepType, new RequestMonitor(getExecutor(), null) {
|
||||||
|
@Override
|
||||||
|
protected void handleFailure() {
|
||||||
|
if (getStatus().getCode() == IDsfStatusConstants.INVALID_STATE) {
|
||||||
|
// Ignore errors. During fast stepping there can be expected race
|
||||||
|
// conditions leading to stepping errors.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
super.handleFailure();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -404,7 +405,7 @@ public final class SteppingController implements IStepQueueManager
|
||||||
fStepQueues.put(execCtx, stepQueue);
|
fStepQueues.put(execCtx, stepQueue);
|
||||||
}
|
}
|
||||||
if (stepQueue.size() < fQueueDepth) {
|
if (stepQueue.size() < fQueueDepth) {
|
||||||
stepQueue.add(new StepRequest(stepType));
|
stepQueue.add(new StepRequest(execCtx, stepType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,7 +429,8 @@ public final class SteppingController implements IStepQueueManager
|
||||||
if (isSteppingDisabled(execCtx)) {
|
if (isSteppingDisabled(execCtx)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (fStepQueues.containsKey(execCtx)) {
|
final List<StepRequest> queue = getStepQueue(execCtx);
|
||||||
|
if (queue != null) {
|
||||||
final int stepDelay = getStepDelay(execCtx);
|
final int stepDelay = getStepDelay(execCtx);
|
||||||
if (stepDelay > 0) {
|
if (stepDelay > 0) {
|
||||||
getExecutor().schedule(new DsfRunnable() {
|
getExecutor().schedule(new DsfRunnable() {
|
||||||
|
@ -438,25 +440,41 @@ public final class SteppingController implements IStepQueueManager
|
||||||
}, stepDelay, TimeUnit.MILLISECONDS);
|
}, stepDelay, TimeUnit.MILLISECONDS);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
List<StepRequest> queue = fStepQueues.get(execCtx);
|
final StepRequest request = queue.get(0);
|
||||||
final StepRequest request = queue.remove(queue.size() - 1);
|
if (!request.inProgress) {
|
||||||
if (queue.isEmpty()) fStepQueues.remove(execCtx);
|
request.inProgress = true;
|
||||||
getRunControl().canStep(
|
getRunControl().canStep(
|
||||||
execCtx, request.fStepType,
|
execCtx, request.fStepType,
|
||||||
new DataRequestMonitor<Boolean>(getExecutor(), null) {
|
new DataRequestMonitor<Boolean>(getExecutor(), null) {
|
||||||
@Override
|
@Override
|
||||||
protected void handleCompleted() {
|
protected void handleCompleted() {
|
||||||
if (isSuccess() && getData()) {
|
if (isSuccess() && getData()) {
|
||||||
doStep(execCtx, request.fStepType);
|
queue.remove(0);
|
||||||
|
if (queue.isEmpty()) fStepQueues.remove(request.fContext);
|
||||||
|
doStep(request.fContext, request.fStepType);
|
||||||
} else {
|
} else {
|
||||||
// For whatever reason we can't step anymore, so clear out
|
// For whatever reason we can't step anymore, so clear out
|
||||||
// the step queue.
|
// the step queue.
|
||||||
fStepQueues.remove(execCtx);
|
fStepQueues.remove(request.fContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<StepRequest> getStepQueue(IExecutionDMContext execCtx) {
|
||||||
|
List<StepRequest> queue = fStepQueues.get(execCtx);
|
||||||
|
if (queue == null) {
|
||||||
|
for (IExecutionDMContext stepCtx : fStepQueues.keySet()) {
|
||||||
|
if (DMContexts.isAncestorOf(stepCtx, execCtx)) {
|
||||||
|
queue = fStepQueues.get(stepCtx);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return queue;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disable stepping for the given execution context.
|
* Disable stepping for the given execution context.
|
||||||
|
@ -514,8 +532,9 @@ public final class SteppingController implements IStepQueueManager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return disabled;
|
return disabled;
|
||||||
|
} else {
|
||||||
|
return getRunControl().isStepping(execCtx);
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void handlePropertyChanged(final IPreferenceStore store, final PropertyChangeEvent event) {
|
protected void handlePropertyChanged(final IPreferenceStore store, final PropertyChangeEvent event) {
|
||||||
|
@ -574,5 +593,4 @@ public final class SteppingController implements IStepQueueManager
|
||||||
enableStepping(e.getDMContext());
|
enableStepping(e.getDMContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,10 +12,12 @@
|
||||||
package org.eclipse.dd.dsf.debug.ui.sourcelookup;
|
package org.eclipse.dd.dsf.debug.ui.sourcelookup;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.LinkedList;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.RejectedExecutionException;
|
import java.util.concurrent.RejectedExecutionException;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||||
import org.eclipse.core.filesystem.EFS;
|
import org.eclipse.core.filesystem.EFS;
|
||||||
|
@ -51,14 +53,20 @@ import org.eclipse.dd.dsf.service.DsfSession;
|
||||||
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.IDMVMContext;
|
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.IDMVMContext;
|
||||||
import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector;
|
import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector;
|
||||||
import org.eclipse.debug.core.sourcelookup.ISourceLookupParticipant;
|
import org.eclipse.debug.core.sourcelookup.ISourceLookupParticipant;
|
||||||
|
import org.eclipse.debug.ui.DebugUITools;
|
||||||
import org.eclipse.debug.ui.IDebugUIConstants;
|
import org.eclipse.debug.ui.IDebugUIConstants;
|
||||||
import org.eclipse.debug.ui.sourcelookup.CommonSourceNotFoundEditorInput;
|
import org.eclipse.debug.ui.sourcelookup.CommonSourceNotFoundEditorInput;
|
||||||
import org.eclipse.debug.ui.sourcelookup.ISourceDisplay;
|
import org.eclipse.debug.ui.sourcelookup.ISourceDisplay;
|
||||||
import org.eclipse.jface.text.BadLocationException;
|
import org.eclipse.jface.text.BadLocationException;
|
||||||
import org.eclipse.jface.text.IDocument;
|
import org.eclipse.jface.text.IDocument;
|
||||||
import org.eclipse.jface.text.IRegion;
|
import org.eclipse.jface.text.IRegion;
|
||||||
|
import org.eclipse.jface.text.ITextOperationTarget;
|
||||||
|
import org.eclipse.jface.text.ITextViewer;
|
||||||
|
import org.eclipse.jface.text.ITextViewerExtension5;
|
||||||
import org.eclipse.jface.text.Position;
|
import org.eclipse.jface.text.Position;
|
||||||
import org.eclipse.swt.custom.BusyIndicator;
|
import org.eclipse.swt.custom.BusyIndicator;
|
||||||
|
import org.eclipse.swt.custom.StyledText;
|
||||||
|
import org.eclipse.swt.graphics.Rectangle;
|
||||||
import org.eclipse.swt.widgets.Display;
|
import org.eclipse.swt.widgets.Display;
|
||||||
import org.eclipse.ui.IEditorDescriptor;
|
import org.eclipse.ui.IEditorDescriptor;
|
||||||
import org.eclipse.ui.IEditorInput;
|
import org.eclipse.ui.IEditorInput;
|
||||||
|
@ -67,9 +75,11 @@ import org.eclipse.ui.IEditorRegistry;
|
||||||
import org.eclipse.ui.IWorkbenchPage;
|
import org.eclipse.ui.IWorkbenchPage;
|
||||||
import org.eclipse.ui.PartInitException;
|
import org.eclipse.ui.PartInitException;
|
||||||
import org.eclipse.ui.PlatformUI;
|
import org.eclipse.ui.PlatformUI;
|
||||||
|
import org.eclipse.ui.editors.text.EditorsUI;
|
||||||
import org.eclipse.ui.ide.FileStoreEditorInput;
|
import org.eclipse.ui.ide.FileStoreEditorInput;
|
||||||
import org.eclipse.ui.part.FileEditorInput;
|
import org.eclipse.ui.part.FileEditorInput;
|
||||||
import org.eclipse.ui.progress.UIJob;
|
import org.eclipse.ui.progress.UIJob;
|
||||||
|
import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
|
||||||
import org.eclipse.ui.texteditor.IDocumentProvider;
|
import org.eclipse.ui.texteditor.IDocumentProvider;
|
||||||
import org.eclipse.ui.texteditor.ITextEditor;
|
import org.eclipse.ui.texteditor.ITextEditor;
|
||||||
|
|
||||||
|
@ -92,30 +102,63 @@ import org.eclipse.ui.texteditor.ITextEditor;
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
public class DsfSourceDisplayAdapter implements ISourceDisplay, ISteppingControlParticipant
|
public class DsfSourceDisplayAdapter implements ISourceDisplay, ISteppingControlParticipant
|
||||||
{
|
{
|
||||||
|
private static final class FrameData {
|
||||||
|
IFrameDMContext fDmc;
|
||||||
|
int fLine;
|
||||||
|
int fLevel;
|
||||||
|
String fFile;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
FrameData other = (FrameData) obj;
|
||||||
|
if (!fDmc.equals(other.fDmc))
|
||||||
|
return false;
|
||||||
|
if (fFile == null) {
|
||||||
|
if (other.fFile != null)
|
||||||
|
return false;
|
||||||
|
} else if (!fFile.equals(other.fFile))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether the given frame data instance refers to the very same location.
|
||||||
|
*
|
||||||
|
* @param frameData
|
||||||
|
* @return <code>true</code> if the frame data refers to the same location
|
||||||
|
*/
|
||||||
|
public boolean isIdentical(FrameData frameData) {
|
||||||
|
return equals(frameData) && fLine == frameData.fLine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A job to perform source lookup on the given DMC.
|
* A job to perform source lookup on the given DMC.
|
||||||
*/
|
*/
|
||||||
class LookupJob extends Job {
|
class LookupJob extends Job {
|
||||||
|
|
||||||
private IDMContext fDmc;
|
private final IWorkbenchPage fPage;
|
||||||
private IWorkbenchPage fPage;
|
private final FrameData fFrameData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new source lookup job.
|
* Constructs a new source lookup job.
|
||||||
*/
|
*/
|
||||||
public LookupJob(IDMContext dmc, IWorkbenchPage page) {
|
public LookupJob(FrameData frameData, IWorkbenchPage page) {
|
||||||
super("DSF Source Lookup"); //$NON-NLS-1$
|
super("DSF Source Lookup"); //$NON-NLS-1$
|
||||||
setPriority(Job.INTERACTIVE);
|
setPriority(Job.INTERACTIVE);
|
||||||
setSystem(true);
|
setSystem(true);
|
||||||
fDmc = dmc;
|
fFrameData = frameData;
|
||||||
fPage = page;
|
fPage = page;
|
||||||
}
|
}
|
||||||
|
|
||||||
IDMContext getDmc() { return fDmc; }
|
IDMContext getDmc() { return fFrameData.fDmc; }
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
protected IStatus run(final IProgressMonitor monitor) {
|
protected IStatus run(final IProgressMonitor monitor) {
|
||||||
if (monitor.isCanceled()) {
|
if (monitor.isCanceled()) {
|
||||||
|
@ -126,22 +169,23 @@ public class DsfSourceDisplayAdapter implements ISourceDisplay, ISteppingControl
|
||||||
executeFromJob(new DsfRunnable() { public void run() {
|
executeFromJob(new DsfRunnable() { public void run() {
|
||||||
if (!monitor.isCanceled()) {
|
if (!monitor.isCanceled()) {
|
||||||
fPrevResult = result;
|
fPrevResult = result;
|
||||||
fPrevModelContext = fDmc;
|
fPrevFrameData = fFrameData;
|
||||||
fRunningLookupJob = null;
|
fRunningLookupJob = null;
|
||||||
startDisplayJob(fPrevResult, fPage);
|
startDisplayJob(fPrevResult, fFrameData, fPage);
|
||||||
}
|
}
|
||||||
}});
|
}});
|
||||||
return Status.OK_STATUS;
|
return Status.OK_STATUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SourceLookupResult performLookup() {
|
private SourceLookupResult performLookup() {
|
||||||
SourceLookupResult result = new SourceLookupResult(fDmc, null, null, null);
|
IDMContext dmc = fFrameData.fDmc;
|
||||||
|
SourceLookupResult result = new SourceLookupResult(dmc , null, null, null);
|
||||||
String editorId = null;
|
String editorId = null;
|
||||||
IEditorInput editorInput = null;
|
IEditorInput editorInput = null;
|
||||||
Object sourceElement = fSourceLookup.getSourceElement(fDmc);
|
Object sourceElement = fSourceLookup.getSourceElement(dmc);
|
||||||
|
|
||||||
if (sourceElement == null) {
|
if (sourceElement == null) {
|
||||||
editorInput = new CommonSourceNotFoundEditorInput(fDmc);
|
editorInput = new CommonSourceNotFoundEditorInput(dmc);
|
||||||
editorId = IDebugUIConstants.ID_COMMON_SOURCE_NOT_FOUND_EDITOR;
|
editorId = IDebugUIConstants.ID_COMMON_SOURCE_NOT_FOUND_EDITOR;
|
||||||
} else if (sourceElement instanceof IFile) {
|
} else if (sourceElement instanceof IFile) {
|
||||||
editorId = getEditorIdForFilename(((IFile)sourceElement).getName());
|
editorId = getEditorIdForFilename(((IFile)sourceElement).getName());
|
||||||
|
@ -153,7 +197,7 @@ public class DsfSourceDisplayAdapter implements ISourceDisplay, ISteppingControl
|
||||||
editorInput = new FileStoreEditorInput(fileStore);
|
editorInput = new FileStoreEditorInput(fileStore);
|
||||||
editorId = getEditorIdForFilename(uriLocation.getPath());
|
editorId = getEditorIdForFilename(uriLocation.getPath());
|
||||||
} catch (CoreException e) {
|
} catch (CoreException e) {
|
||||||
editorInput = new CommonSourceNotFoundEditorInput(fDmc);
|
editorInput = new CommonSourceNotFoundEditorInput(dmc);
|
||||||
editorId = IDebugUIConstants.ID_COMMON_SOURCE_NOT_FOUND_EDITOR;
|
editorId = IDebugUIConstants.ID_COMMON_SOURCE_NOT_FOUND_EDITOR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -181,44 +225,60 @@ public class DsfSourceDisplayAdapter implements ISourceDisplay, ISteppingControl
|
||||||
class DisplayJob extends UIJob {
|
class DisplayJob extends UIJob {
|
||||||
private SourceLookupResult fResult;
|
private SourceLookupResult fResult;
|
||||||
private IWorkbenchPage fPage;
|
private IWorkbenchPage fPage;
|
||||||
|
private FrameData fFrameData;
|
||||||
|
|
||||||
|
private DsfRunnable fDisplayJobFinishedRunnable = new DsfRunnable() {
|
||||||
|
public void run() {
|
||||||
|
// If the current display job does not match up with "this", it means that this job got canceled
|
||||||
|
// after it already completed and after this runnable was queued into the dispatch thread.
|
||||||
|
if (fRunningDisplayJob == DisplayJob.this) {
|
||||||
|
fRunningDisplayJob = null;
|
||||||
|
if (!fDoneStepping.getAndSet(true)) {
|
||||||
|
doneStepping(fResult.getDmc());
|
||||||
|
}
|
||||||
|
serviceDisplayAndClearingJobs();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private AtomicBoolean fDoneStepping = new AtomicBoolean(false);
|
||||||
|
private IRegion fRegion;
|
||||||
|
private ITextViewer fTextViewer;
|
||||||
|
|
||||||
IDMContext getDmc() { return fResult.getDmc(); }
|
IDMContext getDmc() { return fResult.getDmc(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new source display job
|
* Constructs a new source display job
|
||||||
*/
|
*/
|
||||||
public DisplayJob(SourceLookupResult result, IWorkbenchPage page) {
|
public DisplayJob(SourceLookupResult result, FrameData frameData, IWorkbenchPage page) {
|
||||||
super("Debug Source Display"); //$NON-NLS-1$
|
super("Debug Source Display"); //$NON-NLS-1$
|
||||||
setSystem(true);
|
setSystem(true);
|
||||||
setPriority(Job.INTERACTIVE);
|
setPriority(Job.INTERACTIVE);
|
||||||
fResult = result;
|
fResult = result;
|
||||||
|
fFrameData = frameData;
|
||||||
fPage = page;
|
fPage = page;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public IStatus runInUIThread(final IProgressMonitor monitor) {
|
public IStatus runInUIThread(final IProgressMonitor monitor) {
|
||||||
DsfRunnable displayJobFinishedRunnable = new DsfRunnable() {
|
|
||||||
public void run() {
|
|
||||||
// If the current display job does not match up with "this", it means that this job got cancelled
|
|
||||||
// after it already completed and after this runnable was queued into the dispatch thread.
|
|
||||||
if (fRunningDisplayJob == DisplayJob.this) {
|
|
||||||
fRunningDisplayJob = null;
|
|
||||||
serviceDisplayAndClearingJobs();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (monitor.isCanceled()) {
|
if (monitor.isCanceled()) {
|
||||||
executeFromJob(displayJobFinishedRunnable);
|
executeFromJob(fDisplayJobFinishedRunnable);
|
||||||
return Status.CANCEL_STATUS;
|
return Status.CANCEL_STATUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fRegion != null && fTextViewer != null) {
|
||||||
|
if (fRunningDisplayJob == this) {
|
||||||
|
if (!shouldCancelSelectionChange()) {
|
||||||
|
enableLineBackgroundPainter();
|
||||||
|
fTextViewer.setSelectedRange(fRegion.getOffset(), 0);
|
||||||
|
}
|
||||||
|
executeFromJob(fDisplayJobFinishedRunnable);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
IEditorPart editor = openEditor(fResult, fPage);
|
IEditorPart editor = openEditor(fResult, fPage);
|
||||||
if (editor == null) {
|
if (editor == null) {
|
||||||
executeFromJob(displayJobFinishedRunnable);
|
executeFromJob(fDisplayJobFinishedRunnable);
|
||||||
return Status.OK_STATUS;
|
return Status.OK_STATUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,12 +289,42 @@ public class DsfSourceDisplayAdapter implements ISourceDisplay, ISteppingControl
|
||||||
textEditor = (ITextEditor) editor.getAdapter(ITextEditor.class);
|
textEditor = (ITextEditor) editor.getAdapter(ITextEditor.class);
|
||||||
}
|
}
|
||||||
if (textEditor != null) {
|
if (textEditor != null) {
|
||||||
positionEditor(textEditor, fResult.getDmc());
|
if (positionEditor(textEditor, fFrameData)) {
|
||||||
|
return Status.OK_STATUS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
executeFromJob(fDisplayJobFinishedRunnable);
|
||||||
|
}
|
||||||
|
return Status.OK_STATUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
executeFromJob(displayJobFinishedRunnable);
|
private boolean shouldCancelSelectionChange() {
|
||||||
|
Query<Boolean> delaySelectionChangeQuery = new Query<Boolean>() {
|
||||||
|
@Override
|
||||||
|
protected void execute(DataRequestMonitor<Boolean> rm) {
|
||||||
|
IExecutionDMContext execCtx = DMContexts.getAncestorOfType(fFrameData.fDmc,
|
||||||
|
IExecutionDMContext.class);
|
||||||
|
|
||||||
return Status.OK_STATUS;
|
IRunControl runControl = fServicesTracker.getService(IRunControl.class);
|
||||||
|
rm.setData(runControl != null && execCtx != null &&
|
||||||
|
(fController.getPendingStepCount(execCtx) != 0 || runControl.isStepping(execCtx)));
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
fController.getExecutor().execute(delaySelectionChangeQuery);
|
||||||
|
} catch (RejectedExecutionException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return delaySelectionChangeQuery.get();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
return false;
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -275,68 +365,90 @@ public class DsfSourceDisplayAdapter implements ISourceDisplay, ISteppingControl
|
||||||
/**
|
/**
|
||||||
* Positions the text editor for the given stack frame
|
* Positions the text editor for the given stack frame
|
||||||
*/
|
*/
|
||||||
private void positionEditor(ITextEditor editor, final IDMContext dmc) {
|
private boolean positionEditor(ITextEditor editor, final FrameData frameData) {
|
||||||
if (!(dmc instanceof IFrameDMContext)) return;
|
|
||||||
final IFrameDMContext frameDmc = (IFrameDMContext)dmc;
|
|
||||||
|
|
||||||
// We need to retrieve the frame level and line number from the service.
|
|
||||||
// Normally we could just get the needed information from IFrameDMData, but
|
|
||||||
// IFrameDMData, which derives from IModelData can only be accessed on the
|
|
||||||
// dispatch thread, so we need to copy over relevant information from
|
|
||||||
// IFrameDMData into this structure so we can read it in the job thread.
|
|
||||||
class FramePositioningData {
|
|
||||||
int fLine;
|
|
||||||
int fLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Query the service for frame data. We are calling from a job thread,
|
|
||||||
// so we use the Query.get() method, which will block until the
|
|
||||||
// query is completed.
|
|
||||||
Query<FramePositioningData> query = new Query<FramePositioningData>() {
|
|
||||||
@Override
|
|
||||||
protected void execute(final DataRequestMonitor<FramePositioningData> rm) {
|
|
||||||
IStack stackService = fServicesTracker.getService(IStack.class);
|
|
||||||
if (stackService == null) {
|
|
||||||
doneException(new CoreException(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, -1, "Stack data not available", null))); //$NON-NLS-1$
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
stackService.getFrameData(
|
|
||||||
frameDmc,
|
|
||||||
new DataRequestMonitor<IFrameDMData>(fExecutor, rm) {
|
|
||||||
@Override
|
|
||||||
public void handleSuccess() {
|
|
||||||
FramePositioningData clientData = new FramePositioningData();
|
|
||||||
clientData.fLevel = frameDmc.getLevel();
|
|
||||||
// Document line numbers are 0-based. While debugger line numbers are 1-based.
|
|
||||||
clientData.fLine = getData().getLine() - 1;
|
|
||||||
rm.setData(clientData);
|
|
||||||
rm.done();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
try {
|
|
||||||
fExecutor.execute(query);
|
|
||||||
FramePositioningData framePositioningData = query.get();
|
|
||||||
// If the frame data is not available, or the line number is not
|
|
||||||
// known, give up.
|
|
||||||
if (framePositioningData == null || framePositioningData.fLevel < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Position and annotate the editor.
|
// Position and annotate the editor.
|
||||||
IRegion region= getLineInformation(editor, framePositioningData.fLine);
|
fRegion= getLineInformation(editor, frameData.fLine);
|
||||||
if (region != null) {
|
if (fRegion != null) {
|
||||||
editor.selectAndReveal(region.getOffset(), 0);
|
// add annotation
|
||||||
fIPManager.addAnnotation(
|
fIPManager.addAnnotation(
|
||||||
editor, frameDmc, new Position(region.getOffset(), region.getLength()),
|
editor, frameData.fDmc, new Position(fRegion.getOffset(), fRegion.getLength()),
|
||||||
framePositioningData.fLevel == 0);
|
frameData.fLevel == 0);
|
||||||
|
|
||||||
|
// this is a dirty trick to get access to the ITextViewer of the editor
|
||||||
|
Object tot = editor.getAdapter(ITextOperationTarget.class);
|
||||||
|
if (tot instanceof ITextViewer) {
|
||||||
|
fTextViewer = (ITextViewer)tot;
|
||||||
|
int widgetLine = frameData.fLine;
|
||||||
|
if (tot instanceof ITextViewerExtension5) {
|
||||||
|
ITextViewerExtension5 ext5 = (ITextViewerExtension5) tot;
|
||||||
|
// expand region if collapsed
|
||||||
|
ext5.exposeModelRange(fRegion);
|
||||||
|
widgetLine = ext5.modelLine2WidgetLine(widgetLine);
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) { assert false : "Interrupted exception in DSF thread"; //$NON-NLS-1$
|
revealLine(fTextViewer, widgetLine);
|
||||||
} catch (ExecutionException e) { // Ignore
|
|
||||||
|
if (fStepCount > 0 && fSelectionChangeDelay > 0) {
|
||||||
|
disableLineBackgroundPainter();
|
||||||
|
// reschedule for selection change
|
||||||
|
schedule(fSelectionChangeDelay);
|
||||||
|
if (!fDoneStepping.getAndSet(true)) {
|
||||||
|
doneStepping(getDmc());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
fTextViewer.setSelectedRange(fRegion.getOffset(), 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
editor.selectAndReveal(fRegion.getOffset(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scroll the given line into the visible area if it is not yet visible.
|
||||||
|
* @param focusLine
|
||||||
|
* @see org.eclipse.jface.text.TextViewer#revealRange(int, int)
|
||||||
|
*/
|
||||||
|
private void revealLine(ITextViewer viewer, int focusLine) {
|
||||||
|
StyledText textWidget = viewer.getTextWidget();
|
||||||
|
int top = textWidget.getTopIndex();
|
||||||
|
if (top > -1) {
|
||||||
|
|
||||||
|
// scroll vertically
|
||||||
|
int lines = getEstimatedVisibleLinesInViewport(textWidget);
|
||||||
|
int bottom = top + lines;
|
||||||
|
|
||||||
|
int bottomBuffer = Math.max(1, lines / 3);
|
||||||
|
|
||||||
|
if (focusLine >= top && focusLine <= bottom - bottomBuffer) {
|
||||||
|
// do not scroll at all as it is already visible
|
||||||
|
} else {
|
||||||
|
if (focusLine > bottom - bottomBuffer && focusLine <= bottom) {
|
||||||
|
// focusLine is already in bottom bufferZone
|
||||||
|
// scroll to top of bottom bufferzone - for smooth down-scrolling
|
||||||
|
int scrollDelta = focusLine - (bottom - bottomBuffer);
|
||||||
|
textWidget.setTopIndex(top + scrollDelta);
|
||||||
|
} else {
|
||||||
|
// scroll to top of visible area minus buffer zone
|
||||||
|
int topBuffer = lines / 3;
|
||||||
|
textWidget.setTopIndex(Math.max(0, focusLine - topBuffer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the number of visible lines in the view port assuming a constant
|
||||||
|
* line height.
|
||||||
|
*/
|
||||||
|
private int getEstimatedVisibleLinesInViewport(StyledText textWidget) {
|
||||||
|
if (textWidget != null) {
|
||||||
|
Rectangle clArea= textWidget.getClientArea();
|
||||||
|
if (!clArea.isEmpty())
|
||||||
|
return clArea.height / textWidget.getLineHeight();
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -368,9 +480,9 @@ public class DsfSourceDisplayAdapter implements ISourceDisplay, ISteppingControl
|
||||||
* context.
|
* context.
|
||||||
*/
|
*/
|
||||||
class ClearingJob extends UIJob {
|
class ClearingJob extends UIJob {
|
||||||
List<IRunControl.IExecutionDMContext> fDmcsToClear;
|
Set<IRunControl.IExecutionDMContext> fDmcsToClear;
|
||||||
|
|
||||||
public ClearingJob(List<IRunControl.IExecutionDMContext> dmcs) {
|
public ClearingJob(Set<IRunControl.IExecutionDMContext> dmcs) {
|
||||||
super("Debug Source Display"); //$NON-NLS-1$
|
super("Debug Source Display"); //$NON-NLS-1$
|
||||||
setSystem(true);
|
setSystem(true);
|
||||||
setPriority(Job.INTERACTIVE);
|
setPriority(Job.INTERACTIVE);
|
||||||
|
@ -388,6 +500,8 @@ public class DsfSourceDisplayAdapter implements ISourceDisplay, ISteppingControl
|
||||||
serviceDisplayAndClearingJobs();
|
serviceDisplayAndClearingJobs();
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
enableLineBackgroundPainter();
|
||||||
|
|
||||||
if (monitor.isCanceled()) {
|
if (monitor.isCanceled()) {
|
||||||
executeFromJob(clearingJobFinishedRunnable);
|
executeFromJob(clearingJobFinishedRunnable);
|
||||||
return Status.CANCEL_STATUS;
|
return Status.CANCEL_STATUS;
|
||||||
|
@ -402,10 +516,12 @@ public class DsfSourceDisplayAdapter implements ISourceDisplay, ISteppingControl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final boolean DEBUG = false;
|
||||||
|
|
||||||
private DsfSession fSession;
|
private DsfSession fSession;
|
||||||
private DsfExecutor fExecutor;
|
private DsfExecutor fExecutor;
|
||||||
private DsfServicesTracker fServicesTracker;
|
private DsfServicesTracker fServicesTracker;
|
||||||
private IDMContext fPrevModelContext;
|
private FrameData fPrevFrameData;
|
||||||
private SourceLookupResult fPrevResult;
|
private SourceLookupResult fPrevResult;
|
||||||
private ISourceLookupDirector fSourceLookup;
|
private ISourceLookupDirector fSourceLookup;
|
||||||
private DsfSourceLookupParticipant fSourceLookupParticipant;
|
private DsfSourceLookupParticipant fSourceLookupParticipant;
|
||||||
|
@ -415,9 +531,18 @@ public class DsfSourceDisplayAdapter implements ISourceDisplay, ISteppingControl
|
||||||
private DisplayJob fRunningDisplayJob;
|
private DisplayJob fRunningDisplayJob;
|
||||||
private DisplayJob fPendingDisplayJob;
|
private DisplayJob fPendingDisplayJob;
|
||||||
private ClearingJob fRunningClearingJob;
|
private ClearingJob fRunningClearingJob;
|
||||||
private List<IRunControl.IExecutionDMContext> fPendingExecDmcsToClear = new LinkedList<IRunControl.IExecutionDMContext>();
|
private Set<IRunControl.IExecutionDMContext> fPendingExecDmcsToClear = new HashSet<IRunControl.IExecutionDMContext>();
|
||||||
private SteppingController fController;
|
private SteppingController fController;
|
||||||
|
|
||||||
|
/** Delay (in milliseconds) before the selection is changed to the IP location */
|
||||||
|
private int fSelectionChangeDelay = 150;
|
||||||
|
|
||||||
|
private long fStepStartTime = 0;
|
||||||
|
private long fLastStepTime = 0;
|
||||||
|
private long fStepCount;
|
||||||
|
|
||||||
|
private boolean fEnableLineBackgroundPainter;
|
||||||
|
|
||||||
public DsfSourceDisplayAdapter(DsfSession session, ISourceLookupDirector sourceLocator) {
|
public DsfSourceDisplayAdapter(DsfSession session, ISourceLookupDirector sourceLocator) {
|
||||||
this(session, sourceLocator, null);
|
this(session, sourceLocator, null);
|
||||||
}
|
}
|
||||||
|
@ -443,6 +568,18 @@ public class DsfSourceDisplayAdapter implements ISourceDisplay, ISteppingControl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure the delay (in milliseconds) before the selection in the editor
|
||||||
|
* is changed to the IP location.
|
||||||
|
*
|
||||||
|
* @param delay the delay in milliseconds, a non-negative integer
|
||||||
|
*
|
||||||
|
* @since 1.1
|
||||||
|
*/
|
||||||
|
public void setSelectionChangeDelay(int delay) {
|
||||||
|
fSelectionChangeDelay = delay;
|
||||||
|
}
|
||||||
|
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
if (fController != null) {
|
if (fController != null) {
|
||||||
fController.removeSteppingControlParticipant(this);
|
fController.removeSteppingControlParticipant(this);
|
||||||
|
@ -455,7 +592,14 @@ public class DsfSourceDisplayAdapter implements ISourceDisplay, ISteppingControl
|
||||||
// fSourceLookupParticipant is disposed by the source lookup director
|
// fSourceLookupParticipant is disposed by the source lookup director
|
||||||
|
|
||||||
// Need to remove annotations in UI thread.
|
// Need to remove annotations in UI thread.
|
||||||
//fIPManager.removeAllAnnotations();
|
Display display = Display.getDefault();
|
||||||
|
if (!display.isDisposed()) {
|
||||||
|
display.asyncExec(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
enableLineBackgroundPainter();
|
||||||
|
fIPManager.removeAllAnnotations();
|
||||||
|
}});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
|
@ -468,15 +612,40 @@ public class DsfSourceDisplayAdapter implements ISourceDisplay, ISteppingControl
|
||||||
// Quick test. DMC is checked again in source lookup participant, but
|
// Quick test. DMC is checked again in source lookup participant, but
|
||||||
// it's much quicker to test here.
|
// it's much quicker to test here.
|
||||||
if (!(dmc instanceof IFrameDMContext)) return;
|
if (!(dmc instanceof IFrameDMContext)) return;
|
||||||
|
doDisplaySource((IFrameDMContext) dmc, page, force);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doDisplaySource(final IFrameDMContext context, final IWorkbenchPage page, final boolean force) {
|
||||||
|
if (context.getLevel() < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Re-dispatch to executor thread before accessing job lists.
|
// Re-dispatch to executor thread before accessing job lists.
|
||||||
fExecutor.execute(new DsfRunnable() { public void run() {
|
fExecutor.execute(new DsfRunnable() { public void run() {
|
||||||
if (!force && dmc.equals(fPrevModelContext)) {
|
// We need to retrieve the frame level and line number from the service.
|
||||||
fPrevResult.updateArtifact(dmc);
|
IStack stackService = fServicesTracker.getService(IStack.class);
|
||||||
startDisplayJob(fPrevResult, page);
|
if (stackService == null) {
|
||||||
} else {
|
return;
|
||||||
startLookupJob(dmc, page);
|
|
||||||
}
|
}
|
||||||
|
stackService.getFrameData(
|
||||||
|
context,
|
||||||
|
new DataRequestMonitor<IFrameDMData>(fExecutor, null) {
|
||||||
|
@Override
|
||||||
|
public void handleSuccess() {
|
||||||
|
FrameData frameData = new FrameData();
|
||||||
|
frameData.fDmc = context;
|
||||||
|
frameData.fLevel = context.getLevel();
|
||||||
|
// Document line numbers are 0-based. While debugger line numbers are 1-based.
|
||||||
|
IFrameDMData data = getData();
|
||||||
|
frameData.fLine = data.getLine() - 1;
|
||||||
|
frameData.fFile = data.getFile();
|
||||||
|
if (!force && frameData.equals(fPrevFrameData)) {
|
||||||
|
fPrevResult.updateArtifact(context);
|
||||||
|
startDisplayJob(fPrevResult, frameData, page);
|
||||||
|
} else {
|
||||||
|
startLookupJob(frameData, page);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -488,34 +657,32 @@ public class DsfSourceDisplayAdapter implements ISourceDisplay, ISteppingControl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startLookupJob(final IDMContext dmc, final IWorkbenchPage page) {
|
private void startLookupJob(final FrameData frameData, final IWorkbenchPage page) {
|
||||||
// If there is a previous lookup job running, cancel it.
|
// If there is a previous lookup job running, cancel it.
|
||||||
if (fRunningLookupJob != null) {
|
if (fRunningLookupJob != null) {
|
||||||
if (fRunningLookupJob.cancel()) {
|
fRunningLookupJob.cancel();
|
||||||
doneSourceLookup(fRunningLookupJob.getDmc());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fRunningLookupJob = new LookupJob(dmc, page);
|
fRunningLookupJob = new LookupJob(frameData, page);
|
||||||
fRunningLookupJob.schedule();
|
fRunningLookupJob.schedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
// To be called only on dispatch thread.
|
// To be called only on dispatch thread.
|
||||||
private void startDisplayJob(SourceLookupResult lookupResult, IWorkbenchPage page) {
|
private void startDisplayJob(SourceLookupResult lookupResult, FrameData frameData, IWorkbenchPage page) {
|
||||||
DisplayJob nextDisplayJob = new DisplayJob(lookupResult, page);
|
DisplayJob nextDisplayJob = new DisplayJob(lookupResult, frameData, page);
|
||||||
if (fRunningDisplayJob != null) {
|
if (fRunningDisplayJob != null) {
|
||||||
// There is a display job currently running. Cancel it, and set
|
fPendingDisplayJob = null;
|
||||||
// the next display job to be run.
|
IExecutionDMContext[] execCtxs = DMContexts.getAllAncestorsOfType(frameData.fDmc, IExecutionDMContext.class);
|
||||||
if (false && fRunningDisplayJob.cancel()) {
|
fPendingExecDmcsToClear.removeAll(Arrays.asList(execCtxs));
|
||||||
fPendingDisplayJob = nextDisplayJob;
|
|
||||||
fRunningDisplayJob = null;
|
if (frameData.isIdentical(fRunningDisplayJob.fFrameData)) {
|
||||||
serviceDisplayAndClearingJobs();
|
// identical location - we are done
|
||||||
} else {
|
return;
|
||||||
// The job already started, so we need to wait until
|
|
||||||
// serviceDisplayAndClearingJobs() is called by the job itself.
|
|
||||||
fPendingDisplayJob = nextDisplayJob;
|
|
||||||
}
|
}
|
||||||
} else if (fRunningClearingJob != null) {
|
// cancel running display job
|
||||||
|
fRunningDisplayJob.cancel();
|
||||||
|
}
|
||||||
|
if (fRunningClearingJob != null) {
|
||||||
// Wait for the clearing job to finish, instead, set the
|
// Wait for the clearing job to finish, instead, set the
|
||||||
// display job as pending.
|
// display job as pending.
|
||||||
fPendingDisplayJob = nextDisplayJob;
|
fPendingDisplayJob = nextDisplayJob;
|
||||||
|
@ -523,11 +690,10 @@ public class DsfSourceDisplayAdapter implements ISourceDisplay, ISteppingControl
|
||||||
fRunningDisplayJob = nextDisplayJob;
|
fRunningDisplayJob = nextDisplayJob;
|
||||||
fRunningDisplayJob.schedule();
|
fRunningDisplayJob.schedule();
|
||||||
}
|
}
|
||||||
doneSourceLookup(lookupResult.getDmc());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doneSourceLookup(IDMContext context) {
|
private void doneStepping(IDMContext context) {
|
||||||
if (fController != null) {
|
if (fController != null && fController.isSynchronizedSteppingEnabled()) {
|
||||||
// indicate completion of step
|
// indicate completion of step
|
||||||
final IExecutionDMContext dmc = DMContexts.getAncestorOfType(context, IExecutionDMContext.class);
|
final IExecutionDMContext dmc = DMContexts.getAncestorOfType(context, IExecutionDMContext.class);
|
||||||
if (dmc != null) {
|
if (dmc != null) {
|
||||||
|
@ -545,7 +711,7 @@ public class DsfSourceDisplayAdapter implements ISourceDisplay, ISteppingControl
|
||||||
// There are annotations to be cleared, run the job first
|
// There are annotations to be cleared, run the job first
|
||||||
fRunningClearingJob = new ClearingJob(fPendingExecDmcsToClear);
|
fRunningClearingJob = new ClearingJob(fPendingExecDmcsToClear);
|
||||||
fRunningClearingJob.schedule();
|
fRunningClearingJob.schedule();
|
||||||
fPendingExecDmcsToClear = new LinkedList<IRunControl.IExecutionDMContext>();
|
fPendingExecDmcsToClear = new HashSet<IRunControl.IExecutionDMContext>();
|
||||||
} else if (fPendingDisplayJob != null) {
|
} else if (fPendingDisplayJob != null) {
|
||||||
fRunningDisplayJob = fPendingDisplayJob;
|
fRunningDisplayJob = fPendingDisplayJob;
|
||||||
fRunningDisplayJob.schedule();
|
fRunningDisplayJob.schedule();
|
||||||
|
@ -578,7 +744,7 @@ public class DsfSourceDisplayAdapter implements ISourceDisplay, ISteppingControl
|
||||||
if (fRunningClearingJob == null && fRunningDisplayJob == null) {
|
if (fRunningClearingJob == null && fRunningDisplayJob == null) {
|
||||||
fRunningClearingJob = new ClearingJob(fPendingExecDmcsToClear);
|
fRunningClearingJob = new ClearingJob(fPendingExecDmcsToClear);
|
||||||
fRunningClearingJob.schedule();
|
fRunningClearingJob.schedule();
|
||||||
fPendingExecDmcsToClear = new LinkedList<IRunControl.IExecutionDMContext>();
|
fPendingExecDmcsToClear = new HashSet<IRunControl.IExecutionDMContext>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -605,7 +771,66 @@ public class DsfSourceDisplayAdapter implements ISourceDisplay, ISteppingControl
|
||||||
}
|
}
|
||||||
|
|
||||||
@DsfServiceEventHandler
|
@DsfServiceEventHandler
|
||||||
public void eventDispatched(IRunControl.ISuspendedDMEvent e) {
|
public void eventDispatched(final IRunControl.ISuspendedDMEvent e) {
|
||||||
fPrevModelContext = null;
|
updateStepTiming();
|
||||||
|
if (e.getReason() == StateChangeReason.STEP) {
|
||||||
|
// trigger source display immediately (should be optional?)
|
||||||
|
Display.getDefault().asyncExec(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
Object context = DebugUITools.getDebugContext();
|
||||||
|
if (context instanceof IDMVMContext) {
|
||||||
|
final IDMContext dmc = ((IDMVMContext)context).getDMContext();
|
||||||
|
if (dmc instanceof IFrameDMContext && DMContexts.isAncestorOf(dmc, e.getDMContext())) {
|
||||||
|
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
|
||||||
|
doDisplaySource((IFrameDMContext) dmc, page, false);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateStepTiming() {
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
if (now - fLastStepTime > Math.max(fSelectionChangeDelay, 200)) {
|
||||||
|
fStepCount = 0;
|
||||||
|
fStepStartTime = fLastStepTime = now;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fLastStepTime = now;
|
||||||
|
++fStepCount;
|
||||||
|
if (DEBUG) {
|
||||||
|
long delta = now - fStepStartTime;
|
||||||
|
float meanTime = delta/(float)fStepCount/1000;
|
||||||
|
System.out.println("[DsfSourceDisplayAdapter] step speed = " + 1/meanTime); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable editor line background painter if it is enabled.
|
||||||
|
* <p>
|
||||||
|
* <strong>Must be called on display thread.</strong>
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
private void disableLineBackgroundPainter() {
|
||||||
|
if (!fEnableLineBackgroundPainter) {
|
||||||
|
fEnableLineBackgroundPainter = EditorsUI.getPreferenceStore().getBoolean(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE);
|
||||||
|
if (fEnableLineBackgroundPainter) {
|
||||||
|
EditorsUI.getPreferenceStore().setValue(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable the editor line background painter if it was enabled before.
|
||||||
|
* <p>
|
||||||
|
* <strong>Must be called on display thread.</strong>
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
private void enableLineBackgroundPainter() {
|
||||||
|
if (fEnableLineBackgroundPainter) {
|
||||||
|
fEnableLineBackgroundPainter = false;
|
||||||
|
EditorsUI.getPreferenceStore().setValue(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -506,7 +506,7 @@ public class PDARunControl extends AbstractDsfService
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isStepping(IExecutionDMContext context) {
|
public boolean isStepping(IExecutionDMContext context) {
|
||||||
if (isSuspended(context)) {
|
if (!isSuspended(context)) {
|
||||||
if (context instanceof PDAThreadDMContext) {
|
if (context instanceof PDAThreadDMContext) {
|
||||||
PDAThreadDMContext threadContext = (PDAThreadDMContext)context;
|
PDAThreadDMContext threadContext = (PDAThreadDMContext)context;
|
||||||
// Threads can be resumed only if the VM is not suspended.
|
// Threads can be resumed only if the VM is not suspended.
|
||||||
|
|
Loading…
Add table
Reference in a new issue