Skip to content

Commit 93846ca

Browse files
authored
add limits for how many files can have diagnostics (microsoft#188161)
microsoft#187272
1 parent 5fbbf11 commit 93846ca

File tree

2 files changed

+57
-18
lines changed

2 files changed

+57
-18
lines changed

src/vs/workbench/api/common/extHostDiagnostics.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,14 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
3131
constructor(
3232
private readonly _name: string,
3333
private readonly _owner: string,
34+
private readonly _maxDiagnosticsTotal: number,
3435
private readonly _maxDiagnosticsPerFile: number,
3536
private readonly _modelVersionIdProvider: (uri: URI) => number | undefined,
3637
extUri: IExtUri,
3738
proxy: MainThreadDiagnosticsShape | undefined,
3839
onDidChangeDiagnostics: Emitter<readonly vscode.Uri[]>
3940
) {
41+
this._maxDiagnosticsTotal = Math.max(_maxDiagnosticsPerFile, _maxDiagnosticsTotal);
4042
this.#data = new ResourceMap(uri => extUri.getComparisonKey(uri));
4143
this.#proxy = proxy;
4244
this.#onDidChangeDiagnostics = onDidChangeDiagnostics;
@@ -123,6 +125,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
123125
return;
124126
}
125127
const entries: [URI, IMarkerData[]][] = [];
128+
let totalMarkerCount = 0;
126129
for (const uri of toSync) {
127130
let marker: IMarkerData[] = [];
128131
const diagnostics = this.#data.get(uri);
@@ -158,6 +161,12 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
158161
}
159162

160163
entries.push([uri, marker]);
164+
165+
totalMarkerCount += marker.length;
166+
if (totalMarkerCount > this._maxDiagnosticsTotal) {
167+
// ignore markers that are above the limit
168+
break;
169+
}
161170
}
162171
this.#proxy.$changeMany(this._owner, entries);
163172
}
@@ -225,6 +234,7 @@ export class ExtHostDiagnostics implements ExtHostDiagnosticsShape {
225234

226235
private static _idPool: number = 0;
227236
private static readonly _maxDiagnosticsPerFile: number = 1000;
237+
private static readonly _maxDiagnosticsTotal: number = 1.1 * ExtHostDiagnostics._maxDiagnosticsPerFile;
228238

229239
private readonly _proxy: MainThreadDiagnosticsShape;
230240
private readonly _collections = new Map<string, DiagnosticCollection>();
@@ -284,7 +294,9 @@ export class ExtHostDiagnostics implements ExtHostDiagnosticsShape {
284294
const result = new class extends DiagnosticCollection {
285295
constructor() {
286296
super(
287-
name!, owner, ExtHostDiagnostics._maxDiagnosticsPerFile,
297+
name!, owner,
298+
ExtHostDiagnostics._maxDiagnosticsTotal,
299+
ExtHostDiagnostics._maxDiagnosticsPerFile,
288300
uri => _extHostDocumentsAndEditors.getDocument(uri)?.version,
289301
_fileSystemInfoService.extUri, loggingProxy, _onDidChangeDiagnostics
290302
);
@@ -339,7 +351,12 @@ export class ExtHostDiagnostics implements ExtHostDiagnosticsShape {
339351

340352
if (!this._mirrorCollection) {
341353
const name = '_generated_mirror';
342-
const collection = new DiagnosticCollection(name, name, ExtHostDiagnostics._maxDiagnosticsPerFile, _uri => undefined, this._fileSystemInfoService.extUri, undefined, this._onDidChangeDiagnostics);
354+
const collection = new DiagnosticCollection(
355+
name, name,
356+
Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, // no limits because this collection is just a mirror of "sanitized" data
357+
_uri => undefined,
358+
this._fileSystemInfoService.extUri, undefined, this._onDidChangeDiagnostics
359+
);
343360
this._collections.set(name, collection);
344361
this._mirrorCollection = collection;
345362
}

src/vs/workbench/api/test/browser/extHostDiagnostics.test.ts

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ suite('ExtHostDiagnostics', () => {
4040

4141
test('disposeCheck', () => {
4242

43-
const collection = new DiagnosticCollection('test', 'test', 100, versionProvider, extUri, new DiagnosticsShape(), new Emitter());
43+
const collection = new DiagnosticCollection('test', 'test', 100, 100, versionProvider, extUri, new DiagnosticsShape(), new Emitter());
4444

4545
collection.dispose();
4646
collection.dispose(); // that's OK
@@ -56,13 +56,13 @@ suite('ExtHostDiagnostics', () => {
5656

5757

5858
test('diagnostic collection, forEach, clear, has', function () {
59-
let collection = new DiagnosticCollection('test', 'test', 100, versionProvider, extUri, new DiagnosticsShape(), new Emitter());
59+
let collection = new DiagnosticCollection('test', 'test', 100, 100, versionProvider, extUri, new DiagnosticsShape(), new Emitter());
6060
assert.strictEqual(collection.name, 'test');
6161
collection.dispose();
6262
assert.throws(() => collection.name);
6363

6464
let c = 0;
65-
collection = new DiagnosticCollection('test', 'test', 100, versionProvider, extUri, new DiagnosticsShape(), new Emitter());
65+
collection = new DiagnosticCollection('test', 'test', 100, 100, versionProvider, extUri, new DiagnosticsShape(), new Emitter());
6666
collection.forEach(() => c++);
6767
assert.strictEqual(c, 0);
6868

@@ -99,7 +99,7 @@ suite('ExtHostDiagnostics', () => {
9999
});
100100

101101
test('diagnostic collection, immutable read', function () {
102-
const collection = new DiagnosticCollection('test', 'test', 100, versionProvider, extUri, new DiagnosticsShape(), new Emitter());
102+
const collection = new DiagnosticCollection('test', 'test', 100, 100, versionProvider, extUri, new DiagnosticsShape(), new Emitter());
103103
collection.set(URI.parse('foo:bar'), [
104104
new Diagnostic(new Range(0, 0, 1, 1), 'message-1'),
105105
new Diagnostic(new Range(0, 0, 1, 1), 'message-2')
@@ -124,7 +124,7 @@ suite('ExtHostDiagnostics', () => {
124124

125125

126126
test('diagnostics collection, set with dupliclated tuples', function () {
127-
const collection = new DiagnosticCollection('test', 'test', 100, versionProvider, extUri, new DiagnosticsShape(), new Emitter());
127+
const collection = new DiagnosticCollection('test', 'test', 100, 100, versionProvider, extUri, new DiagnosticsShape(), new Emitter());
128128
const uri = URI.parse('sc:hightower');
129129
collection.set([
130130
[uri, [new Diagnostic(new Range(0, 0, 0, 1), 'message-1')]],
@@ -175,7 +175,7 @@ suite('ExtHostDiagnostics', () => {
175175
test('diagnostics collection, set tuple overrides, #11547', function () {
176176

177177
let lastEntries!: [UriComponents, IMarkerData[]][];
178-
const collection = new DiagnosticCollection('test', 'test', 100, versionProvider, extUri, new class extends DiagnosticsShape {
178+
const collection = new DiagnosticCollection('test', 'test', 100, 100, versionProvider, extUri, new class extends DiagnosticsShape {
179179
override $changeMany(owner: string, entries: [UriComponents, IMarkerData[]][]): void {
180180
lastEntries = entries;
181181
return super.$changeMany(owner, entries);
@@ -209,7 +209,7 @@ suite('ExtHostDiagnostics', () => {
209209

210210
const emitter = new Emitter<any>();
211211
emitter.event(_ => eventCount += 1);
212-
const collection = new DiagnosticCollection('test', 'test', 100, versionProvider, extUri, new class extends DiagnosticsShape {
212+
const collection = new DiagnosticCollection('test', 'test', 100, 100, versionProvider, extUri, new class extends DiagnosticsShape {
213213
override $changeMany() {
214214
changeCount += 1;
215215
}
@@ -229,7 +229,7 @@ suite('ExtHostDiagnostics', () => {
229229

230230
test('diagnostics collection, tuples and undefined (small array), #15585', function () {
231231

232-
const collection = new DiagnosticCollection('test', 'test', 100, versionProvider, extUri, new DiagnosticsShape(), new Emitter());
232+
const collection = new DiagnosticCollection('test', 'test', 100, 100, versionProvider, extUri, new DiagnosticsShape(), new Emitter());
233233
const uri = URI.parse('sc:hightower');
234234
const uri2 = URI.parse('sc:nomad');
235235
const diag = new Diagnostic(new Range(0, 0, 0, 1), 'ffff');
@@ -250,7 +250,7 @@ suite('ExtHostDiagnostics', () => {
250250

251251
test('diagnostics collection, tuples and undefined (large array), #15585', function () {
252252

253-
const collection = new DiagnosticCollection('test', 'test', 100, versionProvider, extUri, new DiagnosticsShape(), new Emitter());
253+
const collection = new DiagnosticCollection('test', 'test', 100, 100, versionProvider, extUri, new DiagnosticsShape(), new Emitter());
254254
const tuples: [URI, Diagnostic[]][] = [];
255255

256256
for (let i = 0; i < 500; i++) {
@@ -271,10 +271,10 @@ suite('ExtHostDiagnostics', () => {
271271
}
272272
});
273273

274-
test('diagnostic capping', function () {
274+
test('diagnostic capping (max per file)', function () {
275275

276276
let lastEntries!: [UriComponents, IMarkerData[]][];
277-
const collection = new DiagnosticCollection('test', 'test', 250, versionProvider, extUri, new class extends DiagnosticsShape {
277+
const collection = new DiagnosticCollection('test', 'test', 100, 250, versionProvider, extUri, new class extends DiagnosticsShape {
278278
override $changeMany(owner: string, entries: [UriComponents, IMarkerData[]][]): void {
279279
lastEntries = entries;
280280
return super.$changeMany(owner, entries);
@@ -298,9 +298,31 @@ suite('ExtHostDiagnostics', () => {
298298
assert.strictEqual(lastEntries[0][1][250].severity, MarkerSeverity.Info);
299299
});
300300

301+
test('diagnostic capping (max files)', function () {
302+
303+
let lastEntries!: [UriComponents, IMarkerData[]][];
304+
const collection = new DiagnosticCollection('test', 'test', 2, 1, versionProvider, extUri, new class extends DiagnosticsShape {
305+
override $changeMany(owner: string, entries: [UriComponents, IMarkerData[]][]): void {
306+
lastEntries = entries;
307+
return super.$changeMany(owner, entries);
308+
}
309+
}, new Emitter());
310+
311+
const diag = new Diagnostic(new Range(0, 0, 1, 1), 'Hello');
312+
313+
314+
collection.set([
315+
[URI.parse('aa:bb1'), [diag]],
316+
[URI.parse('aa:bb2'), [diag]],
317+
[URI.parse('aa:bb3'), [diag]],
318+
[URI.parse('aa:bb4'), [diag]],
319+
]);
320+
assert.strictEqual(lastEntries.length, 3); // goes above the limit and then stops
321+
});
322+
301323
test('diagnostic eventing', async function () {
302324
const emitter = new Emitter<readonly URI[]>();
303-
const collection = new DiagnosticCollection('ddd', 'test', 100, versionProvider, extUri, new DiagnosticsShape(), emitter);
325+
const collection = new DiagnosticCollection('ddd', 'test', 100, 100, versionProvider, extUri, new DiagnosticsShape(), emitter);
304326

305327
const diag1 = new Diagnostic(new Range(1, 1, 2, 3), 'diag1');
306328
const diag2 = new Diagnostic(new Range(1, 1, 2, 3), 'diag2');
@@ -338,7 +360,7 @@ suite('ExtHostDiagnostics', () => {
338360

339361
test('vscode.languages.onDidChangeDiagnostics Does Not Provide Document URI #49582', async function () {
340362
const emitter = new Emitter<readonly URI[]>();
341-
const collection = new DiagnosticCollection('ddd', 'test', 100, versionProvider, extUri, new DiagnosticsShape(), emitter);
363+
const collection = new DiagnosticCollection('ddd', 'test', 100, 100, versionProvider, extUri, new DiagnosticsShape(), emitter);
342364

343365
const diag1 = new Diagnostic(new Range(1, 1, 2, 3), 'diag1');
344366

@@ -361,7 +383,7 @@ suite('ExtHostDiagnostics', () => {
361383

362384
test('diagnostics with related information', function (done) {
363385

364-
const collection = new DiagnosticCollection('ddd', 'test', 100, versionProvider, extUri, new class extends DiagnosticsShape {
386+
const collection = new DiagnosticCollection('ddd', 'test', 100, 100, versionProvider, extUri, new class extends DiagnosticsShape {
365387
override $changeMany(owner: string, entries: [UriComponents, IMarkerData[]][]) {
366388

367389
const [[, data]] = entries;
@@ -424,7 +446,7 @@ suite('ExtHostDiagnostics', () => {
424446

425447
test('Error updating diagnostics from extension #60394', function () {
426448
let callCount = 0;
427-
const collection = new DiagnosticCollection('ddd', 'test', 100, versionProvider, extUri, new class extends DiagnosticsShape {
449+
const collection = new DiagnosticCollection('ddd', 'test', 100, 100, versionProvider, extUri, new class extends DiagnosticsShape {
428450
override $changeMany(owner: string, entries: [UriComponents, IMarkerData[]][]) {
429451
callCount += 1;
430452
}
@@ -451,7 +473,7 @@ suite('ExtHostDiagnostics', () => {
451473

452474
const all: [UriComponents, IMarkerData[]][] = [];
453475

454-
const collection = new DiagnosticCollection('ddd', 'test', 100, uri => {
476+
const collection = new DiagnosticCollection('ddd', 'test', 100, 100, uri => {
455477
return 7;
456478
}, extUri, new class extends DiagnosticsShape {
457479
override $changeMany(_owner: string, entries: [UriComponents, IMarkerData[]][]) {

0 commit comments

Comments
 (0)