Ensure no disposables are leaked in inline completion tests.

This commit is contained in:
Henning Dieterichs 2021-07-07 23:57:26 +02:00
parent c4e6c95d8c
commit bc3dde78b3
No known key found for this signature in database
GPG key ID: 771381EFFDB9EC06
3 changed files with 6 additions and 46 deletions

View file

@ -7,7 +7,7 @@ import { CancelablePromise, createCancelablePromise, RunOnceScheduler } from 'vs
import { CancellationToken } from 'vs/base/common/cancellation';
import { onUnexpectedError, onUnexpectedExternalError } from 'vs/base/common/errors';
import { Emitter } from 'vs/base/common/event';
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { Disposable, IDisposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
import * as strings from 'vs/base/common/strings';
import { IActiveCodeEditor } from 'vs/editor/browser/editorBrowser';
import { Position } from 'vs/editor/common/core/position';
@ -17,7 +17,6 @@ import { InlineCompletion, InlineCompletionContext, InlineCompletions, InlineCom
import { EditOperation } from 'vs/editor/common/core/editOperation';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { EditorOption } from 'vs/editor/common/config/editorOptions';
import { MutableDisposable } from 'vs/editor/contrib/inlineCompletions/utils';
import { RedoCommand, UndoCommand } from 'vs/editor/browser/editorExtensions';
import { CoreEditingCommands } from 'vs/editor/browser/controller/coreCommands';
import { IDiffChange, stringDiff } from 'vs/base/common/diff/diff';
@ -381,7 +380,7 @@ export class InlineCompletionsSession extends BaseGhostTextWidgetModel {
public commit(completion: LiveInlineCompletion): void {
// Mark the cache as stale, but don't dispose it yet,
// otherwise command args might get disposed.
const cache = this.cache.replace(undefined);
const cache = this.cache.clearAndLeak();
this.editor.executeEdits(
'inlineSuggestion.accept',

View file

@ -14,6 +14,9 @@ import { GhostTextContext, MockInlineCompletionsProvider, renderGhostTextToText
import { ITestCodeEditor, TestCodeEditorCreationOptions, withAsyncTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor';
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
import sinon = require('sinon');
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
ensureNoDisposablesAreLeakedInTestSuite();
suite('inlineCompletionToGhostText', () => {
function getOutput(text: string, suggestion: string): unknown {
@ -497,6 +500,7 @@ async function withAsyncTestCodeEditorAndInlineCompletionsModel(
const model = instantiationService.createInstance(InlineCompletionsModel, editor);
const context = new GhostTextContext(model, editor);
await callback({ editor, editorViewModel, model, context });
context.dispose();
model.dispose();
});
@ -508,8 +512,6 @@ async function withAsyncTestCodeEditorAndInlineCompletionsModel(
if (options.provider instanceof MockInlineCompletionsProvider) {
options.provider.assertNotCalledTwiceWithin50ms();
}
} finally {
clock?.restore();
disposableStore.dispose();

View file

@ -11,44 +11,3 @@ export function createDisposableRef<T>(object: T, disposable?: IDisposable): IRe
dispose: () => disposable?.dispose(),
};
}
// TODO: merge this class into Matt's MutableDisposable.
/**
* Manages the lifecycle of a disposable value that may be changed.
*
* This ensures that when the disposable value is changed, the previously held disposable is disposed of. You can
* also register a `MutableDisposable` on a `Disposable` to ensure it is automatically cleaned up.
*/
export class MutableDisposable<T extends IDisposable> implements IDisposable {
private _value?: T;
private _isDisposed = false;
get value(): T | undefined {
return this._isDisposed ? undefined : this._value;
}
set value(value: T | undefined) {
if (this._isDisposed || value === this._value) {
return;
}
this._value?.dispose();
this._value = value;
}
clear() {
this.value = undefined;
}
dispose(): void {
this._isDisposed = true;
this._value?.dispose();
this._value = undefined;
}
replace(newValue: T | undefined): T | undefined {
const oldValue = this._value;
this._value = newValue;
return oldValue;
}
}