ripple 0.2.183 → 0.2.184

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Ripple is an elegant TypeScript UI framework",
4
4
  "license": "MIT",
5
5
  "author": "Dominic Gannaway",
6
- "version": "0.2.183",
6
+ "version": "0.2.184",
7
7
  "type": "module",
8
8
  "module": "src/runtime/index-client.js",
9
9
  "main": "src/runtime/index-client.js",
@@ -86,6 +86,6 @@
86
86
  "vscode-languageserver-types": "^3.17.5"
87
87
  },
88
88
  "peerDependencies": {
89
- "ripple": "0.2.183"
89
+ "ripple": "0.2.184"
90
90
  }
91
91
  }
@@ -728,9 +728,9 @@ const visitors = {
728
728
  }
729
729
  if (state.inside_head) {
730
730
  if (node.id.name === 'title') {
731
- const chiildren = normalize_children(node.children, context);
731
+ const children = normalize_children(node.children, context);
732
732
 
733
- if (chiildren.length !== 1 || chiildren[0].type !== 'Text') {
733
+ if (children.length !== 1 || children[0].type !== 'Text') {
734
734
  error(
735
735
  '<title> must have only contain text nodes',
736
736
  state.analysis.module.filename,
@@ -1,13 +1,13 @@
1
- /** @import { CustomMappingData, PluginActionOverrides } from 'ripple/compiler'; */
2
- /** @import { DocumentHighlightKind } from 'vscode-languageserver-types'; */
1
+ /**
2
+ @import { CustomMappingData, PluginActionOverrides } from 'ripple/compiler';
3
+ @import { DocumentHighlightKind } from 'vscode-languageserver-types';
4
+ @import * as AST from 'estree';
5
+ @import * as ESTreeJSX from 'estree-jsx';
6
+ @import {MappingData, CodeMapping, VolarMappingsResult} from 'ripple/compiler';
7
+ @import {CodeMapping as VolarCodeMapping} from '@volar/language-core';
8
+ */
3
9
 
4
10
  /**
5
- * @typedef {import('estree').Position} Position
6
- * @typedef {{start: Position, end: Position}} Location
7
- * @typedef {import('@volar/language-core').CodeMapping} VolarCodeMapping
8
- * @typedef {import('ripple/compiler').MappingData} MappingData
9
- * @typedef {import('ripple/compiler').CodeMapping} CodeMapping
10
- * @typedef {import('ripple/compiler').VolarMappingsResult} VolarMappingsResult
11
11
  * @typedef {{
12
12
  * start: number,
13
13
  * end: number,
@@ -61,7 +61,7 @@ function loc_to_offset(line, column, line_offsets) {
61
61
 
62
62
  /**
63
63
  * Extract CSS source regions from style elements in the AST
64
- * @param {any} ast - The parsed AST
64
+ * @param {AST.Node} ast - The parsed AST
65
65
  * @param {string} source - Original source code
66
66
  * @param {number[]} source_line_offsets
67
67
  * @returns {CssSourceRegion[]}
@@ -74,10 +74,14 @@ function extractCssSourceRegions(ast, source, source_line_offsets) {
74
74
  Element(node) {
75
75
  // Check if this is a style element with CSS content
76
76
  if (node.id?.name === 'style' && node.css) {
77
- const openLoc = node.openingElement.loc;
77
+ const openLoc = /** @type {ESTreeJSX.JSXOpeningElement & AST.NodeWithLocation} */ (
78
+ node.openingElement
79
+ ).loc;
78
80
  const cssStart = loc_to_offset(openLoc.end.line, openLoc.end.column, source_line_offsets);
79
81
 
80
- const closeLoc = node.closingElement.loc;
82
+ const closeLoc = /** @type {ESTreeJSX.JSXClosingElement & AST.NodeWithLocation} */ (
83
+ node.closingElement
84
+ ).loc;
81
85
  const cssEnd = loc_to_offset(
82
86
  closeLoc.start.line,
83
87
  closeLoc.start.column,
@@ -102,8 +106,8 @@ function extractCssSourceRegions(ast, source, source_line_offsets) {
102
106
 
103
107
  /**
104
108
  * Create Volar mappings by walking the transformed AST
105
- * @param {any} ast - The transformed AST
106
- * @param {any} ast_from_source - The original AST from source
109
+ * @param {AST.Node} ast - The transformed AST
110
+ * @param {AST.Node} ast_from_source - The original AST from source
107
111
  * @param {string} source - Original source code
108
112
  * @param {string} generated_code - Generated code (returned in output, not used for searching)
109
113
  * @param {object} esrap_source_map - Esrap source map for accurate position lookup
@@ -147,17 +151,18 @@ export function convert_source_map_to_mappings(
147
151
  // All tokens must have source/generated text and loc property for accurate positioning
148
152
  /**
149
153
  * @type {Array<{
150
- * source: string,
154
+ * source: string | null | undefined,
151
155
  * generated: string,
152
156
  * is_full_import_statement?: boolean,
153
- * loc: Location,
154
- * end_loc?: Location,
157
+ * loc: AST.SourceLocation,
158
+ * end_loc?: AST.SourceLocation,
155
159
  * metadata?: PluginActionOverrides
156
160
  * }>}
157
161
  */
158
162
  const tokens = [];
159
163
 
160
164
  // We have to visit everything in generated order to maintain correct indices
165
+
161
166
  walk(ast, null, {
162
167
  _(node, { visit }) {
163
168
  // Collect key node types: Identifiers, Literals, and JSX Elements
@@ -231,7 +236,11 @@ export function convert_source_map_to_mappings(
231
236
  } else if (node.type === 'ImportSpecifier') {
232
237
  // If local and imported are the same, only visit local to avoid duplicates
233
238
  // Otherwise visit both in order
234
- if (node.imported && node.local && node.imported.name !== node.local.name) {
239
+ if (
240
+ node.imported &&
241
+ node.local &&
242
+ /** @type {AST.Identifier} */ (node.imported).name !== node.local.name
243
+ ) {
235
244
  visit(node.imported);
236
245
  visit(node.local);
237
246
  } else if (node.local) {
@@ -250,7 +259,12 @@ export function convert_source_map_to_mappings(
250
259
  } else if (node.type === 'ExportSpecifier') {
251
260
  // If local and exported are the same, only visit local to avoid duplicates
252
261
  // Otherwise visit both in order
253
- if (node.local && node.exported && node.local.name !== node.exported.name) {
262
+ if (
263
+ node.local &&
264
+ node.exported &&
265
+ /** @type {AST.Identifier} */ (node.local).name !==
266
+ /** @type {AST.Identifier} */ (node.exported).name
267
+ ) {
254
268
  visit(node.local);
255
269
  visit(node.exported);
256
270
  } else if (node.local) {
@@ -271,7 +285,7 @@ export function convert_source_map_to_mappings(
271
285
  } else if (node.type === 'ExportDefaultDeclaration') {
272
286
  // Visit the declaration
273
287
  if (node.declaration) {
274
- visit(node.declaration);
288
+ visit(/** @type {AST.Node} */ (node.declaration));
275
289
  }
276
290
  return;
277
291
  } else if (node.type === 'ExportAllDeclaration') {
@@ -357,7 +371,7 @@ export function convert_source_map_to_mappings(
357
371
  // 2. Visit children in order
358
372
  if (node.children) {
359
373
  for (const child of node.children) {
360
- visit(child);
374
+ visit(/** @type {AST.Node} */ (child));
361
375
  }
362
376
  }
363
377
 
@@ -366,7 +380,9 @@ export function convert_source_map_to_mappings(
366
380
  !node.openingElement?.selfClosing &&
367
381
  node.closingElement?.name?.type === 'JSXIdentifier'
368
382
  ) {
369
- const closingNameNode = node.closingElement.name;
383
+ const closingNameNode = /** @type {ESTreeJSX.JSXIdentifier & AST.NodeWithLocation} */ (
384
+ node.closingElement.name
385
+ );
370
386
  if (closingNameNode.metadata?.is_capitalized) {
371
387
  tokens.push({
372
388
  source: closingNameNode.metadata.original_name,
@@ -390,24 +406,25 @@ export function convert_source_map_to_mappings(
390
406
  ) {
391
407
  // Add function/component keyword token
392
408
  if (node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression') {
409
+ const node_fn = /** @type (typeof node) & AST.NodeWithLocation */ (node);
393
410
  const source_keyword = node.metadata?.was_component ? 'component' : 'function';
394
411
  // Add token for the keyword - esrap already mapped it via context.write('function', node)
395
412
  tokens.push({
396
413
  source: source_keyword,
397
414
  generated: 'function',
398
415
  loc: {
399
- start: { line: node.loc.start.line, column: node.loc.start.column },
416
+ start: { line: node_fn.loc.start.line, column: node_fn.loc.start.column },
400
417
  end: {
401
- line: node.loc.start.line,
402
- column: node.loc.start.column + source_keyword.length,
418
+ line: node_fn.loc.start.line,
419
+ column: node_fn.loc.start.column + source_keyword.length,
403
420
  },
404
421
  },
405
422
  });
406
423
  }
407
424
 
408
425
  // Visit in source order: id, params, body
409
- if (node.id) {
410
- visit(node.id);
426
+ if (/** @type {AST.FunctionDeclaration | AST.FunctionExpression} */ (node).id) {
427
+ visit(/** @type {AST.FunctionDeclaration | AST.FunctionExpression} */ (node).id);
411
428
  }
412
429
  if (node.params) {
413
430
  for (const param of node.params) {
@@ -478,8 +495,8 @@ export function convert_source_map_to_mappings(
478
495
  visit(node.right);
479
496
  }
480
497
  // Ripple-specific: index variable
481
- if (node.index) {
482
- visit(node.index);
498
+ if (/** @type {AST.ForOfStatement} */ (node).index) {
499
+ visit(/** @type {AST.ForOfStatement} */ (node).index);
483
500
  }
484
501
  if (node.body) {
485
502
  visit(node.body);
@@ -511,14 +528,17 @@ export function convert_source_map_to_mappings(
511
528
  if (node.pending) {
512
529
  // Add a special token for the 'pending' keyword with customData
513
530
  // to suppress TypeScript diagnostics and provide custom hover/definition
531
+ const pending = /** @type {(typeof node.pending) & AST.NodeWithLocation} */ (
532
+ node.pending
533
+ );
514
534
  const pendingKeywordLoc = {
515
535
  start: {
516
- line: node.pending.loc.start.line,
517
- column: node.pending.loc.start.column - 'pending '.length,
536
+ line: pending.loc.start.line,
537
+ column: pending.loc.start.column - 'pending '.length,
518
538
  },
519
539
  end: {
520
- line: node.pending.loc.start.line,
521
- column: node.pending.loc.start.column - 1,
540
+ line: pending.loc.start.line,
541
+ column: pending.loc.start.column - 1,
522
542
  },
523
543
  };
524
544
  tokens.push({
@@ -764,8 +784,8 @@ export function convert_source_map_to_mappings(
764
784
  if (node.argument) {
765
785
  visit(node.argument);
766
786
  // Visit type annotation if present (for RestElement)
767
- if (node.argument.typeAnnotation) {
768
- visit(node.argument.typeAnnotation);
787
+ if (/** @type {AST.Pattern} */ (node.argument).typeAnnotation) {
788
+ visit(/** @type {AST.Pattern} */ (node.argument).typeAnnotation);
769
789
  }
770
790
  }
771
791
  // RestElement itself can have typeAnnotation
@@ -828,7 +848,7 @@ export function convert_source_map_to_mappings(
828
848
  // Visit children in order
829
849
  if (node.children) {
830
850
  for (const child of node.children) {
831
- visit(child);
851
+ visit(/** @type {AST.Node} */ (child));
832
852
  }
833
853
  }
834
854
  return;
@@ -956,10 +976,11 @@ export function convert_source_map_to_mappings(
956
976
  if (node.typeName) {
957
977
  visit(node.typeName);
958
978
  }
959
- // Check both typeParameters and typeArguments (different parsers use different names)
960
- if (node.typeParameters) {
961
- visit(node.typeParameters);
962
- }
979
+
980
+ // typeParameters and typeArguments (different parsers use different names)
981
+ // tsTypeParameters is a bug in the estree-typescript
982
+ // but we fixed in the analyzer to typeArguments.
983
+
963
984
  if (node.typeArguments) {
964
985
  visit(node.typeArguments);
965
986
  }
@@ -1004,8 +1025,13 @@ export function convert_source_map_to_mappings(
1004
1025
  for (const param of node.parameters) {
1005
1026
  visit(param);
1006
1027
  // Visit type annotation on the parameter
1007
- if (param.typeAnnotation) {
1008
- visit(param.typeAnnotation);
1028
+ if (
1029
+ /** @type {Exclude<AST.Parameter, AST.TSParameterProperty>} */ (param).typeAnnotation
1030
+ ) {
1031
+ visit(
1032
+ /** @type {Exclude<AST.Parameter, AST.TSParameterProperty>} */ (param)
1033
+ .typeAnnotation,
1034
+ );
1009
1035
  }
1010
1036
  }
1011
1037
  }
@@ -1042,8 +1068,13 @@ export function convert_source_map_to_mappings(
1042
1068
  for (const param of node.parameters) {
1043
1069
  visit(param);
1044
1070
  // Visit type annotation on the parameter
1045
- if (param.typeAnnotation) {
1046
- visit(param.typeAnnotation);
1071
+ if (
1072
+ /** @type {Exclude<AST.Parameter, AST.TSParameterProperty>} */ (param).typeAnnotation
1073
+ ) {
1074
+ visit(
1075
+ /** @type {Exclude<AST.Parameter, AST.TSParameterProperty>} */ (param)
1076
+ .typeAnnotation,
1077
+ );
1047
1078
  }
1048
1079
  }
1049
1080
  }
@@ -1057,8 +1088,13 @@ export function convert_source_map_to_mappings(
1057
1088
  for (const param of node.parameters) {
1058
1089
  visit(param);
1059
1090
  // Visit type annotation on the parameter
1060
- if (param.typeAnnotation) {
1061
- visit(param.typeAnnotation);
1091
+ if (
1092
+ /** @type {Exclude<AST.Parameter, AST.TSParameterProperty>} */ (param).typeAnnotation
1093
+ ) {
1094
+ visit(
1095
+ /** @type {Exclude<AST.Parameter, AST.TSParameterProperty>} */ (param)
1096
+ .typeAnnotation,
1097
+ );
1062
1098
  }
1063
1099
  }
1064
1100
  }
@@ -1078,8 +1114,13 @@ export function convert_source_map_to_mappings(
1078
1114
  for (const param of node.parameters) {
1079
1115
  visit(param);
1080
1116
  // Visit type annotation on the parameter
1081
- if (param.typeAnnotation) {
1082
- visit(param.typeAnnotation);
1117
+ if (
1118
+ /** @type {Exclude<AST.Parameter, AST.TSParameterProperty>} */ (param).typeAnnotation
1119
+ ) {
1120
+ visit(
1121
+ /** @type {Exclude<AST.Parameter, AST.TSParameterProperty>} */ (param)
1122
+ .typeAnnotation,
1123
+ );
1083
1124
  }
1084
1125
  }
1085
1126
  }
@@ -1170,6 +1211,9 @@ export function convert_source_map_to_mappings(
1170
1211
  if (node.exprName) {
1171
1212
  visit(node.exprName);
1172
1213
  }
1214
+ if (node.typeArguments) {
1215
+ visit(node.typeArguments);
1216
+ }
1173
1217
  return;
1174
1218
  } else if (node.type === 'TSInterfaceDeclaration') {
1175
1219
  // Interface declaration
@@ -1327,7 +1371,7 @@ export function convert_source_map_to_mappings(
1327
1371
  });
1328
1372
 
1329
1373
  for (const token of tokens) {
1330
- const source_text = token.source;
1374
+ const source_text = token.source ?? '';
1331
1375
  const gen_text = token.generated;
1332
1376
 
1333
1377
  const source_start = loc_to_offset(
@@ -1344,7 +1388,7 @@ export function convert_source_map_to_mappings(
1344
1388
  let gen_start;
1345
1389
 
1346
1390
  if (token.is_full_import_statement) {
1347
- const end_loc = /** @type {Location} */ (token.end_loc).end;
1391
+ const end_loc = /** @type {AST.SourceLocation} */ (token.end_loc).end;
1348
1392
  const source_end = loc_to_offset(end_loc.line, end_loc.column, source_line_offsets);
1349
1393
 
1350
1394
  // Look up where import keyword and source literal map to in generated code
@@ -1,5 +1,12 @@
1
- /** @import { Binding, ScopeInterface, ScopeRoot as ScopeRootInterface } from '#compiler' */
2
- /** @import * as AST from 'estree' */
1
+ /**
2
+ @import {
3
+ Binding,
4
+ ScopeInterface,
5
+ ScopeRoot as ScopeRootInterface,
6
+ Context
7
+ } from '#compiler';
8
+ @import * as AST from 'estree';
9
+ */
3
10
 
4
11
  import is_reference from 'is-reference';
5
12
  import { extract_identifiers, object, unwrap_pattern } from '../utils/ast.js';
@@ -45,7 +52,7 @@ export function create_scopes(ast, root, parent) {
45
52
  /**
46
53
  * Create a block scope
47
54
  * @param {AST.Node} node - AST node
48
- * @param {{ state: any, next: Function }} context - Visitor context
55
+ * @param {Context<AST.Node, State>} context - Visitor context
49
56
  */
50
57
  const create_block_scope = (node, { state, next }) => {
51
58
  const scope = state.scope.child(true);
@@ -60,7 +67,7 @@ export function create_scopes(ast, root, parent) {
60
67
  next({ scope });
61
68
  };
62
69
 
63
- walk(/** @type {AST.Node} */ (ast), state, {
70
+ walk(ast, state, {
64
71
  // references
65
72
  Identifier(node, { path, state }) {
66
73
  const parent = path.at(-1);
@@ -95,12 +102,6 @@ export function create_scopes(ast, root, parent) {
95
102
  }
96
103
  },
97
104
 
98
- /**
99
- * @param {AST.Component} node
100
- * @param {Object} context
101
- * @param {any} context.state
102
- * @param {Function} context.next
103
- */
104
105
  Component(node, { state, next }) {
105
106
  const scope = state.scope.child();
106
107
  scopes.set(node, scope);
@@ -114,12 +115,6 @@ export function create_scopes(ast, root, parent) {
114
115
  next({ scope });
115
116
  },
116
117
 
117
- /**
118
- * @param {AST.Element} node
119
- * @param {Object} context
120
- * @param {any} context.state
121
- * @param {Function} context.next
122
- */
123
118
  Element(node, { state, next }) {
124
119
  const scope = state.scope.child();
125
120
  scopes.set(node, scope);
@@ -86,7 +86,7 @@ declare module 'estree' {
86
86
  Attribute: Attribute;
87
87
  RefAttribute: RefAttribute;
88
88
  SpreadAttribute: SpreadAttribute;
89
- // Stylesheet: AST.CSS.StyleSheet;
89
+ ParenthesizedExpression: ParenthesizedExpression;
90
90
  }
91
91
 
92
92
  interface ExpressionMap {
@@ -98,6 +98,12 @@ declare module 'estree' {
98
98
  Text: TextNode;
99
99
  }
100
100
 
101
+ // Missing estree type
102
+ interface ParenthesizedExpression extends BaseNode {
103
+ type: 'ParenthesizedExpression';
104
+ expression: Expression;
105
+ }
106
+
101
107
  interface Comment {
102
108
  context?: Parse.CommentMetaData | null;
103
109
  }
@@ -512,7 +518,9 @@ declare module 'estree-jsx' {
512
518
  }
513
519
 
514
520
  declare module 'estree' {
515
- interface NodeMap {
521
+ // Helper map for creating our own TypeNode
522
+ // and to be used to extend estree's NodeMap
523
+ interface TSNodeMap {
516
524
  // TypeScript nodes
517
525
  TSAnyKeyword: TSAnyKeyword;
518
526
  TSArrayType: TSArrayType;
@@ -577,49 +585,188 @@ declare module 'estree' {
577
585
  TSUnknownKeyword: TSUnknownKeyword;
578
586
  TSVoidKeyword: TSVoidKeyword;
579
587
  TSParenthesizedType: TSParenthesizedType;
588
+ TSExpressionWithTypeArguments: TSExpressionWithTypeArguments;
580
589
  }
581
590
 
591
+ // Extend NodeMap to include TypeScript nodes
592
+ interface NodeMap extends TSNodeMap {}
593
+
594
+ // Create our version of TypeNode with modified types to be used in replacements
595
+ type TypeNode = TSNodeMap[keyof TSNodeMap];
596
+ type EntityName = AST.Identifier | AST.ThisExpression | TSQualifiedName;
597
+ type Parameter =
598
+ | ArrayPattern
599
+ | AssignmentPattern
600
+ | Identifier
601
+ | ObjectPattern
602
+ | RestElement
603
+ | TSParameterProperty;
604
+ type TypeElement =
605
+ | TSCallSignatureDeclaration
606
+ | TSConstructSignatureDeclaration
607
+ | TSIndexSignature
608
+ | TSMethodSignature
609
+ | TSPropertySignature;
610
+ type TSPropertySignature = TSPropertySignatureComputedName | TSPropertySignatureNonComputedName;
611
+ type PropertyNameComputed = Expression;
612
+ type PropertyNameNonComputed = Identifier | NumberLiteral | StringLiteral;
613
+
582
614
  // TypeScript AST node interfaces from @sveltejs/acorn-typescript
583
615
  // Based on TSESTree types but adapted for acorn's output format
584
616
  interface TSAnyKeyword extends AcornTSNode<TSESTree.TSAnyKeyword> {}
585
- interface TSArrayType extends AcornTSNode<TSESTree.TSArrayType> {}
617
+ interface TSArrayType extends Omit<AcornTSNode<TSESTree.TSArrayType>, 'elementType'> {
618
+ elementType: TypeNode;
619
+ }
586
620
  interface TSAsExpression extends AcornTSNode<TSESTree.TSAsExpression> {
587
621
  // Have to override it to use our Expression for required properties like metadata
588
622
  expression: AST.Expression;
589
623
  }
590
624
  interface TSBigIntKeyword extends AcornTSNode<TSESTree.TSBigIntKeyword> {}
591
625
  interface TSBooleanKeyword extends AcornTSNode<TSESTree.TSBooleanKeyword> {}
592
- interface TSCallSignatureDeclaration extends AcornTSNode<TSESTree.TSCallSignatureDeclaration> {}
593
- interface TSConditionalType extends AcornTSNode<TSESTree.TSConditionalType> {}
594
- interface TSConstructorType extends AcornTSNode<TSESTree.TSConstructorType> {}
626
+ interface TSCallSignatureDeclaration
627
+ extends Omit<
628
+ AcornTSNode<TSESTree.TSCallSignatureDeclaration>,
629
+ 'typeParameters' | 'typeAnnotation'
630
+ > {
631
+ parameters: Parameter[];
632
+ typeParameters: TSTypeParameterDeclaration | undefined;
633
+ typeAnnotation: TSTypeAnnotation | undefined;
634
+ }
635
+ interface TSConditionalType
636
+ extends Omit<
637
+ AcornTSNode<TSESTree.TSConditionalType>,
638
+ 'checkType' | 'extendsType' | 'falseType' | 'trueType'
639
+ > {
640
+ checkType: TypeNode;
641
+ extendsType: TypeNode;
642
+ falseType: TypeNode;
643
+ trueType: TypeNode;
644
+ }
645
+ interface TSConstructorType
646
+ extends Omit<AcornTSNode<TSESTree.TSConstructorType>, 'typeParameters' | 'params'> {
647
+ typeAnnotation: TSTypeAnnotation | undefined;
648
+ typeParameters: TSTypeParameterDeclaration | undefined;
649
+ parameters: Parameter[];
650
+ }
595
651
  interface TSConstructSignatureDeclaration
596
- extends AcornTSNode<TSESTree.TSConstructSignatureDeclaration> {}
597
- interface TSDeclareFunction extends AcornTSNode<TSESTree.TSDeclareFunction> {}
598
- interface TSEnumDeclaration extends AcornTSNode<TSESTree.TSEnumDeclaration> {}
599
- interface TSEnumMember extends AcornTSNode<TSESTree.TSEnumMember> {}
600
- interface TSExportAssignment extends AcornTSNode<TSESTree.TSExportAssignment> {}
601
- interface TSExternalModuleReference extends AcornTSNode<TSESTree.TSExternalModuleReference> {}
602
- interface TSFunctionType extends AcornTSNode<TSESTree.TSFunctionType> {}
652
+ extends Omit<
653
+ AcornTSNode<TSESTree.TSConstructSignatureDeclaration>,
654
+ 'typeParameters' | 'typeAnnotation'
655
+ > {
656
+ parameters: Parameter[];
657
+ typeParameters: TSTypeParameterDeclaration | undefined;
658
+ typeAnnotation: TSTypeAnnotation | undefined;
659
+ }
660
+ interface TSDeclareFunction
661
+ extends Omit<
662
+ AcornTSNode<TSESTree.TSDeclareFunction>,
663
+ 'id' | 'params' | 'typeParameters' | 'returnType'
664
+ > {
665
+ id: AST.Identifier;
666
+ params: Parameter[];
667
+ typeParameters: TSTypeParameterDeclaration | undefined;
668
+ returnType: TSTypeAnnotation | undefined;
669
+ }
670
+ interface TSEnumDeclaration
671
+ extends Omit<AcornTSNode<TSESTree.TSEnumDeclaration>, 'id' | 'members'> {
672
+ id: AST.Identifier;
673
+ members: TSEnumMember[];
674
+ }
675
+ interface TSEnumMember extends Omit<AcornTSNode<TSESTree.TSEnumMember>, 'id' | 'initializer'> {
676
+ id: AST.Identifier | StringLiteral;
677
+ initializer: AST.Expression | undefined;
678
+ }
679
+ interface TSExportAssignment
680
+ extends Omit<AcornTSNode<TSESTree.TSExportAssignment>, 'expression'> {
681
+ expression: AST.Expression;
682
+ }
683
+ interface TSExternalModuleReference
684
+ extends Omit<AcornTSNode<TSESTree.TSExternalModuleReference>, 'expression'> {
685
+ expression: StringLiteral;
686
+ }
687
+ interface TSFunctionType
688
+ extends Omit<AcornTSNode<TSESTree.TSFunctionType>, 'typeParameters' | 'params'> {
689
+ typeAnnotation: TSTypeAnnotation | undefined;
690
+ typeParameters: TSTypeParameterDeclaration | undefined;
691
+ parameters: Parameter[];
692
+ }
603
693
  interface TSImportEqualsDeclaration extends AcornTSNode<TSESTree.TSImportEqualsDeclaration> {}
604
- interface TSImportType extends AcornTSNode<TSESTree.TSImportType> {}
605
- interface TSIndexedAccessType extends AcornTSNode<TSESTree.TSIndexedAccessType> {}
606
- interface TSIndexSignature extends AcornTSNode<TSESTree.TSIndexSignature> {}
607
- interface TSInferType extends AcornTSNode<TSESTree.TSInferType> {}
694
+ interface TSImportType
695
+ extends Omit<AcornTSNode<TSESTree.TSImportType>, 'argument' | 'qualifier' | 'typeParameters'> {
696
+ argument: TypeNode;
697
+ qualifier: EntityName | null;
698
+ // looks like acorn-typescript has typeParameters
699
+ typeParameters: TSTypeParameterDeclaration | undefined | undefined;
700
+ }
701
+ interface TSIndexedAccessType
702
+ extends Omit<AcornTSNode<TSESTree.TSIndexedAccessType>, 'indexType' | 'objectType'> {
703
+ indexType: TypeNode;
704
+ objectType: TypeNode;
705
+ }
706
+ interface TSIndexSignature
707
+ extends Omit<AcornTSNode<TSESTree.TSIndexSignature>, 'parameters' | 'typeAnnotation'> {
708
+ parameters: Parameter[];
709
+ typeAnnotation: TSTypeAnnotation | undefined;
710
+ }
711
+ interface TSInferType extends Omit<AcornTSNode<TSESTree.TSInferType>, 'typeParameter'> {
712
+ typeParameter: TSTypeParameter;
713
+ }
608
714
  interface TSInstantiationExpression extends AcornTSNode<TSESTree.TSInstantiationExpression> {
609
715
  expression: AST.Expression;
610
716
  }
611
- interface TSInterfaceBody extends AcornTSNode<TSESTree.TSInterfaceBody> {}
612
- interface TSInterfaceDeclaration extends AcornTSNode<TSESTree.TSInterfaceDeclaration> {}
613
- interface TSIntersectionType extends AcornTSNode<TSESTree.TSIntersectionType> {}
717
+ interface TSInterfaceBody extends Omit<AcornTSNode<TSESTree.TSInterfaceBody>, 'body'> {
718
+ body: TypeElement[];
719
+ }
720
+ interface TSInterfaceDeclaration
721
+ extends Omit<
722
+ AcornTSNode<TSESTree.TSInterfaceDeclaration>,
723
+ 'id' | 'typeParameters' | 'body' | 'extends'
724
+ > {
725
+ id: AST.Identifier;
726
+ typeParameters: TSTypeParameterDeclaration | undefined;
727
+ body: TSInterfaceBody;
728
+ extends: TSExpressionWithTypeArguments[];
729
+ }
730
+ interface TSIntersectionType extends Omit<AcornTSNode<TSESTree.TSIntersectionType>, 'types'> {
731
+ types: TypeNode[];
732
+ }
614
733
  interface TSIntrinsicKeyword extends AcornTSNode<TSESTree.TSIntrinsicKeyword> {}
615
- interface TSLiteralType extends AcornTSNode<TSESTree.TSLiteralType> {}
616
- interface TSMappedType extends AcornTSNode<TSESTree.TSMappedType> {}
617
- interface TSMethodSignature extends AcornTSNode<TSESTree.TSMethodSignature> {}
618
- interface TSModuleBlock extends AcornTSNode<TSESTree.TSModuleBlock> {}
619
- interface TSModuleDeclaration extends AcornTSNode<TSESTree.TSModuleDeclaration> {}
620
- interface TSNamedTupleMember extends AcornTSNode<TSESTree.TSNamedTupleMember> {}
734
+ interface TSLiteralType extends Omit<AcornTSNode<TSESTree.TSLiteralType>, 'literal'> {
735
+ literal: AST.Literal | AST.TemplateLiteral;
736
+ }
737
+ interface TSMappedType
738
+ extends Omit<AcornTSNode<TSESTree.TSMappedType>, 'typeParameter' | 'typeAnnotation'> {
739
+ typeAnnotation: TypeNode | undefined;
740
+ typeParameter: TSTypeParameter;
741
+ }
742
+ interface TSMethodSignature
743
+ extends Omit<
744
+ AcornTSNode<TSESTree.TSMethodSignature>,
745
+ 'key' | 'typeParameters' | 'params' | 'typeAnnotation'
746
+ > {
747
+ key: PropertyNameComputed | PropertyNameNonComputed;
748
+ typeParameters: TSTypeParameterDeclaration | undefined;
749
+ parameters: Parameter[];
750
+ // doesn't actually exist in the spec but acorn-typescript adds it
751
+ typeAnnotation: TSTypeAnnotation | undefined;
752
+ }
753
+ interface TSModuleBlock extends Omit<AcornTSNode<TSESTree.TSModuleBlock>, 'body'> {
754
+ body: AST.Statement[];
755
+ }
756
+ interface TSModuleDeclaration
757
+ extends Omit<AcornTSNode<TSESTree.TSModuleDeclaration>, 'body' | 'id'> {
758
+ body: TSModuleBlock;
759
+ id: AST.Identifier;
760
+ }
761
+ interface TSNamedTupleMember
762
+ extends Omit<AcornTSNode<TSESTree.TSNamedTupleMember>, 'elementType' | 'label'> {
763
+ elementType: TypeNode;
764
+ label: AST.Identifier;
765
+ }
621
766
  interface TSNamespaceExportDeclaration
622
- extends AcornTSNode<TSESTree.TSNamespaceExportDeclaration> {}
767
+ extends Omit<AcornTSNode<TSESTree.TSNamespaceExportDeclaration>, 'id'> {
768
+ id: AST.Identifier;
769
+ }
623
770
  interface TSNeverKeyword extends AcornTSNode<TSESTree.TSNeverKeyword> {}
624
771
  interface TSNonNullExpression extends AcornTSNode<TSESTree.TSNonNullExpression> {
625
772
  expression: AST.Expression;
@@ -627,36 +774,106 @@ declare module 'estree' {
627
774
  interface TSNullKeyword extends AcornTSNode<TSESTree.TSNullKeyword> {}
628
775
  interface TSNumberKeyword extends AcornTSNode<TSESTree.TSNumberKeyword> {}
629
776
  interface TSObjectKeyword extends AcornTSNode<TSESTree.TSObjectKeyword> {}
630
- interface TSOptionalType extends AcornTSNode<TSESTree.TSOptionalType> {}
777
+ interface TSOptionalType extends Omit<AcornTSNode<TSESTree.TSOptionalType>, 'typeAnnotation'> {
778
+ typeAnnotation: TypeNode;
779
+ }
631
780
  interface TSParameterProperty extends AcornTSNode<TSESTree.TSParameterProperty> {}
632
- interface TSPropertySignature extends AcornTSNode<TSESTree.TSPropertySignature> {}
633
- interface TSQualifiedName extends AcornTSNode<TSESTree.TSQualifiedName> {}
634
- interface TSRestType extends AcornTSNode<TSESTree.TSRestType> {}
781
+ interface TSPropertySignatureComputedName
782
+ extends Omit<AcornTSNode<TSESTree.TSPropertySignatureComputedName>, 'key' | 'typeAnnotation'> {
783
+ key: PropertyNameComputed;
784
+ typeAnnotation: TSTypeAnnotation | undefined;
785
+ }
786
+ interface TSPropertySignatureNonComputedName
787
+ extends Omit<
788
+ AcornTSNode<TSESTree.TSPropertySignatureNonComputedName>,
789
+ 'key' | 'typeAnnotation'
790
+ > {
791
+ key: PropertyNameNonComputed;
792
+ typeAnnotation: TSTypeAnnotation | undefined;
793
+ }
794
+ interface TSQualifiedName extends Omit<AcornTSNode<TSESTree.TSQualifiedName>, 'left' | 'right'> {
795
+ left: EntityName;
796
+ right: AST.Identifier;
797
+ }
798
+ interface TSRestType extends Omit<AcornTSNode<TSESTree.TSRestType>, 'typeAnnotation'> {
799
+ typeAnnotation: TypeNode;
800
+ }
635
801
  interface TSSatisfiesExpression extends AcornTSNode<TSESTree.TSSatisfiesExpression> {
636
802
  expression: AST.Expression;
637
803
  }
638
804
  interface TSStringKeyword extends AcornTSNode<TSESTree.TSStringKeyword> {}
639
805
  interface TSSymbolKeyword extends AcornTSNode<TSESTree.TSSymbolKeyword> {}
640
806
  interface TSThisType extends AcornTSNode<TSESTree.TSThisType> {}
641
- interface TSTupleType extends AcornTSNode<TSESTree.TSTupleType> {}
642
- interface TSTypeAliasDeclaration extends AcornTSNode<TSESTree.TSTypeAliasDeclaration> {}
643
- interface TSTypeAnnotation extends AcornTSNode<TSESTree.TSTypeAnnotation> {}
807
+ interface TSTupleType extends Omit<AcornTSNode<TSESTree.TSTupleType>, 'elementTypes'> {
808
+ elementTypes: TypeNode[];
809
+ }
810
+ interface TSTypeAliasDeclaration
811
+ extends Omit<
812
+ AcornTSNode<TSESTree.TSTypeAliasDeclaration>,
813
+ 'id' | 'typeParameters' | 'typeAnnotation'
814
+ > {
815
+ id: AST.Identifier;
816
+ typeAnnotation: TypeNode;
817
+ typeParameters: TSTypeParameterDeclaration | undefined;
818
+ }
819
+ interface TSTypeAnnotation
820
+ extends Omit<AcornTSNode<TSESTree.TSTypeAnnotation>, 'typeAnnotation'> {
821
+ typeAnnotation: TypeNode;
822
+ }
644
823
  interface TSTypeAssertion extends AcornTSNode<TSESTree.TSTypeAssertion> {
645
824
  expression: AST.Expression;
646
825
  }
647
- interface TSTypeLiteral extends AcornTSNode<TSESTree.TSTypeLiteral> {}
648
- interface TSTypeOperator extends AcornTSNode<TSESTree.TSTypeOperator> {}
649
- interface TSTypeParameter extends AcornTSNode<TSESTree.TSTypeParameter> {}
650
- interface TSTypeParameterDeclaration extends AcornTSNode<TSESTree.TSTypeParameterDeclaration> {}
826
+ interface TSTypeLiteral extends Omit<AcornTSNode<TSESTree.TSTypeLiteral>, 'members'> {
827
+ members: TypeElement[];
828
+ }
829
+ interface TSTypeOperator extends Omit<AcornTSNode<TSESTree.TSTypeOperator>, 'typeAnnotation'> {
830
+ typeAnnotation: TypeNode | undefined;
831
+ }
832
+ interface TSTypeParameter
833
+ extends Omit<AcornTSNode<TSESTree.TSTypeParameter>, 'name' | 'constraint' | 'default'> {
834
+ constraint: TypeNode | undefined;
835
+ default: TypeNode | undefined;
836
+ name: AST.Identifier;
837
+ }
838
+ interface TSTypeParameterDeclaration
839
+ extends Omit<AcornTSNode<TSESTree.TSTypeParameterDeclaration>, 'params'> {
840
+ params: TypeNode[];
841
+ }
651
842
  interface TSTypeParameterInstantiation
652
- extends AcornTSNode<TSESTree.TSTypeParameterInstantiation> {}
843
+ extends Omit<AcornTSNode<TSESTree.TSTypeParameterInstantiation>, 'params'> {
844
+ params: TypeNode[];
845
+ }
653
846
  interface TSTypePredicate extends AcornTSNode<TSESTree.TSTypePredicate> {}
654
- interface TSTypeQuery extends AcornTSNode<TSESTree.TSTypeQuery> {}
655
- interface TSTypeReference extends AcornTSNode<TSESTree.TSTypeReference> {}
847
+ interface TSTypeQuery
848
+ extends Omit<AcornTSNode<TSESTree.TSTypeQuery>, 'exprName' | 'typeArguments'> {
849
+ exprName: EntityName | TSImportType;
850
+ typeArguments: TSTypeParameterInstantiation | undefined;
851
+ }
852
+ interface TSTypeReference
853
+ extends Omit<AcornTSNode<TSESTree.TSTypeReference>, 'typeName' | 'typeArguments'> {
854
+ typeArguments: TSTypeParameterInstantiation | undefined;
855
+ typeName: EntityName;
856
+ }
656
857
  interface TSUndefinedKeyword extends AcornTSNode<TSESTree.TSUndefinedKeyword> {}
657
- interface TSUnionType extends AcornTSNode<TSESTree.TSUnionType> {}
858
+ interface TSUnionType extends Omit<AcornTSNode<TSESTree.TSUnionType>, 'types'> {
859
+ types: TypeNode[];
860
+ }
861
+ // TSInterfaceHeritage doesn't exist in acorn-typescript which uses TSExpressionWithTypeArguments
862
+ interface TSInterfaceHeritage
863
+ extends Omit<AcornTSNode<TSESTree.TSInterfaceHeritage>, 'expression' | 'typeParameters'> {
864
+ expression: AST.Expression;
865
+ // acorn-typescript uses typeParameters instead of typeArguments
866
+ typeParameters: TSTypeParameterInstantiation | undefined;
867
+ }
868
+ // Extends TSInterfaceHeritage as it's the semantically the same as used by acorn-typescript
869
+ interface TSExpressionWithTypeArguments extends Omit<TSInterfaceHeritage, 'type'> {
870
+ type: 'TSExpressionWithTypeArguments';
871
+ }
872
+
658
873
  interface TSUnknownKeyword extends AcornTSNode<TSESTree.TSUnknownKeyword> {}
659
874
  interface TSVoidKeyword extends AcornTSNode<TSESTree.TSVoidKeyword> {}
875
+ interface NumberLiteral extends AcornTSNode<TSESTree.NumberLiteral> {}
876
+ interface StringLiteral extends AcornTSNode<TSESTree.StringLiteral> {}
660
877
 
661
878
  // acorn-typescript specific nodes (not in @typescript-eslint/types)
662
879
  interface TSParenthesizedType extends AST.BaseNode {
@@ -674,7 +891,7 @@ declare module 'estree' {
674
891
  }
675
892
 
676
893
  import type { Comment, Position } from 'acorn';
677
- import type { M } from 'vitest/dist/chunks/environment.d.cL3nLXbE.js';
894
+ import type { A, M } from 'vitest/dist/chunks/environment.d.cL3nLXbE.js';
678
895
 
679
896
  /**
680
897
  * Parse error information
@@ -65,6 +65,85 @@ export namespace Parse {
65
65
  BIND_OUTSIDE: 5;
66
66
  }
67
67
 
68
+ /**
69
+ * Branch ID for tracking disjunction structure in regular expressions
70
+ * Used to determine whether a duplicate capture group name is allowed
71
+ * because it is in a separate branch.
72
+ */
73
+ export interface BranchID {
74
+ /** Parent disjunction branch */
75
+ parent: BranchID | null;
76
+ /** Identifies this set of sibling branches */
77
+ base: BranchID;
78
+ /** Check if this branch is separated from another branch */
79
+ separatedFrom(alt: BranchID): boolean;
80
+ /** Create a sibling branch */
81
+ sibling(): BranchID;
82
+ }
83
+
84
+ /**
85
+ * Regular expression validation state
86
+ * Used by the parser to validate regular expression literals
87
+ * See: https://github.com/acornjs/acorn/blob/main/acorn/src/regexp.js
88
+ */
89
+ export interface RegExpValidationState {
90
+ /** Reference to the parser instance */
91
+ parser: Parser;
92
+ /** Valid flags for the current ECMAScript version */
93
+ validFlags: string;
94
+ /** Unicode properties data for the current ECMAScript version */
95
+ unicodeProperties: any;
96
+ /** Source pattern string of the regular expression */
97
+ source: string;
98
+ /** Flags string of the regular expression */
99
+ flags: string;
100
+ /** Start position of the regular expression in the source */
101
+ start: number;
102
+ /** Whether unicode flag (u) is enabled */
103
+ switchU: boolean;
104
+ /** Whether unicode sets flag (v) is enabled (ES2024+) */
105
+ switchV: boolean;
106
+ /** Whether named capture groups are enabled */
107
+ switchN: boolean;
108
+ /** Current position in the pattern */
109
+ pos: number;
110
+ /** Last integer value parsed */
111
+ lastIntValue: number;
112
+ /** Last string value parsed */
113
+ lastStringValue: string;
114
+ /** Whether the last assertion can be quantified */
115
+ lastAssertionIsQuantifiable: boolean;
116
+ /** Number of capturing parentheses */
117
+ numCapturingParens: number;
118
+ /** Maximum back reference number */
119
+ maxBackReference: number;
120
+ /** Map of group names to their information */
121
+ groupNames: Record<string, BranchID[]>;
122
+ /** Array of back reference names */
123
+ backReferenceNames: string[];
124
+ /** Current branch ID for tracking disjunction structure */
125
+ branchID: BranchID | null;
126
+
127
+ /** Reset state for a new pattern */
128
+ reset(start: number, pattern: string, flags: string): void;
129
+ /** Raise a validation error */
130
+ raise(message: string): void;
131
+ /** Get code point at position i (handles surrogate pairs if unicode mode) */
132
+ at(i: number, forceU?: boolean): number;
133
+ /** Get next index after position i (handles surrogate pairs if unicode mode) */
134
+ nextIndex(i: number, forceU?: boolean): number;
135
+ /** Get code point at current position */
136
+ current(forceU?: boolean): number;
137
+ /** Get code point at next position */
138
+ lookahead(forceU?: boolean): number;
139
+ /** Advance position to next character */
140
+ advance(forceU?: boolean): void;
141
+ /** Try to eat a specific character */
142
+ eat(ch: number, forceU?: boolean): boolean;
143
+ /** Try to eat a sequence of characters */
144
+ eatChars(chs: number[], forceU?: boolean): boolean;
145
+ }
146
+
68
147
  export interface Options extends Omit<acorn.Options, 'onComment' | 'ecmaVersion'> {
69
148
  rippleOptions: {
70
149
  loose: boolean;
@@ -297,6 +376,15 @@ export namespace Parse {
297
376
  tokContexts: AcornTypeScriptTokContexts;
298
377
  }
299
378
 
379
+ interface Scope {
380
+ flags: number;
381
+ var: string[];
382
+ lexical: string[];
383
+ functions: string[];
384
+ }
385
+
386
+ type Exports = Record<string, boolean>;
387
+
300
388
  /**
301
389
  * Extended Parser instance with internal properties
302
390
  *
@@ -360,7 +448,7 @@ export namespace Parse {
360
448
  /** Current scope flags stack */
361
449
  scopeStack: Array<{ flags: number; var: string[]; lexical: string[]; functions: string[] }>;
362
450
  /** Regular expression validation state */
363
- regexpState?: any;
451
+ regexpState: RegExpValidationState | null;
364
452
  /** Whether we can use await keyword */
365
453
  canAwait: boolean;
366
454
  /** Position of await keyword (0 if not in async context) */
@@ -376,7 +464,7 @@ export namespace Parse {
376
464
  /** Potential arrow in for-await position */
377
465
  potentialArrowInForAwait: boolean;
378
466
  /** Private name stack for class private fields validation */
379
- privateNameStack: Array<{ declared: Record<string, any>; used: Array<AST.Node> }>;
467
+ privateNameStack: Array<{ declared: Record<string, string>; used: Array<AST.Node> }>;
380
468
  /** Undefined exports for module validation */
381
469
  undefinedExports: Record<string, AST.Node>;
382
470
 
@@ -646,16 +734,16 @@ export namespace Parse {
646
734
  declareName(name: string, bindingType: BindingType[keyof BindingType], pos: number): void;
647
735
 
648
736
  /** Get current scope */
649
- currentScope(): { flags: number; var: string[]; lexical: string[]; functions: string[] };
737
+ currentScope(): Scope;
650
738
 
651
739
  /** Get current variable scope (for var declarations) */
652
- currentVarScope(): { flags: number; var: string[]; lexical: string[]; functions: string[] };
740
+ currentVarScope(): Scope;
653
741
 
654
742
  /** Get current "this" scope */
655
- currentThisScope(): { flags: number; var: string[]; lexical: string[]; functions: string[] };
743
+ currentThisScope(): Scope;
656
744
 
657
745
  /** Check if treating functions as var in current scope */
658
- treatFunctionsAsVarInScope(scope: any): boolean;
746
+ treatFunctionsAsVarInScope(scope: Scope): boolean;
659
747
 
660
748
  // ============================================================
661
749
  // Context Management
@@ -1262,7 +1350,7 @@ export namespace Parse {
1262
1350
  parseClassSuper(node: AST.Node): void;
1263
1351
 
1264
1352
  /** Enter class body scope */
1265
- enterClassBody(): Record<string, any>;
1353
+ enterClassBody(): Record<string, string>;
1266
1354
 
1267
1355
  /** Exit class body scope */
1268
1356
  exitClassBody(): void;
@@ -1325,11 +1413,11 @@ export namespace Parse {
1325
1413
  /** Parse export declaration */
1326
1414
  parseExport(
1327
1415
  node: AST.Node,
1328
- exports?: any,
1416
+ exports?: Exports,
1329
1417
  ): AST.ExportNamedDeclaration | AST.ExportDefaultDeclaration | AST.ExportAllDeclaration;
1330
1418
 
1331
1419
  /** Parse export specifiers */
1332
- parseExportSpecifiers(exports?: any): AST.ExportSpecifier[];
1420
+ parseExportSpecifiers(exports?: Exports): AST.ExportSpecifier[];
1333
1421
 
1334
1422
  /** Parse export default declaration */
1335
1423
  parseExportDefaultDeclaration(): AST.Declaration | AST.Expression | AST.Component;