diff --git a/.github/generated/ast_changes_watch_list.yml b/.github/generated/ast_changes_watch_list.yml index 1313d008aefc5..4f3b319532cad 100644 --- a/.github/generated/ast_changes_watch_list.yml +++ b/.github/generated/ast_changes_watch_list.yml @@ -5,11 +5,13 @@ src: - '.github/generated/ast_changes_watch_list.yml' - '.github/workflows/ci.yml' - 'apps/oxlint/src-js/generated/constants.ts' + - 'apps/oxlint/src-js/generated/deserialize.d.ts' - 'apps/oxlint/src-js/generated/deserialize.js' - 'apps/oxlint/src-js/generated/keys.ts' - 'apps/oxlint/src-js/generated/type_ids.ts' - 'apps/oxlint/src-js/generated/types.d.ts' - 'apps/oxlint/src-js/generated/visitor.d.ts' + - 'apps/oxlint/src-js/generated/walk.d.ts' - 'apps/oxlint/src-js/generated/walk.js' - 'apps/oxlint/src/generated/raw_transfer_constants.rs' - 'crates/oxc_allocator/src/**' @@ -35,13 +37,21 @@ src: - 'crates/oxc_syntax/src/**' - 'crates/oxc_traverse/src/generated/scopes_collector.rs' - 'napi/parser/generated/constants.js' + - 'napi/parser/generated/deserialize/js.d.ts' - 'napi/parser/generated/deserialize/js.js' + - 'napi/parser/generated/deserialize/js_parent.d.ts' - 'napi/parser/generated/deserialize/js_parent.js' + - 'napi/parser/generated/deserialize/js_range.d.ts' - 'napi/parser/generated/deserialize/js_range.js' + - 'napi/parser/generated/deserialize/js_range_parent.d.ts' - 'napi/parser/generated/deserialize/js_range_parent.js' + - 'napi/parser/generated/deserialize/ts.d.ts' - 'napi/parser/generated/deserialize/ts.js' + - 'napi/parser/generated/deserialize/ts_parent.d.ts' - 'napi/parser/generated/deserialize/ts_parent.js' + - 'napi/parser/generated/deserialize/ts_range.d.ts' - 'napi/parser/generated/deserialize/ts_range.js' + - 'napi/parser/generated/deserialize/ts_range_parent.d.ts' - 'napi/parser/generated/deserialize/ts_range_parent.js' - 'napi/parser/generated/lazy/constructors.js' - 'napi/parser/generated/lazy/type_ids.js' @@ -49,6 +59,7 @@ src: - 'napi/parser/generated/visit/keys.js' - 'napi/parser/generated/visit/type_ids.js' - 'napi/parser/generated/visit/visitor.d.ts' + - 'napi/parser/generated/visit/walk.d.ts' - 'napi/parser/generated/visit/walk.js' - 'napi/parser/src/generated/assert_layouts.rs' - 'napi/parser/src/generated/derive_estree.rs' diff --git a/apps/oxlint/src-js/generated/deserialize.d.ts b/apps/oxlint/src-js/generated/deserialize.d.ts new file mode 100644 index 0000000000000..eb0662bcd2d40 --- /dev/null +++ b/apps/oxlint/src-js/generated/deserialize.d.ts @@ -0,0 +1,17 @@ +// Auto-generated code, DO NOT EDIT DIRECTLY! +// To edit this generated file you have to edit `tasks/ast_tools/src/generators/raw_transfer.rs`. + +import type { Program } from "./types.d.ts"; +import type { Location as SourceLocation } from "../plugins/location.ts"; + +type BufferWithArrays = Uint8Array & { uint32: Uint32Array; float64: Float64Array }; +type GetLoc = (node: { range: [number, number] }) => SourceLocation; + +export declare function deserializeProgramOnly( + buffer: BufferWithArrays, + sourceText: string, + sourceByteLen: number, + getLoc: GetLoc, +): Program; + +export declare function resetBuffer(): void; diff --git a/apps/oxlint/src-js/generated/walk.d.ts b/apps/oxlint/src-js/generated/walk.d.ts new file mode 100644 index 0000000000000..aa92d2e287b31 --- /dev/null +++ b/apps/oxlint/src-js/generated/walk.d.ts @@ -0,0 +1,11 @@ +// Auto-generated code, DO NOT EDIT DIRECTLY! +// To edit this generated file you have to edit `tasks/ast_tools/src/generators/estree_visit.rs`. + +import type { Node, Program } from "./types.d.ts"; + +type VisitFn = ((node: Node) => void) | null; +type EnterExitVisitor = { enter: VisitFn; exit: VisitFn } | null; +type CompiledVisitors = (VisitFn | EnterExitVisitor)[]; + +export declare function walkProgram(program: Program, visitors: CompiledVisitors): void; +export declare const ancestors: Node[]; diff --git a/apps/oxlint/src-js/plugins/lint.ts b/apps/oxlint/src-js/plugins/lint.ts index 70e430379bc51..b618893f73e0e 100644 --- a/apps/oxlint/src-js/plugins/lint.ts +++ b/apps/oxlint/src-js/plugins/lint.ts @@ -21,7 +21,6 @@ import { TOKEN } from '../../dist/src-js/raw-transfer/lazy-common.js'; import { walkProgram } from '../generated/walk.js'; */ -// @ts-expect-error - TODO: We need to generate `.d.ts` file for this module import { walkProgram } from "../generated/walk.js"; import type { AfterHook, BufferWithArrays } from "./types.ts"; @@ -195,6 +194,7 @@ export function lintFileImpl( // e.g. file extension is not one the rule acts on. if (needsVisit) { if (ast === null) initAst(); + debugAssertIsNonNull(ast); walkProgram(ast, compiledVisitor); // Lazy implementation diff --git a/apps/oxlint/src-js/plugins/selector.ts b/apps/oxlint/src-js/plugins/selector.ts index 65bea612442f4..a592bc5ece7ae 100644 --- a/apps/oxlint/src-js/plugins/selector.ts +++ b/apps/oxlint/src-js/plugins/selector.ts @@ -1,7 +1,6 @@ import esquery from "esquery"; import visitorKeys from "../generated/keys.ts"; import { FUNCTION_NODE_TYPE_IDS, NODE_TYPE_IDS_MAP } from "../generated/type_ids.ts"; -// @ts-expect-error - TODO: We need to generate `.d.ts` file for this module import { ancestors } from "../generated/walk.js"; import { debugAssert } from "../utils/asserts.ts"; @@ -257,7 +256,13 @@ export function wrapVisitFnWithSelectorMatch( ): VisitFn { return (node: Node) => { if ( - esqueryMatches(node as unknown as EsqueryNode, esquerySelector, ancestors, ESQUERY_OPTIONS) + esqueryMatches( + node as unknown as EsqueryNode, + esquerySelector, + // @ts-expect-error: our TS types don't align perfectly with estree + ancestors, + ESQUERY_OPTIONS, + ) ) { visitFn(node); } diff --git a/apps/oxlint/src-js/plugins/source_code.ts b/apps/oxlint/src-js/plugins/source_code.ts index 7a8c671508847..bd0a2141f11b0 100644 --- a/apps/oxlint/src-js/plugins/source_code.ts +++ b/apps/oxlint/src-js/plugins/source_code.ts @@ -2,7 +2,6 @@ import { DATA_POINTER_POS_32, SOURCE_LEN_OFFSET } from "../generated/constants.t // We use the deserializer which removes `ParenthesizedExpression`s from AST, // and with `range`, `loc`, and `parent` properties on AST nodes, to match ESLint -// @ts-expect-error - TODO: We need to generate `.d.ts` file for this module import { deserializeProgramOnly, resetBuffer } from "../generated/deserialize.js"; import visitorKeys from "../generated/keys.ts"; @@ -83,6 +82,7 @@ export function initSourceText(): void { export function initAst(): void { if (sourceText === null) initSourceText(); debugAssertIsNonNull(sourceText); + debugAssertIsNonNull(buffer); ast = deserializeProgramOnly(buffer, sourceText, sourceByteLen, getNodeLoc); debugAssertIsNonNull(ast); diff --git a/napi/parser/generated/deserialize/js.d.ts b/napi/parser/generated/deserialize/js.d.ts new file mode 100644 index 0000000000000..ecdaa9648d555 --- /dev/null +++ b/napi/parser/generated/deserialize/js.d.ts @@ -0,0 +1,14 @@ +// Auto-generated code, DO NOT EDIT DIRECTLY! +// To edit this generated file you have to edit `tasks/ast_tools/src/generators/raw_transfer.rs`. + +import type * as ESTree from "@oxc-project/types"; + +type BufferWithArrays = Uint8Array & { uint32: Uint32Array; float64: Float64Array }; + +export declare function deserialize( + buffer: BufferWithArrays, + sourceText: string, + sourceByteLen: number, +): ESTree.Program; + +export declare function resetBuffer(): void; diff --git a/napi/parser/generated/deserialize/js_parent.d.ts b/napi/parser/generated/deserialize/js_parent.d.ts new file mode 100644 index 0000000000000..ecdaa9648d555 --- /dev/null +++ b/napi/parser/generated/deserialize/js_parent.d.ts @@ -0,0 +1,14 @@ +// Auto-generated code, DO NOT EDIT DIRECTLY! +// To edit this generated file you have to edit `tasks/ast_tools/src/generators/raw_transfer.rs`. + +import type * as ESTree from "@oxc-project/types"; + +type BufferWithArrays = Uint8Array & { uint32: Uint32Array; float64: Float64Array }; + +export declare function deserialize( + buffer: BufferWithArrays, + sourceText: string, + sourceByteLen: number, +): ESTree.Program; + +export declare function resetBuffer(): void; diff --git a/napi/parser/generated/deserialize/js_range.d.ts b/napi/parser/generated/deserialize/js_range.d.ts new file mode 100644 index 0000000000000..ecdaa9648d555 --- /dev/null +++ b/napi/parser/generated/deserialize/js_range.d.ts @@ -0,0 +1,14 @@ +// Auto-generated code, DO NOT EDIT DIRECTLY! +// To edit this generated file you have to edit `tasks/ast_tools/src/generators/raw_transfer.rs`. + +import type * as ESTree from "@oxc-project/types"; + +type BufferWithArrays = Uint8Array & { uint32: Uint32Array; float64: Float64Array }; + +export declare function deserialize( + buffer: BufferWithArrays, + sourceText: string, + sourceByteLen: number, +): ESTree.Program; + +export declare function resetBuffer(): void; diff --git a/napi/parser/generated/deserialize/js_range_parent.d.ts b/napi/parser/generated/deserialize/js_range_parent.d.ts new file mode 100644 index 0000000000000..ecdaa9648d555 --- /dev/null +++ b/napi/parser/generated/deserialize/js_range_parent.d.ts @@ -0,0 +1,14 @@ +// Auto-generated code, DO NOT EDIT DIRECTLY! +// To edit this generated file you have to edit `tasks/ast_tools/src/generators/raw_transfer.rs`. + +import type * as ESTree from "@oxc-project/types"; + +type BufferWithArrays = Uint8Array & { uint32: Uint32Array; float64: Float64Array }; + +export declare function deserialize( + buffer: BufferWithArrays, + sourceText: string, + sourceByteLen: number, +): ESTree.Program; + +export declare function resetBuffer(): void; diff --git a/napi/parser/generated/deserialize/ts.d.ts b/napi/parser/generated/deserialize/ts.d.ts new file mode 100644 index 0000000000000..ecdaa9648d555 --- /dev/null +++ b/napi/parser/generated/deserialize/ts.d.ts @@ -0,0 +1,14 @@ +// Auto-generated code, DO NOT EDIT DIRECTLY! +// To edit this generated file you have to edit `tasks/ast_tools/src/generators/raw_transfer.rs`. + +import type * as ESTree from "@oxc-project/types"; + +type BufferWithArrays = Uint8Array & { uint32: Uint32Array; float64: Float64Array }; + +export declare function deserialize( + buffer: BufferWithArrays, + sourceText: string, + sourceByteLen: number, +): ESTree.Program; + +export declare function resetBuffer(): void; diff --git a/napi/parser/generated/deserialize/ts_parent.d.ts b/napi/parser/generated/deserialize/ts_parent.d.ts new file mode 100644 index 0000000000000..ecdaa9648d555 --- /dev/null +++ b/napi/parser/generated/deserialize/ts_parent.d.ts @@ -0,0 +1,14 @@ +// Auto-generated code, DO NOT EDIT DIRECTLY! +// To edit this generated file you have to edit `tasks/ast_tools/src/generators/raw_transfer.rs`. + +import type * as ESTree from "@oxc-project/types"; + +type BufferWithArrays = Uint8Array & { uint32: Uint32Array; float64: Float64Array }; + +export declare function deserialize( + buffer: BufferWithArrays, + sourceText: string, + sourceByteLen: number, +): ESTree.Program; + +export declare function resetBuffer(): void; diff --git a/napi/parser/generated/deserialize/ts_range.d.ts b/napi/parser/generated/deserialize/ts_range.d.ts new file mode 100644 index 0000000000000..ecdaa9648d555 --- /dev/null +++ b/napi/parser/generated/deserialize/ts_range.d.ts @@ -0,0 +1,14 @@ +// Auto-generated code, DO NOT EDIT DIRECTLY! +// To edit this generated file you have to edit `tasks/ast_tools/src/generators/raw_transfer.rs`. + +import type * as ESTree from "@oxc-project/types"; + +type BufferWithArrays = Uint8Array & { uint32: Uint32Array; float64: Float64Array }; + +export declare function deserialize( + buffer: BufferWithArrays, + sourceText: string, + sourceByteLen: number, +): ESTree.Program; + +export declare function resetBuffer(): void; diff --git a/napi/parser/generated/deserialize/ts_range_parent.d.ts b/napi/parser/generated/deserialize/ts_range_parent.d.ts new file mode 100644 index 0000000000000..ecdaa9648d555 --- /dev/null +++ b/napi/parser/generated/deserialize/ts_range_parent.d.ts @@ -0,0 +1,14 @@ +// Auto-generated code, DO NOT EDIT DIRECTLY! +// To edit this generated file you have to edit `tasks/ast_tools/src/generators/raw_transfer.rs`. + +import type * as ESTree from "@oxc-project/types"; + +type BufferWithArrays = Uint8Array & { uint32: Uint32Array; float64: Float64Array }; + +export declare function deserialize( + buffer: BufferWithArrays, + sourceText: string, + sourceByteLen: number, +): ESTree.Program; + +export declare function resetBuffer(): void; diff --git a/napi/parser/generated/visit/walk.d.ts b/napi/parser/generated/visit/walk.d.ts new file mode 100644 index 0000000000000..8df9af0421f26 --- /dev/null +++ b/napi/parser/generated/visit/walk.d.ts @@ -0,0 +1,10 @@ +// Auto-generated code, DO NOT EDIT DIRECTLY! +// To edit this generated file you have to edit `tasks/ast_tools/src/generators/estree_visit.rs`. + +import type * as ESTree from "@oxc-project/types"; + +type VisitFn = ((node: ESTree.Node) => void) | null; +type EnterExitVisitor = { enter: VisitFn; exit: VisitFn } | null; +type CompiledVisitors = (VisitFn | EnterExitVisitor)[]; + +export declare function walkProgram(program: ESTree.Program, visitors: CompiledVisitors): void; diff --git a/tasks/ast_tools/src/generators/estree_visit.rs b/tasks/ast_tools/src/generators/estree_visit.rs index 67e60e180c70a..b3f12ac3f6471 100644 --- a/tasks/ast_tools/src/generators/estree_visit.rs +++ b/tasks/ast_tools/src/generators/estree_visit.rs @@ -46,6 +46,8 @@ impl Generator for ESTreeVisitGenerator { let Codes { walk_parser, walk_oxlint, + walk_dts_parser, + walk_dts_oxlint, visitor_keys, type_ids_map_parser, type_ids_map_oxlint, @@ -58,6 +60,10 @@ impl Generator for ESTreeVisitGenerator { path: format!("{NAPI_PARSER_PACKAGE_PATH}/generated/visit/walk.js"), code: walk_parser, }, + Output::Javascript { + path: format!("{NAPI_PARSER_PACKAGE_PATH}/generated/visit/walk.d.ts"), + code: walk_dts_parser, + }, Output::Javascript { path: format!("{NAPI_PARSER_PACKAGE_PATH}/generated/visit/keys.js"), code: visitor_keys.clone(), @@ -74,6 +80,10 @@ impl Generator for ESTreeVisitGenerator { path: format!("{OXLINT_APP_PATH}/src-js/generated/walk.js"), code: walk_oxlint, }, + Output::Javascript { + path: format!("{OXLINT_APP_PATH}/src-js/generated/walk.d.ts"), + code: walk_dts_oxlint, + }, Output::Javascript { // This file is also valid as TS path: format!("{OXLINT_APP_PATH}/src-js/generated/keys.ts"), @@ -96,6 +106,8 @@ impl Generator for ESTreeVisitGenerator { struct Codes { walk_parser: String, walk_oxlint: String, + walk_dts_parser: String, + walk_dts_oxlint: String, visitor_keys: String, type_ids_map_parser: String, type_ids_map_oxlint: String, @@ -443,9 +455,45 @@ fn generate(codegen: &Codegen) -> Codes { }} "); + // Type definitions for walk.js. + // The visitors parameter is a compiled visitor array, not a VisitorObject. + // The compiled visitor is an array indexed by node type ID, where each entry is either: + // - `null` (no visitor for this node type) + // - A function (leaf node visitor) + // - `{ enter, exit }` object (non-leaf node visitor) + #[rustfmt::skip] + let walk_dts_parser = " + import type * as ESTree from '@oxc-project/types'; + + type VisitFn = ((node: ESTree.Node) => void) | null; + type EnterExitVisitor = { enter: VisitFn; exit: VisitFn } | null; + type CompiledVisitors = (VisitFn | EnterExitVisitor)[]; + + export declare function walkProgram(program: ESTree.Program, visitors: CompiledVisitors): void; + ".to_string(); + + // For oxlint, the visitors parameter is a compiled visitor array, not a VisitorObject. + // The compiled visitor is an array indexed by node type ID, where each entry is either: + // - `null` (no visitor for this node type) + // - A function (leaf node visitor) + // - `{ enter, exit }` object (non-leaf node visitor) + #[rustfmt::skip] + let walk_dts_oxlint = " + import type { Node, Program } from './types.d.ts'; + + type VisitFn = ((node: Node) => void) | null; + type EnterExitVisitor = { enter: VisitFn; exit: VisitFn } | null; + type CompiledVisitors = (VisitFn | EnterExitVisitor)[]; + + export declare function walkProgram(program: Program, visitors: CompiledVisitors): void; + export declare const ancestors: Node[]; + ".to_string(); + Codes { walk_parser, walk_oxlint, + walk_dts_parser, + walk_dts_oxlint, visitor_keys, type_ids_map_parser: type_ids_map, type_ids_map_oxlint, diff --git a/tasks/ast_tools/src/generators/raw_transfer.rs b/tasks/ast_tools/src/generators/raw_transfer.rs index 41604d51cc595..b9d74d8c3e0a9 100644 --- a/tasks/ast_tools/src/generators/raw_transfer.rs +++ b/tasks/ast_tools/src/generators/raw_transfer.rs @@ -196,6 +196,41 @@ fn generate_deserializers( }} "); + // Type definition for deserialize.js (linter variant) + #[rustfmt::skip] + let code_type_definition_linter = " + import type { Program } from './types.d.ts'; + import type { Location as SourceLocation } from '../plugins/location.ts'; + + type BufferWithArrays = Uint8Array & { uint32: Uint32Array; float64: Float64Array }; + type GetLoc = (node: { range: [number, number] }) => SourceLocation; + + export declare function deserializeProgramOnly( + buffer: BufferWithArrays, + sourceText: string, + sourceByteLen: number, + getLoc: GetLoc + ): Program; + + export declare function resetBuffer(): void; + ".to_string(); + + // Type definition for deserialize variants (parser) + #[rustfmt::skip] + let code_type_definition_parser = " + import type * as ESTree from '@oxc-project/types'; + + type BufferWithArrays = Uint8Array & { uint32: Uint32Array; float64: Float64Array }; + + export declare function deserialize( + buffer: BufferWithArrays, + sourceText: string, + sourceByteLen: number + ): ESTree.Program; + + export declare function resetBuffer(): void; + ".to_string(); + for type_def in &schema.types { match type_def { TypeDef::Struct(struct_def) => { @@ -287,7 +322,33 @@ fn generate_deserializers( let mut generator = VariantGen { variant_paths: vec![] }; let codes = generator.generate(&code); - generator.variant_paths.into_iter().zip(codes).collect() + let mut outputs: Vec<(String, String)> = + generator.variant_paths.into_iter().zip(codes).collect(); + + // Add type definition files for parser variants + for is_ts in [false, true] { + for range in [false, true] { + for parent in [false, true] { + outputs.push(( + format!( + "{NAPI_PARSER_PACKAGE_PATH}/generated/deserialize/{}{}{}.d.ts", + if is_ts { "ts" } else { "js" }, + if range { "_range" } else { "" }, + if parent { "_parent" } else { "" }, + ), + code_type_definition_parser.clone(), + )); + } + } + } + + // Add type definition file for linter + outputs.push(( + format!("{OXLINT_APP_PATH}/src-js/generated/deserialize.d.ts"), + code_type_definition_linter, + )); + + outputs } /// Type of deserializer in which some code appears.