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 @@ +/// <reference path="./node.ts" preserve="true" /> +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<string, unknown>; + 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<string, string>): FileSystem { + interface VDirectory { + type: "directory"; + children: Record<string, VNode>; + } + + 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<T>(visitor: (node: Node) => T): T | undefined; + getSourceFile(): SourceFile; + } + + export interface NodeArray<T> { + 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<Partial<Record<SyntaxKind, readonly string[]>>> = { + [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<number, RemoteNode | RemoteNodeList> | 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<RemoteNode> implements NodeArray<RemoteNode> { + parent: RemoteNode; + protected view: DataView; + protected decoder: TextDecoder; + protected index: number; + /** Keys are positions */ + protected _children: Map<number, RemoteNode | RemoteNodeList> | 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<RemoteNode> { + 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<T>(visitNode: (node: Node) => T, visitList?: (list: NodeArray<Node>) => 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<string, Project> = new Map(); + private symbols: Map<string, Symbol> = new Map(); + private types: Map<string, Type> = 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<T>(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<string, unknown>; + fileNames: string[]; +} + +export interface ProjectResponse { + id: string; + configFileName: string; + compilerOptions: Record<string, unknown>; + 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<string, string> = 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<SyntaxKind.CommaToken> { + 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<Statement>; + 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<T> extends ReadonlyTextRange, ReadonlyArray<T> { + readonly length: number; + readonly pos: number; + readonly end: number; +} + +// TODO(rbuckton): Constraint 'TKind' to 'TokenSyntaxKind' +export interface Token<TKind extends SyntaxKind> extends Node { + readonly kind: TKind; +} + +export type EndOfFile = Token<SyntaxKind.EndOfFile>; + +// Punctuation +export interface PunctuationToken<TKind extends PunctuationSyntaxKind> extends Token<TKind> { +} + +export type DotToken = PunctuationToken<SyntaxKind.DotToken>; +export type DotDotDotToken = PunctuationToken<SyntaxKind.DotDotDotToken>; +export type QuestionToken = PunctuationToken<SyntaxKind.QuestionToken>; +export type ExclamationToken = PunctuationToken<SyntaxKind.ExclamationToken>; +export type ColonToken = PunctuationToken<SyntaxKind.ColonToken>; +export type EqualsToken = PunctuationToken<SyntaxKind.EqualsToken>; +export type AmpersandAmpersandEqualsToken = PunctuationToken<SyntaxKind.AmpersandAmpersandEqualsToken>; +export type BarBarEqualsToken = PunctuationToken<SyntaxKind.BarBarEqualsToken>; +export type QuestionQuestionEqualsToken = PunctuationToken<SyntaxKind.QuestionQuestionEqualsToken>; +export type AsteriskToken = PunctuationToken<SyntaxKind.AsteriskToken>; +export type EqualsGreaterThanToken = PunctuationToken<SyntaxKind.EqualsGreaterThanToken>; +export type PlusToken = PunctuationToken<SyntaxKind.PlusToken>; +export type MinusToken = PunctuationToken<SyntaxKind.MinusToken>; +export type QuestionDotToken = PunctuationToken<SyntaxKind.QuestionDotToken>; + +// Keywords +export interface KeywordToken<TKind extends KeywordSyntaxKind> extends Token<TKind> { +} + +export type AssertsKeyword = KeywordToken<SyntaxKind.AssertsKeyword>; +export type AssertKeyword = KeywordToken<SyntaxKind.AssertKeyword>; +export type AwaitKeyword = KeywordToken<SyntaxKind.AwaitKeyword>; +export type CaseKeyword = KeywordToken<SyntaxKind.CaseKeyword>; + +export interface ModifierToken<TKind extends ModifierSyntaxKind> extends KeywordToken<TKind> { +} + +export type AbstractKeyword = ModifierToken<SyntaxKind.AbstractKeyword>; +export type AccessorKeyword = ModifierToken<SyntaxKind.AccessorKeyword>; +export type AsyncKeyword = ModifierToken<SyntaxKind.AsyncKeyword>; +export type ConstKeyword = ModifierToken<SyntaxKind.ConstKeyword>; +export type DeclareKeyword = ModifierToken<SyntaxKind.DeclareKeyword>; +export type DefaultKeyword = ModifierToken<SyntaxKind.DefaultKeyword>; +export type ExportKeyword = ModifierToken<SyntaxKind.ExportKeyword>; +export type InKeyword = ModifierToken<SyntaxKind.InKeyword>; +export type PrivateKeyword = ModifierToken<SyntaxKind.PrivateKeyword>; +export type ProtectedKeyword = ModifierToken<SyntaxKind.ProtectedKeyword>; +export type PublicKeyword = ModifierToken<SyntaxKind.PublicKeyword>; +export type ReadonlyKeyword = ModifierToken<SyntaxKind.ReadonlyKeyword>; +export type OutKeyword = ModifierToken<SyntaxKind.OutKeyword>; +export type OverrideKeyword = ModifierToken<SyntaxKind.OverrideKeyword>; +export type StaticKeyword = ModifierToken<SyntaxKind.StaticKeyword>; + +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<Modifier>; + +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<Modifier>; + 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<TypeParameterDeclaration> | undefined; + readonly parameters: NodeArray<ParameterDeclaration>; + 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<VariableDeclaration>; +} + +// dprint-ignore +export interface ParameterDeclaration extends NamedDeclaration { + readonly kind: SyntaxKind.Parameter; + readonly parent: SignatureDeclaration; + readonly modifiers?: NodeArray<ModifierLike>; + 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<Modifier>; + 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<ModifierLike>; + 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<BindingElement>; +} + +export interface ArrayBindingPattern extends Node { + readonly kind: SyntaxKind.ArrayBindingPattern; + readonly parent: VariableDeclaration | ParameterDeclaration | BindingElement; + readonly elements: NodeArray<ArrayBindingElement>; +} + +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<ModifierLike>; + readonly name?: Identifier; + readonly body?: FunctionBody; +} + +export interface MethodSignature extends SignatureDeclarationBase, TypeElement { + readonly kind: SyntaxKind.MethodSignature; + readonly parent: TypeLiteralNode | InterfaceDeclaration; + readonly modifiers?: NodeArray<Modifier>; + 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<ModifierLike> | undefined; + readonly name: PropertyName; + readonly body?: FunctionBody | undefined; +} + +export interface ConstructorDeclaration extends FunctionLikeDeclarationBase, ClassElement { + readonly kind: SyntaxKind.Constructor; + readonly parent: ClassLikeDeclaration; + readonly modifiers?: NodeArray<ModifierLike> | 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<ModifierLike>; + 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<ModifierLike>; + 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<ModifierLike>; + 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<TKind extends KeywordTypeSyntaxKind = KeywordTypeSyntaxKind> extends KeywordToken<TKind>, 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<Modifier>; +} + +export interface NodeWithTypeArguments extends TypeNode { + readonly typeArguments?: NodeArray<TypeNode>; +} + +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<TypeElement>; +} + +export interface ArrayTypeNode extends TypeNode { + readonly kind: SyntaxKind.ArrayType; + readonly elementType: TypeNode; +} + +export interface TupleTypeNode extends TypeNode { + readonly kind: SyntaxKind.TupleType; + readonly elements: NodeArray<TypeNode | NamedTupleMember>; +} + +export interface NamedTupleMember extends TypeNode, Declaration { + readonly kind: SyntaxKind.NamedTupleMember; + readonly dotDotDotToken?: Token<SyntaxKind.DotDotDotToken>; + readonly name: Identifier; + readonly questionToken?: Token<SyntaxKind.QuestionToken>; + 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<TypeNode>; +} + +export interface IntersectionTypeNode extends TypeNode { + readonly kind: SyntaxKind.IntersectionType; + readonly types: NodeArray<TypeNode>; +} + +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<TypeElement>; +} + +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<TemplateLiteralTypeSpan>; +} + +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<BinaryOperator>; + +export interface BinaryExpression extends Expression, Declaration { + readonly kind: SyntaxKind.BinaryExpression; + readonly left: Expression; + readonly operatorToken: BinaryOperatorToken; + readonly right: Expression; +} + +export type AssignmentOperatorToken = Token<AssignmentOperator>; + +export interface AssignmentExpression<TOperator extends AssignmentOperatorToken> extends BinaryExpression { + readonly left: LeftHandSideExpression; + readonly operatorToken: TOperator; +} + +export interface ObjectDestructuringAssignment extends AssignmentExpression<EqualsToken> { + readonly left: ObjectLiteralExpression; +} + +export interface ArrayDestructuringAssignment extends AssignmentExpression<EqualsToken> { + 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<EqualsToken> // 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<Modifier>; + 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<Modifier>; + 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<TemplateSpan>; +} + +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<Expression>; + 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<T extends ObjectLiteralElement> extends PrimaryExpression, Declaration { + readonly properties: NodeArray<T>; +} + +// An ObjectLiteralExpression is the declaration node for an anonymous symbol. +export interface ObjectLiteralExpression extends ObjectLiteralExpressionBase<ObjectLiteralElementLike> { + 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<TypeNode>; + readonly arguments: NodeArray<Expression>; +} + +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<TypeNode>; + readonly arguments?: NodeArray<Expression>; +} + +export interface TaggedTemplateExpression extends MemberExpression { + readonly kind: SyntaxKind.TaggedTemplateExpression; + readonly tag: LeftHandSideExpression; + readonly typeArguments?: NodeArray<TypeNode>; + readonly template: TemplateLiteral; +} + +export interface InstanceofExpression extends BinaryExpression { + readonly operatorToken: Token<SyntaxKind.InstanceOfKeyword>; +} + +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 <TagName attrs>...</TagName> +export interface JsxElement extends PrimaryExpression { + readonly kind: SyntaxKind.JsxElement; + readonly openingElement: JsxOpeningElement; + readonly children: NodeArray<JsxChild>; + readonly closingElement: JsxClosingElement; +} + +/// Either the opening tag in a <Tag>...</Tag> pair or the lone <Tag /> 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<JsxAttributeLike>; + 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 <Tag>...</Tag> JsxElement +export interface JsxOpeningElement extends Expression { + readonly kind: SyntaxKind.JsxOpeningElement; + readonly parent: JsxElement; + readonly tagName: JsxTagNameExpression; + readonly typeArguments?: NodeArray<TypeNode>; + readonly attributes: JsxAttributes; +} + +/// A JSX expression of the form <TagName attrs /> +export interface JsxSelfClosingElement extends PrimaryExpression { + readonly kind: SyntaxKind.JsxSelfClosingElement; + readonly tagName: JsxTagNameExpression; + readonly typeArguments?: NodeArray<TypeNode>; + readonly attributes: JsxAttributes; +} + +/// A JSX expression of the form <>...</> +export interface JsxFragment extends PrimaryExpression { + readonly kind: SyntaxKind.JsxFragment; + readonly openingFragment: JsxOpeningFragment; + readonly children: NodeArray<JsxChild>; + 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; <X y /> is sugar for <X y={true} /> + 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<SyntaxKind.DotDotDotToken>; + 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<Expression>; +} + +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<Statement>; + multiLine?: boolean; +} + +export interface VariableStatement extends Statement { + readonly kind: SyntaxKind.VariableStatement; + readonly modifiers?: NodeArray<ModifierLike>; + 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<CaseOrDefaultClause>; +} + +export interface CaseClause extends Node { + readonly kind: SyntaxKind.CaseClause; + readonly parent: CaseBlock; + readonly expression: Expression; + readonly statements: NodeArray<Statement>; +} + +export interface DefaultClause extends Node { + readonly kind: SyntaxKind.DefaultClause; + readonly parent: CaseBlock; + readonly statements: NodeArray<Statement>; +} + +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<TypeParameterDeclaration>; + readonly heritageClauses?: NodeArray<HeritageClause>; + readonly members: NodeArray<ClassElement>; +} + +export interface ClassDeclaration extends ClassLikeDeclarationBase, DeclarationStatement { + readonly kind: SyntaxKind.ClassDeclaration; + readonly modifiers?: NodeArray<ModifierLike>; + /** May be undefined in `export default class { ... }`. */ + readonly name?: Identifier; +} + +export interface ClassExpression extends ClassLikeDeclarationBase, PrimaryExpression { + readonly kind: SyntaxKind.ClassExpression; + readonly modifiers?: NodeArray<ModifierLike>; +} + +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<ModifierLike>; + readonly name: Identifier; + readonly typeParameters?: NodeArray<TypeParameterDeclaration>; + readonly heritageClauses?: NodeArray<HeritageClause>; + readonly members: NodeArray<TypeElement>; +} + +export interface HeritageClause extends Node { + readonly kind: SyntaxKind.HeritageClause; + readonly parent: InterfaceDeclaration | ClassLikeDeclaration; + readonly token: SyntaxKind.ExtendsKeyword | SyntaxKind.ImplementsKeyword; + readonly types: NodeArray<ExpressionWithTypeArguments>; +} + +export interface TypeAliasDeclaration extends DeclarationStatement { + readonly kind: SyntaxKind.TypeAliasDeclaration; + readonly modifiers?: NodeArray<ModifierLike>; + readonly name: Identifier; + readonly typeParameters?: NodeArray<TypeParameterDeclaration>; + 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<ModifierLike>; + readonly name: Identifier; + readonly members: NodeArray<EnumMember>; +} + +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<ModifierLike>; + 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<Statement>; +} + +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<ModifierLike>; + 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<ModifierLike>; + 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<ImportAttribute>; + 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<ModifierLike>; + 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<ImportSpecifier>; +} + +export interface NamedExports extends Node { + readonly kind: SyntaxKind.NamedExports; + readonly parent: ExportDeclaration; + readonly elements: NodeArray<ExportSpecifier>; +} + +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<ModifierLike>; + 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<JSDocTag>; + readonly comment?: string | NodeArray<JSDocComment>; +} + +export interface JSDocTag extends Node { + readonly parent: JSDoc | JSDocTypeLiteral; + readonly tagName: Identifier; + readonly comment?: string | NodeArray<JSDocComment>; +} + +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<TypeParameterDeclaration>; +} + +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<TOut extends TIn, TIn = any>(value: TIn | undefined, test: (value: TIn) => value is TOut): TOut | undefined { + return value !== undefined && test(value) ? value : undefined; +} + +export function cast<TOut extends TIn, TIn = any>(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<T, U>(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