From 85e693316af092e16f8d242fabbda5745159acdc Mon Sep 17 00:00:00 2001 From: fisker Date: Thu, 11 Sep 2025 07:17:29 +0800 Subject: [PATCH 1/3] refactor(typescript-estree): add `Converter#covertChildren()` --- packages/typescript-estree/src/convert.ts | 111 +++++++++++----------- 1 file changed, 54 insertions(+), 57 deletions(-) diff --git a/packages/typescript-estree/src/convert.ts b/packages/typescript-estree/src/convert.ts index 0ffc735c3a14..219c5431fd74 100644 --- a/packages/typescript-estree/src/convert.ts +++ b/packages/typescript-estree/src/convert.ts @@ -643,6 +643,19 @@ export class Converter { return this.converter(child, parent, false); } + /** + * Converts TypeScript node array into an ESTree node list. + * @param children the child `ts.NodeArray` or `ts.Node[]` + * @param parent parentNode + * @returns the converted ESTree node list + */ + private convertChildren( + children?: ts.NodeArray | ts.Node[], + parent?: ts.Node, + ): any { + return children?.map(child => this.converter(child, parent, false)); + } + /** * Converts a TypeScript node into an ESTree node. * @param child the child ts.Node @@ -702,9 +715,7 @@ export class Converter { return this.createNode(node, { type: AST_NODE_TYPES.TSTypeParameterInstantiation, range, - params: typeArguments.map(typeArgument => - this.convertChild(typeArgument), - ), + params: this.convertChildren(typeArguments), }); } @@ -730,9 +741,7 @@ export class Converter { type: AST_NODE_TYPES.TSTypeParameterDeclaration, loc: getLocFor(range, this.ast), range, - params: typeParameters.map(typeParameter => - this.convertChild(typeParameter), - ), + params: this.convertChildren(typeParameters), } as TSESTree.TSTypeParameterDeclaration; } @@ -750,8 +759,9 @@ export class Converter { return parameters.map(param => { const convertedParam = this.convertChild(param) as TSESTree.Parameter; - convertedParam.decorators = - getDecorators(param)?.map(el => this.convertChild(el)) ?? []; + convertedParam.decorators = this.convertChildren( + getDecorators(param) ?? [], + ); return convertedParam; }); @@ -797,9 +807,7 @@ export class Converter { private convertImportAttributes( node: ts.ImportAttributes | undefined, ): TSESTree.ImportAttribute[] { - return node == null - ? [] - : node.elements.map(element => this.convertChild(element)); + return node == null ? [] : this.convertChildren(node.elements); } private convertJSXIdentifier( @@ -1060,7 +1068,7 @@ export class Converter { return this.createNode(node, { type: AST_NODE_TYPES.SwitchStatement, - cases: node.caseBlock.clauses.map(el => this.convertChild(el)), + cases: this.convertChildren(node.caseBlock.clauses), discriminant: this.convertChild(node.expression), }); @@ -1069,7 +1077,7 @@ export class Converter { return this.createNode(node, { type: AST_NODE_TYPES.SwitchCase, // expression is present in case only - consequent: node.statements.map(el => this.convertChild(el)), + consequent: this.convertChildren(node.statements), test: node.kind === SyntaxKind.CaseClause ? this.convertChild(node.expression) @@ -1259,9 +1267,7 @@ export class Converter { case SyntaxKind.VariableStatement: { const result = this.createNode(node, { type: AST_NODE_TYPES.VariableDeclaration, - declarations: node.declarationList.declarations.map(el => - this.convertChild(el), - ), + declarations: this.convertChildren(node.declarationList.declarations), declare: hasModifier(SyntaxKind.DeclareKeyword, node), kind: getDeclarationKind(node.declarationList), }); @@ -1338,7 +1344,7 @@ export class Converter { case SyntaxKind.VariableDeclarationList: { const result = this.createNode(node, { type: AST_NODE_TYPES.VariableDeclaration, - declarations: node.declarations.map(el => this.convertChild(el)), + declarations: this.convertChildren(node.declarations), declare: false, kind: getDeclarationKind(node), }); @@ -1382,14 +1388,14 @@ export class Converter { return this.createNode(node, { type: AST_NODE_TYPES.ArrayPattern, decorators: [], - elements: node.elements.map(el => this.convertPattern(el)), + elements: this.convertChildren(node.elements), optional: false, typeAnnotation: undefined, }); } return this.createNode(node, { type: AST_NODE_TYPES.ArrayExpression, - elements: node.elements.map(el => this.convertChild(el)), + elements: this.convertChildren(node.elements), }); } @@ -1551,8 +1557,7 @@ export class Converter { accessibility: getTSNodeAccessibility(node), computed: isComputedProperty(node.name), declare: hasModifier(SyntaxKind.DeclareKeyword, node), - decorators: - getDecorators(node)?.map(el => this.convertChild(el)) ?? [], + decorators: this.convertChildren(getDecorators(node) ?? []), definite: !!node.exclamationToken, key, optional: @@ -1614,7 +1619,7 @@ export class Converter { | TSESTree.TSAbstractMethodDefinition; if (parent.kind === SyntaxKind.ObjectLiteralExpression) { - method.params = node.parameters.map(el => this.convertChild(el)); + method.params = this.convertChildren(node.parameters); result = this.createNode(node, { type: AST_NODE_TYPES.Property, @@ -1650,8 +1655,7 @@ export class Converter { type: methodDefinitionType, accessibility: getTSNodeAccessibility(node), computed: isComputedProperty(node.name), - decorators: - getDecorators(node)?.map(el => this.convertChild(el)) ?? [], + decorators: this.convertChildren(getDecorators(node) ?? []), key: this.convertChild(node.name), kind: 'method', optional: !!node.questionToken, @@ -2133,16 +2137,14 @@ export class Converter { body: this.createNode(node, { type: AST_NODE_TYPES.ClassBody, range: [node.members.pos - 1, node.end], - body: node.members - .filter(isESTreeClassMember) - .map(el => this.convertChild(el)), + body: this.convertChildren( + node.members.filter(isESTreeClassMember), + ), }), declare: hasModifier(SyntaxKind.DeclareKeyword, node), - decorators: - getDecorators(node)?.map(el => this.convertChild(el)) ?? [], + decorators: this.convertChildren(getDecorators(node) ?? []), id: this.convertChild(node.name), - implements: - implementsClause?.types.map(el => this.convertChild(el)) ?? [], + implements: this.convertChildren(implementsClause?.types ?? []), superClass: extendsClause?.types[0] ? this.convertChild(extendsClause.types[0].expression) : null, @@ -2219,8 +2221,8 @@ export class Converter { break; case SyntaxKind.NamedImports: result.specifiers.push( - ...node.importClause.namedBindings.elements.map( - el => this.convertChild(el) as TSESTree.ImportClause, + ...this.convertChildren( + node.importClause.namedBindings.elements, ), ); break; @@ -2268,8 +2270,9 @@ export class Converter { declaration: null, exportKind: node.isTypeOnly ? 'type' : 'value', source: this.convertChild(node.moduleSpecifier), - specifiers: node.exportClause.elements.map(el => - this.convertChild(el, node), + specifiers: this.convertChildren( + node.exportClause.elements, + node, ), }, 'assertions', @@ -2508,7 +2511,7 @@ export class Converter { } const callee = this.convertChild(node.expression); - const args = node.arguments.map(el => this.convertChild(el)); + const args = this.convertChildren(node.arguments); const typeArguments = node.typeArguments && this.convertTypeArgumentsToTypeParameterInstantiation( @@ -2538,9 +2541,7 @@ export class Converter { // NOTE - NewExpression cannot have an optional chain in it return this.createNode(node, { type: AST_NODE_TYPES.NewExpression, - arguments: node.arguments - ? node.arguments.map(el => this.convertChild(el)) - : [], + arguments: this.convertChildren(node.arguments ?? []), callee: this.convertChild(node.expression), typeArguments, }); @@ -2678,7 +2679,7 @@ export class Converter { case SyntaxKind.JsxElement: return this.createNode(node, { type: AST_NODE_TYPES.JSXElement, - children: node.children.map(el => this.convertChild(el)), + children: this.convertChildren(node.children), closingElement: this.convertChild(node.closingElement), openingElement: this.convertChild(node.openingElement), }); @@ -2686,7 +2687,7 @@ export class Converter { case SyntaxKind.JsxFragment: return this.createNode(node, { type: AST_NODE_TYPES.JSXFragment, - children: node.children.map(el => this.convertChild(el)), + children: this.convertChildren(node.children), closingFragment: this.convertChild(node.closingFragment), openingFragment: this.convertChild(node.openingFragment), }); @@ -2703,9 +2704,7 @@ export class Converter { openingElement: this.createNode(node, { type: AST_NODE_TYPES.JSXOpeningElement, range: getRange(node, this.ast), - attributes: node.attributes.properties.map(el => - this.convertChild(el), - ), + attributes: this.convertChildren(node.attributes.properties), name: this.convertJSXTagName(node.tagName, node), selfClosing: true, typeArguments: node.typeArguments @@ -2721,9 +2720,7 @@ export class Converter { case SyntaxKind.JsxOpeningElement: { return this.createNode(node, { type: AST_NODE_TYPES.JSXOpeningElement, - attributes: node.attributes.properties.map(el => - this.convertChild(el), - ), + attributes: this.convertChildren(node.attributes.properties), name: this.convertJSXTagName(node.tagName, node), selfClosing: false, typeArguments: @@ -2866,7 +2863,7 @@ export class Converter { case SyntaxKind.TypeLiteral: { return this.createNode(node, { type: AST_NODE_TYPES.TSTypeLiteral, - members: node.members.map(el => this.convertChild(el)), + members: this.convertChildren(node.members), }); } @@ -2990,7 +2987,7 @@ export class Converter { return this.createNode(node, { type: AST_NODE_TYPES.TSIndexSignature, accessibility: getTSNodeAccessibility(node), - parameters: node.parameters.map(el => this.convertChild(el)), + parameters: this.convertChildren(node.parameters), readonly: hasModifier(SyntaxKind.ReadonlyKeyword, node), static: hasModifier(SyntaxKind.StaticKeyword, node), typeAnnotation: @@ -3116,7 +3113,7 @@ export class Converter { body: this.createNode(node, { type: AST_NODE_TYPES.TSInterfaceBody, range: [node.members.pos - 1, node.end], - body: node.members.map(member => this.convertChild(member)), + body: this.convertChildren(node.members), }), declare: hasModifier(SyntaxKind.DeclareKeyword, node), extends: interfaceExtends, @@ -3252,7 +3249,7 @@ export class Converter { } case SyntaxKind.EnumDeclaration: { - const members = node.members.map(el => this.convertChild(el)); + const members = this.convertChildren(node.members); const result = this.createNode( node, this.#withDeprecatedGetter( @@ -3269,7 +3266,7 @@ export class Converter { }, 'members', `'body.members'`, - node.members.map(el => this.convertChild(el)), + this.convertChildren(node.members), ), ); @@ -3446,13 +3443,13 @@ export class Converter { case SyntaxKind.UnionType: { return this.createNode(node, { type: AST_NODE_TYPES.TSUnionType, - types: node.types.map(el => this.convertChild(el)), + types: this.convertChildren(node.types), }); } case SyntaxKind.IntersectionType: { return this.createNode(node, { type: AST_NODE_TYPES.TSIntersectionType, - types: node.types.map(el => this.convertChild(el)), + types: this.convertChildren(node.types), }); } case SyntaxKind.AsExpression: { @@ -3526,7 +3523,7 @@ export class Converter { // Tuple case SyntaxKind.TupleType: { - const elementTypes = node.elements.map(el => this.convertChild(el)); + const elementTypes = this.convertChildren(node.elements); return this.createNode(node, { type: AST_NODE_TYPES.TSTupleType, @@ -3685,7 +3682,7 @@ export class Converter { } const decorators = getDecorators(node); if (decorators?.length) { - result.decorators = decorators.map(el => this.convertChild(el)); + result.decorators = this.convertChildren(decorators); } // keys we never want to clone from the base typescript node as they @@ -3717,7 +3714,7 @@ export class Converter { .filter(([key]) => !KEYS_TO_NOT_COPY.has(key)) .forEach(([key, value]) => { if (Array.isArray(value)) { - result[key] = value.map(el => this.convertChild(el as TSNode)); + result[key] = this.convertChildren(value); } else if (value && typeof value === 'object' && value.kind) { // need to check node[key].kind to ensure we don't try to convert a symbol result[key] = this.convertChild(value as TSNode); From 66495b4b4e3cf9c7bb83a337fcfdbbcf912b5917 Mon Sep 17 00:00:00 2001 From: fisker Date: Thu, 11 Sep 2025 07:28:04 +0800 Subject: [PATCH 2/3] Linting --- packages/typescript-estree/src/convert.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/typescript-estree/src/convert.ts b/packages/typescript-estree/src/convert.ts index 219c5431fd74..a973c052b2d1 100644 --- a/packages/typescript-estree/src/convert.ts +++ b/packages/typescript-estree/src/convert.ts @@ -650,7 +650,7 @@ export class Converter { * @returns the converted ESTree node list */ private convertChildren( - children?: ts.NodeArray | ts.Node[], + children?: ts.Node[] | ts.NodeArray, parent?: ts.Node, ): any { return children?.map(child => this.converter(child, parent, false)); @@ -2221,9 +2221,9 @@ export class Converter { break; case SyntaxKind.NamedImports: result.specifiers.push( - ...this.convertChildren( + ...(this.convertChildren( node.importClause.namedBindings.elements, - ), + ) as TSESTree.ImportClause[]), ); break; } From 76736ffbd8a6b33a29ad6a02e353e4ee9ebe7cef Mon Sep 17 00:00:00 2001 From: fisker Date: Thu, 11 Sep 2025 08:16:17 +0800 Subject: [PATCH 3/3] Fix --- packages/typescript-estree/src/convert.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/typescript-estree/src/convert.ts b/packages/typescript-estree/src/convert.ts index a973c052b2d1..5af31f740712 100644 --- a/packages/typescript-estree/src/convert.ts +++ b/packages/typescript-estree/src/convert.ts @@ -1388,7 +1388,7 @@ export class Converter { return this.createNode(node, { type: AST_NODE_TYPES.ArrayPattern, decorators: [], - elements: this.convertChildren(node.elements), + elements: node.elements.map(el => this.convertPattern(el)), optional: false, typeAnnotation: undefined, });