diff --git a/api/src/main.ts b/api/src/main.ts index 4f3b0e46..32cc9ff9 100644 --- a/api/src/main.ts +++ b/api/src/main.ts @@ -896,9 +896,8 @@ export interface PythonEnvironmentManagerRegistrationApi { * * @param manager Environment Manager implementation to register. * @param options Optional registration options. - * @param options.extensionId The extension ID of the calling extension. This is used as a fallback when - * automatic extension detection fails, such as during F5 debugging where the extension's file path - * does not contain its marketplace ID. If automatic detection succeeds, this value is ignored. + * @param options.extensionId The extension ID of the calling extension. When this is not specified, + * or when the specified extension cannot be found, the extension ID will be automatically detected. * @returns A disposable that can be used to unregister the environment manager. * @see {@link EnvironmentManager} */ @@ -1005,9 +1004,8 @@ export interface PythonPackageManagerRegistrationApi { * * @param manager Package Manager implementation to register. * @param options Optional registration options. - * @param options.extensionId The extension ID of the calling extension. This is used as a fallback when - * automatic extension detection fails, such as during F5 debugging where the extension's file path - * does not contain its marketplace ID. If automatic detection succeeds, this value is ignored. + * @param options.extensionId The extension ID of the calling extension. When this is not specified, + * or when the specified extension cannot be found, the extension ID will be automatically detected. * @returns A disposable that can be used to unregister the package manager. * @see {@link PackageManager} */ diff --git a/src/api.ts b/src/api.ts index 0286f017..b641ad3f 100644 --- a/src/api.ts +++ b/src/api.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import { +import type { Disposable, Event, FileChangeType, @@ -890,9 +890,8 @@ export interface PythonEnvironmentManagerRegistrationApi { * * @param manager Environment Manager implementation to register. * @param options Optional registration options. - * @param options.extensionId The extension ID of the calling extension. This is used as a fallback when - * automatic extension detection fails, such as during F5 debugging where the extension's file path - * does not contain its marketplace ID. If automatic detection succeeds, this value is ignored. + * @param options.extensionId The extension ID of the calling extension. When this is not specified, + * or when the specified extension cannot be found, the extension ID will be automatically detected. * @returns A disposable that can be used to unregister the environment manager. * @see {@link EnvironmentManager} */ @@ -999,9 +998,8 @@ export interface PythonPackageManagerRegistrationApi { * * @param manager Package Manager implementation to register. * @param options Optional registration options. - * @param options.extensionId The extension ID of the calling extension. This is used as a fallback when - * automatic extension detection fails, such as during F5 debugging where the extension's file path - * does not contain its marketplace ID. If automatic detection succeeds, this value is ignored. + * @param options.extensionId The extension ID of the calling extension. When this is not specified, + * or when the specified extension cannot be found, the extension ID will be automatically detected. * @returns A disposable that can be used to unregister the package manager. * @see {@link PackageManager} */ diff --git a/src/common/utils/frameUtils.ts b/src/common/utils/frameUtils.ts index 0eb45404..fd4fd236 100644 --- a/src/common/utils/frameUtils.ts +++ b/src/common/utils/frameUtils.ts @@ -22,15 +22,28 @@ function getFrameData(): FrameData[] { } function getPathFromFrame(frame: FrameData): string { - if (frame.filePath && frame.filePath.startsWith('file://')) { + if (frame.filePath?.startsWith('file://')) { return Uri.parse(frame.filePath).fsPath; } return frame.filePath; } -export function getCallingExtension(extensionIdHint?: string): string { +export function getCallingExtension(extensionId?: string): string { const pythonExts = [ENVS_EXTENSION_ID, PYTHON_EXTENSION_ID]; const extensions = allExtensions(); + + // Use the provided extensionId when available. + // Only accept if it matches an actually loaded extension so we can always return something. + if (extensionId) { + const hintExt = extensions.find((ext) => ext.id === extensionId); + if (hintExt) { + traceVerbose(`Using provided extensionId: ${extensionId}`); + return extensionId; + } + traceWarn(`Provided extensionId '${extensionId}' not found in loaded extensions, ignoring`); + } + + // Search the stack as a fallback when no extensionId is provided const otherExts = extensions.filter((ext) => !pythonExts.includes(ext.id)); const frames = getFrameData(); @@ -94,19 +107,6 @@ export function getCallingExtension(extensionIdHint?: string): string { } } - // Use the provided extensionId hint as a fallback (e.g., during F5 debugging where - // stack-based detection fails because the file path doesn't contain the extension ID). - // Only accept the hint if it matches an actually loaded extension for safety. - if (extensionIdHint) { - const hintExt = extensions.find((ext) => ext.id === extensionIdHint); - if (hintExt) { - traceVerbose(`Using provided extensionId hint: ${extensionIdHint}`); - extensionIdCache.set(cacheKey, extensionIdHint); - return extensionIdHint; - } - traceWarn(`Provided extensionId hint '${extensionIdHint}' not found in loaded extensions, ignoring`); - } - // Fallback - we're likely being called from Python extension or built-in managers traceWarn( `Could not determine calling extension from stack frames. ` +