提交 aa351d82 编写于 作者: I isidor

debug: keep repl elements per session

上级 b58200ca
......@@ -205,7 +205,10 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
public $appendDebugConsole(value: string): Thenable<void> {
// Use warning as severity to get the orange color for messages coming from the debug extension
this.debugService.logToRepl(value, severity.Warning);
const session = this.debugService.getViewModel().focusedSession;
if (session) {
session.appendToRepl(value, severity.Warning);
}
return TPromise.wrap<void>(undefined);
}
......
......@@ -239,9 +239,7 @@ export class RestartAction extends AbstractDebugAction {
return this.startAction.run();
}
if (this.debugService.getModel().getSessions().length <= 1) {
this.debugService.removeReplExpressions();
}
session.removeReplExpressions();
return this.debugService.restartSession(session);
}
......@@ -692,8 +690,11 @@ export class ClearReplAction extends AbstractDebugAction {
}
public run(): TPromise<any> {
this.debugService.removeReplExpressions();
aria.status(nls.localize('debugConsoleCleared', "Debug console was cleared"));
const session = this.debugService.getViewModel().focusedSession;
if (session) {
session.removeReplExpressions();
aria.status(nls.localize('debugConsoleCleared', "Debug console was cleared"));
}
// focus back to repl
return this.panelService.openPanel(REPL_ID, true);
......@@ -706,7 +707,6 @@ export class ToggleReplAction extends TogglePanelAction {
private toDispose: lifecycle.IDisposable[];
constructor(id: string, label: string,
@IDebugService private debugService: IDebugService,
@IPartService partService: IPartService,
@IPanelService panelService: IPanelService
) {
......@@ -716,12 +716,6 @@ export class ToggleReplAction extends TogglePanelAction {
}
private registerListeners(): void {
this.toDispose.push(this.debugService.getModel().onDidChangeReplElements(() => {
if (!this.isReplVisible()) {
this.class = 'debug-action toggle-repl notification';
this.tooltip = nls.localize('unreadOutput', "New Output in Debug Console");
}
}));
this.toDispose.push(this.panelService.onDidPanelOpen(panel => {
if (panel.getId() === REPL_ID) {
this.class = 'debug-action toggle-repl';
......@@ -730,11 +724,6 @@ export class ToggleReplAction extends TogglePanelAction {
}));
}
private isReplVisible(): boolean {
const panel = this.panelService.getActivePanel();
return panel && panel.getId() === REPL_ID;
}
public dispose(): void {
super.dispose();
this.toDispose = lifecycle.dispose(this.toDispose);
......
......@@ -159,7 +159,9 @@ class SelectionToReplAction extends EditorAction {
const panelService = accessor.get(IPanelService);
const text = editor.getModel().getValueInRange(editor.getSelection());
return debugService.addReplExpression(text)
const viewModel = debugService.getViewModel();
const session = viewModel.focusedSession;
return session.addReplExpression(viewModel.focusedStackFrame, text)
.then(() => panelService.openPanel(REPL_ID, true))
.then(_ => void 0);
}
......
......@@ -152,6 +152,16 @@ export interface IDebugSession extends ITreeElement {
setConfiguration(configuration: { resolved: IConfig, unresolved: IConfig }): void;
rawUpdate(data: IRawModelUpdate): void;
getThread(threadId: number): IThread;
getAllThreads(): ReadonlyArray<IThread>;
clearThreads(removeThreads: boolean, reference?: number): void;
getReplElements(): ReadonlyArray<IReplElement>;
removeReplExpressions(): void;
addReplExpression(stackFrame: IStackFrame, name: string): TPromise<void>;
appendToRepl(data: string | IExpression, severity: severity, source?: IReplElementSource): void;
// session events
readonly onDidEndAdapter: Event<AdapterEndEvent>;
readonly onDidChangeState: Event<void>;
......@@ -200,10 +210,6 @@ export interface IDebugSession extends ITreeElement {
setVariable(variablesReference: number, name: string, value: string): TPromise<DebugProtocol.SetVariableResponse>;
loadSource(resource: uri): TPromise<DebugProtocol.SourceResponse>;
getLoadedSources(): TPromise<Source[]>;
getThread(threadId: number): IThread;
getAllThreads(): ReadonlyArray<IThread>;
clearThreads(removeThreads: boolean, reference?: number): void;
}
export interface IThread extends ITreeElement {
......@@ -379,7 +385,6 @@ export interface IDebugModel extends ITreeElement {
onDidChangeBreakpoints: Event<IBreakpointsChangeEvent>;
onDidChangeCallStack: Event<void>;
onDidChangeWatchExpressions: Event<IExpression>;
onDidChangeReplElements: Event<void>;
}
/**
......@@ -721,21 +726,6 @@ export interface IDebugService {
*/
sendAllBreakpoints(session?: IDebugSession): TPromise<any>;
/**
* Adds a new expression to the repl.
*/
addReplExpression(name: string): TPromise<void>;
/**
* Removes all repl expressions.
*/
removeReplExpressions(): void;
/**
* Appends the passed string to the debug repl.
*/
logToRepl(value: string | IExpression, sev?: severity, source?: IReplElementSource): void;
/**
* Adds a new watch expression and evaluates it against the debug adapter.
*/
......
......@@ -25,8 +25,6 @@ import { sep } from 'vs/base/common/paths';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
const MAX_REPL_LENGTH = 10000;
export abstract class AbstractReplElement implements IReplElement {
private static ID_COUNTER = 0;
......@@ -728,13 +726,11 @@ export class DebugModel implements IDebugModel {
private sessions: IDebugSession[];
private toDispose: lifecycle.IDisposable[];
private replElements: IReplElement[];
private schedulers = new Map<string, RunOnceScheduler>();
private breakpointsSessionId: string;
private readonly _onDidChangeBreakpoints: Emitter<IBreakpointsChangeEvent>;
private readonly _onDidChangeCallStack: Emitter<void>;
private readonly _onDidChangeWatchExpressions: Emitter<IExpression>;
private readonly _onDidChangeREPLElements: Emitter<void>;
constructor(
private breakpoints: Breakpoint[],
......@@ -745,12 +741,10 @@ export class DebugModel implements IDebugModel {
private textFileService: ITextFileService
) {
this.sessions = [];
this.replElements = [];
this.toDispose = [];
this._onDidChangeBreakpoints = new Emitter<IBreakpointsChangeEvent>();
this._onDidChangeCallStack = new Emitter<void>();
this._onDidChangeWatchExpressions = new Emitter<IExpression>();
this._onDidChangeREPLElements = new Emitter<void>();
}
public getId(): string {
......@@ -782,10 +776,6 @@ export class DebugModel implements IDebugModel {
return this._onDidChangeWatchExpressions.event;
}
public get onDidChangeReplElements(): Event<void> {
return this._onDidChangeREPLElements.event;
}
public rawUpdate(data: IRawModelUpdate): void {
let session = this.sessions.filter(p => p.getId() === data.sessionId).pop();
if (session) {
......@@ -1015,51 +1005,8 @@ export class DebugModel implements IDebugModel {
this._onDidChangeBreakpoints.fire({ removed: removed });
}
public getReplElements(): IReplElement[] {
return this.replElements;
}
public addReplExpression(session: IDebugSession, stackFrame: IStackFrame, name: string): TPromise<void> {
const expression = new Expression(name);
this.addReplElements([expression]);
return expression.evaluate(session, stackFrame, 'repl')
.then(() => this._onDidChangeREPLElements.fire());
}
public appendToRepl(data: string | IExpression, severity: severity, source?: IReplElementSource): void {
if (typeof data === 'string') {
const previousElement = this.replElements.length && (this.replElements[this.replElements.length - 1] as SimpleReplElement);
const toAdd = data.split('\n').map((line, index) => new SimpleReplElement(line, severity, index === 0 ? source : undefined));
if (previousElement && previousElement.value === '') {
// remove potential empty lines between different repl types
this.replElements.pop();
} else if (previousElement instanceof SimpleReplElement && severity === previousElement.severity && toAdd.length && toAdd[0].sourceData === previousElement.sourceData) {
previousElement.value += toAdd.shift().value;
}
this.addReplElements(toAdd);
} else {
// TODO@Isidor hack, we should introduce a new type which is an output that can fetch children like an expression
(<any>data).severity = severity;
(<any>data).sourceData = source;
this.addReplElements([data]);
}
this._onDidChangeREPLElements.fire();
}
private addReplElements(newElements: IReplElement[]): void {
this.replElements.push(...newElements);
if (this.replElements.length > MAX_REPL_LENGTH) {
this.replElements.splice(0, this.replElements.length - MAX_REPL_LENGTH);
}
}
public removeReplExpressions(): void {
if (this.replElements.length > 0) {
this.replElements = [];
this._onDidChangeREPLElements.fire();
}
public getReplElements(): ReadonlyArray<IReplElement> {
return this.sessions.map(s => s.getReplElements()).reduce((left, right) => left.concat(right), []);
}
public getWatchExpressions(): Expression[] {
......
......@@ -46,7 +46,7 @@ import { IAction, Action } from 'vs/base/common/actions';
import { deepClone, equals } from 'vs/base/common/objects';
import { DebugSession } from 'vs/workbench/parts/debug/electron-browser/debugSession';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import { IDebugService, State, IDebugSession, CONTEXT_DEBUG_TYPE, CONTEXT_DEBUG_STATE, CONTEXT_IN_DEBUG_MODE, IThread, IDebugConfiguration, VIEWLET_ID, REPL_ID, IConfig, ILaunch, IViewModel, IConfigurationManager, IDebugModel, IReplElementSource, IEnablement, IBreakpoint, IBreakpointData, IExpression, ICompound, IGlobalConfig, IStackFrame, AdapterEndEvent } from 'vs/workbench/parts/debug/common/debug';
import { IDebugService, State, IDebugSession, CONTEXT_DEBUG_TYPE, CONTEXT_DEBUG_STATE, CONTEXT_IN_DEBUG_MODE, IThread, IDebugConfiguration, VIEWLET_ID, REPL_ID, IConfig, ILaunch, IViewModel, IConfigurationManager, IDebugModel, IReplElementSource, IEnablement, IBreakpoint, IBreakpointData, ICompound, IGlobalConfig, IStackFrame, AdapterEndEvent } from 'vs/workbench/parts/debug/common/debug';
import { isExtensionHostDebugging } from 'vs/workbench/parts/debug/common/debugUtils';
import { RunOnceScheduler } from 'vs/base/common/async';
......@@ -266,9 +266,7 @@ export class DebugService implements IDebugService {
this.textFileService.saveAll().then(() => this.configurationService.reloadConfiguration(launch ? launch.workspace : undefined).then(() =>
this.extensionService.whenInstalledExtensionsRegistered().then(() => {
// If it is the very first start debugging we need to clear the repl and our sessions map
if (this.model.getSessions().length === 0) {
this.removeReplExpressions();
this.allSessions.clear();
}
......@@ -786,16 +784,6 @@ export class DebugService implements IDebugService {
//---- REPL
addReplExpression(name: string): TPromise<void> {
return this.model.addReplExpression(this.viewModel.focusedSession, this.viewModel.focusedStackFrame, name)
// Evaluate all watch expressions and fetch variables again since repl evaluation might have changed some.
.then(() => this.focusStackFrame(this.viewModel.focusedStackFrame, this.viewModel.focusedThread, this.viewModel.focusedSession));
}
removeReplExpressions(): void {
this.model.removeReplExpressions();
}
private addToRepl(session: IDebugSession, extensionOutput: IRemoteConsoleLog) {
let sev = extensionOutput.severity === 'warn' ? severity.Warning : extensionOutput.severity === 'error' ? severity.Error : severity.Info;
......@@ -836,12 +824,12 @@ export class DebugService implements IDebugService {
// flush any existing simple values logged
if (simpleVals.length) {
this.logToRepl(simpleVals.join(' '), sev, source);
session.appendToRepl(simpleVals.join(' '), sev, source);
simpleVals = [];
}
// show object
this.logToRepl(new RawObjectReplElement((<any>a).prototype, a, undefined, nls.localize('snapshotObj', "Only primitive values are shown for this object.")), sev, source);
session.appendToRepl(new RawObjectReplElement((<any>a).prototype, a, undefined, nls.localize('snapshotObj', "Only primitive values are shown for this object.")), sev, source);
}
// string: watch out for % replacement directive
......@@ -871,22 +859,10 @@ export class DebugService implements IDebugService {
// flush simple values
// always append a new line for output coming from an extension such that separate logs go to separate lines #23695
if (simpleVals.length) {
this.logToRepl(simpleVals.join(' ') + '\n', sev, source);
session.appendToRepl(simpleVals.join(' ') + '\n', sev, source);
}
}
logToRepl(value: string | IExpression, sev = severity.Info, source?: IReplElementSource): void {
const clearAnsiSequence = '\u001b[2J';
if (typeof value === 'string' && value.indexOf(clearAnsiSequence) >= 0) {
// [2J is the ansi escape sequence for clearing the display http://ascii-table.com/ansi-escape-sequences.php
this.model.removeReplExpressions();
this.model.appendToRepl(nls.localize('consoleCleared', "Console was cleared"), severity.Ignore);
value = value.substr(value.lastIndexOf(clearAnsiSequence) + clearAnsiSequence.length);
}
this.model.appendToRepl(value, sev, source);
}
//---- watches
addWatchExpression(name: string): void {
......
......@@ -13,10 +13,10 @@ import { Event, Emitter } from 'vs/base/common/event';
import { CompletionItem, completionKindFromLegacyString } from 'vs/editor/common/modes';
import { Position } from 'vs/editor/common/core/position';
import * as aria from 'vs/base/browser/ui/aria/aria';
import { IDebugSession, IConfig, IThread, IRawModelUpdate, IDebugService, IRawStoppedDetails, State, LoadedSourceEvent, IFunctionBreakpoint, IExceptionBreakpoint, ActualBreakpoints, IBreakpoint, IExceptionInfo, AdapterEndEvent, IDebugger, VIEWLET_ID, IDebugConfiguration } from 'vs/workbench/parts/debug/common/debug';
import { IDebugSession, IConfig, IThread, IRawModelUpdate, IDebugService, IRawStoppedDetails, State, LoadedSourceEvent, IFunctionBreakpoint, IExceptionBreakpoint, ActualBreakpoints, IBreakpoint, IExceptionInfo, AdapterEndEvent, IDebugger, VIEWLET_ID, IDebugConfiguration, IReplElement, IStackFrame, IExpression, IReplElementSource } from 'vs/workbench/parts/debug/common/debug';
import { Source } from 'vs/workbench/parts/debug/common/debugSource';
import { mixin } from 'vs/base/common/objects';
import { Thread, ExpressionContainer, DebugModel } from 'vs/workbench/parts/debug/common/debugModel';
import { Thread, ExpressionContainer, DebugModel, Expression, SimpleReplElement } from 'vs/workbench/parts/debug/common/debugModel';
import { RawDebugSession } from 'vs/workbench/parts/debug/electron-browser/rawDebugSession';
import product from 'vs/platform/node/product';
import { INotificationService } from 'vs/platform/notification/common/notification';
......@@ -32,6 +32,8 @@ import { Range } from 'vs/editor/common/core/range';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
const MAX_REPL_LENGTH = 10000;
export class DebugSession implements IDebugSession {
private id: string;
......@@ -41,6 +43,7 @@ export class DebugSession implements IDebugSession {
private threads = new Map<number, Thread>();
private rawListeners: IDisposable[] = [];
private fetchThreadsScheduler: RunOnceScheduler;
private replElements: IReplElement[] = [];
private readonly _onDidChangeState = new Emitter<void>();
private readonly _onDidEndAdapter = new Emitter<AdapterEndEvent>();
......@@ -48,6 +51,7 @@ export class DebugSession implements IDebugSession {
private readonly _onDidLoadedSource = new Emitter<LoadedSourceEvent>();
private readonly _onDidCustomEvent = new Emitter<DebugProtocol.Event>();
private readonly _onDidChangeREPLElements = new Emitter<void>();
constructor(
private _configuration: { resolved: IConfig, unresolved: IConfig },
......@@ -109,6 +113,10 @@ export class DebugSession implements IDebugSession {
return this._onDidEndAdapter.event;
}
get onDidChangeReplElements(): Event<void> {
return this._onDidChangeREPLElements.event;
}
//---- DAP events
get onDidCustomEvent(): Event<DebugProtocol.Event> {
......@@ -119,7 +127,6 @@ export class DebugSession implements IDebugSession {
return this._onDidLoadedSource.event;
}
//---- DAP requests
/**
......@@ -673,11 +680,11 @@ export class DebugSession implements IDebugSession {
return Promise.all(waitFor).then(() => children.forEach(child => {
// Since we can not display multiple trees in a row, we are displaying these variables one after the other (ignoring their names)
child.name = null;
this.debugService.logToRepl(child, outputSeverity, source);
this.appendToRepl(child, outputSeverity, source);
}));
}));
} else if (typeof event.body.output === 'string') {
Promise.all(waitFor).then(() => this.debugService.logToRepl(event.body.output, outputSeverity, source));
Promise.all(waitFor).then(() => this.appendToRepl(event.body.output, outputSeverity, source));
}
Promise.all(outputPromises).then(() => outputPromises = []);
}));
......@@ -775,4 +782,64 @@ export class DebugSession implements IDebugSession {
private getUriKey(uri: URI): string {
return platform.isLinux ? uri.toString() : uri.toString().toLowerCase();
}
// REPL
public getReplElements(): ReadonlyArray<IReplElement> {
return this.replElements;
}
public addReplExpression(stackFrame: IStackFrame, name: string): TPromise<void> {
const expression = new Expression(name);
this.addReplElements([expression]);
const viewModel = this.debugService.getViewModel();
return expression.evaluate(this, stackFrame, 'repl')
.then(() => this._onDidChangeREPLElements.fire())
// Evaluate all watch expressions and fetch variables again since repl evaluation might have changed some.
.then(() => this.debugService.focusStackFrame(viewModel.focusedStackFrame, viewModel.focusedThread, viewModel.focusedSession));
}
public appendToRepl(data: string | IExpression, sev: severity, source?: IReplElementSource): void {
const clearAnsiSequence = '\u001b[2J';
if (typeof data === 'string' && data.indexOf(clearAnsiSequence) >= 0) {
// [2J is the ansi escape sequence for clearing the display http://ascii-table.com/ansi-escape-sequences.php
this.removeReplExpressions();
this.appendToRepl(nls.localize('consoleCleared', "Console was cleared"), severity.Ignore);
data = data.substr(data.lastIndexOf(clearAnsiSequence) + clearAnsiSequence.length);
}
if (typeof data === 'string') {
const previousElement = this.replElements.length && (this.replElements[this.replElements.length - 1] as SimpleReplElement);
const toAdd = data.split('\n').map((line, index) => new SimpleReplElement(line, sev, index === 0 ? source : undefined));
if (previousElement && previousElement.value === '') {
// remove potential empty lines between different repl types
this.replElements.pop();
} else if (previousElement instanceof SimpleReplElement && sev === previousElement.severity && toAdd.length && toAdd[0].sourceData === previousElement.sourceData) {
previousElement.value += toAdd.shift().value;
}
this.addReplElements(toAdd);
} else {
// TODO@Isidor hack, we should introduce a new type which is an output that can fetch children like an expression
(<any>data).severity = sev;
(<any>data).sourceData = source;
this.addReplElements([data]);
}
this._onDidChangeREPLElements.fire();
}
private addReplElements(newElements: IReplElement[]): void {
this.replElements.push(...newElements);
if (this.replElements.length > MAX_REPL_LENGTH) {
this.replElements.splice(0, this.replElements.length - MAX_REPL_LENGTH);
}
}
removeReplExpressions(): void {
if (this.replElements.length > 0) {
this.replElements = [];
this._onDidChangeREPLElements.fire();
}
}
}
......@@ -106,9 +106,10 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati
}
private registerListeners(): void {
this._register(this.debugService.getModel().onDidChangeReplElements(() => {
this.refreshReplElements(this.debugService.getModel().getReplElements().length === 0);
}));
// TODO@Isidor
// this._register(this.debugService.getModel().onDidChangeReplElements(() => {
// this.refreshReplElements(this.debugService.getModel().getReplElements().length === 0);
// }));
this._register(this.panelService.onDidPanelOpen(panel => this.refreshReplElements(true)));
}
......@@ -235,12 +236,16 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati
}
public acceptReplInput(): void {
this.debugService.addReplExpression(this.replInput.getValue());
this.history.add(this.replInput.getValue());
this.replInput.setValue('');
// Trigger a layout to shrink a potential multi line input
this.replInputHeight = Repl.REPL_INPUT_INITIAL_HEIGHT;
this.layout(this.dimension);
const viewModel = this.debugService.getViewModel();
const session = viewModel.focusedSession;
if (session) {
session.addReplExpression(viewModel.focusedStackFrame, this.replInput.getValue());
this.history.add(this.replInput.getValue());
this.replInput.setValue('');
// Trigger a layout to shrink a potential multi line input
this.replInputHeight = Repl.REPL_INPUT_INITIAL_HEIGHT;
this.layout(this.dimension);
}
}
public getVisibleContent(): string {
......
......@@ -8,9 +8,10 @@ import { Event } from 'vs/base/common/event';
import { TPromise } from 'vs/base/common/winjs.base';
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { Position } from 'vs/editor/common/core/position';
import { ILaunch, IDebugService, State, IDebugSession, IConfigurationManager, IStackFrame, IBreakpointData, IBreakpointUpdateData, IConfig, IDebugModel, IViewModel, IBreakpoint, LoadedSourceEvent, IThread, IRawModelUpdate, ActualBreakpoints, IFunctionBreakpoint, IExceptionBreakpoint, IDebugger, IExceptionInfo, AdapterEndEvent } from 'vs/workbench/parts/debug/common/debug';
import { ILaunch, IDebugService, State, IDebugSession, IConfigurationManager, IStackFrame, IBreakpointData, IBreakpointUpdateData, IConfig, IDebugModel, IViewModel, IBreakpoint, LoadedSourceEvent, IThread, IRawModelUpdate, ActualBreakpoints, IFunctionBreakpoint, IExceptionBreakpoint, IDebugger, IExceptionInfo, AdapterEndEvent, IReplElement, IExpression, IReplElementSource } from 'vs/workbench/parts/debug/common/debug';
import { Source } from 'vs/workbench/parts/debug/common/debugSource';
import { CompletionItem } from 'vs/editor/common/modes';
import Severity from 'vs/base/common/severity';
export class MockDebugService implements IDebugService {
......@@ -117,7 +118,7 @@ export class MockDebugService implements IDebugService {
return null;
}
public logToRepl(value: string): void { }
public logToRepl(session: IDebugSession, value: string): void { }
public sourceIsNotAvailable(uri: uri): void { }
......@@ -127,6 +128,17 @@ export class MockDebugService implements IDebugService {
}
export class MockSession implements IDebugSession {
getReplElements(): ReadonlyArray<IReplElement> {
return [];
}
removeReplExpressions(): void { }
addReplExpression(stackFrame: IStackFrame, name: string): TPromise<void> {
return TPromise.as(void 0);
}
appendToRepl(data: string | IExpression, severity: Severity, source?: IReplElementSource): void { }
configuration: IConfig = { type: 'mock', request: 'launch' };
unresolvedConfiguration: IConfig = { type: 'mock', request: 'launch' };
......
......@@ -354,9 +354,9 @@ suite('Debug - Model', () => {
session['raw'] = <any>rawSession;
const thread = new Thread(session, 'mockthread', 1);
const stackFrame = new StackFrame(thread, 1, null, 'app.js', 'normal', { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 10 }, 1);
model.addReplExpression(session, stackFrame, 'myVariable').then();
model.addReplExpression(session, stackFrame, 'myVariable').then();
model.addReplExpression(session, stackFrame, 'myVariable').then();
session.addReplExpression(stackFrame, 'myVariable').then();
session.addReplExpression(stackFrame, 'myVariable').then();
session.addReplExpression(stackFrame, 'myVariable').then();
assert.equal(model.getReplElements().length, 3);
model.getReplElements().forEach(re => {
......@@ -365,7 +365,7 @@ suite('Debug - Model', () => {
assert.equal((<Expression>re).reference, 0);
});
model.removeReplExpressions();
session.removeReplExpressions();
assert.equal(model.getReplElements().length, 0);
});
......@@ -401,10 +401,11 @@ suite('Debug - Model', () => {
// Repl output
test('repl output', () => {
model.appendToRepl('first line\n', severity.Error);
model.appendToRepl('second line', severity.Error);
model.appendToRepl('third line', severity.Warning);
model.appendToRepl('fourth line', severity.Error);
const session = new DebugSession({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined, model, undefined, undefined, undefined, undefined, undefined, undefined, undefined);
session.appendToRepl('first line\n', severity.Error);
session.appendToRepl('second line', severity.Error);
session.appendToRepl('third line', severity.Warning);
session.appendToRepl('fourth line', severity.Error);
let elements = <SimpleReplElement[]>model.getReplElements();
assert.equal(elements.length, 4);
......@@ -417,19 +418,19 @@ suite('Debug - Model', () => {
assert.equal(elements[3].value, 'fourth line');
assert.equal(elements[3].severity, severity.Error);
model.appendToRepl('1', severity.Warning);
session.appendToRepl('1', severity.Warning);
elements = <SimpleReplElement[]>model.getReplElements();
assert.equal(elements.length, 5);
assert.equal(elements[4].value, '1');
assert.equal(elements[4].severity, severity.Warning);
const keyValueObject = { 'key1': 2, 'key2': 'value' };
model.appendToRepl(new RawObjectReplElement('fake', keyValueObject), null);
session.appendToRepl(new RawObjectReplElement('fake', keyValueObject), null);
const element = <RawObjectReplElement>model.getReplElements()[5];
assert.equal(element.value, 'Object');
assert.deepEqual(element.valueObj, keyValueObject);
model.removeReplExpressions();
session.removeReplExpressions();
assert.equal(model.getReplElements().length, 0);
});
});
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册