1111import { existsSync , readdirSync , readFileSync } from "node:fs" ;
1212import { dirname , join , relative , resolve } from "node:path" ;
1313import { inspect } from "node:util" ;
14+ import { type Node as ESTreeNode , walk } from "estree-walker" ;
1415import { err , ok , Result } from "neverthrow" ;
15- import { type Node , parseSync } from "oxc-parser" ;
16+ import { type Node , type Program , parseSync } from "oxc-parser" ;
1617import { parseDocument } from "yaml" ;
1718import { z } from "zod" ;
1819import { countNoun , quote } from "../../src/text.js" ;
@@ -133,19 +134,10 @@ function layerOf(arch: Architecture, path: string): string | undefined {
133134 ) ?. [ 0 ] ;
134135}
135136
136- function * nodesOf ( value : unknown ) : Generator < Node > {
137- if ( Array . isArray ( value ) ) {
138- for ( const item of value ) {
139- yield * nodesOf ( item ) ;
140- }
141- } else if ( typeof value === "object" && value !== null ) {
142- if ( "type" in value && typeof value . type === "string" ) {
143- yield value as Node ;
144- }
145- for ( const child of Object . values ( value ) ) {
146- yield * nodesOf ( child ) ;
147- }
148- }
137+ /** `visit` on every node of `program`, preorder. estree-walker finds the children by the fields carrying a `type`,
138+ * so oxc's TypeScript nodes walk like the ESTree ones; only its signature is typed to ESTree, hence the casts. */
139+ function eachNode ( program : Program , visit : ( node : Node ) => void ) : void {
140+ walk ( program as unknown as ESTreeNode , { enter : ( node ) => visit ( node as unknown as Node ) } ) ;
149141}
150142
151143/** The expression under the wrappers parentheses and TypeScript add: `(require)(x)`, `require!(x)`,
@@ -222,9 +214,9 @@ export function importSpecifiers(text: string, file: string): string[] {
222214 ) ;
223215 }
224216 const specifiers = new Set < string > ( ) ;
225- for ( const node of nodesOf ( program ) ) {
217+ eachNode ( program , ( node ) => {
226218 if ( ! isModuleLoad ( node ) ) {
227- continue ;
219+ return ;
228220 }
229221 const specifier = literalModuleRequest ( node ) ;
230222 if ( specifier === undefined ) {
@@ -233,7 +225,7 @@ export function importSpecifiers(text: string, file: string): string[] {
233225 ) ;
234226 }
235227 specifiers . add ( specifier ) ;
236- }
228+ } ) ;
237229 return [ ...specifiers ] . filter ( ( specifier ) => / ^ \. \. ? \/ / . test ( specifier ) ) ;
238230}
239231
0 commit comments