diff --git a/src/vs/workbench/api/node/extHostDiagnostics.ts b/src/vs/workbench/api/node/extHostDiagnostics.ts index 0fa5eeaa480..38b7850a6c6 100644 --- a/src/vs/workbench/api/node/extHostDiagnostics.ts +++ b/src/vs/workbench/api/node/extHostDiagnostics.ts @@ -8,6 +8,7 @@ import {localize} from 'vs/nls'; import {IThreadService} from 'vs/workbench/services/thread/common/threadService'; import {IMarkerData} from 'vs/platform/markers/common/markers'; import URI from 'vs/base/common/uri'; +import {compare} from 'vs/base/common/strings'; import Severity from 'vs/base/common/severity'; import * as vscode from 'vscode'; import {MainContext, MainThreadDiagnosticsShape, ExtHostDiagnosticsShape} from './extHost.protocol'; @@ -72,20 +73,23 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection { } else if (Array.isArray(first)) { // update many rows toSync = []; - for (let entry of first) { - let [uri, diagnostics] = entry; - toSync.push(uri); + let lastUri: vscode.Uri; + for (const entry of first.slice(0).sort(DiagnosticCollection._compareTuplesByUri)) { + const [uri, diagnostics] = entry; + if (!lastUri || uri.toString() !== lastUri.toString()) { + if (lastUri && this._data[lastUri.toString()].length === 0) { + delete this._data[lastUri.toString()]; + } + lastUri = uri; + toSync.push(uri); + this._data[uri.toString()] = []; + } + if (!diagnostics) { // [Uri, undefined] means clear this - delete this._data[uri.toString()]; + this._data[uri.toString()].length = 0; } else { - // set or merge diagnostics - let existing = this._data[uri.toString()]; - if (existing) { - existing.push(...diagnostics); - } else { - this._data[uri.toString()] = diagnostics; - } + this._data[uri.toString()].push(...diagnostics); } } } @@ -196,6 +200,10 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection { default: return Severity.Error; } } + + private static _compareTuplesByUri(a: [vscode.Uri, vscode.Diagnostic[]], b: [vscode.Uri, vscode.Diagnostic[]]): number { + return compare(a[0].toString(), b[0].toString()); + } } export class ExtHostDiagnostics extends ExtHostDiagnosticsShape { diff --git a/src/vs/workbench/test/node/api/extHostDiagnostics.test.ts b/src/vs/workbench/test/node/api/extHostDiagnostics.test.ts index 999f59de499..ec1c67b84ab 100644 --- a/src/vs/workbench/test/node/api/extHostDiagnostics.test.ts +++ b/src/vs/workbench/test/node/api/extHostDiagnostics.test.ts @@ -159,6 +159,35 @@ suite('ExtHostDiagnostics', () => { collection.dispose(); }); + test('diagnostics collection, set tuple overrides, #11547', function () { + + let lastEntries: [URI, IMarkerData[]][]; + let collection = new DiagnosticCollection('test', new class extends DiagnosticsShape { + $changeMany(owner: string, entries: [URI, IMarkerData[]][]): TPromise { + lastEntries = entries; + return super.$changeMany(owner, entries); + } + }); + let uri = URI.parse('sc:hightower'); + + collection.set([[uri, [new Diagnostic(new Range(0, 0, 1, 1), 'error')]]]); + assert.equal(collection.get(uri).length, 1); + assert.equal(collection.get(uri)[0].message, 'error'); + assert.equal(lastEntries.length, 1); + let [[, data1]] = lastEntries; + assert.equal(data1.length, 1); + assert.equal(data1[0].message, 'error'); + lastEntries = undefined; + + collection.set([[uri, [new Diagnostic(new Range(0, 0, 1, 1), 'warning')]]]); + assert.equal(collection.get(uri).length, 1); + assert.equal(collection.get(uri)[0].message, 'warning'); + assert.equal(lastEntries.length, 1); + let [[, data2]] = lastEntries; + assert.equal(data2.length, 1); + assert.equal(data2[0].message, 'warning'); + lastEntries = undefined; + }); test('diagnostic capping', function () {