Skip to content

Commit ba96e78

Browse files
committed
Merge branch 'main' of https://github.com/microsoft/typescript-go into feat/2280
2 parents c0c1117 + baae7a1 commit ba96e78

735 files changed

Lines changed: 10491 additions & 2894 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.dprint.jsonc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@
5151
"internal/lsp/lsproto/_generate/*.json",
5252
"internal/lsp/lsproto/_generate/metaModelSchema.mts",
5353
// Needs to be LF to have a working shebang.
54-
"_packages/native-preview/bin/tsgo.js"
54+
"_packages/native-preview/bin/tsgo.js",
55+
"_packages/native-preview/vendor/**"
5556
],
5657
// Note: if adding new languages, make sure settings.template.json is updated too.
5758
// Also, if updating typescript, update the one in package.json.

Herebyfile.mjs

Lines changed: 87 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -310,21 +310,19 @@ export const generate = task({
310310

311311
/** @type {EnumDef[]} */
312312
const enumDefs = [
313-
// @typescript/api enums
314-
{ name: "SymbolFlags", goPrefix: "SymbolFlags", goFile: "internal/ast/symbolflags.go", outDir: "_packages/api/src/enums" },
315-
{ name: "TypeFlags", goPrefix: "TypeFlags", goFile: "internal/checker/types.go", outDir: "_packages/api/src/enums" },
316-
{ name: "ObjectFlags", goPrefix: "ObjectFlags", goFile: "internal/checker/types.go", outDir: "_packages/api/src/enums" },
317-
{ name: "SignatureFlags", goPrefix: "SignatureFlags", goFile: "internal/checker/types.go", outDir: "_packages/api/src/enums" },
318-
{ name: "SignatureKind", goPrefix: "SignatureKind", goFile: "internal/checker/types.go", outDir: "_packages/api/src/enums" },
319-
{ name: "ElementFlags", goPrefix: "ElementFlags", goFile: "internal/checker/types.go", outDir: "_packages/api/src/enums" },
320-
{ name: "TypePredicateKind", goPrefix: "TypePredicateKind", goFile: "internal/checker/types.go", outDir: "_packages/api/src/enums" },
321-
{ name: "DiagnosticCategory", goPrefix: "Category", goFile: "internal/diagnostics/diagnostics.go", outDir: "_packages/api/src/enums" },
322-
// @typescript/ast enums
323-
{ name: "SyntaxKind", goPrefix: "Kind", goFile: "internal/ast/kind_generated.go", outDir: "_packages/ast/src/enums" },
324-
{ name: "NodeFlags", goPrefix: "NodeFlags", goFile: "internal/ast/nodeflags.go", outDir: "_packages/ast/src/enums" },
325-
{ name: "OuterExpressionKinds", goPrefix: "OEK", goFile: "internal/ast/utilities.go", outDir: "_packages/ast/src/enums" },
326-
{ name: "ModifierFlags", goPrefix: "ModifierFlags", goFile: "internal/ast/modifierflags.go", outDir: "_packages/ast/src/enums" },
327-
{ name: "TokenFlags", goPrefix: "TokenFlags", goFile: "internal/ast/tokenflags.go", outDir: "_packages/ast/src/enums", constEnum: true },
313+
{ name: "SymbolFlags", goPrefix: "SymbolFlags", goFile: "internal/ast/symbolflags.go", outDir: "_packages/native-preview/src/enums" },
314+
{ name: "TypeFlags", goPrefix: "TypeFlags", goFile: "internal/checker/types.go", outDir: "_packages/native-preview/src/enums" },
315+
{ name: "ObjectFlags", goPrefix: "ObjectFlags", goFile: "internal/checker/types.go", outDir: "_packages/native-preview/src/enums" },
316+
{ name: "SignatureFlags", goPrefix: "SignatureFlags", goFile: "internal/checker/types.go", outDir: "_packages/native-preview/src/enums" },
317+
{ name: "SignatureKind", goPrefix: "SignatureKind", goFile: "internal/checker/types.go", outDir: "_packages/native-preview/src/enums" },
318+
{ name: "ElementFlags", goPrefix: "ElementFlags", goFile: "internal/checker/types.go", outDir: "_packages/native-preview/src/enums" },
319+
{ name: "TypePredicateKind", goPrefix: "TypePredicateKind", goFile: "internal/checker/types.go", outDir: "_packages/native-preview/src/enums" },
320+
{ name: "DiagnosticCategory", goPrefix: "Category", goFile: "internal/diagnostics/diagnostics.go", outDir: "_packages/native-preview/src/enums" },
321+
{ name: "SyntaxKind", goPrefix: "Kind", goFile: "internal/ast/kind_generated.go", outDir: "_packages/native-preview/src/enums" },
322+
{ name: "NodeFlags", goPrefix: "NodeFlags", goFile: "internal/ast/nodeflags.go", outDir: "_packages/native-preview/src/enums" },
323+
{ name: "OuterExpressionKinds", goPrefix: "OEK", goFile: "internal/ast/utilities.go", outDir: "_packages/native-preview/src/enums" },
324+
{ name: "ModifierFlags", goPrefix: "ModifierFlags", goFile: "internal/ast/modifierflags.go", outDir: "_packages/native-preview/src/enums" },
325+
{ name: "TokenFlags", goPrefix: "TokenFlags", goFile: "internal/ast/tokenflags.go", outDir: "_packages/native-preview/src/enums", constEnum: true },
328326
];
329327

330328
/**
@@ -706,7 +704,7 @@ async function runTestTools() {
706704
}
707705

708706
async function runTestAPI() {
709-
await $`npm run -w @typescript/api test`;
707+
await $`npm run -w @typescript/native-preview test:only`;
710708
}
711709

712710
export const testTools = task({
@@ -717,23 +715,23 @@ export const testTools = task({
717715

718716
export const buildAPI = task({
719717
name: "build:api",
720-
description: "Builds @typescript/api and @typescript/ast.",
718+
description: "Builds @typescript/native-preview JS API.",
721719
run: async () => {
722-
await $`npm run -w @typescript/api build`;
720+
await $`npm run -w @typescript/native-preview build`;
723721
},
724722
});
725723

726724
export const buildAPITests = task({
727725
name: "build:api:test",
728-
description: "Builds the @typescript/api tests.",
726+
description: "Builds the @typescript/native-preview JS API tests.",
729727
run: async () => {
730-
await $`npm run -w @typescript/api build:test`;
728+
await $`npm run -w @typescript/native-preview build:test`;
731729
},
732730
});
733731

734732
export const testAPI = task({
735733
name: "test:api",
736-
description: "Runs the @typescript/api tests.",
734+
description: "Runs the @typescript/native-preview JS API tests.",
737735
dependencies: [tsgo, buildAPITests],
738736
run: runTestAPI,
739737
});
@@ -1470,6 +1468,41 @@ const nativePreviewPlatforms = memoize(() => {
14701468
}
14711469
});
14721470

1471+
/**
1472+
* Recursively strips `@typescript/source` export conditions from a package.json object.
1473+
* Processes `exports` and `imports` fields, skipping past subpath keys (starting with "."
1474+
* or "#") and recursing into condition objects. After removal, simplifies objects that have
1475+
* only a single `default` key down to their bare value.
1476+
* @param {Record<string, any>} packageJson
1477+
*/
1478+
function stripSourceConditions(packageJson) {
1479+
for (const field of ["exports", "imports"]) {
1480+
if (packageJson[field] != null && typeof packageJson[field] === "object") {
1481+
packageJson[field] = stripConditionsFromValue(packageJson[field]);
1482+
}
1483+
}
1484+
}
1485+
1486+
/**
1487+
* @param {any} value
1488+
* @returns {any}
1489+
*/
1490+
function stripConditionsFromValue(value) {
1491+
if (value == null || typeof value !== "object") {
1492+
return value;
1493+
}
1494+
delete value["@typescript/source"];
1495+
for (const key of Object.keys(value)) {
1496+
value[key] = stripConditionsFromValue(value[key]);
1497+
}
1498+
// Simplify: if only "default" remains, collapse to its value.
1499+
const keys = Object.keys(value);
1500+
if (keys.length === 1 && keys[0] === "default") {
1501+
return value["default"];
1502+
}
1503+
return value;
1504+
}
1505+
14731506
export const buildNativePreviewPackages = task({
14741507
name: "native-preview:build-packages",
14751508
hiddenFromTaskList: true,
@@ -1486,7 +1519,7 @@ async function runBuildNativePreviewPackages() {
14861519
const inputPackageJson = JSON.parse(fs.readFileSync(path.join(inputDir, "package.json"), "utf8"));
14871520
inputPackageJson.version = getVersion();
14881521
delete inputPackageJson.private;
1489-
delete inputPackageJson.engines;
1522+
stripSourceConditions(inputPackageJson);
14901523

14911524
const { stdout: gitHead } = await $pipe`git rev-parse HEAD`;
14921525
inputPackageJson.gitHead = gitHead;
@@ -1500,19 +1533,50 @@ async function runBuildNativePreviewPackages() {
15001533

15011534
await fs.promises.mkdir(mainPackageDir, { recursive: true });
15021535

1503-
await cpWithoutNodeModulesOrTsconfig(inputDir, mainPackageDir);
1536+
// Copy package contents excluding node_modules and dist (dist is copied separately after build).
1537+
// The package.json "files" field controls what npm pack actually includes.
1538+
await cpRecursive(inputDir, mainPackageDir, p => !p.endsWith("/node_modules") && !p.includes("/dist"));
15041539

15051540
await fs.promises.writeFile(path.join(mainPackageDir, "package.json"), JSON.stringify(mainPackage, undefined, 4));
15061541
await fs.promises.copyFile("LICENSE", path.join(mainPackageDir, "LICENSE"));
15071542
// No NOTICE.txt here; does not ship the binary or libs. If this changes, we should add it.
15081543

1544+
// Build JS API and copy dist into the package.
1545+
await $`npm run -w @typescript/native-preview build`;
1546+
await cpRecursive(path.join(inputDir, "dist"), path.join(mainPackageDir, "dist"));
1547+
1548+
// Validate that .d.ts files contain no external imports (all imports must start with "." or "#").
1549+
const dtsFiles = await glob(`${mainPackageDir}/dist/**/*.d.ts`);
1550+
const importErrors = [];
1551+
for (const dtsFile of dtsFiles) {
1552+
const content = await fs.promises.readFile(dtsFile, "utf-8");
1553+
const relPath = path.relative(mainPackageDir, dtsFile);
1554+
for (const [i, line] of content.split("\n").entries()) {
1555+
// Match: import ... from "specifier" / export ... from "specifier"
1556+
const fromMatch = line.match(/(?:import|export)\s.*?\sfrom\s+["']([^"']+)["']/);
1557+
if (fromMatch && !fromMatch[1].startsWith(".") && !fromMatch[1].startsWith("#")) {
1558+
importErrors.push(`${relPath}:${i + 1}: external import declaration "${fromMatch[1]}"`);
1559+
}
1560+
// Match: import("specifier")
1561+
for (const m of line.matchAll(/import\(["']([^"']+)["']\)/g)) {
1562+
if (!m[1].startsWith(".") && !m[1].startsWith("#")) {
1563+
importErrors.push(`${relPath}:${i + 1}: external dynamic import "${m[1]}"`);
1564+
}
1565+
}
1566+
}
1567+
}
1568+
if (importErrors.length) {
1569+
throw new Error(`Found external imports in .d.ts files:\n${importErrors.map(e => " " + e).join("\n")}`);
1570+
}
1571+
15091572
const extraFlags = getReleaseBuildFlags(options.setPrerelease ? getVersion() : undefined);
15101573

15111574
const platformBuilders = platforms.map(({ npmDir, npmPackageName, nodeOs, nodeArch, goos, goarch }) => async () => {
15121575
const packageJson = {
15131576
...inputPackageJson,
15141577
bin: undefined,
15151578
imports: undefined,
1579+
dependencies: undefined,
15161580
name: npmPackageName,
15171581
os: [nodeOs],
15181582
cpu: [nodeArch],

_extension/package.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,25 @@
6868
"experimental"
6969
]
7070
},
71+
"typescript.native-preview.additionalTsdkLocations": {
72+
"type": "array",
73+
"items": {
74+
"type": "string"
75+
},
76+
"default": [],
77+
"description": "Additional paths to tsgo binary directories or @typescript/native-preview packages that should appear in the version selector.",
78+
"tags": [
79+
"experimental"
80+
]
81+
},
82+
"typescript.native-preview.showDebugInfo": {
83+
"type": "boolean",
84+
"default": false,
85+
"description": "Show debug information (PID, executable path) in the server menu.",
86+
"tags": [
87+
"experimental"
88+
]
89+
},
7190
"typescript.native-preview.goMemLimit": {
7291
"type": "string",
7392
"description": "Set GOMEMLIMIT for the language server (e.g., '2048MiB', '4GiB'). See https://pkg.go.dev/runtime#hdr-Environment_Variables for more information.",

_extension/src/client.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ export class Client implements vscode.Disposable {
8080
sendNotification: sendNotificationMiddleware,
8181
provideHover: () => undefined,
8282
},
83+
diagnosticCollectionName: "typescript",
8384
diagnosticPullOptions: {
8485
onChange: true,
8586
onSave: true,
@@ -248,6 +249,10 @@ export class Client implements vscode.Disposable {
248249
return this.exe;
249250
}
250251

252+
get serverPid(): number | undefined {
253+
return (this.client as any)?._serverProcess?.pid;
254+
}
255+
251256
/**
252257
* Initialize an API session and return the socket path for connecting.
253258
* This allows other extensions to get a direct connection to the API server.

_extension/src/extension.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ import {
1212
} from "./util";
1313

1414
import { TelemetryReporter as VSCodeTelemetryReporter } from "@vscode/extension-telemetry";
15-
import { SessionManager } from "./session";
15+
import {
16+
promptUseWorkspaceVersion,
17+
SessionManager,
18+
} from "./session";
1619
import { createTelemetryReporter } from "./telemetryReporting";
1720

1821
export interface ExtensionAPI {
@@ -111,6 +114,11 @@ export async function activate(context: vscode.ExtensionContext): Promise<Extens
111114

112115
await sessionManager.start(context);
113116

117+
// Prompt user to use workspace version if one is detected and they haven't opted in yet.
118+
promptUseWorkspaceVersion(context).catch(err => {
119+
output.appendLine(`Error prompting to use workspace version: ${err}`);
120+
});
121+
114122
function onLanguageServerInitialized(listener: () => void): vscode.Disposable {
115123
if (sessionManager.currentSession?.client.isInitialized) {
116124
listener();

0 commit comments

Comments
 (0)