diff --git a/_extension/src/session.ts b/_extension/src/session.ts index 6bb76a1cf03..11b02bde953 100644 --- a/_extension/src/session.ts +++ b/_extension/src/session.ts @@ -349,19 +349,31 @@ interface DetectedVersion { label: string; version: string; tsdkPath: string; + relativeTsdkPath: string; exePath: string; } async function findWorkspaceNativePreviewPackages(): Promise { const results: DetectedVersion[] = []; - for (const folder of vscode.workspace.workspaceFolders ?? []) { - const packagePath = vscode.Uri.joinPath(folder.uri, "node_modules", "@typescript", "native-preview"); + const folders = vscode.workspace.workspaceFolders ?? []; + const relativeWorkspacePath = "node_modules/@typescript/native-preview"; + const pathSegments = relativeWorkspacePath.split("/"); + for (let i = 0; i < folders.length; i++) { + const folder = folders[i]; + const packagePath = vscode.Uri.joinPath(folder.uri, ...pathSegments); const resolved = await resolveTsdkPathToExe(path.normalize(packagePath.fsPath)); if (!resolved) continue; + // Use a relative path only for the first workspace folder since + // workspaceResolve anchors relative paths there. For other folders, + // fall back to the absolute path so the setting resolves correctly. + const relativeTsdkPath = i === 0 + ? `./${relativeWorkspacePath}` + : path.normalize(packagePath.fsPath); results.push({ label: folder.name, version: resolved?.version ?? "unknown", tsdkPath: path.normalize(packagePath.fsPath), + relativeTsdkPath, exePath: resolved?.path ?? "", }); } @@ -383,7 +395,9 @@ async function promptSelectVersion(context: vscode.ExtensionContext, client: Cli detail: builtinExe.path, run: async () => { await context.workspaceState.update(useWorkspaceTsdkStorageKey, false); - await config.update("tsdk", undefined, vscode.ConfigurationTarget.Workspace); + // Suppress the workspace-version prompt so it doesn't re-fire + // after the user explicitly chose bundled. + await context.workspaceState.update("typescript.native-preview.suppressPromptWorkspaceTsdk", true); outputChannel.appendLine("Switched to bundled tsgo version."); }, }); @@ -391,14 +405,15 @@ async function promptSelectVersion(context: vscode.ExtensionContext, client: Cli // Workspace versions if (vscode.workspace.isTrusted) { for (const wsVersion of workspaceVersions) { - const isActive = currentExePath === wsVersion.tsdkPath; + const isActive = currentExePath === wsVersion.exePath; items.push({ label: (isActive ? "• " : "") + "Use Workspace Version", description: wsVersion.version, - detail: wsVersion.tsdkPath, + detail: wsVersion.relativeTsdkPath, run: async () => { await context.workspaceState.update(useWorkspaceTsdkStorageKey, true); - await config.update("tsdk", wsVersion.tsdkPath, vscode.ConfigurationTarget.Workspace); + await context.workspaceState.update("typescript.native-preview.suppressPromptWorkspaceTsdk", false); + await config.update("tsdk", wsVersion.relativeTsdkPath, vscode.ConfigurationTarget.Workspace); outputChannel.appendLine(`Switched to workspace tsgo version (${wsVersion.version}).`); }, }); @@ -473,6 +488,7 @@ export async function promptUseWorkspaceVersion(context: vscode.ExtensionContext const workspaceVersions = await findWorkspaceNativePreviewPackages(); if (workspaceVersions.length === 0) return; + const config = vscode.workspace.getConfiguration("typescript.native-preview"); const wsVersion = workspaceVersions[0]; const allow = "Allow"; const dismiss = "Dismiss"; @@ -488,8 +504,14 @@ export async function promptUseWorkspaceVersion(context: vscode.ExtensionContext if (result === allow) { if (!vscode.workspace.isTrusted) return; await context.workspaceState.update(useWorkspaceTsdkStorageKey, true); - const config = vscode.workspace.getConfiguration("typescript.native-preview"); - await config.update("tsdk", wsVersion.tsdkPath, vscode.ConfigurationTarget.Workspace); + // Only write tsdk if it isn't already pointing at the workspace install, + // so we don't overwrite a committed relative path with a new value. + const currentTsdk = config.get("tsdk"); + const resolvedCurrent = currentTsdk ? await resolveTsdkPathToExe(currentTsdk) : undefined; + const alreadyResolved = resolvedCurrent && workspaceVersions.some(ws => ws.exePath === resolvedCurrent.path); + if (!alreadyResolved) { + await config.update("tsdk", wsVersion.relativeTsdkPath, vscode.ConfigurationTarget.Workspace); + } await vscode.commands.executeCommand("typescript.native-preview.restart"); } else if (result === suppress) {