Skip to content

Commit d9eb700

Browse files
committed
refactor(compat-eslint): 8 more shapes — type-position slots via callback
Migrates 8 more hand-written subclasses using the via-callback + whenAbsent='undefined' factory capabilities added in the previous commit: TypeReference (typeArguments via convertTypeArguments) ConstructorType (typeParameters / returnType) ModuleDeclaration (declare/global/kind from flags) EnumMember (computed from name kind) TypeAliasDeclaration (declare from modifiers) ImportEqualsDeclaration (importKind from isTypeOnly) IndexSignature (readonly/static from modifiers) PropertyAssignment (kind/method/optional/shorthand defaults + computed from name kind) Each replaces a hand-written class + switch case with a declarative defineShape entry. Custom converter callbacks (convertTypeArguments, convertTypeParameters, convertTypeAnnotation) plug in via the slot's `via` option without bespoke factory extensions. Status: 46 shapes (up from 38), 107 hand-written subclasses (down from 115). Net -94 lines this commit. All compat-eslint suites pass.
1 parent 2131195 commit d9eb700

1 file changed

Lines changed: 86 additions & 180 deletions

File tree

packages/compat-eslint/lib/lazy-estree.ts

Lines changed: 86 additions & 180 deletions
Original file line numberDiff line numberDiff line change
@@ -1510,6 +1510,92 @@ defineShape(SK.TypeOfExpression, {
15101510
defaults: { operator: 'typeof', prefix: true },
15111511
slots: { argument: { tsField: 'expression' } },
15121512
});
1513+
// Shapes that use custom converter funcs + whenAbsent='undefined' for
1514+
// type-position slots:
1515+
defineShape(SK.TypeReference, {
1516+
type: 'TSTypeReference',
1517+
slots: {
1518+
typeName: { tsField: 'typeName' },
1519+
typeArguments: { tsField: 'typeArguments', via: convertTypeArguments, whenAbsent: 'undefined' },
1520+
},
1521+
});
1522+
defineShape(SK.ConstructorType, {
1523+
type: 'TSConstructorType',
1524+
consts: (tn: ts.ConstructorTypeNode) => ({
1525+
abstract: !!tn.modifiers?.some(m => m.kind === SK.AbstractKeyword),
1526+
}),
1527+
slots: {
1528+
typeParameters: { tsField: 'typeParameters', via: convertTypeParameters, whenAbsent: 'undefined' },
1529+
params: { tsField: 'parameters', via: 'convertChildren' },
1530+
returnType: { tsField: 'type', via: convertTypeAnnotation, whenAbsent: 'undefined' },
1531+
},
1532+
});
1533+
defineShape(SK.ModuleDeclaration, {
1534+
type: 'TSModuleDeclaration',
1535+
consts: (tn: ts.ModuleDeclaration) => ({
1536+
declare: !!tn.modifiers?.some(m => m.kind === SK.DeclareKeyword),
1537+
global: !!(tn.flags & ts.NodeFlags.GlobalAugmentation),
1538+
kind: tn.flags & ts.NodeFlags.Namespace ? 'namespace' : 'module',
1539+
}),
1540+
slots: {
1541+
id: { tsField: 'name' },
1542+
body: { tsField: 'body' },
1543+
},
1544+
});
1545+
defineShape(SK.EnumMember, {
1546+
type: 'TSEnumMember',
1547+
consts: (tn: ts.EnumMember) => ({
1548+
computed: tn.name.kind === SK.ComputedPropertyName,
1549+
}),
1550+
slots: {
1551+
id: { tsField: 'name' },
1552+
initializer: { tsField: 'initializer' },
1553+
},
1554+
});
1555+
defineShape(SK.TypeAliasDeclaration, {
1556+
type: 'TSTypeAliasDeclaration',
1557+
consts: (tn: ts.TypeAliasDeclaration) => ({
1558+
declare: !!tn.modifiers?.some(m => m.kind === SK.DeclareKeyword),
1559+
}),
1560+
slots: {
1561+
id: { tsField: 'name' },
1562+
typeParameters: { tsField: 'typeParameters', via: convertTypeParameters, whenAbsent: 'undefined' },
1563+
typeAnnotation: { tsField: 'type' },
1564+
},
1565+
});
1566+
defineShape(SK.ImportEqualsDeclaration, {
1567+
type: 'TSImportEqualsDeclaration',
1568+
consts: (tn: ts.ImportEqualsDeclaration) => ({
1569+
importKind: tn.isTypeOnly ? 'type' : 'value',
1570+
}),
1571+
slots: {
1572+
id: { tsField: 'name' },
1573+
moduleReference: { tsField: 'moduleReference' },
1574+
},
1575+
});
1576+
defineShape(SK.IndexSignature, {
1577+
type: 'TSIndexSignature',
1578+
defaults: { accessibility: undefined },
1579+
consts: (tn: ts.IndexSignatureDeclaration) => ({
1580+
readonly: !!tn.modifiers?.some(m => m.kind === SK.ReadonlyKeyword),
1581+
static: !!tn.modifiers?.some(m => m.kind === SK.StaticKeyword),
1582+
}),
1583+
slots: {
1584+
parameters: { tsField: 'parameters', via: 'convertChildren' },
1585+
typeAnnotation: { tsField: 'type', via: convertTypeAnnotation, whenAbsent: 'undefined' },
1586+
},
1587+
});
1588+
defineShape(SK.PropertyAssignment, {
1589+
type: 'Property',
1590+
defaults: { kind: 'init', method: false, optional: false, shorthand: false },
1591+
consts: (tn: ts.PropertyAssignment) => ({
1592+
computed: tn.name.kind === SK.ComputedPropertyName,
1593+
}),
1594+
slots: {
1595+
key: { tsField: 'name' },
1596+
value: { tsField: 'initializer' },
1597+
},
1598+
});
15131599

