diff --git a/src/vs/editor/common/languages.ts b/src/vs/editor/common/languages.ts index 0a0545a891abe..bef68de579deb 100644 --- a/src/vs/editor/common/languages.ts +++ b/src/vs/editor/common/languages.ts @@ -2107,7 +2107,7 @@ export interface CodeLens { export interface CodeLensList { lenses: CodeLens[]; - dispose(): void; + dispose?(): void; } export interface CodeLensProvider { diff --git a/src/vs/editor/common/languages/languageConfigurationRegistry.ts b/src/vs/editor/common/languages/languageConfigurationRegistry.ts index bf0516d531b23..f42b06d0b7462 100644 --- a/src/vs/editor/common/languages/languageConfigurationRegistry.ts +++ b/src/vs/editor/common/languages/languageConfigurationRegistry.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Emitter, Event } from '../../../base/common/event.js'; -import { Disposable, IDisposable, toDisposable } from '../../../base/common/lifecycle.js'; +import { Disposable, IDisposable, markAsSingleton, toDisposable } from '../../../base/common/lifecycle.js'; import * as strings from '../../../base/common/strings.js'; import { ITextModel } from '../model.js'; import { DEFAULT_WORD_REGEXP, ensureValidWordDefinition } from '../core/wordHelper.js'; @@ -202,7 +202,7 @@ class ComposedLanguageConfiguration { ); this._entries.push(entry); this._resolved = null; - return toDisposable(() => { + return markAsSingleton(toDisposable(() => { for (let i = 0; i < this._entries.length; i++) { if (this._entries[i] === entry) { this._entries.splice(i, 1); @@ -210,7 +210,7 @@ class ComposedLanguageConfiguration { break; } } - }); + })); } public getResolvedConfiguration(): ResolvedLanguageConfiguration | null { @@ -332,10 +332,10 @@ export class LanguageConfigurationRegistry extends Disposable { const disposable = entries.register(configuration, priority); this._onDidChange.fire(new LanguageConfigurationChangeEvent(languageId)); - return toDisposable(() => { + return markAsSingleton(toDisposable(() => { disposable.dispose(); this._onDidChange.fire(new LanguageConfigurationChangeEvent(languageId)); - }); + })); } public getLanguageConfiguration(languageId: string): ResolvedLanguageConfiguration | null { diff --git a/src/vs/editor/contrib/codelens/browser/codeLensCache.ts b/src/vs/editor/contrib/codelens/browser/codeLensCache.ts index 5f479695091d1..6dcde99c36995 100644 --- a/src/vs/editor/contrib/codelens/browser/codeLensCache.ts +++ b/src/vs/editor/contrib/codelens/browser/codeLensCache.ts @@ -77,7 +77,7 @@ export class CodeLensCache implements ICodeLensCache { }; }); const copyModel = new CodeLensModel(); - copyModel.add({ lenses: copyItems, dispose: () => { } }, this._fakeProvider); + copyModel.add({ lenses: copyItems }, this._fakeProvider); const item = new CacheItem(model.getLineCount(), copyModel); this._cache.set(model.uri.toString(), item); diff --git a/src/vs/editor/contrib/codelens/browser/codelens.ts b/src/vs/editor/contrib/codelens/browser/codelens.ts index 0a777339b04e8..be24cae08b018 100644 --- a/src/vs/editor/contrib/codelens/browser/codelens.ts +++ b/src/vs/editor/contrib/codelens/browser/codelens.ts @@ -5,7 +5,7 @@ import { CancellationToken } from '../../../../base/common/cancellation.js'; import { illegalArgument, onUnexpectedExternalError } from '../../../../base/common/errors.js'; -import { DisposableStore } from '../../../../base/common/lifecycle.js'; +import { DisposableStore, isDisposable } from '../../../../base/common/lifecycle.js'; import { assertType } from '../../../../base/common/types.js'; import { URI } from '../../../../base/common/uri.js'; import { ITextModel } from '../../../common/model.js'; @@ -24,18 +24,21 @@ export class CodeLensModel { lenses: CodeLensItem[] = []; - private readonly _disposables = new DisposableStore(); + private _store: DisposableStore | undefined; dispose(): void { - this._disposables.dispose(); + this._store?.dispose(); } get isDisposed(): boolean { - return this._disposables.isDisposed; + return this._store?.isDisposed ?? false; } add(list: CodeLensList, provider: CodeLensProvider): void { - this._disposables.add(list); + if (isDisposable(list)) { + this._store ??= new DisposableStore(); + this._store.add(list); + } for (const symbol of list.lenses) { this.lenses.push({ symbol, provider }); } diff --git a/src/vs/editor/contrib/hover/browser/contentHoverRendered.ts b/src/vs/editor/contrib/hover/browser/contentHoverRendered.ts index 81ccfcbc60b22..a80bdb7966fb0 100644 --- a/src/vs/editor/contrib/hover/browser/contentHoverRendered.ts +++ b/src/vs/editor/contrib/hover/browser/contentHoverRendered.ts @@ -273,6 +273,7 @@ class RenderedContentHoverParts extends Disposable { ...hoverContext }; const disposables = new DisposableStore(); + disposables.add(statusBar); for (const participant of participants) { const renderedHoverParts = this._renderHoverPartsForParticipant(hoverParts, participant, hoverRenderingContext); disposables.add(renderedHoverParts); @@ -294,7 +295,7 @@ class RenderedContentHoverParts extends Disposable { actions: renderedStatusBar.actions, }); } - return toDisposable(() => { disposables.dispose(); }); + return disposables; } private _renderHoverPartsForParticipant(hoverParts: IHoverPart[], participant: IEditorHoverParticipant, hoverRenderingContext: IEditorHoverRenderContext): IRenderedHoverParts { diff --git a/src/vs/editor/contrib/links/browser/getLinks.ts b/src/vs/editor/contrib/links/browser/getLinks.ts index cd2e19c756e06..be8a31af119bf 100644 --- a/src/vs/editor/contrib/links/browser/getLinks.ts +++ b/src/vs/editor/contrib/links/browser/getLinks.ts @@ -70,6 +70,8 @@ export class Link implements ILink { export class LinksList { + static readonly Empty = new LinksList([]); + readonly links: Link[]; private readonly _disposables = new DisposableStore(); @@ -137,27 +139,31 @@ export class LinksList { } -export function getLinks(providers: LanguageFeatureRegistry, model: ITextModel, token: CancellationToken): Promise { - +export async function getLinks(providers: LanguageFeatureRegistry, model: ITextModel, token: CancellationToken): Promise { const lists: [ILinksList, LinkProvider][] = []; // ask all providers for links in parallel - const promises = providers.ordered(model).reverse().map((provider, i) => { - return Promise.resolve(provider.provideLinks(model, token)).then(result => { + const promises = providers.ordered(model).reverse().map(async (provider, i) => { + try { + const result = await provider.provideLinks(model, token); if (result) { lists[i] = [result, provider]; } - }, onUnexpectedExternalError); - }); - - return Promise.all(promises).then(() => { - const result = new LinksList(coalesce(lists)); - if (!token.isCancellationRequested) { - return result; + } catch (err) { + onUnexpectedExternalError(err); } - result.dispose(); - return new LinksList([]); }); + + await Promise.all(promises); + + let res = new LinksList(coalesce(lists)); + + if (token.isCancellationRequested) { + res.dispose(); + res = LinksList.Empty; + } + + return res; } diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index bd27d47994110..5db429fff414e 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -8060,7 +8060,7 @@ declare namespace monaco.languages { export interface CodeLensList { lenses: CodeLens[]; - dispose(): void; + dispose?(): void; } export interface CodeLensProvider { diff --git a/src/vs/platform/actions/common/actions.ts b/src/vs/platform/actions/common/actions.ts index 2b784b5bf5e1e..9f1452f4b65cc 100644 --- a/src/vs/platform/actions/common/actions.ts +++ b/src/vs/platform/actions/common/actions.ts @@ -5,7 +5,7 @@ import { IAction, SubmenuAction } from '../../../base/common/actions.js'; import { Event, MicrotaskEmitter } from '../../../base/common/event.js'; -import { DisposableStore, dispose, IDisposable, toDisposable } from '../../../base/common/lifecycle.js'; +import { DisposableStore, dispose, IDisposable, markAsSingleton, toDisposable } from '../../../base/common/lifecycle.js'; import { LinkedList } from '../../../base/common/linkedList.js'; import { ThemeIcon } from '../../../base/common/themables.js'; import { ICommandAction, ICommandActionTitle, Icon, ILocalizedString } from '../../action/common/action.js'; @@ -397,11 +397,11 @@ export const MenuRegistry: IMenuRegistry = new class implements IMenuRegistry { this._commands.set(command.id, command); this._onDidChangeMenu.fire(MenuRegistryChangeEvent.for(MenuId.CommandPalette)); - return toDisposable(() => { + return markAsSingleton(toDisposable(() => { if (this._commands.delete(command.id)) { this._onDidChangeMenu.fire(MenuRegistryChangeEvent.for(MenuId.CommandPalette)); } - }); + })); } getCommand(id: string): ICommandAction | undefined { @@ -422,10 +422,10 @@ export const MenuRegistry: IMenuRegistry = new class implements IMenuRegistry { } const rm = list.push(item); this._onDidChangeMenu.fire(MenuRegistryChangeEvent.for(id)); - return toDisposable(() => { + return markAsSingleton(toDisposable(() => { rm(); this._onDidChangeMenu.fire(MenuRegistryChangeEvent.for(id)); - }); + })); } appendMenuItems(items: Iterable<{ id: MenuId; item: IMenuItem | ISubmenuItem }>): IDisposable { diff --git a/src/vs/platform/commands/common/commands.ts b/src/vs/platform/commands/common/commands.ts index 53e32c4842e1b..b6e7bc6fe501f 100644 --- a/src/vs/platform/commands/common/commands.ts +++ b/src/vs/platform/commands/common/commands.ts @@ -6,7 +6,7 @@ import { Emitter, Event } from '../../../base/common/event.js'; import { Iterable } from '../../../base/common/iterator.js'; import { IJSONSchema } from '../../../base/common/jsonSchema.js'; -import { IDisposable, toDisposable } from '../../../base/common/lifecycle.js'; +import { IDisposable, markAsSingleton, toDisposable } from '../../../base/common/lifecycle.js'; import { LinkedList } from '../../../base/common/linkedList.js'; import { TypeConstraint, validateConstraints } from '../../../base/common/types.js'; import { ILocalizedString } from '../../action/common/action.js'; @@ -121,7 +121,7 @@ export const CommandsRegistry: ICommandRegistry = new class implements ICommandR // tell the world about this command this._onDidRegisterCommand.fire(id); - return ret; + return markAsSingleton(ret); } registerCommandAlias(oldId: string, newId: string): IDisposable { diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsList.ts b/src/vs/workbench/contrib/extensions/browser/extensionsList.ts index 2afa3e73bbf63..7293bfef2b0a1 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsList.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsList.ts @@ -114,7 +114,7 @@ export class Renderer implements IPagedRenderer { focusOnlyEnabledItems: true }); actionbar.setFocusable(false); - actionbar.onDidRun(({ error }) => error && this.notificationService.error(error)); + const actionBarListener = actionbar.onDidRun(({ error }) => error && this.notificationService.error(error)); const extensionStatusIconAction = this.instantiationService.createInstance(ExtensionStatusAction); const actions = [ @@ -150,7 +150,7 @@ export class Renderer implements IPagedRenderer { const extensionContainers: ExtensionContainers = this.instantiationService.createInstance(ExtensionContainers, [...actions, ...widgets]); actionbar.push(actions, { icon: true, label: true }); - const disposable = combinedDisposable(...actions, ...widgets, actionbar, extensionContainers); + const disposable = combinedDisposable(...actions, ...widgets, actionbar, actionBarListener, extensionContainers); return { root, element, icon, name, installCount, ratings, description, publisherDisplayName, disposables: [disposable], actionbar, diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index 8a05bb6c06f7e..a786b73aab1a5 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -21,7 +21,7 @@ import { IContextKeyService, IContextKey, ContextKeyExpr, RawContextKey } from ' import { ICommandService } from '../../../../platform/commands/common/commands.js'; import { IKeybindingService } from '../../../../platform/keybinding/common/keybinding.js'; import { MenuItemAction, IMenuService, registerAction2, MenuId, IAction2Options, MenuRegistry, Action2, IMenu } from '../../../../platform/actions/common/actions.js'; -import { IAction, ActionRunner, Action, Separator, IActionRunner } from '../../../../base/common/actions.js'; +import { IAction, ActionRunner, Action, Separator, IActionRunner, toAction } from '../../../../base/common/actions.js'; import { ActionBar, IActionViewItemProvider } from '../../../../base/browser/ui/actionbar/actionbar.js'; import { IThemeService, IFileIconTheme } from '../../../../platform/theme/common/themeService.js'; import { isSCMResource, isSCMResourceGroup, isSCMRepository, isSCMInput, collectContextMenuActions, getActionViewItemProvider, isSCMActionButton, isSCMViewService, isSCMResourceNode, connectPrimaryMenu } from './util.js'; @@ -2988,7 +2988,14 @@ export class SCMActionButton implements IDisposable { for (let index = 0; index < button.secondaryCommands.length; index++) { const commands = button.secondaryCommands[index]; for (const command of commands) { - actions.push(new Action(command.id, command.title, undefined, true, async () => await this.executeCommand(command.id, ...(command.arguments || [])))); + actions.push(toAction({ + id: command.id, + label: command.title, + enabled: true, + run: async () => { + await this.executeCommand(command.id, ...(command.arguments || [])); + } + })); } if (commands.length) { actions.push(new Separator()); diff --git a/src/vs/workbench/services/authentication/browser/authenticationUsageService.ts b/src/vs/workbench/services/authentication/browser/authenticationUsageService.ts index 514e1ce72da75..08f8436fdf793 100644 --- a/src/vs/workbench/services/authentication/browser/authenticationUsageService.ts +++ b/src/vs/workbench/services/authentication/browser/authenticationUsageService.ts @@ -81,11 +81,11 @@ export class AuthenticationUsageService extends Disposable implements IAuthentic } } - this._authenticationService.onDidRegisterAuthenticationProvider( + this._register(this._authenticationService.onDidRegisterAuthenticationProvider( provider => this._queue.queue( () => this._addExtensionsToCache(provider.id) ) - ); + )); } async initializeExtensionUsageCache(): Promise {