Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
* Fixes microsoft#208449

* Fixes leak

* Fixes more leaks
  • Loading branch information
hediet authored and sergioengineer committed Apr 23, 2024
1 parent 90faa9a commit 3002101
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 15 deletions.
8 changes: 7 additions & 1 deletion src/vs/base/common/cancellation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/

import { Emitter, Event } from 'vs/base/common/event';
import { IDisposable } from 'vs/base/common/lifecycle';
import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle';

export interface CancellationToken {

Expand Down Expand Up @@ -140,3 +140,9 @@ export class CancellationTokenSource {
}
}
}

export function cancelOnDispose(store: DisposableStore): CancellationToken {
const source = new CancellationTokenSource();
store.add({ dispose() { source.cancel(); } });
return source.token;
}
20 changes: 17 additions & 3 deletions src/vs/base/common/observableInternal/promise.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Derived, derived } from 'vs/base/common/observableInternal/derived';
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import { DebugNameData, Owner } from 'vs/base/common/observableInternal/debugName';
import { strictEquals } from 'vs/base/common/equals';
import { CancellationError } from 'vs/base/common/errors';

export class ObservableLazy<T> {
private readonly _value = observableValue<T | undefined>(this, undefined);
Expand Down Expand Up @@ -120,9 +121,9 @@ export class ObservableLazyPromise<T> {
* Resolves the promise when the observables state matches the predicate.
*/
export function waitForState<T>(observable: IObservable<T | null | undefined>): Promise<T>;
export function waitForState<T, TState extends T>(observable: IObservable<T>, predicate: (state: T) => state is TState, isError?: (state: T) => boolean | unknown | undefined): Promise<TState>;
export function waitForState<T>(observable: IObservable<T>, predicate: (state: T) => boolean, isError?: (state: T) => boolean | unknown | undefined): Promise<T>;
export function waitForState<T>(observable: IObservable<T>, predicate?: (state: T) => boolean, isError?: (state: T) => boolean | unknown | undefined): Promise<T> {
export function waitForState<T, TState extends T>(observable: IObservable<T>, predicate: (state: T) => state is TState, isError?: (state: T) => boolean | unknown | undefined, cancellationToken?: CancellationToken): Promise<TState>;
export function waitForState<T>(observable: IObservable<T>, predicate: (state: T) => boolean, isError?: (state: T) => boolean | unknown | undefined, cancellationToken?: CancellationToken): Promise<T>;
export function waitForState<T>(observable: IObservable<T>, predicate?: (state: T) => boolean, isError?: (state: T) => boolean | unknown | undefined, cancellationToken?: CancellationToken): Promise<T> {
if (!predicate) {
predicate = state => state !== null && state !== undefined;
}
Expand Down Expand Up @@ -154,6 +155,19 @@ export function waitForState<T>(observable: IObservable<T>, predicate?: (state:
}
}
});
if (cancellationToken) {
const dc = cancellationToken.onCancellationRequested(() => {
d.dispose();
dc.dispose();
reject(new CancellationError());
});
if (cancellationToken.isCancellationRequested) {
d.dispose();
dc.dispose();
reject(new CancellationError());
return;
}
}
isImmediateRun = false;
if (shouldDispose) {
d.dispose();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,14 @@

import { createStyleSheet2 } from 'vs/base/browser/dom';
import { alert } from 'vs/base/browser/ui/aria/aria';
import { timeout } from 'vs/base/common/async';
import { cancelOnDispose } from 'vs/base/common/cancellation';
import { itemEquals, itemsEquals } from 'vs/base/common/equals';
import { Disposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
import { IObservable, ITransaction, autorun, autorunHandleChanges, constObservable, derived, disposableObservableValue, observableFromEvent, observableSignal, observableValue, transaction } from 'vs/base/common/observable';
import { IObservable, ITransaction, autorun, autorunHandleChanges, constObservable, derived, disposableObservableValue, observableFromEvent, observableSignal, observableValue, transaction, waitForState } from 'vs/base/common/observable';
import { ISettableObservable, observableValueOpts } from 'vs/base/common/observableInternal/base';
import { mapObservableArrayCached } from 'vs/base/common/observableInternal/utils';
import { isUndefined } from 'vs/base/common/types';
import { CoreEditingCommands } from 'vs/editor/browser/coreCommands';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { EditorOption } from 'vs/editor/common/config/editorOptions';
Expand All @@ -23,16 +29,13 @@ import { InlineCompletionsHintsWidget, InlineSuggestionHintsContentWidget } from
import { InlineCompletionsModel, VersionIdChangeReason } from 'vs/editor/contrib/inlineCompletions/browser/inlineCompletionsModel';
import { SuggestWidgetAdaptor } from 'vs/editor/contrib/inlineCompletions/browser/suggestWidgetInlineCompletionProvider';
import { localize } from 'vs/nls';
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
import { AccessibilitySignal, IAccessibilitySignalService } from 'vs/platform/accessibilitySignal/browser/accessibilitySignalService';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { mapObservableArrayCached } from 'vs/base/common/observableInternal/utils';
import { ISettableObservable, observableValueOpts } from 'vs/base/common/observableInternal/base';
import { itemsEquals, itemEquals } from 'vs/base/common/equals';
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';

export class InlineCompletionsController extends Disposable {
static ID = 'editor.contrib.inlineCompletionsController';
Expand Down Expand Up @@ -217,6 +220,7 @@ export class InlineCompletionsController extends Disposable {
this._suggestWidgetAdaptor.stopForceRenderingAbove();
}));

const cancellationStore = this._register(new DisposableStore());
let lastInlineCompletionId: string | undefined = undefined;
this._register(autorunHandleChanges({
handleChange: (context, changeSummary) => {
Expand All @@ -225,7 +229,7 @@ export class InlineCompletionsController extends Disposable {
}
return true;
},
}, async reader => {
}, async (reader, _) => {
/** @description InlineCompletionsController.playAccessibilitySignalAndReadSuggestion */
this._playAccessibilitySignal.read(reader);

Expand All @@ -237,13 +241,18 @@ export class InlineCompletionsController extends Disposable {
}

if (state.inlineCompletion.semanticId !== lastInlineCompletionId) {
cancellationStore.clear();
lastInlineCompletionId = state.inlineCompletion.semanticId;
const lineText = model.textModel.getLineContent(state.primaryGhostText.lineNumber);
this._accessibilitySignalService.playSignal(AccessibilitySignal.inlineSuggestion).then(() => {
if (this.editor.getOption(EditorOption.screenReaderAnnounceInlineSuggestion)) {
this.provideScreenReaderUpdate(state.primaryGhostText.renderForScreenReader(lineText));
}
});

await timeout(50, cancelOnDispose(cancellationStore));
await waitForState(this._suggestWidgetAdaptor.selectedItem, isUndefined, () => false, cancelOnDispose(cancellationStore));

await this._accessibilitySignalService.playSignal(AccessibilitySignal.inlineSuggestion);

if (this.editor.getOption(EditorOption.screenReaderAnnounceInlineSuggestion)) {
this.provideScreenReaderUpdate(state.primaryGhostText.renderForScreenReader(lineText));
}
}
}));

Expand Down

0 comments on commit 3002101

Please sign in to comment.