15141600
function convertChildInner(child: ts.Node, parent: LazyNode): LazyNode | null {
15151601
const ShapeCls = SHAPE_CLASSES.get(child.kind);
@@ -1523,8 +1609,6 @@ function convertChildInner(child: ts.Node, parent: LazyNode): LazyNode | null {
15231609
return new VariableDeclarationNode(child as ts.VariableStatement, parent);
15241610
case SK.VariableDeclaration:
15251611
return new VariableDeclaratorNode(child as ts.VariableDeclaration, parent);
1526-
case SK.TypeReference:
1527-
return new TSTypeReferenceNode(child, parent);
15281612
case SK.NumericLiteral:
15291613
return new LiteralNode(child as ts.NumericLiteral, parent);
15301614
case SK.StringLiteral:
@@ -1614,18 +1698,12 @@ function convertChildInner(child: ts.Node, parent: LazyNode): LazyNode | null {
16141698
child as ts.ConstructSignatureDeclaration,
16151699
parent,
16161700
);
1617-
case SK.IndexSignature:
1618-
return new TSIndexSignatureNode(child as ts.IndexSignatureDeclaration, parent);
16191701
case SK.ExportDeclaration:
16201702
return convertExportDeclaration(child as ts.ExportDeclaration, parent);
16211703
case SK.ExportSpecifier:
16221704
return new ExportSpecifierNode(child as ts.ExportSpecifier, parent);
16231705
case SK.ExportAssignment:
16241706
return convertExportAssignment(child as ts.ExportAssignment, parent);
1625-
case SK.ImportEqualsDeclaration:
1626-
return new TSImportEqualsDeclarationNode(child as ts.ImportEqualsDeclaration, parent);
1627-
case SK.TypeAliasDeclaration:
1628-
return new TSTypeAliasDeclarationNode(child as ts.TypeAliasDeclaration, parent);
16291707
case SK.PrefixUnaryExpression:
16301708
return new UnaryLikeExpressionNode(child as ts.PrefixUnaryExpression, parent, true);
16311709
case SK.PostfixUnaryExpression:
@@ -1656,8 +1734,6 @@ function convertChildInner(child: ts.Node, parent: LazyNode): LazyNode | null {
16561734
return allowPattern
16571735
? new ObjectPatternFromLiteralNode(child, parent)
16581736
: new ObjectExpressionNode(child, parent);
1659-
case SK.PropertyAssignment:
1660-
return new PropertyAssignmentNode(child as ts.PropertyAssignment, parent);
16611737
case SK.ShorthandPropertyAssignment:
16621738
return new ShorthandPropertyNode(child, parent);
16631739
case SK.ComputedPropertyName:
@@ -1769,20 +1845,14 @@ function convertChildInner(child: ts.Node, parent: LazyNode): LazyNode | null {
17691845
}
17701846
case SK.PrivateIdentifier:
17711847
return new PrivateIdentifierNode(child as ts.PrivateIdentifier, parent);
1772-
case SK.ConstructorType:
1773-
return new TSConstructorTypeNode(child as ts.ConstructorTypeNode, parent);
17741848
case SK.MappedType:
17751849
return new TSMappedTypeNode(child as ts.MappedTypeNode, parent);
17761850
case SK.ThisType:
17771851
return new TSThisTypeNode(child, parent);
17781852
case SK.TypePredicate:
17791853
return new TSTypePredicateNode(child as ts.TypePredicateNode, parent);
1780-
case SK.ModuleDeclaration:
1781-
return new TSModuleDeclarationNode(child as ts.ModuleDeclaration, parent);
17821854
case SK.EnumDeclaration:
17831855
return new TSEnumDeclarationNode(child as ts.EnumDeclaration, parent);
1784-
case SK.EnumMember:
1785-
return new TSEnumMemberNode(child as ts.EnumMember, parent);
17861856
case SK.HeritageClause:
17871857
return null; // handled inline by ClassNode
17881858
case SK.VariableDeclarationList:
@@ -2171,21 +2241,6 @@ class VariableDeclaratorNode extends LazyNode {
21712241
}
21722242
}
21732243

2174-
class TSTypeReferenceNode extends LazyNode {
2175-
readonly type = 'TSTypeReference' as const;
2176-
private _typeName?: LazyNode | null;
2177-
private _typeArguments?: LazyNode | undefined;
2178-
2179-
get typeName() {
2180-
return this._typeName ??= convertChild((this._ts as ts.TypeReferenceNode).typeName, this);
2181-
}
2182-
2183-
get typeArguments() {
2184-
if (this._typeArguments !== undefined) return this._typeArguments;
2185-
return this._typeArguments = convertTypeArguments((this._ts as ts.TypeReferenceNode).typeArguments, this);
2186-
}
2187-
}
2188-
21892244
class TSTypeAnnotationNode extends LazyNode {
21902245
readonly type = 'TSTypeAnnotation' as const;
21912246
private _typeAnnotation?: LazyNode | null;
@@ -2814,31 +2869,6 @@ class PrivateIdentifierNode extends LazyNode {
28142869
}
28152870
}
28162871

2817-
class TSConstructorTypeNode extends LazyNode {
2818-
readonly type = 'TSConstructorType' as const;
2819-
readonly abstract: boolean;
2820-
private _typeParameters?: LazyNode | undefined;
2821-
private _params?: (LazyNode | null)[];
2822-
private _returnType?: LazyNode | null | undefined;
2823-
2824-
constructor(tsNode: ts.ConstructorTypeNode, parent: LazyNode) {
2825-
super(tsNode, parent);
2826-
this.abstract = !!tsNode.modifiers?.some(m => m.kind === SK.AbstractKeyword);
2827-
}
2828-
get typeParameters() {
2829-
if (this._typeParameters !== undefined) return this._typeParameters;
2830-
return this._typeParameters = convertTypeParameters((this._ts as ts.ConstructorTypeNode).typeParameters, this);
2831-
}
2832-
get params() {
2833-
return this._params ??= convertChildren((this._ts as ts.ConstructorTypeNode).parameters, this);
2834-
}
2835-
get returnType() {
2836-
if (this._returnType !== undefined) return this._returnType;
2837-
const t = (this._ts as ts.ConstructorTypeNode).type;
2838-
return this._returnType = t ? convertTypeAnnotation(t, this) : undefined;
2839-
}
2840-
}
2841-
28422872
class TSMappedTypeNode extends LazyNode {
28432873
readonly type = 'TSMappedType' as const;
28442874
readonly readonly: boolean | '+' | '-' | undefined;
@@ -2906,28 +2936,6 @@ class TSTypePredicateNode extends LazyNode {
29062936
}
29072937
}
29082938

2909-
class TSModuleDeclarationNode extends LazyNode {
2910-
readonly type = 'TSModuleDeclaration' as const;
2911-
readonly declare: boolean;
2912-
readonly global: boolean;
2913-
readonly kind: 'namespace' | 'module' | 'global';
2914-
private _id?: LazyNode | null;
2915-
private _body?: LazyNode | null;
2916-
2917-
constructor(tsNode: ts.ModuleDeclaration, parent: LazyNode) {
2918-
super(tsNode, parent);
2919-
this.declare = !!tsNode.modifiers?.some(m => m.kind === SK.DeclareKeyword);
2920-
this.global = !!(tsNode.flags & ts.NodeFlags.GlobalAugmentation);
2921-
this.kind = tsNode.flags & ts.NodeFlags.Namespace ? 'namespace' : 'module';
2922-
}
2923-
get id() {
2924-
return this._id ??= convertChild((this._ts as ts.ModuleDeclaration).name, this);
2925-
}
2926-
get body() {
2927-
return this._body ??= convertChild((this._ts as ts.ModuleDeclaration).body, this);
2928-
}
2929-
}
2930-
29312939
class TSEnumDeclarationNode extends LazyNode {
29322940
readonly type = 'TSEnumDeclaration' as const;
29332941
readonly const: boolean;
@@ -2973,23 +2981,6 @@ class TSEnumBodyNode extends LazyNode {
29732981
}
29742982
}
29752983

2976-
class TSEnumMemberNode extends LazyNode {
2977-
readonly type = 'TSEnumMember' as const;
2978-
readonly computed: boolean;
2979-
private _id?: LazyNode | null;
2980-
private _initializer?: LazyNode | null;
2981-
constructor(tsNode: ts.EnumMember, parent: LazyNode) {
2982-
super(tsNode, parent);
2983-
this.computed = tsNode.name.kind === SK.ComputedPropertyName;
2984-
}
2985-
get id() {
2986-
return this._id ??= convertChild((this._ts as ts.EnumMember).name, this);
2987-
}
2988-
get initializer() {
2989-
return this._initializer ??= convertChild((this._ts as ts.EnumMember).initializer, this);
2990-
}
2991-
}
2992-
29932984
// Pull `@dec` decorators out of a node's `modifiers` array. TS folds
29942985
// decorators and modifiers into one list since 4.8; typescript-estree
29952986
// emits them as a separate `decorators` slot on the owning ESTree node.
@@ -3053,27 +3044,6 @@ class ObjectExpressionNode extends LazyNode {
30533044
}
30543045
}
30553046

3056-
class PropertyAssignmentNode extends LazyNode {
3057-
readonly type = 'Property' as const;
3058-
readonly kind: 'init' = 'init';
3059-
readonly method = false;
3060-
readonly optional = false;
3061-
readonly shorthand = false;
3062-
readonly computed: boolean;
3063-
private _key?: LazyNode | null;
3064-
private _value?: LazyNode | null;
3065-
constructor(tsNode: ts.PropertyAssignment, parent: LazyNode) {
3066-
super(tsNode, parent);
3067-
this.computed = tsNode.name.kind === SK.ComputedPropertyName;
3068-
}
3069-
get key() {
3070-
return this._key ??= convertChild((this._ts as ts.PropertyAssignment).name, this);
3071-
}
3072-
get value() {
3073-
return this._value ??= convertChild((this._ts as ts.PropertyAssignment).initializer, this);
3074-
}
3075-
}
3076-
30773047
class ShorthandPropertyNode extends LazyNode {
30783048
readonly type = 'Property' as const;
30793049
readonly kind: 'init' = 'init';
@@ -3435,29 +3405,6 @@ class SpreadElementNode extends LazyNode {
34353405
}
34363406
}
34373407

3438-
class TSTypeAliasDeclarationNode extends LazyNode {
3439-
readonly type = 'TSTypeAliasDeclaration' as const;
3440-
readonly declare: boolean;
3441-
private _typeParameters?: LazyNode | undefined;
3442-
private _id?: LazyNode | null;
3443-
private _typeAnnotation?: LazyNode | null;
3444-
3445-
constructor(tsNode: ts.TypeAliasDeclaration, parent: LazyNode) {
3446-
super(tsNode, parent);
3447-
this.declare = !!tsNode.modifiers?.some(m => m.kind === SK.DeclareKeyword);
3448-
}
3449-
get id() {
3450-
return this._id ??= convertChild((this._ts as ts.TypeAliasDeclaration).name, this);
3451-
}
3452-
get typeParameters() {
3453-
if (this._typeParameters !== undefined) return this._typeParameters;
3454-
return this._typeParameters = convertTypeParameters((this._ts as ts.TypeAliasDeclaration).typeParameters, this);
3455-
}
3456-
get typeAnnotation() {
3457-
return this._typeAnnotation ??= convertChild((this._ts as ts.TypeAliasDeclaration).type, this);
3458-
}
3459-
}
3460-
34613408
// Prefix/postfix unary expressions: ++/-- become UpdateExpression, others
34623409
// become UnaryExpression (matches typescript-estree's split at line 2188).
34633410
class UnaryLikeExpressionNode extends LazyNode {
@@ -3675,24 +3622,6 @@ class TSExportAssignmentNode extends LazyNode {
36753622
}
36763623
}
36773624

3678-
class TSImportEqualsDeclarationNode extends LazyNode {
3679-
readonly type = 'TSImportEqualsDeclaration' as const;
3680-
readonly importKind: 'value' | 'type';
3681-
private _id?: LazyNode | null;
3682-
private _moduleReference?: LazyNode | null;
3683-
3684-
constructor(tsNode: ts.ImportEqualsDeclaration, parent: LazyNode) {
3685-
super(tsNode, parent);
3686-
this.importKind = tsNode.isTypeOnly ? 'type' : 'value';
3687-
}
3688-
get id() {
3689-
return this._id ??= convertChild((this._ts as ts.ImportEqualsDeclaration).name, this);
3690-
}
3691-
get moduleReference() {
3692-
return this._moduleReference ??= convertChild((this._ts as ts.ImportEqualsDeclaration).moduleReference, this);
3693-
}
3694-
}
3695-
36963625
// CallSignature + ConstructSignature share a shape — params + returnType +
36973626
// typeParameters. typescript-estree picks the type literal at construction.
36983627
class TSCallishSignatureNode extends LazyNode {
@@ -3723,29 +3652,6 @@ class TSCallishSignatureNode extends LazyNode {
37233652
}
37243653
}
37253654

3726-
class TSIndexSignatureNode extends LazyNode {
3727-
readonly type = 'TSIndexSignature' as const;
3728-
readonly accessibility = undefined;
3729-
readonly readonly: boolean;
3730-
readonly static: boolean;
3731-
private _parameters?: (LazyNode | null)[];
3732-
private _typeAnnotation?: LazyNode | null | undefined;
3733-
3734-
constructor(tsNode: ts.IndexSignatureDeclaration, parent: LazyNode) {
3735-
super(tsNode, parent);
3736-
this.readonly = !!tsNode.modifiers?.some(m => m.kind === SK.ReadonlyKeyword);
3737-
this.static = !!tsNode.modifiers?.some(m => m.kind === SK.StaticKeyword);
3738-
}
3739-
get parameters() {
3740-
return this._parameters ??= convertChildren((this._ts as ts.IndexSignatureDeclaration).parameters, this);
3741-
}
3742-
get typeAnnotation() {
3743-
if (this._typeAnnotation !== undefined) return this._typeAnnotation;
3744-
const t = (this._ts as ts.IndexSignatureDeclaration).type;
3745-
return this._typeAnnotation = t ? convertTypeAnnotation(t, this) : undefined;
3746-
}
3747-
}
3748-
37493655
// Interface — `body` is wrapped in a synthetic TSInterfaceBody whose range
37503656
// starts one char before the first member (the `{`). MVP skips
37513657
// heritageClauses + typeParameters (the `extends` and generics array).

0 commit comments

Comments
 (0)