-
Notifications
You must be signed in to change notification settings - Fork 29.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
adopt ensureNoDisposablesLeaked in code action model tests #209279
base: main
Are you sure you want to change the base?
Changes from 7 commits
d8f0dee
a2f7e04
ee71421
2394fcc
4d25e85
2907961
f005f2e
a18a742
0dcb64a
a5dc84c
88f4711
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,7 +6,7 @@ | |
import { CancelablePromise, createCancelablePromise, TimeoutTimer } from 'vs/base/common/async'; | ||
import { isCancellationError } from 'vs/base/common/errors'; | ||
import { Emitter } from 'vs/base/common/event'; | ||
import { Disposable, MutableDisposable } from 'vs/base/common/lifecycle'; | ||
import { Disposable, DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle'; | ||
import { isEqual } from 'vs/base/common/resources'; | ||
import { URI } from 'vs/base/common/uri'; | ||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; | ||
|
@@ -48,8 +48,13 @@ class CodeActionOracle extends Disposable { | |
} | ||
|
||
public trigger(trigger: CodeActionTrigger): void { | ||
const selection = this._getRangeOfSelectionUnlessWhitespaceEnclosed(trigger); | ||
this._signalChange(selection ? { trigger, selection } : undefined); | ||
try { | ||
const selection = this._getRangeOfSelectionUnlessWhitespaceEnclosed(trigger); | ||
this._signalChange(selection ? { trigger, selection } : undefined); | ||
} finally { | ||
// dispose after finishing (and after our _delay has passed) | ||
setTimeout(() => this.dispose(), 300); | ||
} | ||
} | ||
|
||
private _onMarkerChanges(resources: readonly URI[]): void { | ||
|
@@ -163,6 +168,8 @@ export class CodeActionModel extends Disposable { | |
private readonly _onDidChangeState = this._register(new Emitter<CodeActionsState.State>()); | ||
public readonly onDidChangeState = this._onDidChangeState.event; | ||
|
||
private readonly disposables = this._register(new DisposableStore()); | ||
|
||
private _disposed = false; | ||
|
||
constructor( | ||
|
@@ -192,6 +199,7 @@ export class CodeActionModel extends Disposable { | |
return; | ||
} | ||
this._disposed = true; | ||
this.disposables.dispose(); | ||
|
||
super.dispose(); | ||
this.setState(CodeActionsState.Empty, true); | ||
|
@@ -229,9 +237,10 @@ export class CodeActionModel extends Disposable { | |
|
||
const actions = createCancelablePromise(async token => { | ||
if (this._settingEnabledNearbyQuickfixes() && trigger.trigger.type === CodeActionTriggerType.Invoke && (trigger.trigger.triggerAction === CodeActionTriggerSource.QuickFix || trigger.trigger.filter?.include?.contains(CodeActionKind.QuickFix))) { | ||
const codeActionSet = await getCodeActions(this._registry, model, trigger.selection, trigger.trigger, Progress.None, token); | ||
const codeActionSet = this.disposables.add(await getCodeActions(this._registry, model, trigger.selection, trigger.trigger, Progress.None, token)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this introduces a leak as items are added to Instead try to make sure the old disposable values are released once a new set of values come in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That sounds like something for a DisposableStore and/or a MutableDisposable |
||
const allCodeActions = [...codeActionSet.allActions]; | ||
if (token.isCancellationRequested) { | ||
this.disposables.delete(codeActionSet); | ||
return emptyCodeActionSet; | ||
} | ||
|
||
|
@@ -270,7 +279,7 @@ export class CodeActionModel extends Disposable { | |
}; | ||
|
||
const selectionAsPosition = new Selection(trackedPosition.lineNumber, trackedPosition.column, trackedPosition.lineNumber, trackedPosition.column); | ||
const actionsAtMarker = await getCodeActions(this._registry, model, selectionAsPosition, newCodeActionTrigger, Progress.None, token); | ||
const actionsAtMarker = this.disposables.add(await getCodeActions(this._registry, model, selectionAsPosition, newCodeActionTrigger, Progress.None, token)); | ||
|
||
if (actionsAtMarker.validActions.length !== 0) { | ||
for (const action of actionsAtMarker.validActions) { | ||
|
@@ -315,8 +324,8 @@ export class CodeActionModel extends Disposable { | |
} | ||
} | ||
} | ||
// temporarilly hiding here as this is enabled/disabled behind a setting. | ||
return getCodeActions(this._registry, model, trigger.selection, trigger.trigger, Progress.None, token); | ||
const codeActionSet = this.disposables.add(await getCodeActions(this._registry, model, trigger.selection, trigger.trigger, Progress.None, token)); | ||
return codeActionSet; | ||
}); | ||
if (trigger.trigger.type === CodeActionTriggerType.Invoke) { | ||
this._progressService?.showWhile(actions, 250); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems fishy. You rarely want to call
dispose
directly like this as using the object should no longer be used after it has been disposed of . It looks like this object is meant to hang around for a whileWhat object was getting reported as leaked?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, this is the stack trace:
codeActionModel.js:269
is the call togetCodeActions
that we are returning.agree, when disposing immediately, you would get the error i mentioned before, so the code action set and actions derived from it are seemingly used in the command later on as well, so disposing it early (even after no longer being used in the function) leads to issues. will continue to explore this as well.