make sure createDiagnosticsCollection doesn't leak RPC, https://github.com/microsoft/vscode/issues/115679

This commit is contained in:
Johannes Rieken
2021-08-27 12:05:23 +02:00
parent f5ce7996ae
commit f71aba6560
2 changed files with 40 additions and 29 deletions

View File

@@ -19,7 +19,10 @@ import { IExtUri } from 'vs/base/common/resources';
export class DiagnosticCollection implements vscode.DiagnosticCollection {
private readonly _data: ResourceMap<vscode.Diagnostic[]>;
readonly #proxy: MainThreadDiagnosticsShape | undefined;
readonly #onDidChangeDiagnostics: Emitter<vscode.Uri[]>;
readonly #data: ResourceMap<vscode.Diagnostic[]>;
private _isDisposed = false;
constructor(
@@ -27,19 +30,21 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
private readonly _owner: string,
private readonly _maxDiagnosticsPerFile: number,
extUri: IExtUri,
private readonly _proxy: MainThreadDiagnosticsShape | undefined,
private readonly _onDidChangeDiagnostics: Emitter<vscode.Uri[]>
proxy: MainThreadDiagnosticsShape | undefined,
onDidChangeDiagnostics: Emitter<vscode.Uri[]>
) {
this._data = new ResourceMap(uri => extUri.getComparisonKey(uri));
this.#data = new ResourceMap(uri => extUri.getComparisonKey(uri));
this.#proxy = proxy;
this.#onDidChangeDiagnostics = onDidChangeDiagnostics;
}
dispose(): void {
if (!this._isDisposed) {
this._onDidChangeDiagnostics.fire([...this._data.keys()]);
if (this._proxy) {
this._proxy.$clear(this._owner);
this.#onDidChangeDiagnostics.fire([...this.#data.keys()]);
if (this.#proxy) {
this.#proxy.$clear(this._owner);
}
this._data.clear();
this.#data.clear();
this._isDisposed = true;
}
}
@@ -73,7 +78,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
}
// update single row
this._data.set(first, diagnostics.slice());
this.#data.set(first, diagnostics.slice());
toSync = [first];
} else if (Array.isArray(first)) {
@@ -87,22 +92,22 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
for (const tuple of first) {
const [uri, diagnostics] = tuple;
if (!lastUri || uri.toString() !== lastUri.toString()) {
if (lastUri && this._data.get(lastUri)!.length === 0) {
this._data.delete(lastUri);
if (lastUri && this.#data.get(lastUri)!.length === 0) {
this.#data.delete(lastUri);
}
lastUri = uri;
toSync.push(uri);
this._data.set(uri, []);
this.#data.set(uri, []);
}
if (!diagnostics) {
// [Uri, undefined] means clear this
const currentDiagnostics = this._data.get(uri);
const currentDiagnostics = this.#data.get(uri);
if (currentDiagnostics) {
currentDiagnostics.length = 0;
}
} else {
const currentDiagnostics = this._data.get(uri);
const currentDiagnostics = this.#data.get(uri);
if (currentDiagnostics) {
currentDiagnostics.push(...diagnostics);
}
@@ -111,16 +116,16 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
}
// send event for extensions
this._onDidChangeDiagnostics.fire(toSync);
this.#onDidChangeDiagnostics.fire(toSync);
// compute change and send to main side
if (!this._proxy) {
if (!this.#proxy) {
return;
}
const entries: [URI, IMarkerData[]][] = [];
for (let uri of toSync) {
let marker: IMarkerData[] = [];
const diagnostics = this._data.get(uri);
const diagnostics = this.#data.get(uri);
if (diagnostics) {
// no more than N diagnostics per file
@@ -154,37 +159,37 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
entries.push([uri, marker]);
}
this._proxy.$changeMany(this._owner, entries);
this.#proxy.$changeMany(this._owner, entries);
}
delete(uri: vscode.Uri): void {
this._checkDisposed();
this._onDidChangeDiagnostics.fire([uri]);
this._data.delete(uri);
if (this._proxy) {
this._proxy.$changeMany(this._owner, [[uri, undefined]]);
this.#onDidChangeDiagnostics.fire([uri]);
this.#data.delete(uri);
if (this.#proxy) {
this.#proxy.$changeMany(this._owner, [[uri, undefined]]);
}
}
clear(): void {
this._checkDisposed();
this._onDidChangeDiagnostics.fire([...this._data.keys()]);
this._data.clear();
if (this._proxy) {
this._proxy.$clear(this._owner);
this.#onDidChangeDiagnostics.fire([...this.#data.keys()]);
this.#data.clear();
if (this.#proxy) {
this.#proxy.$clear(this._owner);
}
}
forEach(callback: (uri: URI, diagnostics: ReadonlyArray<vscode.Diagnostic>, collection: DiagnosticCollection) => any, thisArg?: any): void {
this._checkDisposed();
for (let uri of this._data.keys()) {
for (let uri of this.#data.keys()) {
callback.apply(thisArg, [uri, this.get(uri), this]);
}
}
get(uri: URI): ReadonlyArray<vscode.Diagnostic> {
this._checkDisposed();
const result = this._data.get(uri);
const result = this.#data.get(uri);
if (Array.isArray(result)) {
return <ReadonlyArray<vscode.Diagnostic>>Object.freeze(result.slice(0));
}
@@ -193,7 +198,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
has(uri: URI): boolean {
this._checkDisposed();
return Array.isArray(this._data.get(uri));
return Array.isArray(this.#data.get(uri));
}
private _checkDisposed() {