提交 8d5f269a 编写于 作者: I isidor

debug: use schedulres to prevent flashing on the views side not in the service

上级 3245e2a4
......@@ -9,7 +9,6 @@ import { guessMimeTypes } from 'vs/base/common/mime';
import Event, { Emitter } from 'vs/base/common/event';
import uuid = require('vs/base/common/uuid');
import uri from 'vs/base/common/uri';
import { RunOnceScheduler } from 'vs/base/common/async';
import { Action } from 'vs/base/common/actions';
import arrays = require('vs/base/common/arrays');
import types = require('vs/base/common/types');
......@@ -317,7 +316,7 @@ export class DebugService implements debug.IDebugService {
}));
this.toDisposeOnSessionEnd[session.getId()].push(session.onDidContinued(event => {
this.lazyTransitionToRunningState(session, event.body.allThreadsContinued ? undefined : event.body.threadId);
this.transitionToRunningState(session, event.body.allThreadsContinued ? undefined : event.body.threadId);
}));
this.toDisposeOnSessionEnd[session.getId()].push(session.onDidOutput(event => {
......@@ -665,7 +664,7 @@ export class DebugService implements debug.IDebugService {
}
this.extensionService.activateByEvent(`onDebug:${configuration.type}`).done(null, errors.onUnexpectedError);
this.inDebugMode.set(true);
this.lazyTransitionToRunningState(session);
this.transitionToRunningState(session);
this.telemetryService.publicLog('debugSessionStart', {
type: configuration.type,
......@@ -885,19 +884,10 @@ export class DebugService implements debug.IDebugService {
return this.configurationManager;
}
private lazyTransitionToRunningState(session: RawDebugSession, threadId?: number): void {
let setNewFocusedStackFrameScheduler: RunOnceScheduler;
const toDispose = session.onDidStop(e => {
if (e.body.threadId === threadId || e.body.allThreadsStopped || !threadId) {
setNewFocusedStackFrameScheduler.cancel();
}
});
private transitionToRunningState(session: RawDebugSession, threadId?: number): void {
this.model.clearThreads(session.getId(), false, threadId);
// Get a top stack frame of a stopped thread if there is any.
const process = this.model.getProcesses().filter(p => p.getId() === session.getId()).pop();
const stoppedThread = process && process.getAllThreads().filter(t => t.stopped).pop();
const callStack = stoppedThread ? stoppedThread.getCachedCallStack() : null;
......@@ -907,15 +897,7 @@ export class DebugService implements debug.IDebugService {
this.setStateAndEmit(session.getId(), process.session.requestType === debug.SessionRequestType.LAUNCH_NO_DEBUG ? debug.State.RunningNoDebug : debug.State.Running);
}
// Do not immediatly set a new focused stack frame since that might cause unnecessery flickering
// of the tree in the debug viewlet. Only set focused stack frame if no stopped event has arrived in 500ms.
setNewFocusedStackFrameScheduler = new RunOnceScheduler(() => {
toDispose.dispose();
aria.status(nls.localize('debuggingContinued', "Debugging continued."));
this.setFocusedStackFrameAndEvaluate(stackFrameToFocus).done(null, errors.onUnexpectedError);
}, 500);
setNewFocusedStackFrameScheduler.schedule();
this.setFocusedStackFrameAndEvaluate(stackFrameToFocus).done(null, errors.onUnexpectedError);
}
private getDebugStringEditorInput(process: debug.IProcess, source: Source, value: string, mtype: string): DebugStringEditorInput {
......
......@@ -48,6 +48,7 @@ const $ = builder.$;
export class VariablesView extends viewlet.CollapsibleViewletView {
private static MEMENTO = 'variablesview.memento';
private onFocusStackFrameScheduler: RunOnceScheduler;
constructor(
actionRunner: actions.IActionRunner,
......@@ -60,6 +61,22 @@ export class VariablesView extends viewlet.CollapsibleViewletView {
@IInstantiationService private instantiationService: IInstantiationService
) {
super(actionRunner, !!settings[VariablesView.MEMENTO], nls.localize('variablesSection', "Variables Section"), messageService, keybindingService, contextMenuService);
// Use schedulre to prevent unnecessary flashing
this.onFocusStackFrameScheduler = new RunOnceScheduler(() => {
// Always clear tree highlight to avoid ending up in a broken state #12203
this.tree.clearHighlight();
this.tree.refresh().then(() => {
const stackFrame = this.debugService.getViewModel().focusedStackFrame;
if (stackFrame) {
return stackFrame.getScopes().then(scopes => {
if (scopes.length > 0 && !scopes[0].expensive) {
return this.tree.expand(scopes[0]);
}
});
}
}).done(null, errors.onUnexpectedError);
}, 700);
}
public renderHeader(container: HTMLElement): void {
......@@ -87,7 +104,15 @@ export class VariablesView extends viewlet.CollapsibleViewletView {
const collapseAction = this.instantiationService.createInstance(viewlet.CollapseAction, this.tree, false, 'explorer-action collapse-explorer');
this.toolBar.setActions(actionbarregistry.prepareActions([collapseAction]))();
this.toDispose.push(viewModel.onDidFocusStackFrame(sf => this.onFocusStackFrame(sf)));
this.toDispose.push(viewModel.onDidFocusStackFrame(sf => {
// Only delay if the stack frames got cleared and there is no active stack frame
// Otherwise just update immediately
if (sf) {
this.onFocusStackFrameScheduler.schedule(0);
} else if (!this.onFocusStackFrameScheduler.isScheduled()) {
this.onFocusStackFrameScheduler.schedule();
}
}));
this.toDispose.push(this.debugService.onDidChangeState(state => {
collapseAction.enabled = state === debug.State.Running || state === debug.State.Stopped;
}));
......@@ -117,20 +142,6 @@ export class VariablesView extends viewlet.CollapsibleViewletView {
}));
}
private onFocusStackFrame(stackFrame: debug.IStackFrame): void {
// Always clear tree highlight to avoid ending up in a broken state #12203
this.tree.clearHighlight();
this.tree.refresh().then(() => {
if (stackFrame) {
return stackFrame.getScopes().then(scopes => {
if (scopes.length > 0 && !scopes[0].expensive) {
return this.tree.expand(scopes[0]);
}
});
}
}).done(null, errors.onUnexpectedError);
}
public shutdown(): void {
this.settings[VariablesView.MEMENTO] = (this.state === splitview.CollapsibleState.COLLAPSED);
super.shutdown();
......@@ -140,6 +151,8 @@ export class VariablesView extends viewlet.CollapsibleViewletView {
export class WatchExpressionsView extends viewlet.CollapsibleViewletView {
private static MEMENTO = 'watchexpressionsview.memento';
private onWatchExpressionsUpdatedScheduler: RunOnceScheduler;
private toReveal: debug.IExpression;
constructor(
actionRunner: actions.IActionRunner,
......@@ -151,12 +164,19 @@ export class WatchExpressionsView extends viewlet.CollapsibleViewletView {
@IInstantiationService private instantiationService: IInstantiationService
) {
super(actionRunner, !!settings[WatchExpressionsView.MEMENTO], nls.localize('expressionsSection', "Expressions Section"), messageService, keybindingService, contextMenuService);
this.toDispose.push(this.debugService.getModel().onDidChangeWatchExpressions(we => {
// only expand when a new watch expression is added.
if (we instanceof Expression) {
this.expand();
}
}));
this.onWatchExpressionsUpdatedScheduler = new RunOnceScheduler(() => {
this.tree.refresh().done(() => {
return this.toReveal instanceof Expression ? this.tree.reveal(this.toReveal) : TPromise.as(true);
}, errors.onUnexpectedError);
}, 250);
}
public renderHeader(container: HTMLElement): void {
......@@ -185,7 +205,13 @@ export class WatchExpressionsView extends viewlet.CollapsibleViewletView {
const removeAllWatchExpressionsAction = this.instantiationService.createInstance(debugactions.RemoveAllWatchExpressionsAction, debugactions.RemoveAllWatchExpressionsAction.ID, debugactions.RemoveAllWatchExpressionsAction.LABEL);
this.toolBar.setActions(actionbarregistry.prepareActions([addWatchExpressionAction, collapseAction, removeAllWatchExpressionsAction]))();
this.toDispose.push(this.debugService.getModel().onDidChangeWatchExpressions(we => this.onWatchExpressionsUpdated(we)));
this.toDispose.push(this.debugService.getModel().onDidChangeWatchExpressions(we => {
if (!this.onWatchExpressionsUpdatedScheduler.isScheduled()) {
this.onWatchExpressionsUpdatedScheduler.schedule();
}
this.toReveal = we;
}));
this.toDispose.push(this.debugService.getViewModel().onDidSelectExpression(expression => {
if (!expression || !(expression instanceof Expression)) {
return;
......@@ -202,12 +228,6 @@ export class WatchExpressionsView extends viewlet.CollapsibleViewletView {
}));
}
private onWatchExpressionsUpdated(expression: debug.IExpression): void {
this.tree.refresh().done(() => {
return expression instanceof Expression ? this.tree.reveal(expression) : TPromise.as(true);
}, errors.onUnexpectedError);
}
public shutdown(): void {
this.settings[WatchExpressionsView.MEMENTO] = (this.state === splitview.CollapsibleState.COLLAPSED);
super.shutdown();
......@@ -233,10 +253,8 @@ export class CallStackView extends viewlet.CollapsibleViewletView {
@IInstantiationService private instantiationService: IInstantiationService
) {
super(actionRunner, !!settings[CallStackView.MEMENTO], nls.localize('callstackSection', "Call Stack Section"), messageService, keybindingService, contextMenuService);
this.createSchedulers();
}
private createSchedulers(): void {
// Create schedulers to prevent unnecessary flashing of tree when reacting to changes
this.onStackFrameFocusScheduler = new RunOnceScheduler(() => {
const stackFrame = this.debugService.getViewModel().focusedStackFrame;
if (!stackFrame) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册