Add a mechanism to track disposables from unit tests
This commit is contained in:
parent
11ac71b272
commit
7c3aacb40a
|
@ -14,34 +14,53 @@ import { Iterable } from 'vs/base/common/iterator';
|
|||
* extend Disposable or use a DisposableStore. This means there are a lot of false positives.
|
||||
*/
|
||||
const TRACK_DISPOSABLES = false;
|
||||
let disposableTracker: IDisposableTracker | null = null;
|
||||
|
||||
const __is_disposable_tracked__ = '__is_disposable_tracked__';
|
||||
|
||||
function markTracked<T extends IDisposable>(x: T): void {
|
||||
if (!TRACK_DISPOSABLES) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (x && x !== Disposable.None) {
|
||||
try {
|
||||
(x as any)[__is_disposable_tracked__] = true;
|
||||
} catch {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
export interface IDisposableTracker {
|
||||
trackDisposable(x: IDisposable): void;
|
||||
markTracked(x: IDisposable): void;
|
||||
}
|
||||
|
||||
function trackDisposable<T extends IDisposable>(x: T): T {
|
||||
if (!TRACK_DISPOSABLES) {
|
||||
export function setDisposableTracker(tracker: IDisposableTracker | null): void {
|
||||
disposableTracker = tracker;
|
||||
}
|
||||
|
||||
if (TRACK_DISPOSABLES) {
|
||||
const __is_disposable_tracked__ = '__is_disposable_tracked__';
|
||||
disposableTracker = new class implements IDisposableTracker {
|
||||
trackDisposable(x: IDisposable): void {
|
||||
const stack = new Error('Potentially leaked disposable').stack!;
|
||||
setTimeout(() => {
|
||||
if (!(x as any)[__is_disposable_tracked__]) {
|
||||
console.log(stack);
|
||||
}
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
markTracked(x: IDisposable): void {
|
||||
if (x && x !== Disposable.None) {
|
||||
try {
|
||||
(x as any)[__is_disposable_tracked__] = true;
|
||||
} catch {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function markTracked<T extends IDisposable>(x: T): void {
|
||||
if (!disposableTracker) {
|
||||
return;
|
||||
}
|
||||
disposableTracker.markTracked(x);
|
||||
}
|
||||
|
||||
export function trackDisposable<T extends IDisposable>(x: T): T {
|
||||
if (!disposableTracker) {
|
||||
return x;
|
||||
}
|
||||
|
||||
const stack = new Error('Potentially leaked disposable').stack!;
|
||||
setTimeout(() => {
|
||||
if (!(x as any)[__is_disposable_tracked__]) {
|
||||
console.log(stack);
|
||||
}
|
||||
}, 3000);
|
||||
disposableTracker.trackDisposable(x);
|
||||
return x;
|
||||
}
|
||||
|
||||
|
|
36
src/vs/base/test/common/lifecycle.ts
Normal file
36
src/vs/base/test/common/lifecycle.ts
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IDisposable, IDisposableTracker, setDisposableTracker } from 'vs/base/common/lifecycle';
|
||||
|
||||
class DisposableTracker implements IDisposableTracker {
|
||||
allDisposables: [IDisposable, string][] = [];
|
||||
trackDisposable(x: IDisposable): void {
|
||||
this.allDisposables.push([x, new Error().stack!]);
|
||||
}
|
||||
markTracked(x: IDisposable): void {
|
||||
for (let idx = 0; idx < this.allDisposables.length; idx++) {
|
||||
if (this.allDisposables[idx][0] === x) {
|
||||
this.allDisposables.splice(idx, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let currentTracker: DisposableTracker | null = null;
|
||||
|
||||
export function beginTrackingDisposables(): void {
|
||||
currentTracker = new DisposableTracker();
|
||||
setDisposableTracker(currentTracker);
|
||||
}
|
||||
|
||||
export function logTrackedDisposables(): void {
|
||||
if (currentTracker) {
|
||||
setDisposableTracker(null);
|
||||
console.log(currentTracker!.allDisposables.map(e => `${e[0]}\n${e[1]}`).join('\n\n'));
|
||||
currentTracker = null;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue