diff --git a/src/client/interpreter/contracts.ts b/src/client/interpreter/contracts.ts index b4b0e068aeaf..43f312db0328 100644 --- a/src/client/interpreter/contracts.ts +++ b/src/client/interpreter/contracts.ts @@ -88,6 +88,7 @@ export interface IInterpreterService { export const IInterpreterDisplay = Symbol('IInterpreterDisplay'); export interface IInterpreterDisplay { refresh(resource?: Uri): Promise; + registerVisibilityFilter(filter: IInterpreterStatusbarVisibilityFilter): void; } export const IShebangCodeLensProvider = Symbol('IShebangCodeLensProvider'); diff --git a/src/client/interpreter/display/index.ts b/src/client/interpreter/display/index.ts index ddad61daeeb9..c52e11509057 100644 --- a/src/client/interpreter/display/index.ts +++ b/src/client/interpreter/display/index.ts @@ -1,4 +1,4 @@ -import { inject, injectable, multiInject } from 'inversify'; +import { inject, injectable } from 'inversify'; import { Disposable, OutputChannel, StatusBarAlignment, StatusBarItem, Uri } from 'vscode'; import { IApplicationShell, IWorkspaceService } from '../../common/application/types'; import { STANDARD_OUTPUT_CHANNEL } from '../../common/constants'; @@ -15,17 +15,6 @@ import { IInterpreterStatusbarVisibilityFilter, } from '../contracts'; -/** - * Create this class as Inversify doesn't allow @multiinject if there are no registered items. - * i.e. we must always have one for @multiinject to work. - */ -@injectable() -export class AlwaysDisplayStatusBar implements IInterpreterStatusbarVisibilityFilter { - public get hidden(): boolean { - return false; - } -} - @injectable() export class InterpreterDisplay implements IInterpreterDisplay { private readonly statusBar: StatusBarItem; @@ -38,12 +27,9 @@ export class InterpreterDisplay implements IInterpreterDisplay { private readonly autoSelection: IInterpreterAutoSelectionService; private interpreterPath: string | undefined; private statusBarCanBeDisplayed?: boolean; + private visibilityFilters: IInterpreterStatusbarVisibilityFilter[] = []; - constructor( - @inject(IServiceContainer) private readonly serviceContainer: IServiceContainer, - @multiInject(IInterpreterStatusbarVisibilityFilter) - private readonly visibilityFilters: IInterpreterStatusbarVisibilityFilter[], - ) { + constructor(@inject(IServiceContainer) private readonly serviceContainer: IServiceContainer) { this.helper = serviceContainer.get(IInterpreterHelper); this.workspaceService = serviceContainer.get(IWorkspaceService); this.pathUtils = serviceContainer.get(IPathUtils); @@ -62,9 +48,6 @@ export class InterpreterDisplay implements IInterpreterDisplay { this, disposableRegistry, ); - this.visibilityFilters - .filter((item) => item.changed) - .forEach((item) => item.changed!(this.updateVisibility, this, disposableRegistry)); // NOSONAR } public async refresh(resource?: Uri) { // Use the workspace Uri if available @@ -77,6 +60,13 @@ export class InterpreterDisplay implements IInterpreterDisplay { } await this.updateDisplay(resource); } + public registerVisibilityFilter(filter: IInterpreterStatusbarVisibilityFilter) { + const disposableRegistry = this.serviceContainer.get(IDisposableRegistry); + this.visibilityFilters.push(filter); + if (filter.changed) { + filter.changed(this.updateVisibility, this, disposableRegistry); + } + } private onDidChangeInterpreterInformation(info: PythonEnvironment) { if (!this.currentlySelectedInterpreterPath || this.currentlySelectedInterpreterPath === info.path) { this.updateDisplay(this.currentlySelectedWorkspaceFolder).ignoreErrors(); diff --git a/src/client/interpreter/serviceRegistry.ts b/src/client/interpreter/serviceRegistry.ts index 98d7b2851daa..159e744a44f8 100644 --- a/src/client/interpreter/serviceRegistry.ts +++ b/src/client/interpreter/serviceRegistry.ts @@ -47,11 +47,10 @@ import { IInterpreterHelper, IInterpreterLocatorProgressHandler, IInterpreterService, - IInterpreterStatusbarVisibilityFilter, IInterpreterVersionService, IShebangCodeLensProvider, } from './contracts'; -import { AlwaysDisplayStatusBar, InterpreterDisplay } from './display'; +import { InterpreterDisplay } from './display'; import { InterpreterSelectionTip } from './display/interpreterSelectionTip'; import { InterpreterLocatorProgressStatubarHandler } from './display/progressDisplay'; import { ShebangCodeLensProvider } from './display/shebangCodeLensProvider'; @@ -164,10 +163,6 @@ export function registerInterpreterTypes(serviceManager: IServiceManager) { IExtensionSingleActivationService, PreWarmActivatedEnvironmentVariables, ); - serviceManager.addSingleton( - IInterpreterStatusbarVisibilityFilter, - AlwaysDisplayStatusBar, - ); } export function registerTypes(serviceManager: IServiceManager) { diff --git a/src/client/jupyter/jupyterIntegration.ts b/src/client/jupyter/jupyterIntegration.ts index 18e1016c2590..0d5c0e595391 100644 --- a/src/client/jupyter/jupyterIntegration.ts +++ b/src/client/jupyter/jupyterIntegration.ts @@ -24,7 +24,11 @@ import { isResource } from '../common/utils/misc'; import { getDebugpyPackagePath } from '../debugger/extension/adapter/remoteLaunchers'; import { IEnvironmentActivationService } from '../interpreter/activation/types'; import { IInterpreterQuickPickItem, IInterpreterSelector } from '../interpreter/configuration/types'; -import { IInterpreterService } from '../interpreter/contracts'; +import { + IInterpreterDisplay, + IInterpreterService, + IInterpreterStatusbarVisibilityFilter, +} from '../interpreter/contracts'; import { IWindowsStoreInterpreter } from '../interpreter/locators/types'; import { WindowsStoreInterpreter } from '../pythonEnvironments/discovery/locators/services/windowsStoreInterpreter'; import { PythonEnvironment } from '../pythonEnvironments/info'; @@ -109,6 +113,10 @@ type PythonApiForJupyterExtension = { * @param resource file that determines which connection to return */ getLanguageServer(resource?: InterpreterUri): Promise; + /** + * Registers a visibility filter for the interpreter status bar. + */ + registerInterpreterStatusFilter(filter: IInterpreterStatusbarVisibilityFilter): void; }; export type JupyterExtensionApi = { @@ -143,6 +151,7 @@ export class JupyterExtensionIntegration { @inject(IEnvironmentActivationService) private readonly envActivation: IEnvironmentActivationService, @inject(ILanguageServerCache) private readonly languageServerCache: ILanguageServerCache, @inject(IMemento) @named(GLOBAL_MEMENTO) private globalState: Memento, + @inject(IInterpreterDisplay) private interpreterDisplay: IInterpreterDisplay, ) {} public registerApi(jupyterExtensionApi: JupyterExtensionApi): JupyterExtensionApi | undefined { @@ -185,6 +194,9 @@ export class JupyterExtensionIntegration { } return undefined; }, + registerInterpreterStatusFilter: this.interpreterDisplay.registerVisibilityFilter.bind( + this.interpreterDisplay, + ), }); return undefined; } diff --git a/src/test/interpreters/display.unit.test.ts b/src/test/interpreters/display.unit.test.ts index 6e2c7efbbfc3..16a4f32746ad 100644 --- a/src/test/interpreters/display.unit.test.ts +++ b/src/test/interpreters/display.unit.test.ts @@ -117,7 +117,8 @@ suite('Interpreters Display', () => { createInterpreterDisplay(); }); function createInterpreterDisplay(filters: IInterpreterStatusbarVisibilityFilter[] = []) { - interpreterDisplay = new InterpreterDisplay(serviceContainer.object, filters); + interpreterDisplay = new InterpreterDisplay(serviceContainer.object); + filters.forEach((f) => interpreterDisplay.registerVisibilityFilter(f)); } function setupWorkspaceFolder(resource: Uri, workspaceFolder?: Uri) { if (workspaceFolder) {