Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 24 additions & 11 deletions packages/vscode-typescript/src/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
getExe,
getWorkspaceTsdkConfigValue,
getWorkspaceTsdkForPrompt,
pathHasTsserverJs,
readNativePreviewConfig,
resolveTsdkPath,
resolveTsdkPathToExe,
Expand Down Expand Up @@ -498,18 +499,30 @@ async function getStradaExtensionVersion(extensionId: string, pathToTypescript:
}
}

const workspacePackageSubpaths: readonly (readonly string[])[] = [
["node_modules", "typescript"],
["node_modules", "@typescript", "native-preview"],
];

async function findWorkspaceNativePreviewPackages(): Promise<DetectedVersion[]> {
const results: DetectedVersion[] = [];
for (const folder of vscode.workspace.workspaceFolders ?? []) {
const packagePath = vscode.Uri.joinPath(folder.uri, "node_modules", "@typescript", "native-preview");
const resolved = await resolveTsdkPathToExe(path.normalize(packagePath.fsPath));
if (!resolved) continue;
results.push({
folder,
version: resolved?.version ?? "unknown",
tsdkPath: path.normalize(packagePath.fsPath),
exePath: resolved?.path ?? "",
});
for (const candidate of workspacePackageSubpaths) {
const packagePath = vscode.Uri.joinPath(folder.uri, ...candidate);
const normalizedPath = path.normalize(packagePath.fsPath);
if (await pathHasTsserverJs(normalizedPath)) {
continue;
}
const resolved = await resolveTsdkPathToExe(normalizedPath);
if (!resolved) continue;
results.push({
folder,
version: resolved.version ?? "unknown",
tsdkPath: normalizedPath,
exePath: resolved.path ?? "",
});
break;
}
}
return results;
}
Expand Down Expand Up @@ -655,7 +668,7 @@ async function promptSelectVersion(context: vscode.ExtensionContext, client: Cli

/**
* If the workspace has a tsdk setting pending consent, or has
* `@typescript/typescript` installed in node_modules, prompt the user
* TypeScript 7 installed in node_modules, prompt the user
* to allow using it.
*/
export async function promptUseWorkspaceVersion(context: vscode.ExtensionContext): Promise<void> {
Expand Down Expand Up @@ -694,7 +707,7 @@ export async function promptUseWorkspaceVersion(context: vscode.ExtensionContext
}
}
else {
// No workspace tsdk config, but check if native-preview is installed
// No workspace tsdk config, but check if TypeScript 7 is installed
// in the workspace's node_modules.
const workspaceVersions = await findWorkspaceNativePreviewPackages();
if (workspaceVersions.length === 0) return;
Expand Down
2 changes: 1 addition & 1 deletion packages/vscode-typescript/src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ async function getTsdkCandidates(options?: { nativeOnly?: boolean; filter?: (can
return candidates.filter(options?.filter ?? (() => true)).sort(compareExplicitConfigValues);
}

async function pathHasTsserverJs(tsdkPath: string): Promise<boolean> {
export async function pathHasTsserverJs(tsdkPath: string): Promise<boolean> {
const resolved = workspaceResolve(tsdkPath);
for (const candidate of [vscode.Uri.joinPath(resolved, "tsserver.js"), vscode.Uri.joinPath(resolved, "lib", "tsserver.js")]) {
try {
Expand Down
15 changes: 11 additions & 4 deletions packages/vscode-typescript/test/tsdkPackage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,16 @@ import test, { describe } from "node:test";
import { resolvePackageExecutable } from "../src/tsdkPackage";

const platformPackage = `typescript-${process.platform}-${process.arch}`;
const nativePlatformPackage = `native-preview-${process.platform}-${process.arch}`;
const exeSuffix = process.platform === "win32" ? ".exe" : "";
const exeName = `tsc${exeSuffix}`;
const nativeExeName = `tsgo${exeSuffix}`;

function createPackage(root: string, relativePath: string): string {
function createPackage(root: string, relativePath: string, packageJson: object = {}): string {
const packagePath = path.join(root, relativePath);
fs.mkdirSync(packagePath, { recursive: true });
const packageJsonPath = path.join(packagePath, "package.json");
fs.writeFileSync(packageJsonPath, "{}");
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, undefined, 2));
return packageJsonPath;
}

Expand Down Expand Up @@ -75,14 +76,20 @@ describe("tsdk package resolution", { concurrency: true }, () => {
platformPath: `node_modules/@typescript/${platformPackage}`,
});

const nativePlatformPackage = `native-preview-${process.platform}-${process.arch}`;
testResolution("resolves the native-preview package", {
testResolution("resolves the @typescript/typescript native-preview package", {
packagePath: "node_modules/@typescript/typescript",
platformPath: `node_modules/@typescript/${nativePlatformPackage}`,
platformPackage: nativePlatformPackage,
exeName: nativeExeName,
});

testResolution("resolves the @typescript/native-preview package", {
packagePath: "node_modules/@typescript/native-preview",
platformPath: `node_modules/@typescript/${nativePlatformPackage}`,
platformPackage: nativePlatformPackage,
exeName: nativeExeName,
});
Comment on lines +86 to +91

testResolution("resolves a non-hoisted platform package", {
packagePath: "node_modules/@typescript/native",
platformPath: `node_modules/@typescript/native/node_modules/@typescript/${platformPackage}`,
Expand Down
Loading