diff --git a/src/vs/workbench/parts/debug/common/debugModel.ts b/src/vs/workbench/parts/debug/common/debugModel.ts index 8de493c8544..29d29838739 100644 --- a/src/vs/workbench/parts/debug/common/debugModel.ts +++ b/src/vs/workbench/parts/debug/common/debugModel.ts @@ -12,6 +12,7 @@ import { generateUuid } from 'vs/base/common/uuid'; import { clone } from 'vs/base/common/objects'; import severity from 'vs/base/common/severity'; import { isObject, isString } from 'vs/base/common/types'; +import * as strings from 'vs/base/common/strings'; import { distinct } from 'vs/base/common/arrays'; import { IRange } from 'vs/editor/common/editorCommon'; import { Range } from 'vs/editor/common/core/range'; @@ -40,7 +41,6 @@ export class ValueOutputElement extends OutputElement { constructor( public value: string, public severity: severity, - public category?: string, public counter = 1 ) { super(); @@ -288,7 +288,6 @@ export class Variable extends ExpressionContainer implements debug.IExpression { this.namedVariables = response.body.namedVariables; this.indexedVariables = response.body.indexedVariables; } - // TODO@Isidor notify stackFrame that a change has happened so watch expressions get revelauted }, err => { this.errorMessage = err.message; }); @@ -808,63 +807,37 @@ export class Model implements debug.IModel { public addReplExpression(process: debug.IProcess, stackFrame: debug.IStackFrame, name: string): TPromise { const expression = new Expression(name); - this.addReplElements([expression]); + this.addReplElement(expression); return expression.evaluate(process, stackFrame, 'repl') .then(() => this._onDidChangeREPLElements.fire()); } - public logToRepl(value: string | { [key: string]: any }, severity?: severity): void { - let elements: OutputElement[] = []; - let previousOutput = this.replElements.length && (this.replElements[this.replElements.length - 1]); + public appendReplOutput(value: string | { [key: string]: any }, severity?: severity): void { + const previousOutput = this.replElements.length && (this.replElements[this.replElements.length - 1] as ValueOutputElement); - // string message if (typeof value === 'string') { - if (value && value.trim() && previousOutput && previousOutput.value === value && previousOutput.severity === severity) { - previousOutput.counter++; // we got the same output (but not an empty string when trimmed) so we just increment the counter + const groupTogether = previousOutput instanceof ValueOutputElement && severity === previousOutput.severity; + if (groupTogether) { + if (strings.endsWith(previousOutput.value, '\n') && previousOutput.value === value && value.trim()) { + // we got the same output (but not an empty string when trimmed) so we just increment the counter + previousOutput.counter++; + } else { + // append to previous line if same group + previousOutput.value += value; + } } else { - let lines = value.trim().split('\n'); - lines.forEach((line, index) => { - elements.push(new ValueOutputElement(line, severity)); - }); + this.addReplElement(new ValueOutputElement(value, severity)); } + } else { + // key-value output + this.addReplElement(new KeyValueOutputElement((value).prototype, value, nls.localize('snapshotObj', "Only primitive values are shown for this object."))); } - // key-value output - else { - elements.push(new KeyValueOutputElement((value).prototype, value, nls.localize('snapshotObj', "Only primitive values are shown for this object."))); - } - - if (elements.length) { - this.addReplElements(elements); - } this._onDidChangeREPLElements.fire(); } - public appendReplOutput(value: string, severity?: severity): void { - const elements: OutputElement[] = []; - const previousOutput = this.replElements.length && (this.replElements[this.replElements.length - 1]); - const lines = value.split('\n'); - const groupTogether = !!previousOutput && (previousOutput.category === 'output' && severity === previousOutput.severity); - - if (groupTogether) { - // append to previous line if same group - previousOutput.value += lines.shift(); - } else if (previousOutput && previousOutput.value === '') { - // remove potential empty lines between different output types - this.replElements.pop(); - } - - // fill in lines as output value elements - lines.forEach((line, index) => { - elements.push(new ValueOutputElement(line, severity, 'output')); - }); - - this.addReplElements(elements); - this._onDidChangeREPLElements.fire(); - } - - private addReplElements(newElements: debug.ITreeElement[]): void { - this.replElements.push(...newElements); + private addReplElement(newElement: debug.ITreeElement): void { + this.replElements.push(newElement); if (this.replElements.length > MAX_REPL_LENGTH) { this.replElements.splice(0, this.replElements.length - MAX_REPL_LENGTH); } diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 7bf8ada792d..7316cec68ee 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -195,12 +195,12 @@ export class DebugService implements debug.IDebugService { // flush any existing simple values logged if (simpleVals.length) { - this.model.logToRepl(simpleVals.join(' '), sev); + this.model.appendReplOutput(simpleVals.join(' '), sev); simpleVals = []; } // show object - this.model.logToRepl(a, sev); + this.model.appendReplOutput(a, sev); } // string: watch out for % replacement directive @@ -229,7 +229,7 @@ export class DebugService implements debug.IDebugService { // flush simple values if (simpleVals.length) { - this.model.logToRepl(simpleVals.join(' '), sev); + this.model.appendReplOutput(simpleVals.join(' '), sev); } } } diff --git a/src/vs/workbench/parts/debug/test/node/debugModel.test.ts b/src/vs/workbench/parts/debug/test/node/debugModel.test.ts index 0259b19346a..1a2db11ee55 100644 --- a/src/vs/workbench/parts/debug/test/node/debugModel.test.ts +++ b/src/vs/workbench/parts/debug/test/node/debugModel.test.ts @@ -331,34 +331,45 @@ suite('Debug - Model', () => { // Repl output test('repl output', () => { - model.logToRepl('first line', severity.Error); - model.logToRepl('second line', severity.Warning); - model.logToRepl('second line', severity.Warning); - model.logToRepl('second line', severity.Error); + model.appendReplOutput('first line\n', severity.Error); + model.appendReplOutput('second line\n', severity.Warning); + model.appendReplOutput('second line\n', severity.Warning); + model.appendReplOutput('second line\n', severity.Error); let elements = model.getReplElements(); assert.equal(elements.length, 3); - assert.equal(elements[0].value, 'first line'); + assert.equal(elements[0].value, 'first line\n'); assert.equal(elements[0].counter, 1); assert.equal(elements[0].severity, severity.Error); - assert.equal(elements[1].value, 'second line'); + assert.equal(elements[1].value, 'second line\n'); assert.equal(elements[1].counter, 2); assert.equal(elements[1].severity, severity.Warning); - model.appendReplOutput('1', severity.Error); - model.appendReplOutput('2', severity.Error); - model.appendReplOutput('3', severity.Error); + model.appendReplOutput('1', severity.Warning); + model.appendReplOutput('2', severity.Warning); + model.appendReplOutput('3', severity.Warning); elements = model.getReplElements(); assert.equal(elements.length, 4); assert.equal(elements[3].value, '123'); - assert.equal(elements[3].severity, severity.Error); + assert.equal(elements[3].severity, severity.Warning); const keyValueObject = { 'key1': 2, 'key2': 'value' }; - model.logToRepl(keyValueObject); + model.appendReplOutput(keyValueObject); const element = model.getReplElements()[4]; assert.equal(element.value, 'Object'); assert.deepEqual(element.valueObj, keyValueObject); + const multiLineContent = 'multi line \n string \n last line'; + model.appendReplOutput(multiLineContent); + const multiLineElement = model.getReplElements()[5]; + assert.equal(multiLineElement.value, multiLineContent); + assert.equal(model.getReplElements().length, 6); + + model.appendReplOutput('second line', severity.Warning); + model.appendReplOutput('second line', severity.Warning); + + assert.equal((model.getReplElements()[6]).value, 'second linesecond line'); + model.removeReplExpressions(); assert.equal(model.getReplElements().length, 0); });