diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 1712783850..21aabe935b 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -23,6 +23,7 @@ jobs:
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4.3.0
+ - uses: dtolnay/rust-toolchain@fcf085fcb4b4b8f63f96906cd713eb52181b5ea4 # stable
- uses: ./.github/actions/setup-go
with:
cache-name: build
@@ -36,6 +37,7 @@ jobs:
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4.3.0
+ - uses: dtolnay/rust-toolchain@fcf085fcb4b4b8f63f96906cd713eb52181b5ea4 # stable
- run: npm ci
@@ -90,6 +92,7 @@ jobs:
- uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4.3.0
with:
node-version: 'lts/*'
+ - uses: dtolnay/rust-toolchain@fcf085fcb4b4b8f63f96906cd713eb52181b5ea4 # stable
- uses: ./.github/actions/setup-go
with:
cache-name: test
@@ -103,7 +106,16 @@ jobs:
- name: Tests
id: test
- run: npx hereby test:all
+ run: npx hereby test
+
+ - name: Benchmarks
+ run: npx hereby test:benchmarks
+
+ - name: Tools Tests
+ run: npx hereby test:tools
+
+ - name: API Tests
+ run: npx hereby test:api
- run: git add .
@@ -150,6 +162,7 @@ jobs:
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4.3.0
+ - uses: dtolnay/rust-toolchain@fcf085fcb4b4b8f63f96906cd713eb52181b5ea4 # stable
- uses: ./.github/actions/setup-go
with:
cache-name: lint${{ (matrix.noembed && '-noembed') || ''}}
@@ -163,6 +176,7 @@ jobs:
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4.3.0
+ - uses: dtolnay/rust-toolchain@fcf085fcb4b4b8f63f96906cd713eb52181b5ea4 # stable
- uses: ./.github/actions/setup-go
with:
cache-name: format
@@ -179,6 +193,7 @@ jobs:
with:
submodules: true
- uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4.3.0
+ - uses: dtolnay/rust-toolchain@fcf085fcb4b4b8f63f96906cd713eb52181b5ea4 # stable
- uses: ./.github/actions/setup-go
with:
cache-name: generate
@@ -211,6 +226,7 @@ jobs:
with:
submodules: true
- uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4.3.0
+ - uses: dtolnay/rust-toolchain@fcf085fcb4b4b8f63f96906cd713eb52181b5ea4 # stable
- uses: ./.github/actions/setup-go
with:
cache-name: smoke
@@ -242,6 +258,7 @@ jobs:
with:
submodules: true
- uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4.3.0
+ - uses: dtolnay/rust-toolchain@fcf085fcb4b4b8f63f96906cd713eb52181b5ea4 # stable
- uses: ./.github/actions/setup-go
with:
cache-name: baselines
diff --git a/.github/workflows/merge-queue.yml b/.github/workflows/merge-queue.yml
index 22b64b7e4c..0e83867847 100644
--- a/.github/workflows/merge-queue.yml
+++ b/.github/workflows/merge-queue.yml
@@ -22,6 +22,7 @@ jobs:
- uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4.3.0
with:
node-version: 'lts/*'
+ - uses: dtolnay/rust-toolchain@fcf085fcb4b4b8f63f96906cd713eb52181b5ea4 # stable
- uses: ./.github/actions/setup-go
with:
cache-name: merge-queue-test
diff --git a/Herebyfile.mjs b/Herebyfile.mjs
index 592247f3ab..1be19e0c07 100644
--- a/Herebyfile.mjs
+++ b/Herebyfile.mjs
@@ -314,18 +314,37 @@ async function runTestTools() {
await $test({ cwd: path.join(__dirname, "_tools") })`${gotestsum("tools")} ./...`;
}
+async function runTestAPI() {
+ await $`npm run -w @typescript/api test`;
+}
+
export const testTools = task({
name: "test:tools",
run: runTestTools,
});
+export const buildAPITests = task({
+ name: "build:api:test",
+ run: async () => {
+ await $`npm run -w @typescript/api build:test`;
+ },
+});
+
+export const testAPI = task({
+ name: "test:api",
+ dependencies: [tsgo, buildAPITests],
+ run: runTestAPI,
+});
+
export const testAll = task({
name: "test:all",
+ dependencies: [tsgo, buildAPITests],
run: async () => {
// Prevent interleaving by running these directly instead of in parallel.
await runTests();
await runTestBenchmarks();
await runTestTools();
+ await runTestAPI();
},
});
diff --git a/README.md b/README.md
index adf4ca78fa..5b7f75b8af 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@ Interested developers can clone and run locally to try out things as they become
## How to Build and Run
-This repo uses [Go 1.24 or higher](https://go.dev/dl/), [Node.js with npm](https://nodejs.org/), and [`hereby`](https://www.npmjs.com/package/hereby).
+This repo uses [Go 1.24 or higher](https://go.dev/dl/), [Rust 1.85 or higher](https://www.rust-lang.org/tools/install), [Node.js with npm](https://nodejs.org/), and [`hereby`](https://www.npmjs.com/package/hereby).
For tests and code generation, this repo contains a git submodule to the main TypeScript repo pointing to the commit being ported.
When cloning, you'll want to clone with submodules:
diff --git a/_packages/api/package.json b/_packages/api/package.json
new file mode 100644
index 0000000000..1b8e2f2c80
--- /dev/null
+++ b/_packages/api/package.json
@@ -0,0 +1,51 @@
+{
+ "private": true,
+ "name": "@typescript/api",
+ "version": "1.0.0",
+ "type": "module",
+ "imports": {
+ "#symbolFlags": {
+ "@typescript/source": {
+ "types": "./src/symbolFlags.enum.ts",
+ "default": "./src/symbolFlags.ts"
+ },
+ "types": "./dist/symbolFlags.enum.d.ts",
+ "default": "./dist/symbolFlags.js"
+ },
+ "#typeFlags": {
+ "@typescript/source": {
+ "types": "./src/typeFlags.enum.ts",
+ "default": "./src/typeFlags.ts"
+ },
+ "types": "./dist/typeFlags.enum.d.ts",
+ "default": "./dist/typeFlags.js"
+ }
+ },
+ "exports": {
+ ".": {
+ "@typescript/source": "./src/api.ts",
+ "default": "./dist/api.js"
+ },
+ "./fs": {
+ "@typescript/source": "./src/fs.ts",
+ "default": "./dist/fs.js"
+ },
+ "./proto": {
+ "@typescript/source": "./src/proto.ts",
+ "default": "./dist/proto.js"
+ }
+ },
+ "scripts": {
+ "build": "tsc -b",
+ "build:test": "tsc -b test",
+ "bench": "node --experimental-strip-types --no-warnings --conditions @typescript/source test/api.bench.ts",
+ "test": "node --test --experimental-strip-types --no-warnings --conditions @typescript/source ./test/**/*.test.ts"
+ },
+ "devDependencies": {
+ "tinybench": "^3.1.1"
+ },
+ "dependencies": {
+ "@typescript/ast": "1.0.0",
+ "libsyncrpc": "github:microsoft/libsyncrpc#bb02d84"
+ }
+}
diff --git a/_packages/api/src/api.ts b/_packages/api/src/api.ts
new file mode 100644
index 0000000000..fbfc323917
--- /dev/null
+++ b/_packages/api/src/api.ts
@@ -0,0 +1,179 @@
+///
+import { SymbolFlags } from "#symbolFlags";
+import { TypeFlags } from "#typeFlags";
+import type {
+ Node,
+ SourceFile,
+} from "@typescript/ast";
+import { Client } from "./client.ts";
+import type { FileSystem } from "./fs.ts";
+import { RemoteSourceFile } from "./node.ts";
+import { ObjectRegistry } from "./objectRegistry.ts";
+import type {
+ ConfigResponse,
+ ProjectResponse,
+ SymbolResponse,
+ TypeResponse,
+} from "./proto.ts";
+
+export { SymbolFlags, TypeFlags };
+
+export interface APIOptions {
+ tsserverPath: string;
+ cwd?: string;
+ logFile?: string;
+ fs?: FileSystem;
+}
+
+export class API {
+ private client: Client;
+ private objectRegistry: ObjectRegistry;
+ constructor(options: APIOptions) {
+ this.client = new Client(options);
+ this.objectRegistry = new ObjectRegistry(this.client);
+ }
+
+ parseConfigFile(fileName: string): ConfigResponse {
+ return this.client.request("parseConfigFile", { fileName });
+ }
+
+ loadProject(configFileName: string): Project {
+ const data = this.client.request("loadProject", { configFileName });
+ return this.objectRegistry.getProject(data);
+ }
+
+ echo(message: string): string {
+ return this.client.echo(message);
+ }
+
+ echoBinary(message: Uint8Array): Uint8Array {
+ return this.client.echoBinary(message);
+ }
+
+ close(): void {
+ this.client.close();
+ }
+}
+
+export class DisposableObject {
+ private disposed: boolean = false;
+ protected objectRegistry: ObjectRegistry;
+ constructor(objectRegistry: ObjectRegistry) {
+ this.objectRegistry = objectRegistry;
+ }
+ [globalThis.Symbol.dispose](): void {
+ this.objectRegistry.release(this);
+ this.disposed = true;
+ }
+ dispose(): void {
+ this[globalThis.Symbol.dispose]();
+ }
+ isDisposed(): boolean {
+ return this.disposed;
+ }
+ ensureNotDisposed(): this {
+ if (this.disposed) {
+ throw new Error(`${this.constructor.name} is disposed`);
+ }
+ return this;
+ }
+}
+
+export class Project extends DisposableObject {
+ private decoder = new TextDecoder();
+ private client: Client;
+
+ id: string;
+ configFileName!: string;
+ compilerOptions!: Record;
+ rootFiles!: readonly string[];
+
+ constructor(client: Client, objectRegistry: ObjectRegistry, data: ProjectResponse) {
+ super(objectRegistry);
+ this.id = data.id;
+ this.client = client;
+ this.loadData(data);
+ }
+
+ loadData(data: ProjectResponse): void {
+ this.configFileName = data.configFileName;
+ this.compilerOptions = data.compilerOptions;
+ this.rootFiles = data.rootFiles;
+ }
+
+ reload(): void {
+ this.ensureNotDisposed();
+ this.loadData(this.client.request("loadProject", { configFileName: this.configFileName }));
+ }
+
+ getSourceFile(fileName: string): SourceFile | undefined {
+ this.ensureNotDisposed();
+ const data = this.client.requestBinary("getSourceFile", { project: this.id, fileName });
+ return data ? new RemoteSourceFile(data, this.decoder) as unknown as SourceFile : undefined;
+ }
+
+ getSymbolAtLocation(node: Node): Symbol | undefined;
+ getSymbolAtLocation(nodes: readonly Node[]): (Symbol | undefined)[];
+ getSymbolAtLocation(nodeOrNodes: Node | readonly Node[]): Symbol | (Symbol | undefined)[] | undefined {
+ this.ensureNotDisposed();
+ if (Array.isArray(nodeOrNodes)) {
+ const data = this.client.request("getSymbolsAtLocations", { project: this.id, locations: nodeOrNodes.map(node => node.id) });
+ return data.map((d: SymbolResponse | null) => d ? this.objectRegistry.getSymbol(d) : undefined);
+ }
+ const data = this.client.request("getSymbolAtLocation", { project: this.id, location: (nodeOrNodes as Node).id });
+ return data ? this.objectRegistry.getSymbol(data) : undefined;
+ }
+
+ getSymbolAtPosition(fileName: string, position: number): Symbol | undefined;
+ getSymbolAtPosition(fileName: string, positions: readonly number[]): (Symbol | undefined)[];
+ getSymbolAtPosition(fileName: string, positionOrPositions: number | readonly number[]): Symbol | (Symbol | undefined)[] | undefined {
+ this.ensureNotDisposed();
+ if (typeof positionOrPositions === "number") {
+ const data = this.client.request("getSymbolAtPosition", { project: this.id, fileName, position: positionOrPositions });
+ return data ? this.objectRegistry.getSymbol(data) : undefined;
+ }
+ const data = this.client.request("getSymbolsAtPositions", { project: this.id, fileName, positions: positionOrPositions });
+ return data.map((d: SymbolResponse | null) => d ? this.objectRegistry.getSymbol(d) : undefined);
+ }
+
+ getTypeOfSymbol(symbol: Symbol): Type | undefined;
+ getTypeOfSymbol(symbols: readonly Symbol[]): (Type | undefined)[];
+ getTypeOfSymbol(symbolOrSymbols: Symbol | readonly Symbol[]): Type | (Type | undefined)[] | undefined {
+ this.ensureNotDisposed();
+ if (Array.isArray(symbolOrSymbols)) {
+ const data = this.client.request("getTypesOfSymbols", { project: this.id, symbols: symbolOrSymbols.map(symbol => symbol.ensureNotDisposed().id) });
+ return data.map((d: TypeResponse | null) => d ? this.objectRegistry.getType(d) : undefined);
+ }
+ const data = this.client.request("getTypeOfSymbol", { project: this.id, symbol: (symbolOrSymbols as Symbol).ensureNotDisposed().id });
+ return data ? this.objectRegistry.getType(data) : undefined;
+ }
+}
+
+export class Symbol extends DisposableObject {
+ private client: Client;
+ id: string;
+ name: string;
+ flags: SymbolFlags;
+ checkFlags: number;
+
+ constructor(client: Client, objectRegistry: ObjectRegistry, data: SymbolResponse) {
+ super(objectRegistry);
+ this.client = client;
+ this.id = data.id;
+ this.name = data.name;
+ this.flags = data.flags;
+ this.checkFlags = data.checkFlags;
+ }
+}
+
+export class Type extends DisposableObject {
+ private client: Client;
+ id: string;
+ flags: TypeFlags;
+ constructor(client: Client, objectRegistry: ObjectRegistry, data: TypeResponse) {
+ super(objectRegistry);
+ this.client = client;
+ this.id = data.id;
+ this.flags = data.flags;
+ }
+}
diff --git a/_packages/api/src/client.ts b/_packages/api/src/client.ts
new file mode 100644
index 0000000000..c99d0945f4
--- /dev/null
+++ b/_packages/api/src/client.ts
@@ -0,0 +1,65 @@
+import { SyncRpcChannel } from "libsyncrpc";
+import type { FileSystem } from "./fs.ts";
+
+export interface ClientOptions {
+ tsserverPath: string;
+ cwd?: string;
+ logFile?: string;
+ fs?: FileSystem;
+}
+
+export class Client {
+ private channel: SyncRpcChannel;
+ private decoder = new TextDecoder();
+ private encoder = new TextEncoder();
+
+ constructor(options: ClientOptions) {
+ this.channel = new SyncRpcChannel(options.tsserverPath, [
+ "api",
+ "-cwd",
+ options.cwd ?? process.cwd(),
+ ]);
+
+ this.channel.requestSync(
+ "configure",
+ JSON.stringify({
+ logFile: options.logFile,
+ callbacks: Object.keys(options.fs ?? {}),
+ }),
+ );
+
+ if (options.fs) {
+ for (const [key, callback] of Object.entries(options.fs)) {
+ this.channel.registerCallback(key, (_, arg) => {
+ const result = callback(JSON.parse(arg));
+ return JSON.stringify(result) ?? "";
+ });
+ }
+ }
+ }
+
+ request(method: string, payload: any): any {
+ const encodedPayload = JSON.stringify(payload);
+ const result = this.channel.requestSync(method, encodedPayload);
+ if (result.length) {
+ const decodedResult = JSON.parse(result);
+ return decodedResult;
+ }
+ }
+
+ requestBinary(method: string, payload: any): Uint8Array {
+ return this.channel.requestBinarySync(method, this.encoder.encode(JSON.stringify(payload)));
+ }
+
+ echo(payload: string): string {
+ return this.channel.requestSync("echo", payload);
+ }
+
+ echoBinary(payload: Uint8Array): Uint8Array {
+ return this.channel.requestBinarySync("echo", payload);
+ }
+
+ close(): void {
+ this.channel.close();
+ }
+}
diff --git a/_packages/api/src/fs.ts b/_packages/api/src/fs.ts
new file mode 100644
index 0000000000..f84d35da82
--- /dev/null
+++ b/_packages/api/src/fs.ts
@@ -0,0 +1,142 @@
+import { getPathComponents } from "./path.ts";
+
+export interface FileSystemEntries {
+ files: string[];
+ directories: string[];
+}
+
+export interface FileSystem {
+ directoryExists?: (directoryName: string) => boolean | undefined;
+ fileExists?: (fileName: string) => boolean | undefined;
+ getAccessibleEntries?: (directoryName: string) => FileSystemEntries | undefined;
+ readFile?: (fileName: string) => string | null | undefined;
+ realpath?: (path: string) => string | undefined;
+}
+
+export function createVirtualFileSystem(files: Record): FileSystem {
+ interface VDirectory {
+ type: "directory";
+ children: Record;
+ }
+
+ interface VFile {
+ type: "file";
+ content: string;
+ }
+
+ type VNode = VDirectory | VFile;
+
+ const root: VDirectory = {
+ type: "directory",
+ children: {},
+ };
+
+ for (const [filePath, fileContent] of Object.entries(files)) {
+ createFile(filePath, fileContent);
+ }
+
+ return {
+ directoryExists,
+ fileExists,
+ getAccessibleEntries,
+ readFile,
+ realpath: path => path,
+ };
+
+ /**
+ * Traverse the tree from the root according to path segments.
+ * Returns the node if found, or null if any segment doesn't exist.
+ */
+ function getNodeFromPath(path: string): VNode | undefined {
+ if (!path || path === "/") {
+ return root;
+ }
+ const segments = getPathComponents(path).slice(1);
+ let current: VNode = root;
+
+ for (const segment of segments) {
+ if (current.type !== "directory") {
+ return undefined;
+ }
+ const child: VNode = current.children[segment];
+ if (!child) {
+ return undefined; // segment not found
+ }
+ current = child;
+ }
+
+ return current;
+ }
+
+ /**
+ * Ensure that the directory path (given by `segments`) exists,
+ * creating subdirectories as needed. Returns the final directory node.
+ */
+ function ensureDirectory(segments: string[]): VDirectory {
+ let current: VDirectory = root;
+ for (const segment of segments) {
+ if (!current.children[segment]) {
+ // Create a new directory node
+ current.children[segment] = { type: "directory", children: {} };
+ }
+ else if (current.children[segment].type !== "directory") {
+ // A file with the same name already exists
+ throw new Error(`Cannot create directory: a file already exists at "/${segments.join("/")}"`);
+ }
+ current = current.children[segment] as VDirectory;
+ }
+ return current;
+ }
+
+ /**
+ * Create (or overwrite) a file at the given path with provided content.
+ * Automatically creates parent directories if needed.
+ */
+ function createFile(path: string, content: string) {
+ const segments = getPathComponents(path).slice(1);
+ if (segments.length === 0) {
+ throw new Error(`Invalid file path: "${path}"`);
+ }
+ const filename = segments.pop()!;
+ const directorySegments = segments;
+ const dirNode = ensureDirectory(directorySegments);
+ dirNode.children[filename] = { type: "file", content };
+ }
+
+ function directoryExists(directoryName: string): boolean {
+ const node = getNodeFromPath(directoryName);
+ return !!node && node.type === "directory";
+ }
+
+ function fileExists(fileName: string): boolean {
+ const node = getNodeFromPath(fileName);
+ return !!node && node.type === "file";
+ }
+
+ function getAccessibleEntries(directoryName: string): FileSystemEntries | undefined {
+ const node = getNodeFromPath(directoryName);
+ if (!node || node.type !== "directory") {
+ // Not found or not a directory
+ return undefined;
+ }
+ const files: string[] = [];
+ const directories: string[] = [];
+ for (const [name, child] of Object.entries(node.children)) {
+ if (child.type === "file") {
+ files.push(name);
+ }
+ else {
+ directories.push(name);
+ }
+ }
+ return { files, directories };
+ }
+
+ function readFile(fileName: string): string | undefined {
+ const node = getNodeFromPath(fileName);
+ if (!node || node.type !== "file") {
+ return undefined; // doesn't exist or is not a file
+ }
+ return node.content;
+ }
+}
diff --git a/_packages/api/src/node.ts b/_packages/api/src/node.ts
new file mode 100644
index 0000000000..d906b3310b
--- /dev/null
+++ b/_packages/api/src/node.ts
@@ -0,0 +1,947 @@
+import {
+ type Node,
+ type NodeArray,
+ type SourceFile,
+ SyntaxKind,
+} from "@typescript/ast";
+
+declare module "@typescript/ast" {
+ export interface Node {
+ readonly id: string;
+ forEachChild(visitor: (node: Node) => T): T | undefined;
+ getSourceFile(): SourceFile;
+ }
+
+ export interface NodeArray {
+ at(index: number): T;
+ }
+}
+
+const popcount8 = [0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8];
+
+const childProperties: Readonly>> = {
+ [SyntaxKind.QualifiedName]: ["left", "right"],
+ [SyntaxKind.TypeParameter]: ["modifiers", "name", "constraint", "defaultType"],
+ [SyntaxKind.IfStatement]: ["expression", "thenStatement", "elseStatement"],
+ [SyntaxKind.DoStatement]: ["statement", "expression"],
+ [SyntaxKind.WhileStatement]: ["expression", "statement"],
+ [SyntaxKind.ForStatement]: ["initializer", "condition", "incrementor", "statement"],
+ [SyntaxKind.ForInStatement]: ["awaitModifier", "initializer", "expression", "statement"],
+ [SyntaxKind.ForOfStatement]: ["awaitModifier", "initializer", "expression", "statement"],
+ [SyntaxKind.WithStatement]: ["expression", "statement"],
+ [SyntaxKind.SwitchStatement]: ["expression", "caseBlock"],
+ [SyntaxKind.CaseClause]: ["expression", "statements"],
+ [SyntaxKind.DefaultClause]: ["expression", "statements"],
+ [SyntaxKind.TryStatement]: ["tryBlock", "catchClause", "finallyBlock"],
+ [SyntaxKind.CatchClause]: ["variableDeclaration", "block"],
+ [SyntaxKind.LabeledStatement]: ["label", "statement"],
+ [SyntaxKind.VariableStatement]: ["modifiers", "declarationList"],
+ [SyntaxKind.VariableDeclaration]: ["name", "exclamationToken", "type", "initializer"],
+ [SyntaxKind.Parameter]: ["modifiers", "dotDotDotToken", "name", "questionToken", "type", "initializer"],
+ [SyntaxKind.BindingElement]: ["dotDotDotToken", "propertyName", "name", "initializer"],
+ [SyntaxKind.FunctionDeclaration]: ["modifiers", "asteriskToken", "name", "typeParameters", "parameters", "type", "body"],
+ [SyntaxKind.InterfaceDeclaration]: ["modifiers", "name", "typeParameters", "heritageClauses", "members"],
+ [SyntaxKind.TypeAliasDeclaration]: ["modifiers", "name", "typeParameters", "type"],
+ [SyntaxKind.EnumMember]: ["name", "initializer"],
+ [SyntaxKind.EnumDeclaration]: ["modifiers", "name", "members"],
+ [SyntaxKind.ModuleDeclaration]: ["modifiers", "name", "body"],
+ [SyntaxKind.ImportEqualsDeclaration]: ["modifiers", "name", "moduleReference"],
+ [SyntaxKind.ImportDeclaration]: ["modifiers", "importClause", "moduleSpecifier", "attributes"],
+ [SyntaxKind.ImportSpecifier]: ["propertyName", "name"],
+ [SyntaxKind.ImportClause]: ["name", "namedBindings"],
+ [SyntaxKind.ExportAssignment]: ["modifiers", "expression"],
+ [SyntaxKind.NamespaceExportDeclaration]: ["modifiers", "name"],
+ [SyntaxKind.ExportDeclaration]: ["modifiers", "exportClause", "moduleSpecifier", "attributes"],
+ [SyntaxKind.ExportSpecifier]: ["propertyName", "name"],
+ [SyntaxKind.CallSignature]: ["typeParameters", "parameters", "type"],
+ [SyntaxKind.ConstructSignature]: ["typeParameters", "parameters", "type"],
+ [SyntaxKind.Constructor]: ["modifiers", "typeParameters", "parameters", "type", "body"],
+ [SyntaxKind.GetAccessor]: ["modifiers", "name", "typeParameters", "parameters", "type", "body"],
+ [SyntaxKind.SetAccessor]: ["modifiers", "name", "typeParameters", "parameters", "type", "body"],
+ [SyntaxKind.IndexSignature]: ["modifiers", "parameters", "type"],
+ [SyntaxKind.MethodSignature]: ["modifiers", "name", "postfixToken", "typeParameters", "parameters", "type"],
+ [SyntaxKind.MethodDeclaration]: ["modifiers", "asteriskToken", "name", "postfixToken", "typeParameters", "parameters", "type", "body"],
+ [SyntaxKind.PropertySignature]: ["modifiers", "name", "postfixToken", "type", "initializer"],
+ [SyntaxKind.PropertyDeclaration]: ["modifiers", "name", "postfixToken", "type", "initializer"],
+ [SyntaxKind.BinaryExpression]: ["left", "operatorToken", "right"],
+ [SyntaxKind.YieldExpression]: ["asteriskToken", "expression"],
+ [SyntaxKind.ArrowFunction]: ["modifiers", "typeParameters", "parameters", "type", "equalsGreaterThanToken", "body"],
+ [SyntaxKind.FunctionExpression]: ["modifiers", "asteriskToken", "name", "typeParameters", "parameters", "type", "body"],
+ [SyntaxKind.AsExpression]: ["expression", "type"],
+ [SyntaxKind.SatisfiesExpression]: ["expression", "type"],
+ [SyntaxKind.ConditionalExpression]: ["condition", "questionToken", "whenTrue", "colonToken", "whenFalse"],
+ [SyntaxKind.PropertyAccessExpression]: ["expression", "questionDotToken", "name"],
+ [SyntaxKind.ElementAccessExpression]: ["expression", "questionDotToken", "argumentExpression"],
+ [SyntaxKind.CallExpression]: ["expression", "questionDotToken", "typeArguments", "arguments"],
+ [SyntaxKind.NewExpression]: ["expression", "typeArguments", "arguments"],
+ [SyntaxKind.TemplateExpression]: ["head", "templateSpans"],
+ [SyntaxKind.TemplateSpan]: ["expression", "literal"],
+ [SyntaxKind.TaggedTemplateExpression]: ["tag", "questionDotToken", "typeArguments", "template"],
+ [SyntaxKind.PropertyAssignment]: ["modifiers", "name", "postfixToken", "initializer"],
+ [SyntaxKind.ShorthandPropertyAssignment]: ["modifiers", "name", "postfixToken", "equalsToken", "objectAssignmentInitializer"],
+ [SyntaxKind.TypeAssertionExpression]: ["type", "expression"],
+ [SyntaxKind.ConditionalType]: ["checkType", "extendsType", "trueType", "falseType"],
+ [SyntaxKind.IndexedAccessType]: ["objectType", "indexType"],
+ [SyntaxKind.TypeReference]: ["typeName", "typeArguments"],
+ [SyntaxKind.ExpressionWithTypeArguments]: ["expression", "typeArguments"],
+ [SyntaxKind.TypePredicate]: ["assertsModifier", "parameterName", "type"],
+ [SyntaxKind.ImportType]: ["argument", "attributes", "qualifier", "typeArguments"],
+ [SyntaxKind.ImportAttribute]: ["name", "value"],
+ [SyntaxKind.TypeQuery]: ["exprName", "typeArguments"],
+ [SyntaxKind.MappedType]: ["readonlyToken", "typeParameter", "nameType", "questionToken", "type", "members"],
+ [SyntaxKind.NamedTupleMember]: ["dotDotDotToken", "name", "questionToken", "type"],
+ [SyntaxKind.FunctionType]: ["typeParameters", "parameters", "type"],
+ [SyntaxKind.ConstructorType]: ["modifiers", "typeParameters", "parameters", "type"],
+ [SyntaxKind.TemplateLiteralType]: ["head", "templateSpans"],
+ [SyntaxKind.TemplateLiteralTypeSpan]: ["type", "literal"],
+ [SyntaxKind.JsxElement]: ["openingElement", "children", "closingElement"],
+ [SyntaxKind.JsxNamespacedName]: ["name", "namespace"],
+ [SyntaxKind.JsxOpeningElement]: ["tagName", "typeArguments", "attributes"],
+ [SyntaxKind.JsxSelfClosingElement]: ["tagName", "typeArguments", "attributes"],
+ [SyntaxKind.JsxFragment]: ["openingFragment", "children", "closingFragment"],
+ [SyntaxKind.JsxAttribute]: ["name", "initializer"],
+ [SyntaxKind.JsxExpression]: ["dotDotDotToken", "expression"],
+ [SyntaxKind.JSDoc]: ["comment", "tags"],
+ [SyntaxKind.JSDocTypeTag]: ["tagName", "typeExpression", "comment"],
+ [SyntaxKind.JSDocTag]: ["tagName", "comment"],
+ [SyntaxKind.JSDocTemplateTag]: ["tagName", "constraint", "typeParameters", "comment"],
+ [SyntaxKind.JSDocReturnTag]: ["tagName", "typeExpression", "comment"],
+ [SyntaxKind.JSDocPublicTag]: ["tagName", "comment"],
+ [SyntaxKind.JSDocPrivateTag]: ["tagName", "comment"],
+ [SyntaxKind.JSDocProtectedTag]: ["tagName", "comment"],
+ [SyntaxKind.JSDocReadonlyTag]: ["tagName", "comment"],
+ [SyntaxKind.JSDocOverrideTag]: ["tagName", "comment"],
+ [SyntaxKind.JSDocDeprecatedTag]: ["tagName", "comment"],
+ [SyntaxKind.JSDocSeeTag]: ["tagName", "nameExpression", "comment"],
+ [SyntaxKind.JSDocImplementsTag]: ["tagName", "className", "comment"],
+ [SyntaxKind.JSDocAugmentsTag]: ["tagName", "className", "comment"],
+ [SyntaxKind.JSDocSatisfiesTag]: ["tagName", "typeExpression", "comment"],
+ [SyntaxKind.JSDocThisTag]: ["tagName", "typeExpression", "comment"],
+ [SyntaxKind.JSDocImportTag]: ["tagName", "importClause", "moduleSpecifier", "attributes", "comment"],
+ [SyntaxKind.JSDocCallbackTag]: ["tagName", "typeExpression", "fullName", "comment"],
+ [SyntaxKind.JSDocOverloadTag]: ["tagName", "typeExpression", "comment"],
+ [SyntaxKind.JSDocTypedefTag]: ["tagName", "typeExpression", "fullName", "comment"],
+ [SyntaxKind.JSDocSignature]: ["typeParameters", "parameters", "type"],
+ [SyntaxKind.ClassStaticBlockDeclaration]: ["modifiers", "body"],
+ [SyntaxKind.ClassDeclaration]: ["modifiers", "name", "typeParameters", "heritageClauses", "members"],
+
+ // Later properties are in variable order, needs special handling
+ [SyntaxKind.JSDocPropertyTag]: [undefined!, undefined!],
+ [SyntaxKind.JSDocParameterTag]: ["tagName", undefined!, undefined!, "comment"],
+};
+
+const HEADER_OFFSET_RESERVED = 0;
+const HEADER_OFFSET_STRING_TABLE_OFFSETS = 4;
+const HEADER_OFFSET_STRING_TABLE = 8;
+const HEADER_OFFSET_EXTENDED_DATA = 12;
+const HEADER_OFFSET_NODES = 16;
+const HEADER_SIZE = 20;
+
+type NodeDataType = typeof NODE_DATA_TYPE_CHILDREN | typeof NODE_DATA_TYPE_STRING | typeof NODE_DATA_TYPE_EXTENDED;
+const NODE_DATA_TYPE_CHILDREN = 0x00000000;
+const NODE_DATA_TYPE_STRING = 0x40000000;
+const NODE_DATA_TYPE_EXTENDED = 0x80000000;
+const NODE_DATA_TYPE_MASK = 0xc0_00_00_00;
+const NODE_CHILD_MASK = 0x00_00_00_ff;
+const NODE_STRING_INDEX_MASK = 0x00_ff_ff_ff;
+const NODE_EXTENDED_DATA_MASK = 0x00_ff_ff_ff;
+
+const NODE_OFFSET_KIND = 0;
+const NODE_OFFSET_POS = 4;
+const NODE_OFFSET_END = 8;
+const NODE_OFFSET_NEXT = 12;
+const NODE_OFFSET_PARENT = 16;
+const NODE_OFFSET_DATA = 20;
+const NODE_LEN = 24;
+
+const KIND_NODE_LIST = 2 ** 32 - 1;
+
+export class RemoteNodeBase {
+ parent: RemoteNode;
+ protected view: DataView;
+ protected decoder: TextDecoder;
+ protected index: number;
+ /** Keys are positions */
+ protected _children: Map | undefined;
+
+ constructor(view: DataView, decoder: TextDecoder, index: number, parent: RemoteNode) {
+ this.view = view;
+ this.decoder = decoder;
+ this.index = index;
+ this.parent = parent;
+ }
+
+ get kind(): SyntaxKind {
+ return this.view.getUint32(this.byteIndex + NODE_OFFSET_KIND, true);
+ }
+
+ get pos(): number {
+ return this.view.getUint32(this.byteIndex + NODE_OFFSET_POS, true);
+ }
+
+ get end(): number {
+ return this.view.getUint32(this.byteIndex + NODE_OFFSET_END, true);
+ }
+
+ get next(): number {
+ return this.view.getUint32(this.byteIndex + NODE_OFFSET_NEXT, true);
+ }
+
+ protected get byteIndex(): number {
+ return this.offsetNodes + this.index * NODE_LEN;
+ }
+
+ protected get offsetStringTableOffsets(): number {
+ return this.view.getUint32(HEADER_OFFSET_STRING_TABLE_OFFSETS, true);
+ }
+
+ protected get offsetStringTable(): number {
+ return this.view.getUint32(HEADER_OFFSET_STRING_TABLE, true);
+ }
+
+ protected get offsetExtendedData(): number {
+ return this.view.getUint32(HEADER_OFFSET_EXTENDED_DATA, true);
+ }
+
+ protected get offsetNodes(): number {
+ return this.view.getUint32(HEADER_OFFSET_NODES, true);
+ }
+
+ protected get parentIndex(): number {
+ return this.view.getUint32(this.byteIndex + NODE_OFFSET_PARENT, true);
+ }
+
+ protected get data(): number {
+ return this.view.getUint32(this.byteIndex + NODE_OFFSET_DATA, true);
+ }
+
+ protected get dataType(): NodeDataType {
+ return (this.data & NODE_DATA_TYPE_MASK) as NodeDataType;
+ }
+
+ protected get childMask(): number {
+ if (this.dataType !== NODE_DATA_TYPE_CHILDREN) {
+ return 0;
+ }
+ return this.data & NODE_CHILD_MASK;
+ }
+
+ protected getFileText(start: number, end: number): string {
+ return this.decoder.decode(new Uint8Array(this.view.buffer, this.offsetStringTable + start, end - start));
+ }
+}
+
+export class RemoteNodeList extends Array implements NodeArray {
+ parent: RemoteNode;
+ protected view: DataView;
+ protected decoder: TextDecoder;
+ protected index: number;
+ /** Keys are positions */
+ protected _children: Map | undefined;
+
+ get pos(): number {
+ return this.view.getUint32(this.byteIndex + NODE_OFFSET_POS, true);
+ }
+
+ get end(): number {
+ return this.view.getUint32(this.byteIndex + NODE_OFFSET_END, true);
+ }
+
+ get next(): number {
+ return this.view.getUint32(this.byteIndex + NODE_OFFSET_NEXT, true);
+ }
+
+ private get data(): number {
+ return this.view.getUint32(this.byteIndex + NODE_OFFSET_DATA, true);
+ }
+
+ private get offsetNodes(): number {
+ return this.view.getUint32(HEADER_OFFSET_NODES, true);
+ }
+
+ private get byteIndex(): number {
+ return this.offsetNodes + this.index * NODE_LEN;
+ }
+
+ constructor(view: DataView, decoder: TextDecoder, index: number, parent: RemoteNode) {
+ super();
+ this.view = view;
+ this.decoder = decoder;
+ this.index = index;
+ this.parent = parent;
+ this.length = this.data;
+
+ const length = this.length;
+ for (let i = 0; i < length; i++) {
+ Object.defineProperty(this, i, {
+ get() {
+ return this.at(i);
+ },
+ });
+ }
+ }
+
+ *[Symbol.iterator](): ArrayIterator {
+ let next = this.index + 1;
+ while (next) {
+ const child = this.getOrCreateChildAtNodeIndex(next);
+ next = child.next;
+ yield child as RemoteNode;
+ }
+ }
+
+ at(index: number): RemoteNode {
+ if (!Number.isInteger(index)) {
+ return undefined!;
+ }
+ if (index < 0) {
+ index = this.length - index;
+ }
+ let next = this.index + 1;
+ for (let i = 0; i < index; i++) {
+ const child = this.getOrCreateChildAtNodeIndex(next);
+ next = child.next;
+ }
+ return this.getOrCreateChildAtNodeIndex(next) as RemoteNode;
+ }
+
+ private getOrCreateChildAtNodeIndex(index: number): RemoteNode | RemoteNodeList {
+ const pos = this.view.getUint32(this.offsetNodes + index * NODE_LEN + NODE_OFFSET_POS, true);
+ let child = (this._children ??= new Map()).get(pos);
+ if (!child) {
+ const kind = this.view.getUint32(this.offsetNodes + index * NODE_LEN + NODE_OFFSET_KIND, true);
+ if (kind === KIND_NODE_LIST) {
+ throw new Error("NodeList cannot directly contain another NodeList");
+ }
+ child = new RemoteNode(this.view, this.decoder, index, this.parent);
+ this._children.set(pos, child);
+ }
+ return child;
+ }
+
+ __print(): string {
+ const result = [];
+ result.push(`kind: NodeList`);
+ result.push(`index: ${this.index}`);
+ result.push(`byteIndex: ${this.byteIndex}`);
+ result.push(`length: ${this.length}`);
+ return result.join("\n");
+ }
+}
+
+export class RemoteNode extends RemoteNodeBase implements Node {
+ protected static NODE_LEN: number = NODE_LEN;
+ private sourceFile: SourceFile;
+ id: string;
+
+ constructor(view: DataView, decoder: TextDecoder, index: number, parent: RemoteNode) {
+ super(view, decoder, index, parent);
+ let sourceFile: RemoteNode = this;
+ while (sourceFile && sourceFile.kind !== SyntaxKind.SourceFile) {
+ sourceFile = sourceFile.parent;
+ }
+ if (!sourceFile) {
+ throw new Error("SourceFile not found");
+ }
+ this.sourceFile = sourceFile as unknown as SourceFile;
+ this.id = `${sourceFile.id}.${this.pos}.${this.kind}`;
+ }
+
+ forEachChild(visitNode: (node: Node) => T, visitList?: (list: NodeArray) => T): T | undefined {
+ if (this.hasChildren()) {
+ let next = this.index + 1;
+ do {
+ const child = this.getOrCreateChildAtNodeIndex(next);
+ if (child instanceof RemoteNodeList) {
+ if (visitList) {
+ const result = visitList(child);
+ if (result) {
+ return result;
+ }
+ }
+ for (const node of child) {
+ const result = visitNode(node);
+ if (result) {
+ return result;
+ }
+ }
+ }
+ else {
+ const result = visitNode(child);
+ if (result) {
+ return result;
+ }
+ }
+ next = child.next;
+ }
+ while (next);
+ }
+ }
+
+ getSourceFile(): SourceFile {
+ return this.sourceFile;
+ }
+
+ protected getString(index: number): string {
+ const start = this.view.getUint32(this.offsetStringTableOffsets + index * 4, true);
+ const end = this.view.getUint32(this.offsetStringTableOffsets + (index + 1) * 4, true);
+ const text = new Uint8Array(this.view.buffer, this.offsetStringTable + start, end - start);
+ return this.decoder.decode(text);
+ }
+
+ private getOrCreateChildAtNodeIndex(index: number): RemoteNode | RemoteNodeList {
+ const pos = this.view.getUint32(this.offsetNodes + index * NODE_LEN + NODE_OFFSET_POS, true);
+ let child = (this._children ??= new Map()).get(pos);
+ if (!child) {
+ const kind = this.view.getUint32(this.offsetNodes + index * NODE_LEN + NODE_OFFSET_KIND, true);
+ child = kind === KIND_NODE_LIST
+ ? new RemoteNodeList(this.view, this.decoder, index, this)
+ : new RemoteNode(this.view, this.decoder, index, this);
+ this._children.set(pos, child);
+ }
+ return child;
+ }
+
+ private hasChildren(): boolean {
+ if (this._children) {
+ return true;
+ }
+ if (this.byteIndex >= this.view.byteLength - NODE_LEN) {
+ return false;
+ }
+ const nextNodeParent = this.view.getUint32(this.offsetNodes + (this.index + 1) * NODE_LEN + NODE_OFFSET_PARENT, true);
+ return nextNodeParent === this.index;
+ }
+
+ private getNamedChild(propertyName: string): RemoteNode | RemoteNodeList | undefined {
+ const propertyNames = childProperties[this.kind];
+ if (!propertyNames) {
+ // `childProperties` is only defined for nodes with more than one child property.
+ // Get the only child if it exists.
+ const child = this.getOrCreateChildAtNodeIndex(this.index + 1);
+ if (child.next !== 0) {
+ throw new Error("Expected only one child");
+ }
+ return child;
+ }
+
+ let order = propertyNames.indexOf(propertyName);
+ if (order === -1) {
+ // JSDocPropertyTag and JSDocParameterTag need special handling
+ // because they have a conditional property order
+ const kind = this.kind;
+ if (kind === SyntaxKind.JSDocPropertyTag) {
+ switch (propertyName) {
+ case "name":
+ order = this.isNameFirst ? 0 : 1;
+ break;
+ case "typeExpression":
+ order = this.isNameFirst ? 1 : 0;
+ break;
+ }
+ }
+ else if (kind === SyntaxKind.JSDocParameterTag) {
+ switch (propertyName) {
+ case "name":
+ order = this.isNameFirst ? 1 : 2;
+ case "typeExpression":
+ order = this.isNameFirst ? 2 : 1;
+ }
+ }
+ // Node kind does not have this property
+ return undefined;
+ }
+ const mask = this.childMask;
+ if (!(mask & (1 << order))) {
+ // Property is not present
+ return undefined;
+ }
+
+ // The property index is `order`, minus the number of zeros in the mask that are in bit positions less
+ // than the `order`th bit. Example:
+ //
+ // This is a MethodDeclaration with mask 0b01110101. The possible properties are
+ // ["modifiers", "asteriskToken", "name", "postfixToken", "typeParameters", "parameters", "type", "body"]
+ // (it has modifiers, name, typeParameters, parameters, and type).
+ //
+ // | Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+ // | ----- | ---- | ---- | ---------- | -------------- | ------------ | ---- | ------------- | --------- |
+ // | Value | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 1 |
+ // | Name | body | type | parameters | typeParameters | postfixToken | name | asteriskToken | modifiers |
+ //
+ // We are trying to get the index of "parameters" (bit = 5).
+ // First, set all the more significant bits to 1:
+ //
+ // | Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+ // | ----- | ---- | ---- | ---------- | -------------- | ------------ | ---- | ------------- | --------- |
+ // | Value | 1 | 1 | 1 | 1 | 0 | 1 | 0 | 1 |
+ //
+ // Then, flip the bits:
+ //
+ // | Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+ // | ----- | ---- | ---- | ---------- | -------------- | ------------ | ---- | ------------- | --------- |
+ // | Value | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 |
+ //
+ // Counting the 1s gives us the number of *missing properties* before the `order`th property. If every property
+ // were present, we would have `parameters = children[5]`, but since `postfixToken` and `astersiskToken` are
+ // missing, we have `parameters = children[5 - 2]`.
+ const propertyIndex = order - popcount8[~(mask | ((0xff << order) & 0xff)) & 0xff];
+ return this.getOrCreateChildAtNodeIndex(this.index + 1 + propertyIndex);
+ }
+
+ __print(): string {
+ const result = [];
+ result.push(`index: ${this.index}`);
+ result.push(`byteIndex: ${this.byteIndex}`);
+ result.push(`kind: ${SyntaxKind[this.kind]}`);
+ result.push(`pos: ${this.pos}`);
+ result.push(`end: ${this.end}`);
+ result.push(`next: ${this.next}`);
+ result.push(`parent: ${this.parentIndex}`);
+ result.push(`data: ${this.data.toString(2).padStart(32, "0")}`);
+ const dataType = this.dataType === NODE_DATA_TYPE_CHILDREN ? "children" :
+ this.dataType === NODE_DATA_TYPE_STRING ? "string" :
+ "extended";
+ result.push(`dataType: ${dataType}`);
+ if (this.dataType === NODE_DATA_TYPE_CHILDREN) {
+ result.push(`childMask: ${this.childMask.toString(2).padStart(8, "0")}`);
+ result.push(`childProperties: ${childProperties[this.kind]?.join(", ")}`);
+ }
+ return result.join("\n");
+ }
+
+ __printChildren(): string {
+ const result = [];
+ let next = this.index + 1;
+ while (next) {
+ const child = this.getOrCreateChildAtNodeIndex(next);
+ next = child.next;
+ result.push(child.__print());
+ }
+ return result.join("\n\n");
+ }
+
+ __printSubtree(): string {
+ const result = [this.__print()];
+ this.forEachChild(function visitNode(node) {
+ result.push((node as RemoteNode).__print());
+ node.forEachChild(visitNode);
+ }, visitList => {
+ result.push((visitList as RemoteNodeList).__print());
+ });
+ return result.join("\n\n");
+ }
+
+ // Boolean properties
+ get isArrayType(): boolean | undefined {
+ switch (this.kind) {
+ case SyntaxKind.JSDocTypeLiteral:
+ return (this.data & 1 << 24) !== 0;
+ }
+ }
+
+ get isTypeOnly(): boolean | undefined {
+ switch (this.kind) {
+ case SyntaxKind.ImportSpecifier:
+ case SyntaxKind.ImportClause:
+ case SyntaxKind.ExportSpecifier:
+ case SyntaxKind.ImportEqualsDeclaration:
+ case SyntaxKind.ExportDeclaration:
+ return (this.data & 1 << 24) !== 0;
+ }
+ }
+
+ get isTypeOf(): boolean | undefined {
+ switch (this.kind) {
+ case SyntaxKind.ImportType:
+ return (this.data & 1 << 24) !== 0;
+ }
+ }
+
+ get multiline(): boolean | undefined {
+ switch (this.kind) {
+ case SyntaxKind.Block:
+ case SyntaxKind.ArrayLiteralExpression:
+ case SyntaxKind.ObjectLiteralExpression:
+ case SyntaxKind.ImportAttributes:
+ return (this.data & 1 << 24) !== 0;
+ }
+ }
+
+ get isExportEquals(): boolean | undefined {
+ switch (this.kind) {
+ case SyntaxKind.ExportAssignment:
+ return (this.data & 1 << 24) !== 0;
+ }
+ }
+
+ get isBracketed(): boolean | undefined {
+ switch (this.kind) {
+ case SyntaxKind.JSDocPropertyTag:
+ case SyntaxKind.JSDocParameterTag:
+ return (this.data & 1 << 24) !== 0;
+ }
+ }
+
+ get containsOnlyTriviaWhiteSpaces(): boolean | undefined {
+ switch (this.kind) {
+ case SyntaxKind.JsxText:
+ return (this.data & 1 << 24) !== 0;
+ }
+ }
+
+ get isNameFirst(): boolean | undefined {
+ switch (this.kind) {
+ case SyntaxKind.JSDocPropertyTag:
+ case SyntaxKind.JSDocParameterTag:
+ return (this.data & 1 << 25) !== 0;
+ }
+ }
+
+ // Children properties
+ get argument(): RemoteNode | undefined {
+ return this.getNamedChild("argument") as RemoteNode;
+ }
+ get argumentExpression(): RemoteNode | undefined {
+ return this.getNamedChild("argumentExpression") as RemoteNode;
+ }
+ get arguments(): RemoteNodeList | undefined {
+ return this.getNamedChild("arguments") as RemoteNodeList;
+ }
+ get assertsModifier(): RemoteNode | undefined {
+ return this.getNamedChild("assertsModifier") as RemoteNode;
+ }
+ get asteriskToken(): RemoteNode | undefined {
+ return this.getNamedChild("asteriskToken") as RemoteNode;
+ }
+ get attributes(): RemoteNode | undefined {
+ return this.getNamedChild("attributes") as RemoteNode;
+ }
+ get awaitModifier(): RemoteNode | undefined {
+ return this.getNamedChild("awaitModifier") as RemoteNode;
+ }
+ get block(): RemoteNode | undefined {
+ return this.getNamedChild("block") as RemoteNode;
+ }
+ get body(): RemoteNode | undefined {
+ return this.getNamedChild("body") as RemoteNode;
+ }
+ get caseBlock(): RemoteNode | undefined {
+ return this.getNamedChild("caseBlock") as RemoteNode;
+ }
+ get catchClause(): RemoteNode | undefined {
+ return this.getNamedChild("catchClause") as RemoteNode;
+ }
+ get checkType(): RemoteNode | undefined {
+ return this.getNamedChild("checkType") as RemoteNode;
+ }
+ get children(): RemoteNodeList | undefined {
+ return this.getNamedChild("children") as RemoteNodeList;
+ }
+ get className(): RemoteNode | undefined {
+ return this.getNamedChild("className") as RemoteNode;
+ }
+ get closingElement(): RemoteNode | undefined {
+ return this.getNamedChild("closingElement") as RemoteNode;
+ }
+ get closingFragment(): RemoteNode | undefined {
+ return this.getNamedChild("closingFragment") as RemoteNode;
+ }
+ get colonToken(): RemoteNode | undefined {
+ return this.getNamedChild("colonToken") as RemoteNode;
+ }
+ get comment(): RemoteNode | undefined {
+ return this.getNamedChild("comment") as RemoteNode;
+ }
+ get condition(): RemoteNode | undefined {
+ return this.getNamedChild("condition") as RemoteNode;
+ }
+ get constraint(): RemoteNode | undefined {
+ return this.getNamedChild("constraint") as RemoteNode;
+ }
+ get declarationList(): RemoteNode | undefined {
+ return this.getNamedChild("declarationList") as RemoteNode;
+ }
+ get defaultType(): RemoteNode | undefined {
+ return this.getNamedChild("defaultType") as RemoteNode;
+ }
+ get dotDotDotToken(): RemoteNode | undefined {
+ return this.getNamedChild("dotDotDotToken") as RemoteNode;
+ }
+ get elements(): RemoteNodeList | undefined {
+ return this.getNamedChild("elements") as RemoteNodeList;
+ }
+ get elseStatement(): RemoteNode | undefined {
+ return this.getNamedChild("elseStatement") as RemoteNode;
+ }
+ get equalsGreaterThanToken(): RemoteNode | undefined {
+ return this.getNamedChild("equalsGreaterThanToken") as RemoteNode;
+ }
+ get equalsToken(): RemoteNode | undefined {
+ return this.getNamedChild("equalsToken") as RemoteNode;
+ }
+ get exclamationToken(): RemoteNode | undefined {
+ return this.getNamedChild("exclamationToken") as RemoteNode;
+ }
+ get exportClause(): RemoteNode | undefined {
+ return this.getNamedChild("exportClause") as RemoteNode;
+ }
+ get expression(): RemoteNode | undefined {
+ return this.getNamedChild("expression") as RemoteNode;
+ }
+ get exprName(): RemoteNode | undefined {
+ return this.getNamedChild("exprName") as RemoteNode;
+ }
+ get extendsType(): RemoteNode | undefined {
+ return this.getNamedChild("extendsType") as RemoteNode;
+ }
+ get falseType(): RemoteNode | undefined {
+ return this.getNamedChild("falseType") as RemoteNode;
+ }
+ get finallyBlock(): RemoteNode | undefined {
+ return this.getNamedChild("finallyBlock") as RemoteNode;
+ }
+ get fullName(): RemoteNode | undefined {
+ return this.getNamedChild("fullName") as RemoteNode;
+ }
+ get head(): RemoteNode | undefined {
+ return this.getNamedChild("head") as RemoteNode;
+ }
+ get heritageClauses(): RemoteNodeList | undefined {
+ return this.getNamedChild("heritageClauses") as RemoteNodeList;
+ }
+ get importClause(): RemoteNode | undefined {
+ return this.getNamedChild("importClause") as RemoteNode;
+ }
+ get incrementor(): RemoteNode | undefined {
+ return this.getNamedChild("incrementor") as RemoteNode;
+ }
+ get indexType(): RemoteNode | undefined {
+ return this.getNamedChild("indexType") as RemoteNode;
+ }
+ get initializer(): RemoteNode | undefined {
+ return this.getNamedChild("initializer") as RemoteNode;
+ }
+ get label(): RemoteNode | undefined {
+ return this.getNamedChild("label") as RemoteNode;
+ }
+ get left(): RemoteNode | undefined {
+ return this.getNamedChild("left") as RemoteNode;
+ }
+ get literal(): RemoteNode | undefined {
+ return this.getNamedChild("literal") as RemoteNode;
+ }
+ get members(): RemoteNodeList | undefined {
+ return this.getNamedChild("members") as RemoteNodeList;
+ }
+ get modifiers(): RemoteNodeList | undefined {
+ return this.getNamedChild("modifiers") as RemoteNodeList;
+ }
+ get moduleReference(): RemoteNode | undefined {
+ return this.getNamedChild("moduleReference") as RemoteNode;
+ }
+ get moduleSpecifier(): RemoteNode | undefined {
+ return this.getNamedChild("moduleSpecifier") as RemoteNode;
+ }
+ get name(): RemoteNode | undefined {
+ return this.getNamedChild("name") as RemoteNode;
+ }
+ get namedBindings(): RemoteNode | undefined {
+ return this.getNamedChild("namedBindings") as RemoteNode;
+ }
+ get nameExpression(): RemoteNode | undefined {
+ return this.getNamedChild("nameExpression") as RemoteNode;
+ }
+ get namespace(): RemoteNode | undefined {
+ return this.getNamedChild("namespace") as RemoteNode;
+ }
+ get nameType(): RemoteNode | undefined {
+ return this.getNamedChild("nameType") as RemoteNode;
+ }
+ get objectAssignmentInitializer(): RemoteNode | undefined {
+ return this.getNamedChild("objectAssignmentInitializer") as RemoteNode;
+ }
+ get objectType(): RemoteNode | undefined {
+ return this.getNamedChild("objectType") as RemoteNode;
+ }
+ get openingElement(): RemoteNode | undefined {
+ return this.getNamedChild("openingElement") as RemoteNode;
+ }
+ get openingFragment(): RemoteNode | undefined {
+ return this.getNamedChild("openingFragment") as RemoteNode;
+ }
+ get operatorToken(): RemoteNode | undefined {
+ return this.getNamedChild("operatorToken") as RemoteNode;
+ }
+ get parameterName(): RemoteNode | undefined {
+ return this.getNamedChild("parameterName") as RemoteNode;
+ }
+ get parameters(): RemoteNodeList | undefined {
+ return this.getNamedChild("parameters") as RemoteNodeList;
+ }
+ get postfixToken(): RemoteNode | undefined {
+ return this.getNamedChild("postfixToken") as RemoteNode;
+ }
+ get propertyName(): RemoteNode | undefined {
+ return this.getNamedChild("propertyName") as RemoteNode;
+ }
+ get qualifier(): RemoteNode | undefined {
+ return this.getNamedChild("qualifier") as RemoteNode;
+ }
+ get questionDotToken(): RemoteNode | undefined {
+ return this.getNamedChild("questionDotToken") as RemoteNode;
+ }
+ get questionToken(): RemoteNode | undefined {
+ return this.getNamedChild("questionToken") as RemoteNode;
+ }
+ get readonlyToken(): RemoteNode | undefined {
+ return this.getNamedChild("readonlyToken") as RemoteNode;
+ }
+ get right(): RemoteNode | undefined {
+ return this.getNamedChild("right") as RemoteNode;
+ }
+ get statement(): RemoteNode | undefined {
+ return this.getNamedChild("statement") as RemoteNode;
+ }
+ get statements(): RemoteNodeList | undefined {
+ return this.getNamedChild("statements") as RemoteNodeList;
+ }
+ get tag(): RemoteNode | undefined {
+ return this.getNamedChild("tag") as RemoteNode;
+ }
+ get tagName(): RemoteNode | undefined {
+ return this.getNamedChild("tagName") as RemoteNode;
+ }
+ get tags(): RemoteNodeList | undefined {
+ return this.getNamedChild("tags") as RemoteNodeList;
+ }
+ get template(): RemoteNode | undefined {
+ return this.getNamedChild("template") as RemoteNode;
+ }
+ get templateSpans(): RemoteNodeList | undefined {
+ return this.getNamedChild("templateSpans") as RemoteNodeList;
+ }
+ get thenStatement(): RemoteNode | undefined {
+ return this.getNamedChild("thenStatement") as RemoteNode;
+ }
+ get trueType(): RemoteNode | undefined {
+ return this.getNamedChild("trueType") as RemoteNode;
+ }
+ get tryBlock(): RemoteNode | undefined {
+ return this.getNamedChild("tryBlock") as RemoteNode;
+ }
+ get type(): RemoteNode | undefined {
+ return this.getNamedChild("type") as RemoteNode;
+ }
+ get typeArguments(): RemoteNode | undefined {
+ return this.getNamedChild("typeArguments") as RemoteNode;
+ }
+ get typeExpression(): RemoteNode | undefined {
+ return this.getNamedChild("typeExpression") as RemoteNode;
+ }
+ get typeName(): RemoteNode | undefined {
+ return this.getNamedChild("typeName") as RemoteNode;
+ }
+ get typeParameter(): RemoteNode | undefined {
+ return this.getNamedChild("typeParameter") as RemoteNode;
+ }
+ get typeParameters(): RemoteNodeList | undefined {
+ return this.getNamedChild("typeParameters") as RemoteNodeList;
+ }
+ get value(): RemoteNode | undefined {
+ return this.getNamedChild("value") as RemoteNode;
+ }
+ get variableDeclaration(): RemoteNode | undefined {
+ return this.getNamedChild("variableDeclaration") as RemoteNode;
+ }
+ get whenFalse(): RemoteNode | undefined {
+ return this.getNamedChild("whenFalse") as RemoteNode;
+ }
+ get whenTrue(): RemoteNode | undefined {
+ return this.getNamedChild("whenTrue") as RemoteNode;
+ }
+
+ // String properties
+ get text(): string | undefined {
+ switch (this.kind) {
+ case SyntaxKind.JsxText:
+ case SyntaxKind.Identifier:
+ case SyntaxKind.PrivateIdentifier:
+ case SyntaxKind.StringLiteral:
+ case SyntaxKind.NumericLiteral:
+ case SyntaxKind.BigIntLiteral:
+ case SyntaxKind.RegularExpressionLiteral:
+ case SyntaxKind.NoSubstitutionTemplateLiteral:
+ case SyntaxKind.JSDocText: {
+ const stringIndex = this.data & NODE_STRING_INDEX_MASK;
+ return this.getString(stringIndex);
+ }
+ case SyntaxKind.SourceFile:
+ case SyntaxKind.TemplateHead:
+ case SyntaxKind.TemplateMiddle:
+ case SyntaxKind.TemplateTail: {
+ const extendedDataOffset = this.offsetExtendedData + (this.data & NODE_EXTENDED_DATA_MASK);
+ const stringIndex = this.view.getUint32(extendedDataOffset, true);
+ return this.getString(stringIndex);
+ }
+ }
+ }
+
+ get rawText(): string | undefined {
+ switch (this.kind) {
+ case SyntaxKind.TemplateHead:
+ case SyntaxKind.TemplateMiddle:
+ case SyntaxKind.TemplateTail:
+ const extendedDataOffset = this.offsetExtendedData + (this.data & NODE_EXTENDED_DATA_MASK);
+ const stringIndex = this.view.getUint32(extendedDataOffset + 4, true);
+ return this.getString(stringIndex);
+ }
+ }
+
+ get fileName(): string | undefined {
+ switch (this.kind) {
+ case SyntaxKind.SourceFile:
+ const extendedDataOffset = this.offsetExtendedData + (this.data & NODE_EXTENDED_DATA_MASK);
+ const stringIndex = this.view.getUint32(extendedDataOffset + 4, true);
+ return this.getString(stringIndex);
+ }
+ }
+
+ // Other properties
+ get flags(): number {
+ switch (this.kind) {
+ case SyntaxKind.VariableDeclarationList:
+ return this.data & (1 << 24 | 1 << 25) >> 24;
+ default:
+ return 0;
+ }
+ }
+
+ get token(): SyntaxKind | undefined {
+ switch (this.kind) {
+ case SyntaxKind.ImportAttributes:
+ if ((this.data & 1 << 25) !== 0) {
+ return SyntaxKind.AssertKeyword;
+ }
+ return SyntaxKind.WithKeyword;
+ }
+ }
+
+ get templateFlags(): number | undefined {
+ switch (this.kind) {
+ case SyntaxKind.TemplateHead:
+ case SyntaxKind.TemplateMiddle:
+ case SyntaxKind.TemplateTail:
+ const extendedDataOffset = this.offsetExtendedData + (this.data & NODE_EXTENDED_DATA_MASK);
+ return this.view.getUint32(extendedDataOffset + 8, true);
+ }
+ }
+}
+
+export class RemoteSourceFile extends RemoteNode {
+ constructor(data: Uint8Array, decoder: TextDecoder) {
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
+ super(view, decoder, 1, undefined!);
+ this.id = this.getString(this.view.getUint32(this.offsetExtendedData + 8, true));
+ }
+}
diff --git a/_packages/api/src/objectRegistry.ts b/_packages/api/src/objectRegistry.ts
new file mode 100644
index 0000000000..7a36ecb9c6
--- /dev/null
+++ b/_packages/api/src/objectRegistry.ts
@@ -0,0 +1,85 @@
+import {
+ Project,
+ Symbol,
+ Type,
+} from "./api.ts";
+import type { Client } from "./client.ts";
+import type {
+ ProjectResponse,
+ SymbolResponse,
+ TypeResponse,
+} from "./proto.ts";
+
+export class ObjectRegistry {
+ private client: Client;
+ private projects: Map = new Map();
+ private symbols: Map = new Map();
+ private types: Map = new Map();
+
+ constructor(client: Client) {
+ this.client = client;
+ }
+
+ getProject(data: ProjectResponse): Project {
+ let project = this.projects.get(data.id);
+ if (project) {
+ return project;
+ }
+
+ project = new Project(this.client, this, data);
+ this.projects.set(data.id, project);
+ return project;
+ }
+
+ getSymbol(data: SymbolResponse): Symbol {
+ let symbol = this.symbols.get(data.id);
+ if (symbol) {
+ return symbol;
+ }
+
+ symbol = new Symbol(this.client, this, data);
+ this.symbols.set(data.id, symbol);
+ return symbol;
+ }
+
+ getType(data: TypeResponse): Type {
+ let type = this.types.get(data.id);
+ if (type) {
+ return type;
+ }
+
+ type = new Type(this.client, this, data);
+ this.types.set(data.id, type);
+ return type;
+ }
+
+ release(object: object): void {
+ if (object instanceof Project) {
+ this.releaseProject(object);
+ }
+ else if (object instanceof Symbol) {
+ this.releaseSymbol(object);
+ }
+ else if (object instanceof Type) {
+ this.releaseType(object);
+ }
+ else {
+ throw new Error("Unknown object type");
+ }
+ }
+
+ releaseProject(project: Project): void {
+ this.projects.delete(project.id);
+ this.client.request("release", project.id);
+ }
+
+ releaseSymbol(symbol: Symbol): void {
+ this.symbols.delete(symbol.id);
+ this.client.request("release", symbol.id);
+ }
+
+ releaseType(type: Type): void {
+ this.types.delete(type.id);
+ this.client.request("release", type.id);
+ }
+}
diff --git a/_packages/api/src/path.ts b/_packages/api/src/path.ts
new file mode 100644
index 0000000000..487432f057
--- /dev/null
+++ b/_packages/api/src/path.ts
@@ -0,0 +1,136 @@
+const CharacterCodesSlash = "/".charCodeAt(0);
+const CharacterCodesBackslash = "\\".charCodeAt(0);
+const CharacterCodesColon = ":".charCodeAt(0);
+const CharacterCodesPercent = "%".charCodeAt(0);
+const CharacterCodes3 = "3".charCodeAt(0);
+const CharacterCodesa = "a".charCodeAt(0);
+const CharacterCodesz = "z".charCodeAt(0);
+const CharacterCodesA = "A".charCodeAt(0);
+const CharacterCodesZ = "Z".charCodeAt(0);
+const directorySeparator = "/";
+const altDirectorySeparator = "\\";
+const urlSchemeSeparator = "://";
+
+function isVolumeCharacter(charCode: number) {
+ return (charCode >= CharacterCodesa && charCode <= CharacterCodesz) ||
+ (charCode >= CharacterCodesA && charCode <= CharacterCodesZ);
+}
+
+function getFileUrlVolumeSeparatorEnd(url: string, start: number) {
+ const ch0 = url.charCodeAt(start);
+ if (ch0 === CharacterCodesColon) return start + 1;
+ if (ch0 === CharacterCodesPercent && url.charCodeAt(start + 1) === CharacterCodes3) {
+ const ch2 = url.charCodeAt(start + 2);
+ if (ch2 === CharacterCodesa || ch2 === CharacterCodesA) return start + 3;
+ }
+ return -1;
+}
+
+/**
+ * Returns length of the root part of a path or URL (i.e. length of "/", "x:/", "//server/share/, file:///user/files").
+ *
+ * For example:
+ * ```ts
+ * getRootLength("a") === 0 // ""
+ * getRootLength("/") === 1 // "/"
+ * getRootLength("c:") === 2 // "c:"
+ * getRootLength("c:d") === 0 // ""
+ * getRootLength("c:/") === 3 // "c:/"
+ * getRootLength("c:\\") === 3 // "c:\\"
+ * getRootLength("//server") === 7 // "//server"
+ * getRootLength("//server/share") === 8 // "//server/"
+ * getRootLength("\\\\server") === 7 // "\\\\server"
+ * getRootLength("\\\\server\\share") === 8 // "\\\\server\\"
+ * getRootLength("file:///path") === 8 // "file:///"
+ * getRootLength("file:///c:") === 10 // "file:///c:"
+ * getRootLength("file:///c:d") === 8 // "file:///"
+ * getRootLength("file:///c:/path") === 11 // "file:///c:/"
+ * getRootLength("file://server") === 13 // "file://server"
+ * getRootLength("file://server/path") === 14 // "file://server/"
+ * getRootLength("http://server") === 13 // "http://server"
+ * getRootLength("http://server/path") === 14 // "http://server/"
+ * ```
+ *
+ * @internal
+ */
+export function getRootLength(path: string): number {
+ const rootLength = getEncodedRootLength(path);
+ return rootLength < 0 ? ~rootLength : rootLength;
+}
+
+/**
+ * Returns length of the root part of a path or URL (i.e. length of "/", "x:/", "//server/share/, file:///user/files").
+ * If the root is part of a URL, the twos-complement of the root length is returned.
+ */
+function getEncodedRootLength(path: string): number {
+ if (!path) return 0;
+ const ch0 = path.charCodeAt(0);
+
+ // POSIX or UNC
+ if (ch0 === CharacterCodesSlash || ch0 === CharacterCodesBackslash) {
+ if (path.charCodeAt(1) !== ch0) return 1; // POSIX: "/" (or non-normalized "\")
+
+ const p1 = path.indexOf(ch0 === CharacterCodesSlash ? directorySeparator : altDirectorySeparator, 2);
+ if (p1 < 0) return path.length; // UNC: "//server" or "\\server"
+
+ return p1 + 1; // UNC: "//server/" or "\\server\"
+ }
+
+ // DOS
+ if (isVolumeCharacter(ch0) && path.charCodeAt(1) === CharacterCodesColon) {
+ const ch2 = path.charCodeAt(2);
+ if (ch2 === CharacterCodesSlash || ch2 === CharacterCodesBackslash) return 3; // DOS: "c:/" or "c:\"
+ if (path.length === 2) return 2; // DOS: "c:" (but not "c:d")
+ }
+
+ // URL
+ const schemeEnd = path.indexOf(urlSchemeSeparator);
+ if (schemeEnd !== -1) {
+ const authorityStart = schemeEnd + urlSchemeSeparator.length;
+ const authorityEnd = path.indexOf(directorySeparator, authorityStart);
+ if (authorityEnd !== -1) { // URL: "file:///", "file://server/", "file://server/path"
+ // For local "file" URLs, include the leading DOS volume (if present).
+ // Per https://www.ietf.org/rfc/rfc1738.txt, a host of "" or "localhost" is a
+ // special case interpreted as "the machine from which the URL is being interpreted".
+ const scheme = path.slice(0, schemeEnd);
+ const authority = path.slice(authorityStart, authorityEnd);
+ if (
+ scheme === "file" && (authority === "" || authority === "localhost") &&
+ isVolumeCharacter(path.charCodeAt(authorityEnd + 1))
+ ) {
+ const volumeSeparatorEnd = getFileUrlVolumeSeparatorEnd(path, authorityEnd + 2);
+ if (volumeSeparatorEnd !== -1) {
+ if (path.charCodeAt(volumeSeparatorEnd) === CharacterCodesSlash) {
+ // URL: "file:///c:/", "file://localhost/c:/", "file:///c%3a/", "file://localhost/c%3a/"
+ return ~(volumeSeparatorEnd + 1);
+ }
+ if (volumeSeparatorEnd === path.length) {
+ // URL: "file:///c:", "file://localhost/c:", "file:///c$3a", "file://localhost/c%3a"
+ // but not "file:///c:d" or "file:///c%3ad"
+ return ~volumeSeparatorEnd;
+ }
+ }
+ }
+ return ~(authorityEnd + 1); // URL: "file://server/", "http://server/"
+ }
+ return ~path.length; // URL: "file://server", "http://server"
+ }
+
+ // relative
+ return 0;
+}
+
+export function getPathComponents(path: string): string[] {
+ return pathComponents(path, getRootLength(path));
+}
+
+function pathComponents(path: string, rootLength: number) {
+ const root = path.substring(0, rootLength);
+ const rest = path.substring(rootLength).split("/");
+ if (rest.length && !lastOrUndefined(rest)) rest.pop();
+ return [root, ...rest];
+}
+
+function lastOrUndefined(array: T[]): T | undefined {
+ return array.length ? array[array.length - 1] : undefined;
+}
diff --git a/_packages/api/src/proto.ts b/_packages/api/src/proto.ts
new file mode 100644
index 0000000000..d47eceab7e
--- /dev/null
+++ b/_packages/api/src/proto.ts
@@ -0,0 +1,23 @@
+export interface ConfigResponse {
+ options: Record;
+ fileNames: string[];
+}
+
+export interface ProjectResponse {
+ id: string;
+ configFileName: string;
+ compilerOptions: Record;
+ rootFiles: string[];
+}
+
+export interface SymbolResponse {
+ id: string;
+ name: string;
+ flags: number;
+ checkFlags: number;
+}
+
+export interface TypeResponse {
+ id: string;
+ flags: number;
+}
diff --git a/_packages/api/src/symbolFlags.enum.ts b/_packages/api/src/symbolFlags.enum.ts
new file mode 100644
index 0000000000..8032b9fa45
--- /dev/null
+++ b/_packages/api/src/symbolFlags.enum.ts
@@ -0,0 +1,75 @@
+export enum SymbolFlags {
+ None = 0,
+ FunctionScopedVariable = 1 << 0,
+ BlockScopedVariable = 1 << 1,
+ Property = 1 << 2,
+ EnumMember = 1 << 3,
+ Function = 1 << 4,
+ Class = 1 << 5,
+ Interface = 1 << 6,
+ ConstEnum = 1 << 7,
+ RegularEnum = 1 << 8,
+ ValueModule = 1 << 9,
+ NamespaceModule = 1 << 10,
+ TypeLiteral = 1 << 11,
+ ObjectLiteral = 1 << 12,
+ Method = 1 << 13,
+ Constructor = 1 << 14,
+ GetAccessor = 1 << 15,
+ SetAccessor = 1 << 16,
+ Signature = 1 << 17,
+ TypeParameter = 1 << 18,
+ TypeAlias = 1 << 19,
+ ExportValue = 1 << 20,
+ Alias = 1 << 21,
+ Prototype = 1 << 22,
+ ExportStar = 1 << 23,
+ Optional = 1 << 24,
+ Transient = 1 << 25,
+ Assignment = 1 << 26,
+ ModuleExports = 1 << 27,
+ ConstEnumOnlyModule = 1 << 28,
+ ReplaceableByMethod = 1 << 29,
+ GlobalLookup = 1 << 30,
+ All = 1 << 30 - 1,
+
+ Enum = RegularEnum | ConstEnum,
+ Variable = FunctionScopedVariable | BlockScopedVariable,
+ Value = Variable | Property | EnumMember | ObjectLiteral | Function | Class | Enum | ValueModule | Method | GetAccessor | SetAccessor,
+ Type = Class | Interface | Enum | EnumMember | TypeLiteral | TypeParameter | TypeAlias,
+ Namespace = ValueModule | NamespaceModule | Enum,
+ Module = ValueModule | NamespaceModule,
+ Accessor = GetAccessor | SetAccessor,
+
+ FunctionScopedVariableExcludes = Value & ~FunctionScopedVariable,
+
+ BlockScopedVariableExcludes = Value,
+
+ ParameterExcludes = Value,
+ PropertyExcludes = Value & ~Property,
+ EnumMemberExcludes = Value | Type,
+ FunctionExcludes = Value & ~(Function | ValueModule | Class),
+ ClassExcludes = (Value | Type) & ~(ValueModule | Interface | Function),
+ InterfaceExcludes = Type & ~(Interface | Class),
+ RegularEnumExcludes = (Value | Type) & ~(RegularEnum | ValueModule),
+ ConstEnumExcludes = (Value | Type) & ~ConstEnum,
+ ValueModuleExcludes = Value & ~(Function | Class | RegularEnum | ValueModule),
+ NamespaceModuleExcludes = None,
+ MethodExcludes = Value & ~Method,
+ GetAccessorExcludes = Value & ~SetAccessor,
+ SetAccessorExcludes = Value & ~GetAccessor,
+ AccessorExcludes = Value & ~Accessor,
+ TypeParameterExcludes = Type & ~TypeParameter,
+ TypeAliasExcludes = Type,
+ AliasExcludes = Alias,
+ ModuleMember = Variable | Function | Class | Interface | Enum | Module | TypeAlias | Alias,
+ ExportHasLocal = Function | Class | Enum | ValueModule,
+ BlockScoped = BlockScopedVariable | Class | Enum,
+ PropertyOrAccessor = Property | Accessor,
+ ClassMember = Method | Accessor | Property,
+ ExportSupportsDefaultModifier = Class | Function | Interface,
+ ExportDoesNotSupportDefaultModifier = ~ExportSupportsDefaultModifier,
+
+ Classifiable = Class | Enum | TypeAlias | Interface | TypeParameter | Module | Alias,
+ LateBindingContainer = Class | Interface | TypeLiteral | ObjectLiteral | Function,
+}
diff --git a/_packages/api/src/symbolFlags.ts b/_packages/api/src/symbolFlags.ts
new file mode 100644
index 0000000000..896335fb8f
--- /dev/null
+++ b/_packages/api/src/symbolFlags.ts
@@ -0,0 +1,71 @@
+export var SymbolFlags: any;
+(function (SymbolFlags) {
+ SymbolFlags[SymbolFlags["None"] = 0] = "None";
+ SymbolFlags[SymbolFlags["FunctionScopedVariable"] = 1] = "FunctionScopedVariable";
+ SymbolFlags[SymbolFlags["BlockScopedVariable"] = 2] = "BlockScopedVariable";
+ SymbolFlags[SymbolFlags["Property"] = 4] = "Property";
+ SymbolFlags[SymbolFlags["EnumMember"] = 8] = "EnumMember";
+ SymbolFlags[SymbolFlags["Function"] = 16] = "Function";
+ SymbolFlags[SymbolFlags["Class"] = 32] = "Class";
+ SymbolFlags[SymbolFlags["Interface"] = 64] = "Interface";
+ SymbolFlags[SymbolFlags["ConstEnum"] = 128] = "ConstEnum";
+ SymbolFlags[SymbolFlags["RegularEnum"] = 256] = "RegularEnum";
+ SymbolFlags[SymbolFlags["ValueModule"] = 512] = "ValueModule";
+ SymbolFlags[SymbolFlags["NamespaceModule"] = 1024] = "NamespaceModule";
+ SymbolFlags[SymbolFlags["TypeLiteral"] = 2048] = "TypeLiteral";
+ SymbolFlags[SymbolFlags["ObjectLiteral"] = 4096] = "ObjectLiteral";
+ SymbolFlags[SymbolFlags["Method"] = 8192] = "Method";
+ SymbolFlags[SymbolFlags["Constructor"] = 16384] = "Constructor";
+ SymbolFlags[SymbolFlags["GetAccessor"] = 32768] = "GetAccessor";
+ SymbolFlags[SymbolFlags["SetAccessor"] = 65536] = "SetAccessor";
+ SymbolFlags[SymbolFlags["Signature"] = 131072] = "Signature";
+ SymbolFlags[SymbolFlags["TypeParameter"] = 262144] = "TypeParameter";
+ SymbolFlags[SymbolFlags["TypeAlias"] = 524288] = "TypeAlias";
+ SymbolFlags[SymbolFlags["ExportValue"] = 1048576] = "ExportValue";
+ SymbolFlags[SymbolFlags["Alias"] = 2097152] = "Alias";
+ SymbolFlags[SymbolFlags["Prototype"] = 4194304] = "Prototype";
+ SymbolFlags[SymbolFlags["ExportStar"] = 8388608] = "ExportStar";
+ SymbolFlags[SymbolFlags["Optional"] = 16777216] = "Optional";
+ SymbolFlags[SymbolFlags["Transient"] = 33554432] = "Transient";
+ SymbolFlags[SymbolFlags["Assignment"] = 67108864] = "Assignment";
+ SymbolFlags[SymbolFlags["ModuleExports"] = 134217728] = "ModuleExports";
+ SymbolFlags[SymbolFlags["ConstEnumOnlyModule"] = 268435456] = "ConstEnumOnlyModule";
+ SymbolFlags[SymbolFlags["ReplaceableByMethod"] = 536870912] = "ReplaceableByMethod";
+ SymbolFlags[SymbolFlags["GlobalLookup"] = 1073741824] = "GlobalLookup";
+ SymbolFlags[SymbolFlags["All"] = 536870912] = "All";
+ SymbolFlags[SymbolFlags["Enum"] = 384] = "Enum";
+ SymbolFlags[SymbolFlags["Variable"] = 3] = "Variable";
+ SymbolFlags[SymbolFlags["Value"] = 111551] = "Value";
+ SymbolFlags[SymbolFlags["Type"] = 788968] = "Type";
+ SymbolFlags[SymbolFlags["Namespace"] = 1920] = "Namespace";
+ SymbolFlags[SymbolFlags["Module"] = 1536] = "Module";
+ SymbolFlags[SymbolFlags["Accessor"] = 98304] = "Accessor";
+ SymbolFlags[SymbolFlags["FunctionScopedVariableExcludes"] = 111550] = "FunctionScopedVariableExcludes";
+ SymbolFlags[SymbolFlags["BlockScopedVariableExcludes"] = 111551] = "BlockScopedVariableExcludes";
+ SymbolFlags[SymbolFlags["ParameterExcludes"] = 111551] = "ParameterExcludes";
+ SymbolFlags[SymbolFlags["PropertyExcludes"] = 111547] = "PropertyExcludes";
+ SymbolFlags[SymbolFlags["EnumMemberExcludes"] = 900095] = "EnumMemberExcludes";
+ SymbolFlags[SymbolFlags["FunctionExcludes"] = 110991] = "FunctionExcludes";
+ SymbolFlags[SymbolFlags["ClassExcludes"] = 899503] = "ClassExcludes";
+ SymbolFlags[SymbolFlags["InterfaceExcludes"] = 788872] = "InterfaceExcludes";
+ SymbolFlags[SymbolFlags["RegularEnumExcludes"] = 899327] = "RegularEnumExcludes";
+ SymbolFlags[SymbolFlags["ConstEnumExcludes"] = 899967] = "ConstEnumExcludes";
+ SymbolFlags[SymbolFlags["ValueModuleExcludes"] = 110735] = "ValueModuleExcludes";
+ SymbolFlags[SymbolFlags["NamespaceModuleExcludes"] = 0] = "NamespaceModuleExcludes";
+ SymbolFlags[SymbolFlags["MethodExcludes"] = 103359] = "MethodExcludes";
+ SymbolFlags[SymbolFlags["GetAccessorExcludes"] = 46015] = "GetAccessorExcludes";
+ SymbolFlags[SymbolFlags["SetAccessorExcludes"] = 78783] = "SetAccessorExcludes";
+ SymbolFlags[SymbolFlags["AccessorExcludes"] = 13247] = "AccessorExcludes";
+ SymbolFlags[SymbolFlags["TypeParameterExcludes"] = 526824] = "TypeParameterExcludes";
+ SymbolFlags[SymbolFlags["TypeAliasExcludes"] = 788968] = "TypeAliasExcludes";
+ SymbolFlags[SymbolFlags["AliasExcludes"] = 2097152] = "AliasExcludes";
+ SymbolFlags[SymbolFlags["ModuleMember"] = 2623475] = "ModuleMember";
+ SymbolFlags[SymbolFlags["ExportHasLocal"] = 944] = "ExportHasLocal";
+ SymbolFlags[SymbolFlags["BlockScoped"] = 418] = "BlockScoped";
+ SymbolFlags[SymbolFlags["PropertyOrAccessor"] = 98308] = "PropertyOrAccessor";
+ SymbolFlags[SymbolFlags["ClassMember"] = 106500] = "ClassMember";
+ SymbolFlags[SymbolFlags["ExportSupportsDefaultModifier"] = 112] = "ExportSupportsDefaultModifier";
+ SymbolFlags[SymbolFlags["ExportDoesNotSupportDefaultModifier"] = -113] = "ExportDoesNotSupportDefaultModifier";
+ SymbolFlags[SymbolFlags["Classifiable"] = 2885600] = "Classifiable";
+ SymbolFlags[SymbolFlags["LateBindingContainer"] = 6256] = "LateBindingContainer";
+})(SymbolFlags || (SymbolFlags = {}));
diff --git a/_packages/api/src/typeFlags.enum.ts b/_packages/api/src/typeFlags.enum.ts
new file mode 100644
index 0000000000..1c57bd0c31
--- /dev/null
+++ b/_packages/api/src/typeFlags.enum.ts
@@ -0,0 +1,32 @@
+export enum TypeFlags {
+ None = 0,
+ Any = 1 << 0,
+ Unknown = 1 << 1,
+ Undefined = 1 << 2,
+ Null = 1 << 3,
+ Void = 1 << 4,
+ String = 1 << 5,
+ Number = 1 << 6,
+ BigInt = 1 << 7,
+ Boolean = 1 << 8,
+ ESSymbol = 1 << 9,
+ StringLiteral = 1 << 10,
+ NumberLiteral = 1 << 11,
+ BigIntLiteral = 1 << 12,
+ BooleanLiteral = 1 << 13,
+ UniqueESSymbol = 1 << 14,
+ EnumLiteral = 1 << 15,
+ Enum = 1 << 16,
+ Never = 1 << 17,
+ TypeParameter = 1 << 18,
+ Object = 1 << 19,
+ Union = 1 << 20,
+ Intersection = 1 << 21,
+ Index = 1 << 22,
+ IndexedAccess = 1 << 23,
+ Conditional = 1 << 24,
+ Substitution = 1 << 25,
+ NonPrimitive = 1 << 26,
+ TemplateLiteral = 1 << 27,
+ StringMapping = 1 << 28,
+}
diff --git a/_packages/api/src/typeFlags.ts b/_packages/api/src/typeFlags.ts
new file mode 100644
index 0000000000..a581948cb0
--- /dev/null
+++ b/_packages/api/src/typeFlags.ts
@@ -0,0 +1,33 @@
+export var TypeFlags: any;
+(function (TypeFlags) {
+ TypeFlags[TypeFlags["None"] = 0] = "None";
+ TypeFlags[TypeFlags["Any"] = 1] = "Any";
+ TypeFlags[TypeFlags["Unknown"] = 2] = "Unknown";
+ TypeFlags[TypeFlags["Undefined"] = 4] = "Undefined";
+ TypeFlags[TypeFlags["Null"] = 8] = "Null";
+ TypeFlags[TypeFlags["Void"] = 16] = "Void";
+ TypeFlags[TypeFlags["String"] = 32] = "String";
+ TypeFlags[TypeFlags["Number"] = 64] = "Number";
+ TypeFlags[TypeFlags["BigInt"] = 128] = "BigInt";
+ TypeFlags[TypeFlags["Boolean"] = 256] = "Boolean";
+ TypeFlags[TypeFlags["ESSymbol"] = 512] = "ESSymbol";
+ TypeFlags[TypeFlags["StringLiteral"] = 1024] = "StringLiteral";
+ TypeFlags[TypeFlags["NumberLiteral"] = 2048] = "NumberLiteral";
+ TypeFlags[TypeFlags["BigIntLiteral"] = 4096] = "BigIntLiteral";
+ TypeFlags[TypeFlags["BooleanLiteral"] = 8192] = "BooleanLiteral";
+ TypeFlags[TypeFlags["UniqueESSymbol"] = 16384] = "UniqueESSymbol";
+ TypeFlags[TypeFlags["EnumLiteral"] = 32768] = "EnumLiteral";
+ TypeFlags[TypeFlags["Enum"] = 65536] = "Enum";
+ TypeFlags[TypeFlags["Never"] = 131072] = "Never";
+ TypeFlags[TypeFlags["TypeParameter"] = 262144] = "TypeParameter";
+ TypeFlags[TypeFlags["Object"] = 524288] = "Object";
+ TypeFlags[TypeFlags["Union"] = 1048576] = "Union";
+ TypeFlags[TypeFlags["Intersection"] = 2097152] = "Intersection";
+ TypeFlags[TypeFlags["Index"] = 4194304] = "Index";
+ TypeFlags[TypeFlags["IndexedAccess"] = 8388608] = "IndexedAccess";
+ TypeFlags[TypeFlags["Conditional"] = 16777216] = "Conditional";
+ TypeFlags[TypeFlags["Substitution"] = 33554432] = "Substitution";
+ TypeFlags[TypeFlags["NonPrimitive"] = 67108864] = "NonPrimitive";
+ TypeFlags[TypeFlags["TemplateLiteral"] = 134217728] = "TemplateLiteral";
+ TypeFlags[TypeFlags["StringMapping"] = 268435456] = "StringMapping";
+})(TypeFlags || (TypeFlags = {}));
diff --git a/_packages/api/test/api.bench.ts b/_packages/api/test/api.bench.ts
new file mode 100644
index 0000000000..11da280dee
--- /dev/null
+++ b/_packages/api/test/api.bench.ts
@@ -0,0 +1,303 @@
+import {
+ API,
+ type Project,
+} from "@typescript/api";
+import {
+ type FileSystem,
+ type FileSystemEntries,
+} from "@typescript/api/fs";
+import {
+ type Node,
+ type SourceFile,
+ SyntaxKind,
+} from "@typescript/ast";
+import fs, { existsSync } from "node:fs";
+import path from "node:path";
+import { fileURLToPath } from "node:url";
+import { Bench } from "tinybench";
+import ts from "typescript";
+
+const isMain = process.argv[1] === fileURLToPath(import.meta.url);
+if (isMain) {
+ await runBenchmarks();
+}
+
+export async function runBenchmarks(singleIteration?: boolean) {
+ const repoRoot = fileURLToPath(new URL("../../../", import.meta.url).toString());
+ if (!existsSync(path.join(repoRoot, "_submodules/TypeScript/src/compiler"))) {
+ console.warn("Warning: TypeScript submodule is not cloned; skipping benchmarks.");
+ return;
+ }
+
+ const bench = new Bench({
+ name: "Sync API",
+ teardown,
+ ...singleIteration ? {
+ iterations: 1,
+ warmup: false,
+ time: 0,
+ } : undefined,
+ });
+
+ let api: API;
+ let project: Project;
+ let tsProgram: ts.Program;
+ let file: SourceFile;
+ let tsFile: ts.SourceFile;
+
+ const programIdentifierCount = (() => {
+ spawnAPI();
+ loadProject();
+ getProgramTS();
+ let count = 0;
+ file!.forEachChild(function visit(node) {
+ if (node.kind === SyntaxKind.Identifier) {
+ count++;
+ }
+ node.forEachChild(visit);
+ });
+ teardown();
+ return count;
+ })();
+
+ const SMALL_STRING = "ping";
+ const LARGE_STRING = "a".repeat(1_000_000);
+ const SMALL_UINT8_ARRAY = new Uint8Array([1, 2, 3, 4]);
+ const LARGE_UINT8_ARRAY = new Uint8Array(1_000_000);
+
+ bench
+ .add("spawn API", () => {
+ spawnAPI();
+ })
+ .add("echo (small string)", () => {
+ api.echo(SMALL_STRING);
+ }, { beforeAll: spawnAPI })
+ .add("echo (large string)", () => {
+ api.echo(LARGE_STRING);
+ }, { beforeAll: spawnAPI })
+ .add("echo (small Uint8Array)", () => {
+ api.echoBinary(SMALL_UINT8_ARRAY);
+ }, { beforeAll: spawnAPI })
+ .add("echo (large Uint8Array)", () => {
+ api.echoBinary(LARGE_UINT8_ARRAY);
+ }, { beforeAll: spawnAPI })
+ .add("load project", () => {
+ loadProject();
+ }, { beforeAll: spawnAPI })
+ .add("load project (client FS)", () => {
+ loadProject();
+ }, { beforeAll: spawnAPIHosted })
+ .add("TS - load project", () => {
+ tsCreateProgram();
+ })
+ .add("transfer debug.ts", () => {
+ getDebugTS();
+ }, { beforeAll: all(spawnAPI, loadProject) })
+ .add("transfer program.ts", () => {
+ getProgramTS();
+ }, { beforeAll: all(spawnAPI, loadProject) })
+ .add("transfer checker.ts", () => {
+ getCheckerTS();
+ }, { beforeAll: all(spawnAPI, loadProject) })
+ .add("materialize program.ts", () => {
+ file.forEachChild(function visit(node) {
+ node.forEachChild(visit);
+ });
+ }, { beforeAll: all(spawnAPI, loadProject, getProgramTS) })
+ .add("materialize checker.ts", () => {
+ file.forEachChild(function visit(node) {
+ node.forEachChild(visit);
+ });
+ }, { beforeAll: all(spawnAPI, loadProject, getCheckerTS) })
+ .add("getSymbolAtPosition - one location", () => {
+ project.getSymbolAtPosition("program.ts", 8895);
+ }, { beforeAll: all(spawnAPI, loadProject, createChecker) })
+ .add("TS - getSymbolAtPosition - one location", () => {
+ tsProgram.getTypeChecker().getSymbolAtLocation(
+ // @ts-ignore internal API
+ ts.getTokenAtPosition(tsFile, 8895),
+ );
+ }, { beforeAll: all(tsCreateProgram, tsCreateChecker, tsGetProgramTS) })
+ .add(`getSymbolAtPosition - ${programIdentifierCount} identifiers`, () => {
+ file.forEachChild(function visit(node) {
+ if (node.kind === SyntaxKind.Identifier) {
+ project.getSymbolAtPosition("program.ts", node.pos);
+ }
+ node.forEachChild(visit);
+ });
+ }, { beforeAll: all(spawnAPI, loadProject, createChecker, getProgramTS) })
+ .add(`getSymbolAtPosition - ${programIdentifierCount} identifiers (batched)`, () => {
+ const positions: number[] = [];
+ file.forEachChild(function visit(node) {
+ if (node.kind === SyntaxKind.Identifier) {
+ positions.push(node.pos);
+ }
+ node.forEachChild(visit);
+ });
+ project.getSymbolAtPosition("program.ts", positions);
+ }, { beforeAll: all(spawnAPI, loadProject, createChecker, getProgramTS) })
+ .add(`getSymbolAtLocation - ${programIdentifierCount} identifiers`, () => {
+ file.forEachChild(function visit(node) {
+ if (node.kind === SyntaxKind.Identifier) {
+ project.getSymbolAtLocation(node);
+ }
+ node.forEachChild(visit);
+ });
+ }, { beforeAll: all(spawnAPI, loadProject, createChecker, getProgramTS) })
+ .add(`getSymbolAtLocation - ${programIdentifierCount} identifiers (batched)`, () => {
+ const nodes: Node[] = [];
+ file.forEachChild(function visit(node) {
+ if (node.kind === SyntaxKind.Identifier) {
+ nodes.push(node);
+ }
+ node.forEachChild(visit);
+ });
+ project.getSymbolAtLocation(nodes);
+ }, { beforeAll: all(spawnAPI, loadProject, createChecker, getProgramTS) })
+ .add(`TS - getSymbolAtLocation - ${programIdentifierCount} identifiers`, () => {
+ const checker = tsProgram.getTypeChecker();
+ tsFile.forEachChild(function visit(node) {
+ if (node.kind === ts.SyntaxKind.Identifier) {
+ checker.getSymbolAtLocation(node);
+ }
+ node.forEachChild(visit);
+ });
+ }, { beforeAll: all(tsCreateProgram, tsCreateChecker, tsGetProgramTS) });
+
+ await bench.run();
+ console.table(bench.table());
+
+ function spawnAPI() {
+ api = new API({
+ cwd: repoRoot,
+ tsserverPath: fileURLToPath(new URL(`../../../built/local/tsgo${process.platform === "win32" ? ".exe" : ""}`, import.meta.url).toString()),
+ });
+ }
+
+ function spawnAPIHosted() {
+ api = new API({
+ cwd: repoRoot,
+ tsserverPath: fileURLToPath(new URL(`../../../built/local/tsgo${process.platform === "win32" ? ".exe" : ""}`, import.meta.url).toString()),
+ fs: createNodeFileSystem(),
+ });
+ }
+
+ function loadProject() {
+ project = api.loadProject("_submodules/TypeScript/src/compiler/tsconfig.json");
+ }
+
+ function tsCreateProgram() {
+ const configFileName = fileURLToPath(new URL("../../../_submodules/TypeScript/src/compiler/tsconfig.json", import.meta.url).toString());
+ const configFile = ts.readConfigFile(configFileName, ts.sys.readFile);
+ const parsedCommandLine = ts.parseJsonConfigFileContent(configFile.config, ts.sys, path.dirname(configFileName));
+ const host = ts.createCompilerHost(parsedCommandLine.options);
+ tsProgram = ts.createProgram({
+ rootNames: parsedCommandLine.fileNames,
+ options: parsedCommandLine.options,
+ host,
+ });
+ }
+
+ function createChecker() {
+ // checker is created lazily, for measuring symbol time in a loop
+ // we need to create it first.
+ project.getSymbolAtPosition("core.ts", 0);
+ }
+
+ function tsCreateChecker() {
+ tsProgram.getTypeChecker();
+ }
+
+ function getDebugTS() {
+ file = project.getSourceFile("debug.ts")!;
+ }
+
+ function getProgramTS() {
+ file = project.getSourceFile("program.ts")!;
+ }
+
+ function tsGetProgramTS() {
+ tsFile = tsProgram.getSourceFile(fileURLToPath(new URL("../../../_submodules/TypeScript/src/compiler/program.ts", import.meta.url).toString()))!;
+ }
+
+ function getCheckerTS() {
+ file = project.getSourceFile("checker.ts")!;
+ }
+
+ function teardown() {
+ api?.close();
+ api = undefined!;
+ project = undefined!;
+ file = undefined!;
+ tsProgram = undefined!;
+ tsFile = undefined!;
+ }
+
+ function all(...fns: (() => void)[]) {
+ return () => {
+ for (const fn of fns) {
+ fn();
+ }
+ };
+ }
+
+ function createNodeFileSystem(): FileSystem {
+ return {
+ directoryExists: directoryName => {
+ try {
+ return fs.statSync(directoryName).isDirectory();
+ }
+ catch {
+ return false;
+ }
+ },
+ fileExists: fileName => {
+ try {
+ return fs.statSync(fileName).isFile();
+ }
+ catch {
+ return false;
+ }
+ },
+ readFile: fileName => {
+ try {
+ return fs.readFileSync(fileName, "utf8");
+ }
+ catch {
+ return undefined;
+ }
+ },
+ getAccessibleEntries: dirName => {
+ const entries: FileSystemEntries = {
+ files: [],
+ directories: [],
+ };
+ for (const entry of fs.readdirSync(dirName, { withFileTypes: true })) {
+ if (entry.isFile()) {
+ entries.files.push(entry.name);
+ }
+ else if (entry.isDirectory()) {
+ entries.directories.push(entry.name);
+ }
+ else if (entry.isSymbolicLink()) {
+ const fullName = path.join(dirName, entry.name);
+ try {
+ const stat = fs.statSync(fullName);
+ if (stat.isFile()) {
+ entries.files.push(entry.name);
+ }
+ else if (stat.isDirectory()) {
+ entries.directories.push(entry.name);
+ }
+ }
+ catch {
+ // Ignore errors
+ }
+ }
+ }
+ return entries;
+ },
+ realpath: fs.realpathSync,
+ };
+ }
+}
diff --git a/_packages/api/test/api.test.ts b/_packages/api/test/api.test.ts
new file mode 100644
index 0000000000..846b44d604
--- /dev/null
+++ b/_packages/api/test/api.test.ts
@@ -0,0 +1,164 @@
+import {
+ API,
+ SymbolFlags,
+ TypeFlags,
+} from "@typescript/api";
+import { createVirtualFileSystem } from "@typescript/api/fs";
+import {
+ cast,
+ isImportDeclaration,
+ isNamedImports,
+ isTemplateHead,
+ isTemplateMiddle,
+ isTemplateTail,
+} from "@typescript/ast";
+import assert from "node:assert";
+import {
+ describe,
+ test,
+} from "node:test";
+import { fileURLToPath } from "node:url";
+import { runBenchmarks } from "./api.bench.ts";
+
+const defaultFiles = {
+ "/tsconfig.json": "{}",
+ "/src/index.ts": `import { foo } from './foo';`,
+ "/src/foo.ts": `export const foo = 42;`,
+};
+
+describe("API", () => {
+ test("parseConfigFile", () => {
+ const api = spawnAPI();
+ const config = api.parseConfigFile("/tsconfig.json");
+ assert.deepEqual(config.fileNames, ["/src/index.ts", "/src/foo.ts"]);
+ assert.deepEqual(config.options, { configFilePath: "/tsconfig.json" });
+ });
+});
+
+describe("Project", () => {
+ test("getSymbolAtPosition", () => {
+ const api = spawnAPI();
+ const project = api.loadProject("/tsconfig.json");
+ const symbol = project.getSymbolAtPosition("/src/index.ts", 9);
+ assert.ok(symbol);
+ assert.equal(symbol.name, "foo");
+ assert.ok(symbol.flags & SymbolFlags.Alias);
+ });
+
+ test("getSymbolAtLocation", () => {
+ const api = spawnAPI();
+ const project = api.loadProject("/tsconfig.json");
+ const sourceFile = project.getSourceFile("/src/index.ts");
+ assert.ok(sourceFile);
+ const node = cast(
+ cast(sourceFile.statements[0], isImportDeclaration).importClause?.namedBindings,
+ isNamedImports,
+ ).elements[0].name;
+ assert.ok(node);
+ const symbol = project.getSymbolAtLocation(node);
+ assert.ok(symbol);
+ assert.equal(symbol.name, "foo");
+ assert.ok(symbol.flags & SymbolFlags.Alias);
+ });
+
+ test("getTypeOfSymbol", () => {
+ const api = spawnAPI();
+ const project = api.loadProject("/tsconfig.json");
+ const symbol = project.getSymbolAtPosition("/src/index.ts", 9);
+ assert.ok(symbol);
+ const type = project.getTypeOfSymbol(symbol);
+ assert.ok(type);
+ assert.ok(type.flags & TypeFlags.NumberLiteral);
+ });
+});
+
+describe("SourceFile", () => {
+ test("file properties", () => {
+ const api = spawnAPI();
+ const project = api.loadProject("/tsconfig.json");
+ const sourceFile = project.getSourceFile("/src/index.ts");
+
+ assert.ok(sourceFile);
+ assert.equal(sourceFile.text, defaultFiles["/src/index.ts"]);
+ assert.equal(sourceFile.fileName, "/src/index.ts");
+ });
+
+ test("extended data", () => {
+ const api = spawnAPI();
+ const project = api.loadProject("/tsconfig.json");
+ const sourceFile = project.getSourceFile("/src/index.ts");
+
+ assert.ok(sourceFile);
+ let nodeCount = 1;
+ sourceFile.forEachChild(function visit(node) {
+ if (isTemplateHead(node)) {
+ assert.equal(node.text, "head ");
+ assert.equal(node.rawText, "head ");
+ assert.equal(node.templateFlags, 0);
+ }
+ else if (isTemplateMiddle(node)) {
+ assert.equal(node.text, "middle");
+ assert.equal(node.rawText, "middle");
+ assert.equal(node.templateFlags, 0);
+ }
+ else if (isTemplateTail(node)) {
+ assert.equal(node.text, " tail");
+ assert.equal(node.rawText, " tail");
+ assert.equal(node.templateFlags, 0);
+ }
+ nodeCount++;
+ node.forEachChild(visit);
+ });
+ assert.equal(nodeCount, 7);
+ });
+});
+
+test("Object equality", () => {
+ const api = spawnAPI();
+ const project = api.loadProject("/tsconfig.json");
+ assert.strictEqual(project, api.loadProject("/tsconfig.json"));
+ assert.strictEqual(
+ project.getSymbolAtPosition("/src/index.ts", 9),
+ project.getSymbolAtPosition("/src/index.ts", 10),
+ );
+});
+
+test("Dispose", () => {
+ const api = spawnAPI();
+ const project = api.loadProject("/tsconfig.json");
+ const symbol = project.getSymbolAtPosition("/src/index.ts", 9);
+ assert.ok(symbol);
+ assert.ok(symbol.isDisposed() === false);
+ symbol.dispose();
+ assert.ok(symbol.isDisposed() === true);
+ assert.throws(() => {
+ project.getTypeOfSymbol(symbol);
+ }, {
+ name: "Error",
+ message: "Symbol is disposed",
+ });
+
+ const symbol2 = project.getSymbolAtPosition("/src/index.ts", 9);
+ assert.ok(symbol2);
+ assert.notStrictEqual(symbol, symbol2);
+ // @ts-ignore private API
+ api.client.request("release", symbol2.id);
+ assert.throws(() => {
+ project.getTypeOfSymbol(symbol2);
+ }, {
+ name: "Error",
+ message: `symbol "${symbol.id}" not found`,
+ });
+});
+
+test("Benchmarks", async () => {
+ await runBenchmarks(/*singleIteration*/ true);
+});
+
+function spawnAPI(files: Record = defaultFiles) {
+ return new API({
+ cwd: fileURLToPath(new URL("../../../", import.meta.url).toString()),
+ tsserverPath: fileURLToPath(new URL(`../../../built/local/tsgo${process.platform === "win32" ? ".exe" : ""}`, import.meta.url).toString()),
+ fs: createVirtualFileSystem(files),
+ });
+}
diff --git a/_packages/api/test/tsconfig.json b/_packages/api/test/tsconfig.json
new file mode 100644
index 0000000000..b1a688b3b8
--- /dev/null
+++ b/_packages/api/test/tsconfig.json
@@ -0,0 +1,6 @@
+{
+ "extends": "../tsconfig.dev.json",
+ "references": [
+ { "path": ".." }
+ ]
+}
diff --git a/_packages/api/tsconfig.base.json b/_packages/api/tsconfig.base.json
new file mode 100644
index 0000000000..c99f883b56
--- /dev/null
+++ b/_packages/api/tsconfig.base.json
@@ -0,0 +1,9 @@
+{
+ "compilerOptions": {
+ "strict": true,
+ "composite": true,
+ "forceConsistentCasingInFileNames": true,
+ "rewriteRelativeImportExtensions": true,
+ "verbatimModuleSyntax": true
+ }
+}
diff --git a/_packages/api/tsconfig.dev.json b/_packages/api/tsconfig.dev.json
new file mode 100644
index 0000000000..d3b396340e
--- /dev/null
+++ b/_packages/api/tsconfig.dev.json
@@ -0,0 +1,10 @@
+{
+ "extends": "./tsconfig.base.json",
+ "compilerOptions": {
+ "module": "nodenext",
+ "strict": true,
+ "noEmit": true,
+ "verbatimModuleSyntax": true,
+ "allowImportingTsExtensions": true
+ }
+}
diff --git a/_packages/api/tsconfig.json b/_packages/api/tsconfig.json
new file mode 100644
index 0000000000..b3b68a0719
--- /dev/null
+++ b/_packages/api/tsconfig.json
@@ -0,0 +1,16 @@
+{
+ "extends": "./tsconfig.base.json",
+ "compilerOptions": {
+ "module": "node16",
+ "isolatedDeclarations": true,
+ "sourceMap": true,
+ "declaration": true,
+ "declarationMap": true,
+ "rootDir": "src",
+ "outDir": "dist"
+ },
+ "include": ["src"],
+ "references": [
+ { "path": "../ast" }
+ ]
+}
diff --git a/_packages/ast/package.json b/_packages/ast/package.json
new file mode 100644
index 0000000000..0bddc1cdba
--- /dev/null
+++ b/_packages/ast/package.json
@@ -0,0 +1,39 @@
+{
+ "private": true,
+ "name": "@typescript/ast",
+ "version": "1.0.0",
+ "description": "TypeScript AST definitions",
+ "type": "module",
+ "imports": {
+ "#syntaxKind": {
+ "@typescript/source": {
+ "types": "./src/syntaxKind.enum.ts",
+ "default": "./src/syntaxKind.ts"
+ },
+ "types": "./dist/syntaxKind.enum.d.ts",
+ "default": "./dist/syntaxKind.js"
+ },
+ "#tokenFlags": {
+ "@typescript/source": {
+ "types": "./src/tokenFlags.enum.ts",
+ "default": "./src/tokenFlags.ts"
+ },
+ "types": "./dist/tokenFlags.enum.d.ts",
+ "default": "./dist/tokenFlags.js"
+ }
+ },
+ "exports": {
+ ".": {
+ "@typescript/source": "./src/index.ts",
+ "default": "./dist/index.js"
+ },
+ "./is": {
+ "@typescript/source": "./src/is.ts",
+ "default": "./dist/is.js"
+ },
+ "./utils": {
+ "@typescript/source": "./src/utils.ts",
+ "default": "./dist/utils.js"
+ }
+ }
+}
diff --git a/_packages/ast/src/index.ts b/_packages/ast/src/index.ts
new file mode 100644
index 0000000000..74af64f5dd
--- /dev/null
+++ b/_packages/ast/src/index.ts
@@ -0,0 +1,4 @@
+export { SyntaxKind } from "#syntaxKind";
+export * from "./is.ts";
+export * from "./nodes.ts";
+export * from "./utils.ts";
diff --git a/_packages/ast/src/is.ts b/_packages/ast/src/is.ts
new file mode 100644
index 0000000000..d9563838f5
--- /dev/null
+++ b/_packages/ast/src/is.ts
@@ -0,0 +1,1115 @@
+import { SyntaxKind } from "#syntaxKind";
+import type {
+ AbstractKeyword,
+ AccessorKeyword,
+ ArrayBindingPattern,
+ ArrayLiteralExpression,
+ ArrayTypeNode,
+ ArrowFunction,
+ AsExpression,
+ AssertsKeyword,
+ AsteriskToken,
+ AsyncKeyword,
+ AwaitExpression,
+ AwaitKeyword,
+ BigIntLiteral,
+ BinaryExpression,
+ BindingElement,
+ Block,
+ BreakStatement,
+ CallExpression,
+ CallSignatureDeclaration,
+ CaseBlock,
+ CaseClause,
+ CaseKeyword,
+ CatchClause,
+ ClassDeclaration,
+ ClassExpression,
+ ClassStaticBlockDeclaration,
+ ColonToken,
+ CommaListExpression,
+ ComputedPropertyName,
+ ConditionalExpression,
+ ConditionalTypeNode,
+ ConstructorDeclaration,
+ ConstructorTypeNode,
+ ConstructSignatureDeclaration,
+ ContinueStatement,
+ DebuggerStatement,
+ Decorator,
+ DefaultClause,
+ DefaultKeyword,
+ DeleteExpression,
+ DoStatement,
+ DotDotDotToken,
+ ElementAccessExpression,
+ EmptyStatement,
+ EnumDeclaration,
+ EnumMember,
+ EqualsGreaterThanToken,
+ ExclamationToken,
+ ExportAssignment,
+ ExportDeclaration,
+ ExportKeyword,
+ ExportSpecifier,
+ ExpressionStatement,
+ ExpressionWithTypeArguments,
+ ExternalModuleReference,
+ ForInStatement,
+ ForOfStatement,
+ ForStatement,
+ FunctionDeclaration,
+ FunctionExpression,
+ FunctionTypeNode,
+ GetAccessorDeclaration,
+ HeritageClause,
+ Identifier,
+ IfStatement,
+ ImportAttribute,
+ ImportAttributes,
+ ImportClause,
+ ImportDeclaration,
+ ImportEqualsDeclaration,
+ ImportExpression,
+ ImportSpecifier,
+ ImportTypeNode,
+ IndexedAccessTypeNode,
+ IndexSignatureDeclaration,
+ InferTypeNode,
+ InterfaceDeclaration,
+ IntersectionTypeNode,
+ JSDoc,
+ JSDocAllType,
+ JSDocAugmentsTag,
+ JSDocCallbackTag,
+ JSDocDeprecatedTag,
+ JSDocImplementsTag,
+ JSDocImportTag,
+ JSDocLink,
+ JSDocLinkCode,
+ JSDocLinkPlain,
+ JSDocMemberName,
+ JSDocNameReference,
+ JSDocNonNullableType,
+ JSDocNullableType,
+ JSDocOptionalType,
+ JSDocOverloadTag,
+ JSDocOverrideTag,
+ JSDocParameterTag,
+ JSDocPrivateTag,
+ JSDocPropertyTag,
+ JSDocProtectedTag,
+ JSDocPublicTag,
+ JSDocReadonlyTag,
+ JSDocReturnTag,
+ JSDocSatisfiesTag,
+ JSDocSeeTag,
+ JSDocSignature,
+ JSDocTemplateTag,
+ JSDocThisTag,
+ JSDocTypedefTag,
+ JSDocTypeExpression,
+ JSDocTypeLiteral,
+ JSDocTypeTag,
+ JSDocUnknownTag,
+ JSDocVariadicType,
+ JsxAttribute,
+ JsxAttributes,
+ JsxClosingElement,
+ JsxClosingFragment,
+ JsxElement,
+ JsxExpression,
+ JsxFragment,
+ JsxNamespacedName,
+ JsxOpeningElement,
+ JsxOpeningFragment,
+ JsxSelfClosingElement,
+ JsxSpreadAttribute,
+ JsxText,
+ LabeledStatement,
+ LiteralTypeNode,
+ MappedTypeNode,
+ MetaProperty,
+ MethodDeclaration,
+ MethodSignature,
+ MinusToken,
+ ModuleBlock,
+ ModuleDeclaration,
+ ModuleExportName,
+ NamedExports,
+ NamedImports,
+ NamedTupleMember,
+ NamespaceExport,
+ NamespaceExportDeclaration,
+ NamespaceImport,
+ NewExpression,
+ Node,
+ NonNullExpression,
+ NoSubstitutionTemplateLiteral,
+ NumericLiteral,
+ ObjectBindingPattern,
+ ObjectLiteralExpression,
+ OmittedExpression,
+ OptionalTypeNode,
+ OverrideKeyword,
+ ParameterDeclaration,
+ ParenthesizedExpression,
+ ParenthesizedTypeNode,
+ PartiallyEmittedExpression,
+ PlusToken,
+ PostfixUnaryExpression,
+ PrefixUnaryExpression,
+ PrivateIdentifier,
+ PropertyAccessExpression,
+ PropertyAssignment,
+ PropertyDeclaration,
+ PropertySignature,
+ QualifiedName,
+ QuestionDotToken,
+ QuestionToken,
+ ReadonlyKeyword,
+ RegularExpressionLiteral,
+ RestTypeNode,
+ ReturnStatement,
+ SatisfiesExpression,
+ SemicolonClassElement,
+ SetAccessorDeclaration,
+ ShorthandPropertyAssignment,
+ SourceFile,
+ SpreadAssignment,
+ SpreadElement,
+ StaticKeyword,
+ StringLiteral,
+ SuperExpression,
+ SwitchStatement,
+ TaggedTemplateExpression,
+ TemplateExpression,
+ TemplateHead,
+ TemplateLiteralTypeNode,
+ TemplateLiteralTypeSpan,
+ TemplateMiddle,
+ TemplateSpan,
+ TemplateTail,
+ ThisTypeNode,
+ ThrowStatement,
+ Token,
+ TryStatement,
+ TupleTypeNode,
+ TypeAliasDeclaration,
+ TypeAssertion,
+ TypeLiteralNode,
+ TypeOfExpression,
+ TypeOperatorNode,
+ TypeParameterDeclaration,
+ TypePredicateNode,
+ TypeQueryNode,
+ TypeReferenceNode,
+ UnionTypeNode,
+ VariableDeclaration,
+ VariableDeclarationList,
+ VariableStatement,
+ VoidExpression,
+ WhileStatement,
+ WithStatement,
+ YieldExpression,
+} from "./nodes.ts";
+
+// Literals
+
+export function isNumericLiteral(node: Node): node is NumericLiteral {
+ return node.kind === SyntaxKind.NumericLiteral;
+}
+
+export function isBigIntLiteral(node: Node): node is BigIntLiteral {
+ return node.kind === SyntaxKind.BigIntLiteral;
+}
+
+export function isStringLiteral(node: Node): node is StringLiteral {
+ return node.kind === SyntaxKind.StringLiteral;
+}
+
+export function isJsxText(node: Node): node is JsxText {
+ return node.kind === SyntaxKind.JsxText;
+}
+
+export function isRegularExpressionLiteral(node: Node): node is RegularExpressionLiteral {
+ return node.kind === SyntaxKind.RegularExpressionLiteral;
+}
+
+export function isNoSubstitutionTemplateLiteral(node: Node): node is NoSubstitutionTemplateLiteral {
+ return node.kind === SyntaxKind.NoSubstitutionTemplateLiteral;
+}
+
+// Pseudo-literals
+
+export function isTemplateHead(node: Node): node is TemplateHead {
+ return node.kind === SyntaxKind.TemplateHead;
+}
+
+export function isTemplateMiddle(node: Node): node is TemplateMiddle {
+ return node.kind === SyntaxKind.TemplateMiddle;
+}
+
+export function isTemplateTail(node: Node): node is TemplateTail {
+ return node.kind === SyntaxKind.TemplateTail;
+}
+
+// Punctuation
+
+export function isDotDotDotToken(node: Node): node is DotDotDotToken {
+ return node.kind === SyntaxKind.DotDotDotToken;
+}
+
+/** @internal */
+export function isCommaToken(node: Node): node is Token {
+ return node.kind === SyntaxKind.CommaToken;
+}
+
+export function isPlusToken(node: Node): node is PlusToken {
+ return node.kind === SyntaxKind.PlusToken;
+}
+
+export function isMinusToken(node: Node): node is MinusToken {
+ return node.kind === SyntaxKind.MinusToken;
+}
+
+export function isAsteriskToken(node: Node): node is AsteriskToken {
+ return node.kind === SyntaxKind.AsteriskToken;
+}
+
+export function isExclamationToken(node: Node): node is ExclamationToken {
+ return node.kind === SyntaxKind.ExclamationToken;
+}
+
+export function isQuestionToken(node: Node): node is QuestionToken {
+ return node.kind === SyntaxKind.QuestionToken;
+}
+
+export function isColonToken(node: Node): node is ColonToken {
+ return node.kind === SyntaxKind.ColonToken;
+}
+
+export function isQuestionDotToken(node: Node): node is QuestionDotToken {
+ return node.kind === SyntaxKind.QuestionDotToken;
+}
+
+export function isEqualsGreaterThanToken(node: Node): node is EqualsGreaterThanToken {
+ return node.kind === SyntaxKind.EqualsGreaterThanToken;
+}
+
+// Identifiers
+
+export function isIdentifier(node: Node): node is Identifier {
+ return node.kind === SyntaxKind.Identifier;
+}
+
+export function isPrivateIdentifier(node: Node): node is PrivateIdentifier {
+ return node.kind === SyntaxKind.PrivateIdentifier;
+}
+
+// Reserved Words
+
+/** @internal */
+export function isExportModifier(node: Node): node is ExportKeyword {
+ return node.kind === SyntaxKind.ExportKeyword;
+}
+
+/** @internal */
+export function isDefaultModifier(node: Node): node is DefaultKeyword {
+ return node.kind === SyntaxKind.DefaultKeyword;
+}
+
+/** @internal */
+export function isAsyncModifier(node: Node): node is AsyncKeyword {
+ return node.kind === SyntaxKind.AsyncKeyword;
+}
+
+export function isAssertsKeyword(node: Node): node is AssertsKeyword {
+ return node.kind === SyntaxKind.AssertsKeyword;
+}
+
+export function isAwaitKeyword(node: Node): node is AwaitKeyword {
+ return node.kind === SyntaxKind.AwaitKeyword;
+}
+
+/** @internal */
+export function isReadonlyKeyword(node: Node): node is ReadonlyKeyword {
+ return node.kind === SyntaxKind.ReadonlyKeyword;
+}
+
+/** @internal */
+export function isStaticModifier(node: Node): node is StaticKeyword {
+ return node.kind === SyntaxKind.StaticKeyword;
+}
+
+/** @internal */
+export function isAbstractModifier(node: Node): node is AbstractKeyword {
+ return node.kind === SyntaxKind.AbstractKeyword;
+}
+
+/** @internal */
+export function isOverrideModifier(node: Node): node is OverrideKeyword {
+ return node.kind === SyntaxKind.OverrideKeyword;
+}
+
+/** @internal */
+export function isAccessorModifier(node: Node): node is AccessorKeyword {
+ return node.kind === SyntaxKind.AccessorKeyword;
+}
+
+/** @internal */
+export function isSuperKeyword(node: Node): node is SuperExpression {
+ return node.kind === SyntaxKind.SuperKeyword;
+}
+
+/** @internal */
+export function isImportKeyword(node: Node): node is ImportExpression {
+ return node.kind === SyntaxKind.ImportKeyword;
+}
+
+/** @internal */
+export function isCaseKeyword(node: Node): node is CaseKeyword {
+ return node.kind === SyntaxKind.CaseKeyword;
+}
+
+// Names
+
+export function isQualifiedName(node: Node): node is QualifiedName {
+ return node.kind === SyntaxKind.QualifiedName;
+}
+
+export function isComputedPropertyName(node: Node): node is ComputedPropertyName {
+ return node.kind === SyntaxKind.ComputedPropertyName;
+}
+
+// Signature elements
+
+export function isTypeParameterDeclaration(node: Node): node is TypeParameterDeclaration {
+ return node.kind === SyntaxKind.TypeParameter;
+}
+
+// TODO(rbuckton): Rename to 'isParameterDeclaration'
+export function isParameter(node: Node): node is ParameterDeclaration {
+ return node.kind === SyntaxKind.Parameter;
+}
+
+export function isDecorator(node: Node): node is Decorator {
+ return node.kind === SyntaxKind.Decorator;
+}
+
+// TypeMember
+
+export function isPropertySignature(node: Node): node is PropertySignature {
+ return node.kind === SyntaxKind.PropertySignature;
+}
+
+export function isPropertyDeclaration(node: Node): node is PropertyDeclaration {
+ return node.kind === SyntaxKind.PropertyDeclaration;
+}
+
+export function isMethodSignature(node: Node): node is MethodSignature {
+ return node.kind === SyntaxKind.MethodSignature;
+}
+
+export function isMethodDeclaration(node: Node): node is MethodDeclaration {
+ return node.kind === SyntaxKind.MethodDeclaration;
+}
+
+export function isClassStaticBlockDeclaration(node: Node): node is ClassStaticBlockDeclaration {
+ return node.kind === SyntaxKind.ClassStaticBlockDeclaration;
+}
+
+export function isConstructorDeclaration(node: Node): node is ConstructorDeclaration {
+ return node.kind === SyntaxKind.Constructor;
+}
+
+export function isGetAccessorDeclaration(node: Node): node is GetAccessorDeclaration {
+ return node.kind === SyntaxKind.GetAccessor;
+}
+
+export function isSetAccessorDeclaration(node: Node): node is SetAccessorDeclaration {
+ return node.kind === SyntaxKind.SetAccessor;
+}
+
+export function isCallSignatureDeclaration(node: Node): node is CallSignatureDeclaration {
+ return node.kind === SyntaxKind.CallSignature;
+}
+
+export function isConstructSignatureDeclaration(node: Node): node is ConstructSignatureDeclaration {
+ return node.kind === SyntaxKind.ConstructSignature;
+}
+
+export function isIndexSignatureDeclaration(node: Node): node is IndexSignatureDeclaration {
+ return node.kind === SyntaxKind.IndexSignature;
+}
+
+// Type
+
+export function isTypePredicateNode(node: Node): node is TypePredicateNode {
+ return node.kind === SyntaxKind.TypePredicate;
+}
+
+export function isTypeReferenceNode(node: Node): node is TypeReferenceNode {
+ return node.kind === SyntaxKind.TypeReference;
+}
+
+export function isFunctionTypeNode(node: Node): node is FunctionTypeNode {
+ return node.kind === SyntaxKind.FunctionType;
+}
+
+export function isConstructorTypeNode(node: Node): node is ConstructorTypeNode {
+ return node.kind === SyntaxKind.ConstructorType;
+}
+
+export function isTypeQueryNode(node: Node): node is TypeQueryNode {
+ return node.kind === SyntaxKind.TypeQuery;
+}
+
+export function isTypeLiteralNode(node: Node): node is TypeLiteralNode {
+ return node.kind === SyntaxKind.TypeLiteral;
+}
+
+export function isArrayTypeNode(node: Node): node is ArrayTypeNode {
+ return node.kind === SyntaxKind.ArrayType;
+}
+
+export function isTupleTypeNode(node: Node): node is TupleTypeNode {
+ return node.kind === SyntaxKind.TupleType;
+}
+
+export function isNamedTupleMember(node: Node): node is NamedTupleMember {
+ return node.kind === SyntaxKind.NamedTupleMember;
+}
+
+export function isOptionalTypeNode(node: Node): node is OptionalTypeNode {
+ return node.kind === SyntaxKind.OptionalType;
+}
+
+export function isRestTypeNode(node: Node): node is RestTypeNode {
+ return node.kind === SyntaxKind.RestType;
+}
+
+export function isUnionTypeNode(node: Node): node is UnionTypeNode {
+ return node.kind === SyntaxKind.UnionType;
+}
+
+export function isIntersectionTypeNode(node: Node): node is IntersectionTypeNode {
+ return node.kind === SyntaxKind.IntersectionType;
+}
+
+export function isConditionalTypeNode(node: Node): node is ConditionalTypeNode {
+ return node.kind === SyntaxKind.ConditionalType;
+}
+
+export function isInferTypeNode(node: Node): node is InferTypeNode {
+ return node.kind === SyntaxKind.InferType;
+}
+
+export function isParenthesizedTypeNode(node: Node): node is ParenthesizedTypeNode {
+ return node.kind === SyntaxKind.ParenthesizedType;
+}
+
+export function isThisTypeNode(node: Node): node is ThisTypeNode {
+ return node.kind === SyntaxKind.ThisType;
+}
+
+export function isTypeOperatorNode(node: Node): node is TypeOperatorNode {
+ return node.kind === SyntaxKind.TypeOperator;
+}
+
+export function isIndexedAccessTypeNode(node: Node): node is IndexedAccessTypeNode {
+ return node.kind === SyntaxKind.IndexedAccessType;
+}
+
+export function isMappedTypeNode(node: Node): node is MappedTypeNode {
+ return node.kind === SyntaxKind.MappedType;
+}
+
+export function isLiteralTypeNode(node: Node): node is LiteralTypeNode {
+ return node.kind === SyntaxKind.LiteralType;
+}
+
+export function isImportTypeNode(node: Node): node is ImportTypeNode {
+ return node.kind === SyntaxKind.ImportType;
+}
+
+export function isTemplateLiteralTypeSpan(node: Node): node is TemplateLiteralTypeSpan {
+ return node.kind === SyntaxKind.TemplateLiteralTypeSpan;
+}
+
+export function isTemplateLiteralTypeNode(node: Node): node is TemplateLiteralTypeNode {
+ return node.kind === SyntaxKind.TemplateLiteralType;
+}
+
+// Binding patterns
+
+export function isObjectBindingPattern(node: Node): node is ObjectBindingPattern {
+ return node.kind === SyntaxKind.ObjectBindingPattern;
+}
+
+export function isArrayBindingPattern(node: Node): node is ArrayBindingPattern {
+ return node.kind === SyntaxKind.ArrayBindingPattern;
+}
+
+export function isBindingElement(node: Node): node is BindingElement {
+ return node.kind === SyntaxKind.BindingElement;
+}
+
+// Expression
+
+export function isArrayLiteralExpression(node: Node): node is ArrayLiteralExpression {
+ return node.kind === SyntaxKind.ArrayLiteralExpression;
+}
+
+export function isObjectLiteralExpression(node: Node): node is ObjectLiteralExpression {
+ return node.kind === SyntaxKind.ObjectLiteralExpression;
+}
+
+export function isPropertyAccessExpression(node: Node): node is PropertyAccessExpression {
+ return node.kind === SyntaxKind.PropertyAccessExpression;
+}
+
+export function isElementAccessExpression(node: Node): node is ElementAccessExpression {
+ return node.kind === SyntaxKind.ElementAccessExpression;
+}
+
+export function isCallExpression(node: Node): node is CallExpression {
+ return node.kind === SyntaxKind.CallExpression;
+}
+
+export function isNewExpression(node: Node): node is NewExpression {
+ return node.kind === SyntaxKind.NewExpression;
+}
+
+export function isTaggedTemplateExpression(node: Node): node is TaggedTemplateExpression {
+ return node.kind === SyntaxKind.TaggedTemplateExpression;
+}
+
+export function isTypeAssertionExpression(node: Node): node is TypeAssertion {
+ return node.kind === SyntaxKind.TypeAssertionExpression;
+}
+
+export function isParenthesizedExpression(node: Node): node is ParenthesizedExpression {
+ return node.kind === SyntaxKind.ParenthesizedExpression;
+}
+
+export function isFunctionExpression(node: Node): node is FunctionExpression {
+ return node.kind === SyntaxKind.FunctionExpression;
+}
+
+export function isArrowFunction(node: Node): node is ArrowFunction {
+ return node.kind === SyntaxKind.ArrowFunction;
+}
+
+export function isDeleteExpression(node: Node): node is DeleteExpression {
+ return node.kind === SyntaxKind.DeleteExpression;
+}
+
+export function isTypeOfExpression(node: Node): node is TypeOfExpression {
+ return node.kind === SyntaxKind.TypeOfExpression;
+}
+
+export function isVoidExpression(node: Node): node is VoidExpression {
+ return node.kind === SyntaxKind.VoidExpression;
+}
+
+export function isAwaitExpression(node: Node): node is AwaitExpression {
+ return node.kind === SyntaxKind.AwaitExpression;
+}
+
+export function isPrefixUnaryExpression(node: Node): node is PrefixUnaryExpression {
+ return node.kind === SyntaxKind.PrefixUnaryExpression;
+}
+
+export function isPostfixUnaryExpression(node: Node): node is PostfixUnaryExpression {
+ return node.kind === SyntaxKind.PostfixUnaryExpression;
+}
+
+export function isBinaryExpression(node: Node): node is BinaryExpression {
+ return node.kind === SyntaxKind.BinaryExpression;
+}
+
+export function isConditionalExpression(node: Node): node is ConditionalExpression {
+ return node.kind === SyntaxKind.ConditionalExpression;
+}
+
+export function isTemplateExpression(node: Node): node is TemplateExpression {
+ return node.kind === SyntaxKind.TemplateExpression;
+}
+
+export function isYieldExpression(node: Node): node is YieldExpression {
+ return node.kind === SyntaxKind.YieldExpression;
+}
+
+export function isSpreadElement(node: Node): node is SpreadElement {
+ return node.kind === SyntaxKind.SpreadElement;
+}
+
+export function isClassExpression(node: Node): node is ClassExpression {
+ return node.kind === SyntaxKind.ClassExpression;
+}
+
+export function isOmittedExpression(node: Node): node is OmittedExpression {
+ return node.kind === SyntaxKind.OmittedExpression;
+}
+
+export function isExpressionWithTypeArguments(node: Node): node is ExpressionWithTypeArguments {
+ return node.kind === SyntaxKind.ExpressionWithTypeArguments;
+}
+
+export function isAsExpression(node: Node): node is AsExpression {
+ return node.kind === SyntaxKind.AsExpression;
+}
+
+export function isSatisfiesExpression(node: Node): node is SatisfiesExpression {
+ return node.kind === SyntaxKind.SatisfiesExpression;
+}
+
+export function isNonNullExpression(node: Node): node is NonNullExpression {
+ return node.kind === SyntaxKind.NonNullExpression;
+}
+
+export function isMetaProperty(node: Node): node is MetaProperty {
+ return node.kind === SyntaxKind.MetaProperty;
+}
+
+export function isPartiallyEmittedExpression(node: Node): node is PartiallyEmittedExpression {
+ return node.kind === SyntaxKind.PartiallyEmittedExpression;
+}
+
+export function isCommaListExpression(node: Node): node is CommaListExpression {
+ return node.kind === SyntaxKind.CommaListExpression;
+}
+
+// Misc
+
+export function isTemplateSpan(node: Node): node is TemplateSpan {
+ return node.kind === SyntaxKind.TemplateSpan;
+}
+
+export function isSemicolonClassElement(node: Node): node is SemicolonClassElement {
+ return node.kind === SyntaxKind.SemicolonClassElement;
+}
+
+// Elements
+
+export function isBlock(node: Node): node is Block {
+ return node.kind === SyntaxKind.Block;
+}
+
+export function isVariableStatement(node: Node): node is VariableStatement {
+ return node.kind === SyntaxKind.VariableStatement;
+}
+
+export function isEmptyStatement(node: Node): node is EmptyStatement {
+ return node.kind === SyntaxKind.EmptyStatement;
+}
+
+export function isExpressionStatement(node: Node): node is ExpressionStatement {
+ return node.kind === SyntaxKind.ExpressionStatement;
+}
+
+export function isIfStatement(node: Node): node is IfStatement {
+ return node.kind === SyntaxKind.IfStatement;
+}
+
+export function isDoStatement(node: Node): node is DoStatement {
+ return node.kind === SyntaxKind.DoStatement;
+}
+
+export function isWhileStatement(node: Node): node is WhileStatement {
+ return node.kind === SyntaxKind.WhileStatement;
+}
+
+export function isForStatement(node: Node): node is ForStatement {
+ return node.kind === SyntaxKind.ForStatement;
+}
+
+export function isForInStatement(node: Node): node is ForInStatement {
+ return node.kind === SyntaxKind.ForInStatement;
+}
+
+export function isForOfStatement(node: Node): node is ForOfStatement {
+ return node.kind === SyntaxKind.ForOfStatement;
+}
+
+export function isContinueStatement(node: Node): node is ContinueStatement {
+ return node.kind === SyntaxKind.ContinueStatement;
+}
+
+export function isBreakStatement(node: Node): node is BreakStatement {
+ return node.kind === SyntaxKind.BreakStatement;
+}
+
+export function isReturnStatement(node: Node): node is ReturnStatement {
+ return node.kind === SyntaxKind.ReturnStatement;
+}
+
+export function isWithStatement(node: Node): node is WithStatement {
+ return node.kind === SyntaxKind.WithStatement;
+}
+
+export function isSwitchStatement(node: Node): node is SwitchStatement {
+ return node.kind === SyntaxKind.SwitchStatement;
+}
+
+export function isLabeledStatement(node: Node): node is LabeledStatement {
+ return node.kind === SyntaxKind.LabeledStatement;
+}
+
+export function isThrowStatement(node: Node): node is ThrowStatement {
+ return node.kind === SyntaxKind.ThrowStatement;
+}
+
+export function isTryStatement(node: Node): node is TryStatement {
+ return node.kind === SyntaxKind.TryStatement;
+}
+
+export function isDebuggerStatement(node: Node): node is DebuggerStatement {
+ return node.kind === SyntaxKind.DebuggerStatement;
+}
+
+export function isVariableDeclaration(node: Node): node is VariableDeclaration {
+ return node.kind === SyntaxKind.VariableDeclaration;
+}
+
+export function isVariableDeclarationList(node: Node): node is VariableDeclarationList {
+ return node.kind === SyntaxKind.VariableDeclarationList;
+}
+
+export function isFunctionDeclaration(node: Node): node is FunctionDeclaration {
+ return node.kind === SyntaxKind.FunctionDeclaration;
+}
+
+export function isClassDeclaration(node: Node): node is ClassDeclaration {
+ return node.kind === SyntaxKind.ClassDeclaration;
+}
+
+export function isInterfaceDeclaration(node: Node): node is InterfaceDeclaration {
+ return node.kind === SyntaxKind.InterfaceDeclaration;
+}
+
+export function isTypeAliasDeclaration(node: Node): node is TypeAliasDeclaration {
+ return node.kind === SyntaxKind.TypeAliasDeclaration;
+}
+
+export function isEnumDeclaration(node: Node): node is EnumDeclaration {
+ return node.kind === SyntaxKind.EnumDeclaration;
+}
+
+export function isModuleDeclaration(node: Node): node is ModuleDeclaration {
+ return node.kind === SyntaxKind.ModuleDeclaration;
+}
+
+export function isModuleBlock(node: Node): node is ModuleBlock {
+ return node.kind === SyntaxKind.ModuleBlock;
+}
+
+export function isCaseBlock(node: Node): node is CaseBlock {
+ return node.kind === SyntaxKind.CaseBlock;
+}
+
+export function isNamespaceExportDeclaration(node: Node): node is NamespaceExportDeclaration {
+ return node.kind === SyntaxKind.NamespaceExportDeclaration;
+}
+
+export function isImportEqualsDeclaration(node: Node): node is ImportEqualsDeclaration {
+ return node.kind === SyntaxKind.ImportEqualsDeclaration;
+}
+
+export function isImportDeclaration(node: Node): node is ImportDeclaration {
+ return node.kind === SyntaxKind.ImportDeclaration;
+}
+
+export function isImportClause(node: Node): node is ImportClause {
+ return node.kind === SyntaxKind.ImportClause;
+}
+
+export function isImportAttributes(node: Node): node is ImportAttributes {
+ return node.kind === SyntaxKind.ImportAttributes;
+}
+
+export function isImportAttribute(node: Node): node is ImportAttribute {
+ return node.kind === SyntaxKind.ImportAttribute;
+}
+
+export function isNamespaceImport(node: Node): node is NamespaceImport {
+ return node.kind === SyntaxKind.NamespaceImport;
+}
+
+export function isNamespaceExport(node: Node): node is NamespaceExport {
+ return node.kind === SyntaxKind.NamespaceExport;
+}
+
+export function isNamedImports(node: Node): node is NamedImports {
+ return node.kind === SyntaxKind.NamedImports;
+}
+
+export function isImportSpecifier(node: Node): node is ImportSpecifier {
+ return node.kind === SyntaxKind.ImportSpecifier;
+}
+
+export function isExportAssignment(node: Node): node is ExportAssignment {
+ return node.kind === SyntaxKind.ExportAssignment;
+}
+
+export function isExportDeclaration(node: Node): node is ExportDeclaration {
+ return node.kind === SyntaxKind.ExportDeclaration;
+}
+
+export function isNamedExports(node: Node): node is NamedExports {
+ return node.kind === SyntaxKind.NamedExports;
+}
+
+export function isExportSpecifier(node: Node): node is ExportSpecifier {
+ return node.kind === SyntaxKind.ExportSpecifier;
+}
+
+export function isModuleExportName(node: Node): node is ModuleExportName {
+ return node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.StringLiteral;
+}
+
+// Module References
+
+export function isExternalModuleReference(node: Node): node is ExternalModuleReference {
+ return node.kind === SyntaxKind.ExternalModuleReference;
+}
+
+// JSX
+
+export function isJsxElement(node: Node): node is JsxElement {
+ return node.kind === SyntaxKind.JsxElement;
+}
+
+export function isJsxSelfClosingElement(node: Node): node is JsxSelfClosingElement {
+ return node.kind === SyntaxKind.JsxSelfClosingElement;
+}
+
+export function isJsxOpeningElement(node: Node): node is JsxOpeningElement {
+ return node.kind === SyntaxKind.JsxOpeningElement;
+}
+
+export function isJsxClosingElement(node: Node): node is JsxClosingElement {
+ return node.kind === SyntaxKind.JsxClosingElement;
+}
+
+export function isJsxFragment(node: Node): node is JsxFragment {
+ return node.kind === SyntaxKind.JsxFragment;
+}
+
+export function isJsxOpeningFragment(node: Node): node is JsxOpeningFragment {
+ return node.kind === SyntaxKind.JsxOpeningFragment;
+}
+
+export function isJsxClosingFragment(node: Node): node is JsxClosingFragment {
+ return node.kind === SyntaxKind.JsxClosingFragment;
+}
+
+export function isJsxAttribute(node: Node): node is JsxAttribute {
+ return node.kind === SyntaxKind.JsxAttribute;
+}
+
+export function isJsxAttributes(node: Node): node is JsxAttributes {
+ return node.kind === SyntaxKind.JsxAttributes;
+}
+
+export function isJsxSpreadAttribute(node: Node): node is JsxSpreadAttribute {
+ return node.kind === SyntaxKind.JsxSpreadAttribute;
+}
+
+export function isJsxExpression(node: Node): node is JsxExpression {
+ return node.kind === SyntaxKind.JsxExpression;
+}
+
+export function isJsxNamespacedName(node: Node): node is JsxNamespacedName {
+ return node.kind === SyntaxKind.JsxNamespacedName;
+}
+
+// Clauses
+
+export function isCaseClause(node: Node): node is CaseClause {
+ return node.kind === SyntaxKind.CaseClause;
+}
+
+export function isDefaultClause(node: Node): node is DefaultClause {
+ return node.kind === SyntaxKind.DefaultClause;
+}
+
+export function isHeritageClause(node: Node): node is HeritageClause {
+ return node.kind === SyntaxKind.HeritageClause;
+}
+
+export function isCatchClause(node: Node): node is CatchClause {
+ return node.kind === SyntaxKind.CatchClause;
+}
+
+// Property assignments
+
+export function isPropertyAssignment(node: Node): node is PropertyAssignment {
+ return node.kind === SyntaxKind.PropertyAssignment;
+}
+
+export function isShorthandPropertyAssignment(node: Node): node is ShorthandPropertyAssignment {
+ return node.kind === SyntaxKind.ShorthandPropertyAssignment;
+}
+
+export function isSpreadAssignment(node: Node): node is SpreadAssignment {
+ return node.kind === SyntaxKind.SpreadAssignment;
+}
+
+// Enum
+
+export function isEnumMember(node: Node): node is EnumMember {
+ return node.kind === SyntaxKind.EnumMember;
+}
+
+// Top-level nodes
+export function isSourceFile(node: Node): node is SourceFile {
+ return node.kind === SyntaxKind.SourceFile;
+}
+
+// TODO(rbuckton): isInputFiles
+
+// JSDoc Elements
+
+export function isJSDocTypeExpression(node: Node): node is JSDocTypeExpression {
+ return node.kind === SyntaxKind.JSDocTypeExpression;
+}
+
+export function isJSDocNameReference(node: Node): node is JSDocNameReference {
+ return node.kind === SyntaxKind.JSDocNameReference;
+}
+
+export function isJSDocMemberName(node: Node): node is JSDocMemberName {
+ return node.kind === SyntaxKind.JSDocMemberName;
+}
+
+export function isJSDocLink(node: Node): node is JSDocLink {
+ return node.kind === SyntaxKind.JSDocLink;
+}
+
+export function isJSDocLinkCode(node: Node): node is JSDocLinkCode {
+ return node.kind === SyntaxKind.JSDocLinkCode;
+}
+
+export function isJSDocLinkPlain(node: Node): node is JSDocLinkPlain {
+ return node.kind === SyntaxKind.JSDocLinkPlain;
+}
+
+export function isJSDocAllType(node: Node): node is JSDocAllType {
+ return node.kind === SyntaxKind.JSDocAllType;
+}
+
+export function isJSDocNullableType(node: Node): node is JSDocNullableType {
+ return node.kind === SyntaxKind.JSDocNullableType;
+}
+
+export function isJSDocNonNullableType(node: Node): node is JSDocNonNullableType {
+ return node.kind === SyntaxKind.JSDocNonNullableType;
+}
+
+export function isJSDocOptionalType(node: Node): node is JSDocOptionalType {
+ return node.kind === SyntaxKind.JSDocOptionalType;
+}
+
+export function isJSDocVariadicType(node: Node): node is JSDocVariadicType {
+ return node.kind === SyntaxKind.JSDocVariadicType;
+}
+
+export function isJSDoc(node: Node): node is JSDoc {
+ return node.kind === SyntaxKind.JSDoc;
+}
+
+export function isJSDocTypeLiteral(node: Node): node is JSDocTypeLiteral {
+ return node.kind === SyntaxKind.JSDocTypeLiteral;
+}
+
+export function isJSDocSignature(node: Node): node is JSDocSignature {
+ return node.kind === SyntaxKind.JSDocSignature;
+}
+
+// JSDoc Tags
+
+export function isJSDocAugmentsTag(node: Node): node is JSDocAugmentsTag {
+ return node.kind === SyntaxKind.JSDocAugmentsTag;
+}
+
+export function isJSDocCallbackTag(node: Node): node is JSDocCallbackTag {
+ return node.kind === SyntaxKind.JSDocCallbackTag;
+}
+
+export function isJSDocPublicTag(node: Node): node is JSDocPublicTag {
+ return node.kind === SyntaxKind.JSDocPublicTag;
+}
+
+export function isJSDocPrivateTag(node: Node): node is JSDocPrivateTag {
+ return node.kind === SyntaxKind.JSDocPrivateTag;
+}
+
+export function isJSDocProtectedTag(node: Node): node is JSDocProtectedTag {
+ return node.kind === SyntaxKind.JSDocProtectedTag;
+}
+
+export function isJSDocReadonlyTag(node: Node): node is JSDocReadonlyTag {
+ return node.kind === SyntaxKind.JSDocReadonlyTag;
+}
+
+export function isJSDocOverrideTag(node: Node): node is JSDocOverrideTag {
+ return node.kind === SyntaxKind.JSDocOverrideTag;
+}
+
+export function isJSDocOverloadTag(node: Node): node is JSDocOverloadTag {
+ return node.kind === SyntaxKind.JSDocOverloadTag;
+}
+
+export function isJSDocDeprecatedTag(node: Node): node is JSDocDeprecatedTag {
+ return node.kind === SyntaxKind.JSDocDeprecatedTag;
+}
+
+export function isJSDocSeeTag(node: Node): node is JSDocSeeTag {
+ return node.kind === SyntaxKind.JSDocSeeTag;
+}
+
+export function isJSDocParameterTag(node: Node): node is JSDocParameterTag {
+ return node.kind === SyntaxKind.JSDocParameterTag;
+}
+
+export function isJSDocReturnTag(node: Node): node is JSDocReturnTag {
+ return node.kind === SyntaxKind.JSDocReturnTag;
+}
+
+export function isJSDocThisTag(node: Node): node is JSDocThisTag {
+ return node.kind === SyntaxKind.JSDocThisTag;
+}
+
+export function isJSDocTypeTag(node: Node): node is JSDocTypeTag {
+ return node.kind === SyntaxKind.JSDocTypeTag;
+}
+
+export function isJSDocTemplateTag(node: Node): node is JSDocTemplateTag {
+ return node.kind === SyntaxKind.JSDocTemplateTag;
+}
+
+export function isJSDocTypedefTag(node: Node): node is JSDocTypedefTag {
+ return node.kind === SyntaxKind.JSDocTypedefTag;
+}
+
+export function isJSDocUnknownTag(node: Node): node is JSDocUnknownTag {
+ return node.kind === SyntaxKind.JSDocTag;
+}
+
+export function isJSDocPropertyTag(node: Node): node is JSDocPropertyTag {
+ return node.kind === SyntaxKind.JSDocPropertyTag;
+}
+
+export function isJSDocImplementsTag(node: Node): node is JSDocImplementsTag {
+ return node.kind === SyntaxKind.JSDocImplementsTag;
+}
+
+export function isJSDocSatisfiesTag(node: Node): node is JSDocSatisfiesTag {
+ return node.kind === SyntaxKind.JSDocSatisfiesTag;
+}
+
+export function isJSDocImportTag(node: Node): node is JSDocImportTag {
+ return node.kind === SyntaxKind.JSDocImportTag;
+}
diff --git a/_packages/ast/src/nodes.ts b/_packages/ast/src/nodes.ts
new file mode 100644
index 0000000000..a265f5545e
--- /dev/null
+++ b/_packages/ast/src/nodes.ts
@@ -0,0 +1,2414 @@
+import { SyntaxKind } from "#syntaxKind";
+import { TokenFlags } from "#tokenFlags";
+
+export interface TextRange {
+ pos: number;
+ end: number;
+}
+
+export interface Node extends ReadonlyTextRange {
+ readonly kind: SyntaxKind;
+ readonly parent: Node;
+}
+
+export interface SourceFile extends Node {
+ readonly kind: SyntaxKind.SourceFile;
+ readonly statements: NodeArray;
+ readonly text: string;
+ readonly fileName: string;
+}
+
+export type TriviaSyntaxKind =
+ | SyntaxKind.SingleLineCommentTrivia
+ | SyntaxKind.MultiLineCommentTrivia
+ | SyntaxKind.NewLineTrivia
+ | SyntaxKind.WhitespaceTrivia
+ | SyntaxKind.ConflictMarkerTrivia;
+
+export type LiteralSyntaxKind =
+ | SyntaxKind.NumericLiteral
+ | SyntaxKind.BigIntLiteral
+ | SyntaxKind.StringLiteral
+ | SyntaxKind.JsxText
+ | SyntaxKind.JsxTextAllWhiteSpaces
+ | SyntaxKind.RegularExpressionLiteral
+ | SyntaxKind.NoSubstitutionTemplateLiteral;
+
+export type PseudoLiteralSyntaxKind =
+ | SyntaxKind.TemplateHead
+ | SyntaxKind.TemplateMiddle
+ | SyntaxKind.TemplateTail;
+
+export type PunctuationSyntaxKind =
+ | SyntaxKind.OpenBraceToken
+ | SyntaxKind.CloseBraceToken
+ | SyntaxKind.OpenParenToken
+ | SyntaxKind.CloseParenToken
+ | SyntaxKind.OpenBracketToken
+ | SyntaxKind.CloseBracketToken
+ | SyntaxKind.DotToken
+ | SyntaxKind.DotDotDotToken
+ | SyntaxKind.SemicolonToken
+ | SyntaxKind.CommaToken
+ | SyntaxKind.QuestionDotToken
+ | SyntaxKind.LessThanToken
+ | SyntaxKind.LessThanSlashToken
+ | SyntaxKind.GreaterThanToken
+ | SyntaxKind.LessThanEqualsToken
+ | SyntaxKind.GreaterThanEqualsToken
+ | SyntaxKind.EqualsEqualsToken
+ | SyntaxKind.ExclamationEqualsToken
+ | SyntaxKind.EqualsEqualsEqualsToken
+ | SyntaxKind.ExclamationEqualsEqualsToken
+ | SyntaxKind.EqualsGreaterThanToken
+ | SyntaxKind.PlusToken
+ | SyntaxKind.MinusToken
+ | SyntaxKind.AsteriskToken
+ | SyntaxKind.AsteriskAsteriskToken
+ | SyntaxKind.SlashToken
+ | SyntaxKind.PercentToken
+ | SyntaxKind.PlusPlusToken
+ | SyntaxKind.MinusMinusToken
+ | SyntaxKind.LessThanLessThanToken
+ | SyntaxKind.GreaterThanGreaterThanToken
+ | SyntaxKind.GreaterThanGreaterThanGreaterThanToken
+ | SyntaxKind.AmpersandToken
+ | SyntaxKind.BarToken
+ | SyntaxKind.CaretToken
+ | SyntaxKind.ExclamationToken
+ | SyntaxKind.TildeToken
+ | SyntaxKind.AmpersandAmpersandToken
+ | SyntaxKind.AmpersandAmpersandEqualsToken
+ | SyntaxKind.BarBarToken
+ | SyntaxKind.BarBarEqualsToken
+ | SyntaxKind.QuestionQuestionToken
+ | SyntaxKind.QuestionQuestionEqualsToken
+ | SyntaxKind.QuestionToken
+ | SyntaxKind.ColonToken
+ | SyntaxKind.AtToken
+ | SyntaxKind.BacktickToken
+ | SyntaxKind.HashToken
+ | SyntaxKind.EqualsToken
+ | SyntaxKind.PlusEqualsToken
+ | SyntaxKind.MinusEqualsToken
+ | SyntaxKind.AsteriskEqualsToken
+ | SyntaxKind.AsteriskAsteriskEqualsToken
+ | SyntaxKind.SlashEqualsToken
+ | SyntaxKind.PercentEqualsToken
+ | SyntaxKind.LessThanLessThanEqualsToken
+ | SyntaxKind.GreaterThanGreaterThanEqualsToken
+ | SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken
+ | SyntaxKind.AmpersandEqualsToken
+ | SyntaxKind.BarEqualsToken
+ | SyntaxKind.CaretEqualsToken;
+
+export type KeywordSyntaxKind =
+ | SyntaxKind.AbstractKeyword
+ | SyntaxKind.AccessorKeyword
+ | SyntaxKind.AnyKeyword
+ | SyntaxKind.AsKeyword
+ | SyntaxKind.AssertsKeyword
+ | SyntaxKind.AssertKeyword
+ | SyntaxKind.AsyncKeyword
+ | SyntaxKind.AwaitKeyword
+ | SyntaxKind.BigIntKeyword
+ | SyntaxKind.BooleanKeyword
+ | SyntaxKind.BreakKeyword
+ | SyntaxKind.CaseKeyword
+ | SyntaxKind.CatchKeyword
+ | SyntaxKind.ClassKeyword
+ | SyntaxKind.ConstKeyword
+ | SyntaxKind.ConstructorKeyword
+ | SyntaxKind.ContinueKeyword
+ | SyntaxKind.DebuggerKeyword
+ | SyntaxKind.DeclareKeyword
+ | SyntaxKind.DefaultKeyword
+ | SyntaxKind.DeleteKeyword
+ | SyntaxKind.DoKeyword
+ | SyntaxKind.ElseKeyword
+ | SyntaxKind.EnumKeyword
+ | SyntaxKind.ExportKeyword
+ | SyntaxKind.ExtendsKeyword
+ | SyntaxKind.FalseKeyword
+ | SyntaxKind.FinallyKeyword
+ | SyntaxKind.ForKeyword
+ | SyntaxKind.FromKeyword
+ | SyntaxKind.FunctionKeyword
+ | SyntaxKind.GetKeyword
+ | SyntaxKind.GlobalKeyword
+ | SyntaxKind.IfKeyword
+ | SyntaxKind.ImplementsKeyword
+ | SyntaxKind.ImportKeyword
+ | SyntaxKind.InferKeyword
+ | SyntaxKind.InKeyword
+ | SyntaxKind.InstanceOfKeyword
+ | SyntaxKind.InterfaceKeyword
+ | SyntaxKind.IntrinsicKeyword
+ | SyntaxKind.IsKeyword
+ | SyntaxKind.KeyOfKeyword
+ | SyntaxKind.LetKeyword
+ | SyntaxKind.ModuleKeyword
+ | SyntaxKind.NamespaceKeyword
+ | SyntaxKind.NeverKeyword
+ | SyntaxKind.NewKeyword
+ | SyntaxKind.NullKeyword
+ | SyntaxKind.NumberKeyword
+ | SyntaxKind.ObjectKeyword
+ | SyntaxKind.OfKeyword
+ | SyntaxKind.PackageKeyword
+ | SyntaxKind.PrivateKeyword
+ | SyntaxKind.ProtectedKeyword
+ | SyntaxKind.PublicKeyword
+ | SyntaxKind.ReadonlyKeyword
+ | SyntaxKind.OutKeyword
+ | SyntaxKind.OverrideKeyword
+ | SyntaxKind.RequireKeyword
+ | SyntaxKind.ReturnKeyword
+ | SyntaxKind.SatisfiesKeyword
+ | SyntaxKind.SetKeyword
+ | SyntaxKind.StaticKeyword
+ | SyntaxKind.StringKeyword
+ | SyntaxKind.SuperKeyword
+ | SyntaxKind.SwitchKeyword
+ | SyntaxKind.SymbolKeyword
+ | SyntaxKind.ThisKeyword
+ | SyntaxKind.ThrowKeyword
+ | SyntaxKind.TrueKeyword
+ | SyntaxKind.TryKeyword
+ | SyntaxKind.TypeKeyword
+ | SyntaxKind.TypeOfKeyword
+ | SyntaxKind.UndefinedKeyword
+ | SyntaxKind.UniqueKeyword
+ | SyntaxKind.UnknownKeyword
+ | SyntaxKind.UsingKeyword
+ | SyntaxKind.VarKeyword
+ | SyntaxKind.VoidKeyword
+ | SyntaxKind.WhileKeyword
+ | SyntaxKind.WithKeyword
+ | SyntaxKind.YieldKeyword;
+
+export type ModifierSyntaxKind =
+ | SyntaxKind.AbstractKeyword
+ | SyntaxKind.AccessorKeyword
+ | SyntaxKind.AsyncKeyword
+ | SyntaxKind.ConstKeyword
+ | SyntaxKind.DeclareKeyword
+ | SyntaxKind.DefaultKeyword
+ | SyntaxKind.ExportKeyword
+ | SyntaxKind.InKeyword
+ | SyntaxKind.PrivateKeyword
+ | SyntaxKind.ProtectedKeyword
+ | SyntaxKind.PublicKeyword
+ | SyntaxKind.ReadonlyKeyword
+ | SyntaxKind.OutKeyword
+ | SyntaxKind.OverrideKeyword
+ | SyntaxKind.StaticKeyword;
+
+export type KeywordTypeSyntaxKind =
+ | SyntaxKind.AnyKeyword
+ | SyntaxKind.BigIntKeyword
+ | SyntaxKind.BooleanKeyword
+ | SyntaxKind.IntrinsicKeyword
+ | SyntaxKind.NeverKeyword
+ | SyntaxKind.NumberKeyword
+ | SyntaxKind.ObjectKeyword
+ | SyntaxKind.StringKeyword
+ | SyntaxKind.SymbolKeyword
+ | SyntaxKind.UndefinedKeyword
+ | SyntaxKind.UnknownKeyword
+ | SyntaxKind.VoidKeyword;
+
+export type TokenSyntaxKind =
+ | SyntaxKind.Unknown
+ | SyntaxKind.EndOfFile
+ | TriviaSyntaxKind
+ | LiteralSyntaxKind
+ | PseudoLiteralSyntaxKind
+ | PunctuationSyntaxKind
+ | SyntaxKind.Identifier
+ | KeywordSyntaxKind;
+
+export type JsxTokenSyntaxKind =
+ | SyntaxKind.LessThanSlashToken
+ | SyntaxKind.EndOfFile
+ | SyntaxKind.ConflictMarkerTrivia
+ | SyntaxKind.JsxText
+ | SyntaxKind.JsxTextAllWhiteSpaces
+ | SyntaxKind.OpenBraceToken
+ | SyntaxKind.LessThanToken;
+
+export type JSDocSyntaxKind =
+ | SyntaxKind.EndOfFile
+ | SyntaxKind.WhitespaceTrivia
+ | SyntaxKind.AtToken
+ | SyntaxKind.NewLineTrivia
+ | SyntaxKind.AsteriskToken
+ | SyntaxKind.OpenBraceToken
+ | SyntaxKind.CloseBraceToken
+ | SyntaxKind.LessThanToken
+ | SyntaxKind.GreaterThanToken
+ | SyntaxKind.OpenBracketToken
+ | SyntaxKind.CloseBracketToken
+ | SyntaxKind.OpenParenToken
+ | SyntaxKind.CloseParenToken
+ | SyntaxKind.EqualsToken
+ | SyntaxKind.CommaToken
+ | SyntaxKind.DotToken
+ | SyntaxKind.Identifier
+ | SyntaxKind.BacktickToken
+ | SyntaxKind.HashToken
+ | SyntaxKind.Unknown
+ | KeywordSyntaxKind;
+
+export interface ReadonlyTextRange {
+ readonly pos: number;
+ readonly end: number;
+}
+
+export interface NodeArray extends ReadonlyTextRange, ReadonlyArray {
+ readonly length: number;
+ readonly pos: number;
+ readonly end: number;
+}
+
+// TODO(rbuckton): Constraint 'TKind' to 'TokenSyntaxKind'
+export interface Token extends Node {
+ readonly kind: TKind;
+}
+
+export type EndOfFile = Token;
+
+// Punctuation
+export interface PunctuationToken extends Token {
+}
+
+export type DotToken = PunctuationToken;
+export type DotDotDotToken = PunctuationToken;
+export type QuestionToken = PunctuationToken;
+export type ExclamationToken = PunctuationToken;
+export type ColonToken = PunctuationToken;
+export type EqualsToken = PunctuationToken;
+export type AmpersandAmpersandEqualsToken = PunctuationToken;
+export type BarBarEqualsToken = PunctuationToken;
+export type QuestionQuestionEqualsToken = PunctuationToken;
+export type AsteriskToken = PunctuationToken;
+export type EqualsGreaterThanToken = PunctuationToken;
+export type PlusToken = PunctuationToken;
+export type MinusToken = PunctuationToken;
+export type QuestionDotToken = PunctuationToken;
+
+// Keywords
+export interface KeywordToken extends Token {
+}
+
+export type AssertsKeyword = KeywordToken;
+export type AssertKeyword = KeywordToken;
+export type AwaitKeyword = KeywordToken;
+export type CaseKeyword = KeywordToken;
+
+export interface ModifierToken extends KeywordToken {
+}
+
+export type AbstractKeyword = ModifierToken;
+export type AccessorKeyword = ModifierToken;
+export type AsyncKeyword = ModifierToken;
+export type ConstKeyword = ModifierToken;
+export type DeclareKeyword = ModifierToken;
+export type DefaultKeyword = ModifierToken;
+export type ExportKeyword = ModifierToken;
+export type InKeyword = ModifierToken;
+export type PrivateKeyword = ModifierToken;
+export type ProtectedKeyword = ModifierToken;
+export type PublicKeyword = ModifierToken;
+export type ReadonlyKeyword = ModifierToken;
+export type OutKeyword = ModifierToken;
+export type OverrideKeyword = ModifierToken;
+export type StaticKeyword = ModifierToken;
+
+export type Modifier =
+ | AbstractKeyword
+ | AccessorKeyword
+ | AsyncKeyword
+ | ConstKeyword
+ | DeclareKeyword
+ | DefaultKeyword
+ | ExportKeyword
+ | InKeyword
+ | PrivateKeyword
+ | ProtectedKeyword
+ | PublicKeyword
+ | OutKeyword
+ | OverrideKeyword
+ | ReadonlyKeyword
+ | StaticKeyword;
+
+export type ModifierLike = Modifier | Decorator;
+
+export type AccessibilityModifier =
+ | PublicKeyword
+ | PrivateKeyword
+ | ProtectedKeyword;
+
+export type ParameterPropertyModifier =
+ | AccessibilityModifier
+ | ReadonlyKeyword;
+
+export type ClassMemberModifier =
+ | AccessibilityModifier
+ | ReadonlyKeyword
+ | StaticKeyword
+ | AccessorKeyword;
+
+export type ModifiersArray = NodeArray;
+
+export interface Identifier extends PrimaryExpression, Declaration {
+ readonly kind: SyntaxKind.Identifier;
+ /**
+ * Prefer to use `id.unescapedText`. (Note: This is available only in services, not internally to the TypeScript compiler.)
+ * Text of identifier, but if the identifier begins with two underscores, this will begin with three.
+ */
+ readonly text: string;
+}
+
+export interface QualifiedName extends Node {
+ readonly kind: SyntaxKind.QualifiedName;
+ readonly left: EntityName;
+ readonly right: Identifier;
+}
+
+export type EntityName = Identifier | QualifiedName;
+
+export type PropertyName =
+ | Identifier
+ | StringLiteral
+ | NoSubstitutionTemplateLiteral
+ | NumericLiteral
+ | ComputedPropertyName
+ | PrivateIdentifier
+ | BigIntLiteral;
+
+export type MemberName = Identifier | PrivateIdentifier;
+
+export type DeclarationName =
+ | PropertyName
+ | JsxAttributeName
+ | StringLiteralLike
+ | ElementAccessExpression
+ | BindingPattern
+ | EntityNameExpression;
+
+export interface Declaration extends Node {
+}
+
+export interface NamedDeclaration extends Declaration {
+ readonly name?: DeclarationName;
+}
+
+export interface DeclarationStatement extends NamedDeclaration, Statement {
+ readonly name?: Identifier | StringLiteral | NumericLiteral;
+}
+
+export interface ComputedPropertyName extends Node {
+ readonly kind: SyntaxKind.ComputedPropertyName;
+ readonly parent: Declaration;
+ readonly expression: Expression;
+}
+
+// Typed as a PrimaryExpression due to its presence in BinaryExpressions (#field in expr)
+export interface PrivateIdentifier extends PrimaryExpression {
+ readonly kind: SyntaxKind.PrivateIdentifier;
+ // escaping not strictly necessary
+ // avoids gotchas in transforms and utils
+ readonly escapedText: string;
+}
+
+export interface Decorator extends Node {
+ readonly kind: SyntaxKind.Decorator;
+ readonly parent: NamedDeclaration;
+ readonly expression: LeftHandSideExpression;
+}
+
+export interface TypeParameterDeclaration extends NamedDeclaration {
+ readonly kind: SyntaxKind.TypeParameter;
+ readonly parent: DeclarationWithTypeParameterChildren | InferTypeNode;
+ readonly modifiers?: NodeArray;
+ readonly name: Identifier;
+ /** Note: Consider calling `getEffectiveConstraintOfTypeParameter` */
+ readonly constraint?: TypeNode;
+ readonly default?: TypeNode;
+
+ // For error recovery purposes (see `isGrammarError` in utilities.ts).
+ expression?: Expression;
+}
+
+export interface SignatureDeclarationBase extends NamedDeclaration {
+ readonly kind: SignatureDeclaration["kind"];
+ readonly name?: PropertyName;
+ readonly typeParameters?: NodeArray | undefined;
+ readonly parameters: NodeArray;
+ readonly type?: TypeNode | undefined;
+}
+
+export type SignatureDeclaration =
+ | CallSignatureDeclaration
+ | ConstructSignatureDeclaration
+ | MethodSignature
+ | IndexSignatureDeclaration
+ | FunctionTypeNode
+ | ConstructorTypeNode
+ | FunctionDeclaration
+ | MethodDeclaration
+ | ConstructorDeclaration
+ | AccessorDeclaration
+ | FunctionExpression
+ | ArrowFunction;
+
+export interface CallSignatureDeclaration extends SignatureDeclarationBase, TypeElement {
+ readonly kind: SyntaxKind.CallSignature;
+}
+
+export interface ConstructSignatureDeclaration extends SignatureDeclarationBase, TypeElement {
+ readonly kind: SyntaxKind.ConstructSignature;
+}
+
+export type BindingName = Identifier | BindingPattern;
+
+// dprint-ignore
+export interface VariableDeclaration extends NamedDeclaration {
+ readonly kind: SyntaxKind.VariableDeclaration;
+ readonly parent: VariableDeclarationList | CatchClause;
+ readonly name: BindingName; // Declared variable name
+ readonly exclamationToken?: ExclamationToken; // Optional definite assignment assertion
+ readonly type?: TypeNode; // Optional type annotation
+ readonly initializer?: Expression; // Optional initializer
+}
+
+export interface VariableDeclarationList extends Node {
+ readonly kind: SyntaxKind.VariableDeclarationList;
+ readonly parent: VariableStatement | ForStatement | ForOfStatement | ForInStatement;
+ readonly declarations: NodeArray;
+}
+
+// dprint-ignore
+export interface ParameterDeclaration extends NamedDeclaration {
+ readonly kind: SyntaxKind.Parameter;
+ readonly parent: SignatureDeclaration;
+ readonly modifiers?: NodeArray;
+ readonly dotDotDotToken?: DotDotDotToken; // Present on rest parameter
+ readonly name: BindingName; // Declared parameter name.
+ readonly questionToken?: QuestionToken; // Present on optional parameter
+ readonly type?: TypeNode; // Optional type annotation
+ readonly initializer?: Expression; // Optional initializer
+}
+
+// dprint-ignore
+export interface BindingElement extends NamedDeclaration {
+ readonly kind: SyntaxKind.BindingElement;
+ readonly parent: BindingPattern;
+ readonly propertyName?: PropertyName; // Binding property name (in object binding pattern)
+ readonly dotDotDotToken?: DotDotDotToken; // Present on rest element (in object binding pattern)
+ readonly name: BindingName; // Declared binding element name
+ readonly initializer?: Expression; // Optional initializer
+}
+
+// dprint-ignore
+export interface PropertySignature extends TypeElement {
+ readonly kind: SyntaxKind.PropertySignature;
+ readonly parent: TypeLiteralNode | InterfaceDeclaration;
+ readonly modifiers?: NodeArray;
+ readonly name: PropertyName; // Declared property name
+ readonly questionToken?: QuestionToken; // Present on optional property
+ readonly type?: TypeNode; // Optional type annotation
+}
+
+// dprint-ignore
+export interface PropertyDeclaration extends ClassElement {
+ readonly kind: SyntaxKind.PropertyDeclaration;
+ readonly parent: ClassLikeDeclaration;
+ readonly modifiers?: NodeArray;
+ readonly name: PropertyName;
+ readonly questionToken?: QuestionToken; // Present for use with reporting a grammar error for auto-accessors (see `isGrammarError` in utilities.ts)
+ readonly exclamationToken?: ExclamationToken;
+ readonly type?: TypeNode;
+ readonly initializer?: Expression; // Optional initializer
+}
+
+export interface AutoAccessorPropertyDeclaration extends PropertyDeclaration {
+ _autoAccessorBrand: any;
+}
+
+export interface ObjectLiteralElement extends NamedDeclaration {
+ _objectLiteralBrand: any;
+ readonly name?: PropertyName;
+}
+
+/** Unlike ObjectLiteralElement, excludes JSXAttribute and JSXSpreadAttribute. */
+export type ObjectLiteralElementLike =
+ | PropertyAssignment
+ | ShorthandPropertyAssignment
+ | SpreadAssignment
+ | MethodDeclaration
+ | AccessorDeclaration;
+
+export interface PropertyAssignment extends ObjectLiteralElement {
+ readonly kind: SyntaxKind.PropertyAssignment;
+ readonly parent: ObjectLiteralExpression;
+ readonly name: PropertyName;
+ readonly initializer: Expression;
+}
+
+export interface ShorthandPropertyAssignment extends ObjectLiteralElement {
+ readonly kind: SyntaxKind.ShorthandPropertyAssignment;
+ readonly parent: ObjectLiteralExpression;
+ readonly name: Identifier;
+ // used when ObjectLiteralExpression is used in ObjectAssignmentPattern
+ // it is a grammar error to appear in actual object initializer (see `isGrammarError` in utilities.ts):
+ readonly equalsToken?: EqualsToken;
+ readonly objectAssignmentInitializer?: Expression;
+}
+
+export interface SpreadAssignment extends ObjectLiteralElement {
+ readonly kind: SyntaxKind.SpreadAssignment;
+ readonly parent: ObjectLiteralExpression;
+ readonly expression: Expression;
+}
+
+export type VariableLikeDeclaration =
+ | VariableDeclaration
+ | ParameterDeclaration
+ | BindingElement
+ | PropertyDeclaration
+ | PropertyAssignment
+ | PropertySignature
+ | JsxAttribute
+ | ShorthandPropertyAssignment
+ | EnumMember
+ | JSDocPropertyTag
+ | JSDocParameterTag;
+
+export interface ObjectBindingPattern extends Node {
+ readonly kind: SyntaxKind.ObjectBindingPattern;
+ readonly parent: VariableDeclaration | ParameterDeclaration | BindingElement;
+ readonly elements: NodeArray;
+}
+
+export interface ArrayBindingPattern extends Node {
+ readonly kind: SyntaxKind.ArrayBindingPattern;
+ readonly parent: VariableDeclaration | ParameterDeclaration | BindingElement;
+ readonly elements: NodeArray;
+}
+
+export type BindingPattern = ObjectBindingPattern | ArrayBindingPattern;
+
+export type ArrayBindingElement = BindingElement | OmittedExpression;
+
+/**
+ * Several node kinds share function-like features such as a signature,
+ * a name, and a body. These nodes should extend FunctionLikeDeclarationBase.
+ * Examples:
+ * - FunctionDeclaration
+ * - MethodDeclaration
+ * - AccessorDeclaration
+ */
+export interface FunctionLikeDeclarationBase extends SignatureDeclarationBase {
+ _functionLikeDeclarationBrand: any;
+
+ readonly asteriskToken?: AsteriskToken | undefined;
+ readonly questionToken?: QuestionToken | undefined;
+ readonly exclamationToken?: ExclamationToken | undefined;
+ readonly body?: Block | Expression | undefined;
+}
+
+export type FunctionLikeDeclaration =
+ | FunctionDeclaration
+ | MethodDeclaration
+ | GetAccessorDeclaration
+ | SetAccessorDeclaration
+ | ConstructorDeclaration
+ | FunctionExpression
+ | ArrowFunction;
+/** @deprecated Use SignatureDeclaration */
+export type FunctionLike = SignatureDeclaration;
+
+export interface FunctionDeclaration extends FunctionLikeDeclarationBase, DeclarationStatement {
+ readonly kind: SyntaxKind.FunctionDeclaration;
+ readonly modifiers?: NodeArray;
+ readonly name?: Identifier;
+ readonly body?: FunctionBody;
+}
+
+export interface MethodSignature extends SignatureDeclarationBase, TypeElement {
+ readonly kind: SyntaxKind.MethodSignature;
+ readonly parent: TypeLiteralNode | InterfaceDeclaration;
+ readonly modifiers?: NodeArray;
+ readonly name: PropertyName;
+}
+
+// Note that a MethodDeclaration is considered both a ClassElement and an ObjectLiteralElement.
+// Both the grammars for ClassDeclaration and ObjectLiteralExpression allow for MethodDeclarations
+// as child elements, and so a MethodDeclaration satisfies both interfaces. This avoids the
+// alternative where we would need separate kinds/types for ClassMethodDeclaration and
+// ObjectLiteralMethodDeclaration, which would look identical.
+//
+// Because of this, it may be necessary to determine what sort of MethodDeclaration you have
+// at later stages of the compiler pipeline. In that case, you can either check the parent kind
+// of the method, or use helpers like isObjectLiteralMethodDeclaration
+export interface MethodDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement {
+ readonly kind: SyntaxKind.MethodDeclaration;
+ readonly parent: ClassLikeDeclaration | ObjectLiteralExpression;
+ readonly modifiers?: NodeArray | undefined;
+ readonly name: PropertyName;
+ readonly body?: FunctionBody | undefined;
+}
+
+export interface ConstructorDeclaration extends FunctionLikeDeclarationBase, ClassElement {
+ readonly kind: SyntaxKind.Constructor;
+ readonly parent: ClassLikeDeclaration;
+ readonly modifiers?: NodeArray | undefined;
+ readonly body?: FunctionBody | undefined;
+}
+
+/** For when we encounter a semicolon in a class declaration. ES6 allows these as class elements. */
+export interface SemicolonClassElement extends ClassElement {
+ readonly kind: SyntaxKind.SemicolonClassElement;
+ readonly parent: ClassLikeDeclaration;
+}
+
+// See the comment on MethodDeclaration for the intuition behind GetAccessorDeclaration being a
+// ClassElement and an ObjectLiteralElement.
+export interface GetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, TypeElement, ObjectLiteralElement {
+ readonly kind: SyntaxKind.GetAccessor;
+ readonly parent: ClassLikeDeclaration | ObjectLiteralExpression | TypeLiteralNode | InterfaceDeclaration;
+ readonly modifiers?: NodeArray;
+ readonly name: PropertyName;
+ readonly body?: FunctionBody;
+}
+
+// See the comment on MethodDeclaration for the intuition behind SetAccessorDeclaration being a
+// ClassElement and an ObjectLiteralElement.
+export interface SetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, TypeElement, ObjectLiteralElement {
+ readonly kind: SyntaxKind.SetAccessor;
+ readonly parent: ClassLikeDeclaration | ObjectLiteralExpression | TypeLiteralNode | InterfaceDeclaration;
+ readonly modifiers?: NodeArray;
+ readonly name: PropertyName;
+ readonly body?: FunctionBody;
+}
+
+export type AccessorDeclaration = GetAccessorDeclaration | SetAccessorDeclaration;
+
+export interface IndexSignatureDeclaration extends SignatureDeclarationBase, ClassElement, TypeElement {
+ readonly kind: SyntaxKind.IndexSignature;
+ readonly parent: ObjectTypeDeclaration;
+ readonly modifiers?: NodeArray;
+ readonly type: TypeNode;
+}
+
+export interface ClassStaticBlockDeclaration extends ClassElement {
+ readonly kind: SyntaxKind.ClassStaticBlockDeclaration;
+ readonly parent: ClassDeclaration | ClassExpression;
+ readonly body: Block;
+}
+
+export interface TypeNode extends Node {
+ _typeNodeBrand: any;
+}
+
+export interface KeywordTypeNode extends KeywordToken, TypeNode {
+ readonly kind: TKind;
+}
+
+export interface ImportTypeNode extends NodeWithTypeArguments {
+ readonly kind: SyntaxKind.ImportType;
+ readonly isTypeOf: boolean;
+ readonly argument: TypeNode;
+ readonly attributes?: ImportAttributes;
+ readonly qualifier?: EntityName;
+}
+
+export interface ThisTypeNode extends TypeNode {
+ readonly kind: SyntaxKind.ThisType;
+}
+
+export type FunctionOrConstructorTypeNode = FunctionTypeNode | ConstructorTypeNode;
+
+export interface FunctionOrConstructorTypeNodeBase extends TypeNode, SignatureDeclarationBase {
+ readonly kind: SyntaxKind.FunctionType | SyntaxKind.ConstructorType;
+ readonly type: TypeNode;
+}
+
+export interface FunctionTypeNode extends FunctionOrConstructorTypeNodeBase {
+ readonly kind: SyntaxKind.FunctionType;
+}
+
+export interface ConstructorTypeNode extends FunctionOrConstructorTypeNodeBase {
+ readonly kind: SyntaxKind.ConstructorType;
+ readonly modifiers?: NodeArray;
+}
+
+export interface NodeWithTypeArguments extends TypeNode {
+ readonly typeArguments?: NodeArray;
+}
+
+export type TypeReferenceType = TypeReferenceNode | ExpressionWithTypeArguments;
+
+export interface TypeReferenceNode extends NodeWithTypeArguments {
+ readonly kind: SyntaxKind.TypeReference;
+ readonly typeName: EntityName;
+}
+
+export interface TypePredicateNode extends TypeNode {
+ readonly kind: SyntaxKind.TypePredicate;
+ readonly parent: SignatureDeclaration | JSDocTypeExpression;
+ readonly assertsModifier?: AssertsKeyword;
+ readonly parameterName: Identifier | ThisTypeNode;
+ readonly type?: TypeNode;
+}
+
+export interface TypeQueryNode extends NodeWithTypeArguments {
+ readonly kind: SyntaxKind.TypeQuery;
+ readonly exprName: EntityName;
+}
+
+// A TypeLiteral is the declaration node for an anonymous symbol.
+export interface TypeLiteralNode extends TypeNode, Declaration {
+ readonly kind: SyntaxKind.TypeLiteral;
+ readonly members: NodeArray;
+}
+
+export interface ArrayTypeNode extends TypeNode {
+ readonly kind: SyntaxKind.ArrayType;
+ readonly elementType: TypeNode;
+}
+
+export interface TupleTypeNode extends TypeNode {
+ readonly kind: SyntaxKind.TupleType;
+ readonly elements: NodeArray;
+}
+
+export interface NamedTupleMember extends TypeNode, Declaration {
+ readonly kind: SyntaxKind.NamedTupleMember;
+ readonly dotDotDotToken?: Token;
+ readonly name: Identifier;
+ readonly questionToken?: Token;
+ readonly type: TypeNode;
+}
+
+export interface OptionalTypeNode extends TypeNode {
+ readonly kind: SyntaxKind.OptionalType;
+ readonly type: TypeNode;
+}
+
+export interface RestTypeNode extends TypeNode {
+ readonly kind: SyntaxKind.RestType;
+ readonly type: TypeNode;
+}
+
+export type UnionOrIntersectionTypeNode = UnionTypeNode | IntersectionTypeNode;
+
+export interface UnionTypeNode extends TypeNode {
+ readonly kind: SyntaxKind.UnionType;
+ readonly types: NodeArray;
+}
+
+export interface IntersectionTypeNode extends TypeNode {
+ readonly kind: SyntaxKind.IntersectionType;
+ readonly types: NodeArray;
+}
+
+export interface ConditionalTypeNode extends TypeNode {
+ readonly kind: SyntaxKind.ConditionalType;
+ readonly checkType: TypeNode;
+ readonly extendsType: TypeNode;
+ readonly trueType: TypeNode;
+ readonly falseType: TypeNode;
+}
+
+export interface InferTypeNode extends TypeNode {
+ readonly kind: SyntaxKind.InferType;
+ readonly typeParameter: TypeParameterDeclaration;
+}
+
+export interface ParenthesizedTypeNode extends TypeNode {
+ readonly kind: SyntaxKind.ParenthesizedType;
+ readonly type: TypeNode;
+}
+
+export interface TypeOperatorNode extends TypeNode {
+ readonly kind: SyntaxKind.TypeOperator;
+ readonly operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword;
+ readonly type: TypeNode;
+}
+
+export interface IndexedAccessTypeNode extends TypeNode {
+ readonly kind: SyntaxKind.IndexedAccessType;
+ readonly objectType: TypeNode;
+ readonly indexType: TypeNode;
+}
+
+export interface MappedTypeNode extends TypeNode, Declaration {
+ readonly kind: SyntaxKind.MappedType;
+ readonly readonlyToken?: ReadonlyKeyword | PlusToken | MinusToken;
+ readonly typeParameter: TypeParameterDeclaration;
+ readonly nameType?: TypeNode;
+ readonly questionToken?: QuestionToken | PlusToken | MinusToken;
+ readonly type?: TypeNode;
+ /** Used only to produce grammar errors */
+ readonly members?: NodeArray;
+}
+
+export interface LiteralTypeNode extends TypeNode {
+ readonly kind: SyntaxKind.LiteralType;
+ readonly literal: NullLiteral | BooleanLiteral | LiteralExpression | PrefixUnaryExpression;
+}
+
+export interface StringLiteral extends LiteralExpression, Declaration {
+ readonly kind: SyntaxKind.StringLiteral;
+}
+
+export type StringLiteralLike = StringLiteral | NoSubstitutionTemplateLiteral;
+export type PropertyNameLiteral = Identifier | StringLiteralLike | NumericLiteral | JsxNamespacedName | BigIntLiteral;
+
+export interface TemplateLiteralTypeNode extends TypeNode {
+ kind: SyntaxKind.TemplateLiteralType;
+ readonly head: TemplateHead;
+ readonly templateSpans: NodeArray;
+}
+
+export interface TemplateLiteralTypeSpan extends TypeNode {
+ readonly kind: SyntaxKind.TemplateLiteralTypeSpan;
+ readonly parent: TemplateLiteralTypeNode;
+ readonly type: TypeNode;
+ readonly literal: TemplateMiddle | TemplateTail;
+}
+
+// Note: 'brands' in our syntax nodes serve to give us a small amount of nominal typing.
+// Consider 'Expression'. Without the brand, 'Expression' is actually no different
+// (structurally) than 'Node'. Because of this you can pass any Node to a function that
+// takes an Expression without any error. By using the 'brands' we ensure that the type
+// checker actually thinks you have something of the right type. Note: the brands are
+// never actually given values. At runtime they have zero cost.
+
+export interface Expression extends Node {
+ _expressionBrand: any;
+}
+
+export interface OmittedExpression extends Expression {
+ readonly kind: SyntaxKind.OmittedExpression;
+}
+
+// Represents an expression that is elided as part of a transformation to emit comments on a
+// not-emitted node. The 'expression' property of a PartiallyEmittedExpression should be emitted.
+export interface PartiallyEmittedExpression extends LeftHandSideExpression {
+ readonly kind: SyntaxKind.PartiallyEmittedExpression;
+ readonly expression: Expression;
+}
+
+export interface UnaryExpression extends Expression {
+ _unaryExpressionBrand: any;
+}
+
+/** Deprecated, please use UpdateExpression */
+export type IncrementExpression = UpdateExpression;
+export interface UpdateExpression extends UnaryExpression {
+ _updateExpressionBrand: any;
+}
+
+// see: https://tc39.github.io/ecma262/#prod-UpdateExpression
+// see: https://tc39.github.io/ecma262/#prod-UnaryExpression
+export type PrefixUnaryOperator =
+ | SyntaxKind.PlusPlusToken
+ | SyntaxKind.MinusMinusToken
+ | SyntaxKind.PlusToken
+ | SyntaxKind.MinusToken
+ | SyntaxKind.TildeToken
+ | SyntaxKind.ExclamationToken;
+
+export interface PrefixUnaryExpression extends UpdateExpression {
+ readonly kind: SyntaxKind.PrefixUnaryExpression;
+ readonly operator: PrefixUnaryOperator;
+ readonly operand: UnaryExpression;
+}
+
+// see: https://tc39.github.io/ecma262/#prod-UpdateExpression
+export type PostfixUnaryOperator =
+ | SyntaxKind.PlusPlusToken
+ | SyntaxKind.MinusMinusToken;
+
+export interface PostfixUnaryExpression extends UpdateExpression {
+ readonly kind: SyntaxKind.PostfixUnaryExpression;
+ readonly operand: LeftHandSideExpression;
+ readonly operator: PostfixUnaryOperator;
+}
+
+export interface LeftHandSideExpression extends UpdateExpression {
+ _leftHandSideExpressionBrand: any;
+}
+
+export interface MemberExpression extends LeftHandSideExpression {
+ _memberExpressionBrand: any;
+}
+
+export interface PrimaryExpression extends MemberExpression {
+ _primaryExpressionBrand: any;
+}
+
+export interface NullLiteral extends PrimaryExpression {
+ readonly kind: SyntaxKind.NullKeyword;
+}
+
+export interface TrueLiteral extends PrimaryExpression {
+ readonly kind: SyntaxKind.TrueKeyword;
+}
+
+export interface FalseLiteral extends PrimaryExpression {
+ readonly kind: SyntaxKind.FalseKeyword;
+}
+
+export type BooleanLiteral = TrueLiteral | FalseLiteral;
+
+export interface ThisExpression extends PrimaryExpression {
+ readonly kind: SyntaxKind.ThisKeyword;
+}
+
+export interface SuperExpression extends PrimaryExpression {
+ readonly kind: SyntaxKind.SuperKeyword;
+}
+
+export interface ImportExpression extends PrimaryExpression {
+ readonly kind: SyntaxKind.ImportKeyword;
+}
+
+export interface DeleteExpression extends UnaryExpression {
+ readonly kind: SyntaxKind.DeleteExpression;
+ readonly expression: UnaryExpression;
+}
+
+export interface TypeOfExpression extends UnaryExpression {
+ readonly kind: SyntaxKind.TypeOfExpression;
+ readonly expression: UnaryExpression;
+}
+
+export interface VoidExpression extends UnaryExpression {
+ readonly kind: SyntaxKind.VoidExpression;
+ readonly expression: UnaryExpression;
+}
+
+export interface AwaitExpression extends UnaryExpression {
+ readonly kind: SyntaxKind.AwaitExpression;
+ readonly expression: UnaryExpression;
+}
+
+export interface YieldExpression extends Expression {
+ readonly kind: SyntaxKind.YieldExpression;
+ readonly asteriskToken?: AsteriskToken;
+ readonly expression?: Expression;
+}
+
+// see: https://tc39.github.io/ecma262/#prod-ExponentiationExpression
+export type ExponentiationOperator = SyntaxKind.AsteriskAsteriskToken;
+
+// see: https://tc39.github.io/ecma262/#prod-MultiplicativeOperator
+export type MultiplicativeOperator =
+ | SyntaxKind.AsteriskToken
+ | SyntaxKind.SlashToken
+ | SyntaxKind.PercentToken;
+
+// see: https://tc39.github.io/ecma262/#prod-MultiplicativeExpression
+export type MultiplicativeOperatorOrHigher =
+ | ExponentiationOperator
+ | MultiplicativeOperator;
+
+// see: https://tc39.github.io/ecma262/#prod-AdditiveExpression
+export type AdditiveOperator =
+ | SyntaxKind.PlusToken
+ | SyntaxKind.MinusToken;
+
+// see: https://tc39.github.io/ecma262/#prod-AdditiveExpression
+export type AdditiveOperatorOrHigher =
+ | MultiplicativeOperatorOrHigher
+ | AdditiveOperator;
+
+// see: https://tc39.github.io/ecma262/#prod-ShiftExpression
+export type ShiftOperator =
+ | SyntaxKind.LessThanLessThanToken
+ | SyntaxKind.GreaterThanGreaterThanToken
+ | SyntaxKind.GreaterThanGreaterThanGreaterThanToken;
+
+// see: https://tc39.github.io/ecma262/#prod-ShiftExpression
+export type ShiftOperatorOrHigher =
+ | AdditiveOperatorOrHigher
+ | ShiftOperator;
+
+// see: https://tc39.github.io/ecma262/#prod-RelationalExpression
+export type RelationalOperator =
+ | SyntaxKind.LessThanToken
+ | SyntaxKind.LessThanEqualsToken
+ | SyntaxKind.GreaterThanToken
+ | SyntaxKind.GreaterThanEqualsToken
+ | SyntaxKind.InstanceOfKeyword
+ | SyntaxKind.InKeyword;
+
+// see: https://tc39.github.io/ecma262/#prod-RelationalExpression
+export type RelationalOperatorOrHigher =
+ | ShiftOperatorOrHigher
+ | RelationalOperator;
+
+// see: https://tc39.github.io/ecma262/#prod-EqualityExpression
+export type EqualityOperator =
+ | SyntaxKind.EqualsEqualsToken
+ | SyntaxKind.EqualsEqualsEqualsToken
+ | SyntaxKind.ExclamationEqualsEqualsToken
+ | SyntaxKind.ExclamationEqualsToken;
+
+// see: https://tc39.github.io/ecma262/#prod-EqualityExpression
+export type EqualityOperatorOrHigher =
+ | RelationalOperatorOrHigher
+ | EqualityOperator;
+
+// see: https://tc39.github.io/ecma262/#prod-BitwiseANDExpression
+// see: https://tc39.github.io/ecma262/#prod-BitwiseXORExpression
+// see: https://tc39.github.io/ecma262/#prod-BitwiseORExpression
+export type BitwiseOperator =
+ | SyntaxKind.AmpersandToken
+ | SyntaxKind.BarToken
+ | SyntaxKind.CaretToken;
+
+// see: https://tc39.github.io/ecma262/#prod-BitwiseANDExpression
+// see: https://tc39.github.io/ecma262/#prod-BitwiseXORExpression
+// see: https://tc39.github.io/ecma262/#prod-BitwiseORExpression
+export type BitwiseOperatorOrHigher =
+ | EqualityOperatorOrHigher
+ | BitwiseOperator;
+
+// see: https://tc39.github.io/ecma262/#prod-LogicalANDExpression
+// see: https://tc39.github.io/ecma262/#prod-LogicalORExpression
+export type LogicalOperator =
+ | SyntaxKind.AmpersandAmpersandToken
+ | SyntaxKind.BarBarToken;
+
+// see: https://tc39.github.io/ecma262/#prod-LogicalANDExpression
+// see: https://tc39.github.io/ecma262/#prod-LogicalORExpression
+export type LogicalOperatorOrHigher =
+ | BitwiseOperatorOrHigher
+ | LogicalOperator;
+
+// see: https://tc39.github.io/ecma262/#prod-AssignmentOperator
+export type CompoundAssignmentOperator =
+ | SyntaxKind.PlusEqualsToken
+ | SyntaxKind.MinusEqualsToken
+ | SyntaxKind.AsteriskAsteriskEqualsToken
+ | SyntaxKind.AsteriskEqualsToken
+ | SyntaxKind.SlashEqualsToken
+ | SyntaxKind.PercentEqualsToken
+ | SyntaxKind.AmpersandEqualsToken
+ | SyntaxKind.BarEqualsToken
+ | SyntaxKind.CaretEqualsToken
+ | SyntaxKind.LessThanLessThanEqualsToken
+ | SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken
+ | SyntaxKind.GreaterThanGreaterThanEqualsToken
+ | SyntaxKind.BarBarEqualsToken
+ | SyntaxKind.AmpersandAmpersandEqualsToken
+ | SyntaxKind.QuestionQuestionEqualsToken;
+
+// see: https://tc39.github.io/ecma262/#prod-AssignmentExpression
+export type AssignmentOperator =
+ | SyntaxKind.EqualsToken
+ | CompoundAssignmentOperator;
+
+// see: https://tc39.github.io/ecma262/#prod-AssignmentExpression
+export type AssignmentOperatorOrHigher =
+ | SyntaxKind.QuestionQuestionToken
+ | LogicalOperatorOrHigher
+ | AssignmentOperator;
+
+// see: https://tc39.github.io/ecma262/#prod-Expression
+export type BinaryOperator =
+ | AssignmentOperatorOrHigher
+ | SyntaxKind.CommaToken;
+
+export type LogicalOrCoalescingAssignmentOperator =
+ | SyntaxKind.AmpersandAmpersandEqualsToken
+ | SyntaxKind.BarBarEqualsToken
+ | SyntaxKind.QuestionQuestionEqualsToken;
+
+export type BinaryOperatorToken = Token;
+
+export interface BinaryExpression extends Expression, Declaration {
+ readonly kind: SyntaxKind.BinaryExpression;
+ readonly left: Expression;
+ readonly operatorToken: BinaryOperatorToken;
+ readonly right: Expression;
+}
+
+export type AssignmentOperatorToken = Token;
+
+export interface AssignmentExpression extends BinaryExpression {
+ readonly left: LeftHandSideExpression;
+ readonly operatorToken: TOperator;
+}
+
+export interface ObjectDestructuringAssignment extends AssignmentExpression {
+ readonly left: ObjectLiteralExpression;
+}
+
+export interface ArrayDestructuringAssignment extends AssignmentExpression {
+ readonly left: ArrayLiteralExpression;
+}
+
+export type DestructuringAssignment =
+ | ObjectDestructuringAssignment
+ | ArrayDestructuringAssignment;
+
+export type BindingOrAssignmentElement =
+ | VariableDeclaration
+ | ParameterDeclaration
+ | ObjectBindingOrAssignmentElement
+ | ArrayBindingOrAssignmentElement;
+
+export type ObjectBindingOrAssignmentElement =
+ | BindingElement
+ | PropertyAssignment // AssignmentProperty
+ | ShorthandPropertyAssignment // AssignmentProperty
+ | SpreadAssignment // AssignmentRestProperty
+;
+
+export type ArrayBindingOrAssignmentElement =
+ | BindingElement
+ | OmittedExpression // Elision
+ | SpreadElement // AssignmentRestElement
+ | ArrayLiteralExpression // ArrayAssignmentPattern
+ | ObjectLiteralExpression // ObjectAssignmentPattern
+ | AssignmentExpression // AssignmentElement
+ | Identifier // DestructuringAssignmentTarget
+ | PropertyAccessExpression // DestructuringAssignmentTarget
+ | ElementAccessExpression // DestructuringAssignmentTarget
+;
+
+export type BindingOrAssignmentElementRestIndicator =
+ | DotDotDotToken // from BindingElement
+ | SpreadElement // AssignmentRestElement
+ | SpreadAssignment // AssignmentRestProperty
+;
+
+export type BindingOrAssignmentElementTarget =
+ | BindingOrAssignmentPattern
+ | Identifier
+ | PropertyAccessExpression
+ | ElementAccessExpression
+ | OmittedExpression;
+
+export type ObjectBindingOrAssignmentPattern =
+ | ObjectBindingPattern
+ | ObjectLiteralExpression // ObjectAssignmentPattern
+;
+
+export type ArrayBindingOrAssignmentPattern =
+ | ArrayBindingPattern
+ | ArrayLiteralExpression // ArrayAssignmentPattern
+;
+
+export type AssignmentPattern = ObjectLiteralExpression | ArrayLiteralExpression;
+
+export type BindingOrAssignmentPattern = ObjectBindingOrAssignmentPattern | ArrayBindingOrAssignmentPattern;
+
+export interface ConditionalExpression extends Expression {
+ readonly kind: SyntaxKind.ConditionalExpression;
+ readonly condition: Expression;
+ readonly questionToken: QuestionToken;
+ readonly whenTrue: Expression;
+ readonly colonToken: ColonToken;
+ readonly whenFalse: Expression;
+}
+
+export type FunctionBody = Block;
+export type ConciseBody = FunctionBody | Expression;
+
+export interface FunctionExpression extends PrimaryExpression, FunctionLikeDeclarationBase {
+ readonly kind: SyntaxKind.FunctionExpression;
+ readonly modifiers?: NodeArray;
+ readonly name?: Identifier;
+ readonly body: FunctionBody; // Required, whereas the member inherited from FunctionDeclaration is optional
+}
+
+export interface ArrowFunction extends Expression, FunctionLikeDeclarationBase {
+ readonly kind: SyntaxKind.ArrowFunction;
+ readonly modifiers?: NodeArray;
+ readonly equalsGreaterThanToken: EqualsGreaterThanToken;
+ readonly body: ConciseBody;
+ readonly name: never;
+}
+
+// The text property of a LiteralExpression stores the interpreted value of the literal in text form. For a StringLiteral,
+// or any literal of a template, this means quotes have been removed and escapes have been converted to actual characters.
+// For a NumericLiteral, the stored value is the toString() representation of the number. For example 1, 1.00, and 1e0 are all stored as just "1".
+export interface LiteralLikeNode extends Node {
+ text: string;
+ isUnterminated?: boolean;
+ hasExtendedUnicodeEscape?: boolean;
+}
+
+export interface TemplateLiteralLikeNode extends LiteralLikeNode {
+ rawText?: string;
+ templateFlags?: TokenFlags;
+}
+
+// The text property of a LiteralExpression stores the interpreted value of the literal in text form. For a StringLiteral,
+// or any literal of a template, this means quotes have been removed and escapes have been converted to actual characters.
+// For a NumericLiteral, the stored value is the toString() representation of the number. For example 1, 1.00, and 1e0 are all stored as just "1".
+export interface LiteralExpression extends LiteralLikeNode, PrimaryExpression {
+ _literalExpressionBrand: any;
+}
+
+export interface RegularExpressionLiteral extends LiteralExpression {
+ readonly kind: SyntaxKind.RegularExpressionLiteral;
+}
+
+// dprint-ignore
+export interface NoSubstitutionTemplateLiteral extends LiteralExpression, TemplateLiteralLikeNode, Declaration {
+ readonly kind: SyntaxKind.NoSubstitutionTemplateLiteral;
+}
+
+export interface NumericLiteral extends LiteralExpression, Declaration {
+ readonly kind: SyntaxKind.NumericLiteral;
+ readonly numericLiteralFlags: TokenFlags;
+}
+
+export interface BigIntLiteral extends LiteralExpression {
+ readonly kind: SyntaxKind.BigIntLiteral;
+}
+
+export type LiteralToken =
+ | NumericLiteral
+ | BigIntLiteral
+ | StringLiteral
+ | JsxText
+ | RegularExpressionLiteral
+ | NoSubstitutionTemplateLiteral;
+
+export interface TemplateHead extends TemplateLiteralLikeNode {
+ readonly kind: SyntaxKind.TemplateHead;
+ readonly parent: TemplateExpression | TemplateLiteralTypeNode;
+ templateFlags: TokenFlags;
+}
+
+export interface TemplateMiddle extends TemplateLiteralLikeNode {
+ readonly kind: SyntaxKind.TemplateMiddle;
+ readonly parent: TemplateSpan | TemplateLiteralTypeSpan;
+ templateFlags: TokenFlags;
+}
+
+export interface TemplateTail extends TemplateLiteralLikeNode {
+ readonly kind: SyntaxKind.TemplateTail;
+ readonly parent: TemplateSpan | TemplateLiteralTypeSpan;
+ templateFlags: TokenFlags;
+}
+
+export type PseudoLiteralToken =
+ | TemplateHead
+ | TemplateMiddle
+ | TemplateTail;
+
+export type TemplateLiteralToken =
+ | NoSubstitutionTemplateLiteral
+ | PseudoLiteralToken;
+
+export interface TemplateExpression extends PrimaryExpression {
+ readonly kind: SyntaxKind.TemplateExpression;
+ readonly head: TemplateHead;
+ readonly templateSpans: NodeArray;
+}
+
+export type TemplateLiteral =
+ | TemplateExpression
+ | NoSubstitutionTemplateLiteral;
+
+// Each of these corresponds to a substitution expression and a template literal, in that order.
+// The template literal must have kind TemplateMiddleLiteral or TemplateTailLiteral.
+export interface TemplateSpan extends Node {
+ readonly kind: SyntaxKind.TemplateSpan;
+ readonly parent: TemplateExpression;
+ readonly expression: Expression;
+ readonly literal: TemplateMiddle | TemplateTail;
+}
+
+export interface ParenthesizedExpression extends PrimaryExpression {
+ readonly kind: SyntaxKind.ParenthesizedExpression;
+ readonly expression: Expression;
+}
+
+export interface ArrayLiteralExpression extends PrimaryExpression {
+ readonly kind: SyntaxKind.ArrayLiteralExpression;
+ readonly elements: NodeArray;
+ multiLine?: boolean;
+}
+
+export interface SpreadElement extends Expression {
+ readonly kind: SyntaxKind.SpreadElement;
+ readonly parent: ArrayLiteralExpression | CallExpression | NewExpression;
+ readonly expression: Expression;
+}
+
+/**
+ * This interface is a base interface for ObjectLiteralExpression and JSXAttributes to extend from. JSXAttributes is similar to
+ * ObjectLiteralExpression in that it contains array of properties; however, JSXAttributes' properties can only be
+ * JSXAttribute or JSXSpreadAttribute. ObjectLiteralExpression, on the other hand, can only have properties of type
+ * ObjectLiteralElement (e.g. PropertyAssignment, ShorthandPropertyAssignment etc.)
+ */
+export interface ObjectLiteralExpressionBase extends PrimaryExpression, Declaration {
+ readonly properties: NodeArray;
+}
+
+// An ObjectLiteralExpression is the declaration node for an anonymous symbol.
+export interface ObjectLiteralExpression extends ObjectLiteralExpressionBase {
+ readonly kind: SyntaxKind.ObjectLiteralExpression;
+ multiLine?: boolean;
+}
+
+export type EntityNameExpression = Identifier | PropertyAccessEntityNameExpression;
+export type EntityNameOrEntityNameExpression = EntityName | EntityNameExpression;
+export type AccessExpression = PropertyAccessExpression | ElementAccessExpression;
+
+export interface PropertyAccessExpression extends MemberExpression, NamedDeclaration {
+ readonly kind: SyntaxKind.PropertyAccessExpression;
+ readonly expression: LeftHandSideExpression;
+ readonly questionDotToken?: QuestionDotToken;
+ readonly name: MemberName;
+}
+
+export interface PropertyAccessChain extends PropertyAccessExpression {
+ _optionalChainBrand: any;
+ readonly name: MemberName;
+}
+
+export interface SuperPropertyAccessExpression extends PropertyAccessExpression {
+ readonly expression: SuperExpression;
+}
+
+/** Brand for a PropertyAccessExpression which, like a QualifiedName, consists of a sequence of identifiers separated by dots. */
+export interface PropertyAccessEntityNameExpression extends PropertyAccessExpression {
+ _propertyAccessExpressionLikeQualifiedNameBrand?: any;
+ readonly expression: EntityNameExpression;
+ readonly name: Identifier;
+}
+
+export interface ElementAccessExpression extends MemberExpression, Declaration {
+ readonly kind: SyntaxKind.ElementAccessExpression;
+ readonly expression: LeftHandSideExpression;
+ readonly questionDotToken?: QuestionDotToken;
+ readonly argumentExpression: Expression;
+}
+
+export interface ElementAccessChain extends ElementAccessExpression {
+ _optionalChainBrand: any;
+}
+
+export interface SuperElementAccessExpression extends ElementAccessExpression {
+ readonly expression: SuperExpression;
+}
+
+// see: https://tc39.github.io/ecma262/#prod-SuperProperty
+export type SuperProperty = SuperPropertyAccessExpression | SuperElementAccessExpression;
+
+export interface CallExpression extends LeftHandSideExpression, Declaration {
+ readonly kind: SyntaxKind.CallExpression;
+ readonly expression: LeftHandSideExpression;
+ readonly questionDotToken?: QuestionDotToken;
+ readonly typeArguments?: NodeArray;
+ readonly arguments: NodeArray;
+}
+
+export interface CallChain extends CallExpression {
+ _optionalChainBrand: any;
+}
+
+export type OptionalChain =
+ | PropertyAccessChain
+ | ElementAccessChain
+ | CallChain
+ | NonNullChain;
+
+// see: https://tc39.github.io/ecma262/#prod-SuperCall
+export interface SuperCall extends CallExpression {
+ readonly expression: SuperExpression;
+}
+
+export interface ImportCall extends CallExpression {
+ readonly expression: ImportExpression;
+}
+
+export interface ExpressionWithTypeArguments extends MemberExpression, NodeWithTypeArguments {
+ readonly kind: SyntaxKind.ExpressionWithTypeArguments;
+ readonly expression: LeftHandSideExpression;
+}
+
+export interface NewExpression extends PrimaryExpression, Declaration {
+ readonly kind: SyntaxKind.NewExpression;
+ readonly expression: LeftHandSideExpression;
+ readonly typeArguments?: NodeArray;
+ readonly arguments?: NodeArray;
+}
+
+export interface TaggedTemplateExpression extends MemberExpression {
+ readonly kind: SyntaxKind.TaggedTemplateExpression;
+ readonly tag: LeftHandSideExpression;
+ readonly typeArguments?: NodeArray;
+ readonly template: TemplateLiteral;
+}
+
+export interface InstanceofExpression extends BinaryExpression {
+ readonly operatorToken: Token;
+}
+
+export type CallLikeExpression =
+ | CallExpression
+ | NewExpression
+ | TaggedTemplateExpression
+ | Decorator
+ | JsxOpeningLikeElement
+ | InstanceofExpression;
+
+export interface AsExpression extends Expression {
+ readonly kind: SyntaxKind.AsExpression;
+ readonly expression: Expression;
+ readonly type: TypeNode;
+}
+
+export interface TypeAssertion extends UnaryExpression {
+ readonly kind: SyntaxKind.TypeAssertionExpression;
+ readonly type: TypeNode;
+ readonly expression: UnaryExpression;
+}
+
+export interface SatisfiesExpression extends Expression {
+ readonly kind: SyntaxKind.SatisfiesExpression;
+ readonly expression: Expression;
+ readonly type: TypeNode;
+}
+
+export type AssertionExpression =
+ | TypeAssertion
+ | AsExpression;
+
+export interface NonNullExpression extends LeftHandSideExpression {
+ readonly kind: SyntaxKind.NonNullExpression;
+ readonly expression: Expression;
+}
+
+export interface NonNullChain extends NonNullExpression {
+ _optionalChainBrand: any;
+}
+
+// NOTE: MetaProperty is really a MemberExpression, but we consider it a PrimaryExpression
+// for the same reasons we treat NewExpression as a PrimaryExpression.
+export interface MetaProperty extends PrimaryExpression {
+ readonly kind: SyntaxKind.MetaProperty;
+ readonly keywordToken: SyntaxKind.NewKeyword | SyntaxKind.ImportKeyword;
+ readonly name: Identifier;
+}
+
+/// A JSX expression of the form ...
+export interface JsxElement extends PrimaryExpression {
+ readonly kind: SyntaxKind.JsxElement;
+ readonly openingElement: JsxOpeningElement;
+ readonly children: NodeArray;
+ readonly closingElement: JsxClosingElement;
+}
+
+/// Either the opening tag in a ... pair or the lone in a self-closing form
+export type JsxOpeningLikeElement =
+ | JsxSelfClosingElement
+ | JsxOpeningElement;
+
+export type JsxAttributeLike =
+ | JsxAttribute
+ | JsxSpreadAttribute;
+
+export type JsxAttributeName =
+ | Identifier
+ | JsxNamespacedName;
+
+export type JsxTagNameExpression =
+ | Identifier
+ | ThisExpression
+ | JsxTagNamePropertyAccess
+ | JsxNamespacedName;
+
+export interface JsxTagNamePropertyAccess extends PropertyAccessExpression {
+ readonly expression: Identifier | ThisExpression | JsxTagNamePropertyAccess;
+}
+
+export interface JsxAttributes extends PrimaryExpression, Declaration {
+ readonly properties: NodeArray;
+ readonly kind: SyntaxKind.JsxAttributes;
+ readonly parent: JsxOpeningLikeElement;
+}
+
+export interface JsxNamespacedName extends Node {
+ readonly kind: SyntaxKind.JsxNamespacedName;
+ readonly name: Identifier;
+ readonly namespace: Identifier;
+}
+
+/// The opening element of a ... JsxElement
+export interface JsxOpeningElement extends Expression {
+ readonly kind: SyntaxKind.JsxOpeningElement;
+ readonly parent: JsxElement;
+ readonly tagName: JsxTagNameExpression;
+ readonly typeArguments?: NodeArray;
+ readonly attributes: JsxAttributes;
+}
+
+/// A JSX expression of the form
+export interface JsxSelfClosingElement extends PrimaryExpression {
+ readonly kind: SyntaxKind.JsxSelfClosingElement;
+ readonly tagName: JsxTagNameExpression;
+ readonly typeArguments?: NodeArray;
+ readonly attributes: JsxAttributes;
+}
+
+/// A JSX expression of the form <>...>
+export interface JsxFragment extends PrimaryExpression {
+ readonly kind: SyntaxKind.JsxFragment;
+ readonly openingFragment: JsxOpeningFragment;
+ readonly children: NodeArray;
+ readonly closingFragment: JsxClosingFragment;
+}
+
+/// The opening element of a <>...> JsxFragment
+export interface JsxOpeningFragment extends Expression {
+ readonly kind: SyntaxKind.JsxOpeningFragment;
+ readonly parent: JsxFragment;
+}
+
+/// The closing element of a <>...> JsxFragment
+export interface JsxClosingFragment extends Expression {
+ readonly kind: SyntaxKind.JsxClosingFragment;
+ readonly parent: JsxFragment;
+}
+
+export interface JsxAttribute extends Declaration {
+ readonly kind: SyntaxKind.JsxAttribute;
+ readonly parent: JsxAttributes;
+ readonly name: JsxAttributeName;
+ /// JSX attribute initializers are optional; is sugar for
+ readonly initializer?: JsxAttributeValue;
+}
+
+export type JsxAttributeValue =
+ | StringLiteral
+ | JsxExpression
+ | JsxElement
+ | JsxSelfClosingElement
+ | JsxFragment;
+
+export interface JsxSpreadAttribute extends ObjectLiteralElement {
+ readonly kind: SyntaxKind.JsxSpreadAttribute;
+ readonly parent: JsxAttributes;
+ readonly expression: Expression;
+}
+
+export interface JsxClosingElement extends Node {
+ readonly kind: SyntaxKind.JsxClosingElement;
+ readonly parent: JsxElement;
+ readonly tagName: JsxTagNameExpression;
+}
+
+export interface JsxExpression extends Expression {
+ readonly kind: SyntaxKind.JsxExpression;
+ readonly parent: JsxElement | JsxFragment | JsxAttributeLike;
+ readonly dotDotDotToken?: Token;
+ readonly expression?: Expression;
+}
+
+export interface JsxText extends LiteralLikeNode {
+ readonly kind: SyntaxKind.JsxText;
+ readonly parent: JsxElement | JsxFragment;
+ readonly containsOnlyTriviaWhiteSpaces: boolean;
+}
+
+export type JsxChild =
+ | JsxText
+ | JsxExpression
+ | JsxElement
+ | JsxSelfClosingElement
+ | JsxFragment;
+
+export interface Statement extends Node {
+ _statementBrand: any;
+}
+
+/**
+ * A list of comma-separated expressions. This node is only created by transformations.
+ */
+export interface CommaListExpression extends Expression {
+ readonly kind: SyntaxKind.CommaListExpression;
+ readonly elements: NodeArray;
+}
+
+export interface EmptyStatement extends Statement {
+ readonly kind: SyntaxKind.EmptyStatement;
+}
+
+export interface DebuggerStatement extends Statement {
+ readonly kind: SyntaxKind.DebuggerStatement;
+}
+
+export interface Block extends Statement {
+ readonly kind: SyntaxKind.Block;
+ readonly statements: NodeArray;
+ multiLine?: boolean;
+}
+
+export interface VariableStatement extends Statement {
+ readonly kind: SyntaxKind.VariableStatement;
+ readonly modifiers?: NodeArray;
+ readonly declarationList: VariableDeclarationList;
+}
+
+export interface ExpressionStatement extends Statement {
+ readonly kind: SyntaxKind.ExpressionStatement;
+ readonly expression: Expression;
+}
+
+export interface IfStatement extends Statement {
+ readonly kind: SyntaxKind.IfStatement;
+ readonly expression: Expression;
+ readonly thenStatement: Statement;
+ readonly elseStatement?: Statement;
+}
+
+export interface IterationStatement extends Statement {
+ readonly statement: Statement;
+}
+
+export interface DoStatement extends IterationStatement {
+ readonly kind: SyntaxKind.DoStatement;
+ readonly expression: Expression;
+}
+
+export interface WhileStatement extends IterationStatement {
+ readonly kind: SyntaxKind.WhileStatement;
+ readonly expression: Expression;
+}
+
+export type ForInitializer =
+ | VariableDeclarationList
+ | Expression;
+
+export interface ForStatement extends IterationStatement {
+ readonly kind: SyntaxKind.ForStatement;
+ readonly initializer?: ForInitializer;
+ readonly condition?: Expression;
+ readonly incrementor?: Expression;
+}
+
+export type ForInOrOfStatement =
+ | ForInStatement
+ | ForOfStatement;
+
+export interface ForInStatement extends IterationStatement {
+ readonly kind: SyntaxKind.ForInStatement;
+ readonly initializer: ForInitializer;
+ readonly expression: Expression;
+}
+
+export interface ForOfStatement extends IterationStatement {
+ readonly kind: SyntaxKind.ForOfStatement;
+ readonly awaitModifier?: AwaitKeyword;
+ readonly initializer: ForInitializer;
+ readonly expression: Expression;
+}
+
+export interface BreakStatement extends Statement {
+ readonly kind: SyntaxKind.BreakStatement;
+ readonly label?: Identifier;
+}
+
+export interface ContinueStatement extends Statement {
+ readonly kind: SyntaxKind.ContinueStatement;
+ readonly label?: Identifier;
+}
+
+export type BreakOrContinueStatement =
+ | BreakStatement
+ | ContinueStatement;
+
+export interface ReturnStatement extends Statement {
+ readonly kind: SyntaxKind.ReturnStatement;
+ readonly expression?: Expression;
+}
+
+export interface WithStatement extends Statement {
+ readonly kind: SyntaxKind.WithStatement;
+ readonly expression: Expression;
+ readonly statement: Statement;
+}
+
+export interface SwitchStatement extends Statement {
+ readonly kind: SyntaxKind.SwitchStatement;
+ readonly expression: Expression;
+ readonly caseBlock: CaseBlock;
+ possiblyExhaustive?: boolean; // initialized by binding
+}
+
+export interface CaseBlock extends Node {
+ readonly kind: SyntaxKind.CaseBlock;
+ readonly parent: SwitchStatement;
+ readonly clauses: NodeArray;
+}
+
+export interface CaseClause extends Node {
+ readonly kind: SyntaxKind.CaseClause;
+ readonly parent: CaseBlock;
+ readonly expression: Expression;
+ readonly statements: NodeArray;
+}
+
+export interface DefaultClause extends Node {
+ readonly kind: SyntaxKind.DefaultClause;
+ readonly parent: CaseBlock;
+ readonly statements: NodeArray;
+}
+
+export type CaseOrDefaultClause =
+ | CaseClause
+ | DefaultClause;
+
+export interface LabeledStatement extends Statement {
+ readonly kind: SyntaxKind.LabeledStatement;
+ readonly label: Identifier;
+ readonly statement: Statement;
+}
+
+export interface ThrowStatement extends Statement {
+ readonly kind: SyntaxKind.ThrowStatement;
+ readonly expression: Expression;
+}
+
+export interface TryStatement extends Statement {
+ readonly kind: SyntaxKind.TryStatement;
+ readonly tryBlock: Block;
+ readonly catchClause?: CatchClause;
+ readonly finallyBlock?: Block;
+}
+
+export interface CatchClause extends Node {
+ readonly kind: SyntaxKind.CatchClause;
+ readonly parent: TryStatement;
+ readonly variableDeclaration?: VariableDeclaration;
+ readonly block: Block;
+}
+
+export type ObjectTypeDeclaration =
+ | ClassLikeDeclaration
+ | InterfaceDeclaration
+ | TypeLiteralNode;
+
+export type DeclarationWithTypeParameters =
+ | DeclarationWithTypeParameterChildren
+ | JSDocTypedefTag
+ | JSDocCallbackTag
+ | JSDocSignature;
+
+export type DeclarationWithTypeParameterChildren =
+ | SignatureDeclaration
+ | ClassLikeDeclaration
+ | InterfaceDeclaration
+ | TypeAliasDeclaration
+ | JSDocTemplateTag;
+
+export interface ClassLikeDeclarationBase extends NamedDeclaration {
+ readonly kind: SyntaxKind.ClassDeclaration | SyntaxKind.ClassExpression;
+ readonly name?: Identifier;
+ readonly typeParameters?: NodeArray;
+ readonly heritageClauses?: NodeArray;
+ readonly members: NodeArray;
+}
+
+export interface ClassDeclaration extends ClassLikeDeclarationBase, DeclarationStatement {
+ readonly kind: SyntaxKind.ClassDeclaration;
+ readonly modifiers?: NodeArray;
+ /** May be undefined in `export default class { ... }`. */
+ readonly name?: Identifier;
+}
+
+export interface ClassExpression extends ClassLikeDeclarationBase, PrimaryExpression {
+ readonly kind: SyntaxKind.ClassExpression;
+ readonly modifiers?: NodeArray;
+}
+
+export type ClassLikeDeclaration =
+ | ClassDeclaration
+ | ClassExpression;
+
+export interface ClassElement extends NamedDeclaration {
+ _classElementBrand: any;
+ readonly name?: PropertyName;
+}
+
+export interface TypeElement extends NamedDeclaration {
+ _typeElementBrand: any;
+ readonly name?: PropertyName;
+ readonly questionToken?: QuestionToken | undefined;
+}
+
+export interface InterfaceDeclaration extends DeclarationStatement {
+ readonly kind: SyntaxKind.InterfaceDeclaration;
+ readonly modifiers?: NodeArray;
+ readonly name: Identifier;
+ readonly typeParameters?: NodeArray;
+ readonly heritageClauses?: NodeArray;
+ readonly members: NodeArray;
+}
+
+export interface HeritageClause extends Node {
+ readonly kind: SyntaxKind.HeritageClause;
+ readonly parent: InterfaceDeclaration | ClassLikeDeclaration;
+ readonly token: SyntaxKind.ExtendsKeyword | SyntaxKind.ImplementsKeyword;
+ readonly types: NodeArray;
+}
+
+export interface TypeAliasDeclaration extends DeclarationStatement {
+ readonly kind: SyntaxKind.TypeAliasDeclaration;
+ readonly modifiers?: NodeArray;
+ readonly name: Identifier;
+ readonly typeParameters?: NodeArray;
+ readonly type: TypeNode;
+}
+
+export interface EnumMember extends NamedDeclaration {
+ readonly kind: SyntaxKind.EnumMember;
+ readonly parent: EnumDeclaration;
+ // This does include ComputedPropertyName, but the parser will give an error
+ // if it parses a ComputedPropertyName in an EnumMember
+ readonly name: PropertyName;
+ readonly initializer?: Expression;
+}
+
+export interface EnumDeclaration extends DeclarationStatement {
+ readonly kind: SyntaxKind.EnumDeclaration;
+ readonly modifiers?: NodeArray;
+ readonly name: Identifier;
+ readonly members: NodeArray;
+}
+
+export type ModuleName =
+ | Identifier
+ | StringLiteral;
+
+export type ModuleBody =
+ | NamespaceBody
+ | JSDocNamespaceBody;
+
+export interface ModuleDeclaration extends DeclarationStatement {
+ readonly kind: SyntaxKind.ModuleDeclaration;
+ readonly parent: ModuleBody | SourceFile;
+ readonly modifiers?: NodeArray;
+ readonly name: ModuleName;
+ readonly body?: ModuleBody | JSDocNamespaceDeclaration;
+}
+
+export type NamespaceBody =
+ | ModuleBlock
+ | NamespaceDeclaration;
+
+export interface NamespaceDeclaration extends ModuleDeclaration {
+ readonly name: Identifier;
+ readonly body: NamespaceBody;
+}
+
+export type JSDocNamespaceBody =
+ | Identifier
+ | JSDocNamespaceDeclaration;
+
+export interface JSDocNamespaceDeclaration extends ModuleDeclaration {
+ readonly name: Identifier;
+ readonly body?: JSDocNamespaceBody;
+}
+
+export interface ModuleBlock extends Node, Statement {
+ readonly kind: SyntaxKind.ModuleBlock;
+ readonly parent: ModuleDeclaration;
+ readonly statements: NodeArray;
+}
+
+export type ModuleReference =
+ | EntityName
+ | ExternalModuleReference;
+
+/**
+ * One of:
+ * - import x = require("mod");
+ * - import x = M.x;
+ */
+export interface ImportEqualsDeclaration extends DeclarationStatement {
+ readonly kind: SyntaxKind.ImportEqualsDeclaration;
+ readonly parent: SourceFile | ModuleBlock;
+ readonly modifiers?: NodeArray;
+ readonly name: Identifier;
+ readonly isTypeOnly: boolean;
+
+ // 'EntityName' for an internal module reference, 'ExternalModuleReference' for an external
+ // module reference.
+ readonly moduleReference: ModuleReference;
+}
+
+export interface ExternalModuleReference extends Node {
+ readonly kind: SyntaxKind.ExternalModuleReference;
+ readonly parent: ImportEqualsDeclaration;
+ readonly expression: Expression;
+}
+
+// In case of:
+// import "mod" => importClause = undefined, moduleSpecifier = "mod"
+// In rest of the cases, module specifier is string literal corresponding to module
+// ImportClause information is shown at its declaration below.
+export interface ImportDeclaration extends Statement {
+ readonly kind: SyntaxKind.ImportDeclaration;
+ readonly parent: SourceFile | ModuleBlock;
+ readonly modifiers?: NodeArray;
+ readonly importClause?: ImportClause;
+ /** If this is not a StringLiteral it will be a grammar error. */
+ readonly moduleSpecifier: Expression;
+ /** @deprecated */ readonly assertClause?: AssertClause;
+ readonly attributes?: ImportAttributes;
+}
+
+export type NamedImportBindings =
+ | NamespaceImport
+ | NamedImports;
+
+export type NamedExportBindings =
+ | NamespaceExport
+ | NamedExports;
+
+// In case of:
+// import d from "mod" => name = d, namedBinding = undefined
+// import * as ns from "mod" => name = undefined, namedBinding: NamespaceImport = { name: ns }
+// import d, * as ns from "mod" => name = d, namedBinding: NamespaceImport = { name: ns }
+// import { a, b as x } from "mod" => name = undefined, namedBinding: NamedImports = { elements: [{ name: a }, { name: x, propertyName: b}]}
+// import d, { a, b as x } from "mod" => name = d, namedBinding: NamedImports = { elements: [{ name: a }, { name: x, propertyName: b}]}
+export interface ImportClause extends NamedDeclaration {
+ readonly kind: SyntaxKind.ImportClause;
+ readonly parent: ImportDeclaration | JSDocImportTag;
+ readonly isTypeOnly: boolean;
+ readonly name?: Identifier; // Default binding
+ readonly namedBindings?: NamedImportBindings;
+}
+
+/** @deprecated */
+export type AssertionKey = ImportAttributeName;
+
+/** @deprecated */
+export interface AssertEntry extends ImportAttribute {}
+
+/** @deprecated */
+export interface AssertClause extends ImportAttributes {}
+
+export type ImportAttributeName = Identifier | StringLiteral;
+
+export interface ImportAttribute extends Node {
+ readonly kind: SyntaxKind.ImportAttribute;
+ readonly parent: ImportAttributes;
+ readonly name: ImportAttributeName;
+ readonly value: Expression;
+}
+
+export interface ImportAttributes extends Node {
+ readonly token: SyntaxKind.WithKeyword | SyntaxKind.AssertKeyword;
+ readonly kind: SyntaxKind.ImportAttributes;
+ readonly parent: ImportDeclaration | ExportDeclaration;
+ readonly elements: NodeArray;
+ readonly multiLine?: boolean;
+}
+
+export interface NamespaceImport extends NamedDeclaration {
+ readonly kind: SyntaxKind.NamespaceImport;
+ readonly parent: ImportClause;
+ readonly name: Identifier;
+}
+
+export interface NamespaceExport extends NamedDeclaration {
+ readonly kind: SyntaxKind.NamespaceExport;
+ readonly parent: ExportDeclaration;
+ readonly name: ModuleExportName;
+}
+
+export interface NamespaceExportDeclaration extends DeclarationStatement {
+ readonly kind: SyntaxKind.NamespaceExportDeclaration;
+ readonly name: Identifier;
+}
+
+export interface ExportDeclaration extends DeclarationStatement {
+ readonly kind: SyntaxKind.ExportDeclaration;
+ readonly parent: SourceFile | ModuleBlock;
+ readonly modifiers?: NodeArray;
+ readonly isTypeOnly: boolean;
+ /** Will not be assigned in the case of `export * from "foo";` */
+ readonly exportClause?: NamedExportBindings;
+ /** If this is not a StringLiteral it will be a grammar error. */
+ readonly moduleSpecifier?: Expression;
+ /** @deprecated */ readonly assertClause?: AssertClause;
+ readonly attributes?: ImportAttributes;
+}
+
+export interface NamedImports extends Node {
+ readonly kind: SyntaxKind.NamedImports;
+ readonly parent: ImportClause;
+ readonly elements: NodeArray;
+}
+
+export interface NamedExports extends Node {
+ readonly kind: SyntaxKind.NamedExports;
+ readonly parent: ExportDeclaration;
+ readonly elements: NodeArray;
+}
+
+export type NamedImportsOrExports = NamedImports | NamedExports;
+
+export interface ImportSpecifier extends NamedDeclaration {
+ readonly kind: SyntaxKind.ImportSpecifier;
+ readonly parent: NamedImports;
+ readonly propertyName?: ModuleExportName; // Name preceding "as" keyword (or undefined when "as" is absent)
+ readonly name: Identifier; // Declared name
+ readonly isTypeOnly: boolean;
+}
+
+export interface ExportSpecifier extends NamedDeclaration {
+ readonly kind: SyntaxKind.ExportSpecifier;
+ readonly parent: NamedExports;
+ readonly isTypeOnly: boolean;
+ readonly propertyName?: ModuleExportName; // Name preceding "as" keyword (or undefined when "as" is absent)
+ readonly name: ModuleExportName; // Declared name
+}
+
+export type ModuleExportName = Identifier | StringLiteral;
+
+export type ImportOrExportSpecifier =
+ | ImportSpecifier
+ | ExportSpecifier;
+
+export type TypeOnlyCompatibleAliasDeclaration =
+ | ImportClause
+ | ImportEqualsDeclaration
+ | NamespaceImport
+ | ImportOrExportSpecifier
+ | ExportDeclaration
+ | NamespaceExport;
+
+export type TypeOnlyImportDeclaration =
+ | ImportClause & { readonly isTypeOnly: true; readonly name: Identifier; }
+ | ImportEqualsDeclaration & { readonly isTypeOnly: true; }
+ | NamespaceImport & { readonly parent: ImportClause & { readonly isTypeOnly: true; }; }
+ | ImportSpecifier & ({ readonly isTypeOnly: true; } | { readonly parent: NamedImports & { readonly parent: ImportClause & { readonly isTypeOnly: true; }; }; });
+
+export type TypeOnlyExportDeclaration =
+ | ExportSpecifier & ({ readonly isTypeOnly: true; } | { readonly parent: NamedExports & { readonly parent: ExportDeclaration & { readonly isTypeOnly: true; }; }; })
+ | ExportDeclaration & { readonly isTypeOnly: true; readonly moduleSpecifier: Expression; } // export * from "mod"
+ | NamespaceExport & { readonly parent: ExportDeclaration & { readonly isTypeOnly: true; readonly moduleSpecifier: Expression; }; } // export * as ns from "mod"
+;
+
+export type TypeOnlyAliasDeclaration = TypeOnlyImportDeclaration | TypeOnlyExportDeclaration;
+
+/**
+ * This is either an `export =` or an `export default` declaration.
+ * Unless `isExportEquals` is set, this node was parsed as an `export default`.
+ */
+export interface ExportAssignment extends DeclarationStatement {
+ readonly kind: SyntaxKind.ExportAssignment;
+ readonly parent: SourceFile;
+ readonly modifiers?: NodeArray;
+ readonly isExportEquals?: boolean;
+ readonly expression: Expression;
+}
+
+// represents a top level: { type } expression in a JSDoc comment.
+export interface JSDocTypeExpression extends TypeNode {
+ readonly kind: SyntaxKind.JSDocTypeExpression;
+ readonly type: TypeNode;
+}
+
+export interface JSDocNameReference extends Node {
+ readonly kind: SyntaxKind.JSDocNameReference;
+ readonly name: EntityName | JSDocMemberName;
+}
+
+/** Class#method reference in JSDoc */
+export interface JSDocMemberName extends Node {
+ readonly kind: SyntaxKind.JSDocMemberName;
+ readonly left: EntityName | JSDocMemberName;
+ readonly right: Identifier;
+}
+
+export interface JSDocType extends TypeNode {
+ _jsDocTypeBrand: any;
+}
+
+export interface JSDocAllType extends JSDocType {
+ readonly kind: SyntaxKind.JSDocAllType;
+}
+
+export interface JSDocNonNullableType extends JSDocType {
+ readonly kind: SyntaxKind.JSDocNonNullableType;
+ readonly type: TypeNode;
+ readonly postfix: boolean;
+}
+
+export interface JSDocNullableType extends JSDocType {
+ readonly kind: SyntaxKind.JSDocNullableType;
+ readonly type: TypeNode;
+ readonly postfix: boolean;
+}
+
+export interface JSDocOptionalType extends JSDocType {
+ readonly kind: SyntaxKind.JSDocOptionalType;
+ readonly type: TypeNode;
+}
+
+export interface JSDocVariadicType extends JSDocType {
+ readonly kind: SyntaxKind.JSDocVariadicType;
+ readonly type: TypeNode;
+}
+
+export type JSDocTypeReferencingNode =
+ | JSDocVariadicType
+ | JSDocOptionalType
+ | JSDocNullableType
+ | JSDocNonNullableType;
+
+export interface JSDoc extends Node {
+ readonly kind: SyntaxKind.JSDoc;
+ readonly parent: HasJSDoc;
+ readonly tags?: NodeArray;
+ readonly comment?: string | NodeArray;
+}
+
+export interface JSDocTag extends Node {
+ readonly parent: JSDoc | JSDocTypeLiteral;
+ readonly tagName: Identifier;
+ readonly comment?: string | NodeArray;
+}
+
+export interface JSDocLink extends Node {
+ readonly kind: SyntaxKind.JSDocLink;
+ readonly name?: EntityName | JSDocMemberName;
+ text: string;
+}
+
+export interface JSDocLinkCode extends Node {
+ readonly kind: SyntaxKind.JSDocLinkCode;
+ readonly name?: EntityName | JSDocMemberName;
+ text: string;
+}
+
+export interface JSDocLinkPlain extends Node {
+ readonly kind: SyntaxKind.JSDocLinkPlain;
+ readonly name?: EntityName | JSDocMemberName;
+ text: string;
+}
+
+export type JSDocComment = JSDocText | JSDocLink | JSDocLinkCode | JSDocLinkPlain;
+
+export interface JSDocText extends Node {
+ readonly kind: SyntaxKind.JSDocText;
+ text: string;
+}
+
+export interface JSDocUnknownTag extends JSDocTag {
+ readonly kind: SyntaxKind.JSDocTag;
+}
+
+/**
+ * Note that `@extends` is a synonym of `@augments`.
+ * Both tags are represented by this interface.
+ */
+export interface JSDocAugmentsTag extends JSDocTag {
+ readonly kind: SyntaxKind.JSDocAugmentsTag;
+ readonly class: ExpressionWithTypeArguments & { readonly expression: Identifier | PropertyAccessEntityNameExpression; };
+}
+
+export interface JSDocImplementsTag extends JSDocTag {
+ readonly kind: SyntaxKind.JSDocImplementsTag;
+ readonly class: ExpressionWithTypeArguments & { readonly expression: Identifier | PropertyAccessEntityNameExpression; };
+}
+
+export interface JSDocDeprecatedTag extends JSDocTag {
+ kind: SyntaxKind.JSDocDeprecatedTag;
+}
+
+export interface JSDocPublicTag extends JSDocTag {
+ readonly kind: SyntaxKind.JSDocPublicTag;
+}
+
+export interface JSDocPrivateTag extends JSDocTag {
+ readonly kind: SyntaxKind.JSDocPrivateTag;
+}
+
+export interface JSDocProtectedTag extends JSDocTag {
+ readonly kind: SyntaxKind.JSDocProtectedTag;
+}
+
+export interface JSDocReadonlyTag extends JSDocTag {
+ readonly kind: SyntaxKind.JSDocReadonlyTag;
+}
+
+export interface JSDocOverrideTag extends JSDocTag {
+ readonly kind: SyntaxKind.JSDocOverrideTag;
+}
+
+export interface JSDocThisTag extends JSDocTag {
+ readonly kind: SyntaxKind.JSDocThisTag;
+ readonly typeExpression: JSDocTypeExpression;
+}
+
+export interface JSDocTemplateTag extends JSDocTag {
+ readonly kind: SyntaxKind.JSDocTemplateTag;
+ readonly constraint: JSDocTypeExpression | undefined;
+ readonly typeParameters: NodeArray;
+}
+
+export interface JSDocSeeTag extends JSDocTag {
+ readonly kind: SyntaxKind.JSDocSeeTag;
+ readonly name?: JSDocNameReference;
+}
+
+export interface JSDocReturnTag extends JSDocTag {
+ readonly kind: SyntaxKind.JSDocReturnTag;
+ readonly typeExpression?: JSDocTypeExpression;
+}
+
+export interface JSDocTypeTag extends JSDocTag {
+ readonly kind: SyntaxKind.JSDocTypeTag;
+ readonly typeExpression: JSDocTypeExpression;
+}
+
+export interface JSDocTypedefTag extends JSDocTag, NamedDeclaration {
+ readonly kind: SyntaxKind.JSDocTypedefTag;
+ readonly parent: JSDoc;
+ readonly fullName?: JSDocNamespaceDeclaration | Identifier;
+ readonly name?: Identifier;
+ readonly typeExpression?: JSDocTypeExpression | JSDocTypeLiteral;
+}
+
+export interface JSDocCallbackTag extends JSDocTag, NamedDeclaration {
+ readonly kind: SyntaxKind.JSDocCallbackTag;
+ readonly parent: JSDoc;
+ readonly fullName?: JSDocNamespaceDeclaration | Identifier;
+ readonly name?: Identifier;
+ readonly typeExpression: JSDocSignature;
+}
+
+export interface JSDocOverloadTag extends JSDocTag {
+ readonly kind: SyntaxKind.JSDocOverloadTag;
+ readonly parent: JSDoc;
+ readonly typeExpression: JSDocSignature;
+}
+
+export interface JSDocSignature extends JSDocType, Declaration {
+ readonly kind: SyntaxKind.JSDocSignature;
+ readonly typeParameters?: readonly JSDocTemplateTag[];
+ readonly parameters: readonly JSDocParameterTag[];
+ readonly type: JSDocReturnTag | undefined;
+}
+
+export interface JSDocPropertyLikeTag extends JSDocTag, Declaration {
+ readonly parent: JSDoc;
+ readonly name: EntityName;
+ readonly typeExpression?: JSDocTypeExpression;
+ /** Whether the property name came before the type -- non-standard for JSDoc, but Typescript-like */
+ readonly isNameFirst: boolean;
+ readonly isBracketed: boolean;
+}
+
+export interface JSDocPropertyTag extends JSDocPropertyLikeTag {
+ readonly kind: SyntaxKind.JSDocPropertyTag;
+}
+
+export interface JSDocParameterTag extends JSDocPropertyLikeTag {
+ readonly kind: SyntaxKind.JSDocParameterTag;
+}
+
+export interface JSDocTypeLiteral extends JSDocType, Declaration {
+ readonly kind: SyntaxKind.JSDocTypeLiteral;
+ readonly jsDocPropertyTags?: readonly JSDocPropertyLikeTag[];
+ /** If true, then this type literal represents an *array* of its type. */
+ readonly isArrayType: boolean;
+}
+
+export interface JSDocSatisfiesTag extends JSDocTag {
+ readonly kind: SyntaxKind.JSDocSatisfiesTag;
+ readonly typeExpression: JSDocTypeExpression;
+}
+
+export interface JSDocImportTag extends JSDocTag {
+ readonly kind: SyntaxKind.JSDocImportTag;
+ readonly parent: JSDoc;
+ readonly importClause?: ImportClause;
+ readonly moduleSpecifier: Expression;
+ readonly attributes?: ImportAttributes;
+}
+
+export type HasJSDoc =
+ | AccessorDeclaration
+ | ArrowFunction
+ | BinaryExpression
+ | Block
+ | BreakStatement
+ | CallSignatureDeclaration
+ | CaseClause
+ | ClassLikeDeclaration
+ | ClassStaticBlockDeclaration
+ | ConstructorDeclaration
+ | ConstructorTypeNode
+ | ConstructSignatureDeclaration
+ | ContinueStatement
+ | DebuggerStatement
+ | DoStatement
+ | ElementAccessExpression
+ | EmptyStatement
+ | EndOfFile
+ | EnumDeclaration
+ | EnumMember
+ | ExportAssignment
+ | ExportDeclaration
+ | ExportSpecifier
+ | ExpressionStatement
+ | ForInStatement
+ | ForOfStatement
+ | ForStatement
+ | FunctionDeclaration
+ | FunctionExpression
+ | FunctionTypeNode
+ | Identifier
+ | IfStatement
+ | ImportDeclaration
+ | ImportEqualsDeclaration
+ | IndexSignatureDeclaration
+ | InterfaceDeclaration
+ | JSDocSignature
+ | LabeledStatement
+ | MethodDeclaration
+ | MethodSignature
+ | ModuleDeclaration
+ | NamedTupleMember
+ | NamespaceExportDeclaration
+ | ObjectLiteralExpression
+ | ParameterDeclaration
+ | ParenthesizedExpression
+ | PropertyAccessExpression
+ | PropertyAssignment
+ | PropertyDeclaration
+ | PropertySignature
+ | ReturnStatement
+ | SemicolonClassElement
+ | ShorthandPropertyAssignment
+ | SpreadAssignment
+ | SwitchStatement
+ | ThrowStatement
+ | TryStatement
+ | TypeAliasDeclaration
+ | TypeParameterDeclaration
+ | VariableDeclaration
+ | VariableStatement
+ | WhileStatement
+ | WithStatement;
diff --git a/_packages/ast/src/syntaxKind.enum.ts b/_packages/ast/src/syntaxKind.enum.ts
new file mode 100644
index 0000000000..31fdf059d7
--- /dev/null
+++ b/_packages/ast/src/syntaxKind.enum.ts
@@ -0,0 +1,352 @@
+export enum SyntaxKind {
+ Unknown,
+ EndOfFile,
+ SingleLineCommentTrivia,
+ MultiLineCommentTrivia,
+ NewLineTrivia,
+ WhitespaceTrivia,
+ ConflictMarkerTrivia,
+ NonTextFileMarkerTrivia,
+ NumericLiteral,
+ BigIntLiteral,
+ StringLiteral,
+ JsxText,
+ JsxTextAllWhiteSpaces,
+ RegularExpressionLiteral,
+ NoSubstitutionTemplateLiteral,
+ TemplateHead,
+ TemplateMiddle,
+ TemplateTail,
+ OpenBraceToken,
+ CloseBraceToken,
+ OpenParenToken,
+ CloseParenToken,
+ OpenBracketToken,
+ CloseBracketToken,
+ DotToken,
+ DotDotDotToken,
+ SemicolonToken,
+ CommaToken,
+ QuestionDotToken,
+ LessThanToken,
+ LessThanSlashToken,
+ GreaterThanToken,
+ LessThanEqualsToken,
+ GreaterThanEqualsToken,
+ EqualsEqualsToken,
+ ExclamationEqualsToken,
+ EqualsEqualsEqualsToken,
+ ExclamationEqualsEqualsToken,
+ EqualsGreaterThanToken,
+ PlusToken,
+ MinusToken,
+ AsteriskToken,
+ AsteriskAsteriskToken,
+ SlashToken,
+ PercentToken,
+ PlusPlusToken,
+ MinusMinusToken,
+ LessThanLessThanToken,
+ GreaterThanGreaterThanToken,
+ GreaterThanGreaterThanGreaterThanToken,
+ AmpersandToken,
+ BarToken,
+ CaretToken,
+ ExclamationToken,
+ TildeToken,
+ AmpersandAmpersandToken,
+ BarBarToken,
+ QuestionToken,
+ ColonToken,
+ AtToken,
+ QuestionQuestionToken,
+ BacktickToken,
+ HashToken,
+ EqualsToken,
+ PlusEqualsToken,
+ MinusEqualsToken,
+ AsteriskEqualsToken,
+ AsteriskAsteriskEqualsToken,
+ SlashEqualsToken,
+ PercentEqualsToken,
+ LessThanLessThanEqualsToken,
+ GreaterThanGreaterThanEqualsToken,
+ GreaterThanGreaterThanGreaterThanEqualsToken,
+ AmpersandEqualsToken,
+ BarEqualsToken,
+ BarBarEqualsToken,
+ AmpersandAmpersandEqualsToken,
+ QuestionQuestionEqualsToken,
+ CaretEqualsToken,
+ Identifier,
+ PrivateIdentifier,
+ JSDocCommentTextToken,
+ BreakKeyword,
+ CaseKeyword,
+ CatchKeyword,
+ ClassKeyword,
+ ConstKeyword,
+ ContinueKeyword,
+ DebuggerKeyword,
+ DefaultKeyword,
+ DeleteKeyword,
+ DoKeyword,
+ ElseKeyword,
+ EnumKeyword,
+ ExportKeyword,
+ ExtendsKeyword,
+ FalseKeyword,
+ FinallyKeyword,
+ ForKeyword,
+ FunctionKeyword,
+ IfKeyword,
+ ImportKeyword,
+ InKeyword,
+ InstanceOfKeyword,
+ NewKeyword,
+ NullKeyword,
+ ReturnKeyword,
+ SuperKeyword,
+ SwitchKeyword,
+ ThisKeyword,
+ ThrowKeyword,
+ TrueKeyword,
+ TryKeyword,
+ TypeOfKeyword,
+ VarKeyword,
+ VoidKeyword,
+ WhileKeyword,
+ WithKeyword,
+ ImplementsKeyword,
+ InterfaceKeyword,
+ LetKeyword,
+ PackageKeyword,
+ PrivateKeyword,
+ ProtectedKeyword,
+ PublicKeyword,
+ StaticKeyword,
+ YieldKeyword,
+ AbstractKeyword,
+ AccessorKeyword,
+ AsKeyword,
+ AssertsKeyword,
+ AssertKeyword,
+ AnyKeyword,
+ AsyncKeyword,
+ AwaitKeyword,
+ BooleanKeyword,
+ ConstructorKeyword,
+ DeclareKeyword,
+ GetKeyword,
+ ImmediateKeyword,
+ InferKeyword,
+ IntrinsicKeyword,
+ IsKeyword,
+ KeyOfKeyword,
+ ModuleKeyword,
+ NamespaceKeyword,
+ NeverKeyword,
+ OutKeyword,
+ ReadonlyKeyword,
+ RequireKeyword,
+ NumberKeyword,
+ ObjectKeyword,
+ SatisfiesKeyword,
+ SetKeyword,
+ StringKeyword,
+ SymbolKeyword,
+ TypeKeyword,
+ UndefinedKeyword,
+ UniqueKeyword,
+ UnknownKeyword,
+ UsingKeyword,
+ FromKeyword,
+ GlobalKeyword,
+ BigIntKeyword,
+ OverrideKeyword,
+ OfKeyword,
+ QualifiedName,
+ ComputedPropertyName,
+ TypeParameter,
+ Parameter,
+ Decorator,
+ PropertySignature,
+ PropertyDeclaration,
+ MethodSignature,
+ MethodDeclaration,
+ ClassStaticBlockDeclaration,
+ Constructor,
+ GetAccessor,
+ SetAccessor,
+ CallSignature,
+ ConstructSignature,
+ IndexSignature,
+ TypePredicate,
+ TypeReference,
+ FunctionType,
+ ConstructorType,
+ TypeQuery,
+ TypeLiteral,
+ ArrayType,
+ TupleType,
+ OptionalType,
+ RestType,
+ UnionType,
+ IntersectionType,
+ ConditionalType,
+ InferType,
+ ParenthesizedType,
+ ThisType,
+ TypeOperator,
+ IndexedAccessType,
+ MappedType,
+ LiteralType,
+ NamedTupleMember,
+ TemplateLiteralType,
+ TemplateLiteralTypeSpan,
+ ImportType,
+ ObjectBindingPattern,
+ ArrayBindingPattern,
+ BindingElement,
+ ArrayLiteralExpression,
+ ObjectLiteralExpression,
+ PropertyAccessExpression,
+ ElementAccessExpression,
+ CallExpression,
+ NewExpression,
+ TaggedTemplateExpression,
+ TypeAssertionExpression,
+ ParenthesizedExpression,
+ FunctionExpression,
+ ArrowFunction,
+ DeleteExpression,
+ TypeOfExpression,
+ VoidExpression,
+ AwaitExpression,
+ PrefixUnaryExpression,
+ PostfixUnaryExpression,
+ BinaryExpression,
+ ConditionalExpression,
+ TemplateExpression,
+ YieldExpression,
+ SpreadElement,
+ ClassExpression,
+ OmittedExpression,
+ ExpressionWithTypeArguments,
+ AsExpression,
+ NonNullExpression,
+ MetaProperty,
+ SyntheticExpression,
+ SatisfiesExpression,
+ TemplateSpan,
+ SemicolonClassElement,
+ Block,
+ EmptyStatement,
+ VariableStatement,
+ ExpressionStatement,
+ IfStatement,
+ DoStatement,
+ WhileStatement,
+ ForStatement,
+ ForInStatement,
+ ForOfStatement,
+ ContinueStatement,
+ BreakStatement,
+ ReturnStatement,
+ WithStatement,
+ SwitchStatement,
+ LabeledStatement,
+ ThrowStatement,
+ TryStatement,
+ DebuggerStatement,
+ VariableDeclaration,
+ VariableDeclarationList,
+ FunctionDeclaration,
+ ClassDeclaration,
+ InterfaceDeclaration,
+ TypeAliasDeclaration,
+ EnumDeclaration,
+ ModuleDeclaration,
+ ModuleBlock,
+ CaseBlock,
+ NamespaceExportDeclaration,
+ ImportEqualsDeclaration,
+ ImportDeclaration,
+ ImportClause,
+ NamespaceImport,
+ NamedImports,
+ ImportSpecifier,
+ ExportAssignment,
+ ExportDeclaration,
+ NamedExports,
+ NamespaceExport,
+ ExportSpecifier,
+ MissingDeclaration,
+ ExternalModuleReference,
+ JsxElement,
+ JsxSelfClosingElement,
+ JsxOpeningElement,
+ JsxClosingElement,
+ JsxFragment,
+ JsxOpeningFragment,
+ JsxClosingFragment,
+ JsxAttribute,
+ JsxAttributes,
+ JsxSpreadAttribute,
+ JsxExpression,
+ JsxNamespacedName,
+ CaseClause,
+ DefaultClause,
+ HeritageClause,
+ CatchClause,
+ ImportAttributes,
+ ImportAttribute,
+ PropertyAssignment,
+ ShorthandPropertyAssignment,
+ SpreadAssignment,
+ EnumMember,
+ SourceFile,
+ Bundle,
+ JSDocTypeExpression,
+ JSDocNameReference,
+ JSDocMemberName,
+ JSDocAllType,
+ JSDocNullableType,
+ JSDocNonNullableType,
+ JSDocOptionalType,
+ JSDocVariadicType,
+ JSDoc,
+ JSDocText,
+ JSDocTypeLiteral,
+ JSDocSignature,
+ JSDocLink,
+ JSDocLinkCode,
+ JSDocLinkPlain,
+ JSDocTag,
+ JSDocAugmentsTag,
+ JSDocImplementsTag,
+ JSDocDeprecatedTag,
+ JSDocPublicTag,
+ JSDocPrivateTag,
+ JSDocProtectedTag,
+ JSDocReadonlyTag,
+ JSDocOverrideTag,
+ JSDocCallbackTag,
+ JSDocOverloadTag,
+ JSDocParameterTag,
+ JSDocReturnTag,
+ JSDocThisTag,
+ JSDocTypeTag,
+ JSDocTemplateTag,
+ JSDocTypedefTag,
+ JSDocSeeTag,
+ JSDocPropertyTag,
+ JSDocSatisfiesTag,
+ JSDocImportTag,
+ SyntaxList,
+ NotEmittedStatement,
+ PartiallyEmittedExpression,
+ CommaListExpression,
+ SyntheticReferenceExpression,
+ Count,
+}
diff --git a/_packages/ast/src/syntaxKind.ts b/_packages/ast/src/syntaxKind.ts
new file mode 100644
index 0000000000..4d86197027
--- /dev/null
+++ b/_packages/ast/src/syntaxKind.ts
@@ -0,0 +1,355 @@
+export var SyntaxKind: any;
+(function (SyntaxKind) {
+ SyntaxKind[SyntaxKind["Unknown"] = 0] = "Unknown";
+ SyntaxKind[SyntaxKind["EndOfFile"] = 1] = "EndOfFile";
+ SyntaxKind[SyntaxKind["SingleLineCommentTrivia"] = 2] = "SingleLineCommentTrivia";
+ SyntaxKind[SyntaxKind["MultiLineCommentTrivia"] = 3] = "MultiLineCommentTrivia";
+ SyntaxKind[SyntaxKind["NewLineTrivia"] = 4] = "NewLineTrivia";
+ SyntaxKind[SyntaxKind["WhitespaceTrivia"] = 5] = "WhitespaceTrivia";
+ SyntaxKind[SyntaxKind["ConflictMarkerTrivia"] = 6] = "ConflictMarkerTrivia";
+ SyntaxKind[SyntaxKind["NonTextFileMarkerTrivia"] = 7] = "NonTextFileMarkerTrivia";
+ SyntaxKind[SyntaxKind["NumericLiteral"] = 8] = "NumericLiteral";
+ SyntaxKind[SyntaxKind["BigIntLiteral"] = 9] = "BigIntLiteral";
+ SyntaxKind[SyntaxKind["StringLiteral"] = 10] = "StringLiteral";
+ SyntaxKind[SyntaxKind["JsxText"] = 11] = "JsxText";
+ SyntaxKind[SyntaxKind["JsxTextAllWhiteSpaces"] = 12] = "JsxTextAllWhiteSpaces";
+ SyntaxKind[SyntaxKind["RegularExpressionLiteral"] = 13] = "RegularExpressionLiteral";
+ SyntaxKind[SyntaxKind["NoSubstitutionTemplateLiteral"] = 14] = "NoSubstitutionTemplateLiteral";
+ SyntaxKind[SyntaxKind["TemplateHead"] = 15] = "TemplateHead";
+ SyntaxKind[SyntaxKind["TemplateMiddle"] = 16] = "TemplateMiddle";
+ SyntaxKind[SyntaxKind["TemplateTail"] = 17] = "TemplateTail";
+ SyntaxKind[SyntaxKind["OpenBraceToken"] = 18] = "OpenBraceToken";
+ SyntaxKind[SyntaxKind["CloseBraceToken"] = 19] = "CloseBraceToken";
+ SyntaxKind[SyntaxKind["OpenParenToken"] = 20] = "OpenParenToken";
+ SyntaxKind[SyntaxKind["CloseParenToken"] = 21] = "CloseParenToken";
+ SyntaxKind[SyntaxKind["OpenBracketToken"] = 22] = "OpenBracketToken";
+ SyntaxKind[SyntaxKind["CloseBracketToken"] = 23] = "CloseBracketToken";
+ SyntaxKind[SyntaxKind["DotToken"] = 24] = "DotToken";
+ SyntaxKind[SyntaxKind["DotDotDotToken"] = 25] = "DotDotDotToken";
+ SyntaxKind[SyntaxKind["SemicolonToken"] = 26] = "SemicolonToken";
+ SyntaxKind[SyntaxKind["CommaToken"] = 27] = "CommaToken";
+ SyntaxKind[SyntaxKind["QuestionDotToken"] = 28] = "QuestionDotToken";
+ SyntaxKind[SyntaxKind["LessThanToken"] = 29] = "LessThanToken";
+ SyntaxKind[SyntaxKind["LessThanSlashToken"] = 30] = "LessThanSlashToken";
+ SyntaxKind[SyntaxKind["GreaterThanToken"] = 31] = "GreaterThanToken";
+ SyntaxKind[SyntaxKind["LessThanEqualsToken"] = 32] = "LessThanEqualsToken";
+ SyntaxKind[SyntaxKind["GreaterThanEqualsToken"] = 33] = "GreaterThanEqualsToken";
+ SyntaxKind[SyntaxKind["EqualsEqualsToken"] = 34] = "EqualsEqualsToken";
+ SyntaxKind[SyntaxKind["ExclamationEqualsToken"] = 35] = "ExclamationEqualsToken";
+ SyntaxKind[SyntaxKind["EqualsEqualsEqualsToken"] = 36] = "EqualsEqualsEqualsToken";
+ SyntaxKind[SyntaxKind["ExclamationEqualsEqualsToken"] = 37] = "ExclamationEqualsEqualsToken";
+ SyntaxKind[SyntaxKind["EqualsGreaterThanToken"] = 38] = "EqualsGreaterThanToken";
+ SyntaxKind[SyntaxKind["PlusToken"] = 39] = "PlusToken";
+ SyntaxKind[SyntaxKind["MinusToken"] = 40] = "MinusToken";
+ SyntaxKind[SyntaxKind["AsteriskToken"] = 41] = "AsteriskToken";
+ SyntaxKind[SyntaxKind["AsteriskAsteriskToken"] = 42] = "AsteriskAsteriskToken";
+ SyntaxKind[SyntaxKind["SlashToken"] = 43] = "SlashToken";
+ SyntaxKind[SyntaxKind["PercentToken"] = 44] = "PercentToken";
+ SyntaxKind[SyntaxKind["PlusPlusToken"] = 45] = "PlusPlusToken";
+ SyntaxKind[SyntaxKind["MinusMinusToken"] = 46] = "MinusMinusToken";
+ SyntaxKind[SyntaxKind["LessThanLessThanToken"] = 47] = "LessThanLessThanToken";
+ SyntaxKind[SyntaxKind["GreaterThanGreaterThanToken"] = 48] = "GreaterThanGreaterThanToken";
+ SyntaxKind[SyntaxKind["GreaterThanGreaterThanGreaterThanToken"] = 49] = "GreaterThanGreaterThanGreaterThanToken";
+ SyntaxKind[SyntaxKind["AmpersandToken"] = 50] = "AmpersandToken";
+ SyntaxKind[SyntaxKind["BarToken"] = 51] = "BarToken";
+ SyntaxKind[SyntaxKind["CaretToken"] = 52] = "CaretToken";
+ SyntaxKind[SyntaxKind["ExclamationToken"] = 53] = "ExclamationToken";
+ SyntaxKind[SyntaxKind["TildeToken"] = 54] = "TildeToken";
+ SyntaxKind[SyntaxKind["AmpersandAmpersandToken"] = 55] = "AmpersandAmpersandToken";
+ SyntaxKind[SyntaxKind["BarBarToken"] = 56] = "BarBarToken";
+ SyntaxKind[SyntaxKind["QuestionToken"] = 57] = "QuestionToken";
+ SyntaxKind[SyntaxKind["ColonToken"] = 58] = "ColonToken";
+ SyntaxKind[SyntaxKind["AtToken"] = 59] = "AtToken";
+ SyntaxKind[SyntaxKind["QuestionQuestionToken"] = 60] = "QuestionQuestionToken";
+ SyntaxKind[SyntaxKind["BacktickToken"] = 61] = "BacktickToken";
+ SyntaxKind[SyntaxKind["HashToken"] = 62] = "HashToken";
+ SyntaxKind[SyntaxKind["EqualsToken"] = 63] = "EqualsToken";
+ SyntaxKind[SyntaxKind["PlusEqualsToken"] = 64] = "PlusEqualsToken";
+ SyntaxKind[SyntaxKind["MinusEqualsToken"] = 65] = "MinusEqualsToken";
+ SyntaxKind[SyntaxKind["AsteriskEqualsToken"] = 66] = "AsteriskEqualsToken";
+ SyntaxKind[SyntaxKind["AsteriskAsteriskEqualsToken"] = 67] = "AsteriskAsteriskEqualsToken";
+ SyntaxKind[SyntaxKind["SlashEqualsToken"] = 68] = "SlashEqualsToken";
+ SyntaxKind[SyntaxKind["PercentEqualsToken"] = 69] = "PercentEqualsToken";
+ SyntaxKind[SyntaxKind["LessThanLessThanEqualsToken"] = 70] = "LessThanLessThanEqualsToken";
+ SyntaxKind[SyntaxKind["GreaterThanGreaterThanEqualsToken"] = 71] = "GreaterThanGreaterThanEqualsToken";
+ SyntaxKind[
+ SyntaxKind["GreaterThanGreaterThanGreaterThanEqualsToken"] = 72
+ ] = "GreaterThanGreaterThanGreaterThanEqualsToken";
+ SyntaxKind[SyntaxKind["AmpersandEqualsToken"] = 73] = "AmpersandEqualsToken";
+ SyntaxKind[SyntaxKind["BarEqualsToken"] = 74] = "BarEqualsToken";
+ SyntaxKind[SyntaxKind["BarBarEqualsToken"] = 75] = "BarBarEqualsToken";
+ SyntaxKind[SyntaxKind["AmpersandAmpersandEqualsToken"] = 76] = "AmpersandAmpersandEqualsToken";
+ SyntaxKind[SyntaxKind["QuestionQuestionEqualsToken"] = 77] = "QuestionQuestionEqualsToken";
+ SyntaxKind[SyntaxKind["CaretEqualsToken"] = 78] = "CaretEqualsToken";
+ SyntaxKind[SyntaxKind["Identifier"] = 79] = "Identifier";
+ SyntaxKind[SyntaxKind["PrivateIdentifier"] = 80] = "PrivateIdentifier";
+ SyntaxKind[SyntaxKind["JSDocCommentTextToken"] = 81] = "JSDocCommentTextToken";
+ SyntaxKind[SyntaxKind["BreakKeyword"] = 82] = "BreakKeyword";
+ SyntaxKind[SyntaxKind["CaseKeyword"] = 83] = "CaseKeyword";
+ SyntaxKind[SyntaxKind["CatchKeyword"] = 84] = "CatchKeyword";
+ SyntaxKind[SyntaxKind["ClassKeyword"] = 85] = "ClassKeyword";
+ SyntaxKind[SyntaxKind["ConstKeyword"] = 86] = "ConstKeyword";
+ SyntaxKind[SyntaxKind["ContinueKeyword"] = 87] = "ContinueKeyword";
+ SyntaxKind[SyntaxKind["DebuggerKeyword"] = 88] = "DebuggerKeyword";
+ SyntaxKind[SyntaxKind["DefaultKeyword"] = 89] = "DefaultKeyword";
+ SyntaxKind[SyntaxKind["DeleteKeyword"] = 90] = "DeleteKeyword";
+ SyntaxKind[SyntaxKind["DoKeyword"] = 91] = "DoKeyword";
+ SyntaxKind[SyntaxKind["ElseKeyword"] = 92] = "ElseKeyword";
+ SyntaxKind[SyntaxKind["EnumKeyword"] = 93] = "EnumKeyword";
+ SyntaxKind[SyntaxKind["ExportKeyword"] = 94] = "ExportKeyword";
+ SyntaxKind[SyntaxKind["ExtendsKeyword"] = 95] = "ExtendsKeyword";
+ SyntaxKind[SyntaxKind["FalseKeyword"] = 96] = "FalseKeyword";
+ SyntaxKind[SyntaxKind["FinallyKeyword"] = 97] = "FinallyKeyword";
+ SyntaxKind[SyntaxKind["ForKeyword"] = 98] = "ForKeyword";
+ SyntaxKind[SyntaxKind["FunctionKeyword"] = 99] = "FunctionKeyword";
+ SyntaxKind[SyntaxKind["IfKeyword"] = 100] = "IfKeyword";
+ SyntaxKind[SyntaxKind["ImportKeyword"] = 101] = "ImportKeyword";
+ SyntaxKind[SyntaxKind["InKeyword"] = 102] = "InKeyword";
+ SyntaxKind[SyntaxKind["InstanceOfKeyword"] = 103] = "InstanceOfKeyword";
+ SyntaxKind[SyntaxKind["NewKeyword"] = 104] = "NewKeyword";
+ SyntaxKind[SyntaxKind["NullKeyword"] = 105] = "NullKeyword";
+ SyntaxKind[SyntaxKind["ReturnKeyword"] = 106] = "ReturnKeyword";
+ SyntaxKind[SyntaxKind["SuperKeyword"] = 107] = "SuperKeyword";
+ SyntaxKind[SyntaxKind["SwitchKeyword"] = 108] = "SwitchKeyword";
+ SyntaxKind[SyntaxKind["ThisKeyword"] = 109] = "ThisKeyword";
+ SyntaxKind[SyntaxKind["ThrowKeyword"] = 110] = "ThrowKeyword";
+ SyntaxKind[SyntaxKind["TrueKeyword"] = 111] = "TrueKeyword";
+ SyntaxKind[SyntaxKind["TryKeyword"] = 112] = "TryKeyword";
+ SyntaxKind[SyntaxKind["TypeOfKeyword"] = 113] = "TypeOfKeyword";
+ SyntaxKind[SyntaxKind["VarKeyword"] = 114] = "VarKeyword";
+ SyntaxKind[SyntaxKind["VoidKeyword"] = 115] = "VoidKeyword";
+ SyntaxKind[SyntaxKind["WhileKeyword"] = 116] = "WhileKeyword";
+ SyntaxKind[SyntaxKind["WithKeyword"] = 117] = "WithKeyword";
+ SyntaxKind[SyntaxKind["ImplementsKeyword"] = 118] = "ImplementsKeyword";
+ SyntaxKind[SyntaxKind["InterfaceKeyword"] = 119] = "InterfaceKeyword";
+ SyntaxKind[SyntaxKind["LetKeyword"] = 120] = "LetKeyword";
+ SyntaxKind[SyntaxKind["PackageKeyword"] = 121] = "PackageKeyword";
+ SyntaxKind[SyntaxKind["PrivateKeyword"] = 122] = "PrivateKeyword";
+ SyntaxKind[SyntaxKind["ProtectedKeyword"] = 123] = "ProtectedKeyword";
+ SyntaxKind[SyntaxKind["PublicKeyword"] = 124] = "PublicKeyword";
+ SyntaxKind[SyntaxKind["StaticKeyword"] = 125] = "StaticKeyword";
+ SyntaxKind[SyntaxKind["YieldKeyword"] = 126] = "YieldKeyword";
+ SyntaxKind[SyntaxKind["AbstractKeyword"] = 127] = "AbstractKeyword";
+ SyntaxKind[SyntaxKind["AccessorKeyword"] = 128] = "AccessorKeyword";
+ SyntaxKind[SyntaxKind["AsKeyword"] = 129] = "AsKeyword";
+ SyntaxKind[SyntaxKind["AssertsKeyword"] = 130] = "AssertsKeyword";
+ SyntaxKind[SyntaxKind["AssertKeyword"] = 131] = "AssertKeyword";
+ SyntaxKind[SyntaxKind["AnyKeyword"] = 132] = "AnyKeyword";
+ SyntaxKind[SyntaxKind["AsyncKeyword"] = 133] = "AsyncKeyword";
+ SyntaxKind[SyntaxKind["AwaitKeyword"] = 134] = "AwaitKeyword";
+ SyntaxKind[SyntaxKind["BooleanKeyword"] = 135] = "BooleanKeyword";
+ SyntaxKind[SyntaxKind["ConstructorKeyword"] = 136] = "ConstructorKeyword";
+ SyntaxKind[SyntaxKind["DeclareKeyword"] = 137] = "DeclareKeyword";
+ SyntaxKind[SyntaxKind["GetKeyword"] = 138] = "GetKeyword";
+ SyntaxKind[SyntaxKind["ImmediateKeyword"] = 139] = "ImmediateKeyword";
+ SyntaxKind[SyntaxKind["InferKeyword"] = 140] = "InferKeyword";
+ SyntaxKind[SyntaxKind["IntrinsicKeyword"] = 141] = "IntrinsicKeyword";
+ SyntaxKind[SyntaxKind["IsKeyword"] = 142] = "IsKeyword";
+ SyntaxKind[SyntaxKind["KeyOfKeyword"] = 143] = "KeyOfKeyword";
+ SyntaxKind[SyntaxKind["ModuleKeyword"] = 144] = "ModuleKeyword";
+ SyntaxKind[SyntaxKind["NamespaceKeyword"] = 145] = "NamespaceKeyword";
+ SyntaxKind[SyntaxKind["NeverKeyword"] = 146] = "NeverKeyword";
+ SyntaxKind[SyntaxKind["OutKeyword"] = 147] = "OutKeyword";
+ SyntaxKind[SyntaxKind["ReadonlyKeyword"] = 148] = "ReadonlyKeyword";
+ SyntaxKind[SyntaxKind["RequireKeyword"] = 149] = "RequireKeyword";
+ SyntaxKind[SyntaxKind["NumberKeyword"] = 150] = "NumberKeyword";
+ SyntaxKind[SyntaxKind["ObjectKeyword"] = 151] = "ObjectKeyword";
+ SyntaxKind[SyntaxKind["SatisfiesKeyword"] = 152] = "SatisfiesKeyword";
+ SyntaxKind[SyntaxKind["SetKeyword"] = 153] = "SetKeyword";
+ SyntaxKind[SyntaxKind["StringKeyword"] = 154] = "StringKeyword";
+ SyntaxKind[SyntaxKind["SymbolKeyword"] = 155] = "SymbolKeyword";
+ SyntaxKind[SyntaxKind["TypeKeyword"] = 156] = "TypeKeyword";
+ SyntaxKind[SyntaxKind["UndefinedKeyword"] = 157] = "UndefinedKeyword";
+ SyntaxKind[SyntaxKind["UniqueKeyword"] = 158] = "UniqueKeyword";
+ SyntaxKind[SyntaxKind["UnknownKeyword"] = 159] = "UnknownKeyword";
+ SyntaxKind[SyntaxKind["UsingKeyword"] = 160] = "UsingKeyword";
+ SyntaxKind[SyntaxKind["FromKeyword"] = 161] = "FromKeyword";
+ SyntaxKind[SyntaxKind["GlobalKeyword"] = 162] = "GlobalKeyword";
+ SyntaxKind[SyntaxKind["BigIntKeyword"] = 163] = "BigIntKeyword";
+ SyntaxKind[SyntaxKind["OverrideKeyword"] = 164] = "OverrideKeyword";
+ SyntaxKind[SyntaxKind["OfKeyword"] = 165] = "OfKeyword";
+ SyntaxKind[SyntaxKind["QualifiedName"] = 166] = "QualifiedName";
+ SyntaxKind[SyntaxKind["ComputedPropertyName"] = 167] = "ComputedPropertyName";
+ SyntaxKind[SyntaxKind["TypeParameter"] = 168] = "TypeParameter";
+ SyntaxKind[SyntaxKind["Parameter"] = 169] = "Parameter";
+ SyntaxKind[SyntaxKind["Decorator"] = 170] = "Decorator";
+ SyntaxKind[SyntaxKind["PropertySignature"] = 171] = "PropertySignature";
+ SyntaxKind[SyntaxKind["PropertyDeclaration"] = 172] = "PropertyDeclaration";
+ SyntaxKind[SyntaxKind["MethodSignature"] = 173] = "MethodSignature";
+ SyntaxKind[SyntaxKind["MethodDeclaration"] = 174] = "MethodDeclaration";
+ SyntaxKind[SyntaxKind["ClassStaticBlockDeclaration"] = 175] = "ClassStaticBlockDeclaration";
+ SyntaxKind[SyntaxKind["Constructor"] = 176] = "Constructor";
+ SyntaxKind[SyntaxKind["GetAccessor"] = 177] = "GetAccessor";
+ SyntaxKind[SyntaxKind["SetAccessor"] = 178] = "SetAccessor";
+ SyntaxKind[SyntaxKind["CallSignature"] = 179] = "CallSignature";
+ SyntaxKind[SyntaxKind["ConstructSignature"] = 180] = "ConstructSignature";
+ SyntaxKind[SyntaxKind["IndexSignature"] = 181] = "IndexSignature";
+ SyntaxKind[SyntaxKind["TypePredicate"] = 182] = "TypePredicate";
+ SyntaxKind[SyntaxKind["TypeReference"] = 183] = "TypeReference";
+ SyntaxKind[SyntaxKind["FunctionType"] = 184] = "FunctionType";
+ SyntaxKind[SyntaxKind["ConstructorType"] = 185] = "ConstructorType";
+ SyntaxKind[SyntaxKind["TypeQuery"] = 186] = "TypeQuery";
+ SyntaxKind[SyntaxKind["TypeLiteral"] = 187] = "TypeLiteral";
+ SyntaxKind[SyntaxKind["ArrayType"] = 188] = "ArrayType";
+ SyntaxKind[SyntaxKind["TupleType"] = 189] = "TupleType";
+ SyntaxKind[SyntaxKind["OptionalType"] = 190] = "OptionalType";
+ SyntaxKind[SyntaxKind["RestType"] = 191] = "RestType";
+ SyntaxKind[SyntaxKind["UnionType"] = 192] = "UnionType";
+ SyntaxKind[SyntaxKind["IntersectionType"] = 193] = "IntersectionType";
+ SyntaxKind[SyntaxKind["ConditionalType"] = 194] = "ConditionalType";
+ SyntaxKind[SyntaxKind["InferType"] = 195] = "InferType";
+ SyntaxKind[SyntaxKind["ParenthesizedType"] = 196] = "ParenthesizedType";
+ SyntaxKind[SyntaxKind["ThisType"] = 197] = "ThisType";
+ SyntaxKind[SyntaxKind["TypeOperator"] = 198] = "TypeOperator";
+ SyntaxKind[SyntaxKind["IndexedAccessType"] = 199] = "IndexedAccessType";
+ SyntaxKind[SyntaxKind["MappedType"] = 200] = "MappedType";
+ SyntaxKind[SyntaxKind["LiteralType"] = 201] = "LiteralType";
+ SyntaxKind[SyntaxKind["NamedTupleMember"] = 202] = "NamedTupleMember";
+ SyntaxKind[SyntaxKind["TemplateLiteralType"] = 203] = "TemplateLiteralType";
+ SyntaxKind[SyntaxKind["TemplateLiteralTypeSpan"] = 204] = "TemplateLiteralTypeSpan";
+ SyntaxKind[SyntaxKind["ImportType"] = 205] = "ImportType";
+ SyntaxKind[SyntaxKind["ObjectBindingPattern"] = 206] = "ObjectBindingPattern";
+ SyntaxKind[SyntaxKind["ArrayBindingPattern"] = 207] = "ArrayBindingPattern";
+ SyntaxKind[SyntaxKind["BindingElement"] = 208] = "BindingElement";
+ SyntaxKind[SyntaxKind["ArrayLiteralExpression"] = 209] = "ArrayLiteralExpression";
+ SyntaxKind[SyntaxKind["ObjectLiteralExpression"] = 210] = "ObjectLiteralExpression";
+ SyntaxKind[SyntaxKind["PropertyAccessExpression"] = 211] = "PropertyAccessExpression";
+ SyntaxKind[SyntaxKind["ElementAccessExpression"] = 212] = "ElementAccessExpression";
+ SyntaxKind[SyntaxKind["CallExpression"] = 213] = "CallExpression";
+ SyntaxKind[SyntaxKind["NewExpression"] = 214] = "NewExpression";
+ SyntaxKind[SyntaxKind["TaggedTemplateExpression"] = 215] = "TaggedTemplateExpression";
+ SyntaxKind[SyntaxKind["TypeAssertionExpression"] = 216] = "TypeAssertionExpression";
+ SyntaxKind[SyntaxKind["ParenthesizedExpression"] = 217] = "ParenthesizedExpression";
+ SyntaxKind[SyntaxKind["FunctionExpression"] = 218] = "FunctionExpression";
+ SyntaxKind[SyntaxKind["ArrowFunction"] = 219] = "ArrowFunction";
+ SyntaxKind[SyntaxKind["DeleteExpression"] = 220] = "DeleteExpression";
+ SyntaxKind[SyntaxKind["TypeOfExpression"] = 221] = "TypeOfExpression";
+ SyntaxKind[SyntaxKind["VoidExpression"] = 222] = "VoidExpression";
+ SyntaxKind[SyntaxKind["AwaitExpression"] = 223] = "AwaitExpression";
+ SyntaxKind[SyntaxKind["PrefixUnaryExpression"] = 224] = "PrefixUnaryExpression";
+ SyntaxKind[SyntaxKind["PostfixUnaryExpression"] = 225] = "PostfixUnaryExpression";
+ SyntaxKind[SyntaxKind["BinaryExpression"] = 226] = "BinaryExpression";
+ SyntaxKind[SyntaxKind["ConditionalExpression"] = 227] = "ConditionalExpression";
+ SyntaxKind[SyntaxKind["TemplateExpression"] = 228] = "TemplateExpression";
+ SyntaxKind[SyntaxKind["YieldExpression"] = 229] = "YieldExpression";
+ SyntaxKind[SyntaxKind["SpreadElement"] = 230] = "SpreadElement";
+ SyntaxKind[SyntaxKind["ClassExpression"] = 231] = "ClassExpression";
+ SyntaxKind[SyntaxKind["OmittedExpression"] = 232] = "OmittedExpression";
+ SyntaxKind[SyntaxKind["ExpressionWithTypeArguments"] = 233] = "ExpressionWithTypeArguments";
+ SyntaxKind[SyntaxKind["AsExpression"] = 234] = "AsExpression";
+ SyntaxKind[SyntaxKind["NonNullExpression"] = 235] = "NonNullExpression";
+ SyntaxKind[SyntaxKind["MetaProperty"] = 236] = "MetaProperty";
+ SyntaxKind[SyntaxKind["SyntheticExpression"] = 237] = "SyntheticExpression";
+ SyntaxKind[SyntaxKind["SatisfiesExpression"] = 238] = "SatisfiesExpression";
+ SyntaxKind[SyntaxKind["TemplateSpan"] = 239] = "TemplateSpan";
+ SyntaxKind[SyntaxKind["SemicolonClassElement"] = 240] = "SemicolonClassElement";
+ SyntaxKind[SyntaxKind["Block"] = 241] = "Block";
+ SyntaxKind[SyntaxKind["EmptyStatement"] = 242] = "EmptyStatement";
+ SyntaxKind[SyntaxKind["VariableStatement"] = 243] = "VariableStatement";
+ SyntaxKind[SyntaxKind["ExpressionStatement"] = 244] = "ExpressionStatement";
+ SyntaxKind[SyntaxKind["IfStatement"] = 245] = "IfStatement";
+ SyntaxKind[SyntaxKind["DoStatement"] = 246] = "DoStatement";
+ SyntaxKind[SyntaxKind["WhileStatement"] = 247] = "WhileStatement";
+ SyntaxKind[SyntaxKind["ForStatement"] = 248] = "ForStatement";
+ SyntaxKind[SyntaxKind["ForInStatement"] = 249] = "ForInStatement";
+ SyntaxKind[SyntaxKind["ForOfStatement"] = 250] = "ForOfStatement";
+ SyntaxKind[SyntaxKind["ContinueStatement"] = 251] = "ContinueStatement";
+ SyntaxKind[SyntaxKind["BreakStatement"] = 252] = "BreakStatement";
+ SyntaxKind[SyntaxKind["ReturnStatement"] = 253] = "ReturnStatement";
+ SyntaxKind[SyntaxKind["WithStatement"] = 254] = "WithStatement";
+ SyntaxKind[SyntaxKind["SwitchStatement"] = 255] = "SwitchStatement";
+ SyntaxKind[SyntaxKind["LabeledStatement"] = 256] = "LabeledStatement";
+ SyntaxKind[SyntaxKind["ThrowStatement"] = 257] = "ThrowStatement";
+ SyntaxKind[SyntaxKind["TryStatement"] = 258] = "TryStatement";
+ SyntaxKind[SyntaxKind["DebuggerStatement"] = 259] = "DebuggerStatement";
+ SyntaxKind[SyntaxKind["VariableDeclaration"] = 260] = "VariableDeclaration";
+ SyntaxKind[SyntaxKind["VariableDeclarationList"] = 261] = "VariableDeclarationList";
+ SyntaxKind[SyntaxKind["FunctionDeclaration"] = 262] = "FunctionDeclaration";
+ SyntaxKind[SyntaxKind["ClassDeclaration"] = 263] = "ClassDeclaration";
+ SyntaxKind[SyntaxKind["InterfaceDeclaration"] = 264] = "InterfaceDeclaration";
+ SyntaxKind[SyntaxKind["TypeAliasDeclaration"] = 265] = "TypeAliasDeclaration";
+ SyntaxKind[SyntaxKind["EnumDeclaration"] = 266] = "EnumDeclaration";
+ SyntaxKind[SyntaxKind["ModuleDeclaration"] = 267] = "ModuleDeclaration";
+ SyntaxKind[SyntaxKind["ModuleBlock"] = 268] = "ModuleBlock";
+ SyntaxKind[SyntaxKind["CaseBlock"] = 269] = "CaseBlock";
+ SyntaxKind[SyntaxKind["NamespaceExportDeclaration"] = 270] = "NamespaceExportDeclaration";
+ SyntaxKind[SyntaxKind["ImportEqualsDeclaration"] = 271] = "ImportEqualsDeclaration";
+ SyntaxKind[SyntaxKind["ImportDeclaration"] = 272] = "ImportDeclaration";
+ SyntaxKind[SyntaxKind["ImportClause"] = 273] = "ImportClause";
+ SyntaxKind[SyntaxKind["NamespaceImport"] = 274] = "NamespaceImport";
+ SyntaxKind[SyntaxKind["NamedImports"] = 275] = "NamedImports";
+ SyntaxKind[SyntaxKind["ImportSpecifier"] = 276] = "ImportSpecifier";
+ SyntaxKind[SyntaxKind["ExportAssignment"] = 277] = "ExportAssignment";
+ SyntaxKind[SyntaxKind["ExportDeclaration"] = 278] = "ExportDeclaration";
+ SyntaxKind[SyntaxKind["NamedExports"] = 279] = "NamedExports";
+ SyntaxKind[SyntaxKind["NamespaceExport"] = 280] = "NamespaceExport";
+ SyntaxKind[SyntaxKind["ExportSpecifier"] = 281] = "ExportSpecifier";
+ SyntaxKind[SyntaxKind["MissingDeclaration"] = 282] = "MissingDeclaration";
+ SyntaxKind[SyntaxKind["ExternalModuleReference"] = 283] = "ExternalModuleReference";
+ SyntaxKind[SyntaxKind["JsxElement"] = 284] = "JsxElement";
+ SyntaxKind[SyntaxKind["JsxSelfClosingElement"] = 285] = "JsxSelfClosingElement";
+ SyntaxKind[SyntaxKind["JsxOpeningElement"] = 286] = "JsxOpeningElement";
+ SyntaxKind[SyntaxKind["JsxClosingElement"] = 287] = "JsxClosingElement";
+ SyntaxKind[SyntaxKind["JsxFragment"] = 288] = "JsxFragment";
+ SyntaxKind[SyntaxKind["JsxOpeningFragment"] = 289] = "JsxOpeningFragment";
+ SyntaxKind[SyntaxKind["JsxClosingFragment"] = 290] = "JsxClosingFragment";
+ SyntaxKind[SyntaxKind["JsxAttribute"] = 291] = "JsxAttribute";
+ SyntaxKind[SyntaxKind["JsxAttributes"] = 292] = "JsxAttributes";
+ SyntaxKind[SyntaxKind["JsxSpreadAttribute"] = 293] = "JsxSpreadAttribute";
+ SyntaxKind[SyntaxKind["JsxExpression"] = 294] = "JsxExpression";
+ SyntaxKind[SyntaxKind["JsxNamespacedName"] = 295] = "JsxNamespacedName";
+ SyntaxKind[SyntaxKind["CaseClause"] = 296] = "CaseClause";
+ SyntaxKind[SyntaxKind["DefaultClause"] = 297] = "DefaultClause";
+ SyntaxKind[SyntaxKind["HeritageClause"] = 298] = "HeritageClause";
+ SyntaxKind[SyntaxKind["CatchClause"] = 299] = "CatchClause";
+ SyntaxKind[SyntaxKind["ImportAttributes"] = 300] = "ImportAttributes";
+ SyntaxKind[SyntaxKind["ImportAttribute"] = 301] = "ImportAttribute";
+ SyntaxKind[SyntaxKind["PropertyAssignment"] = 302] = "PropertyAssignment";
+ SyntaxKind[SyntaxKind["ShorthandPropertyAssignment"] = 303] = "ShorthandPropertyAssignment";
+ SyntaxKind[SyntaxKind["SpreadAssignment"] = 304] = "SpreadAssignment";
+ SyntaxKind[SyntaxKind["EnumMember"] = 305] = "EnumMember";
+ SyntaxKind[SyntaxKind["SourceFile"] = 306] = "SourceFile";
+ SyntaxKind[SyntaxKind["Bundle"] = 307] = "Bundle";
+ SyntaxKind[SyntaxKind["JSDocTypeExpression"] = 308] = "JSDocTypeExpression";
+ SyntaxKind[SyntaxKind["JSDocNameReference"] = 309] = "JSDocNameReference";
+ SyntaxKind[SyntaxKind["JSDocMemberName"] = 310] = "JSDocMemberName";
+ SyntaxKind[SyntaxKind["JSDocAllType"] = 311] = "JSDocAllType";
+ SyntaxKind[SyntaxKind["JSDocNullableType"] = 312] = "JSDocNullableType";
+ SyntaxKind[SyntaxKind["JSDocNonNullableType"] = 313] = "JSDocNonNullableType";
+ SyntaxKind[SyntaxKind["JSDocOptionalType"] = 314] = "JSDocOptionalType";
+ SyntaxKind[SyntaxKind["JSDocVariadicType"] = 315] = "JSDocVariadicType";
+ SyntaxKind[SyntaxKind["JSDoc"] = 316] = "JSDoc";
+ SyntaxKind[SyntaxKind["JSDocText"] = 317] = "JSDocText";
+ SyntaxKind[SyntaxKind["JSDocTypeLiteral"] = 318] = "JSDocTypeLiteral";
+ SyntaxKind[SyntaxKind["JSDocSignature"] = 319] = "JSDocSignature";
+ SyntaxKind[SyntaxKind["JSDocLink"] = 320] = "JSDocLink";
+ SyntaxKind[SyntaxKind["JSDocLinkCode"] = 321] = "JSDocLinkCode";
+ SyntaxKind[SyntaxKind["JSDocLinkPlain"] = 322] = "JSDocLinkPlain";
+ SyntaxKind[SyntaxKind["JSDocTag"] = 323] = "JSDocTag";
+ SyntaxKind[SyntaxKind["JSDocAugmentsTag"] = 324] = "JSDocAugmentsTag";
+ SyntaxKind[SyntaxKind["JSDocImplementsTag"] = 325] = "JSDocImplementsTag";
+ SyntaxKind[SyntaxKind["JSDocDeprecatedTag"] = 326] = "JSDocDeprecatedTag";
+ SyntaxKind[SyntaxKind["JSDocPublicTag"] = 327] = "JSDocPublicTag";
+ SyntaxKind[SyntaxKind["JSDocPrivateTag"] = 328] = "JSDocPrivateTag";
+ SyntaxKind[SyntaxKind["JSDocProtectedTag"] = 329] = "JSDocProtectedTag";
+ SyntaxKind[SyntaxKind["JSDocReadonlyTag"] = 330] = "JSDocReadonlyTag";
+ SyntaxKind[SyntaxKind["JSDocOverrideTag"] = 331] = "JSDocOverrideTag";
+ SyntaxKind[SyntaxKind["JSDocCallbackTag"] = 332] = "JSDocCallbackTag";
+ SyntaxKind[SyntaxKind["JSDocOverloadTag"] = 333] = "JSDocOverloadTag";
+ SyntaxKind[SyntaxKind["JSDocParameterTag"] = 334] = "JSDocParameterTag";
+ SyntaxKind[SyntaxKind["JSDocReturnTag"] = 335] = "JSDocReturnTag";
+ SyntaxKind[SyntaxKind["JSDocThisTag"] = 336] = "JSDocThisTag";
+ SyntaxKind[SyntaxKind["JSDocTypeTag"] = 337] = "JSDocTypeTag";
+ SyntaxKind[SyntaxKind["JSDocTemplateTag"] = 338] = "JSDocTemplateTag";
+ SyntaxKind[SyntaxKind["JSDocTypedefTag"] = 339] = "JSDocTypedefTag";
+ SyntaxKind[SyntaxKind["JSDocSeeTag"] = 340] = "JSDocSeeTag";
+ SyntaxKind[SyntaxKind["JSDocPropertyTag"] = 341] = "JSDocPropertyTag";
+ SyntaxKind[SyntaxKind["JSDocSatisfiesTag"] = 342] = "JSDocSatisfiesTag";
+ SyntaxKind[SyntaxKind["JSDocImportTag"] = 343] = "JSDocImportTag";
+ SyntaxKind[SyntaxKind["SyntaxList"] = 344] = "SyntaxList";
+ SyntaxKind[SyntaxKind["NotEmittedStatement"] = 345] = "NotEmittedStatement";
+ SyntaxKind[SyntaxKind["PartiallyEmittedExpression"] = 346] = "PartiallyEmittedExpression";
+ SyntaxKind[SyntaxKind["CommaListExpression"] = 347] = "CommaListExpression";
+ SyntaxKind[SyntaxKind["SyntheticReferenceExpression"] = 348] = "SyntheticReferenceExpression";
+ SyntaxKind[SyntaxKind["Count"] = 349] = "Count";
+})(SyntaxKind || (SyntaxKind = {}));
diff --git a/_packages/ast/src/tokenFlags.enum.ts b/_packages/ast/src/tokenFlags.enum.ts
new file mode 100644
index 0000000000..1e5160421c
--- /dev/null
+++ b/_packages/ast/src/tokenFlags.enum.ts
@@ -0,0 +1,26 @@
+// dprint-ignore
+export const enum TokenFlags {
+ None = 0,
+ PrecedingLineBreak = 1 << 0,
+ PrecedingJSDocComment = 1 << 1,
+ Unterminated = 1 << 2,
+ ExtendedUnicodeEscape = 1 << 3, // e.g. `\u{10ffff}`
+ Scientific = 1 << 4, // e.g. `10e2`
+ Octal = 1 << 5, // e.g. `0777`
+ HexSpecifier = 1 << 6, // e.g. `0x00000000`
+ BinarySpecifier = 1 << 7, // e.g. `0b0110010000000000`
+ OctalSpecifier = 1 << 8, // e.g. `0o777`
+ ContainsSeparator = 1 << 9, // e.g. `0b1100_0101`
+ UnicodeEscape = 1 << 10, // e.g. `\u00a0`
+ ContainsInvalidEscape = 1 << 11, // e.g. `\uhello`
+ HexEscape = 1 << 12, // e.g. `\xa0`
+ ContainsLeadingZero = 1 << 13, // e.g. `0888`
+ ContainsInvalidSeparator = 1 << 14, // e.g. `0_1`
+ PrecedingJSDocLeadingAsterisks = 1 << 15,
+ BinaryOrOctalSpecifier = BinarySpecifier | OctalSpecifier,
+ WithSpecifier = HexSpecifier | BinaryOrOctalSpecifier,
+ StringLiteralFlags = HexEscape | UnicodeEscape | ExtendedUnicodeEscape | ContainsInvalidEscape,
+ NumericLiteralFlags = Scientific | Octal | ContainsLeadingZero | WithSpecifier | ContainsSeparator | ContainsInvalidSeparator,
+ TemplateLiteralLikeFlags = HexEscape | UnicodeEscape | ExtendedUnicodeEscape | ContainsInvalidEscape,
+ IsInvalid = Octal | ContainsLeadingZero | ContainsInvalidSeparator | ContainsInvalidEscape,
+}
diff --git a/_packages/ast/src/tokenFlags.ts b/_packages/ast/src/tokenFlags.ts
new file mode 100644
index 0000000000..4b0a8cd272
--- /dev/null
+++ b/_packages/ast/src/tokenFlags.ts
@@ -0,0 +1,27 @@
+// dprint-ignore
+export var TokenFlags: any;
+(function (TokenFlags) {
+ TokenFlags[TokenFlags["None"] = 0] = "None";
+ TokenFlags[TokenFlags["PrecedingLineBreak"] = 1] = "PrecedingLineBreak";
+ TokenFlags[TokenFlags["PrecedingJSDocComment"] = 2] = "PrecedingJSDocComment";
+ TokenFlags[TokenFlags["Unterminated"] = 4] = "Unterminated";
+ TokenFlags[TokenFlags["ExtendedUnicodeEscape"] = 8] = "ExtendedUnicodeEscape";
+ TokenFlags[TokenFlags["Scientific"] = 16] = "Scientific";
+ TokenFlags[TokenFlags["Octal"] = 32] = "Octal";
+ TokenFlags[TokenFlags["HexSpecifier"] = 64] = "HexSpecifier";
+ TokenFlags[TokenFlags["BinarySpecifier"] = 128] = "BinarySpecifier";
+ TokenFlags[TokenFlags["OctalSpecifier"] = 256] = "OctalSpecifier";
+ TokenFlags[TokenFlags["ContainsSeparator"] = 512] = "ContainsSeparator";
+ TokenFlags[TokenFlags["UnicodeEscape"] = 1024] = "UnicodeEscape";
+ TokenFlags[TokenFlags["ContainsInvalidEscape"] = 2048] = "ContainsInvalidEscape";
+ TokenFlags[TokenFlags["HexEscape"] = 4096] = "HexEscape";
+ TokenFlags[TokenFlags["ContainsLeadingZero"] = 8192] = "ContainsLeadingZero";
+ TokenFlags[TokenFlags["ContainsInvalidSeparator"] = 16384] = "ContainsInvalidSeparator";
+ TokenFlags[TokenFlags["PrecedingJSDocLeadingAsterisks"] = 32768] = "PrecedingJSDocLeadingAsterisks";
+ TokenFlags[TokenFlags["BinaryOrOctalSpecifier"] = 384] = "BinaryOrOctalSpecifier";
+ TokenFlags[TokenFlags["WithSpecifier"] = 448] = "WithSpecifier";
+ TokenFlags[TokenFlags["StringLiteralFlags"] = 7176] = "StringLiteralFlags";
+ TokenFlags[TokenFlags["NumericLiteralFlags"] = 25584] = "NumericLiteralFlags";
+ TokenFlags[TokenFlags["TemplateLiteralLikeFlags"] = 7176] = "TemplateLiteralLikeFlags";
+ TokenFlags[TokenFlags["IsInvalid"] = 26656] = "IsInvalid";
+})(TokenFlags || (TokenFlags = {}));
diff --git a/_packages/ast/src/utils.ts b/_packages/ast/src/utils.ts
new file mode 100644
index 0000000000..0b77d02fb6
--- /dev/null
+++ b/_packages/ast/src/utils.ts
@@ -0,0 +1,9 @@
+export function tryCast(value: TIn | undefined, test: (value: TIn) => value is TOut): TOut | undefined {
+ return value !== undefined && test(value) ? value : undefined;
+}
+
+export function cast(value: TIn | undefined, test: (value: TIn) => value is TOut): TOut {
+ if (value !== undefined && test(value)) return value;
+
+ throw new Error(`Invalid cast. The supplied value ${value} did not pass the test '${test.name}'.`);
+}
diff --git a/_packages/ast/tsconfig.json b/_packages/ast/tsconfig.json
new file mode 100644
index 0000000000..5be4954833
--- /dev/null
+++ b/_packages/ast/tsconfig.json
@@ -0,0 +1,17 @@
+{
+ "compilerOptions": {
+ "module": "node16",
+ "strict": true,
+ "composite": true,
+ "forceConsistentCasingInFileNames": true,
+ "rewriteRelativeImportExtensions": true,
+ "verbatimModuleSyntax": true,
+ "isolatedDeclarations": true,
+ "sourceMap": true,
+ "declaration": true,
+ "declarationMap": true,
+ "rootDir": "src",
+ "outDir": "dist"
+ },
+ "include": ["src"]
+}
diff --git a/cmd/tsgo/api.go b/cmd/tsgo/api.go
new file mode 100644
index 0000000000..702ce143a2
--- /dev/null
+++ b/cmd/tsgo/api.go
@@ -0,0 +1,38 @@
+package main
+
+import (
+ "errors"
+ "flag"
+ "fmt"
+ "io"
+ "os"
+
+ "github.com/microsoft/typescript-go/internal/api"
+ "github.com/microsoft/typescript-go/internal/bundled"
+ "github.com/microsoft/typescript-go/internal/core"
+)
+
+func runAPI(args []string) int {
+ flag := flag.NewFlagSet("api", flag.ContinueOnError)
+ cwd := flag.String("cwd", core.Must(os.Getwd()), "current working directory")
+ if err := flag.Parse(args); err != nil {
+ return 2
+ }
+
+ defaultLibraryPath := bundled.LibPath()
+
+ s := api.NewServer(&api.ServerOptions{
+ In: os.Stdin,
+ Out: os.Stdout,
+ Err: os.Stderr,
+ Cwd: *cwd,
+ NewLine: "\n",
+ DefaultLibraryPath: defaultLibraryPath,
+ })
+
+ if err := s.Run(); err != nil && !errors.Is(err, io.EOF) {
+ fmt.Println(err)
+ return 1
+ }
+ return 0
+}
diff --git a/cmd/tsgo/main.go b/cmd/tsgo/main.go
index f40ed39bd8..ae23a493ce 100644
--- a/cmd/tsgo/main.go
+++ b/cmd/tsgo/main.go
@@ -133,6 +133,8 @@ func runMain() int {
return int(execute.CommandLine(newSystem(), nil, args[1:]))
case "lsp":
return runLSP(args[1:])
+ case "api":
+ return runAPI(args[1:])
}
}
opts := parseArgs()
diff --git a/internal/api/api.go b/internal/api/api.go
new file mode 100644
index 0000000000..6b04c741aa
--- /dev/null
+++ b/internal/api/api.go
@@ -0,0 +1,375 @@
+package api
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "sync"
+
+ "github.com/microsoft/typescript-go/internal/api/encoder"
+ "github.com/microsoft/typescript-go/internal/ast"
+ "github.com/microsoft/typescript-go/internal/astnav"
+ "github.com/microsoft/typescript-go/internal/checker"
+ "github.com/microsoft/typescript-go/internal/core"
+ "github.com/microsoft/typescript-go/internal/lsp/lsproto"
+ "github.com/microsoft/typescript-go/internal/project"
+ "github.com/microsoft/typescript-go/internal/tsoptions"
+ "github.com/microsoft/typescript-go/internal/tspath"
+ "github.com/microsoft/typescript-go/internal/vfs"
+)
+
+type handleMap[T any] map[Handle[T]]*T
+
+type APIOptions struct {
+ Logger *project.Logger
+}
+
+type API struct {
+ host APIHost
+ options APIOptions
+
+ documentRegistry *project.DocumentRegistry
+ scriptInfosMu sync.RWMutex
+ scriptInfos map[tspath.Path]*project.ScriptInfo
+
+ projects handleMap[project.Project]
+ filesMu sync.Mutex
+ files handleMap[ast.SourceFile]
+ symbolsMu sync.Mutex
+ symbols handleMap[ast.Symbol]
+ typesMu sync.Mutex
+ types handleMap[checker.Type]
+}
+
+var _ project.ProjectHost = (*API)(nil)
+
+func NewAPI(host APIHost, options APIOptions) *API {
+ api := &API{
+ host: host,
+ options: options,
+ scriptInfos: make(map[tspath.Path]*project.ScriptInfo),
+ projects: make(handleMap[project.Project]),
+ files: make(handleMap[ast.SourceFile]),
+ symbols: make(handleMap[ast.Symbol]),
+ types: make(handleMap[checker.Type]),
+ }
+ api.documentRegistry = &project.DocumentRegistry{
+ Options: tspath.ComparePathsOptions{
+ UseCaseSensitiveFileNames: host.FS().UseCaseSensitiveFileNames(),
+ CurrentDirectory: host.GetCurrentDirectory(),
+ },
+ Hooks: project.DocumentRegistryHooks{
+ OnReleaseDocument: func(file *ast.SourceFile) {
+ _ = api.releaseHandle(string(FileHandle(file)))
+ },
+ },
+ }
+ return api
+}
+
+// DefaultLibraryPath implements ProjectHost.
+func (api *API) DefaultLibraryPath() string {
+ return api.host.DefaultLibraryPath()
+}
+
+// DocumentRegistry implements ProjectHost.
+func (api *API) DocumentRegistry() *project.DocumentRegistry {
+ return api.documentRegistry
+}
+
+// FS implements ProjectHost.
+func (api *API) FS() vfs.FS {
+ return api.host.FS()
+}
+
+// GetCurrentDirectory implements ProjectHost.
+func (api *API) GetCurrentDirectory() string {
+ return api.host.GetCurrentDirectory()
+}
+
+// GetOrCreateScriptInfoForFile implements ProjectHost.
+func (api *API) GetOrCreateScriptInfoForFile(fileName string, path tspath.Path, scriptKind core.ScriptKind) *project.ScriptInfo {
+ return api.getOrCreateScriptInfo(fileName, path, scriptKind)
+}
+
+// GetScriptInfoByPath implements ProjectHost.
+func (api *API) GetScriptInfoByPath(path tspath.Path) *project.ScriptInfo {
+ api.scriptInfosMu.RLock()
+ defer api.scriptInfosMu.RUnlock()
+ return api.scriptInfos[path]
+}
+
+// OnDiscoveredSymlink implements ProjectHost.
+func (api *API) OnDiscoveredSymlink(info *project.ScriptInfo) {
+ // !!!
+}
+
+// Log implements ProjectHost.
+func (api *API) Log(s string) {
+ api.options.Logger.Info(s)
+}
+
+// NewLine implements ProjectHost.
+func (api *API) NewLine() string {
+ return api.host.NewLine()
+}
+
+// PositionEncoding implements ProjectHost.
+func (api *API) PositionEncoding() lsproto.PositionEncodingKind {
+ return lsproto.PositionEncodingKindUTF8
+}
+
+func (api *API) HandleRequest(id int, method string, payload []byte) ([]byte, error) {
+ params, err := unmarshalPayload(method, payload)
+ if err != nil {
+ return nil, err
+ }
+
+ switch Method(method) {
+ case MethodRelease:
+ if id, ok := params.(*string); ok {
+ return nil, api.releaseHandle(*id)
+ } else {
+ return nil, fmt.Errorf("expected string for release handle, got %T", params)
+ }
+ case MethodGetSourceFile:
+ params := params.(*GetSourceFileParams)
+ sourceFile, err := api.GetSourceFile(params.Project, params.FileName)
+ if err != nil {
+ return nil, err
+ }
+ return encoder.EncodeSourceFile(sourceFile, string(FileHandle(sourceFile)))
+ case MethodParseConfigFile:
+ return encodeJSON(api.ParseConfigFile(params.(*ParseConfigFileParams).FileName))
+ case MethodLoadProject:
+ return encodeJSON(api.LoadProject(params.(*LoadProjectParams).ConfigFileName))
+ case MethodGetSymbolAtPosition:
+ params := params.(*GetSymbolAtPositionParams)
+ return encodeJSON(api.GetSymbolAtPosition(params.Project, params.FileName, int(params.Position)))
+ case MethodGetSymbolsAtPositions:
+ params := params.(*GetSymbolsAtPositionsParams)
+ return encodeJSON(core.TryMap(params.Positions, func(position uint32) (any, error) {
+ return api.GetSymbolAtPosition(params.Project, params.FileName, int(position))
+ }))
+ case MethodGetSymbolAtLocation:
+ params := params.(*GetSymbolAtLocationParams)
+ return encodeJSON(api.GetSymbolAtLocation(params.Project, params.Location))
+ case MethodGetSymbolsAtLocations:
+ params := params.(*GetSymbolsAtLocationsParams)
+ return encodeJSON(core.TryMap(params.Locations, func(location Handle[ast.Node]) (any, error) {
+ return api.GetSymbolAtLocation(params.Project, location)
+ }))
+ case MethodGetTypeOfSymbol:
+ params := params.(*GetTypeOfSymbolParams)
+ return encodeJSON(api.GetTypeOfSymbol(params.Project, params.Symbol))
+ case MethodGetTypesOfSymbols:
+ params := params.(*GetTypesOfSymbolsParams)
+ return encodeJSON(core.TryMap(params.Symbols, func(symbol Handle[ast.Symbol]) (any, error) {
+ return api.GetTypeOfSymbol(params.Project, symbol)
+ }))
+ default:
+ return nil, fmt.Errorf("unhandled API method %q", method)
+ }
+}
+
+func (api *API) Close() {
+ api.options.Logger.Close()
+}
+
+func (api *API) ParseConfigFile(configFileName string) (*ConfigFileResponse, error) {
+ configFileName = api.toAbsoluteFileName(configFileName)
+ configFileContent, ok := api.host.FS().ReadFile(configFileName)
+ if !ok {
+ return nil, fmt.Errorf("could not read file %q", configFileName)
+ }
+ configDir := tspath.GetDirectoryPath(configFileName)
+ tsConfigSourceFile := tsoptions.NewTsconfigSourceFileFromFilePath(configFileName, api.toPath(configFileName), configFileContent)
+ parsedCommandLine := tsoptions.ParseJsonSourceFileConfigFileContent(
+ tsConfigSourceFile,
+ api.host,
+ configDir,
+ nil, /*existingOptions*/
+ configFileName,
+ nil, /*resolutionStack*/
+ nil, /*extraFileExtensions*/
+ nil, /*extendedConfigCache*/
+ )
+ return &ConfigFileResponse{
+ FileNames: parsedCommandLine.FileNames(),
+ Options: parsedCommandLine.CompilerOptions(),
+ }, nil
+}
+
+func (api *API) LoadProject(configFileName string) (*ProjectResponse, error) {
+ configFileName = api.toAbsoluteFileName(configFileName)
+ configFilePath := api.toPath(configFileName)
+ p := project.NewConfiguredProject(configFileName, configFilePath, api)
+ if err := p.LoadConfig(); err != nil {
+ return nil, err
+ }
+ p.GetProgram()
+ data := NewProjectResponse(p)
+ api.projects[data.Id] = p
+ return data, nil
+}
+
+func (api *API) GetSymbolAtPosition(projectId Handle[project.Project], fileName string, position int) (*SymbolResponse, error) {
+ project, ok := api.projects[projectId]
+ if !ok {
+ return nil, errors.New("project not found")
+ }
+ symbol, err := project.LanguageService().GetSymbolAtPosition(fileName, position)
+ if err != nil || symbol == nil {
+ return nil, err
+ }
+ data := NewSymbolResponse(symbol)
+ api.symbolsMu.Lock()
+ defer api.symbolsMu.Unlock()
+ api.symbols[data.Id] = symbol
+ return data, nil
+}
+
+func (api *API) GetSymbolAtLocation(projectId Handle[project.Project], location Handle[ast.Node]) (*SymbolResponse, error) {
+ project, ok := api.projects[projectId]
+ if !ok {
+ return nil, errors.New("project not found")
+ }
+ fileHandle, pos, kind, err := parseNodeHandle(location)
+ if err != nil {
+ return nil, err
+ }
+ api.filesMu.Lock()
+ defer api.filesMu.Unlock()
+ sourceFile, ok := api.files[fileHandle]
+ if !ok {
+ return nil, fmt.Errorf("file %q not found", fileHandle)
+ }
+ token := astnav.GetTokenAtPosition(sourceFile, pos)
+ if token == nil {
+ return nil, fmt.Errorf("token not found at position %d in file %q", pos, sourceFile.FileName())
+ }
+ node := ast.FindAncestorKind(token, kind)
+ if node == nil {
+ return nil, fmt.Errorf("node of kind %s not found at position %d in file %q", kind.String(), pos, sourceFile.FileName())
+ }
+ symbol := project.LanguageService().GetSymbolAtLocation(node)
+ if symbol == nil {
+ return nil, nil
+ }
+ data := NewSymbolResponse(symbol)
+ api.symbolsMu.Lock()
+ defer api.symbolsMu.Unlock()
+ api.symbols[data.Id] = symbol
+ return data, nil
+}
+
+func (api *API) GetTypeOfSymbol(projectId Handle[project.Project], symbolHandle Handle[ast.Symbol]) (*TypeResponse, error) {
+ project, ok := api.projects[projectId]
+ if !ok {
+ return nil, errors.New("project not found")
+ }
+ api.symbolsMu.Lock()
+ defer api.symbolsMu.Unlock()
+ symbol, ok := api.symbols[symbolHandle]
+ if !ok {
+ return nil, fmt.Errorf("symbol %q not found", symbolHandle)
+ }
+ t := project.LanguageService().GetTypeOfSymbol(symbol)
+ if t == nil {
+ return nil, nil
+ }
+ return NewTypeData(t), nil
+}
+
+func (api *API) GetSourceFile(projectId Handle[project.Project], fileName string) (*ast.SourceFile, error) {
+ project, ok := api.projects[projectId]
+ if !ok {
+ return nil, errors.New("project not found")
+ }
+ sourceFile := project.GetProgram().GetSourceFile(fileName)
+ if sourceFile == nil {
+ return nil, fmt.Errorf("source file %q not found", fileName)
+ }
+ api.filesMu.Lock()
+ defer api.filesMu.Unlock()
+ api.files[FileHandle(sourceFile)] = sourceFile
+ return sourceFile, nil
+}
+
+func (api *API) releaseHandle(handle string) error {
+ switch handle[0] {
+ case handlePrefixProject:
+ projectId := Handle[project.Project](handle)
+ project, ok := api.projects[projectId]
+ if !ok {
+ return fmt.Errorf("project %q not found", handle)
+ }
+ delete(api.projects, projectId)
+ project.Close()
+ case handlePrefixFile:
+ fileId := Handle[ast.SourceFile](handle)
+ api.filesMu.Lock()
+ defer api.filesMu.Unlock()
+ _, ok := api.files[fileId]
+ if !ok {
+ return fmt.Errorf("file %q not found", handle)
+ }
+ delete(api.files, fileId)
+ case handlePrefixSymbol:
+ symbolId := Handle[ast.Symbol](handle)
+ api.symbolsMu.Lock()
+ defer api.symbolsMu.Unlock()
+ _, ok := api.symbols[symbolId]
+ if !ok {
+ return fmt.Errorf("symbol %q not found", handle)
+ }
+ delete(api.symbols, symbolId)
+ case handlePrefixType:
+ typeId := Handle[checker.Type](handle)
+ api.typesMu.Lock()
+ defer api.typesMu.Unlock()
+ _, ok := api.types[typeId]
+ if !ok {
+ return fmt.Errorf("type %q not found", handle)
+ }
+ delete(api.types, typeId)
+ default:
+ return fmt.Errorf("unhandled handle type %q", handle[0])
+ }
+ return nil
+}
+
+func (api *API) getOrCreateScriptInfo(fileName string, path tspath.Path, scriptKind core.ScriptKind) *project.ScriptInfo {
+ api.scriptInfosMu.RLock()
+ info, ok := api.scriptInfos[path]
+ api.scriptInfosMu.RUnlock()
+ if ok {
+ return info
+ }
+
+ content, ok := api.host.FS().ReadFile(fileName)
+ if !ok {
+ return nil
+ }
+ info = project.NewScriptInfo(fileName, path, scriptKind)
+ info.SetTextFromDisk(content)
+ api.scriptInfosMu.Lock()
+ defer api.scriptInfosMu.Unlock()
+ api.scriptInfos[path] = info
+ return info
+}
+
+func (api *API) toAbsoluteFileName(fileName string) string {
+ return tspath.GetNormalizedAbsolutePath(fileName, api.host.GetCurrentDirectory())
+}
+
+func (api *API) toPath(fileName string) tspath.Path {
+ return tspath.ToPath(fileName, api.host.GetCurrentDirectory(), api.host.FS().UseCaseSensitiveFileNames())
+}
+
+func encodeJSON(v any, err error) ([]byte, error) {
+ if err != nil {
+ return nil, err
+ }
+ return json.Marshal(v)
+}
diff --git a/internal/api/encoder/encoder.go b/internal/api/encoder/encoder.go
new file mode 100644
index 0000000000..5a1502eba3
--- /dev/null
+++ b/internal/api/encoder/encoder.go
@@ -0,0 +1,824 @@
+package encoder
+
+import (
+ "encoding/binary"
+ "fmt"
+ "slices"
+
+ "github.com/microsoft/typescript-go/internal/ast"
+)
+
+const (
+ NodeOffsetKind = iota * 4
+ NodeOffsetPos
+ NodeOffsetEnd
+ NodeOffsetNext
+ NodeOffsetParent
+ NodeOffsetData
+ // NodeSize is the number of bytes that represents a single node in the encoded format.
+ NodeSize
+)
+
+const (
+ NodeDataTypeChildren uint32 = iota << 30
+ NodeDataTypeString
+ NodeDataTypeExtendedData
+)
+
+const (
+ NodeDataTypeMask uint32 = 0xc0_00_00_00
+ NodeDataChildMask uint32 = 0x00_00_00_ff
+ NodeDataStringIndexMask uint32 = 0x00_ff_ff_ff
+)
+
+const (
+ SyntaxKindNodeList uint32 = 1<<32 - 1
+)
+
+const (
+ HeaderOffsetMetadata = iota * 4
+ HeaderOffsetStringOffsets
+ HeaderOffsetStringData
+ HeaderOffsetExtendedData
+ HeaderOffsetNodes
+ HeaderSize
+)
+
+const (
+ ProtocolVersion uint8 = 1
+)
+
+// Source File Binary Format
+// =========================
+//
+// The following defines a protocol for serializing TypeScript SourceFile objects to a compact binary format. All integer
+// values are little-endian.
+//
+// Overview
+// --------
+//
+// The format comprises six sections:
+//
+// | Section | Length | Description |
+// | ------------------ | ------------------ | ---------------------------------------------------------------------------------------- |
+// | Header | 20 bytes | Contains byte offsets to the start of each section. |
+// | String offsets | 8 bytes per string | Pairs of starting byte offsets and ending byte offsets into the **string data** section. |
+// | String data | variable | UTF-8 encoded string data. |
+// | Extended node data | variable | Extra data for some kinds of nodes. |
+// | Nodes | 24 bytes per node | Defines the AST structure of the file, with references to strings and extended data. |
+//
+// Header (20 bytes)
+// -----------------
+//
+// The header contains the following fields:
+//
+// | Byte offset | Type | Field |
+// | ----------- | ------ | ----------------------------------------- |
+// | 0 | uint8 | Protocol version |
+// | 1-4 | | Reserved |
+// | 4-8 | uint32 | Byte offset to string offsets section |
+// | 8-12 | uint32 | Byte offset to string data section |
+// | 12-16 | uint32 | Byte offset to extended node data section |
+// | 16-20 | uint32 | Byte offset to nodes section |
+//
+// String offsets (8 bytes per string)
+// -----------------------------------
+//
+// Each string offset entry consists of two 4-byte unsigned integers, representing the start and end byte offsets into the
+// **string data** section.
+//
+// String data (variable)
+// ----------------------
+//
+// The string data section contains UTF-8 encoded string data. In typical cases, the entirety of the string data is the
+// source file text, and individual nodes with string properties reference their positional slice of the file text. In
+// cases where a node's string property is not equal to the slice of file text at its position, the unique string is
+// appended to the string data section after the file text.
+//
+// Extended node data (variable)
+// -----------------------------
+//
+// The extended node data section contains additional data for specific node types. The length and meaning of each entry
+// is defined by the node type.
+//
+// Currently, the only node types that use this section are `TemplateHead`, `TemplateMiddle`, `TemplateTail`, and
+// `SourceFile`. The extended data format for the first three is:
+//
+// | Byte offset | Type | Field |
+// | ----------- | ------ | ------------------------------------------------ |
+// | 0-4 | uint32 | Index of `text` in the string offsets section |
+// | 4-8 | uint32 | Index of `rawText` in the string offsets section |
+// | 8-12 | uint32 | Value of `templateFlags` |
+//
+// and for `SourceFile` is:
+//
+// | Byte offset | Type | Field |
+// | ----------- | ------ | ------------------------------------------------- |
+// | 0-4 | uint32 | Index of `text` in the string offsets section |
+// | 4-8 | uint32 | Index of `fileName` in the string offsets section |
+// | 8-12 | uint32 | Index of `id` in the string offsets section |
+//
+// Nodes (24 bytes per node)
+// -------------------------
+//
+// The nodes section contains the AST structure of the file. Nodes are represented in a flat array in source order,
+// heavily inspired by https://marvinh.dev/blog/speeding-up-javascript-ecosystem-part-11/. Each node has the following
+// structure:
+//
+// | Byte offset | Type | Field |
+// | ----------- | ------ | -------------------------- |
+// | 0-4 | uint32 | Kind |
+// | 4-8 | uint32 | Pos |
+// | 8-12 | uint32 | End |
+// | 12-16 | uint32 | Node index of next sibling |
+// | 16-20 | uint32 | Node index of parent |
+// | 20-24 | | Node data |
+//
+// The first 24 bytes of the nodes section are zeros representing a nil node, such that nodes without a parent or next
+// sibling can unambiuously use `0` for those indices.
+//
+// NodeLists are represented as normal nodes with the special `kind` value `0xff_ff_ff_ff`. They are considered the parent
+// of their contents in the encoded format. A client reconstructing an AST similar to TypeScript's internal representation
+// should instead set the `parent` pointers of a NodeList's children to the NodeList's parent. A NodeList's `data` field
+// is the uint32 length of the list, and does not use one of the data types described below.
+//
+// For node types other than NodeList, the node data field encodes one of the following, determined by the first 2 bits of
+// the field:
+//
+// | Value | Data type | Description |
+// | ----- | --------- | ------------------------------------------------------------------------------------ |
+// | 0b00 | Children | Disambiguates which named properties of the node its children should be assigned to. |
+// | 0b01 | String | The index of the node's string property in the **string offsets** section. |
+// | 0b10 | Extended | The byte offset of the node's extended data into the **extended node data** section. |
+// | 0b11 | Reserved | Reserved for future use. |
+//
+// In all node data types, the remaining 6 bits of the first byte are used to encode booleans specific to the node type:
+//
+// | Node type | Bits 2-5 | Bit 1 | Bit 0 |
+// | ------------------------- | -------- | ------------- | ------------------------------- |
+// | `ImportSpecifier` | | | `isTypeOnly` |
+// | `ImportClause` | | | `isTypeOnly` |
+// | `ExportSpecifier` | | | `isTypeOnly` |
+// | `ImportEqualsDeclaration` | | | `isTypeOnly` |
+// | `ExportDeclaration` | | | `isTypeOnly` |
+// | `ImportTypeNode` | | | `isTypeOf` |
+// | `ExportAssignment` | | | `isExportEquals` |
+// | `Block` | | | `multiline` |
+// | `ArrayLiteralExpression` | | | `multiline` |
+// | `ObjectLiteralExpression` | | | `multiline` |
+// | `JsxText` | | | `containsOnlyTriviaWhiteSpaces` |
+// | `JSDocTypeLiteral` | | | `isArrayType` |
+// | `JsDocPropertyTag` | | `isNameFirst` | `isBracketed` |
+// | `JsDocParameterTag` | | `isNameFirst` | `isBracketed` |
+// | `VariableDeclarationList` | | is `const` | is `let` |
+// | `ImportAttributes` | | is `assert` | `multiline` |
+//
+// The remaining 3 bytes of the node data field vary by data type:
+//
+// ### Children (0b00)
+//
+// If a node has fewer children than its type allows, additional data is needed to determine which properties the children
+// correspond to. The last byte of the 4-byte data field is a bitmask representing the child properties of the node type,
+// in visitor order, where `1` indicates that the child at that property is present and `0` indicates that the property is
+// nil. For example, a `MethodDeclaration` has the following child properties:
+//
+// | Property name | Bit position |
+// | -------------- | ------------ |
+// | modifiers | 0 |
+// | asteriskToken | 1 |
+// | name | 2 |
+// | postfixToken | 3 |
+// | typeParameters | 4 |
+// | parameters | 5 |
+// | returnType | 6 |
+// | body | 7 |
+//
+// A bitmask with value `0b01100101` would indicate that the next four direct descendants (i.e., node records that have a
+// `parent` set to the node index of the `MethodDeclaration`) of the node are its `modifiers`, `name`, `parameters`, and
+// `body` properties, in that order. The remaining properties are nil. (To reconstruct the node with named properties, the
+// client must consult a static table of each node type's child property names.)
+//
+// The bitmask may be zero for node types that can only have a single child, since no disambiguation is needed.
+// Additionally, the children data type may be used for nodes that can never have children, but do not require other
+// data types.
+//
+// ### String (0b01)
+//
+// The string data type is used for nodes with a single string property. (Currently, the name of that property is always
+// `text`.) The last three bytes of the 4-byte data field form a single 24-bit unsigned integer (i.e.,
+// `uint32(0x00_ff_ff_ff & node.data)`) _N_ that is an index into the **string offsets** section. The *N*th 32-bit
+// unsigned integer in the **string offsets** section is the byte offset of the start of the string in the **string data**
+// section, and the *N+1*th 32-bit unsigned integer is the byte offset of the end of the string in the
+// **string data** section.
+//
+// ### Extended (0b10)
+//
+// The extended data type is used for nodes with properties that don't fit into either the children or string data types.
+// The last three bytes of the 4-byte data field form a single 24-bit unsigned integer (i.e.,
+// `uint32(0x00_ff_ff_ff & node.data)`) _N_ that is a byte offset into the **extended node data** section. The length and
+// meaning of the data at that offset is defined by the node type. See the **Extended node data** section for details on
+// the format of the extended data for specific node types.
+
+func EncodeSourceFile(sourceFile *ast.SourceFile, id string) ([]byte, error) {
+ var parentIndex, nodeCount, prevIndex uint32
+ var extendedData []byte
+ strs := newStringTable(sourceFile.Text(), sourceFile.TextCount)
+ nodes := make([]byte, 0, (sourceFile.NodeCount+1)*NodeSize)
+
+ visitor := &ast.NodeVisitor{
+ Hooks: ast.NodeVisitorHooks{
+ VisitNodes: func(nodeList *ast.NodeList, visitor *ast.NodeVisitor) *ast.NodeList {
+ if nodeList == nil || len(nodeList.Nodes) == 0 {
+ return nodeList
+ }
+
+ nodeCount++
+ if prevIndex != 0 {
+ // this is the next sibling of `prevNode`
+ b0, b1, b2, b3 := uint8(nodeCount), uint8(nodeCount>>8), uint8(nodeCount>>16), uint8(nodeCount>>24)
+ nodes[prevIndex*NodeSize+NodeOffsetNext+0] = b0
+ nodes[prevIndex*NodeSize+NodeOffsetNext+1] = b1
+ nodes[prevIndex*NodeSize+NodeOffsetNext+2] = b2
+ nodes[prevIndex*NodeSize+NodeOffsetNext+3] = b3
+ }
+
+ nodes = appendUint32s(nodes, SyntaxKindNodeList, uint32(nodeList.Pos()), uint32(nodeList.End()), 0, parentIndex, uint32(len(nodeList.Nodes)))
+
+ saveParentIndex := parentIndex
+
+ currentIndex := nodeCount
+ prevIndex = 0
+ parentIndex = currentIndex
+ visitor.VisitSlice(nodeList.Nodes)
+ prevIndex = currentIndex
+ parentIndex = saveParentIndex
+
+ return nodeList
+ },
+ VisitModifiers: func(modifiers *ast.ModifierList, visitor *ast.NodeVisitor) *ast.ModifierList {
+ if modifiers != nil && len(modifiers.Nodes) > 0 {
+ visitor.Hooks.VisitNodes(&modifiers.NodeList, visitor)
+ }
+ return modifiers
+ },
+ },
+ }
+ visitor.Visit = func(node *ast.Node) *ast.Node {
+ nodeCount++
+ if prevIndex != 0 {
+ // this is the next sibling of `prevNode`
+ b0, b1, b2, b3 := uint8(nodeCount), uint8(nodeCount>>8), uint8(nodeCount>>16), uint8(nodeCount>>24)
+ nodes[prevIndex*NodeSize+NodeOffsetNext+0] = b0
+ nodes[prevIndex*NodeSize+NodeOffsetNext+1] = b1
+ nodes[prevIndex*NodeSize+NodeOffsetNext+2] = b2
+ nodes[prevIndex*NodeSize+NodeOffsetNext+3] = b3
+ }
+
+ nodes = appendUint32s(nodes, uint32(node.Kind), uint32(node.Pos()), uint32(node.End()), 0, parentIndex, getNodeData(node, strs, &extendedData))
+
+ saveParentIndex := parentIndex
+
+ currentIndex := nodeCount
+ prevIndex = 0
+ parentIndex = currentIndex
+ visitor.VisitEachChild(node)
+ prevIndex = currentIndex
+ parentIndex = saveParentIndex
+ return node
+ }
+
+ nodes = appendUint32s(nodes, 0, 0, 0, 0, 0, 0)
+
+ nodeCount++
+ parentIndex++
+ nodes = appendUint32s(nodes, uint32(sourceFile.Kind), uint32(sourceFile.Pos()), uint32(sourceFile.End()), 0, 0, getSourceFileData(sourceFile, id, strs, &extendedData))
+
+ visitor.VisitEachChild(sourceFile.AsNode())
+
+ metadata := uint32(ProtocolVersion) << 24
+ offsetStringTableOffsets := HeaderSize
+ offsetStringTableData := HeaderSize + len(strs.offsets)*4
+ offsetExtendedData := offsetStringTableData + strs.stringLength()
+ offsetNodes := offsetExtendedData + len(extendedData)
+
+ header := []uint32{
+ metadata,
+ uint32(offsetStringTableOffsets),
+ uint32(offsetStringTableData),
+ uint32(offsetExtendedData),
+ uint32(offsetNodes),
+ }
+
+ var headerBytes, strsBytes []byte
+ headerBytes = appendUint32s(nil, header...)
+ strsBytes = strs.encode()
+
+ return slices.Concat(
+ headerBytes,
+ strsBytes,
+ extendedData,
+ nodes,
+ ), nil
+}
+
+func appendUint32s(buf []byte, values ...uint32) []byte {
+ for _, value := range values {
+ var err error
+ if buf, err = binary.Append(buf, binary.LittleEndian, value); err != nil {
+ // The only error binary.Append can return is for values that are not fixed-size.
+ // This can never happen here, since we are always appending uint32.
+ panic(fmt.Sprintf("failed to append uint32: %v", err))
+ }
+ }
+ return buf
+}
+
+func getSourceFileData(sourceFile *ast.SourceFile, id string, strs *stringTable, extendedData *[]byte) uint32 {
+ t := NodeDataTypeExtendedData
+ extendedDataOffset := len(*extendedData)
+ textIndex := strs.add(sourceFile.Text(), sourceFile.Kind, sourceFile.Pos(), sourceFile.End())
+ fileNameIndex := strs.add(sourceFile.FileName(), 0, 0, 0)
+ idIndex := strs.add(id, 0, 0, 0)
+ *extendedData = appendUint32s(*extendedData, textIndex, fileNameIndex, idIndex)
+ return t | uint32(extendedDataOffset)
+}
+
+func getNodeData(node *ast.Node, strs *stringTable, extendedData *[]byte) uint32 {
+ t := getNodeDataType(node)
+ switch t {
+ case NodeDataTypeChildren:
+ return t | getNodeDefinedData(node) | uint32(getChildrenPropertyMask(node))
+ case NodeDataTypeString:
+ return t | getNodeDefinedData(node) | recordNodeStrings(node, strs)
+ case NodeDataTypeExtendedData:
+ return t | getNodeDefinedData(node) | recordExtendedData(node, strs, extendedData)
+ default:
+ panic("unreachable")
+ }
+}
+
+func getNodeDataType(node *ast.Node) uint32 {
+ switch node.Kind {
+ case ast.KindJsxText,
+ ast.KindIdentifier,
+ ast.KindPrivateIdentifier,
+ ast.KindStringLiteral,
+ ast.KindNumericLiteral,
+ ast.KindBigIntLiteral,
+ ast.KindRegularExpressionLiteral,
+ ast.KindNoSubstitutionTemplateLiteral,
+ ast.KindJSDocText:
+ return NodeDataTypeString
+ case ast.KindTemplateHead,
+ ast.KindTemplateMiddle,
+ ast.KindTemplateTail,
+ ast.KindSourceFile:
+ return NodeDataTypeExtendedData
+ default:
+ return NodeDataTypeChildren
+ }
+}
+
+// getChildrenPropertyMask returns a mask of which children properties are present in the node.
+// It is defined for node kinds that have more than one property that is a pointer to a child node.
+// Example: QualifiedName has two children properties: Left and Right, which are visited in that order.
+// result&1 is non-zero if Left is present, and result&2 is non-zero if Right is present. If the client
+// knows that QualifiedName has properties ["Left", "Right"] and sees an encoded node with only one
+// child, it can use the mask to determine which property is present.
+func getChildrenPropertyMask(node *ast.Node) uint8 {
+ switch node.Kind {
+ case ast.KindQualifiedName:
+ n := node.AsQualifiedName()
+ return (boolToByte(n.Left != nil) << 0) | (boolToByte(n.Right != nil) << 1)
+ case ast.KindTypeParameter:
+ n := node.AsTypeParameter()
+ return (boolToByte(n.Modifiers() != nil) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.Constraint != nil) << 2) | (boolToByte(n.DefaultType != nil) << 3)
+ case ast.KindIfStatement:
+ n := node.AsIfStatement()
+ return (boolToByte(n.Expression != nil) << 0) | (boolToByte(n.ThenStatement != nil) << 1) | (boolToByte(n.ElseStatement != nil) << 2)
+ case ast.KindDoStatement:
+ n := node.AsDoStatement()
+ return (boolToByte(n.Statement != nil) << 0) | (boolToByte(n.Expression != nil) << 1)
+ case ast.KindWhileStatement:
+ n := node.AsWhileStatement()
+ return (boolToByte(n.Expression != nil) << 0) | (boolToByte(n.Statement != nil) << 1)
+ case ast.KindForStatement:
+ n := node.AsForStatement()
+ return (boolToByte(n.Initializer != nil) << 0) | (boolToByte(n.Condition != nil) << 1) | (boolToByte(n.Incrementor != nil) << 2) | (boolToByte(n.Statement != nil) << 3)
+ case ast.KindForInStatement, ast.KindForOfStatement:
+ n := node.AsForInOrOfStatement()
+ return (boolToByte(n.AwaitModifier != nil) << 0) | (boolToByte(n.Initializer != nil) << 1) | (boolToByte(n.Expression != nil) << 2) | (boolToByte(n.Statement != nil) << 3)
+ case ast.KindWithStatement:
+ n := node.AsWithStatement()
+ return (boolToByte(n.Expression != nil) << 0) | (boolToByte(n.Statement != nil) << 1)
+ case ast.KindSwitchStatement:
+ n := node.AsSwitchStatement()
+ return (boolToByte(n.Expression != nil) << 0) | (boolToByte(n.CaseBlock != nil) << 1)
+ case ast.KindCaseClause, ast.KindDefaultClause:
+ n := node.AsCaseOrDefaultClause()
+ return (boolToByte(n.Expression != nil) << 0) | (boolToByte(n.Statements != nil) << 1)
+ case ast.KindTryStatement:
+ n := node.AsTryStatement()
+ return (boolToByte(n.TryBlock != nil) << 0) | (boolToByte(n.CatchClause != nil) << 1) | (boolToByte(n.FinallyBlock != nil) << 2)
+ case ast.KindCatchClause:
+ n := node.AsCatchClause()
+ return (boolToByte(n.VariableDeclaration != nil) << 0) | (boolToByte(n.Block != nil) << 1)
+ case ast.KindLabeledStatement:
+ n := node.AsLabeledStatement()
+ return (boolToByte(n.Label != nil) << 0) | (boolToByte(n.Statement != nil) << 1)
+ case ast.KindVariableStatement:
+ n := node.AsVariableStatement()
+ return (boolToByte(n.Modifiers() != nil) << 0) | (boolToByte(n.DeclarationList != nil) << 1)
+ case ast.KindVariableDeclaration:
+ n := node.AsVariableDeclaration()
+ return (boolToByte(n.Name() != nil) << 0) | (boolToByte(n.ExclamationToken != nil) << 1) | (boolToByte(n.Type != nil) << 2) | (boolToByte(n.Initializer != nil) << 3)
+ case ast.KindParameter:
+ n := node.AsParameterDeclaration()
+ return (boolToByte(n.Modifiers() != nil) << 0) | (boolToByte(n.DotDotDotToken != nil) << 1) | (boolToByte(n.Name() != nil) << 2) | (boolToByte(n.QuestionToken != nil) << 3) | (boolToByte(n.Type != nil) << 4) | (boolToByte(n.Initializer != nil) << 5)
+ case ast.KindBindingElement:
+ n := node.AsBindingElement()
+ return (boolToByte(n.DotDotDotToken != nil) << 0) | (boolToByte(n.PropertyName != nil) << 1) | (boolToByte(n.Name() != nil) << 2) | (boolToByte(n.Initializer != nil) << 3)
+ case ast.KindFunctionDeclaration:
+ n := node.AsFunctionDeclaration()
+ return (boolToByte(n.Modifiers() != nil) << 0) | (boolToByte(n.AsteriskToken != nil) << 1) | (boolToByte(n.Name() != nil) << 2) | (boolToByte(n.TypeParameters != nil) << 3) | (boolToByte(n.Parameters != nil) << 4) | (boolToByte(n.Type != nil) << 5) | (boolToByte(n.Body != nil) << 6)
+ case ast.KindInterfaceDeclaration:
+ n := node.AsInterfaceDeclaration()
+ return (boolToByte(n.Modifiers() != nil) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.TypeParameters != nil) << 2) | (boolToByte(n.HeritageClauses != nil) << 3) | (boolToByte(n.Members != nil) << 4)
+ case ast.KindTypeAliasDeclaration:
+ n := node.AsTypeAliasDeclaration()
+ return (boolToByte(n.Modifiers() != nil) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.TypeParameters != nil) << 2) | (boolToByte(n.Type != nil) << 3)
+ case ast.KindEnumMember:
+ n := node.AsEnumMember()
+ return (boolToByte(n.Name() != nil) << 0) | (boolToByte(n.Initializer != nil) << 1)
+ case ast.KindEnumDeclaration:
+ n := node.AsEnumDeclaration()
+ return (boolToByte(n.Modifiers() != nil) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.Members != nil) << 2)
+ case ast.KindModuleDeclaration:
+ n := node.AsModuleDeclaration()
+ return (boolToByte(n.Modifiers() != nil) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.Body != nil) << 2)
+ case ast.KindImportEqualsDeclaration:
+ n := node.AsImportEqualsDeclaration()
+ return (boolToByte(n.Modifiers() != nil) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.ModuleReference != nil) << 2)
+ case ast.KindImportDeclaration:
+ n := node.AsImportDeclaration()
+ return (boolToByte(n.Modifiers() != nil) << 0) | (boolToByte(n.ImportClause != nil) << 1) | (boolToByte(n.ModuleSpecifier != nil) << 2) | (boolToByte(n.Attributes != nil) << 3)
+ case ast.KindImportSpecifier:
+ n := node.AsImportSpecifier()
+ return (boolToByte(n.PropertyName != nil) << 0) | (boolToByte(n.Name() != nil) << 1)
+ case ast.KindImportClause:
+ n := node.AsImportClause()
+ return (boolToByte(n.Name() != nil) << 0) | (boolToByte(n.NamedBindings != nil) << 1)
+ case ast.KindExportAssignment:
+ n := node.AsExportAssignment()
+ return (boolToByte(n.Modifiers() != nil) << 0) | (boolToByte(n.Expression != nil) << 1)
+ case ast.KindNamespaceExportDeclaration:
+ n := node.AsNamespaceExportDeclaration()
+ return (boolToByte(n.Modifiers() != nil) << 0) | (boolToByte(n.Name() != nil) << 1)
+ case ast.KindExportDeclaration:
+ n := node.AsExportDeclaration()
+ return (boolToByte(n.Modifiers() != nil) << 0) | (boolToByte(n.ExportClause != nil) << 1) | (boolToByte(n.ModuleSpecifier != nil) << 2) | (boolToByte(n.Attributes != nil) << 3)
+ case ast.KindExportSpecifier:
+ n := node.AsExportSpecifier()
+ return (boolToByte(n.PropertyName != nil) << 0) | (boolToByte(n.Name() != nil) << 1)
+ case ast.KindCallSignature:
+ n := node.AsCallSignatureDeclaration()
+ return (boolToByte(n.TypeParameters != nil) << 0) | (boolToByte(n.Parameters != nil) << 1) | (boolToByte(n.Type != nil) << 2)
+ case ast.KindConstructSignature:
+ n := node.AsConstructSignatureDeclaration()
+ return (boolToByte(n.TypeParameters != nil) << 0) | (boolToByte(n.Parameters != nil) << 1) | (boolToByte(n.Type != nil) << 2)
+ case ast.KindConstructor:
+ n := node.AsConstructorDeclaration()
+ return (boolToByte(n.Modifiers() != nil) << 0) | (boolToByte(n.TypeParameters != nil) << 1) | (boolToByte(n.Parameters != nil) << 2) | (boolToByte(n.Type != nil) << 3) | (boolToByte(n.Body != nil) << 4)
+ case ast.KindGetAccessor:
+ n := node.AsGetAccessorDeclaration()
+ return (boolToByte(n.Modifiers() != nil) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.TypeParameters != nil) << 2) | (boolToByte(n.Parameters != nil) << 3) | (boolToByte(n.Type != nil) << 4) | (boolToByte(n.Body != nil) << 5)
+ case ast.KindSetAccessor:
+ n := node.AsSetAccessorDeclaration()
+ return (boolToByte(n.Modifiers() != nil) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.TypeParameters != nil) << 2) | (boolToByte(n.Parameters != nil) << 3) | (boolToByte(n.Type != nil) << 4) | (boolToByte(n.Body != nil) << 5)
+ case ast.KindIndexSignature:
+ n := node.AsIndexSignatureDeclaration()
+ return (boolToByte(n.Modifiers() != nil) << 0) | (boolToByte(n.Parameters != nil) << 1) | (boolToByte(n.Type != nil) << 2)
+ case ast.KindMethodSignature:
+ n := node.AsMethodSignatureDeclaration()
+ return (boolToByte(n.Modifiers() != nil) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.PostfixToken != nil) << 2) | (boolToByte(n.TypeParameters != nil) << 3) | (boolToByte(n.Parameters != nil) << 4) | (boolToByte(n.Type != nil) << 5)
+ case ast.KindMethodDeclaration:
+ n := node.AsMethodDeclaration()
+ return (boolToByte(n.Modifiers() != nil) << 0) | (boolToByte(n.AsteriskToken != nil) << 1) | (boolToByte(n.Name() != nil) << 2) | (boolToByte(n.PostfixToken != nil) << 3) | (boolToByte(n.TypeParameters != nil) << 4) | (boolToByte(n.Parameters != nil) << 5) | (boolToByte(n.Type != nil) << 6) | (boolToByte(n.Body != nil) << 7)
+ case ast.KindPropertySignature:
+ n := node.AsPropertySignatureDeclaration()
+ return (boolToByte(n.Modifiers() != nil) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.PostfixToken != nil) << 2) | (boolToByte(n.Type != nil) << 3) | (boolToByte(n.Initializer != nil) << 4)
+ case ast.KindPropertyDeclaration:
+ n := node.AsPropertyDeclaration()
+ return (boolToByte(n.Modifiers() != nil) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.PostfixToken != nil) << 2) | (boolToByte(n.Type != nil) << 3) | (boolToByte(n.Initializer != nil) << 4)
+ case ast.KindBinaryExpression:
+ n := node.AsBinaryExpression()
+ return (boolToByte(n.Left != nil) << 0) | (boolToByte(n.OperatorToken != nil) << 1) | (boolToByte(n.Right != nil) << 2)
+ case ast.KindYieldExpression:
+ n := node.AsYieldExpression()
+ return (boolToByte(n.AsteriskToken != nil) << 0) | (boolToByte(n.Expression != nil) << 1)
+ case ast.KindArrowFunction:
+ n := node.AsArrowFunction()
+ return (boolToByte(n.Modifiers() != nil) << 0) | (boolToByte(n.TypeParameters != nil) << 1) | (boolToByte(n.Parameters != nil) << 2) | (boolToByte(n.Type != nil) << 3) | (boolToByte(n.EqualsGreaterThanToken != nil) << 4) | (boolToByte(n.Body != nil) << 5)
+ case ast.KindFunctionExpression:
+ n := node.AsFunctionExpression()
+ return (boolToByte(n.Modifiers() != nil) << 0) | (boolToByte(n.AsteriskToken != nil) << 1) | (boolToByte(n.Name() != nil) << 2) | (boolToByte(n.TypeParameters != nil) << 3) | (boolToByte(n.Parameters != nil) << 4) | (boolToByte(n.Type != nil) << 5) | (boolToByte(n.Body != nil) << 6)
+ case ast.KindAsExpression:
+ n := node.AsAsExpression()
+ return (boolToByte(n.Expression != nil) << 0) | (boolToByte(n.Type != nil) << 1)
+ case ast.KindSatisfiesExpression:
+ n := node.AsSatisfiesExpression()
+ return (boolToByte(n.Expression != nil) << 0) | (boolToByte(n.Type != nil) << 1)
+ case ast.KindConditionalExpression:
+ n := node.AsConditionalExpression()
+ return (boolToByte(n.Condition != nil) << 0) | (boolToByte(n.QuestionToken != nil) << 1) | (boolToByte(n.WhenTrue != nil) << 2) | (boolToByte(n.ColonToken != nil) << 3) | (boolToByte(n.WhenFalse != nil) << 4)
+ case ast.KindPropertyAccessExpression:
+ n := node.AsPropertyAccessExpression()
+ return (boolToByte(n.Expression != nil) << 0) | (boolToByte(n.QuestionDotToken != nil) << 1) | (boolToByte(n.Name() != nil) << 2)
+ case ast.KindElementAccessExpression:
+ n := node.AsElementAccessExpression()
+ return (boolToByte(n.Expression != nil) << 0) | (boolToByte(n.QuestionDotToken != nil) << 1) | (boolToByte(n.ArgumentExpression != nil) << 2)
+ case ast.KindCallExpression:
+ n := node.AsCallExpression()
+ return (boolToByte(n.Expression != nil) << 0) | (boolToByte(n.QuestionDotToken != nil) << 1) | (boolToByte(n.TypeArguments != nil) << 2) | (boolToByte(n.Arguments != nil) << 3)
+ case ast.KindNewExpression:
+ n := node.AsNewExpression()
+ return (boolToByte(n.Expression != nil) << 0) | (boolToByte(n.TypeArguments != nil) << 1) | (boolToByte(n.Arguments != nil) << 2)
+ case ast.KindTemplateExpression:
+ n := node.AsTemplateExpression()
+ return (boolToByte(n.Head != nil) << 0) | (boolToByte(n.TemplateSpans != nil) << 1)
+ case ast.KindTemplateSpan:
+ n := node.AsTemplateSpan()
+ return (boolToByte(n.Expression != nil) << 0) | (boolToByte(n.Literal != nil) << 1)
+ case ast.KindTaggedTemplateExpression:
+ n := node.AsTaggedTemplateExpression()
+ return (boolToByte(n.Tag != nil) << 0) | (boolToByte(n.QuestionDotToken != nil) << 1) | (boolToByte(n.TypeArguments != nil) << 2) | (boolToByte(n.Template != nil) << 3)
+ case ast.KindPropertyAssignment:
+ n := node.AsPropertyAssignment()
+ return (boolToByte(n.Modifiers() != nil) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.PostfixToken != nil) << 2) | (boolToByte(n.Initializer != nil) << 3)
+ case ast.KindShorthandPropertyAssignment:
+ n := node.AsShorthandPropertyAssignment()
+ return (boolToByte(n.Modifiers() != nil) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.PostfixToken != nil) << 2) | (boolToByte(n.EqualsToken != nil) << 3) | (boolToByte(n.ObjectAssignmentInitializer != nil) << 4)
+ case ast.KindTypeAssertionExpression:
+ n := node.AsTypeAssertion()
+ return (boolToByte(n.Type != nil) << 0) | (boolToByte(n.Expression != nil) << 1)
+ case ast.KindConditionalType:
+ n := node.AsConditionalTypeNode()
+ return (boolToByte(n.CheckType != nil) << 0) | (boolToByte(n.ExtendsType != nil) << 1) | (boolToByte(n.TrueType != nil) << 2) | (boolToByte(n.FalseType != nil) << 3)
+ case ast.KindIndexedAccessType:
+ n := node.AsIndexedAccessTypeNode()
+ return (boolToByte(n.ObjectType != nil) << 0) | (boolToByte(n.IndexType != nil) << 1)
+ case ast.KindTypeReference:
+ n := node.AsTypeReferenceNode()
+ return (boolToByte(n.TypeName != nil) << 0) | (boolToByte(n.TypeArguments != nil) << 1)
+ case ast.KindExpressionWithTypeArguments:
+ n := node.AsExpressionWithTypeArguments()
+ return (boolToByte(n.Expression != nil) << 0) | (boolToByte(n.TypeArguments != nil) << 1)
+ case ast.KindTypePredicate:
+ n := node.AsTypePredicateNode()
+ return (boolToByte(n.AssertsModifier != nil) << 0) | (boolToByte(n.ParameterName != nil) << 1) | (boolToByte(n.Type != nil) << 2)
+ case ast.KindImportType:
+ n := node.AsImportTypeNode()
+ return (boolToByte(n.Argument != nil) << 0) | (boolToByte(n.Attributes != nil) << 1) | (boolToByte(n.Qualifier != nil) << 2) | (boolToByte(n.TypeArguments != nil) << 3)
+ case ast.KindImportAttribute:
+ n := node.AsImportAttribute()
+ return (boolToByte(n.Name() != nil) << 0) | (boolToByte(n.Value != nil) << 1)
+ case ast.KindTypeQuery:
+ n := node.AsTypeQueryNode()
+ return (boolToByte(n.ExprName != nil) << 0) | (boolToByte(n.TypeArguments != nil) << 1)
+ case ast.KindMappedType:
+ n := node.AsMappedTypeNode()
+ return (boolToByte(n.ReadonlyToken != nil) << 0) | (boolToByte(n.TypeParameter != nil) << 1) | (boolToByte(n.NameType != nil) << 2) | (boolToByte(n.QuestionToken != nil) << 3) | (boolToByte(n.Type != nil) << 4) | (boolToByte(n.Members != nil) << 5)
+ case ast.KindNamedTupleMember:
+ n := node.AsNamedTupleMember()
+ return (boolToByte(n.DotDotDotToken != nil) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.QuestionToken != nil) << 2) | (boolToByte(n.Type != nil) << 3)
+ case ast.KindFunctionType:
+ n := node.AsFunctionTypeNode()
+ return (boolToByte(n.TypeParameters != nil) << 0) | (boolToByte(n.Parameters != nil) << 1) | (boolToByte(n.Type != nil) << 2)
+ case ast.KindConstructorType:
+ n := node.AsConstructorTypeNode()
+ return (boolToByte(n.Modifiers() != nil) << 0) | (boolToByte(n.TypeParameters != nil) << 1) | (boolToByte(n.Parameters != nil) << 2) | (boolToByte(n.Type != nil) << 3)
+ case ast.KindTemplateLiteralType:
+ n := node.AsTemplateLiteralTypeNode()
+ return (boolToByte(n.Head != nil) << 0) | (boolToByte(n.TemplateSpans != nil) << 1)
+ case ast.KindTemplateLiteralTypeSpan:
+ n := node.AsTemplateLiteralTypeSpan()
+ return (boolToByte(n.Type != nil) << 0) | (boolToByte(n.Literal != nil) << 1)
+ case ast.KindJsxElement:
+ n := node.AsJsxElement()
+ return (boolToByte(n.OpeningElement != nil) << 0) | (boolToByte(n.Children != nil) << 1) | (boolToByte(n.ClosingElement != nil) << 2)
+ case ast.KindJsxNamespacedName:
+ n := node.AsJsxNamespacedName()
+ return (boolToByte(n.Name() != nil) << 0) | (boolToByte(n.Namespace != nil) << 1)
+ case ast.KindJsxOpeningElement:
+ n := node.AsJsxOpeningElement()
+ return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.TypeArguments != nil) << 1) | (boolToByte(n.Attributes != nil) << 2)
+ case ast.KindJsxSelfClosingElement:
+ n := node.AsJsxSelfClosingElement()
+ return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.TypeArguments != nil) << 1) | (boolToByte(n.Attributes != nil) << 2)
+ case ast.KindJsxFragment:
+ n := node.AsJsxFragment()
+ return (boolToByte(n.OpeningFragment != nil) << 0) | (boolToByte(n.Children != nil) << 1) | (boolToByte(n.ClosingFragment != nil) << 2)
+ case ast.KindJsxAttribute:
+ n := node.AsJsxAttribute()
+ return (boolToByte(n.Name() != nil) << 0) | (boolToByte(n.Initializer != nil) << 1)
+ case ast.KindJsxExpression:
+ n := node.AsJsxExpression()
+ return (boolToByte(n.DotDotDotToken != nil) << 0) | (boolToByte(n.Expression != nil) << 1)
+ case ast.KindJSDoc:
+ n := node.AsJSDoc()
+ return (boolToByte(n.Comment != nil) << 0) | (boolToByte(n.Tags != nil) << 1)
+ case ast.KindJSDocTypeTag:
+ n := node.AsJSDocTypeTag()
+ return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.TypeExpression != nil) << 1) | (boolToByte(n.Comment != nil) << 2)
+ case ast.KindJSDocTag:
+ n := node.AsJSDocUnknownTag()
+ return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.Comment != nil) << 1)
+ case ast.KindJSDocTemplateTag:
+ n := node.AsJSDocTemplateTag()
+ return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.Constraint != nil) << 1) | (boolToByte(n.TypeParameters() != nil) << 2) | (boolToByte(n.Comment != nil) << 3)
+ case ast.KindJSDocReturnTag:
+ n := node.AsJSDocReturnTag()
+ return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.TypeExpression != nil) << 1) | (boolToByte(n.Comment != nil) << 2)
+ case ast.KindJSDocPublicTag:
+ n := node.AsJSDocPublicTag()
+ return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.Comment != nil) << 1)
+ case ast.KindJSDocPrivateTag:
+ n := node.AsJSDocPrivateTag()
+ return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.Comment != nil) << 1)
+ case ast.KindJSDocProtectedTag:
+ n := node.AsJSDocProtectedTag()
+ return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.Comment != nil) << 1)
+ case ast.KindJSDocReadonlyTag:
+ n := node.AsJSDocReadonlyTag()
+ return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.Comment != nil) << 1)
+ case ast.KindJSDocOverrideTag:
+ n := node.AsJSDocOverrideTag()
+ return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.Comment != nil) << 1)
+ case ast.KindJSDocDeprecatedTag:
+ n := node.AsJSDocDeprecatedTag()
+ return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.Comment != nil) << 1)
+ case ast.KindJSDocSeeTag:
+ n := node.AsJSDocSeeTag()
+ return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.NameExpression != nil) << 1) | (boolToByte(n.Comment != nil) << 2)
+ case ast.KindJSDocImplementsTag:
+ n := node.AsJSDocImplementsTag()
+ return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.ClassName != nil) << 1) | (boolToByte(n.Comment != nil) << 2)
+ case ast.KindJSDocAugmentsTag:
+ n := node.AsJSDocAugmentsTag()
+ return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.ClassName != nil) << 1) | (boolToByte(n.Comment != nil) << 2)
+ case ast.KindJSDocSatisfiesTag:
+ n := node.AsJSDocSatisfiesTag()
+ return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.TypeExpression != nil) << 1) | (boolToByte(n.Comment != nil) << 2)
+ case ast.KindJSDocThisTag:
+ n := node.AsJSDocThisTag()
+ return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.TypeExpression != nil) << 1) | (boolToByte(n.Comment != nil) << 2)
+ case ast.KindJSDocImportTag:
+ n := node.AsJSDocImportTag()
+ return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.ImportClause != nil) << 1) | (boolToByte(n.ModuleSpecifier != nil) << 2) | (boolToByte(n.Attributes != nil) << 3) | (boolToByte(n.Comment != nil) << 4)
+ case ast.KindJSDocCallbackTag:
+ n := node.AsJSDocCallbackTag()
+ return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.TypeExpression != nil) << 1) | (boolToByte(n.FullName != nil) << 2) | (boolToByte(n.Comment != nil) << 3)
+ case ast.KindJSDocOverloadTag:
+ n := node.AsJSDocOverloadTag()
+ return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.TypeExpression != nil) << 1) | (boolToByte(n.Comment != nil) << 2)
+ case ast.KindJSDocTypedefTag:
+ n := node.AsJSDocTypedefTag()
+ return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.TypeExpression != nil) << 1) | (boolToByte(n.Name() != nil) << 2) | (boolToByte(n.Comment != nil) << 3)
+ case ast.KindJSDocSignature:
+ n := node.AsJSDocSignature()
+ return (boolToByte(n.TypeParameters() != nil) << 0) | (boolToByte(n.Parameters != nil) << 1) | (boolToByte(n.Type != nil) << 2)
+ case ast.KindClassStaticBlockDeclaration:
+ n := node.AsClassStaticBlockDeclaration()
+ return (boolToByte(n.Modifiers() != nil) << 0) | (boolToByte(n.Body != nil) << 1)
+ case ast.KindClassDeclaration:
+ n := node.AsClassDeclaration()
+ return (boolToByte(n.Modifiers() != nil) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.TypeParameters != nil) << 2) | (boolToByte(n.HeritageClauses != nil) << 3) | (boolToByte(n.Members != nil) << 4)
+ case ast.KindJSDocPropertyTag:
+ n := node.AsJSDocPropertyTag()
+ if n.IsNameFirst {
+ return (boolToByte(n.Name() != nil) << 0) | (boolToByte(n.TypeExpression != nil) << 1)
+ }
+ return (boolToByte(n.TypeExpression != nil) << 0) | (boolToByte(n.Name() != nil) << 1)
+ case ast.KindJSDocParameterTag:
+ n := node.AsJSDocParameterTag()
+ if n.IsNameFirst {
+ return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.Name() != nil) << 1) | (boolToByte(n.TypeExpression != nil) << 2) | (boolToByte(n.Comment != nil) << 3)
+ }
+ return (boolToByte(n.TagName != nil) << 0) | (boolToByte(n.TypeExpression != nil) << 1) | (boolToByte(n.Name() != nil) << 2) | (boolToByte(n.Comment != nil) << 3)
+ default:
+ return 0
+ }
+}
+
+func getNodeDefinedData(node *ast.Node) uint32 {
+ switch node.Kind {
+ case ast.KindJSDocTypeLiteral:
+ n := node.AsJSDocTypeLiteral()
+ return uint32(boolToByte(n.IsArrayType)) << 24
+ case ast.KindImportSpecifier:
+ n := node.AsImportSpecifier()
+ return uint32(boolToByte(n.IsTypeOnly)) << 24
+ case ast.KindImportClause:
+ n := node.AsImportClause()
+ return uint32(boolToByte(n.IsTypeOnly)) << 24
+ case ast.KindExportSpecifier:
+ n := node.AsExportSpecifier()
+ return uint32(boolToByte(n.IsTypeOnly)) << 24
+ case ast.KindImportType:
+ n := node.AsImportTypeNode()
+ return uint32(boolToByte(n.IsTypeOf)) << 24
+ case ast.KindImportEqualsDeclaration:
+ n := node.AsImportEqualsDeclaration()
+ return uint32(boolToByte(n.IsTypeOnly)) << 24
+ case ast.KindExportAssignment:
+ n := node.AsExportAssignment()
+ return uint32(boolToByte(n.IsExportEquals)) << 24
+ case ast.KindExportDeclaration:
+ n := node.AsExportDeclaration()
+ return uint32(boolToByte(n.IsTypeOnly)) << 24
+ case ast.KindBlock:
+ n := node.AsBlock()
+ return uint32(boolToByte(n.Multiline)) << 24
+ case ast.KindArrayLiteralExpression:
+ n := node.AsArrayLiteralExpression()
+ return uint32(boolToByte(n.MultiLine)) << 24
+ case ast.KindObjectLiteralExpression:
+ n := node.AsObjectLiteralExpression()
+ return uint32(boolToByte(n.MultiLine)) << 24
+ case ast.KindJSDocPropertyTag:
+ n := node.AsJSDocPropertyTag()
+ return uint32(boolToByte(n.IsBracketed))<<24 | uint32(boolToByte(n.IsNameFirst))<<25
+ case ast.KindJSDocParameterTag:
+ n := node.AsJSDocParameterTag()
+ return uint32(boolToByte(n.IsBracketed))<<24 | uint32(boolToByte(n.IsNameFirst))<<25
+ case ast.KindJsxText:
+ n := node.AsJsxText()
+ return uint32(boolToByte(n.ContainsOnlyTriviaWhiteSpaces)) << 24
+ case ast.KindVariableDeclarationList:
+ n := node.AsVariableDeclarationList()
+ return uint32(n.Flags & (ast.NodeFlagsLet | ast.NodeFlagsConst) << 24)
+ case ast.KindImportAttributes:
+ n := node.AsImportAttributes()
+ return uint32(boolToByte(n.MultiLine))<<24 | uint32(boolToByte(n.Token == ast.KindAssertKeyword))<<25
+ }
+ return 0
+}
+
+func recordNodeStrings(node *ast.Node, strs *stringTable) uint32 {
+ switch node.Kind {
+ case ast.KindJsxText:
+ return strs.add(node.AsJsxText().Text, node.Kind, node.Pos(), node.End())
+ case ast.KindIdentifier:
+ return strs.add(node.AsIdentifier().Text, node.Kind, node.Pos(), node.End())
+ case ast.KindPrivateIdentifier:
+ return strs.add(node.AsPrivateIdentifier().Text, node.Kind, node.Pos(), node.End())
+ case ast.KindStringLiteral:
+ return strs.add(node.AsStringLiteral().Text, node.Kind, node.Pos(), node.End())
+ case ast.KindNumericLiteral:
+ return strs.add(node.AsNumericLiteral().Text, node.Kind, node.Pos(), node.End())
+ case ast.KindBigIntLiteral:
+ return strs.add(node.AsBigIntLiteral().Text, node.Kind, node.Pos(), node.End())
+ case ast.KindRegularExpressionLiteral:
+ return strs.add(node.AsRegularExpressionLiteral().Text, node.Kind, node.Pos(), node.End())
+ case ast.KindNoSubstitutionTemplateLiteral:
+ return strs.add(node.AsNoSubstitutionTemplateLiteral().Text, node.Kind, node.Pos(), node.End())
+ case ast.KindJSDocText:
+ return strs.add(node.AsJSDocText().Text, node.Kind, node.Pos(), node.End())
+ default:
+ panic(fmt.Sprintf("Unexpected node kind %v", node.Kind))
+ }
+}
+
+func recordExtendedData(node *ast.Node, strs *stringTable, extendedData *[]byte) uint32 {
+ offset := uint32(len(*extendedData))
+ var text, rawText string
+ var templateFlags uint32
+ switch node.Kind {
+ case ast.KindTemplateTail:
+ n := node.AsTemplateTail()
+ text = n.Text
+ rawText = n.RawText
+ templateFlags = uint32(n.TemplateFlags)
+ case ast.KindTemplateMiddle:
+ n := node.AsTemplateMiddle()
+ text = n.Text
+ rawText = n.RawText
+ templateFlags = uint32(n.TemplateFlags)
+ case ast.KindTemplateHead:
+ n := node.AsTemplateHead()
+ text = n.Text
+ rawText = n.RawText
+ templateFlags = uint32(n.TemplateFlags)
+ }
+ textIndex := strs.add(text, node.Kind, node.Pos(), node.End())
+ rawTextIndex := strs.add(rawText, node.Kind, node.Pos(), node.End())
+ *extendedData = appendUint32s(*extendedData, textIndex, rawTextIndex, templateFlags)
+ return offset
+}
+
+func boolToByte(b bool) byte {
+ if b {
+ return 1
+ }
+ return 0
+}
diff --git a/internal/api/encoder/encoder_test.go b/internal/api/encoder/encoder_test.go
new file mode 100644
index 0000000000..ce616dfc26
--- /dev/null
+++ b/internal/api/encoder/encoder_test.go
@@ -0,0 +1,95 @@
+package encoder_test
+
+import (
+ "encoding/binary"
+ "fmt"
+ "os"
+ "path/filepath"
+ "strings"
+ "testing"
+
+ "github.com/microsoft/typescript-go/internal/api/encoder"
+ "github.com/microsoft/typescript-go/internal/ast"
+ "github.com/microsoft/typescript-go/internal/core"
+ "github.com/microsoft/typescript-go/internal/parser"
+ "github.com/microsoft/typescript-go/internal/repo"
+ "github.com/microsoft/typescript-go/internal/scanner"
+ "github.com/microsoft/typescript-go/internal/testutil/baseline"
+ "gotest.tools/v3/assert"
+)
+
+func TestEncodeSourceFile(t *testing.T) {
+ t.Parallel()
+ sourceFile := parser.ParseSourceFile("/test.ts", "/test.ts", "import { bar } from \"bar\";\nexport function foo(a: string, b: string): any {}\nfoo();", core.ScriptTargetESNext, scanner.JSDocParsingModeParseAll)
+ t.Run("baseline", func(t *testing.T) {
+ t.Parallel()
+ buf, err := encoder.EncodeSourceFile(sourceFile, "")
+ assert.NilError(t, err)
+
+ str := formatEncodedSourceFile(buf)
+ baseline.Run(t, "encodeSourceFile.txt", str, baseline.Options{
+ Subfolder: "api",
+ })
+ })
+}
+
+func BenchmarkEncodeSourceFile(b *testing.B) {
+ repo.SkipIfNoTypeScriptSubmodule(b)
+ filePath := filepath.Join(repo.TypeScriptSubmodulePath, "src/compiler/checker.ts")
+ fileContent, err := os.ReadFile(filePath)
+ assert.NilError(b, err)
+ sourceFile := parser.ParseSourceFile(
+ "/checker.ts",
+ "/checker.ts",
+ string(fileContent),
+ core.ScriptTargetESNext,
+ scanner.JSDocParsingModeParseAll,
+ )
+
+ for b.Loop() {
+ _, err := encoder.EncodeSourceFile(sourceFile, "")
+ assert.NilError(b, err)
+ }
+}
+
+func readUint32(buf []byte, offset int) uint32 {
+ return binary.LittleEndian.Uint32(buf[offset : offset+4])
+}
+
+func formatEncodedSourceFile(encoded []byte) string {
+ var result strings.Builder
+ var getIndent func(parentIndex uint32) string
+ offsetNodes := readUint32(encoded, encoder.HeaderOffsetNodes)
+ offsetStringOffsets := readUint32(encoded, encoder.HeaderOffsetStringOffsets)
+ offsetStrings := readUint32(encoded, encoder.HeaderOffsetStringData)
+ getIndent = func(parentIndex uint32) string {
+ if parentIndex == 0 {
+ return ""
+ }
+ return " " + getIndent(readUint32(encoded, int(offsetNodes)+int(parentIndex)*encoder.NodeSize+encoder.NodeOffsetParent))
+ }
+ j := 1
+ for i := int(offsetNodes) + encoder.NodeSize; i < len(encoded); i += encoder.NodeSize {
+ kind := readUint32(encoded, i+encoder.NodeOffsetKind)
+ pos := readUint32(encoded, i+encoder.NodeOffsetPos)
+ end := readUint32(encoded, i+encoder.NodeOffsetEnd)
+ parentIndex := readUint32(encoded, i+encoder.NodeOffsetParent)
+ result.WriteString(getIndent(parentIndex))
+ if kind == encoder.SyntaxKindNodeList {
+ result.WriteString("NodeList")
+ } else {
+ result.WriteString(ast.Kind(kind).String())
+ }
+ if ast.Kind(kind) == ast.KindIdentifier || ast.Kind(kind) == ast.KindStringLiteral {
+ stringIndex := readUint32(encoded, i+encoder.NodeOffsetData) & encoder.NodeDataStringIndexMask
+ strStart := readUint32(encoded, int(offsetStringOffsets+stringIndex*4))
+ strEnd := readUint32(encoded, int(offsetStringOffsets+stringIndex*4)+4)
+ str := string(encoded[offsetStrings+strStart : offsetStrings+strEnd])
+ result.WriteString(fmt.Sprintf(" \"%s\"", str))
+ }
+ fmt.Fprintf(&result, " [%d, %d), i=%d, next=%d", pos, end, j, encoded[i+encoder.NodeOffsetNext])
+ result.WriteString("\n")
+ j++
+ }
+ return result.String()
+}
diff --git a/internal/api/encoder/stringtable.go b/internal/api/encoder/stringtable.go
new file mode 100644
index 0000000000..098015d87a
--- /dev/null
+++ b/internal/api/encoder/stringtable.go
@@ -0,0 +1,68 @@
+package encoder
+
+import (
+ "strings"
+
+ "github.com/microsoft/typescript-go/internal/ast"
+)
+
+type stringTable struct {
+ fileText string
+ otherStrings *strings.Builder
+ // offsets are pos/end pairs
+ offsets []uint32
+}
+
+func newStringTable(fileText string, stringCount int) *stringTable {
+ builder := &strings.Builder{}
+ return &stringTable{
+ fileText: fileText,
+ otherStrings: builder,
+ offsets: make([]uint32, 0, stringCount*2),
+ }
+}
+
+func (t *stringTable) add(text string, kind ast.Kind, pos int, end int) uint32 {
+ index := uint32(len(t.offsets))
+ if kind == ast.KindSourceFile {
+ t.offsets = append(t.offsets, uint32(pos), uint32(end))
+ return index
+ }
+ length := len(text)
+ if end-pos > 0 {
+ // pos includes leading trivia, but we can usually infer the actual start of the
+ // string from the kind and end
+ endOffset := 0
+ if kind == ast.KindStringLiteral || kind == ast.KindTemplateTail || kind == ast.KindNoSubstitutionTemplateLiteral {
+ endOffset = 1
+ }
+ end = end - endOffset
+ start := end - length
+ fileSlice := t.fileText[start:end]
+ if fileSlice == text {
+ t.offsets = append(t.offsets, uint32(start), uint32(end))
+ return index
+ }
+ }
+ // no exact match, so we need to add it to the string table
+ offset := len(t.fileText) + t.otherStrings.Len()
+ t.otherStrings.WriteString(text)
+ t.offsets = append(t.offsets, uint32(offset), uint32(offset+length))
+ return index
+}
+
+func (t *stringTable) encode() []byte {
+ result := make([]byte, 0, t.encodedLength())
+ result = appendUint32s(result, t.offsets...)
+ result = append(result, t.fileText...)
+ result = append(result, t.otherStrings.String()...)
+ return result
+}
+
+func (t *stringTable) stringLength() int {
+ return len(t.fileText) + t.otherStrings.Len()
+}
+
+func (t *stringTable) encodedLength() int {
+ return len(t.offsets)*4 + len(t.fileText) + t.otherStrings.Len()
+}
diff --git a/internal/api/host.go b/internal/api/host.go
new file mode 100644
index 0000000000..83d45a8c60
--- /dev/null
+++ b/internal/api/host.go
@@ -0,0 +1,10 @@
+package api
+
+import "github.com/microsoft/typescript-go/internal/vfs"
+
+type APIHost interface {
+ FS() vfs.FS
+ DefaultLibraryPath() string
+ GetCurrentDirectory() string
+ NewLine() string
+}
diff --git a/internal/api/proto.go b/internal/api/proto.go
new file mode 100644
index 0000000000..e50684783f
--- /dev/null
+++ b/internal/api/proto.go
@@ -0,0 +1,217 @@
+package api
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "strconv"
+ "strings"
+
+ "github.com/microsoft/typescript-go/internal/ast"
+ "github.com/microsoft/typescript-go/internal/checker"
+ "github.com/microsoft/typescript-go/internal/core"
+ "github.com/microsoft/typescript-go/internal/project"
+)
+
+var (
+ ErrInvalidRequest = errors.New("api: invalid request")
+ ErrClientError = errors.New("api: client error")
+)
+
+type Method string
+
+type Handle[T any] string
+
+const (
+ handlePrefixProject = 'p'
+ handlePrefixSymbol = 's'
+ handlePrefixType = 't'
+ handlePrefixFile = 'f'
+ handlePrefixNode = 'n'
+)
+
+func ProjectHandle(p *project.Project) Handle[project.Project] {
+ return createHandle[project.Project](handlePrefixProject, p.Name())
+}
+
+func SymbolHandle(symbol *ast.Symbol) Handle[ast.Symbol] {
+ return createHandle[ast.Symbol](handlePrefixSymbol, ast.GetSymbolId(symbol))
+}
+
+func TypeHandle(t *checker.Type) Handle[checker.Type] {
+ return createHandle[checker.Type](handlePrefixType, t.Id())
+}
+
+func FileHandle(file *ast.SourceFile) Handle[ast.SourceFile] {
+ return createHandle[ast.SourceFile](handlePrefixFile, ast.GetNodeId(file.AsNode()))
+}
+
+func NodeHandle(node *ast.Node) Handle[ast.Node] {
+ fileHandle := FileHandle(ast.GetSourceFileOfNode(node))
+ return Handle[ast.Node](fmt.Sprintf("%s.%d.%d", fileHandle, node.Pos(), node.Kind))
+}
+
+func parseNodeHandle(handle Handle[ast.Node]) (Handle[ast.SourceFile], int, ast.Kind, error) {
+ parts := strings.SplitN(string(handle), ".", 3)
+ if len(parts) != 3 {
+ return "", 0, 0, fmt.Errorf("invalid node handle %q", handle)
+ }
+
+ fileHandle := Handle[ast.SourceFile](parts[0])
+ pos, err := strconv.ParseInt(parts[1], 10, 32)
+ if err != nil {
+ return "", 0, 0, fmt.Errorf("invalid node handle %q: %w", handle, err)
+ }
+ kind, err := strconv.ParseInt(parts[2], 10, 16)
+ if err != nil {
+ return "", 0, 0, fmt.Errorf("invalid node handle %q: %w", handle, err)
+ }
+ return fileHandle, int(pos), ast.Kind(kind), nil
+}
+
+func createHandle[T any](prefix rune, id any) Handle[T] {
+ return Handle[T](fmt.Sprintf("%c%016x", prefix, id))
+}
+
+const (
+ MethodConfigure Method = "configure"
+ MethodRelease Method = "release"
+
+ MethodParseConfigFile Method = "parseConfigFile"
+ MethodLoadProject Method = "loadProject"
+ MethodGetSymbolAtPosition Method = "getSymbolAtPosition"
+ MethodGetSymbolsAtPositions Method = "getSymbolsAtPositions"
+ MethodGetSymbolAtLocation Method = "getSymbolAtLocation"
+ MethodGetSymbolsAtLocations Method = "getSymbolsAtLocations"
+ MethodGetTypeOfSymbol Method = "getTypeOfSymbol"
+ MethodGetTypesOfSymbols Method = "getTypesOfSymbols"
+ MethodGetSourceFile Method = "getSourceFile"
+)
+
+var unmarshalers = map[Method]func([]byte) (any, error){
+ MethodRelease: unmarshallerFor[string],
+ MethodParseConfigFile: unmarshallerFor[ParseConfigFileParams],
+ MethodLoadProject: unmarshallerFor[LoadProjectParams],
+ MethodGetSourceFile: unmarshallerFor[GetSourceFileParams],
+ MethodGetSymbolAtPosition: unmarshallerFor[GetSymbolAtPositionParams],
+ MethodGetSymbolsAtPositions: unmarshallerFor[GetSymbolsAtPositionsParams],
+ MethodGetSymbolAtLocation: unmarshallerFor[GetSymbolAtLocationParams],
+ MethodGetSymbolsAtLocations: unmarshallerFor[GetSymbolsAtLocationsParams],
+ MethodGetTypeOfSymbol: unmarshallerFor[GetTypeOfSymbolParams],
+ MethodGetTypesOfSymbols: unmarshallerFor[GetTypesOfSymbolsParams],
+}
+
+type ConfigureParams struct {
+ Callbacks []string `json:"callbacks"`
+ LogFile string `json:"logFile"`
+}
+
+type ParseConfigFileParams struct {
+ FileName string `json:"fileName"`
+}
+
+type ConfigFileResponse struct {
+ FileNames []string `json:"fileNames"`
+ Options *core.CompilerOptions `json:"options"`
+}
+
+type LoadProjectParams struct {
+ ConfigFileName string `json:"configFileName"`
+}
+
+type ProjectResponse struct {
+ Id Handle[project.Project] `json:"id"`
+ ConfigFileName string `json:"configFileName"`
+ RootFiles []string `json:"rootFiles"`
+ CompilerOptions *core.CompilerOptions `json:"compilerOptions"`
+}
+
+func NewProjectResponse(project *project.Project) *ProjectResponse {
+ return &ProjectResponse{
+ Id: ProjectHandle(project),
+ ConfigFileName: project.Name(),
+ RootFiles: project.GetRootFileNames(),
+ CompilerOptions: project.GetCompilerOptions(),
+ }
+}
+
+type GetSymbolAtPositionParams struct {
+ Project Handle[project.Project] `json:"project"`
+ FileName string `json:"fileName"`
+ Position uint32 `json:"position"`
+}
+
+type GetSymbolsAtPositionsParams struct {
+ Project Handle[project.Project] `json:"project"`
+ FileName string `json:"fileName"`
+ Positions []uint32 `json:"positions"`
+}
+
+type GetSymbolAtLocationParams struct {
+ Project Handle[project.Project] `json:"project"`
+ Location Handle[ast.Node] `json:"location"`
+}
+
+type GetSymbolsAtLocationsParams struct {
+ Project Handle[project.Project] `json:"project"`
+ Locations []Handle[ast.Node] `json:"locations"`
+}
+
+type SymbolResponse struct {
+ Id Handle[ast.Symbol] `json:"id"`
+ Name string `json:"name"`
+ Flags uint32 `json:"flags"`
+ CheckFlags uint32 `json:"checkFlags"`
+}
+
+func NewSymbolResponse(symbol *ast.Symbol) *SymbolResponse {
+ return &SymbolResponse{
+ Id: SymbolHandle(symbol),
+ Name: symbol.Name,
+ Flags: uint32(symbol.Flags),
+ CheckFlags: uint32(symbol.CheckFlags),
+ }
+}
+
+type GetTypeOfSymbolParams struct {
+ Project Handle[project.Project] `json:"project"`
+ Symbol Handle[ast.Symbol] `json:"symbol"`
+}
+
+type GetTypesOfSymbolsParams struct {
+ Project Handle[project.Project] `json:"project"`
+ Symbols []Handle[ast.Symbol] `json:"symbols"`
+}
+
+type TypeResponse struct {
+ Id Handle[checker.Type] `json:"id"`
+ Flags uint32 `json:"flags"`
+}
+
+func NewTypeData(t *checker.Type) *TypeResponse {
+ return &TypeResponse{
+ Id: TypeHandle(t),
+ Flags: uint32(t.Flags()),
+ }
+}
+
+type GetSourceFileParams struct {
+ Project Handle[project.Project] `json:"project"`
+ FileName string `json:"fileName"`
+}
+
+func unmarshalPayload(method string, payload json.RawMessage) (any, error) {
+ unmarshaler, ok := unmarshalers[Method(method)]
+ if !ok {
+ return nil, fmt.Errorf("unknown API method %q", method)
+ }
+ return unmarshaler(payload)
+}
+
+func unmarshallerFor[T any](data []byte) (any, error) {
+ var v T
+ if err := json.Unmarshal(data, &v); err != nil {
+ return nil, fmt.Errorf("failed to unmarshal %T: %w", (*T)(nil), err)
+ }
+ return &v, nil
+}
diff --git a/internal/api/server.go b/internal/api/server.go
new file mode 100644
index 0000000000..2b60dd855a
--- /dev/null
+++ b/internal/api/server.go
@@ -0,0 +1,477 @@
+package api
+
+import (
+ "bufio"
+ "encoding/binary"
+ "encoding/json"
+ "fmt"
+ "io"
+ "sync"
+
+ "github.com/microsoft/typescript-go/internal/bundled"
+ "github.com/microsoft/typescript-go/internal/project"
+ "github.com/microsoft/typescript-go/internal/vfs"
+ "github.com/microsoft/typescript-go/internal/vfs/osvfs"
+)
+
+//go:generate go tool golang.org/x/tools/cmd/stringer -type=MessageType -output=stringer_generated.go
+
+type MessageType uint8
+
+const (
+ MessageTypeUnknown MessageType = iota
+ MessageTypeRequest
+ MessageTypeCallResponse
+ MessageTypeCallError
+ MessageTypeResponse
+ MessageTypeError
+ MessageTypeCall
+)
+
+func (m MessageType) IsValid() bool {
+ return m >= MessageTypeRequest && m <= MessageTypeCall
+}
+
+type MessagePackType uint8
+
+const (
+ MessagePackTypeFixedArray3 MessagePackType = 0x93
+ MessagePackTypeBin8 MessagePackType = 0xC4
+ MessagePackTypeBin16 MessagePackType = 0xC5
+ MessagePackTypeBin32 MessagePackType = 0xC6
+ MessagePackTypeU8 MessagePackType = 0xCC
+)
+
+type Callback int
+
+const (
+ CallbackDirectoryExists Callback = 1 << iota
+ CallbackFileExists
+ CallbackGetAccessibleEntries
+ CallbackReadFile
+ CallbackRealpath
+)
+
+type ServerOptions struct {
+ In io.Reader
+ Out io.Writer
+ Err io.Writer
+ Cwd string
+ NewLine string
+ DefaultLibraryPath string
+}
+
+var (
+ _ APIHost = (*Server)(nil)
+ _ vfs.FS = (*Server)(nil)
+)
+
+type Server struct {
+ r *bufio.Reader
+ w *bufio.Writer
+ stderr io.Writer
+
+ cwd string
+ newLine string
+ fs vfs.FS
+ defaultLibraryPath string
+
+ callbackMu sync.Mutex
+ enabledCallbacks Callback
+ logger *project.Logger
+ api *API
+
+ requestId int
+}
+
+func NewServer(options *ServerOptions) *Server {
+ if options.Cwd == "" {
+ panic("Cwd is required")
+ }
+
+ server := &Server{
+ r: bufio.NewReader(options.In),
+ w: bufio.NewWriter(options.Out),
+ stderr: options.Err,
+ cwd: options.Cwd,
+ newLine: options.NewLine,
+ fs: bundled.WrapFS(osvfs.FS()),
+ defaultLibraryPath: options.DefaultLibraryPath,
+ }
+ logger := project.NewLogger([]io.Writer{options.Err}, "", project.LogLevelVerbose)
+ api := NewAPI(server, APIOptions{
+ Logger: logger,
+ })
+ server.logger = logger
+ server.api = api
+ return server
+}
+
+// DefaultLibraryPath implements APIHost.
+func (s *Server) DefaultLibraryPath() string {
+ return s.defaultLibraryPath
+}
+
+// FS implements APIHost.
+func (s *Server) FS() vfs.FS {
+ return s
+}
+
+// GetCurrentDirectory implements APIHost.
+func (s *Server) GetCurrentDirectory() string {
+ return s.cwd
+}
+
+// NewLine implements APIHost.
+func (s *Server) NewLine() string {
+ return s.newLine
+}
+
+func (s *Server) Run() error {
+ for {
+ messageType, method, payload, err := s.readRequest("")
+ if err != nil {
+ return err
+ }
+
+ switch messageType {
+ case MessageTypeRequest:
+ result, err := s.handleRequest(method, payload)
+
+ if err != nil {
+ if err := s.sendError(method, err); err != nil {
+ return err
+ }
+ } else {
+ if err := s.sendResponse(method, result); err != nil {
+ return err
+ }
+ }
+ default:
+ return fmt.Errorf("%w: expected request, received: %s", ErrInvalidRequest, messageType.String())
+ }
+ }
+}
+
+func (s *Server) readRequest(expectedMethod string) (messageType MessageType, method string, payload []byte, err error) {
+ t, err := s.r.ReadByte()
+ if err != nil {
+ return messageType, method, payload, err
+ }
+ if MessagePackType(t) != MessagePackTypeFixedArray3 {
+ return messageType, method, payload, fmt.Errorf("%w: expected message to be encoded as fixed 3-element array (0x93), received: 0x%2x", ErrInvalidRequest, t)
+ }
+ t, err = s.r.ReadByte()
+ if err != nil {
+ return messageType, method, payload, err
+ }
+ if MessagePackType(t) != MessagePackTypeU8 {
+ return messageType, method, payload, fmt.Errorf("%w: expected first element of message tuple to be encoded as unsigned 8-bit int (0xcc), received: 0x%2x", ErrInvalidRequest, t)
+ }
+ rawMessageType, err := s.r.ReadByte()
+ if err != nil {
+ return messageType, method, payload, err
+ }
+ messageType = MessageType(rawMessageType)
+ if !messageType.IsValid() {
+ return messageType, method, payload, fmt.Errorf("%w: unknown message type: %d", ErrInvalidRequest, messageType)
+ }
+ rawMethod, err := s.readBin()
+ if err != nil {
+ return messageType, method, payload, err
+ }
+ method = string(rawMethod)
+ if expectedMethod != "" && method != expectedMethod {
+ return messageType, method, payload, fmt.Errorf("%w: expected method %q, received %q", ErrInvalidRequest, expectedMethod, method)
+ }
+ payload, err = s.readBin()
+ return messageType, method, payload, err
+}
+
+func (s *Server) readBin() ([]byte, error) {
+ // https://github.com/msgpack/msgpack/blob/master/spec.md#bin-format-family
+ t, err := s.r.ReadByte()
+ if err != nil {
+ return nil, err
+ }
+ var size uint
+ switch MessagePackType(t) {
+ case MessagePackTypeBin8:
+ var size8 uint8
+ if err = binary.Read(s.r, binary.BigEndian, &size8); err != nil {
+ return nil, err
+ }
+ size = uint(size8)
+ case MessagePackTypeBin16:
+ var size16 uint16
+ if err = binary.Read(s.r, binary.BigEndian, &size16); err != nil {
+ return nil, err
+ }
+ size = uint(size16)
+ case MessagePackTypeBin32:
+ var size32 uint32
+ if err = binary.Read(s.r, binary.BigEndian, &size32); err != nil {
+ return nil, err
+ }
+ size = uint(size32)
+ default:
+ return nil, fmt.Errorf("%w: expected binary data length (0xc4-0xc6), received: 0x%2x", ErrInvalidRequest, t)
+ }
+ payload := make([]byte, size)
+ bytesRead, err := io.ReadFull(s.r, payload)
+ if err != nil {
+ return nil, err
+ }
+ if bytesRead != int(size) {
+ return nil, fmt.Errorf("%w: expected %d bytes, read %d", ErrInvalidRequest, size, bytesRead)
+ }
+ return payload, nil
+}
+
+func (s *Server) enableCallback(callback string) error {
+ switch callback {
+ case "directoryExists":
+ s.enabledCallbacks |= CallbackDirectoryExists
+ case "fileExists":
+ s.enabledCallbacks |= CallbackFileExists
+ case "getAccessibleEntries":
+ s.enabledCallbacks |= CallbackGetAccessibleEntries
+ case "readFile":
+ s.enabledCallbacks |= CallbackReadFile
+ case "realpath":
+ s.enabledCallbacks |= CallbackRealpath
+ default:
+ return fmt.Errorf("unknown callback: %s", callback)
+ }
+ return nil
+}
+
+func (s *Server) handleRequest(method string, payload []byte) ([]byte, error) {
+ s.requestId++
+ switch method {
+ case "configure":
+ return nil, s.handleConfigure(payload)
+ case "echo":
+ return payload, nil
+ default:
+ return s.api.HandleRequest(s.requestId, method, payload)
+ }
+}
+
+func (s *Server) handleConfigure(payload []byte) error {
+ var params *ConfigureParams
+ if err := json.Unmarshal(payload, ¶ms); err != nil {
+ return fmt.Errorf("%w: %w", ErrInvalidRequest, err)
+ }
+ for _, callback := range params.Callbacks {
+ if err := s.enableCallback(callback); err != nil {
+ return err
+ }
+ }
+ if params.LogFile != "" {
+ s.logger.SetFile(params.LogFile)
+ } else {
+ s.logger.SetFile("")
+ }
+ return nil
+}
+
+func (s *Server) sendResponse(method string, result []byte) error {
+ return s.writeMessage(MessageTypeResponse, method, result)
+}
+
+func (s *Server) sendError(method string, err error) error {
+ return s.writeMessage(MessageTypeError, method, []byte(err.Error()))
+}
+
+func (s *Server) writeMessage(messageType MessageType, method string, payload []byte) error {
+ if err := s.w.WriteByte(byte(MessagePackTypeFixedArray3)); err != nil {
+ return err
+ }
+ if err := s.w.WriteByte(byte(MessagePackTypeU8)); err != nil {
+ return err
+ }
+ if err := s.w.WriteByte(byte(messageType)); err != nil {
+ return err
+ }
+ if err := s.writeBin([]byte(method)); err != nil {
+ return err
+ }
+ if err := s.writeBin(payload); err != nil {
+ return err
+ }
+ return s.w.Flush()
+}
+
+func (s *Server) writeBin(payload []byte) error {
+ length := len(payload)
+ if length < 256 {
+ if err := s.w.WriteByte(byte(MessagePackTypeBin8)); err != nil {
+ return err
+ }
+ if err := s.w.WriteByte(byte(length)); err != nil {
+ return err
+ }
+ } else if length < 1<<16 {
+ if err := s.w.WriteByte(byte(MessagePackTypeBin16)); err != nil {
+ return err
+ }
+ if err := binary.Write(s.w, binary.BigEndian, uint16(length)); err != nil {
+ return err
+ }
+ } else {
+ if err := s.w.WriteByte(byte(MessagePackTypeBin32)); err != nil {
+ return err
+ }
+ if err := binary.Write(s.w, binary.BigEndian, uint32(length)); err != nil {
+ return err
+ }
+ }
+ _, err := s.w.Write(payload)
+ return err
+}
+
+func (s *Server) call(method string, payload any) ([]byte, error) {
+ s.callbackMu.Lock()
+ defer s.callbackMu.Unlock()
+ jsonPayload, err := json.Marshal(payload)
+ if err != nil {
+ return nil, err
+ }
+ if err = s.writeMessage(MessageTypeCall, method, jsonPayload); err != nil {
+ return nil, err
+ }
+
+ messageType, _, responsePayload, err := s.readRequest(method)
+ if err != nil {
+ return nil, err
+ }
+
+ if messageType != MessageTypeCallResponse && messageType != MessageTypeCallError {
+ return nil, fmt.Errorf("%w: expected call-response or call-error, received: %s", ErrInvalidRequest, messageType.String())
+ }
+
+ if messageType == MessageTypeCallError {
+ return nil, fmt.Errorf("%w: %s", ErrClientError, responsePayload)
+ }
+
+ return responsePayload, nil
+}
+
+// DirectoryExists implements vfs.FS.
+func (s *Server) DirectoryExists(path string) bool {
+ if s.enabledCallbacks&CallbackDirectoryExists != 0 {
+ result, err := s.call("directoryExists", path)
+ if err != nil {
+ panic(err)
+ }
+ if len(result) > 0 {
+ return string(result) == "true"
+ }
+ }
+ return s.fs.DirectoryExists(path)
+}
+
+// FileExists implements vfs.FS.
+func (s *Server) FileExists(path string) bool {
+ if s.enabledCallbacks&CallbackFileExists != 0 {
+ result, err := s.call("fileExists", path)
+ if err != nil {
+ panic(err)
+ }
+ if len(result) > 0 {
+ return string(result) == "true"
+ }
+ }
+ return s.fs.FileExists(path)
+}
+
+// GetAccessibleEntries implements vfs.FS.
+func (s *Server) GetAccessibleEntries(path string) vfs.Entries {
+ if s.enabledCallbacks&CallbackGetAccessibleEntries != 0 {
+ result, err := s.call("getAccessibleEntries", path)
+ if err != nil {
+ panic(err)
+ }
+ if len(result) > 0 {
+ var rawEntries *struct {
+ Files []string `json:"files"`
+ Directories []string `json:"directories"`
+ }
+ if err := json.Unmarshal(result, &rawEntries); err != nil {
+ panic(err)
+ }
+ if rawEntries != nil {
+ return vfs.Entries{
+ Files: rawEntries.Files,
+ Directories: rawEntries.Directories,
+ }
+ }
+ }
+ }
+ return s.fs.GetAccessibleEntries(path)
+}
+
+// ReadFile implements vfs.FS.
+func (s *Server) ReadFile(path string) (contents string, ok bool) {
+ if s.enabledCallbacks&CallbackReadFile != 0 {
+ data, err := s.call("readFile", path)
+ if err != nil {
+ panic(err)
+ }
+ if string(data) == "null" {
+ return "", false
+ }
+ if len(data) > 0 {
+ var result string
+ if err := json.Unmarshal(data, &result); err != nil {
+ panic(err)
+ }
+ return result, true
+ }
+ }
+ return s.fs.ReadFile(path)
+}
+
+// Realpath implements vfs.FS.
+func (s *Server) Realpath(path string) string {
+ if s.enabledCallbacks&CallbackRealpath != 0 {
+ data, err := s.call("realpath", path)
+ if err != nil {
+ panic(err)
+ }
+ if len(data) > 0 {
+ var result string
+ if err := json.Unmarshal(data, &result); err != nil {
+ panic(err)
+ }
+ return result
+ }
+ }
+ return s.fs.Realpath(path)
+}
+
+// UseCaseSensitiveFileNames implements vfs.FS.
+func (s *Server) UseCaseSensitiveFileNames() bool {
+ return s.fs.UseCaseSensitiveFileNames()
+}
+
+// WriteFile implements vfs.FS.
+func (s *Server) WriteFile(path string, data string, writeByteOrderMark bool) error {
+ return s.fs.WriteFile(path, data, writeByteOrderMark)
+}
+
+// WalkDir implements vfs.FS.
+func (s *Server) WalkDir(root string, walkFn vfs.WalkDirFunc) error {
+ panic("unimplemented")
+}
+
+// Stat implements vfs.FS.
+func (s *Server) Stat(path string) vfs.FileInfo {
+ panic("unimplemented")
+}
+
+// Remove implements vfs.FS.
+func (s *Server) Remove(path string) error {
+ panic("unimplemented")
+}
diff --git a/internal/api/stringer_generated.go b/internal/api/stringer_generated.go
new file mode 100644
index 0000000000..0a740d353b
--- /dev/null
+++ b/internal/api/stringer_generated.go
@@ -0,0 +1,29 @@
+// Code generated by "stringer -type=MessageType -output=stringer_generated.go"; DO NOT EDIT.
+
+package api
+
+import "strconv"
+
+func _() {
+ // An "invalid array index" compiler error signifies that the constant values have changed.
+ // Re-run the stringer command to generate them again.
+ var x [1]struct{}
+ _ = x[MessageTypeUnknown-0]
+ _ = x[MessageTypeRequest-1]
+ _ = x[MessageTypeCallResponse-2]
+ _ = x[MessageTypeCallError-3]
+ _ = x[MessageTypeResponse-4]
+ _ = x[MessageTypeError-5]
+ _ = x[MessageTypeCall-6]
+}
+
+const _MessageType_name = "MessageTypeUnknownMessageTypeRequestMessageTypeCallResponseMessageTypeCallErrorMessageTypeResponseMessageTypeErrorMessageTypeCall"
+
+var _MessageType_index = [...]uint8{0, 18, 36, 59, 79, 98, 114, 129}
+
+func (i MessageType) String() string {
+ if i >= MessageType(len(_MessageType_index)-1) {
+ return "MessageType(" + strconv.FormatInt(int64(i), 10) + ")"
+ }
+ return _MessageType_name[_MessageType_index[i]:_MessageType_index[i+1]]
+}
diff --git a/internal/ast/ast.go b/internal/ast/ast.go
index 7d77dbff0b..7a4a04f01f 100644
--- a/internal/ast/ast.go
+++ b/internal/ast/ast.go
@@ -72,6 +72,9 @@ type NodeFactory struct {
variableDeclarationListPool core.Pool[VariableDeclarationList]
variableDeclarationPool core.Pool[VariableDeclaration]
variableStatementPool core.Pool[VariableStatement]
+
+ nodeCount int
+ textCount int
}
type NodeFactoryHooks struct {
@@ -95,6 +98,19 @@ func newNode(kind Kind, data nodeData, hooks NodeFactoryHooks) *Node {
return n
}
+func (f *NodeFactory) newNode(kind Kind, data nodeData) *Node {
+ f.nodeCount++
+ return newNode(kind, data, f.hooks)
+}
+
+func (f *NodeFactory) NodeCount() int {
+ return f.nodeCount
+}
+
+func (f *NodeFactory) TextCount() int {
+ return f.textCount
+}
+
func updateNode(updated *Node, original *Node, hooks NodeFactoryHooks) *Node {
if updated != original {
updated.Loc = original.Loc
@@ -1843,7 +1859,7 @@ type Token struct {
}
func (f *NodeFactory) NewToken(kind Kind) *Node {
- return newNode(kind, f.tokenPool.New(), f.hooks)
+ return f.newNode(kind, f.tokenPool.New())
}
func (node *Token) Clone(f *NodeFactory) *Node {
@@ -1902,7 +1918,8 @@ type Identifier struct {
func (f *NodeFactory) NewIdentifier(text string) *Node {
data := f.identifierPool.New()
data.Text = text
- return newNode(KindIdentifier, data, f.hooks)
+ f.textCount++
+ return f.newNode(KindIdentifier, data)
}
func (node *Identifier) Clone(f *NodeFactory) *Node {
@@ -1927,7 +1944,8 @@ type PrivateIdentifier struct {
func (f *NodeFactory) NewPrivateIdentifier(text string) *Node {
data := &PrivateIdentifier{}
data.Text = text
- return newNode(KindPrivateIdentifier, data, f.hooks)
+ f.textCount++
+ return f.newNode(KindPrivateIdentifier, data)
}
func (node *PrivateIdentifier) Clone(f *NodeFactory) *Node {
@@ -1956,7 +1974,7 @@ func (f *NodeFactory) NewQualifiedName(left *EntityName, right *IdentifierNode)
data := &QualifiedName{}
data.Left = left
data.Right = right
- return newNode(KindQualifiedName, data, f.hooks)
+ return f.newNode(KindQualifiedName, data)
}
func (f *NodeFactory) UpdateQualifiedName(node *QualifiedName, left *EntityName, right *IdentifierNode) *Node {
@@ -2006,7 +2024,7 @@ func (f *NodeFactory) NewTypeParameterDeclaration(modifiers *ModifierList, name
data.name = name
data.Constraint = constraint
data.DefaultType = defaultType
- return newNode(KindTypeParameter, data, f.hooks)
+ return f.newNode(KindTypeParameter, data)
}
func (f *NodeFactory) UpdateTypeParameterDeclaration(node *TypeParameterDeclaration, modifiers *ModifierList, name *IdentifierNode, constraint *TypeNode, defaultType *TypeNode) *Node {
@@ -2047,7 +2065,7 @@ type ComputedPropertyName struct {
func (f *NodeFactory) NewComputedPropertyName(expression *Expression) *Node {
data := &ComputedPropertyName{}
data.Expression = expression
- return newNode(KindComputedPropertyName, data, f.hooks)
+ return f.newNode(KindComputedPropertyName, data)
}
func (f *NodeFactory) UpdateComputedPropertyName(node *ComputedPropertyName, expression *Expression) *Node {
@@ -2094,7 +2112,7 @@ type Decorator struct {
func (f *NodeFactory) NewDecorator(expression *LeftHandSideExpression) *Node {
data := &Decorator{}
data.Expression = expression
- return newNode(KindDecorator, data, f.hooks)
+ return f.newNode(KindDecorator, data)
}
func (f *NodeFactory) UpdateDecorator(node *Decorator, expression *Expression) *Node {
@@ -2140,7 +2158,7 @@ type EmptyStatement struct {
}
func (f *NodeFactory) NewEmptyStatement() *Node {
- return newNode(KindEmptyStatement, &EmptyStatement{}, f.hooks)
+ return f.newNode(KindEmptyStatement, &EmptyStatement{})
}
func (node *EmptyStatement) Clone(f *NodeFactory) *Node {
@@ -2166,7 +2184,7 @@ func (f *NodeFactory) NewIfStatement(expression *Expression, thenStatement *Stat
data.Expression = expression
data.ThenStatement = thenStatement
data.ElseStatement = elseStatement
- return newNode(KindIfStatement, data, f.hooks)
+ return f.newNode(KindIfStatement, data)
}
func (f *NodeFactory) UpdateIfStatement(node *IfStatement, expression *Expression, thenStatement *Statement, elseStatement *Statement) *Node {
@@ -2211,7 +2229,7 @@ func (f *NodeFactory) NewDoStatement(statement *Statement, expression *Expressio
data := &DoStatement{}
data.Statement = statement
data.Expression = expression
- return newNode(KindDoStatement, data, f.hooks)
+ return f.newNode(KindDoStatement, data)
}
func (f *NodeFactory) UpdateDoStatement(node *DoStatement, statement *Statement, expression *Expression) *Node {
@@ -2251,7 +2269,7 @@ func (f *NodeFactory) NewWhileStatement(expression *Expression, statement *State
data := &WhileStatement{}
data.Expression = expression
data.Statement = statement
- return newNode(KindWhileStatement, data, f.hooks)
+ return f.newNode(KindWhileStatement, data)
}
func (f *NodeFactory) UpdateWhileStatement(node *WhileStatement, expression *Expression, statement *Statement) *Node {
@@ -2295,7 +2313,7 @@ func (f *NodeFactory) NewForStatement(initializer *ForInitializer, condition *Ex
data.Condition = condition
data.Incrementor = incrementor
data.Statement = statement
- return newNode(KindForStatement, data, f.hooks)
+ return f.newNode(KindForStatement, data)
}
func (f *NodeFactory) UpdateForStatement(node *ForStatement, initializer *ForInitializer, condition *Expression, incrementor *Expression, statement *Statement) *Node {
@@ -2346,7 +2364,7 @@ func (f *NodeFactory) NewForInOrOfStatement(kind Kind, awaitModifier *TokenNode,
data.Initializer = initializer
data.Expression = expression
data.Statement = statement
- return newNode(kind, data, f.hooks)
+ return f.newNode(kind, data)
}
func (f *NodeFactory) UpdateForInOrOfStatement(node *ForInOrOfStatement, awaitModifier *TokenNode, initializer *ForInitializer, expression *Expression, statement *Statement) *Node {
@@ -2397,7 +2415,7 @@ type BreakStatement struct {
func (f *NodeFactory) NewBreakStatement(label *IdentifierNode) *Node {
data := &BreakStatement{}
data.Label = label
- return newNode(KindBreakStatement, data, f.hooks)
+ return f.newNode(KindBreakStatement, data)
}
func (f *NodeFactory) UpdateBreakStatement(node *BreakStatement, label *IdentifierNode) *Node {
@@ -2429,7 +2447,7 @@ type ContinueStatement struct {
func (f *NodeFactory) NewContinueStatement(label *IdentifierNode) *Node {
data := &ContinueStatement{}
data.Label = label
- return newNode(KindContinueStatement, data, f.hooks)
+ return f.newNode(KindContinueStatement, data)
}
func (f *NodeFactory) UpdateContinueStatement(node *ContinueStatement, label *IdentifierNode) *Node {
@@ -2462,7 +2480,7 @@ type ReturnStatement struct {
func (f *NodeFactory) NewReturnStatement(expression *Expression) *Node {
data := f.returnStatementPool.New()
data.Expression = expression
- return newNode(KindReturnStatement, data, f.hooks)
+ return f.newNode(KindReturnStatement, data)
}
func (f *NodeFactory) UpdateReturnStatement(node *ReturnStatement, expression *Expression) *Node {
@@ -2505,7 +2523,7 @@ func (f *NodeFactory) NewWithStatement(expression *Expression, statement *Statem
data := &WithStatement{}
data.Expression = expression
data.Statement = statement
- return newNode(KindWithStatement, data, f.hooks)
+ return f.newNode(KindWithStatement, data)
}
func (f *NodeFactory) UpdateWithStatement(node *WithStatement, expression *Expression, statement *Statement) *Node {
@@ -2544,7 +2562,7 @@ func (f *NodeFactory) NewSwitchStatement(expression *Expression, caseBlock *Case
data := &SwitchStatement{}
data.Expression = expression
data.CaseBlock = caseBlock
- return newNode(KindSwitchStatement, data, f.hooks)
+ return f.newNode(KindSwitchStatement, data)
}
func (f *NodeFactory) UpdateSwitchStatement(node *SwitchStatement, expression *Expression, caseBlock *CaseBlockNode) *Node {
@@ -2583,7 +2601,7 @@ type CaseBlock struct {
func (f *NodeFactory) NewCaseBlock(clauses *NodeList) *Node {
data := &CaseBlock{}
data.Clauses = clauses
- return newNode(KindCaseBlock, data, f.hooks)
+ return f.newNode(KindCaseBlock, data)
}
func (f *NodeFactory) UpdateCaseBlock(node *CaseBlock, clauses *CaseClausesList) *Node {
@@ -2623,7 +2641,7 @@ func (f *NodeFactory) NewCaseOrDefaultClause(kind Kind, expression *Expression,
data := &CaseOrDefaultClause{}
data.Expression = expression
data.Statements = statements
- return newNode(kind, data, f.hooks)
+ return f.newNode(kind, data)
}
func (f *NodeFactory) UpdateCaseOrDefaultClause(node *CaseOrDefaultClause, expression *Expression, statements *StatementList) *Node {
@@ -2668,7 +2686,7 @@ type ThrowStatement struct {
func (f *NodeFactory) NewThrowStatement(expression *Expression) *Node {
data := &ThrowStatement{}
data.Expression = expression
- return newNode(KindThrowStatement, data, f.hooks)
+ return f.newNode(KindThrowStatement, data)
}
func (f *NodeFactory) UpdateThrowStatement(node *ThrowStatement, expression *Expression) *Node {
@@ -2709,7 +2727,7 @@ func (f *NodeFactory) NewTryStatement(tryBlock *BlockNode, catchClause *CatchCla
data.TryBlock = tryBlock
data.CatchClause = catchClause
data.FinallyBlock = finallyBlock
- return newNode(KindTryStatement, data, f.hooks)
+ return f.newNode(KindTryStatement, data)
}
func (f *NodeFactory) UpdateTryStatement(node *TryStatement, tryBlock *BlockNode, catchClause *CatchClauseNode, finallyBlock *BlockNode) *Node {
@@ -2755,7 +2773,7 @@ func (f *NodeFactory) NewCatchClause(variableDeclaration *VariableDeclarationNod
data := &CatchClause{}
data.VariableDeclaration = variableDeclaration
data.Block = block
- return newNode(KindCatchClause, data, f.hooks)
+ return f.newNode(KindCatchClause, data)
}
func (f *NodeFactory) UpdateCatchClause(node *CatchClause, variableDeclaration *VariableDeclarationNode, block *BlockNode) *Node {
@@ -2797,7 +2815,7 @@ type DebuggerStatement struct {
}
func (f *NodeFactory) NewDebuggerStatement() *Node {
- return newNode(KindDebuggerStatement, &DebuggerStatement{}, f.hooks)
+ return f.newNode(KindDebuggerStatement, &DebuggerStatement{})
}
func (node *DebuggerStatement) Clone(f *NodeFactory) *Node {
@@ -2816,7 +2834,7 @@ func (f *NodeFactory) NewLabeledStatement(label *IdentifierNode, statement *Stat
data := &LabeledStatement{}
data.Label = label
data.Statement = statement
- return newNode(KindLabeledStatement, data, f.hooks)
+ return f.newNode(KindLabeledStatement, data)
}
func (f *NodeFactory) UpdateLabeledStatement(node *LabeledStatement, label *IdentifierNode, statement *Statement) *Node {
@@ -2856,7 +2874,7 @@ type ExpressionStatement struct {
func (f *NodeFactory) NewExpressionStatement(expression *Expression) *Node {
data := f.expressionStatementPool.New()
data.Expression = expression
- return newNode(KindExpressionStatement, data, f.hooks)
+ return f.newNode(KindExpressionStatement, data)
}
func (f *NodeFactory) UpdateExpressionStatement(node *ExpressionStatement, expression *Expression) *Node {
@@ -2900,7 +2918,7 @@ func (f *NodeFactory) NewBlock(statements *NodeList, multiline bool) *Node {
data := f.blockPool.New()
data.Statements = statements
data.Multiline = multiline
- return newNode(KindBlock, data, f.hooks)
+ return f.newNode(KindBlock, data)
}
func (f *NodeFactory) UpdateBlock(node *Block, statements *StatementList) *Node {
@@ -2943,7 +2961,7 @@ func (f *NodeFactory) NewVariableStatement(modifiers *ModifierList, declarationL
data := f.variableStatementPool.New()
data.modifiers = modifiers
data.DeclarationList = declarationList
- return newNode(KindVariableStatement, data, f.hooks)
+ return f.newNode(KindVariableStatement, data)
}
func (f *NodeFactory) UpdateVariableStatement(node *VariableStatement, modifiers *ModifierList, declarationList *VariableDeclarationListNode) *Node {
@@ -2997,7 +3015,7 @@ func (f *NodeFactory) NewVariableDeclaration(name *BindingName, exclamationToken
data.ExclamationToken = exclamationToken
data.Type = typeNode
data.Initializer = initializer
- return newNode(KindVariableDeclaration, data, f.hooks)
+ return f.newNode(KindVariableDeclaration, data)
}
func (f *NodeFactory) UpdateVariableDeclaration(node *VariableDeclaration, name *BindingName, exclamationToken *TokenNode, typeNode *TypeNode, initializer *Expression) *Node {
@@ -3045,8 +3063,8 @@ type VariableDeclarationList struct {
func (f *NodeFactory) NewVariableDeclarationList(flags NodeFlags, declarations *NodeList) *Node {
data := f.variableDeclarationListPool.New()
data.Declarations = declarations
- node := newNode(KindVariableDeclarationList, data, f.hooks)
- node.Flags |= flags
+ node := f.newNode(KindVariableDeclarationList, data)
+ node.Flags = flags
return node
}
@@ -3093,7 +3111,7 @@ type BindingPattern struct {
func (f *NodeFactory) NewBindingPattern(kind Kind, elements *NodeList) *Node {
data := &BindingPattern{}
data.Elements = elements
- return newNode(kind, data, f.hooks)
+ return f.newNode(kind, data)
}
func (f *NodeFactory) UpdateBindingPattern(node *BindingPattern, elements *BindingElementList) *Node {
@@ -3164,7 +3182,7 @@ func (f *NodeFactory) NewParameterDeclaration(modifiers *ModifierList, dotDotDot
data.QuestionToken = questionToken
data.Type = typeNode
data.Initializer = initializer
- return newNode(KindParameter, data, f.hooks)
+ return f.newNode(KindParameter, data)
}
func (f *NodeFactory) UpdateParameterDeclaration(node *ParameterDeclaration, modifiers *ModifierList, dotDotDotToken *TokenNode, name *BindingName, questionToken *TokenNode, typeNode *TypeNode, initializer *Expression) *Node {
@@ -3231,7 +3249,7 @@ func (f *NodeFactory) NewBindingElement(dotDotDotToken *TokenNode, propertyName
data.PropertyName = propertyName
data.name = name
data.Initializer = initializer
- return newNode(KindBindingElement, data, f.hooks)
+ return f.newNode(KindBindingElement, data)
}
func (f *NodeFactory) UpdateBindingElement(node *BindingElement, dotDotDotToken *TokenNode, propertyName *PropertyName, name *BindingName, initializer *Expression) *Node {
@@ -3279,7 +3297,7 @@ type MissingDeclaration struct {
func (f *NodeFactory) NewMissingDeclaration(modifiers *ModifierList) *Node {
data := &MissingDeclaration{}
data.modifiers = modifiers
- return newNode(KindMissingDeclaration, data, f.hooks)
+ return f.newNode(KindMissingDeclaration, data)
}
func (f *NodeFactory) UpdateMissingDeclaration(node *MissingDeclaration, modifiers *ModifierList) *Node {
@@ -3323,7 +3341,7 @@ func (f *NodeFactory) NewFunctionDeclaration(modifiers *ModifierList, asteriskTo
data.Parameters = parameters
data.Type = returnType
data.Body = body
- return newNode(KindFunctionDeclaration, data, f.hooks)
+ return f.newNode(KindFunctionDeclaration, data)
}
func (f *NodeFactory) UpdateFunctionDeclaration(node *FunctionDeclaration, modifiers *ModifierList, asteriskToken *TokenNode, name *IdentifierNode, typeParameters *TypeParameterList, parameters *ParameterList, returnType *TypeNode, body *BlockNode) *Node {
@@ -3424,7 +3442,7 @@ func (f *NodeFactory) NewClassDeclaration(modifiers *ModifierList, name *Identif
data.TypeParameters = typeParameters
data.HeritageClauses = heritageClauses
data.Members = members
- return newNode(KindClassDeclaration, data, f.hooks)
+ return f.newNode(KindClassDeclaration, data)
}
func (f *NodeFactory) UpdateClassDeclaration(node *ClassDeclaration, modifiers *ModifierList, name *IdentifierNode, typeParameters *TypeParameterList, heritageClauses *HeritageClauseList, members *ClassElementList) *Node {
@@ -3472,7 +3490,7 @@ func (f *NodeFactory) NewClassExpression(modifiers *ModifierList, name *Identifi
data.TypeParameters = typeParameters
data.HeritageClauses = heritageClauses
data.Members = members
- return newNode(KindClassExpression, data, f.hooks)
+ return f.newNode(KindClassExpression, data)
}
func (f *NodeFactory) UpdateClassExpression(node *ClassExpression, modifiers *ModifierList, name *IdentifierNode, typeParameters *TypeParameterList, heritageClauses *HeritageClauseList, members *ClassElementList) *Node {
@@ -3519,7 +3537,7 @@ func (f *NodeFactory) NewHeritageClause(token Kind, types *NodeList) *Node {
data := &HeritageClause{}
data.Token = token
data.Types = types
- return newNode(KindHeritageClause, data, f.hooks)
+ return f.newNode(KindHeritageClause, data)
}
func (f *NodeFactory) UpdateHeritageClause(node *HeritageClause, types *ExpressionWithTypeArgumentsList) *Node {
@@ -3577,7 +3595,7 @@ func (f *NodeFactory) NewInterfaceDeclaration(modifiers *ModifierList, name *Ide
data.TypeParameters = typeParameters
data.HeritageClauses = heritageClauses
data.Members = members
- return newNode(KindInterfaceDeclaration, data, f.hooks)
+ return f.newNode(KindInterfaceDeclaration, data)
}
func (f *NodeFactory) UpdateInterfaceDeclaration(node *InterfaceDeclaration, modifiers *ModifierList, name *IdentifierNode, typeParameters *TypeParameterList, heritageClauses *HeritageClauseList, members *TypeElementList) *Node {
@@ -3626,7 +3644,7 @@ func (f *NodeFactory) newTypeOrJSTypeAliasDeclaration(kind Kind, modifiers *Modi
data.name = name
data.TypeParameters = typeParameters
data.Type = typeNode
- return newNode(kind, data, f.hooks)
+ return f.newNode(kind, data)
}
func (f *NodeFactory) NewTypeAliasDeclaration(modifiers *ModifierList, name *IdentifierNode, typeParameters *NodeList, typeNode *TypeNode) *Node {
@@ -3693,7 +3711,7 @@ func (f *NodeFactory) NewEnumMember(name *PropertyName, initializer *Expression)
data := &EnumMember{}
data.name = name
data.Initializer = initializer
- return newNode(KindEnumMember, data, f.hooks)
+ return f.newNode(KindEnumMember, data)
}
func (f *NodeFactory) UpdateEnumMember(node *EnumMember, name *PropertyName, initializer *Expression) *Node {
@@ -3746,7 +3764,7 @@ func (f *NodeFactory) NewEnumDeclaration(modifiers *ModifierList, name *Identifi
data.modifiers = modifiers
data.name = name
data.Members = members
- return newNode(KindEnumDeclaration, data, f.hooks)
+ return f.newNode(KindEnumDeclaration, data)
}
func (f *NodeFactory) UpdateEnumDeclaration(node *EnumDeclaration, modifiers *ModifierList, name *IdentifierNode, members *EnumMemberList) *Node {
@@ -3798,7 +3816,7 @@ type ModuleBlock struct {
func (f *NodeFactory) NewModuleBlock(statements *NodeList) *Node {
data := &ModuleBlock{}
data.Statements = statements
- return newNode(KindModuleBlock, data, f.hooks)
+ return f.newNode(KindModuleBlock, data)
}
func (f *NodeFactory) UpdateModuleBlock(node *ModuleBlock, statements *StatementList) *Node {
@@ -3848,7 +3866,7 @@ func (f *NodeFactory) NewModuleDeclaration(modifiers *ModifierList, keyword Kind
data.Keyword = keyword
data.name = name
data.Body = body
- node := newNode(KindModuleDeclaration, data, f.hooks)
+ node := f.newNode(KindModuleDeclaration, data)
return node
}
@@ -3936,7 +3954,7 @@ func (f *NodeFactory) NewImportEqualsDeclaration(modifiers *ModifierList, isType
data.IsTypeOnly = isTypeOnly
data.name = name
data.ModuleReference = moduleReference
- return newNode(KindImportEqualsDeclaration, data, f.hooks)
+ return f.newNode(KindImportEqualsDeclaration, data)
}
func (f *NodeFactory) UpdateImportEqualsDeclaration(node *ImportEqualsDeclaration, modifiers *ModifierList, isTypeOnly bool, name *IdentifierNode, moduleReference *ModuleReference) *Node {
@@ -3993,7 +4011,7 @@ func (f *NodeFactory) NewImportDeclaration(modifiers *ModifierList, importClause
data.ImportClause = importClause
data.ModuleSpecifier = moduleSpecifier
data.Attributes = attributes
- return newNode(KindImportDeclaration, data, f.hooks)
+ return f.newNode(KindImportDeclaration, data)
}
func (f *NodeFactory) UpdateImportDeclaration(node *ImportDeclaration, modifiers *ModifierList, importClause *ImportClauseNode, moduleSpecifier *Expression, attributes *ImportAttributesNode) *Node {
@@ -4043,7 +4061,7 @@ func (f *NodeFactory) NewImportSpecifier(isTypeOnly bool, propertyName *ModuleEx
data.IsTypeOnly = isTypeOnly
data.PropertyName = propertyName
data.name = name
- return newNode(KindImportSpecifier, data, f.hooks)
+ return f.newNode(KindImportSpecifier, data)
}
func (f *NodeFactory) UpdateImportSpecifier(node *ImportSpecifier, isTypeOnly bool, propertyName *ModuleExportName, name *IdentifierNode) *Node {
@@ -4092,7 +4110,7 @@ type ExternalModuleReference struct {
func (f *NodeFactory) NewExternalModuleReference(expression *Expression) *Node {
data := &ExternalModuleReference{}
data.Expression = expression
- return newNode(KindExternalModuleReference, data, f.hooks)
+ return f.newNode(KindExternalModuleReference, data)
}
func (f *NodeFactory) UpdateExternalModuleReference(node *ExternalModuleReference, expression *Expression) *Node {
@@ -4139,7 +4157,7 @@ func (f *NodeFactory) NewImportClause(isTypeOnly bool, name *IdentifierNode, nam
data.IsTypeOnly = isTypeOnly
data.name = name
data.NamedBindings = namedBindings
- return newNode(KindImportClause, data, f.hooks)
+ return f.newNode(KindImportClause, data)
}
func (f *NodeFactory) UpdateImportClause(node *ImportClause, isTypeOnly bool, name *IdentifierNode, namedBindings *NamedImportBindings) *Node {
@@ -4190,7 +4208,7 @@ type NamespaceImport struct {
func (f *NodeFactory) NewNamespaceImport(name *IdentifierNode) *Node {
data := &NamespaceImport{}
data.name = name
- return newNode(KindNamespaceImport, data, f.hooks)
+ return f.newNode(KindNamespaceImport, data)
}
func (f *NodeFactory) UpdateNamespaceImport(node *NamespaceImport, name *IdentifierNode) *Node {
@@ -4235,7 +4253,7 @@ type NamedImports struct {
func (f *NodeFactory) NewNamedImports(elements *ImportSpecifierList) *Node {
data := &NamedImports{}
data.Elements = elements
- return newNode(KindNamedImports, data, f.hooks)
+ return f.newNode(KindNamedImports, data)
}
func (f *NodeFactory) UpdateNamedImports(node *NamedImports, elements *ImportSpecifierList) *Node {
@@ -4283,7 +4301,7 @@ func (f *NodeFactory) NewExportAssignment(modifiers *ModifierList, isExportEqual
data.modifiers = modifiers
data.IsExportEquals = isExportEquals
data.Expression = expression
- return newNode(KindExportAssignment, data, f.hooks)
+ return f.newNode(KindExportAssignment, data)
}
func (f *NodeFactory) UpdateExportAssignment(node *ExportAssignment, modifiers *ModifierList, expression *Expression) *Node {
@@ -4327,7 +4345,7 @@ func (f *NodeFactory) NewNamespaceExportDeclaration(modifiers *ModifierList, nam
data := &NamespaceExportDeclaration{}
data.modifiers = modifiers
data.name = name
- return newNode(KindNamespaceExportDeclaration, data, f.hooks)
+ return f.newNode(KindNamespaceExportDeclaration, data)
}
func (f *NodeFactory) UpdateNamespaceExportDeclaration(node *NamespaceExportDeclaration, modifiers *ModifierList, name *IdentifierNode) *Node {
@@ -4377,7 +4395,7 @@ func (f *NodeFactory) NewExportDeclaration(modifiers *ModifierList, isTypeOnly b
data.ExportClause = exportClause
data.ModuleSpecifier = moduleSpecifier
data.Attributes = attributes
- return newNode(KindExportDeclaration, data, f.hooks)
+ return f.newNode(KindExportDeclaration, data)
}
func (f *NodeFactory) UpdateExportDeclaration(node *ExportDeclaration, modifiers *ModifierList, isTypeOnly bool, exportClause *NamedExportBindings, moduleSpecifier *Expression, attributes *ImportAttributesNode) *Node {
@@ -4422,7 +4440,7 @@ type NamespaceExport struct {
func (f *NodeFactory) NewNamespaceExport(name *ModuleExportName) *Node {
data := &NamespaceExport{}
data.name = name
- return newNode(KindNamespaceExport, data, f.hooks)
+ return f.newNode(KindNamespaceExport, data)
}
func (f *NodeFactory) UpdateNamespaceExport(node *NamespaceExport, name *ModuleExportName) *Node {
@@ -4467,7 +4485,7 @@ type NamedExports struct {
func (f *NodeFactory) NewNamedExports(elements *NodeList) *Node {
data := &NamedExports{}
data.Elements = elements
- return newNode(KindNamedExports, data, f.hooks)
+ return f.newNode(KindNamedExports, data)
}
func (f *NodeFactory) UpdateNamedExports(node *NamedExports, elements *ExportSpecifierList) *Node {
@@ -4514,7 +4532,7 @@ func (f *NodeFactory) NewExportSpecifier(isTypeOnly bool, propertyName *ModuleEx
data.IsTypeOnly = isTypeOnly
data.PropertyName = propertyName
data.name = name
- return newNode(KindExportSpecifier, data, f.hooks)
+ return f.newNode(KindExportSpecifier, data)
}
func (f *NodeFactory) UpdateExportSpecifier(node *ExportSpecifier, isTypeOnly bool, propertyName *ModuleExportName, name *ModuleExportName) *Node {
@@ -4589,7 +4607,7 @@ func (f *NodeFactory) NewCallSignatureDeclaration(typeParameters *NodeList, para
data.TypeParameters = typeParameters
data.Parameters = parameters
data.Type = returnType
- return newNode(KindCallSignature, data, f.hooks)
+ return f.newNode(KindCallSignature, data)
}
func (f *NodeFactory) UpdateCallSignatureDeclaration(node *CallSignatureDeclaration, typeParameters *TypeParameterList, parameters *ParameterList, returnType *TypeNode) *Node {
@@ -4630,7 +4648,7 @@ func (f *NodeFactory) NewConstructSignatureDeclaration(typeParameters *NodeList,
data.TypeParameters = typeParameters
data.Parameters = parameters
data.Type = returnType
- return newNode(KindConstructSignature, data, f.hooks)
+ return f.newNode(KindConstructSignature, data)
}
func (f *NodeFactory) UpdateConstructSignatureDeclaration(node *ConstructSignatureDeclaration, typeParameters *TypeParameterList, parameters *ParameterList, returnType *TypeNode) *Node {
@@ -4675,7 +4693,7 @@ func (f *NodeFactory) NewConstructorDeclaration(modifiers *ModifierList, typePar
data.Parameters = parameters
data.Type = returnType
data.Body = body
- return newNode(KindConstructor, data, f.hooks)
+ return f.newNode(KindConstructor, data)
}
func (f *NodeFactory) UpdateConstructorDeclaration(node *ConstructorDeclaration, modifiers *ModifierList, typeParameters *TypeParameterList, parameters *ParameterList, returnType *TypeNode, body *BlockNode) *Node {
@@ -4769,7 +4787,7 @@ func (f *NodeFactory) NewGetAccessorDeclaration(modifiers *ModifierList, name *P
data.Parameters = parameters
data.Type = returnType
data.Body = body
- return newNode(KindGetAccessor, data, f.hooks)
+ return f.newNode(KindGetAccessor, data)
}
func (f *NodeFactory) UpdateGetAccessorDeclaration(node *GetAccessorDeclaration, modifiers *ModifierList, name *PropertyName, typeParameters *TypeParameterList, parameters *ParameterList, returnType *TypeNode, body *BlockNode) *Node {
@@ -4805,7 +4823,7 @@ func (f *NodeFactory) NewSetAccessorDeclaration(modifiers *ModifierList, name *P
data.Parameters = parameters
data.Type = returnType
data.Body = body
- return newNode(KindSetAccessor, data, f.hooks)
+ return f.newNode(KindSetAccessor, data)
}
func (f *NodeFactory) UpdateSetAccessorDeclaration(node *SetAccessorDeclaration, modifiers *ModifierList, name *PropertyName, typeParameters *TypeParameterList, parameters *ParameterList, returnType *TypeNode, body *BlockNode) *Node {
@@ -4844,7 +4862,7 @@ func (f *NodeFactory) NewIndexSignatureDeclaration(modifiers *ModifierList, para
data.modifiers = modifiers
data.Parameters = parameters
data.Type = returnType
- return newNode(KindIndexSignature, data, f.hooks)
+ return f.newNode(KindIndexSignature, data)
}
func (f *NodeFactory) UpdateIndexSignatureDeclaration(node *IndexSignatureDeclaration, modifiers *ModifierList, parameters *ParameterList, returnType *TypeNode) *Node {
@@ -4888,7 +4906,7 @@ func (f *NodeFactory) NewMethodSignatureDeclaration(modifiers *ModifierList, nam
data.TypeParameters = typeParameters
data.Parameters = parameters
data.Type = returnType
- return newNode(KindMethodSignature, data, f.hooks)
+ return f.newNode(KindMethodSignature, data)
}
func (f *NodeFactory) UpdateMethodSignatureDeclaration(node *MethodSignatureDeclaration, modifiers *ModifierList, name *PropertyName, postfixToken *TokenNode, typeParameters *TypeParameterList, parameters *ParameterList, returnType *TypeNode) *Node {
@@ -4937,7 +4955,7 @@ func (f *NodeFactory) NewMethodDeclaration(modifiers *ModifierList, asteriskToke
data.Parameters = parameters
data.Type = returnType
data.Body = body
- return newNode(KindMethodDeclaration, data, f.hooks)
+ return f.newNode(KindMethodDeclaration, data)
}
func (f *NodeFactory) UpdateMethodDeclaration(node *MethodDeclaration, modifiers *ModifierList, asteriskToken *TokenNode, name *PropertyName, postfixToken *TokenNode, typeParameters *TypeParameterList, parameters *ParameterList, returnType *TypeNode, body *BlockNode) *Node {
@@ -5006,7 +5024,7 @@ func (f *NodeFactory) NewPropertySignatureDeclaration(modifiers *ModifierList, n
data.PostfixToken = postfixToken
data.Type = typeNode
data.Initializer = initializer
- return newNode(KindPropertySignature, data, f.hooks)
+ return f.newNode(KindPropertySignature, data)
}
func (f *NodeFactory) UpdatePropertySignatureDeclaration(node *PropertySignatureDeclaration, modifiers *ModifierList, name *PropertyName, postfixToken *TokenNode, typeNode *TypeNode, initializer *Expression) *Node {
@@ -5050,7 +5068,7 @@ func (f *NodeFactory) NewPropertyDeclaration(modifiers *ModifierList, name *Prop
data.PostfixToken = postfixToken
data.Type = typeNode
data.Initializer = initializer
- return newNode(KindPropertyDeclaration, data, f.hooks)
+ return f.newNode(KindPropertyDeclaration, data)
}
func (f *NodeFactory) UpdatePropertyDeclaration(node *PropertyDeclaration, modifiers *ModifierList, name *PropertyName, postfixToken *TokenNode, typeNode *TypeNode, initializer *Expression) *Node {
@@ -5099,7 +5117,7 @@ type SemicolonClassElement struct {
}
func (f *NodeFactory) NewSemicolonClassElement() *Node {
- return newNode(KindSemicolonClassElement, &SemicolonClassElement{}, f.hooks)
+ return f.newNode(KindSemicolonClassElement, &SemicolonClassElement{})
}
func (node *SemicolonClassElement) Clone(f *NodeFactory) *Node {
@@ -5123,7 +5141,7 @@ func (f *NodeFactory) NewClassStaticBlockDeclaration(modifiers *ModifierList, bo
data := &ClassStaticBlockDeclaration{}
data.modifiers = modifiers
data.Body = body
- return newNode(KindClassStaticBlockDeclaration, data, f.hooks)
+ return f.newNode(KindClassStaticBlockDeclaration, data)
}
func (f *NodeFactory) UpdateClassStaticBlockDeclaration(node *ClassStaticBlockDeclaration, modifiers *ModifierList, body *BlockNode) *Node {
@@ -5171,7 +5189,7 @@ type OmittedExpression struct {
}
func (f *NodeFactory) NewOmittedExpression() *Node {
- return newNode(KindOmittedExpression, &OmittedExpression{}, f.hooks)
+ return f.newNode(KindOmittedExpression, &OmittedExpression{})
}
func (node *OmittedExpression) Clone(f *NodeFactory) *Node {
@@ -5190,7 +5208,7 @@ type KeywordExpression struct {
}
func (f *NodeFactory) NewKeywordExpression(kind Kind) *Node {
- return newNode(kind, &KeywordExpression{}, f.hooks)
+ return f.newNode(kind, &KeywordExpression{})
}
func (node *KeywordExpression) Clone(f *NodeFactory) *Node {
@@ -5226,7 +5244,8 @@ type StringLiteral struct {
func (f *NodeFactory) NewStringLiteral(text string) *Node {
data := f.stringLiteralPool.New()
data.Text = text
- return newNode(KindStringLiteral, data, f.hooks)
+ f.textCount++
+ return f.newNode(KindStringLiteral, data)
}
func (node *StringLiteral) Clone(f *NodeFactory) *Node {
@@ -5247,7 +5266,8 @@ type NumericLiteral struct {
func (f *NodeFactory) NewNumericLiteral(text string) *Node {
data := &NumericLiteral{}
data.Text = text
- return newNode(KindNumericLiteral, data, f.hooks)
+ f.textCount++
+ return f.newNode(KindNumericLiteral, data)
}
func (node *NumericLiteral) Clone(f *NodeFactory) *Node {
@@ -5268,7 +5288,8 @@ type BigIntLiteral struct {
func (f *NodeFactory) NewBigIntLiteral(text string) *Node {
data := &BigIntLiteral{}
data.Text = text
- return newNode(KindBigIntLiteral, data, f.hooks)
+ f.textCount++
+ return f.newNode(KindBigIntLiteral, data)
}
func (node *BigIntLiteral) Clone(f *NodeFactory) *Node {
@@ -5293,7 +5314,8 @@ type RegularExpressionLiteral struct {
func (f *NodeFactory) NewRegularExpressionLiteral(text string) *Node {
data := &RegularExpressionLiteral{}
data.Text = text
- return newNode(KindRegularExpressionLiteral, data, f.hooks)
+ f.textCount++
+ return f.newNode(KindRegularExpressionLiteral, data)
}
func (node *RegularExpressionLiteral) Clone(f *NodeFactory) *Node {
@@ -5310,7 +5332,8 @@ type NoSubstitutionTemplateLiteral struct {
func (f *NodeFactory) NewNoSubstitutionTemplateLiteral(text string) *Node {
data := &NoSubstitutionTemplateLiteral{}
data.Text = text
- return newNode(KindNoSubstitutionTemplateLiteral, data, f.hooks)
+ f.textCount++
+ return f.newNode(KindNoSubstitutionTemplateLiteral, data)
}
func (node *NoSubstitutionTemplateLiteral) Clone(f *NodeFactory) *Node {
@@ -5336,7 +5359,7 @@ func (f *NodeFactory) NewBinaryExpression(left *Expression, operatorToken *Token
data.Left = left
data.OperatorToken = operatorToken
data.Right = right
- return newNode(KindBinaryExpression, data, f.hooks)
+ return f.newNode(KindBinaryExpression, data)
}
func (f *NodeFactory) UpdateBinaryExpression(node *BinaryExpression, left *Expression, operatorToken *TokenNode, right *Expression) *Node {
@@ -5381,7 +5404,7 @@ func (f *NodeFactory) NewPrefixUnaryExpression(operator Kind, operand *Expressio
data := &PrefixUnaryExpression{}
data.Operator = operator
data.Operand = operand
- return newNode(KindPrefixUnaryExpression, data, f.hooks)
+ return f.newNode(KindPrefixUnaryExpression, data)
}
func (f *NodeFactory) UpdatePrefixUnaryExpression(node *PrefixUnaryExpression, operand *Expression) *Node {
@@ -5423,7 +5446,7 @@ func (f *NodeFactory) NewPostfixUnaryExpression(operand *Expression, operator Ki
data := &PostfixUnaryExpression{}
data.Operand = operand
data.Operator = operator
- return newNode(KindPostfixUnaryExpression, data, f.hooks)
+ return f.newNode(KindPostfixUnaryExpression, data)
}
func (f *NodeFactory) UpdatePostfixUnaryExpression(node *PostfixUnaryExpression, operand *Expression) *Node {
@@ -5461,7 +5484,7 @@ func (f *NodeFactory) NewYieldExpression(asteriskToken *TokenNode, expression *E
data := &YieldExpression{}
data.AsteriskToken = asteriskToken
data.Expression = expression
- return newNode(KindYieldExpression, data, f.hooks)
+ return f.newNode(KindYieldExpression, data)
}
func (f *NodeFactory) UpdateYieldExpression(node *YieldExpression, asteriskToken *TokenNode, expression *Expression) *Node {
@@ -5507,7 +5530,7 @@ func (f *NodeFactory) NewArrowFunction(modifiers *ModifierList, typeParameters *
data.Type = returnType
data.EqualsGreaterThanToken = equalsGreaterThanToken
data.Body = body
- return newNode(KindArrowFunction, data, f.hooks)
+ return f.newNode(KindArrowFunction, data)
}
func (f *NodeFactory) UpdateArrowFunction(node *ArrowFunction, modifiers *ModifierList, typeParameters *TypeParameterList, parameters *ParameterList, returnType *TypeNode, equalsGreaterThanToken *TokenNode, body *BlockOrExpression) *Node {
@@ -5573,7 +5596,7 @@ func (f *NodeFactory) NewFunctionExpression(modifiers *ModifierList, asteriskTok
data.Parameters = parameters
data.Type = returnType
data.Body = body
- return newNode(KindFunctionExpression, data, f.hooks)
+ return f.newNode(KindFunctionExpression, data)
}
func (f *NodeFactory) UpdateFunctionExpression(node *FunctionExpression, modifiers *ModifierList, asteriskToken *TokenNode, name *IdentifierNode, typeParameters *TypeParameterList, parameters *ParameterList, returnType *TypeNode, body *BlockNode) *Node {
@@ -5634,7 +5657,7 @@ func (f *NodeFactory) NewAsExpression(expression *Expression, typeNode *TypeNode
data := &AsExpression{}
data.Expression = expression
data.Type = typeNode
- return newNode(KindAsExpression, data, f.hooks)
+ return f.newNode(KindAsExpression, data)
}
func (f *NodeFactory) UpdateAsExpression(node *AsExpression, expression *Expression, typeNode *TypeNode) *Node {
@@ -5676,7 +5699,7 @@ func (f *NodeFactory) NewSatisfiesExpression(expression *Expression, typeNode *T
data := &SatisfiesExpression{}
data.Expression = expression
data.Type = typeNode
- return newNode(KindSatisfiesExpression, data, f.hooks)
+ return f.newNode(KindSatisfiesExpression, data)
}
func (f *NodeFactory) UpdateSatisfiesExpression(node *SatisfiesExpression, expression *Expression, typeNode *TypeNode) *Node {
@@ -5729,7 +5752,7 @@ func (f *NodeFactory) NewConditionalExpression(condition *Expression, questionTo
data.WhenTrue = whenTrue
data.ColonToken = colonToken
data.WhenFalse = whenFalse
- return newNode(KindConditionalExpression, data, f.hooks)
+ return f.newNode(KindConditionalExpression, data)
}
func (f *NodeFactory) UpdateConditionalExpression(node *ConditionalExpression, condition *Expression, questionToken *TokenNode, whenTrue *Expression, colonToken *TokenNode, whenFalse *Expression) *Node {
@@ -5774,7 +5797,7 @@ func (f *NodeFactory) NewPropertyAccessExpression(expression *Expression, questi
data.Expression = expression
data.QuestionDotToken = questionDotToken
data.name = name
- node := newNode(KindPropertyAccessExpression, data, f.hooks)
+ node := f.newNode(KindPropertyAccessExpression, data)
node.Flags |= flags & NodeFlagsOptionalChain
return node
}
@@ -5830,7 +5853,7 @@ func (f *NodeFactory) NewElementAccessExpression(expression *Expression, questio
data.Expression = expression
data.QuestionDotToken = questionDotToken
data.ArgumentExpression = argumentExpression
- node := newNode(KindElementAccessExpression, data, f.hooks)
+ node := f.newNode(KindElementAccessExpression, data)
node.Flags |= flags & NodeFlagsOptionalChain
return node
}
@@ -5885,7 +5908,7 @@ func (f *NodeFactory) NewCallExpression(expression *Expression, questionDotToken
data.QuestionDotToken = questionDotToken
data.TypeArguments = typeArguments
data.Arguments = arguments
- node := newNode(KindCallExpression, data, f.hooks)
+ node := f.newNode(KindCallExpression, data)
node.Flags |= flags & NodeFlagsOptionalChain
return node
}
@@ -5940,7 +5963,7 @@ func (f *NodeFactory) NewNewExpression(expression *Expression, typeArguments *No
data.Expression = expression
data.TypeArguments = typeArguments
data.Arguments = arguments
- return newNode(KindNewExpression, data, f.hooks)
+ return f.newNode(KindNewExpression, data)
}
func (f *NodeFactory) UpdateNewExpression(node *NewExpression, expression *Expression, typeArguments *TypeArgumentList, arguments *ArgumentList) *Node {
@@ -5990,7 +6013,7 @@ func (f *NodeFactory) NewMetaProperty(keywordToken Kind, name *IdentifierNode) *
data := &MetaProperty{}
data.KeywordToken = keywordToken
data.name = name
- return newNode(KindMetaProperty, data, f.hooks)
+ return f.newNode(KindMetaProperty, data)
}
func (f *NodeFactory) UpdateMetaProperty(node *MetaProperty, name *IdentifierNode) *Node {
@@ -6036,7 +6059,7 @@ func (f *NodeFactory) NewNonNullExpression(expression *Expression, flags NodeFla
data := &NonNullExpression{}
data.Expression = expression
data.Flags |= flags & NodeFlagsOptionalChain
- return newNode(KindNonNullExpression, data, f.hooks)
+ return f.newNode(KindNonNullExpression, data)
}
func (f *NodeFactory) UpdateNonNullExpression(node *NonNullExpression, expression *Expression) *Node {
@@ -6076,7 +6099,7 @@ type SpreadElement struct {
func (f *NodeFactory) NewSpreadElement(expression *Expression) *Node {
data := &SpreadElement{}
data.Expression = expression
- return newNode(KindSpreadElement, data, f.hooks)
+ return f.newNode(KindSpreadElement, data)
}
func (f *NodeFactory) UpdateSpreadElement(node *SpreadElement, expression *Expression) *Node {
@@ -6119,7 +6142,7 @@ func (f *NodeFactory) NewTemplateExpression(head *TemplateHeadNode, templateSpan
data := &TemplateExpression{}
data.Head = head
data.TemplateSpans = templateSpans
- return newNode(KindTemplateExpression, data, f.hooks)
+ return f.newNode(KindTemplateExpression, data)
}
func (f *NodeFactory) UpdateTemplateExpression(node *TemplateExpression, head *TemplateHeadNode, templateSpans *TemplateSpanList) *Node {
@@ -6162,7 +6185,7 @@ func (f *NodeFactory) NewTemplateSpan(expression *Expression, literal *TemplateM
data := &TemplateSpan{}
data.Expression = expression
data.Literal = literal
- return newNode(KindTemplateSpan, data, f.hooks)
+ return f.newNode(KindTemplateSpan, data)
}
func (f *NodeFactory) UpdateTemplateSpan(node *TemplateSpan, expression *Expression, literal *TemplateMiddleOrTail) *Node {
@@ -6209,7 +6232,7 @@ func (f *NodeFactory) NewTaggedTemplateExpression(tag *Expression, questionDotTo
data.QuestionDotToken = questionDotToken
data.TypeArguments = typeArguments
data.Template = template
- node := newNode(KindTaggedTemplateExpression, data, f.hooks)
+ node := f.newNode(KindTaggedTemplateExpression, data)
node.Flags |= flags & NodeFlagsOptionalChain
return node
}
@@ -6254,7 +6277,7 @@ type ParenthesizedExpression struct {
func (f *NodeFactory) NewParenthesizedExpression(expression *Expression) *Node {
data := f.parenthesizedExpressionPool.New()
data.Expression = expression
- return newNode(KindParenthesizedExpression, data, f.hooks)
+ return f.newNode(KindParenthesizedExpression, data)
}
func (f *NodeFactory) UpdateParenthesizedExpression(node *ParenthesizedExpression, expression *Expression) *Node {
@@ -6301,7 +6324,7 @@ func (f *NodeFactory) NewArrayLiteralExpression(elements *NodeList, multiLine bo
data := &ArrayLiteralExpression{}
data.Elements = elements
data.MultiLine = multiLine
- return newNode(KindArrayLiteralExpression, data, f.hooks)
+ return f.newNode(KindArrayLiteralExpression, data)
}
func (f *NodeFactory) UpdateArrayLiteralExpression(node *ArrayLiteralExpression, elements *ElementList) *Node {
@@ -6349,7 +6372,7 @@ func (f *NodeFactory) NewObjectLiteralExpression(properties *NodeList, multiLine
data := &ObjectLiteralExpression{}
data.Properties = properties
data.MultiLine = multiLine
- return newNode(KindObjectLiteralExpression, data, f.hooks)
+ return f.newNode(KindObjectLiteralExpression, data)
}
func (f *NodeFactory) UpdateObjectLiteralExpression(node *ObjectLiteralExpression, properties *PropertyDefinitionList) *Node {
@@ -6399,7 +6422,7 @@ type SpreadAssignment struct {
func (f *NodeFactory) NewSpreadAssignment(expression *Expression) *Node {
data := &SpreadAssignment{}
data.Expression = expression
- return newNode(KindSpreadAssignment, data, f.hooks)
+ return f.newNode(KindSpreadAssignment, data)
}
func (f *NodeFactory) UpdateSpreadAssignment(node *SpreadAssignment, expression *Expression) *Node {
@@ -6445,7 +6468,7 @@ func (f *NodeFactory) NewPropertyAssignment(modifiers *ModifierList, name *Prope
data.name = name
data.PostfixToken = postfixToken
data.Initializer = initializer
- return newNode(KindPropertyAssignment, data, f.hooks)
+ return f.newNode(KindPropertyAssignment, data)
}
func (f *NodeFactory) UpdatePropertyAssignment(node *PropertyAssignment, modifiers *ModifierList, name *PropertyName, postfixToken *TokenNode, initializer *Expression) *Node {
@@ -6494,7 +6517,7 @@ func (f *NodeFactory) NewShorthandPropertyAssignment(modifiers *ModifierList, na
data.PostfixToken = postfixToken
data.EqualsToken = equalsToken
data.ObjectAssignmentInitializer = objectAssignmentInitializer
- return newNode(KindShorthandPropertyAssignment, data, f.hooks)
+ return f.newNode(KindShorthandPropertyAssignment, data)
}
func (f *NodeFactory) UpdateShorthandPropertyAssignment(node *ShorthandPropertyAssignment, modifiers *ModifierList, name *PropertyName, postfixToken *TokenNode, equalsToken *TokenNode, objectAssignmentInitializer *Expression) *Node {
@@ -6536,7 +6559,7 @@ type DeleteExpression struct {
func (f *NodeFactory) NewDeleteExpression(expression *Expression) *Node {
data := &DeleteExpression{}
data.Expression = expression
- return newNode(KindDeleteExpression, data, f.hooks)
+ return f.newNode(KindDeleteExpression, data)
}
func (f *NodeFactory) UpdateDeleteExpression(node *DeleteExpression, expression *Expression) *Node {
@@ -6572,7 +6595,7 @@ type TypeOfExpression struct {
func (f *NodeFactory) NewTypeOfExpression(expression *Expression) *Node {
data := &TypeOfExpression{}
data.Expression = expression
- return newNode(KindTypeOfExpression, data, f.hooks)
+ return f.newNode(KindTypeOfExpression, data)
}
func (f *NodeFactory) UpdateTypeOfExpression(node *TypeOfExpression, expression *Expression) *Node {
@@ -6612,7 +6635,7 @@ type VoidExpression struct {
func (f *NodeFactory) NewVoidExpression(expression *Expression) *Node {
data := &VoidExpression{}
data.Expression = expression
- return newNode(KindVoidExpression, data, f.hooks)
+ return f.newNode(KindVoidExpression, data)
}
func (f *NodeFactory) UpdateVoidExpression(node *VoidExpression, expression *Expression) *Node {
@@ -6648,7 +6671,7 @@ type AwaitExpression struct {
func (f *NodeFactory) NewAwaitExpression(expression *Expression) *Node {
data := &AwaitExpression{}
data.Expression = expression
- return newNode(KindAwaitExpression, data, f.hooks)
+ return f.newNode(KindAwaitExpression, data)
}
func (f *NodeFactory) UpdateAwaitExpression(node *AwaitExpression, expression *Expression) *Node {
@@ -6690,7 +6713,7 @@ func (f *NodeFactory) NewTypeAssertion(typeNode *TypeNode, expression *Expressio
data := &TypeAssertion{}
data.Type = typeNode
data.Expression = expression
- return newNode(KindTypeAssertionExpression, data, f.hooks)
+ return f.newNode(KindTypeAssertionExpression, data)
}
func (f *NodeFactory) UpdateTypeAssertion(node *TypeAssertion, typeNode *TypeNode, expression *Expression) *Node {
@@ -6734,7 +6757,7 @@ type KeywordTypeNode struct {
}
func (f *NodeFactory) NewKeywordTypeNode(kind Kind) *Node {
- return newNode(kind, f.keywordTypeNodePool.New(), f.hooks)
+ return f.newNode(kind, f.keywordTypeNodePool.New())
}
func (node *KeywordTypeNode) Clone(f *NodeFactory) *Node {
@@ -6768,7 +6791,7 @@ func (f *NodeFactory) UpdateUnionTypeNode(node *UnionTypeNode, types *TypeList)
func (f *NodeFactory) NewUnionTypeNode(types *NodeList) *Node {
data := &UnionTypeNode{}
data.Types = types
- return newNode(KindUnionType, data, f.hooks)
+ return f.newNode(KindUnionType, data)
}
func (node *UnionTypeNode) VisitEachChild(v *NodeVisitor) *Node {
@@ -6795,7 +6818,7 @@ func (f *NodeFactory) UpdateIntersectionTypeNode(node *IntersectionTypeNode, typ
func (f *NodeFactory) NewIntersectionTypeNode(types *NodeList) *Node {
data := &IntersectionTypeNode{}
data.Types = types
- return newNode(KindIntersectionType, data, f.hooks)
+ return f.newNode(KindIntersectionType, data)
}
func (node *IntersectionTypeNode) VisitEachChild(v *NodeVisitor) *Node {
@@ -6823,7 +6846,7 @@ func (f *NodeFactory) NewConditionalTypeNode(checkType *TypeNode, extendsType *T
data.ExtendsType = extendsType
data.TrueType = trueType
data.FalseType = falseType
- return newNode(KindConditionalType, data, f.hooks)
+ return f.newNode(KindConditionalType, data)
}
func (f *NodeFactory) UpdateConditionalTypeNode(node *ConditionalTypeNode, checkType *TypeNode, extendsType *TypeNode, trueType *TypeNode, falseType *TypeNode) *Node {
@@ -6861,7 +6884,7 @@ func (f *NodeFactory) NewTypeOperatorNode(operator Kind, typeNode *TypeNode) *No
data := &TypeOperatorNode{}
data.Operator = operator
data.Type = typeNode
- return newNode(KindTypeOperator, data, f.hooks)
+ return f.newNode(KindTypeOperator, data)
}
func (f *NodeFactory) UpdateTypeOperatorNode(node *TypeOperatorNode, typeNode *TypeNode) *Node {
@@ -6897,7 +6920,7 @@ type InferTypeNode struct {
func (f *NodeFactory) NewInferTypeNode(typeParameter *TypeParameterDeclarationNode) *Node {
data := &InferTypeNode{}
data.TypeParameter = typeParameter
- return newNode(KindInferType, data, f.hooks)
+ return f.newNode(KindInferType, data)
}
func (f *NodeFactory) UpdateInferTypeNode(node *InferTypeNode, typeParameter *TypeNode) *Node {
@@ -6933,7 +6956,7 @@ type ArrayTypeNode struct {
func (f *NodeFactory) NewArrayTypeNode(elementType *TypeNode) *Node {
data := &ArrayTypeNode{}
data.ElementType = elementType
- return newNode(KindArrayType, data, f.hooks)
+ return f.newNode(KindArrayType, data)
}
func (f *NodeFactory) UpdateArrayTypeNode(node *ArrayTypeNode, elementType *TypeNode) *Node {
@@ -6967,7 +6990,7 @@ func (f *NodeFactory) NewIndexedAccessTypeNode(objectType *TypeNode, indexType *
data := &IndexedAccessTypeNode{}
data.ObjectType = objectType
data.IndexType = indexType
- return newNode(KindIndexedAccessType, data, f.hooks)
+ return f.newNode(KindIndexedAccessType, data)
}
func (f *NodeFactory) UpdateIndexedAccessTypeNode(node *IndexedAccessTypeNode, objectType *TypeNode, indexType *TypeNode) *Node {
@@ -7005,7 +7028,7 @@ func (f *NodeFactory) NewTypeReferenceNode(typeName *EntityName, typeArguments *
data := f.typeReferenceNodePool.New()
data.TypeName = typeName
data.TypeArguments = typeArguments
- return newNode(KindTypeReference, data, f.hooks)
+ return f.newNode(KindTypeReference, data)
}
func (f *NodeFactory) UpdateTypeReferenceNode(node *TypeReferenceNode, typeName *EntityName, typeArguments *TypeArgumentList) *Node {
@@ -7044,7 +7067,7 @@ func (f *NodeFactory) NewExpressionWithTypeArguments(expression *Expression, typ
data := &ExpressionWithTypeArguments{}
data.Expression = expression
data.TypeArguments = typeArguments
- return newNode(KindExpressionWithTypeArguments, data, f.hooks)
+ return f.newNode(KindExpressionWithTypeArguments, data)
}
func (f *NodeFactory) UpdateExpressionWithTypeArguments(node *ExpressionWithTypeArguments, expression *Expression, typeArguments *TypeArgumentList) *Node {
@@ -7085,7 +7108,7 @@ type LiteralTypeNode struct {
func (f *NodeFactory) NewLiteralTypeNode(literal *Node) *Node {
data := f.literalTypeNodePool.New()
data.Literal = literal
- return newNode(KindLiteralType, data, f.hooks)
+ return f.newNode(KindLiteralType, data)
}
func (f *NodeFactory) UpdateLiteralTypeNode(node *LiteralTypeNode, literal *Node) *Node {
@@ -7118,7 +7141,7 @@ type ThisTypeNode struct {
}
func (f *NodeFactory) NewThisTypeNode() *Node {
- return newNode(KindThisType, &ThisTypeNode{}, f.hooks)
+ return f.newNode(KindThisType, &ThisTypeNode{})
}
func (node *ThisTypeNode) Clone(f *NodeFactory) *Node {
@@ -7143,7 +7166,7 @@ func (f *NodeFactory) NewTypePredicateNode(assertsModifier *TokenNode, parameter
data.AssertsModifier = assertsModifier
data.ParameterName = parameterName
data.Type = typeNode
- return newNode(KindTypePredicate, data, f.hooks)
+ return f.newNode(KindTypePredicate, data)
}
func (f *NodeFactory) UpdateTypePredicateNode(node *TypePredicateNode, assertsModifier *TokenNode, parameterName *TypePredicateParameterName, typeNode *TypeNode) *Node {
@@ -7187,7 +7210,7 @@ func (f *NodeFactory) NewImportTypeNode(isTypeOf bool, argument *TypeNode, attri
data.Attributes = attributes
data.Qualifier = qualifier
data.TypeArguments = typeArguments
- return newNode(KindImportType, data, f.hooks)
+ return f.newNode(KindImportType, data)
}
func (f *NodeFactory) UpdateImportTypeNode(node *ImportTypeNode, isTypeOf bool, argument *TypeNode, attributes *ImportAttributesNode, qualifier *EntityName, typeArguments *TypeArgumentList) *Node {
@@ -7226,7 +7249,7 @@ func (f *NodeFactory) NewImportAttribute(name *ImportAttributeName, value *Expre
data := &ImportAttribute{}
data.name = name
data.Value = value
- return newNode(KindImportAttribute, data, f.hooks)
+ return f.newNode(KindImportAttribute, data)
}
func (f *NodeFactory) UpdateImportAttribute(node *ImportAttribute, name *ImportAttributeName, value *Expression) *Node {
@@ -7272,7 +7295,7 @@ func (f *NodeFactory) NewImportAttributes(token Kind, attributes *NodeList, mult
data.Token = token
data.Attributes = attributes
data.MultiLine = multiLine
- return newNode(KindImportAttributes, data, f.hooks)
+ return f.newNode(KindImportAttributes, data)
}
func (f *NodeFactory) UpdateImportAttributes(node *ImportAttributes, attributes *ImportAttributeList) *Node {
@@ -7314,7 +7337,7 @@ func (f *NodeFactory) NewTypeQueryNode(exprName *EntityName, typeArguments *Node
data := &TypeQueryNode{}
data.ExprName = exprName
data.TypeArguments = typeArguments
- return newNode(KindTypeQuery, data, f.hooks)
+ return f.newNode(KindTypeQuery, data)
}
func (f *NodeFactory) UpdateTypeQueryNode(node *TypeQueryNode, exprName *EntityName, typeArguments *TypeArgumentList) *Node {
@@ -7362,7 +7385,7 @@ func (f *NodeFactory) NewMappedTypeNode(readonlyToken *TokenNode, typeParameter
data.QuestionToken = questionToken
data.Type = typeNode
data.Members = members
- return newNode(KindMappedType, data, f.hooks)
+ return f.newNode(KindMappedType, data)
}
func (f *NodeFactory) UpdateMappedTypeNode(node *MappedTypeNode, readonlyToken *TokenNode, typeParameter *TypeParameterDeclarationNode, nameType *TypeNode, questionToken *TokenNode, typeNode *TypeNode, members *TypeElementList) *Node {
@@ -7400,7 +7423,7 @@ type TypeLiteralNode struct {
func (f *NodeFactory) NewTypeLiteralNode(members *NodeList) *Node {
data := &TypeLiteralNode{}
data.Members = members
- return newNode(KindTypeLiteral, data, f.hooks)
+ return f.newNode(KindTypeLiteral, data)
}
func (f *NodeFactory) UpdateTypeLiteralNode(node *TypeLiteralNode, members *TypeElementList) *Node {
@@ -7436,7 +7459,7 @@ type TupleTypeNode struct {
func (f *NodeFactory) NewTupleTypeNode(elements *NodeList) *Node {
data := &TupleTypeNode{}
data.Elements = elements
- return newNode(KindTupleType, data, f.hooks)
+ return f.newNode(KindTupleType, data)
}
func (f *NodeFactory) UpdateTupleTypeNode(node *TupleTypeNode, elements *TypeList) *Node {
@@ -7479,7 +7502,7 @@ func (f *NodeFactory) NewNamedTupleMember(dotDotDotToken *TokenNode, name *Ident
data.name = name
data.QuestionToken = questionToken
data.Type = typeNode
- return newNode(KindNamedTupleMember, data, f.hooks)
+ return f.newNode(KindNamedTupleMember, data)
}
func (f *NodeFactory) UpdateNamedTupleMember(node *NamedTupleMember, dotDotDotToken *TokenNode, name *IdentifierNode, questionToken *TokenNode, typeNode *TypeNode) *Node {
@@ -7519,7 +7542,7 @@ type OptionalTypeNode struct {
func (f *NodeFactory) NewOptionalTypeNode(typeNode *TypeNode) *Node {
data := &OptionalTypeNode{}
data.Type = typeNode
- return newNode(KindOptionalType, data, f.hooks)
+ return f.newNode(KindOptionalType, data)
}
func (f *NodeFactory) UpdateOptionalTypeNode(node *OptionalTypeNode, typeNode *TypeNode) *Node {
@@ -7555,7 +7578,7 @@ type RestTypeNode struct {
func (f *NodeFactory) NewRestTypeNode(typeNode *TypeNode) *Node {
data := &RestTypeNode{}
data.Type = typeNode
- return newNode(KindRestType, data, f.hooks)
+ return f.newNode(KindRestType, data)
}
func (f *NodeFactory) UpdateRestTypeNode(node *RestTypeNode, typeNode *TypeNode) *Node {
@@ -7591,7 +7614,7 @@ type ParenthesizedTypeNode struct {
func (f *NodeFactory) NewParenthesizedTypeNode(typeNode *TypeNode) *Node {
data := &ParenthesizedTypeNode{}
data.Type = typeNode
- return newNode(KindParenthesizedType, data, f.hooks)
+ return f.newNode(KindParenthesizedType, data)
}
func (f *NodeFactory) UpdateParenthesizedTypeNode(node *ParenthesizedTypeNode, typeNode *TypeNode) *Node {
@@ -7641,7 +7664,7 @@ func (f *NodeFactory) NewFunctionTypeNode(typeParameters *NodeList, parameters *
data.TypeParameters = typeParameters
data.Parameters = parameters
data.Type = returnType
- return newNode(KindFunctionType, data, f.hooks)
+ return f.newNode(KindFunctionType, data)
}
func (f *NodeFactory) UpdateFunctionTypeNode(node *FunctionTypeNode, typeParameters *TypeParameterList, parameters *ParameterList, returnType *TypeNode) *Node {
@@ -7675,7 +7698,7 @@ func (f *NodeFactory) NewConstructorTypeNode(modifiers *ModifierList, typeParame
data.TypeParameters = typeParameters
data.Parameters = parameters
data.Type = returnType
- return newNode(KindConstructorType, data, f.hooks)
+ return f.newNode(KindConstructorType, data)
}
func (f *NodeFactory) UpdateConstructorTypeNode(node *ConstructorTypeNode, modifiers *ModifierList, typeParameters *TypeParameterList, parameters *ParameterList, returnType *TypeNode) *Node {
@@ -7720,7 +7743,8 @@ func (f *NodeFactory) NewTemplateHead(text string, rawText string, templateFlags
data.Text = text
data.RawText = rawText
data.TemplateFlags = templateFlags
- return newNode(KindTemplateHead, data, f.hooks)
+ f.textCount++
+ return f.newNode(KindTemplateHead, data)
}
func (node *TemplateHead) Clone(f *NodeFactory) *Node {
@@ -7739,7 +7763,8 @@ func (f *NodeFactory) NewTemplateMiddle(text string, rawText string, templateFla
data.Text = text
data.RawText = rawText
data.TemplateFlags = templateFlags
- return newNode(KindTemplateMiddle, data, f.hooks)
+ f.textCount++
+ return f.newNode(KindTemplateMiddle, data)
}
func (node *TemplateMiddle) Clone(f *NodeFactory) *Node {
@@ -7758,7 +7783,8 @@ func (f *NodeFactory) NewTemplateTail(text string, rawText string, templateFlags
data.Text = text
data.RawText = rawText
data.TemplateFlags = templateFlags
- return newNode(KindTemplateTail, data, f.hooks)
+ f.textCount++
+ return f.newNode(KindTemplateTail, data)
}
func (node *TemplateTail) Clone(f *NodeFactory) *Node {
@@ -7777,7 +7803,7 @@ func (f *NodeFactory) NewTemplateLiteralTypeNode(head *TemplateHeadNode, templat
data := &TemplateLiteralTypeNode{}
data.Head = head
data.TemplateSpans = templateSpans
- return newNode(KindTemplateLiteralType, data, f.hooks)
+ return f.newNode(KindTemplateLiteralType, data)
}
func (f *NodeFactory) UpdateTemplateLiteralTypeNode(node *TemplateLiteralTypeNode, head *TemplateHeadNode, templateSpans *TemplateLiteralTypeSpanList) *Node {
@@ -7812,7 +7838,7 @@ func (f *NodeFactory) NewTemplateLiteralTypeSpan(typeNode *TypeNode, literal *Te
data := &TemplateLiteralTypeSpan{}
data.Type = typeNode
data.Literal = literal
- return newNode(KindTemplateLiteralTypeSpan, data, f.hooks)
+ return f.newNode(KindTemplateLiteralTypeSpan, data)
}
func (f *NodeFactory) UpdateTemplateLiteralTypeSpan(node *TemplateLiteralTypeSpan, typeNode *TypeNode, literal *TemplateMiddleOrTail) *Node {
@@ -7852,7 +7878,7 @@ func (f *NodeFactory) NewSyntheticExpression(t any, isSpread bool, tupleNameSour
data.Type = t
data.IsSpread = isSpread
data.TupleNameSource = tupleNameSource
- return newNode(KindSyntheticExpression, data, f.hooks)
+ return f.newNode(KindSyntheticExpression, data)
}
func (node *SyntheticExpression) Clone(f *NodeFactory) *Node {
@@ -7922,7 +7948,7 @@ func (f *NodeFactory) NewJsxElement(openingElement *JsxOpeningElementNode, child
data.OpeningElement = openingElement
data.Children = children
data.ClosingElement = closingElement
- return newNode(KindJsxElement, data, f.hooks)
+ return f.newNode(KindJsxElement, data)
}
func (f *NodeFactory) UpdateJsxElement(node *JsxElement, openingElement *JsxOpeningElementNode, children *JsxChildList, closingElement *JsxClosingElementNode) *Node {
@@ -7966,7 +7992,7 @@ type JsxAttributes struct {
func (f *NodeFactory) NewJsxAttributes(properties *NodeList) *Node {
data := &JsxAttributes{}
data.Properties = properties
- return newNode(KindJsxAttributes, data, f.hooks)
+ return f.newNode(KindJsxAttributes, data)
}
func (f *NodeFactory) UpdateJsxAttributes(node *JsxAttributes, properties *JsxAttributeList) *Node {
@@ -8010,7 +8036,7 @@ func (f *NodeFactory) NewJsxNamespacedName(namespace *IdentifierNode, name *Iden
data := &JsxNamespacedName{}
data.Namespace = namespace
data.name = name
- return newNode(KindJsxNamespacedName, data, f.hooks)
+ return f.newNode(KindJsxNamespacedName, data)
}
func (f *NodeFactory) UpdateJsxNamespacedName(node *JsxNamespacedName, name *IdentifierNode, namespace *IdentifierNode) *Node {
@@ -8061,7 +8087,7 @@ func (f *NodeFactory) NewJsxOpeningElement(tagName *JsxTagNameExpression, typeAr
data.TagName = tagName
data.TypeArguments = typeArguments
data.Attributes = attributes
- return newNode(KindJsxOpeningElement, data, f.hooks)
+ return f.newNode(KindJsxOpeningElement, data)
}
func (f *NodeFactory) UpdateJsxOpeningElement(node *JsxOpeningElement, tagName *JsxTagNameExpression, typeArguments *TypeArgumentList, attributes *JsxAttributesNode) *Node {
@@ -8109,7 +8135,7 @@ func (f *NodeFactory) NewJsxSelfClosingElement(tagName *JsxTagNameExpression, ty
data.TagName = tagName
data.TypeArguments = typeArguments
data.Attributes = attributes
- return newNode(KindJsxSelfClosingElement, data, f.hooks)
+ return f.newNode(KindJsxSelfClosingElement, data)
}
func (f *NodeFactory) UpdateJsxSelfClosingElement(node *JsxSelfClosingElement, tagName *JsxTagNameExpression, typeArguments *TypeArgumentList, attributes *JsxAttributesNode) *Node {
@@ -8157,7 +8183,7 @@ func (f *NodeFactory) NewJsxFragment(openingFragment *JsxOpeningFragmentNode, ch
data.OpeningFragment = openingFragment
data.Children = children
data.ClosingFragment = closingFragment
- return newNode(KindJsxFragment, data, f.hooks)
+ return f.newNode(KindJsxFragment, data)
}
func (f *NodeFactory) UpdateJsxFragment(node *JsxFragment, openingFragment *JsxOpeningFragmentNode, children *JsxChildList, closingFragment *JsxClosingFragmentNode) *Node {
@@ -8191,7 +8217,7 @@ type JsxOpeningFragment struct {
}
func (f *NodeFactory) NewJsxOpeningFragment() *Node {
- return newNode(KindJsxOpeningFragment, &JsxOpeningFragment{}, f.hooks)
+ return f.newNode(KindJsxOpeningFragment, &JsxOpeningFragment{})
}
func (node *JsxOpeningFragment) Clone(f *NodeFactory) *Node {
@@ -8213,7 +8239,7 @@ type JsxClosingFragment struct {
}
func (f *NodeFactory) NewJsxClosingFragment() *Node {
- return newNode(KindJsxClosingFragment, &JsxClosingFragment{}, f.hooks)
+ return f.newNode(KindJsxClosingFragment, &JsxClosingFragment{})
}
func (node *JsxClosingFragment) Clone(f *NodeFactory) *Node {
@@ -8238,7 +8264,7 @@ func (f *NodeFactory) NewJsxAttribute(name *JsxAttributeName, initializer *JsxAt
data := &JsxAttribute{}
data.name = name
data.Initializer = initializer
- return newNode(KindJsxAttribute, data, f.hooks)
+ return f.newNode(KindJsxAttribute, data)
}
func (f *NodeFactory) UpdateJsxAttribute(node *JsxAttribute, name *JsxAttributeName, initializer *JsxAttributeValue) *Node {
@@ -8284,7 +8310,7 @@ type JsxSpreadAttribute struct {
func (f *NodeFactory) NewJsxSpreadAttribute(expression *Expression) *Node {
data := &JsxSpreadAttribute{}
data.Expression = expression
- return newNode(KindJsxSpreadAttribute, data, f.hooks)
+ return f.newNode(KindJsxSpreadAttribute, data)
}
func (f *NodeFactory) UpdateJsxSpreadAttribute(node *JsxSpreadAttribute, expression *Expression) *Node {
@@ -8324,7 +8350,7 @@ type JsxClosingElement struct {
func (f *NodeFactory) NewJsxClosingElement(tagName *JsxTagNameExpression) *Node {
data := &JsxClosingElement{}
data.TagName = tagName
- return newNode(KindJsxClosingElement, data, f.hooks)
+ return f.newNode(KindJsxClosingElement, data)
}
func (f *NodeFactory) UpdateJsxClosingElement(node *JsxClosingElement, tagName *JsxTagNameExpression) *Node {
@@ -8366,7 +8392,7 @@ func (f *NodeFactory) NewJsxExpression(dotDotDotToken *TokenNode, expression *Ex
data := &JsxExpression{}
data.DotDotDotToken = dotDotDotToken
data.Expression = expression
- return newNode(KindJsxExpression, data, f.hooks)
+ return f.newNode(KindJsxExpression, data)
}
func (f *NodeFactory) UpdateJsxExpression(node *JsxExpression, dotDotDotToken *TokenNode, expression *Expression) *Node {
@@ -8408,7 +8434,8 @@ func (f *NodeFactory) NewJsxText(text string, containsOnlyTriviaWhiteSpace bool)
data := &JsxText{}
data.Text = text
data.ContainsOnlyTriviaWhiteSpaces = containsOnlyTriviaWhiteSpace
- return newNode(KindJsxText, data, f.hooks)
+ f.textCount++
+ return f.newNode(KindJsxText, data)
}
func (node *JsxText) Clone(f *NodeFactory) *Node {
@@ -8433,7 +8460,7 @@ type SyntaxList struct {
func (f *NodeFactory) NewSyntaxList(children []*Node) *Node {
data := &SyntaxList{}
data.Children = children
- return newNode(KindSyntaxList, data, f.hooks)
+ return f.newNode(KindSyntaxList, data)
}
func (node *SyntaxList) ForEachChild(v Visitor) bool {
@@ -8456,7 +8483,7 @@ func (f *NodeFactory) NewJSDoc(comment *NodeList, tags *NodeList) *Node {
data := f.jsdocPool.New()
data.Comment = comment
data.Tags = tags
- return newNode(KindJSDoc, data, f.hooks)
+ return f.newNode(KindJSDoc, data)
}
func (f *NodeFactory) UpdateJSDoc(node *JSDoc, comment *NodeList, tags *NodeList) *Node {
@@ -8497,7 +8524,8 @@ type JSDocText struct {
func (f *NodeFactory) NewJSDocText(text string) *Node {
data := f.jsdocTextPool.New()
data.Text = text
- return newNode(KindJSDocText, data, f.hooks)
+ f.textCount++
+ return f.newNode(KindJSDocText, data)
}
func (node *JSDocText) Clone(f *NodeFactory) *Node {
@@ -8513,7 +8541,8 @@ func (f *NodeFactory) NewJSDocLink(name *Node, text string) *Node {
data := &JSDocLink{}
data.name = name
data.Text = text
- return newNode(KindJSDocLink, data, f.hooks)
+ f.textCount++
+ return f.newNode(KindJSDocLink, data)
}
func (f *NodeFactory) UpdateJSDocLink(node *JSDocLink, name *Node, text string) *Node {
@@ -8548,7 +8577,8 @@ func (f *NodeFactory) NewJSDocLinkPlain(name *Node, text string) *Node {
data := &JSDocLinkPlain{}
data.name = name
data.Text = text
- return newNode(KindJSDocLinkPlain, data, f.hooks)
+ f.textCount++
+ return f.newNode(KindJSDocLinkPlain, data)
}
func (f *NodeFactory) UpdateJSDocLinkPlain(node *JSDocLinkPlain, name *Node, text string) *Node {
@@ -8583,7 +8613,8 @@ func (f *NodeFactory) NewJSDocLinkCode(name *Node, text string) *Node {
data := &JSDocLinkCode{}
data.name = name
data.Text = text
- return newNode(KindJSDocLinkCode, data, f.hooks)
+ f.textCount++
+ return f.newNode(KindJSDocLinkCode, data)
}
func (f *NodeFactory) UpdateJSDocLinkCode(node *JSDocLinkCode, name *Node, text string) *Node {
@@ -8620,7 +8651,7 @@ type JSDocTypeExpression struct {
func (f *NodeFactory) NewJSDocTypeExpression(typeNode *TypeNode) *Node {
data := &JSDocTypeExpression{}
data.Type = typeNode
- return newNode(KindJSDocTypeExpression, data, f.hooks)
+ return f.newNode(KindJSDocTypeExpression, data)
}
func (f *NodeFactory) UpdateJSDocTypeExpression(node *JSDocTypeExpression, typeNode *TypeNode) *Node {
@@ -8652,7 +8683,7 @@ type JSDocNonNullableType struct {
func (f *NodeFactory) NewJSDocNonNullableType(typeNode *TypeNode) *Node {
data := &JSDocNonNullableType{}
data.Type = typeNode
- return newNode(KindJSDocNonNullableType, data, f.hooks)
+ return f.newNode(KindJSDocNonNullableType, data)
}
func (f *NodeFactory) UpdateJSDocNonNullableType(node *JSDocNonNullableType, typeNode *TypeNode) *Node {
@@ -8684,7 +8715,7 @@ type JSDocNullableType struct {
func (f *NodeFactory) NewJSDocNullableType(typeNode *TypeNode) *Node {
data := &JSDocNullableType{}
data.Type = typeNode
- return newNode(KindJSDocNullableType, data, f.hooks)
+ return f.newNode(KindJSDocNullableType, data)
}
func (f *NodeFactory) UpdateJSDocNullableType(node *JSDocNullableType, typeNode *TypeNode) *Node {
@@ -8714,7 +8745,7 @@ type JSDocAllType struct {
func (f *NodeFactory) NewJSDocAllType() *Node {
data := &JSDocAllType{}
- return newNode(KindJSDocAllType, data, f.hooks)
+ return f.newNode(KindJSDocAllType, data)
}
func (node *JSDocAllType) Clone(f *NodeFactory) *Node {
@@ -8731,7 +8762,7 @@ type JSDocVariadicType struct {
func (f *NodeFactory) NewJSDocVariadicType(typeNode *TypeNode) *Node {
data := &JSDocVariadicType{}
data.Type = typeNode
- return newNode(KindJSDocVariadicType, data, f.hooks)
+ return f.newNode(KindJSDocVariadicType, data)
}
func (f *NodeFactory) UpdateJSDocVariadicType(node *JSDocVariadicType, typeNode *TypeNode) *Node {
@@ -8763,7 +8794,7 @@ type JSDocOptionalType struct {
func (f *NodeFactory) NewJSDocOptionalType(typeNode *TypeNode) *Node {
data := &JSDocOptionalType{}
data.Type = typeNode
- return newNode(KindJSDocOptionalType, data, f.hooks)
+ return f.newNode(KindJSDocOptionalType, data)
}
func (f *NodeFactory) UpdateJSDocOptionalType(node *JSDocOptionalType, typeNode *TypeNode) *Node {
@@ -8797,7 +8828,7 @@ func (f *NodeFactory) NewJSDocTypeTag(tagName *IdentifierNode, typeExpression *N
data.TagName = tagName
data.TypeExpression = typeExpression
data.Comment = comment
- return newNode(KindJSDocTypeTag, data, f.hooks)
+ return f.newNode(KindJSDocTypeTag, data)
}
func (f *NodeFactory) UpdateJSDocTypeTag(node *JSDocTypeTag, tagName *IdentifierNode, typeExpression *TypeNode, comment *NodeList) *Node {
@@ -8832,7 +8863,7 @@ func (f *NodeFactory) NewJSDocUnknownTag(tagName *IdentifierNode, comment *NodeL
data := &JSDocUnknownTag{}
data.TagName = tagName
data.Comment = comment
- return newNode(KindJSDocTag, data, f.hooks)
+ return f.newNode(KindJSDocTag, data)
}
func (f *NodeFactory) UpdateJSDocUnknownTag(node *JSDocUnknownTag, tagName *IdentifierNode, comment *NodeList) *Node {
@@ -8871,7 +8902,7 @@ func (f *NodeFactory) NewJSDocTemplateTag(tagName *IdentifierNode, constraint *N
data.Constraint = constraint
data.typeParameters = typeParameters
data.Comment = comment
- return newNode(KindJSDocTemplateTag, data, f.hooks)
+ return f.newNode(KindJSDocTemplateTag, data)
}
func (f *NodeFactory) UpdateJSDocTemplateTag(node *JSDocTemplateTag, tagName *IdentifierNode, constraint *Node, typeParameters *TypeParameterList, comment *NodeList) *Node {
@@ -8912,7 +8943,7 @@ func (f *NodeFactory) NewJSDocPropertyTag(tagName *IdentifierNode, name *EntityN
data.TypeExpression = typeExpression
data.IsNameFirst = isNameFirst
data.Comment = comment
- return newNode(KindJSDocPropertyTag, data, f.hooks)
+ return f.newNode(KindJSDocPropertyTag, data)
}
func (f *NodeFactory) UpdateJSDocPropertyTag(node *JSDocPropertyTag, tagName *IdentifierNode, name *EntityName, isBracketed bool, typeExpression *TypeNode, isNameFirst bool, comment *NodeList) *Node {
@@ -8964,7 +8995,7 @@ func (f *NodeFactory) NewJSDocParameterTag(tagName *IdentifierNode, name *Entity
data.TypeExpression = typeExpression
data.IsNameFirst = isNameFirst
data.Comment = comment
- return newNode(KindJSDocParameterTag, data, f.hooks)
+ return f.newNode(KindJSDocParameterTag, data)
}
func (f *NodeFactory) UpdateJSDocParameterTag(node *JSDocParameterTag, tagName *IdentifierNode, name *EntityName, isBracketed bool, typeExpression *TypeNode, isNameFirst bool, comment *NodeList) *Node {
@@ -9013,7 +9044,7 @@ func (f *NodeFactory) NewJSDocReturnTag(tagName *IdentifierNode, typeExpression
data.TagName = tagName
data.TypeExpression = typeExpression
data.Comment = comment
- return newNode(KindJSDocReturnTag, data, f.hooks)
+ return f.newNode(KindJSDocReturnTag, data)
}
func (f *NodeFactory) UpdateJSDocReturnTag(node *JSDocReturnTag, tagName *IdentifierNode, typeExpression *TypeNode, comment *NodeList) *Node {
@@ -9048,7 +9079,7 @@ func (f *NodeFactory) NewJSDocPublicTag(tagName *IdentifierNode, comment *NodeLi
data := &JSDocPublicTag{}
data.TagName = tagName
data.Comment = comment
- return newNode(KindJSDocPublicTag, data, f.hooks)
+ return f.newNode(KindJSDocPublicTag, data)
}
func (f *NodeFactory) UpdateJSDocPublicTag(node *JSDocPublicTag, tagName *IdentifierNode, comment *NodeList) *Node {
@@ -9079,7 +9110,7 @@ func (f *NodeFactory) NewJSDocPrivateTag(tagName *IdentifierNode, comment *NodeL
data := &JSDocPrivateTag{}
data.TagName = tagName
data.Comment = comment
- return newNode(KindJSDocPrivateTag, data, f.hooks)
+ return f.newNode(KindJSDocPrivateTag, data)
}
func (f *NodeFactory) UpdateJSDocPrivateTag(node *JSDocPrivateTag, tagName *IdentifierNode, comment *NodeList) *Node {
@@ -9110,7 +9141,7 @@ func (f *NodeFactory) NewJSDocProtectedTag(tagName *IdentifierNode, comment *Nod
data := &JSDocProtectedTag{}
data.TagName = tagName
data.Comment = comment
- return newNode(KindJSDocProtectedTag, data, f.hooks)
+ return f.newNode(KindJSDocProtectedTag, data)
}
func (f *NodeFactory) UpdateJSDocProtectedTag(node *JSDocProtectedTag, tagName *IdentifierNode, comment *NodeList) *Node {
@@ -9141,7 +9172,7 @@ func (f *NodeFactory) NewJSDocReadonlyTag(tagName *IdentifierNode, comment *Node
data := &JSDocReadonlyTag{}
data.TagName = tagName
data.Comment = comment
- return newNode(KindJSDocReadonlyTag, data, f.hooks)
+ return f.newNode(KindJSDocReadonlyTag, data)
}
func (f *NodeFactory) UpdateJSDocReadonlyTag(node *JSDocReadonlyTag, tagName *IdentifierNode, comment *NodeList) *Node {
@@ -9172,7 +9203,7 @@ func (f *NodeFactory) NewJSDocOverrideTag(tagName *IdentifierNode, comment *Node
data := &JSDocOverrideTag{}
data.TagName = tagName
data.Comment = comment
- return newNode(KindJSDocOverrideTag, data, f.hooks)
+ return f.newNode(KindJSDocOverrideTag, data)
}
func (f *NodeFactory) UpdateJSDocOverrideTag(node *JSDocOverrideTag, tagName *IdentifierNode, comment *NodeList) *Node {
@@ -9203,7 +9234,7 @@ func (f *NodeFactory) NewJSDocDeprecatedTag(tagName *IdentifierNode, comment *No
data := &JSDocDeprecatedTag{}
data.TagName = tagName
data.Comment = comment
- return newNode(KindJSDocDeprecatedTag, data, f.hooks)
+ return f.newNode(KindJSDocDeprecatedTag, data)
}
func (f *NodeFactory) UpdateJSDocDeprecatedTag(node *JSDocDeprecatedTag, tagName *IdentifierNode, comment *NodeList) *Node {
@@ -9240,7 +9271,7 @@ func (f *NodeFactory) NewJSDocSeeTag(tagName *IdentifierNode, nameExpression *Ty
data.TagName = tagName
data.NameExpression = nameExpression
data.Comment = comment
- return newNode(KindJSDocSeeTag, data, f.hooks)
+ return f.newNode(KindJSDocSeeTag, data)
}
func (f *NodeFactory) UpdateJSDocSeeTag(node *JSDocSeeTag, tagName *IdentifierNode, nameExpression *TypeNode, comment *NodeList) *Node {
@@ -9273,7 +9304,7 @@ func (f *NodeFactory) NewJSDocImplementsTag(tagName *IdentifierNode, className *
data.TagName = tagName
data.ClassName = className
data.Comment = comment
- return newNode(KindJSDocImplementsTag, data, f.hooks)
+ return f.newNode(KindJSDocImplementsTag, data)
}
func (f *NodeFactory) UpdateJSDocImplementsTag(node *JSDocImplementsTag, tagName *IdentifierNode, className *Expression, comment *NodeList) *Node {
@@ -9306,7 +9337,7 @@ func (f *NodeFactory) NewJSDocAugmentsTag(tagName *IdentifierNode, className *Ex
data.TagName = tagName
data.ClassName = className
data.Comment = comment
- return newNode(KindJSDocAugmentsTag, data, f.hooks)
+ return f.newNode(KindJSDocAugmentsTag, data)
}
func (f *NodeFactory) UpdateJSDocAugmentsTag(node *JSDocAugmentsTag, tagName *IdentifierNode, className *Expression, comment *NodeList) *Node {
@@ -9339,7 +9370,7 @@ func (f *NodeFactory) NewJSDocSatisfiesTag(tagName *IdentifierNode, typeExpressi
data.TagName = tagName
data.TypeExpression = typeExpression
data.Comment = comment
- return newNode(KindJSDocSatisfiesTag, data, f.hooks)
+ return f.newNode(KindJSDocSatisfiesTag, data)
}
func (f *NodeFactory) UpdateJSDocSatisfiesTag(node *JSDocSatisfiesTag, tagName *IdentifierNode, typeExpression *TypeNode, comment *NodeList) *Node {
@@ -9372,7 +9403,7 @@ func (f *NodeFactory) NewJSDocThisTag(tagName *IdentifierNode, typeExpression *T
data.TagName = tagName
data.TypeExpression = typeExpression
data.Comment = comment
- return newNode(KindJSDocThisTag, data, f.hooks)
+ return f.newNode(KindJSDocThisTag, data)
}
func (f *NodeFactory) UpdateJSDocThisTag(node *JSDocThisTag, tagName *IdentifierNode, typeExpression *TypeNode, comment *NodeList) *Node {
@@ -9409,7 +9440,7 @@ func (f *NodeFactory) NewJSDocImportTag(tagName *IdentifierNode, importClause *D
data.ModuleSpecifier = moduleSpecifier
data.Attributes = attributes
data.Comment = comment
- return newNode(KindJSDocImportTag, data, f.hooks)
+ return f.newNode(KindJSDocImportTag, data)
}
func (f *NodeFactory) UpdateJSDocImportTag(node *JSDocImportTag, tagName *IdentifierNode, importClause *Declaration, moduleSpecifier *Node, attributes *Node, comment *NodeList) *Node {
@@ -9444,7 +9475,7 @@ func (f *NodeFactory) NewJSDocCallbackTag(tagName *IdentifierNode, typeExpressio
data.FullName = fullName
data.TypeExpression = typeExpression
data.Comment = comment
- return newNode(KindJSDocCallbackTag, data, f.hooks)
+ return f.newNode(KindJSDocCallbackTag, data)
}
func (f *NodeFactory) UpdateJSDocCallbackTag(node *JSDocCallbackTag, tagName *IdentifierNode, typeExpression *TypeNode, fullName *Node, comment *NodeList) *Node {
@@ -9477,7 +9508,7 @@ func (f *NodeFactory) NewJSDocOverloadTag(tagName *IdentifierNode, typeExpressio
data.TagName = tagName
data.TypeExpression = typeExpression
data.Comment = comment
- return newNode(KindJSDocOverloadTag, data, f.hooks)
+ return f.newNode(KindJSDocOverloadTag, data)
}
func (f *NodeFactory) UpdateJSDocOverloadTag(node *JSDocOverloadTag, tagName *IdentifierNode, typeExpression *TypeNode, comment *NodeList) *Node {
@@ -9512,7 +9543,7 @@ func (f *NodeFactory) NewJSDocTypedefTag(tagName *IdentifierNode, typeExpression
data.TypeExpression = typeExpression
data.name = name
data.Comment = comment
- return newNode(KindJSDocTypedefTag, data, f.hooks)
+ return f.newNode(KindJSDocTypedefTag, data)
}
func (f *NodeFactory) UpdateJSDocTypedefTag(node *JSDocTypedefTag, tagName *IdentifierNode, typeExpression *Node, fullName *IdentifierNode, comment *NodeList) *Node {
@@ -9551,7 +9582,7 @@ func (f *NodeFactory) NewJSDocTypeLiteral(jsdocPropertyTags []*Node, isArrayType
data := &JSDocTypeLiteral{}
data.JSDocPropertyTags = jsdocPropertyTags
data.IsArrayType = isArrayType
- return newNode(KindJSDocTypeLiteral, data, f.hooks)
+ return f.newNode(KindJSDocTypeLiteral, data)
}
func (f *NodeFactory) UpdateJSDocTypeLiteral(node *JSDocTypeLiteral, jsdocPropertyTags []*Node, isArrayType bool) *Node {
@@ -9587,7 +9618,7 @@ func (f *NodeFactory) NewJSDocSignature(typeParameters *TypeParameterList, param
data.typeParameters = typeParameters
data.Parameters = parameters
data.Type = typeNode
- return newNode(KindJSDocSignature, data, f.hooks)
+ return f.newNode(KindJSDocSignature, data)
}
func (f *NodeFactory) UpdateJSDocSignature(node *JSDocSignature, typeParameters *TypeParameterList, parameters *NodeList, typeNode *JSDocTag) *Node {
@@ -9620,7 +9651,7 @@ type JSDocNameReference struct {
func (f *NodeFactory) NewJSDocNameReference(name *EntityName) *Node {
data := &JSDocNameReference{}
data.name = name
- return newNode(KindJSDocNameReference, data, f.hooks)
+ return f.newNode(KindJSDocNameReference, data)
}
func (f *NodeFactory) UpdateJSDocNameReference(node *JSDocNameReference, name *EntityName) *Node {
@@ -9711,6 +9742,8 @@ type SourceFile struct {
TypeReferenceDirectives []*FileReference
LibReferenceDirectives []*FileReference
CheckJsDirective *CheckJsDirective
+ NodeCount int
+ TextCount int
// Fields set by binder
@@ -9755,7 +9788,7 @@ func (f *NodeFactory) NewSourceFile(text string, fileName string, path tspath.Pa
data.path = path
data.Statements = statements
data.LanguageVersion = core.ScriptTargetLatest
- return newNode(KindSourceFile, data, f.hooks)
+ return f.newNode(KindSourceFile, data)
}
func (node *SourceFile) Text() string {
diff --git a/internal/ast/utilities.go b/internal/ast/utilities.go
index 30a4d350b2..4f690c9490 100644
--- a/internal/ast/utilities.go
+++ b/internal/ast/utilities.go
@@ -908,6 +908,17 @@ func FindAncestor(node *Node, callback func(*Node) bool) *Node {
return nil
}
+// Walks up the parents of a node to find the ancestor that matches the kind
+func FindAncestorKind(node *Node, kind Kind) *Node {
+ for node != nil {
+ if node.Kind == kind {
+ return node
+ }
+ node = node.Parent
+ }
+ return nil
+}
+
type FindAncestorResult int32
const (
diff --git a/internal/checker/types.go b/internal/checker/types.go
index fa77c35cce..a99e7f7c43 100644
--- a/internal/checker/types.go
+++ b/internal/checker/types.go
@@ -538,6 +538,14 @@ type Type struct {
data TypeData // Type specific data
}
+func (t *Type) Id() TypeId {
+ return t.id
+}
+
+func (t *Type) Flags() TypeFlags {
+ return t.flags
+}
+
// Casts for concrete struct types
func (t *Type) AsIntrinsicType() *IntrinsicType { return t.data.(*IntrinsicType) }
diff --git a/internal/core/core.go b/internal/core/core.go
index 53ce832db7..5456fb3077 100644
--- a/internal/core/core.go
+++ b/internal/core/core.go
@@ -58,6 +58,21 @@ func Map[T, U any](slice []T, f func(T) U) []U {
return result
}
+func TryMap[T, U any](slice []T, f func(T) (U, error)) ([]U, error) {
+ if len(slice) == 0 {
+ return nil, nil
+ }
+ result := make([]U, len(slice))
+ for i, value := range slice {
+ mapped, err := f(value)
+ if err != nil {
+ return nil, err
+ }
+ result[i] = mapped
+ }
+ return result, nil
+}
+
func MapIndex[T, U any](slice []T, f func(T, int) U) []U {
if slice == nil {
return nil
diff --git a/internal/ls/api.go b/internal/ls/api.go
new file mode 100644
index 0000000000..62fd233a6f
--- /dev/null
+++ b/internal/ls/api.go
@@ -0,0 +1,39 @@
+package ls
+
+import (
+ "errors"
+ "fmt"
+
+ "github.com/microsoft/typescript-go/internal/ast"
+ "github.com/microsoft/typescript-go/internal/astnav"
+ "github.com/microsoft/typescript-go/internal/checker"
+)
+
+var (
+ ErrNoSourceFile = errors.New("source file not found")
+ ErrNoTokenAtPosition = errors.New("no token found at position")
+)
+
+func (l *LanguageService) GetSymbolAtPosition(fileName string, position int) (*ast.Symbol, error) {
+ program, file := l.tryGetProgramAndFile(fileName)
+ if file == nil {
+ return nil, fmt.Errorf("%w: %s", ErrNoSourceFile, fileName)
+ }
+ node := astnav.GetTokenAtPosition(file, position)
+ if node == nil {
+ return nil, fmt.Errorf("%w: %s:%d", ErrNoTokenAtPosition, fileName, position)
+ }
+ checker := program.GetTypeChecker()
+ return checker.GetSymbolAtLocation(node), nil
+}
+
+func (l *LanguageService) GetSymbolAtLocation(node *ast.Node) *ast.Symbol {
+ program := l.GetProgram()
+ checker := program.GetTypeChecker()
+ return checker.GetSymbolAtLocation(node)
+}
+
+func (l *LanguageService) GetTypeOfSymbol(symbol *ast.Symbol) *checker.Type {
+ checker := l.GetProgram().GetTypeChecker()
+ return checker.GetTypeOfSymbolAtLocation(symbol, nil)
+}
diff --git a/internal/ls/languageservice.go b/internal/ls/languageservice.go
index c3401c5f96..60f0b830a1 100644
--- a/internal/ls/languageservice.go
+++ b/internal/ls/languageservice.go
@@ -57,9 +57,14 @@ func (l *LanguageService) GetProgram() *compiler.Program {
return l.host.GetProgram()
}
-func (l *LanguageService) getProgramAndFile(fileName string) (*compiler.Program, *ast.SourceFile) {
+func (l *LanguageService) tryGetProgramAndFile(fileName string) (*compiler.Program, *ast.SourceFile) {
program := l.GetProgram()
file := program.GetSourceFile(fileName)
+ return program, file
+}
+
+func (l *LanguageService) getProgramAndFile(fileName string) (*compiler.Program, *ast.SourceFile) {
+ program, file := l.tryGetProgramAndFile(fileName)
if file == nil {
panic("file not found")
}
diff --git a/internal/lsp/lsproto/jsonrpc.go b/internal/lsp/lsproto/jsonrpc.go
index 952a3635b9..0af3ac6cf1 100644
--- a/internal/lsp/lsproto/jsonrpc.go
+++ b/internal/lsp/lsproto/jsonrpc.go
@@ -4,6 +4,7 @@ import (
"encoding/json"
"errors"
"fmt"
+ "strings"
)
type JSONRPCVersion struct{}
@@ -43,6 +44,13 @@ func (id *ID) UnmarshalJSON(data []byte) error {
return json.Unmarshal(data, &id.int)
}
+func (id *ID) MustInt() int32 {
+ if id.str != "" {
+ panic("ID is not an integer")
+ }
+ return id.int
+}
+
// TODO(jakebailey): NotificationMessage? Use RequestMessage without ID?
type RequestMessage struct {
@@ -70,6 +78,11 @@ func (r *RequestMessage) UnmarshalJSON(data []byte) error {
return nil
}
+ if strings.HasPrefix(string(r.Method), "@ts/") {
+ r.Params = raw.Params
+ return nil
+ }
+
var params any
var err error
diff --git a/internal/lsp/server.go b/internal/lsp/server.go
index 7118c8b208..dedd8862ed 100644
--- a/internal/lsp/server.go
+++ b/internal/lsp/server.go
@@ -255,11 +255,10 @@ func (s *Server) handleInitialize(req *lsproto.RequestMessage) error {
}
func (s *Server) handleInitialized(req *lsproto.RequestMessage) error {
- s.logger = project.NewLogger([]io.Writer{s.stderr}, project.LogLevelVerbose)
+ s.logger = project.NewLogger([]io.Writer{s.stderr}, "" /*file*/, project.LogLevelVerbose)
s.projectService = project.NewService(s, project.ServiceOptions{
- DefaultLibraryPath: s.defaultLibraryPath,
- Logger: s.logger,
- PositionEncoding: s.positionEncoding,
+ Logger: s.logger,
+ PositionEncoding: s.positionEncoding,
})
s.converters = ls.NewConverters(s.positionEncoding, func(fileName string) ls.ScriptInfo {
diff --git a/internal/parser/parser.go b/internal/parser/parser.go
index 8950bbdf01..5c095b739f 100644
--- a/internal/parser/parser.go
+++ b/internal/parser/parser.go
@@ -352,6 +352,8 @@ func (p *Parser) finishSourceFile(result *ast.SourceFile, isDeclarationFile bool
result.ScriptKind = p.scriptKind
result.Flags |= p.sourceFlags
result.Identifiers = p.identifiers
+ result.NodeCount = p.factory.NodeCount()
+ result.TextCount = p.factory.TextCount()
result.IdentifierCount = p.identifierCount
result.SetJSDocCache(p.jsdocCache)
p.jsdocCache = nil
diff --git a/internal/project/documentregistry.go b/internal/project/documentregistry.go
index f8d86693d8..f4a651e48c 100644
--- a/internal/project/documentregistry.go
+++ b/internal/project/documentregistry.go
@@ -31,20 +31,19 @@ type registryEntry struct {
mu sync.Mutex
}
+type DocumentRegistryHooks struct {
+ OnReleaseDocument func(file *ast.SourceFile)
+}
+
// The document registry represents a store of SourceFile objects that can be shared between
// multiple LanguageService instances.
-type documentRegistry struct {
- options tspath.ComparePathsOptions
+type DocumentRegistry struct {
+ Options tspath.ComparePathsOptions
+ Hooks DocumentRegistryHooks
documents collections.SyncMap[registryKey, *registryEntry]
}
-func newDocumentRegistry(options tspath.ComparePathsOptions) *documentRegistry {
- return &documentRegistry{
- options: options,
- }
-}
-
-// acquireDocument gets a SourceFile from the registry if it exists as the same version tracked
+// AcquireDocument gets a SourceFile from the registry if it exists as the same version tracked
// by the ScriptInfo. If it does not exist, or is out of date, it creates a new SourceFile and
// stores it, tracking that the caller has referenced it. If an oldSourceFile is passed, the registry
// will decrement its reference count and remove it from the registry if the count reaches 0.
@@ -55,7 +54,7 @@ func newDocumentRegistry(options tspath.ComparePathsOptions) *documentRegistry {
// LanguageService instance over time, as well as across multiple instances. Here, we still
// reuse files across multiple LanguageServices, but we only reuse them across Program updates
// when the files haven't changed.
-func (r *documentRegistry) acquireDocument(scriptInfo *ScriptInfo, compilerOptions *core.CompilerOptions, oldSourceFile *ast.SourceFile, oldCompilerOptions *core.CompilerOptions) *ast.SourceFile {
+func (r *DocumentRegistry) AcquireDocument(scriptInfo *ScriptInfo, compilerOptions *core.CompilerOptions, oldSourceFile *ast.SourceFile, oldCompilerOptions *core.CompilerOptions) *ast.SourceFile {
key := newRegistryKey(compilerOptions, scriptInfo.path, scriptInfo.scriptKind)
document := r.getDocumentWorker(scriptInfo, compilerOptions, key)
if oldSourceFile != nil && oldCompilerOptions != nil {
@@ -65,23 +64,26 @@ func (r *documentRegistry) acquireDocument(scriptInfo *ScriptInfo, compilerOptio
return document
}
-func (r *documentRegistry) releaseDocument(file *ast.SourceFile, compilerOptions *core.CompilerOptions) {
+func (r *DocumentRegistry) ReleaseDocument(file *ast.SourceFile, compilerOptions *core.CompilerOptions) {
key := newRegistryKey(compilerOptions, file.Path(), file.ScriptKind)
r.releaseDocumentWithKey(key)
}
-func (r *documentRegistry) releaseDocumentWithKey(key registryKey) {
+func (r *DocumentRegistry) releaseDocumentWithKey(key registryKey) {
if entry, ok := r.documents.Load(key); ok {
entry.mu.Lock()
defer entry.mu.Unlock()
entry.refCount--
if entry.refCount == 0 {
r.documents.Delete(key)
+ if r.Hooks.OnReleaseDocument != nil {
+ r.Hooks.OnReleaseDocument(entry.sourceFile)
+ }
}
}
}
-func (r *documentRegistry) getDocumentWorker(
+func (r *DocumentRegistry) getDocumentWorker(
scriptInfo *ScriptInfo,
compilerOptions *core.CompilerOptions,
key registryKey,
@@ -115,6 +117,6 @@ func (r *documentRegistry) getDocumentWorker(
}
// size should only be used for testing.
-func (r *documentRegistry) size() int {
+func (r *DocumentRegistry) size() int {
return r.documents.Size()
}
diff --git a/internal/project/logger.go b/internal/project/logger.go
index 2269586926..cc2db1c8bd 100644
--- a/internal/project/logger.go
+++ b/internal/project/logger.go
@@ -4,6 +4,7 @@ import (
"bufio"
"fmt"
"io"
+ "os"
"strings"
"time"
)
@@ -18,18 +19,38 @@ const (
)
type Logger struct {
- outputs []*bufio.Writer
- level LogLevel
- inGroup bool
- seq int
+ outputs []*bufio.Writer
+ fileHandle *os.File
+ level LogLevel
+ inGroup bool
+ seq int
}
-func NewLogger(outputs []io.Writer, level LogLevel) *Logger {
+func NewLogger(outputs []io.Writer, file string, level LogLevel) *Logger {
var o []*bufio.Writer
for _, w := range outputs {
o = append(o, bufio.NewWriter(w))
}
- return &Logger{outputs: o, level: level}
+ logger := &Logger{outputs: o, level: level}
+ logger.SetFile(file)
+ return logger
+}
+
+func (l *Logger) SetFile(file string) {
+ if l.fileHandle != nil {
+ oldWriter := l.outputs[len(l.outputs)-1]
+ l.outputs = l.outputs[:len(l.outputs)-1]
+ _ = oldWriter.Flush()
+ l.fileHandle.Close()
+ }
+ if file != "" {
+ f, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0o666)
+ if err != nil {
+ panic(err)
+ }
+ l.fileHandle = f
+ l.outputs = append(l.outputs, bufio.NewWriter(f))
+ }
}
func (l *Logger) PerfTrace(s string) {
@@ -45,22 +66,43 @@ func (l *Logger) Error(s string) {
}
func (l *Logger) StartGroup() {
+ if l == nil {
+ return
+ }
l.inGroup = true
}
func (l *Logger) EndGroup() {
+ if l == nil {
+ return
+ }
l.inGroup = false
}
func (l *Logger) LoggingEnabled() bool {
- return len(l.outputs) > 0
+ return l != nil && len(l.outputs) > 0
}
func (l *Logger) HasLevel(level LogLevel) bool {
- return l.LoggingEnabled() && l.level >= level
+ return l != nil && l.LoggingEnabled() && l.level >= level
+}
+
+func (l *Logger) Close() {
+ if l == nil {
+ return
+ }
+ for _, output := range l.outputs {
+ _ = output.Flush()
+ }
+ if l.fileHandle != nil {
+ _ = l.fileHandle.Close()
+ }
}
func (l *Logger) msg(s string, messageType string) {
+ if l == nil {
+ return
+ }
for _, output := range l.outputs {
header := fmt.Sprintf("%s %d", messageType, l.seq)
output.WriteString(header) //nolint: errcheck
diff --git a/internal/project/project.go b/internal/project/project.go
index 14bd41d354..3aa4e4751e 100644
--- a/internal/project/project.go
+++ b/internal/project/project.go
@@ -11,6 +11,7 @@ import (
"github.com/microsoft/typescript-go/internal/core"
"github.com/microsoft/typescript-go/internal/ls"
"github.com/microsoft/typescript-go/internal/lsp/lsproto"
+ "github.com/microsoft/typescript-go/internal/tsoptions"
"github.com/microsoft/typescript-go/internal/tspath"
"github.com/microsoft/typescript-go/internal/vfs"
)
@@ -30,9 +31,21 @@ const (
KindAuxiliary
)
+type ProjectHost interface {
+ tsoptions.ParseConfigHost
+ NewLine() string
+ DefaultLibraryPath() string
+ DocumentRegistry() *DocumentRegistry
+ GetScriptInfoByPath(path tspath.Path) *ScriptInfo
+ GetOrCreateScriptInfoForFile(fileName string, path tspath.Path, scriptKind core.ScriptKind) *ScriptInfo
+ OnDiscoveredSymlink(info *ScriptInfo)
+ Log(s string)
+ PositionEncoding() lsproto.PositionEncodingKind
+}
+
type Project struct {
- projectService *Service
- mu sync.Mutex
+ host ProjectHost
+ mu sync.Mutex
name string
kind Kind
@@ -59,25 +72,25 @@ type Project struct {
program *compiler.Program
}
-func NewConfiguredProject(configFileName string, configFilePath tspath.Path, projectService *Service) *Project {
- project := NewProject(configFileName, KindConfigured, tspath.GetDirectoryPath(configFileName), projectService)
+func NewConfiguredProject(configFileName string, configFilePath tspath.Path, host ProjectHost) *Project {
+ project := NewProject(configFileName, KindConfigured, tspath.GetDirectoryPath(configFileName), host)
project.configFileName = configFileName
project.configFilePath = configFilePath
project.initialLoadPending = true
return project
}
-func NewInferredProject(compilerOptions *core.CompilerOptions, currentDirectory string, projectRootPath tspath.Path, projectService *Service) *Project {
- project := NewProject(projectNamer.next("/dev/null/inferredProject"), KindInferred, currentDirectory, projectService)
+func NewInferredProject(compilerOptions *core.CompilerOptions, currentDirectory string, projectRootPath tspath.Path, host ProjectHost) *Project {
+ project := NewProject(projectNamer.next("/dev/null/inferredProject"), KindInferred, currentDirectory, host)
project.rootPath = projectRootPath
project.compilerOptions = compilerOptions
return project
}
-func NewProject(name string, kind Kind, currentDirectory string, projectService *Service) *Project {
- projectService.log(fmt.Sprintf("Creating %sProject: %s, currentDirectory: %s", kind.String(), name, currentDirectory))
+func NewProject(name string, kind Kind, currentDirectory string, host ProjectHost) *Project {
+ host.Log(fmt.Sprintf("Creating %sProject: %s, currentDirectory: %s", kind.String(), name, currentDirectory))
project := &Project{
- projectService: projectService,
+ host: host,
name: name,
kind: kind,
currentDirectory: currentDirectory,
@@ -90,12 +103,12 @@ func NewProject(name string, kind Kind, currentDirectory string, projectService
// FS implements LanguageServiceHost.
func (p *Project) FS() vfs.FS {
- return p.projectService.host.FS()
+ return p.host.FS()
}
// DefaultLibraryPath implements LanguageServiceHost.
func (p *Project) DefaultLibraryPath() string {
- return p.projectService.host.DefaultLibraryPath()
+ return p.host.DefaultLibraryPath()
}
// GetCompilerOptions implements LanguageServiceHost.
@@ -117,7 +130,7 @@ func (p *Project) GetProjectVersion() int {
func (p *Project) GetRootFileNames() []string {
fileNames := make([]string, 0, p.rootFileNames.Size())
for path, fileName := range p.rootFileNames.Entries() {
- if p.projectService.getScriptInfo(path) != nil {
+ if p.host.GetScriptInfoByPath(path) != nil {
fileNames = append(fileNames, fileName)
}
}
@@ -136,7 +149,7 @@ func (p *Project) GetSourceFile(fileName string, path tspath.Path, languageVersi
oldSourceFile = p.program.GetSourceFileByPath(scriptInfo.path)
oldCompilerOptions = p.program.GetCompilerOptions()
}
- return p.projectService.documentRegistry.acquireDocument(scriptInfo, p.GetCompilerOptions(), oldSourceFile, oldCompilerOptions)
+ return p.host.DocumentRegistry().AcquireDocument(scriptInfo, p.GetCompilerOptions(), oldSourceFile, oldCompilerOptions)
}
return nil
}
@@ -149,7 +162,7 @@ func (p *Project) GetProgram() *compiler.Program {
// NewLine implements LanguageServiceHost.
func (p *Project) NewLine() string {
- return p.projectService.host.NewLine()
+ return p.host.NewLine()
}
// Trace implements LanguageServiceHost.
@@ -159,17 +172,17 @@ func (p *Project) Trace(msg string) {
// GetDefaultLibraryPath implements ls.Host.
func (p *Project) GetDefaultLibraryPath() string {
- return p.projectService.options.DefaultLibraryPath
+ return p.host.DefaultLibraryPath()
}
// GetScriptInfo implements ls.Host.
func (p *Project) GetScriptInfo(fileName string) ls.ScriptInfo {
- return p.projectService.GetScriptInfo(fileName)
+ return p.host.GetScriptInfoByPath(p.toPath(fileName))
}
// GetPositionEncoding implements ls.Host.
func (p *Project) GetPositionEncoding() lsproto.PositionEncodingKind {
- return p.projectService.options.PositionEncoding
+ return p.host.PositionEncoding()
}
func (p *Project) Name() string {
@@ -180,6 +193,10 @@ func (p *Project) Kind() Kind {
return p.kind
}
+func (p *Project) Version() int {
+ return p.version
+}
+
func (p *Project) CurrentProgram() *compiler.Program {
return p.program
}
@@ -189,7 +206,7 @@ func (p *Project) LanguageService() *ls.LanguageService {
}
func (p *Project) getOrCreateScriptInfoAndAttachToProject(fileName string, scriptKind core.ScriptKind) *ScriptInfo {
- if scriptInfo := p.projectService.getOrCreateScriptInfoNotOpenedByClient(fileName, p.projectService.toPath(fileName), scriptKind); scriptInfo != nil {
+ if scriptInfo := p.host.GetOrCreateScriptInfoForFile(fileName, p.toPath(fileName), scriptKind); scriptInfo != nil {
scriptInfo.attachToProject(p)
return scriptInfo
}
@@ -241,7 +258,9 @@ func (p *Project) updateGraph() bool {
p.initialLoadPending = false
if p.kind == KindConfigured && p.reloadConfig {
- p.projectService.loadConfiguredProject(p)
+ if err := p.LoadConfig(); err != nil {
+ panic(fmt.Sprintf("failed to reload config: %v", err))
+ }
p.reloadConfig = false
}
@@ -259,7 +278,7 @@ func (p *Project) updateGraph() bool {
if p.program != oldProgram && oldProgram != nil {
for _, oldSourceFile := range oldProgram.GetSourceFiles() {
if p.program.GetSourceFileByPath(oldSourceFile.Path()) == nil {
- p.projectService.documentRegistry.releaseDocument(oldSourceFile, oldProgram.GetCompilerOptions())
+ p.host.DocumentRegistry().ReleaseDocument(oldSourceFile, oldProgram.GetCompilerOptions())
}
}
}
@@ -326,7 +345,7 @@ func (p *Project) removeFile(info *ScriptInfo, fileExists bool, detachFromProjec
func (p *Project) addRoot(info *ScriptInfo) {
// !!!
// if p.kind == KindInferred {
- // p.projectService.startWatchingConfigFilesForInferredProjectRoot(info.path);
+ // p.host.startWatchingConfigFilesForInferredProjectRoot(info.path);
// // handle JS toggling
// }
if p.isRoot(info) {
@@ -337,6 +356,75 @@ func (p *Project) addRoot(info *ScriptInfo) {
p.markAsDirty()
}
+func (p *Project) LoadConfig() error {
+ if p.kind != KindConfigured {
+ panic("loadConfig called on non-configured project")
+ }
+
+ if configFileContent, ok := p.host.FS().ReadFile(p.configFileName); ok {
+ configDir := tspath.GetDirectoryPath(p.configFileName)
+ tsConfigSourceFile := tsoptions.NewTsconfigSourceFileFromFilePath(p.configFileName, p.configFilePath, configFileContent)
+ parsedCommandLine := tsoptions.ParseJsonSourceFileConfigFileContent(
+ tsConfigSourceFile,
+ p.host,
+ configDir,
+ nil, /*existingOptions*/
+ p.configFileName,
+ nil, /*resolutionStack*/
+ nil, /*extraFileExtensions*/
+ nil, /*extendedConfigCache*/
+ )
+
+ p.logf("Config: %s : %s",
+ p.configFileName,
+ core.Must(core.StringifyJson(map[string]any{
+ "rootNames": parsedCommandLine.FileNames(),
+ "options": parsedCommandLine.CompilerOptions(),
+ "projectReferences": parsedCommandLine.ProjectReferences(),
+ }, " ", " ")),
+ )
+
+ p.compilerOptions = parsedCommandLine.CompilerOptions()
+ p.setRootFiles(parsedCommandLine.FileNames())
+ } else {
+ p.compilerOptions = &core.CompilerOptions{}
+ return fmt.Errorf("could not read file %q", p.configFileName)
+ }
+
+ p.markAsDirty()
+ return nil
+}
+
+func (p *Project) setRootFiles(rootFileNames []string) {
+ newRootScriptInfos := make(map[tspath.Path]struct{}, len(rootFileNames))
+ for _, file := range rootFileNames {
+ scriptKind := p.getScriptKind(file)
+ scriptInfo := p.host.GetOrCreateScriptInfoForFile(file, p.toPath(file), scriptKind)
+ newRootScriptInfos[scriptInfo.path] = struct{}{}
+ if _, isRoot := p.rootFileNames.Get(scriptInfo.path); !isRoot {
+ p.addRoot(scriptInfo)
+ if scriptInfo.isOpen {
+ // !!!
+ // s.removeRootOfInferredProjectIfNowPartOfOtherProject(scriptInfo)
+ }
+ } else {
+ p.rootFileNames.Set(scriptInfo.path, file)
+ }
+ }
+
+ if p.rootFileNames.Size() > len(rootFileNames) {
+ for root := range p.rootFileNames.Keys() {
+ if _, ok := newRootScriptInfos[root]; !ok {
+ if info := p.host.GetScriptInfoByPath(root); info != nil {
+ p.removeFile(info, true /*fileExists*/, true /*detachFromProject*/)
+ } else {
+ p.rootFileNames.Delete(root)
+ }
+ }
+ }
+ }
+}
+
func (p *Project) clearSourceMapperCache() {
// !!!
}
@@ -368,5 +456,13 @@ func (p *Project) print(writeFileNames bool, writeFileExplanation bool, writeFil
}
func (p *Project) log(s string) {
- p.projectService.log(s)
+ p.host.Log(s)
+}
+
+func (p *Project) logf(format string, args ...interface{}) {
+ p.log(fmt.Sprintf(format, args...))
+}
+
+func (p *Project) Close() {
+ // !!!
}
diff --git a/internal/project/scriptinfo.go b/internal/project/scriptinfo.go
index 2ad81034c1..f97f15ad13 100644
--- a/internal/project/scriptinfo.go
+++ b/internal/project/scriptinfo.go
@@ -29,7 +29,7 @@ type ScriptInfo struct {
containingProjects []*Project
}
-func newScriptInfo(fileName string, path tspath.Path, scriptKind core.ScriptKind) *ScriptInfo {
+func NewScriptInfo(fileName string, path tspath.Path, scriptKind core.ScriptKind) *ScriptInfo {
isDynamic := isDynamicFileName(fileName)
realpath := core.IfElse(isDynamic, path, "")
return &ScriptInfo{
@@ -70,7 +70,7 @@ func (s *ScriptInfo) open(newText string) {
}
}
-func (s *ScriptInfo) setTextFromDisk(newText string) {
+func (s *ScriptInfo) SetTextFromDisk(newText string) {
if newText != s.text {
s.setText(newText)
s.matchesDiskText = true
@@ -146,7 +146,7 @@ func (s *ScriptInfo) ensureRealpath(fs vfs.FS) {
project := s.containingProjects[0]
s.realpath = project.toPath(realpath)
if s.realpath != s.path {
- project.projectService.recordSymlink(s)
+ project.host.OnDiscoveredSymlink(s)
}
}
}
@@ -184,64 +184,3 @@ func (s *ScriptInfo) delayReloadNonMixedContentFile() {
s.pendingReloadFromDisk = true
s.markContainingProjectsAsDirty()
}
-
-func (s *ScriptInfo) getDefaultProject() *Project {
- switch len(s.containingProjects) {
- case 0:
- panic("scriptInfo must be attached to a project before calling getDefaultProject")
- case 1:
- project := s.containingProjects[0]
- if project.deferredClose || project.kind == KindAutoImportProvider || project.kind == KindAuxiliary {
- panic("scriptInfo must be attached to a non-background project before calling getDefaultProject")
- }
- return project
- default:
- // If this file belongs to multiple projects, below is the order in which default project is used
- // - first external project
- // - for open script info, its default configured project during opening is default if info is part of it
- // - first configured project of which script info is not a source of project reference redirect
- // - first configured project
- // - first inferred project
- var firstConfiguredProject *Project
- var firstInferredProject *Project
- var firstNonSourceOfProjectReferenceRedirect *Project
- var defaultConfiguredProject *Project
-
- for index, project := range s.containingProjects {
- if project.kind == KindConfigured {
- if project.deferredClose {
- continue
- }
- // !!! if !project.isSourceOfProjectReferenceRedirect(s.fileName) {
- if defaultConfiguredProject == nil && index != len(s.containingProjects)-1 {
- defaultConfiguredProject = project.projectService.findDefaultConfiguredProject(s)
- }
- if defaultConfiguredProject == project {
- return project
- }
- if firstNonSourceOfProjectReferenceRedirect == nil {
- firstNonSourceOfProjectReferenceRedirect = project
- }
- // }
- if firstConfiguredProject == nil {
- firstConfiguredProject = project
- }
- } else if firstInferredProject == nil && project.kind == KindInferred {
- firstInferredProject = project
- }
- }
- if defaultConfiguredProject != nil {
- return defaultConfiguredProject
- }
- if firstNonSourceOfProjectReferenceRedirect != nil {
- return firstNonSourceOfProjectReferenceRedirect
- }
- if firstConfiguredProject != nil {
- return firstConfiguredProject
- }
- if firstInferredProject != nil {
- return firstInferredProject
- }
- panic("no project found")
- }
-}
diff --git a/internal/project/service.go b/internal/project/service.go
index d2ecaa2617..6fe70c8a95 100644
--- a/internal/project/service.go
+++ b/internal/project/service.go
@@ -8,8 +8,8 @@ import (
"github.com/microsoft/typescript-go/internal/core"
"github.com/microsoft/typescript-go/internal/ls"
"github.com/microsoft/typescript-go/internal/lsp/lsproto"
- "github.com/microsoft/typescript-go/internal/tsoptions"
"github.com/microsoft/typescript-go/internal/tspath"
+ "github.com/microsoft/typescript-go/internal/vfs"
)
type projectLoadKind int
@@ -28,11 +28,12 @@ type assignProjectResult struct {
}
type ServiceOptions struct {
- DefaultLibraryPath string
- Logger *Logger
- PositionEncoding lsproto.PositionEncodingKind
+ Logger *Logger
+ PositionEncoding lsproto.PositionEncodingKind
}
+var _ ProjectHost = (*Service)(nil)
+
type Service struct {
host ServiceHost
options ServiceOptions
@@ -46,7 +47,7 @@ type Service struct {
// if it exists
inferredProjects []*Project
- documentRegistry *documentRegistry
+ documentRegistry *DocumentRegistry
scriptInfosMu sync.RWMutex
scriptInfos map[tspath.Path]*ScriptInfo
openFiles map[tspath.Path]string // values are projectRootPath, if provided
@@ -59,7 +60,7 @@ type Service struct {
func NewService(host ServiceHost, options ServiceOptions) *Service {
options.Logger.Info(fmt.Sprintf("currentDirectory:: %s useCaseSensitiveFileNames:: %t", host.GetCurrentDirectory(), host.FS().UseCaseSensitiveFileNames()))
- options.Logger.Info("libs Location:: " + options.DefaultLibraryPath)
+ options.Logger.Info("libs Location:: " + host.DefaultLibraryPath())
return &Service{
host: host,
options: options,
@@ -70,10 +71,12 @@ func NewService(host ServiceHost, options ServiceOptions) *Service {
configuredProjects: make(map[tspath.Path]*Project),
- documentRegistry: newDocumentRegistry(tspath.ComparePathsOptions{
- UseCaseSensitiveFileNames: host.FS().UseCaseSensitiveFileNames(),
- CurrentDirectory: host.GetCurrentDirectory(),
- }),
+ documentRegistry: &DocumentRegistry{
+ Options: tspath.ComparePathsOptions{
+ UseCaseSensitiveFileNames: host.FS().UseCaseSensitiveFileNames(),
+ CurrentDirectory: host.GetCurrentDirectory(),
+ },
+ },
scriptInfos: make(map[tspath.Path]*ScriptInfo),
openFiles: make(map[tspath.Path]string),
filenameToScriptInfoVersion: make(map[tspath.Path]int),
@@ -81,6 +84,46 @@ func NewService(host ServiceHost, options ServiceOptions) *Service {
}
}
+// GetCurrentDirectory implements ProjectHost.
+func (s *Service) GetCurrentDirectory() string {
+ return s.host.GetCurrentDirectory()
+}
+
+// Log implements ProjectHost.
+func (s *Service) Log(msg string) {
+ s.options.Logger.Info(msg)
+}
+
+// NewLine implements ProjectHost.
+func (s *Service) NewLine() string {
+ return s.host.NewLine()
+}
+
+// DefaultLibraryPath implements ProjectHost.
+func (s *Service) DefaultLibraryPath() string {
+ return s.host.DefaultLibraryPath()
+}
+
+// DocumentRegistry implements ProjectHost.
+func (s *Service) DocumentRegistry() *DocumentRegistry {
+ return s.documentRegistry
+}
+
+// FS implements ProjectHost.
+func (s *Service) FS() vfs.FS {
+ return s.host.FS()
+}
+
+// GetOrCreateScriptInfoForFile implements ProjectHost.
+func (s *Service) GetOrCreateScriptInfoForFile(fileName string, path tspath.Path, scriptKind core.ScriptKind) *ScriptInfo {
+ return s.getOrCreateScriptInfoNotOpenedByClient(fileName, path, scriptKind)
+}
+
+// PositionEncoding implements ProjectHost.
+func (s *Service) PositionEncoding() lsproto.PositionEncodingKind {
+ return s.options.PositionEncoding
+}
+
func (s *Service) Projects() []*Project {
projects := make([]*Project, 0, len(s.configuredProjects)+len(s.inferredProjects))
for _, project := range s.configuredProjects {
@@ -91,10 +134,10 @@ func (s *Service) Projects() []*Project {
}
func (s *Service) GetScriptInfo(fileName string) *ScriptInfo {
- return s.getScriptInfo(s.toPath(fileName))
+ return s.GetScriptInfoByPath(s.toPath(fileName))
}
-func (s *Service) getScriptInfo(path tspath.Path) *ScriptInfo {
+func (s *Service) GetScriptInfoByPath(path tspath.Path) *ScriptInfo {
s.scriptInfosMu.RLock()
defer s.scriptInfosMu.RUnlock()
if info, ok := s.scriptInfos[path]; ok && !info.deferredDelete {
@@ -105,7 +148,7 @@ func (s *Service) getScriptInfo(path tspath.Path) *ScriptInfo {
func (s *Service) OpenFile(fileName string, fileContent string, scriptKind core.ScriptKind, projectRootPath string) {
path := s.toPath(fileName)
- existing := s.getScriptInfo(path)
+ existing := s.GetScriptInfoByPath(path)
info := s.getOrCreateOpenScriptInfo(fileName, path, fileContent, scriptKind, projectRootPath)
if existing == nil && info != nil && !info.isDynamic {
// !!!
@@ -118,7 +161,7 @@ func (s *Service) OpenFile(fileName string, fileContent string, scriptKind core.
func (s *Service) ChangeFile(fileName string, changes []ls.TextChange) {
path := s.toPath(fileName)
- info := s.getScriptInfo(path)
+ info := s.GetScriptInfoByPath(path)
if info == nil {
panic("scriptInfo not found")
}
@@ -126,7 +169,7 @@ func (s *Service) ChangeFile(fileName string, changes []ls.TextChange) {
}
func (s *Service) CloseFile(fileName string) {
- if info := s.getScriptInfo(s.toPath(fileName)); info != nil {
+ if info := s.GetScriptInfoByPath(s.toPath(fileName)); info != nil {
fileExists := !info.isDynamic && s.host.FS().FileExists(info.fileName)
info.close(fileExists)
for _, project := range info.containingProjects {
@@ -142,21 +185,21 @@ func (s *Service) CloseFile(fileName string) {
}
func (s *Service) MarkFileSaved(fileName string, text string) {
- if info := s.getScriptInfo(s.toPath(fileName)); info != nil {
- info.setTextFromDisk(text)
+ if info := s.GetScriptInfoByPath(s.toPath(fileName)); info != nil {
+ info.SetTextFromDisk(text)
}
}
func (s *Service) EnsureDefaultProjectForFile(fileName string) (*ScriptInfo, *Project) {
path := s.toPath(fileName)
- if info := s.getScriptInfo(path); info != nil && !info.isOrphan() {
- if project := info.getDefaultProject(); project != nil {
+ if info := s.GetScriptInfoByPath(path); info != nil && !info.isOrphan() {
+ if project := s.getDefaultProjectForScript(info); project != nil {
return info, project
}
}
s.ensureProjectStructureUpToDate()
- if info := s.getScriptInfo(path); info != nil {
- if project := info.getDefaultProject(); project != nil {
+ if info := s.GetScriptInfoByPath(path); info != nil {
+ if project := s.getDefaultProjectForScript(info); project != nil {
return info, project
}
}
@@ -164,7 +207,7 @@ func (s *Service) EnsureDefaultProjectForFile(fileName string) (*ScriptInfo, *Pr
}
func (s *Service) Close() {
- // !!!
+ s.options.Logger.Close()
}
// SourceFileCount should only be used for testing.
@@ -186,11 +229,11 @@ func (s *Service) ensureProjectStructureUpToDate() {
}
func (s *Service) ensureProjectForOpenFiles() {
- s.log("Before ensureProjectForOpenFiles:")
+ s.Log("Before ensureProjectForOpenFiles:")
s.printProjects()
for filePath, projectRootPath := range s.openFiles {
- info := s.getScriptInfo(filePath)
+ info := s.GetScriptInfoByPath(filePath)
if info == nil {
panic("scriptInfo not found for open file")
}
@@ -204,7 +247,7 @@ func (s *Service) ensureProjectForOpenFiles() {
project.updateIfDirty()
}
- s.log("After ensureProjectForOpenFiles:")
+ s.Log("After ensureProjectForOpenFiles:")
s.printProjects()
}
@@ -249,7 +292,7 @@ func (s *Service) deleteScriptInfo(info *ScriptInfo) {
// !!! closeSourceMapFileWatcher
}
-func (s *Service) recordSymlink(info *ScriptInfo) {
+func (s *Service) OnDiscoveredSymlink(info *ScriptInfo) {
s.realpathToScriptInfosMu.Lock()
defer s.realpathToScriptInfosMu.Unlock()
if scriptInfos, ok := s.realpathToScriptInfos[info.realpath]; ok {
@@ -308,9 +351,9 @@ func (s *Service) getOrCreateScriptInfoWorker(fileName string, path tspath.Path,
}
}
- info = newScriptInfo(fileName, path, scriptKind)
+ info = NewScriptInfo(fileName, path, scriptKind)
if fromDisk {
- info.setTextFromDisk(fileContent)
+ info.SetTextFromDisk(fileContent)
}
s.scriptInfosMu.Lock()
@@ -513,6 +556,67 @@ func (s *Service) getOrCreateInferredProjectForProjectRootPath(info *ScriptInfo,
return bestMatch
}
+func (s *Service) getDefaultProjectForScript(scriptInfo *ScriptInfo) *Project {
+ switch len(scriptInfo.containingProjects) {
+ case 0:
+ panic("scriptInfo must be attached to a project before calling getDefaultProject")
+ case 1:
+ project := scriptInfo.containingProjects[0]
+ if project.deferredClose || project.kind == KindAutoImportProvider || project.kind == KindAuxiliary {
+ panic("scriptInfo must be attached to a non-background project before calling getDefaultProject")
+ }
+ return project
+ default:
+ // If this file belongs to multiple projects, below is the order in which default project is used
+ // - first external project
+ // - for open script info, its default configured project during opening is default if info is part of it
+ // - first configured project of which script info is not a source of project reference redirect
+ // - first configured project
+ // - first inferred project
+ var firstConfiguredProject *Project
+ var firstInferredProject *Project
+ var firstNonSourceOfProjectReferenceRedirect *Project
+ var defaultConfiguredProject *Project
+
+ for index, project := range scriptInfo.containingProjects {
+ if project.kind == KindConfigured {
+ if project.deferredClose {
+ continue
+ }
+ // !!! if !project.isSourceOfProjectReferenceRedirect(scriptInfo.fileName) {
+ if defaultConfiguredProject == nil && index != len(scriptInfo.containingProjects)-1 {
+ defaultConfiguredProject = s.findDefaultConfiguredProject(scriptInfo)
+ }
+ if defaultConfiguredProject == project {
+ return project
+ }
+ if firstNonSourceOfProjectReferenceRedirect == nil {
+ firstNonSourceOfProjectReferenceRedirect = project
+ }
+ // }
+ if firstConfiguredProject == nil {
+ firstConfiguredProject = project
+ }
+ } else if firstInferredProject == nil && project.kind == KindInferred {
+ firstInferredProject = project
+ }
+ }
+ if defaultConfiguredProject != nil {
+ return defaultConfiguredProject
+ }
+ if firstNonSourceOfProjectReferenceRedirect != nil {
+ return firstNonSourceOfProjectReferenceRedirect
+ }
+ if firstConfiguredProject != nil {
+ return firstConfiguredProject
+ }
+ if firstInferredProject != nil {
+ return firstInferredProject
+ }
+ panic("no project found")
+ }
+}
+
func (s *Service) createInferredProject(currentDirectory string, projectRootPath tspath.Path) *Project {
// !!!
compilerOptions := core.CompilerOptions{}
@@ -526,62 +630,9 @@ func (s *Service) toPath(fileName string) tspath.Path {
}
func (s *Service) loadConfiguredProject(project *Project) {
- if configFileContent, ok := s.host.FS().ReadFile(project.configFileName); ok {
- configDir := tspath.GetDirectoryPath(project.configFileName)
- tsConfigSourceFile := tsoptions.NewTsconfigSourceFileFromFilePath(project.configFileName, s.toPath(project.configFileName), configFileContent)
- parsedCommandLine := tsoptions.ParseJsonSourceFileConfigFileContent(
- tsConfigSourceFile,
- s.host,
- configDir,
- nil, /*existingOptions*/
- project.configFileName,
- nil, /*resolutionStack*/
- nil, /*extraFileExtensions*/
- nil, /*extendedConfigCache*/
- )
-
- s.logf("Config: %s : %s",
- project.configFileName,
- core.Must(core.StringifyJson(map[string]any{
- "rootNames": parsedCommandLine.FileNames(),
- "options": parsedCommandLine.CompilerOptions(),
- "projectReferences": parsedCommandLine.ProjectReferences(),
- }, " ", " ")),
- )
-
- newRootScriptInfos := make(map[tspath.Path]struct{}, len(parsedCommandLine.FileNames()))
- project.compilerOptions = parsedCommandLine.CompilerOptions()
- for _, file := range parsedCommandLine.FileNames() {
- scriptKind := project.getScriptKind(file)
- scriptInfo := s.getOrCreateScriptInfoNotOpenedByClient(file, s.toPath(file), scriptKind)
- newRootScriptInfos[scriptInfo.path] = struct{}{}
- if _, isRoot := project.rootFileNames.Get(scriptInfo.path); !isRoot {
- project.addRoot(scriptInfo)
- if scriptInfo.isOpen {
- // !!!
- // s.removeRootOfInferredProjectIfNowPartOfOtherProject(scriptInfo)
- }
- } else {
- project.rootFileNames.Set(scriptInfo.path, file)
- }
- }
-
- if project.rootFileNames.Size() > len(parsedCommandLine.FileNames()) {
- for root := range project.rootFileNames.Keys() {
- if _, ok := newRootScriptInfos[root]; !ok {
- if info := s.getScriptInfo(root); info != nil {
- project.removeFile(info, true /*fileExists*/, true /*detachFromProject*/)
- } else {
- project.rootFileNames.Delete(root)
- }
- }
- }
- }
- } else {
- project.compilerOptions = &core.CompilerOptions{}
+ if err := project.LoadConfig(); err != nil {
+ panic(fmt.Errorf("failed to load project %q: %w", project.configFileName, err))
}
-
- project.markAsDirty()
}
func (s *Service) printProjects() {
@@ -591,25 +642,21 @@ func (s *Service) printProjects() {
s.options.Logger.StartGroup()
for _, project := range s.configuredProjects {
- s.log(project.print(false /*writeFileNames*/, false /*writeFileExpanation*/, false /*writeFileVersionAndText*/))
+ s.Log(project.print(false /*writeFileNames*/, false /*writeFileExpanation*/, false /*writeFileVersionAndText*/))
}
for _, project := range s.inferredProjects {
- s.log(project.print(false /*writeFileNames*/, false /*writeFileExpanation*/, false /*writeFileVersionAndText*/))
+ s.Log(project.print(false /*writeFileNames*/, false /*writeFileExpanation*/, false /*writeFileVersionAndText*/))
}
- s.log("Open files: ")
+ s.Log("Open files: ")
for path, projectRootPath := range s.openFiles {
- info := s.getScriptInfo(path)
+ info := s.GetScriptInfoByPath(path)
s.logf("\tFileName: %s ProjectRootPath: %s", info.fileName, projectRootPath)
- s.log("\t\tProjects: " + strings.Join(core.Map(info.containingProjects, func(project *Project) string { return project.name }), ", "))
+ s.Log("\t\tProjects: " + strings.Join(core.Map(info.containingProjects, func(project *Project) string { return project.name }), ", "))
}
s.options.Logger.EndGroup()
}
-func (s *Service) log(msg string) {
- s.options.Logger.Info(msg)
-}
-
func (s *Service) logf(format string, args ...any) {
- s.log(fmt.Sprintf(format, args...))
+ s.Log(fmt.Sprintf(format, args...))
}
diff --git a/internal/project/service_test.go b/internal/project/service_test.go
index 25fa07f83d..90952bb5a7 100644
--- a/internal/project/service_test.go
+++ b/internal/project/service_test.go
@@ -245,7 +245,7 @@ func newProjectServiceHost(files map[string]string) *projectServiceHost {
fs: fs,
defaultLibraryPath: bundled.LibPath(),
}
- host.logger = project.NewLogger([]io.Writer{&host.output}, project.LogLevelVerbose)
+ host.logger = project.NewLogger([]io.Writer{&host.output}, "", project.LogLevelVerbose)
return host
}
diff --git a/package-lock.json b/package-lock.json
index ae2a6f9a5b..cbb54a532b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,7 +10,8 @@
"hasInstallScript": true,
"license": "Apache-2.0",
"workspaces": [
- "./_extension"
+ "./_extension",
+ "./_packages/*"
],
"devDependencies": {
"@types/node": "latest",
@@ -39,6 +40,21 @@
"vscode": "^1.91.0"
}
},
+ "_packages/api": {
+ "name": "@typescript/api",
+ "version": "1.0.0",
+ "dependencies": {
+ "@typescript/ast": "1.0.0",
+ "libsyncrpc": "github:microsoft/libsyncrpc#bb02d84"
+ },
+ "devDependencies": {
+ "tinybench": "^3.1.1"
+ }
+ },
+ "_packages/ast": {
+ "name": "@typescript/ast",
+ "version": "1.0.0"
+ },
"node_modules/@apidevtools/json-schema-ref-parser": {
"version": "11.9.0",
"resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.9.0.tgz",
@@ -251,6 +267,14 @@
"integrity": "sha512-liyfuo/106JdlgSchJzXEQCVArk0CvevqPote8F8HgWgJ3dRCcTHgJIsLDuee0kxk/mhbInzIZk3QWSZJ8R+2w==",
"dev": true
},
+ "node_modules/@typescript/api": {
+ "resolved": "_packages/api",
+ "link": true
+ },
+ "node_modules/@typescript/ast": {
+ "resolved": "_packages/ast",
+ "link": true
+ },
"node_modules/ansi-regex": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
@@ -705,6 +729,14 @@
"@types/json-schema": "^7.0.15"
}
},
+ "node_modules/libsyncrpc": {
+ "version": "0.0.0",
+ "resolved": "git+ssh://git@github.com/microsoft/libsyncrpc.git#bb02d8458da5b6dda1507b3390ea7cca80b99ca3",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10.16.0 < 11 || >= 11.8.0 < 12 || >= 12.0.0"
+ }
+ },
"node_modules/lru-cache": {
"version": "10.4.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
@@ -1037,6 +1069,16 @@
"node": ">=8.0.0"
}
},
+ "node_modules/tinybench": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-3.1.1.tgz",
+ "integrity": "sha512-74pmf47HY/bHqamcCMGris+1AtGGsqTZ3Hc/UK4QvSmRuf/9PIF9753+c8XBh7JfX2r9KeZtVjOYjd6vFpc0qQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
"node_modules/typescript": {
"version": "5.7.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz",
@@ -1430,6 +1472,17 @@
"integrity": "sha512-liyfuo/106JdlgSchJzXEQCVArk0CvevqPote8F8HgWgJ3dRCcTHgJIsLDuee0kxk/mhbInzIZk3QWSZJ8R+2w==",
"dev": true
},
+ "@typescript/api": {
+ "version": "file:_packages/api",
+ "requires": {
+ "@typescript/ast": "1.0.0",
+ "libsyncrpc": "github:microsoft/libsyncrpc#bb02d84",
+ "tinybench": "^3.1.1"
+ }
+ },
+ "@typescript/ast": {
+ "version": "file:_packages/ast"
+ },
"ansi-regex": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
@@ -1756,6 +1809,10 @@
"@types/json-schema": "^7.0.15"
}
},
+ "libsyncrpc": {
+ "version": "git+ssh://git@github.com/microsoft/libsyncrpc.git#bb02d8458da5b6dda1507b3390ea7cca80b99ca3",
+ "from": "libsyncrpc@github:microsoft/libsyncrpc#bb02d84"
+ },
"lru-cache": {
"version": "10.4.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
@@ -1980,6 +2037,12 @@
"wordwrapjs": "^4.0.0"
}
},
+ "tinybench": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-3.1.1.tgz",
+ "integrity": "sha512-74pmf47HY/bHqamcCMGris+1AtGGsqTZ3Hc/UK4QvSmRuf/9PIF9753+c8XBh7JfX2r9KeZtVjOYjd6vFpc0qQ==",
+ "dev": true
+ },
"typescript": {
"version": "5.7.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz",
diff --git a/package.json b/package.json
index 7130090b01..5cd212c942 100644
--- a/package.json
+++ b/package.json
@@ -37,11 +37,14 @@
"build": "hereby build",
"build:watch": "hereby build:watch",
"test": "hereby test",
+ "api:build": "npm run -w @typescript/api build",
"extension:build": "npm run -w typescript-lsp build",
- "extension:watch": "npm run -w typescript-lsp watch"
+ "extension:watch": "npm run -w typescript-lsp watch",
+ "node": "node --no-warnings --conditions @typescript/source"
},
"workspaces": [
- "./_extension"
+ "./_extension",
+ "./_packages/*"
],
"packageManager": "npm@8.19.4",
"volta": {
diff --git a/testdata/baselines/reference/api/encodeSourceFile.txt b/testdata/baselines/reference/api/encodeSourceFile.txt
new file mode 100644
index 0000000000..88eb7adb80
--- /dev/null
+++ b/testdata/baselines/reference/api/encodeSourceFile.txt
@@ -0,0 +1,30 @@
+KindSourceFile [0, 89), i=1, next=0
+ NodeList [0, 89), i=2, next=0
+ KindImportDeclaration [0, 26), i=3, next=10
+ KindImportClause [6, 14), i=4, next=9
+ KindNamedImports [6, 14), i=5, next=0
+ NodeList [8, 12), i=6, next=0
+ KindImportSpecifier [8, 12), i=7, next=0
+ KindIdentifier "bar" [8, 12), i=8, next=0
+ KindStringLiteral "bar" [19, 25), i=9, next=0
+ KindFunctionDeclaration [26, 82), i=10, next=28
+ NodeList [26, 33), i=11, next=13
+ KindExportKeyword [26, 33), i=12, next=0
+ KindIdentifier "foo" [42, 46), i=13, next=14
+ NodeList [47, 51), i=14, next=19
+ KindTypeParameter [47, 48), i=15, next=17
+ KindIdentifier "T" [47, 48), i=16, next=0
+ KindTypeParameter [49, 51), i=17, next=0
+ KindIdentifier "U" [49, 51), i=18, next=0
+ NodeList [53, 73), i=19, next=26
+ KindParameter [53, 62), i=20, next=23
+ KindIdentifier "a" [53, 54), i=21, next=22
+ KindStringKeyword [55, 62), i=22, next=0
+ KindParameter [63, 73), i=23, next=0
+ KindIdentifier "b" [63, 65), i=24, next=25
+ KindStringKeyword [66, 73), i=25, next=0
+ KindAnyKeyword [75, 79), i=26, next=27
+ KindBlock [79, 82), i=27, next=0
+ KindExpressionStatement [82, 89), i=28, next=0
+ KindCallExpression [82, 88), i=29, next=0
+ KindIdentifier "foo" [82, 86), i=30, next=0