@tsrx/core 0.1.54 → 0.1.56

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": "Core compiler infrastructure for TSRX syntax",
4
4
  "license": "MIT",
5
5
  "author": "Dominic Gannaway",
6
- "version": "0.1.54",
6
+ "version": "0.1.56",
7
7
  "type": "module",
8
8
  "repository": {
9
9
  "type": "git",
package/src/plugin.js CHANGED
@@ -299,12 +299,32 @@ export function TSRXPlugin(config) {
299
299
  finishNode(node, type) {
300
300
  const finished = super.finishNode(node, type);
301
301
  if (type === 'TSModuleDeclaration') {
302
- const start = /** @type {number} */ (finished.start);
303
- const source = this.input.slice(start, start + 'namespace'.length);
304
- finished.metadata ??= { path: [] };
305
- finished.metadata.module_keyword = source.startsWith('namespace')
306
- ? 'namespace'
307
- : 'module';
302
+ const declaration = /** @type {AST.TSModuleDeclaration} */ (finished);
303
+ const start = /** @type {number} */ (declaration.start);
304
+ // acorn-typescript still exposes the legacy `global` flag without
305
+ // TSESTree's replacement `kind`; replace it at the parser boundary
306
+ // so downstream consumers only receive the current discriminator.
307
+ const legacy = /** @type {{ global?: boolean }} */ (declaration);
308
+ const prefix = this.input
309
+ .slice(start, declaration.id.start)
310
+ .replace(/\/\*[\s\S]*?\*\/|\/\/[^\r\n]*/g, ' ')
311
+ .trim();
312
+ const kind =
313
+ declaration.kind ??
314
+ (legacy.global ? 'global' : prefix.endsWith('namespace') ? 'namespace' : 'module');
315
+ /** @type {AST.TSModuleDeclaration | null} */
316
+ let current = declaration;
317
+ while (current !== null) {
318
+ const current_legacy = /** @type {{ global?: boolean }} */ (current);
319
+ current.kind = kind;
320
+ delete current_legacy.global;
321
+ current.metadata ??= { path: [] };
322
+ current.metadata.module_keyword = kind;
323
+ const body = /** @type {AST.TSModuleBlock | AST.TSModuleDeclaration} */ (
324
+ /** @type {unknown} */ (current.body)
325
+ );
326
+ current = body?.type === 'TSModuleDeclaration' ? body : null;
327
+ }
308
328
  }
309
329
  return finished;
310
330
  }
package/src/scope.js CHANGED
@@ -130,7 +130,7 @@ export function create_scopes(ast, root, parent, error_options) {
130
130
  },
131
131
 
132
132
  TSModuleDeclaration(node, { state, next }) {
133
- const is_submodule = node.metadata?.module_keyword === 'module';
133
+ const is_submodule = node.declare !== true && node.kind === 'module';
134
134
  if (is_submodule && node.id?.type === 'Identifier') {
135
135
  state.scope.declare(node.id, 'normal', 'module', node);
136
136
  }
@@ -180,12 +180,18 @@ export function tsx_with_ts_locations(boundary_tokens = false, comments = undefi
180
180
  }
181
181
  },
182
182
  TSModuleDeclaration: (node, context) => {
183
- // Ambient `declare module '…' { }` must keep its `declare` — the
184
- // typeOnly/volar output is real TS and `module '…' { }` alone is a
185
- // syntax error (TS1035). Non-ambient `module name { }` blocks have no
186
- // `declare` and print unchanged.
183
+ // `declare global` is represented as a TSModuleDeclaration whose id is
184
+ // `global`; adding `module` changes it into an unrelated named module.
185
+ // Ambient `declare module '…' { }` must still keep its `declare` —
186
+ // the typeOnly/volar output is real TS and `module '…' { … }` alone is
187
+ // a syntax error (TS1035).
187
188
  if (node.declare) context.write('declare ');
188
- context.write(node.metadata?.module_keyword ?? 'module');
189
+ if (node.kind === 'global') {
190
+ context.visit(node.id);
191
+ context.visit(node.body);
192
+ return;
193
+ }
194
+ context.write(node.kind);
189
195
  context.write(' ');
190
196
  context.visit(node.id);
191
197
  context.visit(node.body);
@@ -110,7 +110,7 @@ function is_server_module_declaration(node, block_name) {
110
110
  return (
111
111
  node.type === 'TSModuleDeclaration' &&
112
112
  node.declare !== true &&
113
- node.metadata?.module_keyword === 'module' &&
113
+ node.kind === 'module' &&
114
114
  identifier_name(node.id) === block_name
115
115
  );
116
116
  }
@@ -465,6 +465,7 @@ function lower_declaration(declaration, outside_names, block_name) {
465
465
  const namespace = /** @type {AST.TSStatement<AST.TSModuleDeclaration>} */ ({
466
466
  ...declaration,
467
467
  id,
468
+ kind: 'namespace',
468
469
  metadata: { ...declaration.metadata, module_keyword: 'namespace' },
469
470
  body: { ...declaration.body, body: [...aliases, ...rest] },
470
471
  });
package/types/index.d.ts CHANGED
@@ -106,7 +106,7 @@ export interface BaseNodeMetaData {
106
106
  has_template?: boolean;
107
107
  source_name?: string;
108
108
  source_length?: number;
109
- module_keyword?: 'module' | 'namespace';
109
+ module_keyword?: 'global' | 'module' | 'namespace';
110
110
  /**
111
111
  * Generated identifier whose SOURCE span sits inside an authored string
112
112
  * literal (e.g. a server-module lowering's namespace reference carrying
@@ -303,6 +303,8 @@ declare module 'estree' {
303
303
  typeParameters?: TSTypeParameterDeclaration;
304
304
  accessibility?: Accessibility;
305
305
  optional?: boolean;
306
+ abstract?: boolean;
307
+ override?: boolean;
306
308
  }
307
309
 
308
310
  interface PropertyDefinition {
@@ -310,18 +312,26 @@ declare module 'estree' {
310
312
  readonly?: boolean;
311
313
  optional?: boolean;
312
314
  definite?: boolean;
315
+ abstract?: boolean;
316
+ override?: boolean;
317
+ declare?: boolean;
318
+ accessor?: boolean;
313
319
  }
314
320
 
315
321
  interface ClassDeclaration {
316
322
  typeParameters?: AST.TSTypeParameterDeclaration;
317
323
  superTypeParameters?: AST.TSTypeParameterInstantiation;
318
324
  implements?: AST.TSClassImplements[];
325
+ abstract?: boolean;
326
+ declare?: boolean;
319
327
  }
320
328
 
321
329
  interface ClassExpression {
322
330
  typeParameters?: AST.TSTypeParameterDeclaration;
323
331
  superTypeParameters?: AST.TSTypeParameterInstantiation;
324
332
  implements?: AST.TSClassImplements[];
333
+ abstract?: boolean;
334
+ declare?: boolean;
325
335
  }
326
336
 
327
337
  interface Identifier extends AST.TrackedNode {
@@ -351,8 +361,16 @@ declare module 'estree' {
351
361
  tracked?: boolean;
352
362
  }
353
363
 
364
+ // A `@decorator` on a class, class member, or parameter. The parser emits
365
+ // these, but estree has no node type for them.
366
+ interface Decorator extends AST.BaseNode {
367
+ type: 'Decorator';
368
+ expression: AST.Expression;
369
+ }
370
+
354
371
  // Include TypeScript node types and TSRX-specific nodes in NodeMap
355
372
  interface NodeMap {
373
+ Decorator: Decorator;
356
374
  JSXSpreadChild: ESTreeJSX.JSXSpreadChild;
357
375
  TSRXImportDeclaration: TSRXImportDeclaration;
358
376
  TSRXJSXElement: TSRXJSXElement;
@@ -697,6 +715,19 @@ declare module 'estree' {
697
715
  declaration?: TSRXDeclaration | null | undefined;
698
716
  }
699
717
 
718
+ /**
719
+ * estree's `ExportDefaultDeclaration` predates the two TypeScript-only
720
+ * declaration forms the parser puts in this slot: `export default interface
721
+ * Foo {}` yields a `TSInterfaceDeclaration`, and the overload signature
722
+ * `export default function foo();` yields a `TSDeclareFunction`.
723
+ */
724
+ interface TSRXExportDefaultDeclaration extends Omit<AST.ExportDefaultDeclaration, 'declaration'> {
725
+ declaration:
726
+ | AST.ExportDefaultDeclaration['declaration']
727
+ | AST.TSDeclareFunction
728
+ | AST.TSInterfaceDeclaration;
729
+ }
730
+
700
731
  interface TSRXProgram extends Omit<Program, 'body'> {
701
732
  body: (Program['body'][number] | FunctionExpression)[];
702
733
  }
@@ -1271,7 +1302,7 @@ declare module 'estree' {
1271
1302
  }
1272
1303
  interface TSModuleDeclaration extends Omit<
1273
1304
  AcornTSNode<TSESTree.TSModuleDeclaration>,
1274
- 'body' | 'id'
1305
+ 'body' | 'global' | 'id'
1275
1306
  > {
1276
1307
  body: TSModuleBlock;
1277
1308
  /** A string literal for `declare module '<specifier>'`. */