@atscript/core 0.0.1

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/dist/index.cjs ADDED
@@ -0,0 +1,3460 @@
1
+ "use strict";
2
+ //#region rolldown:runtime
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
13
+ get: ((k) => from[k]).bind(null, key),
14
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
+ });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
20
+ value: mod,
21
+ enumerable: true
22
+ }) : target, mod));
23
+
24
+ //#endregion
25
+ const node_fs = __toESM(require("node:fs"));
26
+ const node_fs_promises = __toESM(require("node:fs/promises"));
27
+ const node_path = __toESM(require("node:path"));
28
+ const node_url = __toESM(require("node:url"));
29
+ const rolldown = __toESM(require("rolldown"));
30
+ const __prostojs_parser = __toESM(require("@prostojs/parser"));
31
+ const path = __toESM(require("path"));
32
+ const url = __toESM(require("url"));
33
+ const defu = __toESM(require("defu"));
34
+ const glob = __toESM(require("glob"));
35
+ const fs_promises = __toESM(require("fs/promises"));
36
+
37
+ //#region packages/core/src/parser/nodes/semantic-node.ts
38
+ function _define_property$14(obj, key, value) {
39
+ if (key in obj) Object.defineProperty(obj, key, {
40
+ value,
41
+ enumerable: true,
42
+ configurable: true,
43
+ writable: true
44
+ });
45
+ else obj[key] = value;
46
+ return obj;
47
+ }
48
+ var SemanticNode = class {
49
+ registerAtDocument(doc) {
50
+ if (this.definition) this.definition.registerAtDocument(doc);
51
+ this.annotations?.forEach((val) => {
52
+ doc.registerAnnotation(val);
53
+ });
54
+ }
55
+ setDocumentation(s) {
56
+ this._documentation = s;
57
+ }
58
+ get documentation() {
59
+ return this._documentation;
60
+ }
61
+ get id() {
62
+ return this.token("identifier")?.text;
63
+ }
64
+ get referredIdentifiers() {
65
+ if (isGroup(this)) return this.getIdentifiersRecursive(this);
66
+ return this.definition ? this.getIdentifiersRecursive(this.definition) : [];
67
+ }
68
+ getIdentifiersRecursive(node) {
69
+ if (isGroup(node)) {
70
+ const r = [];
71
+ for (const n of node.unwrap()) r.push(...this.getIdentifiersRecursive(n));
72
+ return r;
73
+ } else return node.referredIdentifiers;
74
+ }
75
+ countAnnotations(name) {
76
+ return this.annotationsCounter?.get(name) ?? 0;
77
+ }
78
+ annotate(name, token) {
79
+ if (!this.annotations) this.annotations = [];
80
+ if (!this.annotationsCounter) this.annotationsCounter = new Map();
81
+ if (this.annotationsCounter.has(name)) this.annotationsCounter.set(name, this.annotationsCounter.get(name) + 1);
82
+ else this.annotationsCounter.set(name, 1);
83
+ token.parentNode = this;
84
+ const a = {
85
+ name,
86
+ token,
87
+ args: []
88
+ };
89
+ this.annotations.push(a);
90
+ return (arg) => {
91
+ arg.parentNode = this;
92
+ arg.index = a.args.length;
93
+ arg.annotationRef = token;
94
+ a.args.push(arg);
95
+ };
96
+ }
97
+ get length() {
98
+ return 0;
99
+ }
100
+ define(node) {
101
+ this.definition = node;
102
+ return this;
103
+ }
104
+ get def() {
105
+ return this.definition;
106
+ }
107
+ get identifier() {
108
+ return this.token("identifier")?.text;
109
+ }
110
+ saveToken(token, semantic) {
111
+ if (!this.tokens) this.tokens = new Map();
112
+ token.parentNode = this;
113
+ this.tokens.set(semantic, token);
114
+ return this;
115
+ }
116
+ wrap(node, token) {
117
+ this.define(node);
118
+ this.saveToken(token, "identifier");
119
+ return this;
120
+ }
121
+ token(s) {
122
+ return this.tokens?.get(s);
123
+ }
124
+ has(s) {
125
+ return this.tokens?.has(s);
126
+ }
127
+ toString(level = 0, prefix = "●") {
128
+ const indent = " ".repeat(level * 2);
129
+ let s = `${this.renderAnnotations()}${prefix} [${this.entity}] "${this.token("identifier")?.text ?? ""}"`;
130
+ this.tokens?.forEach((t, key) => {
131
+ s += key === "identifier" ? "" : ` ${key}: ${t.text} <${t.type}>`;
132
+ });
133
+ s += this.renderChildren();
134
+ return indent + s.split("\n").join(`\n${indent}`);
135
+ }
136
+ renderAnnotations() {
137
+ if (this.annotations) return `${this.annotations?.map(({ token, args }) => `${token.text} ${args.map((a) => a.type === "text" ? `"${a.text}"` : a.text).join(" ")}`).join("\n")}\n`;
138
+ return "";
139
+ }
140
+ renderChildren() {
141
+ if (this.definition) return isGroup(this.definition) ? `\n${this.definition.toString(1, "=")}\n` : `${this.definition.toString(0, ":")}`;
142
+ return "";
143
+ }
144
+ getDefinition() {
145
+ return this.definition;
146
+ }
147
+ constructor(entity) {
148
+ _define_property$14(this, "entity", void 0);
149
+ _define_property$14(this, "tokens", void 0);
150
+ _define_property$14(this, "isGroup", void 0);
151
+ _define_property$14(this, "definition", void 0);
152
+ _define_property$14(this, "annotations", void 0);
153
+ _define_property$14(this, "annotationsCounter", void 0);
154
+ _define_property$14(this, "_documentation", void 0);
155
+ this.entity = entity;
156
+ this.isGroup = false;
157
+ }
158
+ };
159
+
160
+ //#endregion
161
+ //#region packages/core/src/parser/nodes/array-node.ts
162
+ var SemanticArrayNode = class extends SemanticNode {
163
+ get props() {
164
+ if (this.definition) return isStructure(this.definition) ? this.definition.props : new Map();
165
+ return new Map();
166
+ }
167
+ constructor() {
168
+ super("array");
169
+ }
170
+ };
171
+
172
+ //#endregion
173
+ //#region packages/core/src/parser/nodes/const-node.ts
174
+ var SemanticConstNode = class extends SemanticNode {
175
+ registerAtDocument(doc) {
176
+ const token = this.token("identifier");
177
+ if (token && token.type === "text" && token.multiline) doc.registerMessage(token, "Unexpected end of string");
178
+ }
179
+ constructor() {
180
+ super("const");
181
+ }
182
+ };
183
+
184
+ //#endregion
185
+ //#region packages/core/src/parser/nodes/group-node.ts
186
+ function _define_property$13(obj, key, value) {
187
+ if (key in obj) Object.defineProperty(obj, key, {
188
+ value,
189
+ enumerable: true,
190
+ configurable: true,
191
+ writable: true
192
+ });
193
+ else obj[key] = value;
194
+ return obj;
195
+ }
196
+ var SemanticGroup = class extends SemanticNode {
197
+ registerAtDocument(doc) {
198
+ if (this.nodes.length > 0) this.unwrap().forEach((n) => n.registerAtDocument(doc));
199
+ }
200
+ get length() {
201
+ return this.nodes.length;
202
+ }
203
+ get first() {
204
+ return this.nodes[0];
205
+ }
206
+ get op() {
207
+ return this.operator;
208
+ }
209
+ define(node) {
210
+ if (isGroup(node)) {
211
+ this.nodes = node.unwrap();
212
+ this.operator = node.op;
213
+ } else this.nodes = [node];
214
+ return this;
215
+ }
216
+ wrap(node, token) {
217
+ node.define(this);
218
+ node.saveToken(token, "identifier");
219
+ return this;
220
+ }
221
+ unwrap() {
222
+ return this.nodes;
223
+ }
224
+ renderChildren() {
225
+ let s = " (\n";
226
+ s += this.nodes.map((n) => n.toString(2)).join(` <${this.operator || ""}>\n`);
227
+ s += "\n )";
228
+ return s;
229
+ }
230
+ constructor(nodes = [], operator) {
231
+ super("group"), _define_property$13(this, "nodes", void 0), _define_property$13(this, "operator", void 0), _define_property$13(this, "isGroup", void 0), this.nodes = nodes, this.operator = operator, this.isGroup = true;
232
+ }
233
+ };
234
+
235
+ //#endregion
236
+ //#region packages/core/src/parser/nodes/import-node.ts
237
+ var SemanticImportNode = class extends SemanticNode {
238
+ registerAtDocument(doc) {
239
+ const imports = this.definition ? this.getIdentifiersRecursive(this.definition) : [];
240
+ doc.registerImport({
241
+ from: this.token("path"),
242
+ imports,
243
+ block: this.token("inner")
244
+ });
245
+ }
246
+ constructor() {
247
+ super("import");
248
+ }
249
+ };
250
+
251
+ //#endregion
252
+ //#region packages/core/src/parser/nodes/interface-node.ts
253
+ var SemanticInterfaceNode = class extends SemanticNode {
254
+ registerAtDocument(doc) {
255
+ super.registerAtDocument(doc);
256
+ const token = this.token("identifier");
257
+ doc.registerDefinition(token);
258
+ if (token && this.token("export")) {
259
+ token.exported = true;
260
+ doc.registerExport(this);
261
+ }
262
+ }
263
+ get props() {
264
+ if (this.definition) return isStructure(this.definition) ? this.definition.props : new Map();
265
+ return new Map();
266
+ }
267
+ constructor() {
268
+ super("interface");
269
+ }
270
+ };
271
+
272
+ //#endregion
273
+ //#region packages/core/src/parser/token.ts
274
+ function _define_property$12(obj, key, value) {
275
+ if (key in obj) Object.defineProperty(obj, key, {
276
+ value,
277
+ enumerable: true,
278
+ configurable: true,
279
+ writable: true
280
+ });
281
+ else obj[key] = value;
282
+ return obj;
283
+ }
284
+ var Token = class Token {
285
+ toString() {
286
+ const children = this.hasChildren ? ` (${this.children.length})` : "";
287
+ return `[${this.type}] "${this.text}"${children}`;
288
+ }
289
+ clone(replace) {
290
+ const t = {
291
+ ...this._data,
292
+ ...replace
293
+ };
294
+ return new Token(t);
295
+ }
296
+ get text() {
297
+ return this._data.text || "";
298
+ }
299
+ get type() {
300
+ return this._data.type;
301
+ }
302
+ get range() {
303
+ return this._data.getRange();
304
+ }
305
+ get children() {
306
+ return this._data.children || [];
307
+ }
308
+ get hasChildren() {
309
+ return Boolean(this._data.children?.length);
310
+ }
311
+ /**
312
+ * This is truth if the text token was ended with a newline character
313
+ */ get multiline() {
314
+ return this._data.multiline;
315
+ }
316
+ get isAnnotation() {
317
+ return this._data.type === "annotation";
318
+ }
319
+ constructor(_data) {
320
+ _define_property$12(this, "_data", void 0);
321
+ /**
322
+ * Set this to file path (e.g. "./src/file.as") for path token in import statement
323
+ */ _define_property$12(this, "fromPath", void 0);
324
+ /**
325
+ * All definitions that exported must be marked with this flag
326
+ */ _define_property$12(this, "exported", void 0);
327
+ /**
328
+ * All the definitions must be marked with this flag
329
+ */ _define_property$12(this, "isDefinition", void 0);
330
+ /**
331
+ * All the references must be marked with this flag
332
+ */ _define_property$12(this, "isReference", void 0);
333
+ /**
334
+ * All the import tokens must be marked with this flag
335
+ */ _define_property$12(this, "imported", void 0);
336
+ /**
337
+ * All the props must be marked with this flag
338
+ */ _define_property$12(this, "isProp", void 0);
339
+ /**
340
+ * Refs chained via . or ["propName"] are marked with this flag
341
+ */ _define_property$12(this, "isChain", void 0);
342
+ _define_property$12(this, "parentNode", void 0);
343
+ /**
344
+ * Only for annotation arguments: reference to their annotation token
345
+ */ _define_property$12(this, "annotationRef", void 0);
346
+ _define_property$12(this, "index", void 0);
347
+ /**
348
+ * Block type
349
+ */ _define_property$12(this, "blockType", void 0);
350
+ this._data = _data;
351
+ }
352
+ };
353
+
354
+ //#endregion
355
+ //#region packages/core/src/parser/nodes/primitive-node.ts
356
+ function _define_property$11(obj, key, value) {
357
+ if (key in obj) Object.defineProperty(obj, key, {
358
+ value,
359
+ enumerable: true,
360
+ configurable: true,
361
+ writable: true
362
+ });
363
+ else obj[key] = value;
364
+ return obj;
365
+ }
366
+ var SemanticPrimitiveNode = class SemanticPrimitiveNode extends SemanticNode {
367
+ applyAnnotations() {
368
+ this.annotations = [];
369
+ if (this.type === "string" || this.type === "array") {
370
+ if (typeof this.config.expect?.minLength === "number") this.annotations.push({
371
+ name: "expect.minLength",
372
+ token: dummyToken,
373
+ args: [num(this.config.expect.minLength)]
374
+ });
375
+ if (typeof this.config.expect?.maxLength === "number") this.annotations.push({
376
+ name: "expect.maxLength",
377
+ token: dummyToken,
378
+ args: [num(this.config.expect.maxLength)]
379
+ });
380
+ }
381
+ if (this.type === "string") {
382
+ if (typeof this.config.expect?.pattern !== "undefined") {
383
+ const patterns = Array.isArray(this.config.expect.pattern) ? this.config.expect.pattern : [this.config.expect.pattern];
384
+ for (const p of patterns) {
385
+ const args = typeof p === "string" ? [text$1(p)] : [text$1(p.source), text$1(p.flags)];
386
+ if (this.config.expect.message) args[2] = text$1(this.config.expect.message);
387
+ this.annotations.push({
388
+ name: "expect.pattern",
389
+ token: dummyToken,
390
+ args
391
+ });
392
+ }
393
+ }
394
+ }
395
+ if (this.type === "number") {
396
+ if (typeof this.config.expect?.min === "number") this.annotations.push({
397
+ name: "expect.min",
398
+ token: dummyToken,
399
+ args: [num(this.config.expect.min)]
400
+ });
401
+ if (typeof this.config.expect?.max === "number") this.annotations.push({
402
+ name: "expect.max",
403
+ token: dummyToken,
404
+ args: [num(this.config.expect.max)]
405
+ });
406
+ if (this.config.expect?.int === true) this.annotations.push({
407
+ name: "expect.int",
408
+ token: dummyToken,
409
+ args: []
410
+ });
411
+ }
412
+ }
413
+ get key() {
414
+ return this.parentKey ? `${this.parentKey}.${this._id}` : this._id;
415
+ }
416
+ getAllTags(_processed) {
417
+ const allTags = [this._id];
418
+ const processed = _processed || new Set();
419
+ processed.add(this);
420
+ for (const [, node] of this.props) {
421
+ if (processed.has(node)) continue;
422
+ processed.add(node);
423
+ allTags.push(...node.getAllTags(processed));
424
+ }
425
+ return allTags;
426
+ }
427
+ get id() {
428
+ return this._id;
429
+ }
430
+ get documentation() {
431
+ return this.config.documentation ? `**${this.key}** - ${this.config.documentation}` : `**${this.key}**`;
432
+ }
433
+ toString(level = 0, prefix = "●") {
434
+ const indent = " ".repeat(level * 2);
435
+ let s = `${this.renderAnnotations()}${prefix} [${this.entity}] ${JSON.stringify(this.config.type)}`;
436
+ s += this.renderChildren();
437
+ return indent + s.split("\n").join(`\n${indent}`);
438
+ }
439
+ constructor(_id, config, parentKey = "") {
440
+ super("primitive"), _define_property$11(this, "_id", void 0), _define_property$11(this, "config", void 0), _define_property$11(this, "parentKey", void 0), _define_property$11(this, "type", void 0), _define_property$11(this, "props", void 0), _define_property$11(this, "tags", void 0), this._id = _id, this.config = config, this.parentKey = parentKey;
441
+ this.props = new Map();
442
+ this.tags = new Set([_id, ...config?.tags || []]);
443
+ for (const [ext, def] of Object.entries(config.extensions || {})) {
444
+ const node = new SemanticPrimitiveNode(ext, {
445
+ type: def.type ?? config.type,
446
+ documentation: def.documentation ?? config.documentation,
447
+ extensions: def.extensions,
448
+ tags: Array.from(new Set([...def.tags || [], ...Array.from(this.tags)])),
449
+ expect: {
450
+ ...config.expect,
451
+ ...def.expect
452
+ }
453
+ }, this.key);
454
+ this.props.set(ext, node);
455
+ }
456
+ if (typeof config.type === "object") this.type = config.type.kind === "final" ? config.type.value : config.type.kind;
457
+ else this.type = config.type;
458
+ this.applyAnnotations();
459
+ }
460
+ };
461
+ const dummyToken = new Token({
462
+ getRange: () => ({
463
+ end: {
464
+ character: 0,
465
+ line: 0
466
+ },
467
+ start: {
468
+ character: 0,
469
+ line: 0
470
+ }
471
+ }),
472
+ text: "",
473
+ type: "identifier"
474
+ });
475
+ const num = (val) => new Token({
476
+ getRange: () => ({
477
+ end: {
478
+ character: 0,
479
+ line: 0
480
+ },
481
+ start: {
482
+ character: 0,
483
+ line: 0
484
+ }
485
+ }),
486
+ text: val.toString(),
487
+ type: "number"
488
+ });
489
+ const text$1 = (val) => new Token({
490
+ getRange: () => ({
491
+ end: {
492
+ character: 0,
493
+ line: 0
494
+ },
495
+ start: {
496
+ character: 0,
497
+ line: 0
498
+ }
499
+ }),
500
+ text: val,
501
+ type: "text"
502
+ });
503
+
504
+ //#endregion
505
+ //#region packages/core/src/parser/nodes/prop-node.ts
506
+ var SemanticPropNode = class extends SemanticNode {
507
+ registerAtDocument(doc) {
508
+ super.registerAtDocument(doc);
509
+ const token = this.token("identifier");
510
+ if (token && token.type === "text" && token.multiline) doc.registerMessage(token, "Unexpected end of string");
511
+ }
512
+ get nestedProps() {
513
+ if (this.definition && isStructure(this.definition)) return this.definition.props;
514
+ }
515
+ get nestedType() {
516
+ if (this.definition && isRef(this.definition)) return this.definition;
517
+ }
518
+ constructor() {
519
+ super("prop");
520
+ }
521
+ };
522
+
523
+ //#endregion
524
+ //#region packages/core/src/parser/nodes/ref-node.ts
525
+ function _define_property$10(obj, key, value) {
526
+ if (key in obj) Object.defineProperty(obj, key, {
527
+ value,
528
+ enumerable: true,
529
+ configurable: true,
530
+ writable: true
531
+ });
532
+ else obj[key] = value;
533
+ return obj;
534
+ }
535
+ var SemanticRefNode = class extends SemanticNode {
536
+ get referredIdentifiers() {
537
+ return [this.token("identifier")];
538
+ }
539
+ registerAtDocument(doc) {
540
+ super.registerAtDocument(doc);
541
+ this.token("identifier").index = 0;
542
+ this._chain.forEach((c) => {
543
+ doc.tokensIndex.add(c);
544
+ });
545
+ this._dots.forEach((d) => {
546
+ doc.tokensIndex.add(d);
547
+ });
548
+ }
549
+ addChain(token) {
550
+ token.parentNode = this;
551
+ token.isChain = true;
552
+ token.index = this._chain.length + 1;
553
+ this._chain.push(token);
554
+ }
555
+ addDot(token) {
556
+ token.parentNode = this;
557
+ token.isChain = true;
558
+ token.index = this._chain.length;
559
+ this._dots.push(token);
560
+ }
561
+ get chain() {
562
+ return this._chain;
563
+ }
564
+ get hasChain() {
565
+ return this._chain.length > 0;
566
+ }
567
+ toString(level = 0, prefix = "●") {
568
+ const indent = " ".repeat(level * 2);
569
+ let s = `${this.renderAnnotations()}${prefix} [${this.entity}] "${this.token("identifier")?.text ?? ""}"`;
570
+ this.tokens?.forEach((t, key) => {
571
+ s += key === "identifier" ? "" : ` ${key}: ${t.text} <${t.type}>`;
572
+ });
573
+ s += this.hasChain ? `.${this.chain.map((c) => `["${c.text}"]`).join(".")}` : "";
574
+ return indent + s.split("\n").join(`\n${indent}`);
575
+ }
576
+ constructor() {
577
+ super("ref"), _define_property$10(this, "_chain", []), _define_property$10(this, "_dots", []);
578
+ }
579
+ };
580
+
581
+ //#endregion
582
+ //#region packages/core/src/parser/nodes/structure-node.ts
583
+ function _define_property$9(obj, key, value) {
584
+ if (key in obj) Object.defineProperty(obj, key, {
585
+ value,
586
+ enumerable: true,
587
+ configurable: true,
588
+ writable: true
589
+ });
590
+ else obj[key] = value;
591
+ return obj;
592
+ }
593
+ var SemanticStructureNode = class extends SemanticGroup {
594
+ /**
595
+ * Shortcut to set props, used as utility
596
+ */ setProps(props$1) {
597
+ this.nodes = props$1;
598
+ for (const prop of props$1) this.props.set(prop.id, prop);
599
+ }
600
+ registerAtDocument(doc) {
601
+ super.registerAtDocument(doc);
602
+ const block$2 = this.token("identifier");
603
+ block$2.blockType = "structure";
604
+ doc.blocksIndex.add(block$2);
605
+ for (const node of this.nodes) {
606
+ const token = node.token("identifier");
607
+ if (!token) {
608
+ doc.registerMessage(block$2, "Has empty prop node");
609
+ continue;
610
+ }
611
+ const name = token.text;
612
+ if (typeof name !== "string") {
613
+ doc.registerMessage(token, "Prop node has no name");
614
+ continue;
615
+ }
616
+ if (this.props.has(name)) {
617
+ doc.registerMessage(token, "Duplicate prop identifier");
618
+ continue;
619
+ }
620
+ if (!isProp(node)) {
621
+ doc.registerMessage(token, "Non-prop node");
622
+ continue;
623
+ }
624
+ this.props.set(name, node);
625
+ }
626
+ }
627
+ addVirtualProp(opts) {
628
+ const token = opts.refToken || this.token("identifier");
629
+ const propToken = token.clone({
630
+ type: "identifier",
631
+ text: opts.name
632
+ });
633
+ const prop = new SemanticPropNode();
634
+ if (opts.documentation) prop.setDocumentation(opts.documentation);
635
+ prop.saveToken(propToken, "identifier");
636
+ if (typeof opts.type === "string") {
637
+ const ref$1 = new SemanticRefNode();
638
+ const [first, ...rest] = opts.type.split(".");
639
+ const refToken = token.clone({
640
+ type: "identifier",
641
+ text: first
642
+ });
643
+ ref$1.saveToken(refToken, "identifier");
644
+ for (const chain of rest) {
645
+ const chainToken = token.clone({
646
+ type: "identifier",
647
+ text: chain
648
+ });
649
+ ref$1.addChain(chainToken);
650
+ }
651
+ prop.define(ref$1);
652
+ } else prop.define(opts.type);
653
+ this.nodes.push(prop);
654
+ this.props.set(opts.name, prop);
655
+ }
656
+ constructor() {
657
+ super(), _define_property$9(this, "props", new Map());
658
+ this.entity = "structure";
659
+ }
660
+ };
661
+
662
+ //#endregion
663
+ //#region packages/core/src/parser/nodes/tuple-node.ts
664
+ var SemanticTupleNode = class extends SemanticGroup {
665
+ constructor() {
666
+ super();
667
+ this.entity = "tuple";
668
+ }
669
+ };
670
+
671
+ //#endregion
672
+ //#region packages/core/src/parser/nodes/type-node.ts
673
+ var SemanticTypeNode = class extends SemanticNode {
674
+ registerAtDocument(doc) {
675
+ super.registerAtDocument(doc);
676
+ const token = this.token("identifier");
677
+ doc.registerDefinition(token);
678
+ if (token && this.token("export")) {
679
+ token.exported = true;
680
+ doc.registerExport(this);
681
+ }
682
+ if (this.definition) {}
683
+ }
684
+ constructor() {
685
+ super("type");
686
+ }
687
+ };
688
+
689
+ //#endregion
690
+ //#region packages/core/src/parser/nodes/index.ts
691
+ const $n = {
692
+ SemanticGroup,
693
+ SemanticInterfaceNode,
694
+ SemanticTypeNode,
695
+ SemanticRefNode,
696
+ SemanticConstNode,
697
+ SemanticPropNode,
698
+ SemanticStructureNode,
699
+ SemanticTupleNode,
700
+ SemanticArrayNode,
701
+ SemanticImportNode,
702
+ SemanticPrimitiveNode
703
+ };
704
+ function isGroup(node) {
705
+ return node?.entity === "group" || node?.entity === "structure" || node?.entity === "tuple";
706
+ }
707
+ function isInterface(node) {
708
+ return node?.entity === "interface";
709
+ }
710
+ function isType(node) {
711
+ return node?.entity === "type";
712
+ }
713
+ function isRef(node) {
714
+ return node?.entity === "ref";
715
+ }
716
+ function isConst(node) {
717
+ return node?.entity === "const";
718
+ }
719
+ function isProp(node) {
720
+ return node?.entity === "prop";
721
+ }
722
+ function isStructure(node) {
723
+ return node?.entity === "structure";
724
+ }
725
+ function isTuple(node) {
726
+ return node?.entity === "tuple";
727
+ }
728
+ function isArray(node) {
729
+ return node?.entity === "array";
730
+ }
731
+ function isImport(node) {
732
+ return node?.entity === "import";
733
+ }
734
+ function isPrimitive(node) {
735
+ return node?.entity === "primitive";
736
+ }
737
+
738
+ //#endregion
739
+ //#region packages/core/src/annotations/annotation-spec.ts
740
+ function _define_property$8(obj, key, value) {
741
+ if (key in obj) Object.defineProperty(obj, key, {
742
+ value,
743
+ enumerable: true,
744
+ configurable: true,
745
+ writable: true
746
+ });
747
+ else obj[key] = value;
748
+ return obj;
749
+ }
750
+ var AnnotationSpec = class {
751
+ get arguments() {
752
+ if (!this.config.argument) return [];
753
+ return Array.isArray(this.config.argument) ? this.config.argument : [this.config.argument];
754
+ }
755
+ get argumentsSnippet() {
756
+ if (this.arguments.length === 0) return "";
757
+ return this.arguments.map((arg, index) => {
758
+ const placeholderIndex = index + 1;
759
+ const defaultValue = this.getDefaultValueForType(arg.name, arg.type);
760
+ const quote = arg.type === "string" ? `'` : "";
761
+ return `${quote}\${${placeholderIndex}:${defaultValue}}${quote}`;
762
+ }).join(", ");
763
+ }
764
+ validateType(tokenType, type$1) {
765
+ switch (type$1) {
766
+ case "string": return tokenType === "text" ? undefined : "string expected.";
767
+ case "number": return tokenType === "number" ? undefined : "number expected.";
768
+ case "boolean": return tokenType === "identifier" ? undefined : "boolean expected.";
769
+ default: return `unknown type "${type$1}".`;
770
+ }
771
+ }
772
+ modify(mainToken, args, doc) {
773
+ if (this.config.modify) this.config.modify(mainToken, args, doc);
774
+ }
775
+ validate(mainToken, args, doc) {
776
+ const messages = [];
777
+ const specArgs = this.arguments;
778
+ if (!mainToken.parentNode) return;
779
+ if (mainToken.parentNode.countAnnotations(mainToken.text.slice(1)) > 1 && !this.config.multiple) messages.push({
780
+ severity: 1,
781
+ message: `Multiple "${mainToken.text}" annotations are not allowed.`,
782
+ range: mainToken.range
783
+ });
784
+ if (this.config.nodeType && this.config.nodeType.length > 0 && !this.config.nodeType.includes(mainToken.parentNode.entity)) messages.push({
785
+ severity: 1,
786
+ message: `${mainToken.text} applies only to ${this.config.nodeType.join(", ")} nodes.`,
787
+ range: mainToken.range
788
+ });
789
+ const requiredCount = specArgs.filter((a) => !a.optional).length;
790
+ if (args.length < requiredCount) messages.push({
791
+ severity: 1,
792
+ message: `${mainToken.text} requires at least ${requiredCount} arguments, but got ${args.length}.`,
793
+ range: mainToken.range
794
+ });
795
+ if (args.length > specArgs.length) {
796
+ const i = specArgs.length;
797
+ messages.push({
798
+ severity: 1,
799
+ message: `${mainToken.text} got ${args.length} arguments, expected ${specArgs.length}.`,
800
+ range: {
801
+ start: args[i].range.start,
802
+ end: args[args.length - 1].range.end
803
+ }
804
+ });
805
+ }
806
+ for (let i = 0; i < args.length; i++) {
807
+ const token = args[i];
808
+ if (i >= specArgs.length) break;
809
+ const argSpec = specArgs[i];
810
+ const tokenType = token.type;
811
+ const valueText = token.text;
812
+ const typeMessage = this.validateType(tokenType, argSpec.type);
813
+ if (typeMessage) {
814
+ messages.push({
815
+ severity: 1,
816
+ message: `${mainToken.text} at argument #${i + 1}: ${typeMessage}`,
817
+ range: token.range
818
+ });
819
+ continue;
820
+ }
821
+ const values = argSpec.type === "boolean" ? ["true", "false"] : argSpec.values;
822
+ if (values && !values.includes(valueText)) messages.push({
823
+ severity: 1,
824
+ message: `${mainToken.text} at argument #${i + 1} ("${argSpec.name}") must be one of [${values.join(", ")}]`,
825
+ range: token.range
826
+ });
827
+ if (this.config.defType?.length) {
828
+ let def = mainToken.parentNode.getDefinition();
829
+ if (isRef(def)) def = doc.unwindType(def.id, def.chain)?.def || def;
830
+ let defEntity = def?.entity || "unknown";
831
+ if (isInterface(def) || isStructure(def)) defEntity = "object";
832
+ else if (isGroup(def) && def.entity !== "tuple") defEntity = def.op === "&" ? "intersection" : "union";
833
+ if (!isPrimitive(def) && !this.config.defType.includes(defEntity) || isPrimitive(def) && !this.config.defType.includes(def.type)) messages.push({
834
+ message: `Expected type is (${this.config.defType.join(" | ")}), got "${isPrimitive(def) ? def.type : def?.entity || "unknown"}"`,
835
+ severity: 1,
836
+ range: mainToken.range
837
+ });
838
+ }
839
+ }
840
+ if (this.config.validate) messages.push(...this.config.validate(mainToken, args, doc) || []);
841
+ return messages.length > 0 ? messages : undefined;
842
+ }
843
+ renderDocs(index) {
844
+ if (typeof index === "number") {
845
+ const a = this.arguments[index];
846
+ if (a) {
847
+ const values = a.values ? `\n\nValues:\n${a.values.join(", ")}` : "";
848
+ return `### \`${a.name}${a.optional ? "?" : ""}: ${a.type}\`\n\n${a.description}${values}`;
849
+ }
850
+ } else {
851
+ const args = this.arguments;
852
+ return `### ${index} ${args.map((a) => `\`${a.name}${a.optional ? "?" : ""}: ${a.type}\``).join(", ")}\n\n${this.config.description}`;
853
+ }
854
+ }
855
+ getDefaultValueForType(name, type$1) {
856
+ switch (type$1) {
857
+ case "string": return name;
858
+ case "number": return "0";
859
+ case "boolean": return "true";
860
+ default: return "";
861
+ }
862
+ }
863
+ constructor(config) {
864
+ _define_property$8(this, "config", void 0);
865
+ _define_property$8(this, "__is_annotation_spec", void 0);
866
+ this.config = config;
867
+ this.__is_annotation_spec = true;
868
+ }
869
+ };
870
+ function isAnnotationSpec(a) {
871
+ return Boolean(a) && a.__is_annotation_spec;
872
+ }
873
+ function resolveAnnotation(name, annotationsTree) {
874
+ const parts = name.split(".");
875
+ let current = annotationsTree;
876
+ for (const part of parts) {
877
+ if (!current || isAnnotationSpec(current)) return undefined;
878
+ current = current[part];
879
+ }
880
+ return isAnnotationSpec(current) ? current : undefined;
881
+ }
882
+
883
+ //#endregion
884
+ //#region packages/core/src/config/define-config.ts
885
+ function defineConfig(config) {
886
+ return config;
887
+ }
888
+
889
+ //#endregion
890
+ //#region packages/core/src/config/load-config.ts
891
+ async function bundleTsConfig(configFile, forceFormat) {
892
+ const dirnameVarName = "injected_original_dirname";
893
+ const filenameVarName = "injected_original_filename";
894
+ const importMetaUrlVarName = "injected_original_import_meta_url";
895
+ const bundle = await (0, rolldown.rolldown)({
896
+ input: configFile,
897
+ platform: "node",
898
+ resolve: { mainFields: ["main"] },
899
+ define: {
900
+ "__dirname": dirnameVarName,
901
+ "__filename": filenameVarName,
902
+ "import.meta.url": importMetaUrlVarName,
903
+ "import.meta.dirname": dirnameVarName,
904
+ "import.meta.filename": filenameVarName
905
+ },
906
+ treeshake: false,
907
+ external: [/^[\w@][^:]/u],
908
+ plugins: [{
909
+ name: "inject-file-scope-variables",
910
+ transform: {
911
+ filter: { id: /\.[cm]?[jt]s$/u },
912
+ handler(code, id) {
913
+ const injectValues = `const ${dirnameVarName} = ${JSON.stringify(node_path.default.dirname(id))};` + `const ${filenameVarName} = ${JSON.stringify(id)};` + `const ${importMetaUrlVarName} = ${JSON.stringify((0, node_url.pathToFileURL)(id).href)};`;
914
+ return {
915
+ code: injectValues + code,
916
+ map: null
917
+ };
918
+ }
919
+ }
920
+ }]
921
+ });
922
+ const outputDir = node_path.default.dirname(configFile);
923
+ const result = await bundle.write({
924
+ dir: outputDir,
925
+ format: forceFormat || "esm",
926
+ sourcemap: "inline",
927
+ entryFileNames: forceFormat === "cjs" ? "atscript.config.[hash].cjs" : "atscript.config.[hash].mjs"
928
+ });
929
+ const fileName = result.output.find((chunk) => chunk.type === "chunk" && chunk.isEntry).fileName;
930
+ return node_path.default.join(outputDir, fileName);
931
+ }
932
+ const SUPPORTED_JS_CONFIG_FORMATS = [
933
+ ".js",
934
+ ".mjs",
935
+ ".cjs"
936
+ ];
937
+ const SUPPORTED_TS_CONFIG_FORMATS = [
938
+ ".ts",
939
+ ".mts",
940
+ ".cts"
941
+ ];
942
+ const SUPPORTED_CONFIG_FORMATS = [...SUPPORTED_JS_CONFIG_FORMATS, ...SUPPORTED_TS_CONFIG_FORMATS];
943
+ const DEFAULT_CONFIG_BASE = "atscript.config";
944
+ async function resolveConfigFile(docUri, _root) {
945
+ const startDir = docUri.endsWith(".as") ? node_path.default.dirname(docUri) : docUri;
946
+ const root$1 = _root || startDir;
947
+ let currentDir = startDir;
948
+ const rootId = "file://" + root$1;
949
+ while (true) {
950
+ const candidate = await findConfigFileName(currentDir);
951
+ if (candidate) return candidate;
952
+ const parentDir = node_path.default.dirname(currentDir);
953
+ if (currentDir === rootId || parentDir === currentDir) break;
954
+ currentDir = parentDir;
955
+ }
956
+ return undefined;
957
+ }
958
+ async function findConfigFileName(d) {
959
+ const p = d.startsWith("file://") ? d.slice(7) : d;
960
+ const filesInWorkingDirectory = new Set(await (0, node_fs_promises.readdir)(decodeURIComponent(p)));
961
+ for (const extension of SUPPORTED_CONFIG_FORMATS) {
962
+ const fileName = `${DEFAULT_CONFIG_BASE}${extension}`;
963
+ if (filesInWorkingDirectory.has(fileName)) return fileName;
964
+ }
965
+ }
966
+ async function loadTsConfig(configFile, forceFormat) {
967
+ const file = await bundleTsConfig(configFile, forceFormat);
968
+ try {
969
+ return (await import((0, node_url.pathToFileURL)(file).href)).default;
970
+ } catch (error) {
971
+ console.error("Could not load config file", file, error);
972
+ return {};
973
+ } finally {
974
+ node_fs.default.unlink(file, () => {});
975
+ }
976
+ }
977
+ async function loadConfig(configPath, forceFormat) {
978
+ const ext = node_path.default.extname(configPath);
979
+ try {
980
+ if (SUPPORTED_JS_CONFIG_FORMATS.includes(ext)) return forceFormat ? await loadTsConfig(node_path.default.resolve(configPath), forceFormat) : (await import((0, node_url.pathToFileURL)(configPath).href)).default;
981
+ else if (SUPPORTED_TS_CONFIG_FORMATS.includes(ext)) {
982
+ const rawConfigPath = node_path.default.resolve(configPath);
983
+ return await loadTsConfig(rawConfigPath, forceFormat);
984
+ } else throw new Error(`Unsupported config format. Expected: \`${SUPPORTED_CONFIG_FORMATS.join(",")}\` but got \`${ext}\``);
985
+ } catch (error) {
986
+ throw new Error("Error happened while loading config.");
987
+ }
988
+ }
989
+
990
+ //#endregion
991
+ //#region packages/core/src/parser/id-registry.ts
992
+ function _define_property$7(obj, key, value) {
993
+ if (key in obj) Object.defineProperty(obj, key, {
994
+ value,
995
+ enumerable: true,
996
+ configurable: true,
997
+ writable: true
998
+ });
999
+ else obj[key] = value;
1000
+ return obj;
1001
+ }
1002
+ var IdRegistry = class {
1003
+ clear() {
1004
+ this.definitions.clear();
1005
+ this.duplicates.clear();
1006
+ this.forbidden.clear();
1007
+ }
1008
+ registerDefinition(token) {
1009
+ if (!token) return;
1010
+ if (this.reserved.has(token.text)) this.forbidden.add(token);
1011
+ else if (this.definitions.has(token.text)) this.duplicates.add(token);
1012
+ else this.definitions.set(token.text, token);
1013
+ }
1014
+ isDefined(t) {
1015
+ const text$2 = typeof t === "string" ? t : t.text;
1016
+ return this.definitions.has(text$2) || this.globalTypes.has(text$2);
1017
+ }
1018
+ getErrors() {
1019
+ return [...Array.from(this.duplicates, (t) => ({
1020
+ severity: 1,
1021
+ message: `Duplicate identifier "${t.text}"`,
1022
+ range: t.range
1023
+ })), ...Array.from(this.forbidden, (t) => ({
1024
+ severity: 1,
1025
+ message: `Reserved keyword "${t.text}"`,
1026
+ range: t.range
1027
+ }))];
1028
+ }
1029
+ constructor(globalTypes = []) {
1030
+ _define_property$7(this, "reserved", void 0);
1031
+ _define_property$7(this, "globalTypes", void 0);
1032
+ _define_property$7(this, "definitions", new Map());
1033
+ _define_property$7(this, "duplicates", new Set());
1034
+ _define_property$7(this, "forbidden", new Set());
1035
+ this.reserved = new Set([
1036
+ "interface",
1037
+ "type",
1038
+ "import",
1039
+ "from",
1040
+ "export"
1041
+ ].concat(globalTypes));
1042
+ this.globalTypes = new Set(globalTypes);
1043
+ }
1044
+ };
1045
+
1046
+ //#endregion
1047
+ //#region packages/core/src/parser/iterator.ts
1048
+ function _define_property$6(obj, key, value) {
1049
+ if (key in obj) Object.defineProperty(obj, key, {
1050
+ value,
1051
+ enumerable: true,
1052
+ configurable: true,
1053
+ writable: true
1054
+ });
1055
+ else obj[key] = value;
1056
+ return obj;
1057
+ }
1058
+ var NodeIterator = class NodeIterator {
1059
+ get index() {
1060
+ return this.i;
1061
+ }
1062
+ get lastNode() {
1063
+ return this.nodes[this.nodes.length - 1];
1064
+ }
1065
+ unexpectedEOB() {
1066
+ this.issues.unexpectedEOB = true;
1067
+ }
1068
+ unfork(fork) {
1069
+ this.i = fork.index;
1070
+ this.update();
1071
+ }
1072
+ accepted() {
1073
+ if (this.$ && this.$.accepted !== false) {
1074
+ this.$.accepted = true;
1075
+ this.badNodes.delete(this.$);
1076
+ }
1077
+ }
1078
+ toString() {
1079
+ return this.$ ? `[${this.$.type}] ${this.$.text}` : `void`;
1080
+ }
1081
+ update() {
1082
+ this.$ = this.nodes[this.i];
1083
+ return this;
1084
+ }
1085
+ move(v = 1) {
1086
+ this.i += v;
1087
+ this.$ = this.nodes[this.i];
1088
+ return this;
1089
+ }
1090
+ /** @deprecated */ killNextNode(n = 1) {
1091
+ this.nodes.splice(this.i + 1, n);
1092
+ }
1093
+ next(skip) {
1094
+ return this.fork().move().skip(skip);
1095
+ }
1096
+ fork(nodes) {
1097
+ return new NodeIterator(nodes || this.nodes, this.messages, this.badNodes, this.issues, nodes ? this.$ : this.parent, nodes ? 0 : this.i).update();
1098
+ }
1099
+ skip(pun$1) {
1100
+ while (this.$?.type === "comment" || this.$?.type === "punctuation" && pun$1?.length && pun$1.includes(this.$.text)) this.move();
1101
+ return this;
1102
+ }
1103
+ skipUntil(pun$1) {
1104
+ while (this.$ && !this.satisfies({
1105
+ node: "punctuation",
1106
+ text: pun$1
1107
+ })) this.move();
1108
+ }
1109
+ unexpected(force = false, msg = "Unexpected token") {
1110
+ if (force && this.$) this.$.accepted = false;
1111
+ if (this.$ && !this.badNodes.has(this.$)) this.badNodes.set(this.$, msg);
1112
+ }
1113
+ shouldHaveError(depth) {
1114
+ for (let i = this.i; i <= depth; i++) if (i < this.nodes.length) this.nodes[i].accepted = false;
1115
+ }
1116
+ nodesLeft() {
1117
+ return this.nodes.length > 0 && this.index < this.nodes.length;
1118
+ }
1119
+ satisfies(...rules) {
1120
+ for (const rule of rules) {
1121
+ const passed = Array.isArray(rule.node) ? rule.node.includes(this.$?.type) : this.$?.type === rule.node;
1122
+ if (passed && rule.text === undefined) return true;
1123
+ if (passed && Array.isArray(rule.text) ? rule.text.includes(this.$?.text) : this.$?.text === rule.text) return true;
1124
+ }
1125
+ return false;
1126
+ }
1127
+ confirmIssues() {
1128
+ if (this.issues.unexpectedEOB) {
1129
+ const node = this.lastNode || this.parent;
1130
+ const pos = node?.getRange().end || {
1131
+ character: 1,
1132
+ line: 1
1133
+ };
1134
+ this.messages.push({
1135
+ severity: 1,
1136
+ message: `Unexpected end of block`,
1137
+ range: {
1138
+ start: pos,
1139
+ end: pos
1140
+ }
1141
+ });
1142
+ this.issues.unexpectedEOB = false;
1143
+ }
1144
+ }
1145
+ getErrors() {
1146
+ this.badNodes.forEach((msg, node) => {
1147
+ if (node.accepted) this.badNodes.delete(node);
1148
+ });
1149
+ return Array.from(this.badNodes.entries(), ([node, msg]) => ({
1150
+ severity: 1,
1151
+ message: msg,
1152
+ range: node.getRange?.() || {
1153
+ start: {
1154
+ character: 1,
1155
+ line: 1
1156
+ },
1157
+ end: {
1158
+ character: 1,
1159
+ line: 1
1160
+ }
1161
+ }
1162
+ })).concat(this.messages);
1163
+ }
1164
+ constructor(nodes, messages = [], badNodes = new Map(), issues = {}, parent, i = -1) {
1165
+ _define_property$6(this, "nodes", void 0);
1166
+ _define_property$6(this, "messages", void 0);
1167
+ _define_property$6(this, "badNodes", void 0);
1168
+ _define_property$6(this, "issues", void 0);
1169
+ _define_property$6(this, "parent", void 0);
1170
+ _define_property$6(this, "i", void 0);
1171
+ _define_property$6(this, "$", void 0);
1172
+ this.nodes = nodes;
1173
+ this.messages = messages;
1174
+ this.badNodes = badNodes;
1175
+ this.issues = issues;
1176
+ this.parent = parent;
1177
+ this.i = i;
1178
+ }
1179
+ };
1180
+
1181
+ //#endregion
1182
+ //#region packages/core/src/parser/utils.ts
1183
+ function toVsCodeRange(start, end, startOffset = 0, endOffset = 0) {
1184
+ return {
1185
+ start: {
1186
+ line: start.row - 1,
1187
+ character: start.col + startOffset
1188
+ },
1189
+ end: {
1190
+ line: end.row - 1,
1191
+ character: end.col + endOffset
1192
+ }
1193
+ };
1194
+ }
1195
+ function resolveAtscriptFromPath(from, id) {
1196
+ return `file://${path.default.join(id.slice(7).split("/").slice(0, -1).join("/"), from)}.as`;
1197
+ }
1198
+ function getRelPath(fromUri, toUri) {
1199
+ const fromPath = new url.URL(fromUri).pathname;
1200
+ const toPath = new url.URL(toUri).pathname;
1201
+ const relPath = path.default.relative(path.default.dirname(fromPath), toPath);
1202
+ const { dir, name } = path.default.parse(relPath);
1203
+ const prefix = dir.startsWith("..") ? "" : "./";
1204
+ return `${prefix}${dir ? `${dir}/` : ""}${name}`;
1205
+ }
1206
+
1207
+ //#endregion
1208
+ //#region packages/core/src/tokenizer/tokens/a-identifier.token.ts
1209
+ const AIdentifierToken = new __prostojs_parser.BasicNode({
1210
+ icon: "@",
1211
+ tokens: [RegExp("@[\\p{ID_Continue}$.]*", "u"), RegExp("[^\\p{ID_Continue}$.]", "u")],
1212
+ tokenOE: "-eject"
1213
+ }).mapContent("text", "join-clear").onMatch((context) => {
1214
+ context.customData.type = "annotation";
1215
+ });
1216
+
1217
+ //#endregion
1218
+ //#region packages/core/src/tokenizer/tokens/block.token.ts
1219
+ const pairs = {
1220
+ "{": "}",
1221
+ "(": ")",
1222
+ "[": "]"
1223
+ };
1224
+ const BlockToken = new __prostojs_parser.BasicNode({
1225
+ label: "block",
1226
+ icon: "→",
1227
+ tokens: [RegExp("(?<text>[([{])", "u"), (context) => pairs[context.getCustomData().text] || ""],
1228
+ tokenOE: "omit-omit",
1229
+ skipToken: /\s/u
1230
+ }).onMatch((context) => {
1231
+ context.customData.type = "block";
1232
+ });
1233
+
1234
+ //#endregion
1235
+ //#region packages/core/src/tokenizer/tokens/comment.token.ts
1236
+ const inline = new __prostojs_parser.BasicNode({
1237
+ label: "inline-comment",
1238
+ icon: "“",
1239
+ tokens: ["//", /$/mu],
1240
+ tokenOE: "omit-omit"
1241
+ }).mapContent("text", "join-clear").popsAtEOFSource(true).onMatch((context) => {
1242
+ context.customData.type = "comment";
1243
+ });
1244
+ const block$1 = new __prostojs_parser.BasicNode({
1245
+ label: "block-comment",
1246
+ icon: "“",
1247
+ tokens: ["/*", "*/"],
1248
+ tokenOE: "omit-omit"
1249
+ }).mapContent("text", "join-clear").popsAtEOFSource(true).onMatch((context) => {
1250
+ context.customData.type = "comment";
1251
+ });
1252
+ const commentNodes = {
1253
+ inline,
1254
+ block: block$1,
1255
+ all: [inline, block$1]
1256
+ };
1257
+
1258
+ //#endregion
1259
+ //#region packages/core/src/tokenizer/tokens/identifier.token.ts
1260
+ const IdentifierToken = new __prostojs_parser.BasicNode({
1261
+ icon: "I",
1262
+ tokens: [RegExp("[\\p{ID_Start}$_][\\p{ID_Continue}$]*", "u"), RegExp("[^\\p{ID_Continue}$]", "u")],
1263
+ tokenOE: "consume-eject"
1264
+ }).mapContent("text", "join-clear").onMatch((context) => {
1265
+ context.customData.type = "identifier";
1266
+ });
1267
+
1268
+ //#endregion
1269
+ //#region packages/core/src/tokenizer/tokens/number.token.ts
1270
+ const NumberToken = new __prostojs_parser.BasicNode({
1271
+ icon: "N",
1272
+ tokens: [RegExp("\\d[\\p{ID_Continue}$]*", "u"), RegExp("[^\\p{ID_Continue}$]", "u")],
1273
+ tokenOE: "consume-eject"
1274
+ }).mapContent("text", "join-clear").onMatch((context) => {
1275
+ context.customData.type = "number";
1276
+ });
1277
+
1278
+ //#endregion
1279
+ //#region packages/core/src/tokenizer/tokens/punctuation.token.ts
1280
+ const PunctuationToken = new __prostojs_parser.BasicNode({
1281
+ tokens: [RegExp("(?<text>[\\n!&+,\\-./:;=?|])", "u"), ""],
1282
+ tokenOE: "omit-omit",
1283
+ icon: "..."
1284
+ }).onMatch((context) => {
1285
+ context.customData.type = "punctuation";
1286
+ });
1287
+
1288
+ //#endregion
1289
+ //#region packages/core/src/tokenizer/tokens/text.node.ts
1290
+ const TextToken = new __prostojs_parser.BasicNode({
1291
+ icon: "T",
1292
+ tokens: [RegExp("(?<quote>[\"'])", "u"), (context) => new RegExp(`(?<end>${context.getCustomData().quote || ""}|\\n)`)],
1293
+ backSlash: "-ignore",
1294
+ tokenOE: "omit-omit"
1295
+ }).mapContent("text", "join-clear").onMatch((context) => {
1296
+ context.customData.type = "text";
1297
+ }).onPop((context) => {
1298
+ context.customData.multiline = context.customData.end === "\n";
1299
+ });
1300
+
1301
+ //#endregion
1302
+ //#region packages/core/src/tokenizer/tokens/index.ts
1303
+ const tokens = {
1304
+ aIdentifier: AIdentifierToken,
1305
+ punctuation: PunctuationToken,
1306
+ comments: commentNodes.all,
1307
+ inlineComment: commentNodes.inline,
1308
+ blockComment: commentNodes.block,
1309
+ block: BlockToken,
1310
+ identifier: IdentifierToken,
1311
+ number: NumberToken,
1312
+ text: TextToken,
1313
+ root: undefined
1314
+ };
1315
+ const root = new __prostojs_parser.BasicNode({
1316
+ label: "root",
1317
+ skipToken: /\s/u
1318
+ }).addRecognizes(...tokens.comments, tokens.block, tokens.aIdentifier, tokens.identifier, tokens.text, tokens.number, tokens.punctuation);
1319
+ tokens.root = root;
1320
+ BlockToken.addRecognizes(...tokens.comments, tokens.block, tokens.aIdentifier, tokens.identifier, tokens.text, tokens.number, tokens.punctuation);
1321
+ const mapContent = (content) => content.map((item) => {
1322
+ if (typeof item === "string") return {
1323
+ type: "unknown",
1324
+ text: item
1325
+ };
1326
+ const data = item.getCustomData();
1327
+ data.getRange = () => toVsCodeRange(item.startPos, item.endPos, data.startOffset, data.endOffset);
1328
+ return data;
1329
+ });
1330
+ for (const node of Object.values(tokens)) if (node instanceof __prostojs_parser.BasicNode) node.popsAtEOFSource(true).mapContent("children", mapContent);
1331
+
1332
+ //#endregion
1333
+ //#region packages/core/src/tokenizer/index.ts
1334
+ function tokenize(source, debug = false) {
1335
+ const tokens$1 = root.parse(source);
1336
+ if (debug) console.log(tokens$1.toTree());
1337
+ return mapContent(tokens$1.content);
1338
+ }
1339
+
1340
+ //#endregion
1341
+ //#region packages/core/src/parser/pipes/tokens.pipe.ts
1342
+ const identifier = (...text$2) => $token("identifier", text$2.length > 0 ? text$2 : undefined);
1343
+ const text = (...text$2) => $token("text", text$2.length > 0 ? text$2 : undefined);
1344
+ const block = (...text$2) => $token("block", text$2.length > 0 ? text$2.map((v) => v[0]) : undefined);
1345
+ const pun = (...text$2) => $token("punctuation", text$2.length > 0 ? text$2 : undefined);
1346
+ function $token(name, text$2) {
1347
+ const opts = {
1348
+ optional: false,
1349
+ saveAs: undefined,
1350
+ skip: undefined,
1351
+ expect: [{
1352
+ node: name,
1353
+ text: text$2
1354
+ }],
1355
+ isGlobal: false,
1356
+ empty: false,
1357
+ wrapper: undefined,
1358
+ wrapMultiple: false,
1359
+ debug: false,
1360
+ eob: false,
1361
+ suppressEobError: false,
1362
+ lookBehind: false
1363
+ };
1364
+ return {
1365
+ expect: [{
1366
+ node: name,
1367
+ text: text$2
1368
+ }],
1369
+ handler(ni, target) {
1370
+ if (opts.debug) debugger;
1371
+ let firstRun = true;
1372
+ while (firstRun || opts.wrapMultiple) {
1373
+ firstRun = false;
1374
+ if (!ni.$) {
1375
+ const ok = opts.eob || opts.optional;
1376
+ if (!ok && !opts.suppressEobError) ni.unexpectedEOB();
1377
+ return ok;
1378
+ }
1379
+ let matched = ni.satisfies(...opts.expect);
1380
+ if (!matched && opts.lookBehind) {
1381
+ matched = ni.fork().move(-1).satisfies(...opts.expect);
1382
+ if (matched) ni.move(-1);
1383
+ }
1384
+ if (matched) {
1385
+ if (opts.empty && ni.$.children?.length) {
1386
+ ni.unexpected(false, `Expected empty block`);
1387
+ return opts.optional;
1388
+ }
1389
+ if (opts.saveAs) target.node.saveToken(new Token(ni.$), opts.saveAs);
1390
+ ni.accepted();
1391
+ if (opts.wrapper) {
1392
+ const wrapped = target.node;
1393
+ target.node = opts.wrapper().wrap(wrapped, new Token(ni.$));
1394
+ }
1395
+ ni.move();
1396
+ if (opts.skip) ni.skip(opts.skip);
1397
+ if (opts.wrapMultiple) continue;
1398
+ else return true;
1399
+ } else {
1400
+ if (!opts.optional) ni.unexpected();
1401
+ return opts.optional;
1402
+ }
1403
+ }
1404
+ return true;
1405
+ },
1406
+ saveAs(v) {
1407
+ opts.saveAs = v;
1408
+ return this;
1409
+ },
1410
+ wrap(sn, multiple = false) {
1411
+ opts.wrapper = sn;
1412
+ opts.wrapMultiple = multiple;
1413
+ return this;
1414
+ },
1415
+ optional() {
1416
+ opts.optional = true;
1417
+ return this;
1418
+ },
1419
+ empty() {
1420
+ opts.empty = true;
1421
+ return this;
1422
+ },
1423
+ skip(...p) {
1424
+ opts.skip = p;
1425
+ return this;
1426
+ },
1427
+ or(t) {
1428
+ opts.expect.push(...t.expect);
1429
+ return this;
1430
+ },
1431
+ orEob() {
1432
+ opts.eob = true;
1433
+ return this;
1434
+ },
1435
+ suppressEobError() {
1436
+ opts.suppressEobError = true;
1437
+ return this;
1438
+ },
1439
+ global() {
1440
+ opts.isGlobal = true;
1441
+ return this;
1442
+ },
1443
+ lookBehind() {
1444
+ opts.lookBehind = true;
1445
+ return this;
1446
+ },
1447
+ debug() {
1448
+ opts.debug = true;
1449
+ return this;
1450
+ }
1451
+ };
1452
+ }
1453
+
1454
+ //#endregion
1455
+ //#region packages/core/src/parser/pipes/core.pipe.ts
1456
+ function $pipe(entity, pipe = []) {
1457
+ pipe.forEach((p, i) => Object.assign(p, { toString: () => `${entity}.${i}` }));
1458
+ return {
1459
+ targetFactory: () => {
1460
+ switch (entity) {
1461
+ case "interface": return new $n.SemanticInterfaceNode();
1462
+ case "array": return new $n.SemanticArrayNode();
1463
+ case "const": return new $n.SemanticConstNode();
1464
+ case "group": return new $n.SemanticGroup();
1465
+ case "prop": return new $n.SemanticPropNode();
1466
+ case "type": return new $n.SemanticTypeNode();
1467
+ case "ref": return new $n.SemanticRefNode();
1468
+ case "structure": return new $n.SemanticStructureNode();
1469
+ case "tuple": return new $n.SemanticTupleNode();
1470
+ case "import": return new $n.SemanticImportNode();
1471
+ case "primitive": throw new Error("Can't create pipe for primitive node");
1472
+ default: throw new Error(`Can't create pipe for ${entity} node`);
1473
+ }
1474
+ },
1475
+ pipe,
1476
+ toString: () => entity,
1477
+ skipTokens: [],
1478
+ stopCondition: undefined,
1479
+ skip(...s) {
1480
+ this.skipTokens.push(...s);
1481
+ return this;
1482
+ },
1483
+ stop(sc) {
1484
+ this.stopCondition = sc;
1485
+ return this;
1486
+ },
1487
+ t(node, skip = []) {
1488
+ this.pipe.push($token(node).saveAs("identifier").skip(...skip));
1489
+ return this;
1490
+ }
1491
+ };
1492
+ }
1493
+ function runPipes(pipes$1, ni, singlePass = false) {
1494
+ const nodes = [];
1495
+ while (ni.$) {
1496
+ let matched = true;
1497
+ let depth = ni.index;
1498
+ for (const { targetFactory, pipe, skipTokens: skip, stopCondition } of pipes$1) {
1499
+ const target = { node: targetFactory() };
1500
+ const fork = ni.fork();
1501
+ fork.skip(skip);
1502
+ if (!fork.$) {
1503
+ ni.unfork(fork);
1504
+ break;
1505
+ }
1506
+ matched = true;
1507
+ for (const { handler } of pipe) if (!handler(fork, target)) {
1508
+ matched = false;
1509
+ break;
1510
+ }
1511
+ if (fork.index > depth) depth = fork.index;
1512
+ if (matched) {
1513
+ nodes.push(target.node);
1514
+ ni.unfork(fork);
1515
+ if (stopCondition && stopCondition(fork)) return nodes;
1516
+ ni.move(-1);
1517
+ break;
1518
+ }
1519
+ }
1520
+ if (singlePass) return nodes;
1521
+ if (!matched) {
1522
+ ni.shouldHaveError(depth);
1523
+ ni.move(depth - ni.index);
1524
+ }
1525
+ ni.move();
1526
+ if (matched) {} else {
1527
+ ni.confirmIssues();
1528
+ ni.skipUntil([";", "\n"]);
1529
+ }
1530
+ }
1531
+ return nodes;
1532
+ }
1533
+ function runPipesOnce(pipes$1, ni) {
1534
+ return runPipes(pipes$1, ni, true)[0];
1535
+ }
1536
+
1537
+ //#endregion
1538
+ //#region packages/core/src/parser/grouping.ts
1539
+ function groupByPriority(nodes, priority) {
1540
+ if (nodes.length === 1) return nodes[0];
1541
+ if (nodes.length === 0) return undefined;
1542
+ if (nodes.length % 2 === 0) throw new Error(`Invalid number of nodes ${nodes.length}. Odd number expected`);
1543
+ let currentPass = nodes;
1544
+ let temporaryResult = [];
1545
+ let groupped = [];
1546
+ for (const p of priority) {
1547
+ for (const [i, node] of currentPass.entries()) {
1548
+ const isOperator = i % 2 === 1;
1549
+ if (!isOperator && node instanceof Token) throw new Error(`Unexpected token ${node.toString()} at ${i}`);
1550
+ else if (isOperator && !(node instanceof Token)) throw new Error(`Unexpected token ${isGroup(node) ? node.op : node.token.toString()} at ${i}`);
1551
+ if (isOperator) {
1552
+ if (node.text !== p) temporaryResult.push(node);
1553
+ continue;
1554
+ }
1555
+ const prev = currentPass[i - 1]?.text;
1556
+ const next = currentPass[i + 1]?.text;
1557
+ if (prev !== p && next !== p) {
1558
+ temporaryResult.push(node);
1559
+ continue;
1560
+ }
1561
+ if (prev === p || next === p) {
1562
+ groupped.push(node);
1563
+ if (next !== p) {
1564
+ temporaryResult.push(new $n.SemanticGroup(groupped, p));
1565
+ groupped = [];
1566
+ }
1567
+ }
1568
+ }
1569
+ currentPass = temporaryResult;
1570
+ temporaryResult = [];
1571
+ }
1572
+ const output = currentPass[0];
1573
+ return output.length === 1 ? output.first : output;
1574
+ }
1575
+
1576
+ //#endregion
1577
+ //#region packages/core/src/parser/pipes/special.pipe.ts
1578
+ function refWithChain() {
1579
+ const s = {
1580
+ id: { node: "identifier" },
1581
+ dot: {
1582
+ node: "punctuation",
1583
+ text: "."
1584
+ },
1585
+ block: {
1586
+ node: "block",
1587
+ text: "["
1588
+ },
1589
+ end: {
1590
+ node: "punctuation",
1591
+ text: ";"
1592
+ }
1593
+ };
1594
+ return { handler(ni, target) {
1595
+ ni.skip(["\n"]);
1596
+ if (!ni.$) return false;
1597
+ if (ni.satisfies(s.id)) {
1598
+ ni.accepted();
1599
+ target.node.saveToken(new Token(ni.$), "identifier");
1600
+ } else return false;
1601
+ ni.move();
1602
+ if (ni.fork().skip(["\n"]).satisfies(s.end)) {
1603
+ ni.skip(["\n", ";"]);
1604
+ return true;
1605
+ }
1606
+ const fork = ni.fork();
1607
+ let isDot = fork.skip(["\n"]).satisfies(s.dot);
1608
+ let isBlock = fork.satisfies(s.block);
1609
+ while (fork.$ && (isDot || isBlock)) {
1610
+ if (isBlock) if (fork.$.children?.length === 0) {
1611
+ while (isBlock && fork.$.children?.length === 0) {
1612
+ target.node = new SemanticArrayNode().wrap(target.node, new Token(fork.$));
1613
+ fork.move();
1614
+ fork.skip(["\n", ";"]);
1615
+ isBlock = fork.satisfies(s.block);
1616
+ }
1617
+ ni.unfork(fork);
1618
+ return true;
1619
+ } else if (fork.$.children?.length === 1 && fork.$.children[0].type === "text") {
1620
+ if (isRef(target.node)) target.node.addChain(new Token(fork.$.children[0]));
1621
+ } else return true;
1622
+ else {
1623
+ fork.skip(["\n"]);
1624
+ if (fork.next().satisfies(s.id)) {
1625
+ if (isRef(target.node)) target.node.addDot(new Token(fork.$));
1626
+ fork.move();
1627
+ if (isRef(target.node) && fork.$) target.node.addChain(new Token(fork.$));
1628
+ } else {
1629
+ if (isRef(target.node)) target.node.addDot(new Token(fork.$));
1630
+ fork.unexpected();
1631
+ fork.move(1);
1632
+ fork.unexpected();
1633
+ ni.unfork(fork);
1634
+ ni.move();
1635
+ ni.skip([";", "\n"]);
1636
+ return true;
1637
+ }
1638
+ }
1639
+ fork.move();
1640
+ ni.unfork(fork);
1641
+ if (ni.fork().skip(["\n"]).satisfies(s.end)) {
1642
+ ni.skip(["\n", ";"]);
1643
+ return true;
1644
+ }
1645
+ isDot = fork.skip(["\n"]).satisfies(s.dot);
1646
+ isBlock = fork.satisfies(s.block);
1647
+ }
1648
+ return true;
1649
+ } };
1650
+ }
1651
+ function annotations() {
1652
+ const opts = {
1653
+ annotation: { node: "annotation" },
1654
+ argument: [{ node: ["number", "text"] }, {
1655
+ node: "identifier",
1656
+ text: [
1657
+ "true",
1658
+ "false",
1659
+ "undefined",
1660
+ "null"
1661
+ ]
1662
+ }],
1663
+ comma: {
1664
+ node: "punctuation",
1665
+ text: ","
1666
+ },
1667
+ end: {
1668
+ node: "punctuation",
1669
+ text: [";", "\n"]
1670
+ }
1671
+ };
1672
+ return { handler(ni, target) {
1673
+ while (ni.$ && ni.satisfies(opts.annotation)) {
1674
+ const key = ni.$.text?.slice(1);
1675
+ ni.accepted();
1676
+ const addArgument = target.node.annotate(key, new Token(ni.$));
1677
+ ni.move();
1678
+ while (ni.satisfies(opts.comma)) {
1679
+ addArgument(new Token(ni.$));
1680
+ ni.accepted();
1681
+ ni.move();
1682
+ }
1683
+ while (ni.satisfies(...opts.argument)) {
1684
+ addArgument(new Token(ni.$));
1685
+ ni.accepted();
1686
+ ni.move();
1687
+ if (ni.satisfies(opts.comma)) {
1688
+ ni.accepted();
1689
+ ni.move();
1690
+ while (ni.satisfies(opts.comma)) {
1691
+ addArgument(new Token(ni.$));
1692
+ ni.accepted();
1693
+ ni.move();
1694
+ }
1695
+ } else break;
1696
+ }
1697
+ if (ni.satisfies(opts.end)) ni.skip([";", "\n"]);
1698
+ else if (ni.$) {
1699
+ ni.unexpected(false, `Unexpected token in annotation ${ni.toString()}`);
1700
+ ni.skipUntil([";", "\n"]);
1701
+ ni.skip([";", "\n"]);
1702
+ }
1703
+ }
1704
+ return true;
1705
+ } };
1706
+ }
1707
+ function definition(pipes$1) {
1708
+ const opts = {
1709
+ sep: [],
1710
+ priority: false,
1711
+ multiple: false,
1712
+ from: undefined,
1713
+ debug: false,
1714
+ skip: []
1715
+ };
1716
+ return {
1717
+ handler(ni, target) {
1718
+ const targetNode = target.node;
1719
+ if (opts.debug) debugger;
1720
+ if (!ni.$ && !opts.from) return false;
1721
+ if (opts.from && !targetNode.has(opts.from)) {
1722
+ ni.unexpected(false, `Unexpected definition`);
1723
+ return false;
1724
+ }
1725
+ const fork = opts.from ? ni.fork(targetNode.token(opts.from)?.children) : ni;
1726
+ if (opts.from && !fork.nodesLeft()) {
1727
+ targetNode.define(new $n.SemanticGroup());
1728
+ return true;
1729
+ }
1730
+ const resolvedPipes = pipes$1.map((p) => typeof p === "function" ? p() : p);
1731
+ const node = runPipesOnce(resolvedPipes, fork);
1732
+ if (node) {
1733
+ fork.accepted();
1734
+ fork.move();
1735
+ fork.skip(opts.skip);
1736
+ if (!opts.multiple) {
1737
+ targetNode.define(node);
1738
+ return true;
1739
+ }
1740
+ } else {
1741
+ fork.unexpected();
1742
+ return false;
1743
+ }
1744
+ const nodes = [node];
1745
+ while (opts.multiple && fork.$) {
1746
+ if (opts.sep.length > 0) if (fork.satisfies({
1747
+ node: "punctuation",
1748
+ text: opts.sep
1749
+ })) {
1750
+ if (opts.priority) if (fork.next(opts.skip).$) nodes.push(new Token(fork.$));
1751
+ else {
1752
+ fork.unexpected(false, "Unexpected end of group");
1753
+ break;
1754
+ }
1755
+ fork.accepted();
1756
+ fork.move();
1757
+ fork.skip(opts.skip);
1758
+ } else {
1759
+ if (fork.$) fork.unexpected();
1760
+ break;
1761
+ }
1762
+ const nextNode = runPipesOnce(resolvedPipes, fork);
1763
+ if (nextNode) {
1764
+ nodes.push(nextNode);
1765
+ fork.accepted();
1766
+ fork.move();
1767
+ fork.skip(opts.skip);
1768
+ } else {
1769
+ fork.unexpected();
1770
+ return false;
1771
+ }
1772
+ }
1773
+ if (nodes.length === 1) targetNode.define(nodes[0]);
1774
+ else if (opts.priority && opts.sep.length > 0) {
1775
+ if (nodes.length % 2 === 0) {
1776
+ fork.next().unexpected(false, "Error in group definition");
1777
+ return false;
1778
+ }
1779
+ targetNode.define(groupByPriority(nodes, opts.sep));
1780
+ } else targetNode.define(new $n.SemanticGroup(nodes));
1781
+ return true;
1782
+ },
1783
+ separatedBy(...p) {
1784
+ opts.multiple = true;
1785
+ opts.sep.push(...p);
1786
+ return this;
1787
+ },
1788
+ respectPriority() {
1789
+ opts.priority = true;
1790
+ return this;
1791
+ },
1792
+ multiple() {
1793
+ opts.multiple = true;
1794
+ return this;
1795
+ },
1796
+ from(attr) {
1797
+ opts.from = attr;
1798
+ return this;
1799
+ },
1800
+ skip(...skip) {
1801
+ opts.skip = skip;
1802
+ return this;
1803
+ },
1804
+ debug() {
1805
+ opts.debug = true;
1806
+ return this;
1807
+ }
1808
+ };
1809
+ }
1810
+ function unwrap(attr) {
1811
+ const opts = { pipes: [] };
1812
+ return {
1813
+ handler(ni, target) {
1814
+ if (!target.node.has(attr)) return false;
1815
+ const token = target.node.token(attr);
1816
+ const fork = ni.fork(token.children || []);
1817
+ const nodes = runPipes(opts.pipes, fork);
1818
+ target.node.define(new $n.SemanticGroup(nodes));
1819
+ return true;
1820
+ },
1821
+ with(pipes$1) {
1822
+ opts.pipes = pipes$1;
1823
+ return this;
1824
+ }
1825
+ };
1826
+ }
1827
+
1828
+ //#endregion
1829
+ //#region packages/core/src/parser/pipes/pipes.ts
1830
+ const ref = $pipe("ref", [refWithChain()]);
1831
+ const constText = defineValuePipe("const", "text", false);
1832
+ const constNumber = defineValuePipe("const", "number", false);
1833
+ const allowedValuesPipeArray = [
1834
+ ref,
1835
+ constText,
1836
+ constNumber
1837
+ ];
1838
+ const tuplePipeArray = [
1839
+ block("[]").saveAs("identifier"),
1840
+ definition(allowedValuesPipeArray).from("identifier").separatedBy("&", "|", ",").skip("\n").respectPriority(),
1841
+ block("[]").optional().empty().wrap(() => new SemanticArrayNode(), true)
1842
+ ];
1843
+ const groupPipeArray = [
1844
+ block("()").saveAs("identifier"),
1845
+ definition(allowedValuesPipeArray).from("identifier").separatedBy("&", "|").skip("\n").respectPriority(),
1846
+ block("[]").optional().empty().wrap(() => new $n.SemanticArrayNode(), true)
1847
+ ];
1848
+ const tuple = $pipe("tuple", tuplePipeArray).skip("\n");
1849
+ const group = $pipe("group", groupPipeArray).skip("\n");
1850
+ allowedValuesPipeArray.unshift(tuple);
1851
+ allowedValuesPipeArray.unshift(group);
1852
+ const type = $pipe("type", [
1853
+ annotations(),
1854
+ identifier("export").saveAs("export").optional().skip("\n"),
1855
+ identifier("type").saveAs("type").skip("\n").suppressEobError(),
1856
+ identifier().saveAs("identifier").global().skip("\n"),
1857
+ pun("=").skip("\n"),
1858
+ definition(allowedValuesPipeArray).separatedBy("&", "|").skip("\n").respectPriority()
1859
+ ]).skip("\n", ";");
1860
+ const props = $pipe("prop", [
1861
+ annotations(),
1862
+ identifier().or(text()).saveAs("identifier").skip("\n"),
1863
+ pun("?").saveAs("optional").optional().skip("\n"),
1864
+ pun(":").skip("\n"),
1865
+ definition(allowedValuesPipeArray).separatedBy("&", "|").skip("\n").respectPriority(),
1866
+ pun(";", ",", "\n").orEob().lookBehind()
1867
+ ]).skip("\n", ";", ",");
1868
+ const structurePipeArray = [
1869
+ block("{}").saveAs("identifier"),
1870
+ unwrap("identifier").with([props]),
1871
+ block("[]").optional().empty().wrap(() => new $n.SemanticArrayNode(), true)
1872
+ ];
1873
+ function structureBlock(array = false) {
1874
+ return $pipe("structure", array ? structurePipeArray : structurePipeArray.slice(0, 2)).skip("\n", ";");
1875
+ }
1876
+ allowedValuesPipeArray.unshift(structureBlock(true));
1877
+ const interfaceType = $pipe("interface", [
1878
+ annotations(),
1879
+ identifier("export").saveAs("export").optional().skip("\n"),
1880
+ identifier("interface").saveAs("type").skip("\n").suppressEobError(),
1881
+ identifier().saveAs("identifier").global().skip("\n"),
1882
+ definition([structureBlock()])
1883
+ ]).skip("\n", ";");
1884
+ function defineValuePipe(entity, name, supportArray = false) {
1885
+ const steps = [$token(name).saveAs("identifier")];
1886
+ if (supportArray) steps.push(block("[]").optional().empty().wrap(() => new $n.SemanticArrayNode(), true));
1887
+ return $pipe(entity, steps).skip("\n");
1888
+ }
1889
+ const importPipe = $pipe("import", [
1890
+ identifier("import").saveAs("identifier").skip("\n"),
1891
+ block("{}").saveAs("inner").skip("\n"),
1892
+ identifier("from").saveAs("from").skip("\n"),
1893
+ text().saveAs("path").skip(";", "\n"),
1894
+ definition([$pipe("ref", [identifier().saveAs("identifier").skip("\n")])]).from("inner").separatedBy(",").skip("\n").respectPriority()
1895
+ ]).skip("\n", ";");
1896
+ const pipes = {
1897
+ type,
1898
+ props,
1899
+ interfaceType,
1900
+ importPipe,
1901
+ tuple
1902
+ };
1903
+
1904
+ //#endregion
1905
+ //#region packages/core/src/token-index/blocks-index.ts
1906
+ function _define_property$5(obj, key, value) {
1907
+ if (key in obj) Object.defineProperty(obj, key, {
1908
+ value,
1909
+ enumerable: true,
1910
+ configurable: true,
1911
+ writable: true
1912
+ });
1913
+ else obj[key] = value;
1914
+ return obj;
1915
+ }
1916
+ /**
1917
+ * Compares two positions.
1918
+ * @param a - The first position.
1919
+ * @param b - The second position.
1920
+ * @returns -1 if `a` is less than `b`, 1 if `a` is greater than `b`, 0 if they are equal.
1921
+ */ function comparePos(a, b) {
1922
+ if (a.line < b.line) return -1;
1923
+ if (a.line > b.line) return 1;
1924
+ if (a.character < b.character) return -1;
1925
+ if (a.character > b.character) return 1;
1926
+ return 0;
1927
+ }
1928
+ /**
1929
+ * Checks if a given position (line, character) is contained within a token's range.
1930
+ * @param token - The token to check.
1931
+ * @param line - The line number of the position.
1932
+ * @param character - The character number of the position.
1933
+ * @returns `true` if the position is within the token's range, `false` otherwise.
1934
+ */ function contains(token, line, character) {
1935
+ const startCmp = comparePos(token.range.start, {
1936
+ line,
1937
+ character
1938
+ });
1939
+ const endCmp = comparePos(token.range.end, {
1940
+ line,
1941
+ character
1942
+ });
1943
+ return startCmp <= 0 && endCmp > 0;
1944
+ }
1945
+ /**
1946
+ * Determines if token `a` is more nested than token `b`.
1947
+ * @param a - The first token.
1948
+ * @param b - The second token.
1949
+ * @returns `true` if `a` is more nested than `b`, `false` otherwise.
1950
+ */ function moreNested(a, b) {
1951
+ const startCmp = comparePos(a.range.start, b.range.start);
1952
+ const endCmp = comparePos(a.range.end, b.range.end);
1953
+ return startCmp >= 0 && endCmp <= 0;
1954
+ }
1955
+ var BlocksIndex = class {
1956
+ /**
1957
+ * Adds a new token to the index. The token collection is maintained in sorted order by start position.
1958
+ * @param block - The token to add.
1959
+ */ add(block$2) {
1960
+ let left = 0;
1961
+ let right = this.blocks.length;
1962
+ while (left < right) {
1963
+ const mid = left + right >> 1;
1964
+ if (comparePos(this.blocks[mid].range.start, block$2.range.start) < 0) left = mid + 1;
1965
+ else right = mid;
1966
+ }
1967
+ this.blocks.splice(left, 0, block$2);
1968
+ }
1969
+ /**
1970
+ * Finds the most nested token at a specific position.
1971
+ * @param line - The line number of the position.
1972
+ * @param character - The character number of the position.
1973
+ * @returns The most nested token at the given position, or `undefined` if no token is found.
1974
+ */ at(line, character) {
1975
+ const candidates = [];
1976
+ for (const block$2 of this.blocks) {
1977
+ if (comparePos(block$2.range.start, {
1978
+ line,
1979
+ character
1980
+ }) > 0) break;
1981
+ if (contains(block$2, line, character)) candidates.push(block$2);
1982
+ }
1983
+ if (candidates.length === 0) return undefined;
1984
+ let result = candidates[0];
1985
+ for (let i = 1; i < candidates.length; i++) if (moreNested(candidates[i], result)) result = candidates[i];
1986
+ return result;
1987
+ }
1988
+ before(line, character) {
1989
+ throw new Error("Not implemented");
1990
+ }
1991
+ constructor() {
1992
+ _define_property$5(this, "blocks", []);
1993
+ }
1994
+ };
1995
+
1996
+ //#endregion
1997
+ //#region packages/core/src/token-index/tokens-index.ts
1998
+ function _define_property$4(obj, key, value) {
1999
+ if (key in obj) Object.defineProperty(obj, key, {
2000
+ value,
2001
+ enumerable: true,
2002
+ configurable: true,
2003
+ writable: true
2004
+ });
2005
+ else obj[key] = value;
2006
+ return obj;
2007
+ }
2008
+ var TokensIndex = class {
2009
+ /**
2010
+ * Adds a token to the index. The token is stored based on its starting line.
2011
+ * @param token - The token to add to the index.
2012
+ */ add(token) {
2013
+ if (!token?.range) return;
2014
+ const line = token.range.start.line;
2015
+ this.tokensMap[line] = this.tokensMap[line] ?? new Set();
2016
+ this.tokensMap[line].add(token);
2017
+ }
2018
+ /**
2019
+ * Retrieves a token at a specific line and character, if one exists.
2020
+ * @param line - The line number to search in.
2021
+ * @param character - The character position within the line to search for.
2022
+ * @returns The token at the specified line and character, or `undefined` if none exists.
2023
+ */ at(line, character) {
2024
+ const tokens$1 = this.tokensMap[line];
2025
+ if (!tokens$1) return undefined;
2026
+ return Array.from(tokens$1).find((t) => t.range.start.character <= character && t.range.end.character >= character);
2027
+ }
2028
+ /**
2029
+ * Retrieves either the token at the specified (line, character), or if none exists,
2030
+ * the closest token that ends on or before that position. This method checks:
2031
+ * 1. If a token spans (line, character), return it immediately.
2032
+ * 2. Otherwise, look within the same line for tokens that end before `character`.
2033
+ * 3. If still none found, move upwards to previous lines and return the token that ends last.
2034
+ * @param line - The line number to search in.
2035
+ * @param character - The character position within the line to search for.
2036
+ * @returns The found token, or `undefined` if no suitable token is found.
2037
+ */ before(line, character) {
2038
+ const current = this.at(line, character);
2039
+ if (current) return current;
2040
+ const tokensAtLine = this.tokensMap[line];
2041
+ if (tokensAtLine) {
2042
+ let candidate;
2043
+ for (const t of tokensAtLine) if (t.range.end.character < character && (!candidate || t.range.end.character > candidate.range.end.character)) candidate = t;
2044
+ if (candidate) return candidate;
2045
+ }
2046
+ for (let l = line - 1; l >= 0; l--) {
2047
+ const tokens$1 = this.tokensMap[l];
2048
+ if (tokens$1 && tokens$1.size > 0) {
2049
+ let candidate;
2050
+ for (const t of tokens$1) if (!candidate || t.range.end.character > candidate.range.end.character) candidate = t;
2051
+ if (candidate) return candidate;
2052
+ }
2053
+ }
2054
+ return undefined;
2055
+ }
2056
+ constructor() {
2057
+ /**
2058
+ * An array where each index corresponds to a line number, storing a set of tokens
2059
+ * associated with that line.
2060
+ */ _define_property$4(this, "tokensMap", []);
2061
+ }
2062
+ };
2063
+
2064
+ //#endregion
2065
+ //#region packages/core/src/document.ts
2066
+ function _define_property$3(obj, key, value) {
2067
+ if (key in obj) Object.defineProperty(obj, key, {
2068
+ value,
2069
+ enumerable: true,
2070
+ configurable: true,
2071
+ writable: true
2072
+ });
2073
+ else obj[key] = value;
2074
+ return obj;
2075
+ }
2076
+ var AtscriptDoc = class {
2077
+ get name() {
2078
+ return this.id.split("/").pop();
2079
+ }
2080
+ get primitives() {
2081
+ return Array.from(this.config.primitives?.values() ?? []);
2082
+ }
2083
+ async render(format) {
2084
+ return this.manager?.render(this, format);
2085
+ }
2086
+ resolveAnnotation(name) {
2087
+ return resolveAnnotation(name, this.config.annotations);
2088
+ }
2089
+ updateDependencies(docs) {
2090
+ const newDependencies = new Set(docs);
2091
+ this.dependencies.forEach((d) => {
2092
+ if (!newDependencies.has(d)) {
2093
+ d.dependants.delete(this);
2094
+ this.dependencies.delete(d);
2095
+ this.dependenciesMap.delete(d.id);
2096
+ }
2097
+ });
2098
+ newDependencies.forEach((d) => {
2099
+ d.dependants.add(this);
2100
+ this.dependencies.add(d);
2101
+ this.dependenciesMap.set(d.id, d);
2102
+ });
2103
+ }
2104
+ get text() {
2105
+ return this._text;
2106
+ }
2107
+ update(text$2, debug = false) {
2108
+ this._text = text$2;
2109
+ this.cleanup();
2110
+ const rawTokens = tokenize(text$2, debug);
2111
+ const ni = new NodeIterator(rawTokens, []).move();
2112
+ this.nodes = runPipes([
2113
+ pipes.importPipe,
2114
+ pipes.type,
2115
+ pipes.interfaceType
2116
+ ], ni);
2117
+ if (debug) console.log(this.nodes.map((n) => n.toString()).join("\n"));
2118
+ this.semanticMessages = ni.getErrors();
2119
+ this.registerNodes(this.nodes);
2120
+ }
2121
+ cleanup() {
2122
+ this.exports.clear();
2123
+ this.registry.clear();
2124
+ this.importedDefs.clear();
2125
+ this.messages = [];
2126
+ this.referred = [];
2127
+ this.imports.clear();
2128
+ this._allMessages = undefined;
2129
+ this.tokensIndex = new TokensIndex();
2130
+ this.blocksIndex = new BlocksIndex();
2131
+ this.resolvedAnnotations = [];
2132
+ this.annotations = [];
2133
+ }
2134
+ registerNodes(nodes) {
2135
+ for (const node of nodes) {
2136
+ node.registerAtDocument(this);
2137
+ node.referredIdentifiers.forEach((t) => {
2138
+ t.isReference = true;
2139
+ this.referred.push(t);
2140
+ this.tokensIndex.add(t);
2141
+ });
2142
+ }
2143
+ }
2144
+ registerAnnotation(annotationTokens) {
2145
+ this.annotations.push(annotationTokens);
2146
+ const mainToken = annotationTokens.token;
2147
+ const args = annotationTokens.args;
2148
+ this.tokensIndex.add(mainToken);
2149
+ args?.forEach((a) => this.tokensIndex.add(a));
2150
+ const annotationSpec = this.resolveAnnotation(mainToken.text.slice(1));
2151
+ if (annotationSpec) {
2152
+ this.registerMessages(annotationSpec.validate(mainToken, args || [], this));
2153
+ annotationSpec.modify(mainToken, args || [], this);
2154
+ this.resolvedAnnotations.push(mainToken);
2155
+ } else {
2156
+ let severity = 0;
2157
+ switch (this.config.unknownAnnotation) {
2158
+ case "warn":
2159
+ severity = 2;
2160
+ break;
2161
+ case "error":
2162
+ severity = 1;
2163
+ break;
2164
+ default:
2165
+ }
2166
+ if (severity > 0) this.registerMessage(mainToken, `Unknown annotation "${mainToken.text}"`, severity, "dim");
2167
+ }
2168
+ }
2169
+ /**
2170
+ * Recursively resolves a type reference (and any property chain) to find the final underlying definition.
2171
+ *
2172
+ * This method performs a **multi-step** resolution:
2173
+ * 1. Locates the declaration owner of the type (via `getDeclarationOwnerNode`).
2174
+ * 2. Follows references, type aliases, or nested property chains:
2175
+ * - For “Ref” nodes, it uses the identifier to look up the next type.
2176
+ * - For “Type” nodes, it calls `getDefinition()` to move to the underlying structure.
2177
+ * - For property chains (`chain`), it navigates nested properties or nested types,
2178
+ * resolving each level until the final type is reached.
2179
+ *
2180
+ * @param {string} name - The name of the type or identifier to resolve.
2181
+ * @param {Array<string | Token>} [chain=[]] - An optional chain of properties or tokens, each of which
2182
+ * refines the path to the final type (e.g., for `SomeType.prop1.prop2`, `chain` might be `[ "prop1", "prop2" ]`).
2183
+ * @returns {Object | undefined} An object containing:
2184
+ * - `doc`: The `AtscriptDoc` where the final definition is located.
2185
+ * - `node`: The last encountered `SemanticNode` before reaching the final underlying definition (often a `Prop` node).
2186
+ * - `def`: The final resolved `SemanticNode`.
2187
+ *
2188
+ * If the type cannot be resolved or does not exist, returns `undefined`.
2189
+ */ unwindType(name, chain = [], watchCb, _tracked) {
2190
+ const tracked = _tracked || new Set();
2191
+ const decl = this.getDeclarationOwnerNode(name);
2192
+ if (!decl) return undefined;
2193
+ const callCb = watchCb ? () => {
2194
+ if (def && !tracked.has(def) && [
2195
+ "type",
2196
+ "primitive",
2197
+ "prop",
2198
+ "interface"
2199
+ ].includes(def.entity)) {
2200
+ tracked.add(def);
2201
+ watchCb(def);
2202
+ }
2203
+ } : () => {};
2204
+ let node;
2205
+ let def = decl.node;
2206
+ let doc = decl.doc;
2207
+ const resolveRef = () => {
2208
+ if (isRef(def)) {
2209
+ const d = doc.unwindType(def.token("identifier").text, def.chain, watchCb, tracked);
2210
+ doc = d?.doc || doc;
2211
+ def = d?.def;
2212
+ }
2213
+ };
2214
+ const resolveType = () => {
2215
+ while (isType(def)) {
2216
+ callCb();
2217
+ def = def.getDefinition();
2218
+ node = def;
2219
+ resolveRef();
2220
+ }
2221
+ };
2222
+ resolveType();
2223
+ if (!def) return undefined;
2224
+ for (const item of chain) {
2225
+ const itemText = typeof item === "string" ? item : item.text;
2226
+ if (!def) return undefined;
2227
+ if (isProp(def)) if (def.nestedProps?.get(itemText)) def = def.nestedProps.get(itemText);
2228
+ else {
2229
+ def = def.nestedType;
2230
+ resolveRef();
2231
+ resolveType();
2232
+ if (isStructure(def) || isInterface(def)) def = def.props.get(itemText);
2233
+ }
2234
+ else if (isStructure(def) || isInterface(def) || isPrimitive(def)) def = def.props.get(itemText);
2235
+ }
2236
+ if (_tracked) callCb();
2237
+ while (isProp(def)) {
2238
+ node = def;
2239
+ def = def.getDefinition();
2240
+ resolveRef();
2241
+ resolveType();
2242
+ }
2243
+ return def ? {
2244
+ def,
2245
+ doc,
2246
+ node
2247
+ } : undefined;
2248
+ }
2249
+ getUsageListAt(line, character) {
2250
+ const token = this.tokensIndex.at(line, character);
2251
+ if (token) return this.usageListFor(token);
2252
+ }
2253
+ evalAnnotationsForNode(givenNode) {
2254
+ let right = givenNode.annotations;
2255
+ let def = givenNode.getDefinition();
2256
+ if (def) {
2257
+ if (isRef(def)) {
2258
+ const unwound = this.unwindType(def.token("identifier").text, def.chain, (intermediate) => {
2259
+ if (intermediate?.annotations) right = this.mergeNodesAnnotations(intermediate.annotations, right);
2260
+ });
2261
+ def = unwound?.def || def;
2262
+ }
2263
+ if (def) {
2264
+ const merged = this.mergeIntersection(def);
2265
+ right = this.mergeNodesAnnotations(merged.annotations, right);
2266
+ }
2267
+ }
2268
+ return right;
2269
+ }
2270
+ usageListFor(token) {
2271
+ if (token.isDefinition) {
2272
+ const refs = this.referred.filter((t) => t.text === token.text).map((r) => ({
2273
+ uri: this.id,
2274
+ range: r.range,
2275
+ token: r
2276
+ }));
2277
+ if (token.exported) for (const d of this.dependants) {
2278
+ const imp = d.imports.get(this.id);
2279
+ if (imp?.imports.find((t) => t.text === token.text)) refs.push(...d.referred.filter((t) => t.text === token.text).map((r) => ({
2280
+ uri: d.id,
2281
+ range: r.range,
2282
+ token: r
2283
+ })));
2284
+ }
2285
+ return refs;
2286
+ }
2287
+ if (isProp(token.parentNode)) {} else {
2288
+ const defForToken = this.getDefinitionFor(token);
2289
+ if (defForToken?.token?.isDefinition && defForToken.doc) return defForToken.doc.usageListFor(defForToken.token);
2290
+ }
2291
+ return undefined;
2292
+ }
2293
+ /**
2294
+ * Retrieves the definition (i.e., the “go to definition” target) for a given token.
2295
+ *
2296
+ * This method provides a **single-step** resolution of the defining token:
2297
+ * - If the token is defined in the same document, returns that definition.
2298
+ * - If the token is imported, follows the import to return the defining token from the relevant document.
2299
+ * - If the token is a reference to a locally defined identifier, retrieves the local definition.
2300
+ *
2301
+ * @param {Token} token - The token for which to locate the definition.
2302
+ * @returns {Object | undefined} An object containing:
2303
+ * - `uri`: The file path (URI) of the document where the definition is found.
2304
+ * - `doc`: The `AtscriptDoc` instance that owns the definition (if found).
2305
+ * - `token`: The defining token itself (if found).
2306
+ *
2307
+ * If no definition is found, returns `undefined`.
2308
+ */ getDefinitionFor(token) {
2309
+ if (token.isDefinition && !token.imported) return {
2310
+ uri: this.id,
2311
+ doc: this,
2312
+ token
2313
+ };
2314
+ if (token.fromPath) {
2315
+ const absolutePath = resolveAtscriptFromPath(token.fromPath, this.id);
2316
+ return {
2317
+ uri: absolutePath,
2318
+ doc: this.dependenciesMap.get(absolutePath),
2319
+ token
2320
+ };
2321
+ }
2322
+ if ((token.isReference || token.imported) && this.importedDefs.has(token.text) && this.dependenciesMap.size > 0) {
2323
+ const from = this.importedDefs.get(token.text).text;
2324
+ const absolutePath = resolveAtscriptFromPath(from, this.id);
2325
+ const targetDoc = this.dependenciesMap.get(absolutePath);
2326
+ if (targetDoc) {
2327
+ const target = targetDoc.registry.definitions.get(token.text);
2328
+ return target ? {
2329
+ uri: targetDoc.id,
2330
+ doc: targetDoc,
2331
+ token: target
2332
+ } : undefined;
2333
+ }
2334
+ }
2335
+ if (token.isReference) {
2336
+ const def = this.registry.definitions.get(token.text);
2337
+ return def ? {
2338
+ uri: this.id,
2339
+ doc: this,
2340
+ token: def
2341
+ } : undefined;
2342
+ }
2343
+ }
2344
+ getToDefinitionAt(line, character) {
2345
+ const token = this.tokensIndex.at(line, character);
2346
+ if (token) if (token.isChain && isRef(token.parentNode) && typeof token.index === "number") {
2347
+ const id = token.parentNode.id;
2348
+ const unwound = this.unwindType(id, token.parentNode.chain.slice(0, token.index));
2349
+ if (unwound?.node) return [{
2350
+ targetUri: unwound.doc.id,
2351
+ targetRange: unwound.node.token("identifier")?.range ?? zeroRange,
2352
+ targetSelectionRange: unwound.node.token("identifier")?.range ?? zeroRange,
2353
+ originSelectionRange: token.range
2354
+ }];
2355
+ } else {
2356
+ const result = this.getDefinitionFor(token);
2357
+ return result ? [{
2358
+ targetUri: result.uri,
2359
+ targetRange: result.token?.range ?? zeroRange,
2360
+ targetSelectionRange: result.token?.range ?? zeroRange,
2361
+ originSelectionRange: token.range
2362
+ }] : undefined;
2363
+ }
2364
+ }
2365
+ registerImport({ from, imports, block: block$2 }) {
2366
+ const importId = resolveAtscriptFromPath(from.text, this.id);
2367
+ this.imports.set(importId, {
2368
+ from,
2369
+ imports
2370
+ });
2371
+ this.blocksIndex.add(block$2);
2372
+ block$2.blockType = "import";
2373
+ block$2.fromPath = from.text;
2374
+ imports.forEach((t) => {
2375
+ t.imported = true;
2376
+ t.fromPath = from.text;
2377
+ this.registerDefinition(t, true);
2378
+ this.tokensIndex.add(t);
2379
+ this.tokensIndex.add(from);
2380
+ this.importedDefs.set(t.text, from);
2381
+ from.fromPath = from.text;
2382
+ });
2383
+ }
2384
+ registerDefinition(token, asImport = false) {
2385
+ if (token) {
2386
+ token.isDefinition = !asImport;
2387
+ if (asImport) token.isReference = true;
2388
+ this.tokensIndex.add(token);
2389
+ this.registry.registerDefinition(token);
2390
+ }
2391
+ }
2392
+ /**
2393
+ * Finds the owning document and semantic node responsible for declaring a given identifier.
2394
+ *
2395
+ * This method checks:
2396
+ * 1. Whether the identifier is a known primitive (from this document’s config).
2397
+ * 2. If there's a local definition in this document's registry.
2398
+ * - If the definition is imported, it resolves the `fromPath`, locates the correct `AtscriptDoc`
2399
+ * in the dependency map, and recursively tries to get the declaration owner there.
2400
+ * - If the definition is local (not imported), it returns the current document (`this`) along with
2401
+ * the parent node that owns the definition and the token itself.
2402
+ *
2403
+ * @param {string} identifier - The name/identifier whose declaring node should be found.
2404
+ * @returns {{ doc: AtscriptDoc; node?: SemanticNode; token?: Token } | undefined} An object containing:
2405
+ * - `doc`: The `AtscriptDoc` in which the identifier was ultimately declared.
2406
+ * - `node`: The parent `SemanticNode` that defines or owns the declaration (if applicable).
2407
+ * - `token`: The specific token for the declaration (if applicable).
2408
+ *
2409
+ * If no declaration is found, returns `undefined`.
2410
+ */ getDeclarationOwnerNode(identifier$1) {
2411
+ if (this.config.primitives?.has(identifier$1)) return {
2412
+ doc: this,
2413
+ node: this.config.primitives.get(identifier$1)
2414
+ };
2415
+ const def = this.registry.definitions.get(identifier$1);
2416
+ if (def?.imported && def.fromPath) {
2417
+ const absolutePath = resolveAtscriptFromPath(def.fromPath, this.id);
2418
+ const doc = this.dependenciesMap.get(absolutePath);
2419
+ return doc?.getDeclarationOwnerNode(identifier$1);
2420
+ } else if (!def?.imported) return def ? {
2421
+ doc: this,
2422
+ node: def.parentNode,
2423
+ token: def
2424
+ } : undefined;
2425
+ }
2426
+ registerExport(node) {
2427
+ if (node.id) this.exports.set(node.id, node);
2428
+ }
2429
+ registerMessage(token, message, severity = 1, tag) {
2430
+ if (this._allMessages) this._allMessages = undefined;
2431
+ this.messages.push({
2432
+ severity,
2433
+ message,
2434
+ range: token.range,
2435
+ tags: tag === "dim" ? [1] : tag === "crossed" ? [2] : []
2436
+ });
2437
+ }
2438
+ registerMessages(messages) {
2439
+ if (messages) this.messages.push(...messages);
2440
+ }
2441
+ clearMessages() {
2442
+ this._allMessages = undefined;
2443
+ }
2444
+ getUnusedTokens() {
2445
+ const refSet = new Set(this.referred.filter((r) => !r.imported).map((r) => r.text));
2446
+ const tokens$1 = [];
2447
+ for (const [key, token] of Array.from(this.registry.definitions.entries())) if (!refSet.has(key) && !this.exports.has(key)) tokens$1.push(token);
2448
+ return tokens$1;
2449
+ }
2450
+ getDiagMessages() {
2451
+ if (!this._allMessages) {
2452
+ this._allMessages = [
2453
+ ...this.registry.getErrors(),
2454
+ ...this.semanticMessages,
2455
+ ...this.messages
2456
+ ];
2457
+ for (const t of this.referred) {
2458
+ if (!this.registry.isDefined(t)) {
2459
+ this._allMessages.push({
2460
+ severity: 1,
2461
+ message: `Unknown identifier "${t.text}"`,
2462
+ range: t.range
2463
+ });
2464
+ continue;
2465
+ }
2466
+ if (isRef(t.parentNode)) {
2467
+ const def = this.unwindType(t.parentNode.id, t.parentNode.chain)?.def;
2468
+ if (isPrimitive(def) && !def.config.type) {
2469
+ const token = t.parentNode.chain[t.parentNode.chain.length - 1] || t;
2470
+ this._allMessages.push({
2471
+ severity: 1,
2472
+ message: "Invalid type",
2473
+ range: token.range
2474
+ });
2475
+ }
2476
+ if (t.parentNode.hasChain) {
2477
+ const length = t.parentNode.chain.length - 1;
2478
+ for (let i = length; i >= 0; i--) {
2479
+ const token = t.parentNode.chain[i];
2480
+ const decl = this.unwindType(t.parentNode.id, t.parentNode.chain.slice(0, i + 1));
2481
+ if (!decl?.def) this._allMessages.push({
2482
+ severity: 1,
2483
+ message: `Unknown member "${token.text}"`,
2484
+ range: token.range
2485
+ });
2486
+ }
2487
+ }
2488
+ }
2489
+ }
2490
+ }
2491
+ return this._allMessages;
2492
+ }
2493
+ mergeIntersection(node) {
2494
+ if (!isGroup(node)) return node;
2495
+ if (node.op !== "&") return node;
2496
+ const nodes = node.unwrap();
2497
+ if (nodes.length === 0) return node;
2498
+ if (nodes.length === 1) return nodes[0];
2499
+ const newGroup = [];
2500
+ let left = nodes[0];
2501
+ for (let i = 1; i < nodes.length; i++) {
2502
+ const right = nodes[i];
2503
+ const merged = this.mergeDefs(left, right);
2504
+ if (merged.length === 2) {
2505
+ left = merged[1];
2506
+ newGroup.push(merged[0]);
2507
+ } else left = merged[0];
2508
+ }
2509
+ newGroup.push(left);
2510
+ if (newGroup.length > 1) {
2511
+ const newNode = new SemanticGroup(newGroup, "&");
2512
+ return newNode;
2513
+ } else return newGroup[0];
2514
+ }
2515
+ mergeDefs(_left, _right) {
2516
+ let left = _left;
2517
+ let right = _right;
2518
+ if (isRef(left)) left = this.unwindType(left.id, left.chain)?.def;
2519
+ if (isRef(right)) right = this.unwindType(right.id, right.chain)?.def;
2520
+ if (!left || !right) return [_left, _right];
2521
+ if (isPrimitive(left) && isPrimitive(right)) {
2522
+ if (left.config.type === right.config.type) return [left];
2523
+ const never$1 = new SemanticRefNode();
2524
+ never$1.saveToken(new Token({
2525
+ text: "never",
2526
+ type: "identifier",
2527
+ getRange: () => zeroRange
2528
+ }), "identifier");
2529
+ return [never$1];
2530
+ }
2531
+ if ((isStructure(left) || isInterface(left)) && (isStructure(right) || isInterface(right))) {
2532
+ const mergedProps = [];
2533
+ const allProps = new Set([...left.props.keys(), ...right.props.keys()]);
2534
+ for (const key of allProps) {
2535
+ const leftProp = left.props.get(key);
2536
+ const rightProp = right.props.get(key);
2537
+ let mergedDef;
2538
+ if (leftProp && rightProp) {
2539
+ const grp = new SemanticGroup([leftProp.getDefinition(), rightProp.getDefinition()], "&");
2540
+ mergedDef = this.mergeIntersection(grp);
2541
+ } else {
2542
+ const oldProp = leftProp || rightProp;
2543
+ mergedDef = this.mergeIntersection(oldProp.getDefinition());
2544
+ }
2545
+ const prop = new SemanticPropNode();
2546
+ prop.saveToken((leftProp || rightProp).token("identifier"), "identifier");
2547
+ if (isPrimitive(mergedDef)) {
2548
+ const name = mergedDef.id;
2549
+ mergedDef = new SemanticRefNode();
2550
+ mergedDef.saveToken(new Token({
2551
+ text: name,
2552
+ type: "identifier",
2553
+ getRange: () => zeroRange
2554
+ }), "identifier");
2555
+ }
2556
+ prop.define(mergedDef);
2557
+ prop.annotations = this.mergeNodesAnnotations(leftProp?.annotations, rightProp?.annotations);
2558
+ const oldProps = [leftProp, rightProp].filter(Boolean);
2559
+ let optionalToken = oldProps[0]?.token("optional");
2560
+ for (const oldProp of oldProps) if (!oldProp.token("optional")) {
2561
+ optionalToken = undefined;
2562
+ break;
2563
+ }
2564
+ if (optionalToken) prop.saveToken(optionalToken, "optional");
2565
+ mergedProps.push(prop);
2566
+ }
2567
+ const mergedStructure = new SemanticStructureNode();
2568
+ mergedStructure.setProps(mergedProps);
2569
+ this.resolveAnnotation;
2570
+ mergedStructure.annotations = this.mergeNodesAnnotations(left.annotations, right.annotations);
2571
+ return [mergedStructure];
2572
+ }
2573
+ const never = new SemanticRefNode();
2574
+ never.saveToken(new Token({
2575
+ text: "never",
2576
+ type: "identifier",
2577
+ getRange: () => zeroRange
2578
+ }), "identifier");
2579
+ return [never];
2580
+ }
2581
+ /**
2582
+ * Merges two arrays of annotation tokens, ensuring that annotations from the
2583
+ * `right` array take precedence over those from the `left` array.
2584
+ *
2585
+ * - Annotations from `right` are always included.
2586
+ * - Annotations from `left` are included only if they are not already present in `right`.
2587
+ * - This ensures that if an annotation exists in both arrays, the one from `right` is kept.
2588
+ *
2589
+ * @param left - An optional array of annotation tokens to merge (lower priority).
2590
+ * @param right - An optional array of annotation tokens to merge (higher priority).
2591
+ * @returns A merged array of annotation tokens, preserving order while preventing duplicates.
2592
+ */ mergeNodesAnnotations(left, right) {
2593
+ const annotations$1 = [];
2594
+ const savedAnnotations = new Set();
2595
+ for (const a of right || []) {
2596
+ annotations$1.push(a);
2597
+ savedAnnotations.add(a.token.text);
2598
+ }
2599
+ for (const a of left || []) {
2600
+ const spec = this.resolveAnnotation(a.token.text);
2601
+ let append = spec && spec.config.multiple && spec.config.mergeStrategy === "append";
2602
+ if (append || !savedAnnotations.has(a.token.text)) annotations$1.push(a);
2603
+ }
2604
+ return annotations$1;
2605
+ }
2606
+ constructor(id, config, manager) {
2607
+ _define_property$3(this, "id", void 0);
2608
+ _define_property$3(this, "config", void 0);
2609
+ _define_property$3(this, "manager", void 0);
2610
+ _define_property$3(this, "registry", void 0);
2611
+ _define_property$3(this, "semanticMessages", void 0);
2612
+ _define_property$3(this, "messages", void 0);
2613
+ /**
2614
+ * All the non-blocks tokens, that could be referred
2615
+ */ _define_property$3(this, "tokensIndex", void 0);
2616
+ /**
2617
+ * All the block-tokens
2618
+ */ _define_property$3(this, "blocksIndex", void 0);
2619
+ /**
2620
+ * Imports map by URI, contains from Token and imports[] tokens
2621
+ */ _define_property$3(this, "imports", void 0);
2622
+ /**
2623
+ * Map of imported definitions by type/interface identifier
2624
+ */ _define_property$3(this, "importedDefs", void 0);
2625
+ /**
2626
+ * Exported nodes by identifier
2627
+ */ _define_property$3(this, "exports", void 0);
2628
+ /**
2629
+ * Set of documents that this document depend on
2630
+ */ _define_property$3(this, "dependencies", void 0);
2631
+ /**
2632
+ * Set of documents that depend on this document
2633
+ */ _define_property$3(this, "dependants", void 0);
2634
+ /**
2635
+ * List of tokens that refer to some type or interface
2636
+ */ _define_property$3(this, "referred", void 0);
2637
+ /**
2638
+ * Map of dependencies (documents) by URI
2639
+ */ _define_property$3(this, "dependenciesMap", void 0);
2640
+ _define_property$3(this, "nodes", void 0);
2641
+ _define_property$3(this, "_text", void 0);
2642
+ _define_property$3(this, "resolvedAnnotations", void 0);
2643
+ _define_property$3(this, "annotations", void 0);
2644
+ _define_property$3(this, "_allMessages", void 0);
2645
+ this.id = id;
2646
+ this.config = config;
2647
+ this.manager = manager;
2648
+ this.semanticMessages = [];
2649
+ this.messages = [];
2650
+ this.tokensIndex = new TokensIndex();
2651
+ this.blocksIndex = new BlocksIndex();
2652
+ this.imports = new Map();
2653
+ this.importedDefs = new Map();
2654
+ this.exports = new Map();
2655
+ this.dependencies = new Set();
2656
+ this.dependants = new Set();
2657
+ this.referred = [];
2658
+ this.dependenciesMap = new Map();
2659
+ this.nodes = [];
2660
+ this._text = "";
2661
+ this.resolvedAnnotations = [];
2662
+ this.annotations = [];
2663
+ this._allMessages = undefined;
2664
+ this.registry = new IdRegistry(Array.from(config.primitives?.keys() || []));
2665
+ }
2666
+ };
2667
+ const zeroRange = {
2668
+ start: {
2669
+ line: 0,
2670
+ character: 0
2671
+ },
2672
+ end: {
2673
+ line: 0,
2674
+ character: 0
2675
+ }
2676
+ };
2677
+
2678
+ //#endregion
2679
+ //#region packages/core/src/defaults/meta-annotations.ts
2680
+ const metaAnnotations = {
2681
+ label: new AnnotationSpec({
2682
+ description: "Defines a **human-readable label** for a property or entity. Useful for UI, logs, and documentation.\n\n**Example:**```atscript@meta.label \"User Name\"name: string```",
2683
+ argument: {
2684
+ name: "text",
2685
+ type: "string",
2686
+ description: "The label to be used for this field or entity."
2687
+ }
2688
+ }),
2689
+ id: new AnnotationSpec({
2690
+ description: "Marks a field as a unique identifier across multiple domains (DB, API, UI, logs).\n\n**Example:**```atscript@meta.id \"userId\"id: string```",
2691
+ argument: {
2692
+ optional: true,
2693
+ name: "name",
2694
+ type: "string",
2695
+ description: "Custom identifier name (defaults to property name if omitted)."
2696
+ }
2697
+ }),
2698
+ description: new AnnotationSpec({
2699
+ description: "Provides a **detailed description** of a field or entity, often used in documentation.\n\n**Example:**```atscript@meta.description \"Stores the user email address\"email: string```",
2700
+ argument: {
2701
+ name: "text",
2702
+ type: "string",
2703
+ description: "Detailed description for this field or entity."
2704
+ }
2705
+ }),
2706
+ documentation: new AnnotationSpec({
2707
+ description: "Provides **multi-line documentation** for a field or entity.\n\n**Example:**```atscript@meta.documentation \"# bio\"@meta.documentation \"## documentation of bio\"@meta.documentation \"your documentation\"bio: string```",
2708
+ multiple: true,
2709
+ argument: {
2710
+ name: "text",
2711
+ type: "string",
2712
+ description: "A line of documentation text. Multiple annotations can be used to form a full Markdown document."
2713
+ }
2714
+ }),
2715
+ placeholder: new AnnotationSpec({
2716
+ description: "Defines a **default placeholder value** for UI input fields.\n\n**Example:**```atscript@meta.placeholder \"Enter your name\"name: string```",
2717
+ nodeType: ["prop"],
2718
+ argument: {
2719
+ name: "text",
2720
+ type: "string",
2721
+ description: "The placeholder text to display in UI forms."
2722
+ }
2723
+ }),
2724
+ sensitive: new AnnotationSpec({
2725
+ description: "Marks a field as **sensitive** (e.g., passwords, API keys), ensuring it is hidden in logs and UI.\n\n**Example:**```atscript@meta.sensitivepassword: string```",
2726
+ nodeType: ["prop"],
2727
+ multiple: false
2728
+ }),
2729
+ readonly: new AnnotationSpec({
2730
+ description: "Marks a field as **read-only**, preventing modifications after creation.\n\n**Example:**```atscript@meta.readonlycreatedAt: date```",
2731
+ nodeType: ["prop"],
2732
+ multiple: false
2733
+ })
2734
+ };
2735
+
2736
+ //#endregion
2737
+ //#region packages/core/src/defaults/primitives.ts
2738
+ const positive = {
2739
+ documentation: "Number that greater than or equal to zero.",
2740
+ expect: { min: 0 }
2741
+ };
2742
+ const negative = {
2743
+ documentation: "Number that less than or equal to zero.",
2744
+ expect: { max: 0 }
2745
+ };
2746
+ const positiveOrNegative = {
2747
+ positive,
2748
+ negative
2749
+ };
2750
+ const primitives = {
2751
+ never: { documentation: "Represents impossible type." },
2752
+ string: {
2753
+ type: "string",
2754
+ documentation: "Represents textual data.",
2755
+ extensions: {
2756
+ email: {
2757
+ documentation: "Represents an email address.",
2758
+ expect: {
2759
+ pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
2760
+ message: "Invalid email format."
2761
+ }
2762
+ },
2763
+ phone: {
2764
+ documentation: "Represents an phone number.",
2765
+ expect: {
2766
+ pattern: /^\+?[0-9\s-]{10,15}$/,
2767
+ message: "Invalid phone number format."
2768
+ }
2769
+ },
2770
+ date: {
2771
+ documentation: "Represents a date string.",
2772
+ expect: {
2773
+ pattern: [
2774
+ /^\d{4}-\d{2}-\d{2}$/,
2775
+ /^\d{2}\/\d{2}\/\d{4}$/,
2776
+ /^\d{2}-\d{2}-\d{4}$/,
2777
+ /^\d{1,2} [A-Za-z]+ \d{4}$/
2778
+ ],
2779
+ message: "Invalid date format."
2780
+ }
2781
+ },
2782
+ isoDate: {
2783
+ documentation: "Represents a date string in ISO format.",
2784
+ expect: {
2785
+ pattern: [/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/, /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?([+-]\d{2}:\d{2})$/],
2786
+ message: "Invalid ISO date format."
2787
+ }
2788
+ },
2789
+ uuid: {
2790
+ documentation: "Represents a UUID.",
2791
+ expect: {
2792
+ pattern: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,
2793
+ message: "Invalid UUID format."
2794
+ }
2795
+ }
2796
+ }
2797
+ },
2798
+ number: {
2799
+ type: "number",
2800
+ documentation: "Represents numeric data.",
2801
+ extensions: {
2802
+ ...positiveOrNegative,
2803
+ single: {
2804
+ extensions: positiveOrNegative,
2805
+ documentation: "Represents a single-precision floating-point number."
2806
+ },
2807
+ double: {
2808
+ extensions: positiveOrNegative,
2809
+ documentation: "Represents a double-precision floating-point number."
2810
+ },
2811
+ int: {
2812
+ extensions: positiveOrNegative,
2813
+ documentation: "Represents an integer number.",
2814
+ expect: { int: true }
2815
+ },
2816
+ timestamp: {
2817
+ documentation: "Represents a timestamp.",
2818
+ expect: { int: true }
2819
+ }
2820
+ }
2821
+ },
2822
+ boolean: {
2823
+ type: "boolean",
2824
+ documentation: "Represents true/false values.",
2825
+ extensions: {
2826
+ true: { documentation: "Represents a true value." },
2827
+ false: { documentation: "Represents a false value." }
2828
+ }
2829
+ },
2830
+ null: {
2831
+ type: "null",
2832
+ documentation: "Represents NULL value."
2833
+ },
2834
+ void: {
2835
+ type: "void",
2836
+ documentation: "Represents no value."
2837
+ },
2838
+ undefined: {
2839
+ type: "void",
2840
+ documentation: "Represents no value."
2841
+ }
2842
+ };
2843
+
2844
+ //#endregion
2845
+ //#region packages/core/src/defaults/expect-annotations.ts
2846
+ const expectAnnotations = {
2847
+ minLength: new AnnotationSpec({
2848
+ description: "Validates that a string or array has a minimum length.\n\n**Example:**```atscript@expect.minLength 5name: string```",
2849
+ defType: ["array", "string"],
2850
+ argument: {
2851
+ name: "length",
2852
+ type: "number",
2853
+ description: "The minimum length of the string or array."
2854
+ }
2855
+ }),
2856
+ maxLength: new AnnotationSpec({
2857
+ description: "Validates that a string or array has a maximum length.\n\n**Example:**```atscript@expect.maxLength 5name: string```",
2858
+ defType: ["array", "string"],
2859
+ argument: {
2860
+ name: "length",
2861
+ type: "number",
2862
+ description: "The maximum length of the string or array."
2863
+ }
2864
+ }),
2865
+ min: new AnnotationSpec({
2866
+ description: "Validates that a number is greater than or equal to a minimum value.\n\n**Example:**```atscript@expect.min 18age: number```",
2867
+ defType: ["number"],
2868
+ argument: {
2869
+ name: "minValue",
2870
+ type: "number",
2871
+ description: "The minimum value."
2872
+ }
2873
+ }),
2874
+ max: new AnnotationSpec({
2875
+ description: "Validates that a number is less than or equal to a maximum value.\n\n**Example:**```atscript@expect.max 10count: number```",
2876
+ defType: ["number"],
2877
+ argument: {
2878
+ name: "maxValue",
2879
+ type: "number",
2880
+ description: "The maximum value."
2881
+ }
2882
+ }),
2883
+ int: new AnnotationSpec({
2884
+ description: "Validates that a number is an integer (no decimal places).\n\n**Example:**```atscript@expect.intage: number```",
2885
+ defType: ["number"]
2886
+ }),
2887
+ pattern: new AnnotationSpec({
2888
+ description: "Validates that a string matches a specific pattern.\n\n**Example:**```atscript@expect.pattern \"[a-z]+\", \"u\"name: string```",
2889
+ defType: ["string"],
2890
+ multiple: true,
2891
+ mergeStrategy: "append",
2892
+ argument: [
2893
+ {
2894
+ name: "pattern",
2895
+ type: "string",
2896
+ description: "The regular expression pattern to match."
2897
+ },
2898
+ {
2899
+ name: "flags",
2900
+ optional: true,
2901
+ type: "string",
2902
+ values: [
2903
+ "g",
2904
+ "gi",
2905
+ "gim",
2906
+ "gims",
2907
+ "gimsu",
2908
+ "gimsuy",
2909
+ "gimsy",
2910
+ "gimu",
2911
+ "gimuy",
2912
+ "gimy",
2913
+ "gis",
2914
+ "gisu",
2915
+ "gisuy",
2916
+ "gisy",
2917
+ "giu",
2918
+ "giuy",
2919
+ "giy",
2920
+ "gm",
2921
+ "gms",
2922
+ "gmsu",
2923
+ "gmsuy",
2924
+ "gmsy",
2925
+ "gmu",
2926
+ "gmuy",
2927
+ "gmy",
2928
+ "gs",
2929
+ "gsu",
2930
+ "gsuy",
2931
+ "gsy",
2932
+ "gu",
2933
+ "guy",
2934
+ "gy",
2935
+ "i",
2936
+ "im",
2937
+ "ims",
2938
+ "imsu",
2939
+ "imsuy",
2940
+ "imsy",
2941
+ "imu",
2942
+ "imuy",
2943
+ "imy",
2944
+ "is",
2945
+ "isu",
2946
+ "isuy",
2947
+ "isy",
2948
+ "iu",
2949
+ "iuy",
2950
+ "iy",
2951
+ "m",
2952
+ "ms",
2953
+ "msu",
2954
+ "msuy",
2955
+ "msy",
2956
+ "mu",
2957
+ "muy",
2958
+ "my",
2959
+ "s",
2960
+ "su",
2961
+ "suy",
2962
+ "sy",
2963
+ "u",
2964
+ "uy",
2965
+ "y"
2966
+ ],
2967
+ description: "Optional flags for the regular expression."
2968
+ },
2969
+ {
2970
+ name: "message",
2971
+ optional: true,
2972
+ type: "string",
2973
+ description: "Optional error message to display if the validation fails."
2974
+ }
2975
+ ],
2976
+ validate(mainToken, args) {
2977
+ if (args[0]) try {
2978
+ new RegExp(args[0].text);
2979
+ return [];
2980
+ } catch (e) {
2981
+ return [{
2982
+ message: "Invalid regular expression",
2983
+ range: args[0].range,
2984
+ severity: 1
2985
+ }];
2986
+ }
2987
+ return [];
2988
+ }
2989
+ })
2990
+ };
2991
+
2992
+ //#endregion
2993
+ //#region packages/core/src/default-atscript-config.ts
2994
+ function getDefaultAtscriptConfig() {
2995
+ const defaulTAtscriptConfig = {
2996
+ primitives,
2997
+ annotations: {
2998
+ meta: { ...metaAnnotations },
2999
+ expect: { ...expectAnnotations }
3000
+ }
3001
+ };
3002
+ return defaulTAtscriptConfig;
3003
+ }
3004
+
3005
+ //#endregion
3006
+ //#region packages/core/src/plugin/plugin-manager.ts
3007
+ function _define_property$2(obj, key, value) {
3008
+ if (key in obj) Object.defineProperty(obj, key, {
3009
+ value,
3010
+ enumerable: true,
3011
+ configurable: true,
3012
+ writable: true
3013
+ });
3014
+ else obj[key] = value;
3015
+ return obj;
3016
+ }
3017
+ var PluginManager = class {
3018
+ get plugins() {
3019
+ return this.cfg.plugins ?? [];
3020
+ }
3021
+ async getDocConfig() {
3022
+ if (!this._docConfig) {
3023
+ const raw = await this.config();
3024
+ this._docConfig = {};
3025
+ if (raw?.primitives) {
3026
+ this._docConfig.primitives = this._docConfig.primitives || new Map();
3027
+ for (const [key, value] of Object.entries(raw.primitives)) this._docConfig.primitives.set(key, new SemanticPrimitiveNode(key, value));
3028
+ }
3029
+ if (raw?.annotations) {
3030
+ this._docConfig.annotations = this._docConfig.annotations || {};
3031
+ Object.assign(this._docConfig.annotations, raw.annotations);
3032
+ }
3033
+ this._docConfig.unknownAnnotation = raw?.unknownAnnotation;
3034
+ }
3035
+ return this._docConfig;
3036
+ }
3037
+ async config(config = this.cfg) {
3038
+ if (!this._config) {
3039
+ const processed = new Set();
3040
+ config = (0, defu.defu)(config, getDefaultAtscriptConfig());
3041
+ const filtered = this.plugins.filter((plugin) => !processed.has(plugin.name));
3042
+ let i = 0;
3043
+ while (processed.size !== filtered.length) {
3044
+ i++;
3045
+ for (const plugin of filtered) {
3046
+ if (processed.has(plugin.name)) continue;
3047
+ config = (0, defu.defu)(await plugin.config?.(config), config);
3048
+ processed.add(plugin.name);
3049
+ }
3050
+ if (i > 100) throw new Error(`Too many iterations in config`);
3051
+ }
3052
+ this._config = config;
3053
+ }
3054
+ return this._config;
3055
+ }
3056
+ async resolve(id) {
3057
+ let newId = id;
3058
+ for (const plugin of this.plugins) if (plugin.resolve) newId = await plugin.resolve(id);
3059
+ return newId;
3060
+ }
3061
+ async load(id) {
3062
+ const filePath = id.startsWith("file://") ? id.slice(7) : id;
3063
+ for (const plugin of this.plugins) if (plugin.load) {
3064
+ const content$1 = await plugin.load(id);
3065
+ if (content$1) return content$1;
3066
+ }
3067
+ const content = await (0, node_fs_promises.readFile)(filePath, "utf8");
3068
+ return content.toString();
3069
+ }
3070
+ async onDocumnet(doc) {
3071
+ for (const plugin of this.plugins) if (plugin.onDocumnet) await plugin.onDocumnet(doc);
3072
+ }
3073
+ async render(doc, format) {
3074
+ const files = [];
3075
+ for (const plugin of this.plugins) if (plugin.render) {
3076
+ const newFiles = await plugin.render(doc, format);
3077
+ if (newFiles?.length > 0) files.push(...newFiles.map((f) => ({
3078
+ ...f,
3079
+ source: doc.id.startsWith("file://") ? doc.id.slice(7) : doc.id
3080
+ })));
3081
+ }
3082
+ return files;
3083
+ }
3084
+ async buildEnd(output, format, repo) {
3085
+ for (const plugin of this.plugins) if (plugin.buildEnd) await plugin.buildEnd(output, format, repo);
3086
+ }
3087
+ async loopInAnnotationsSpec(cb) {
3088
+ const config = await this.config();
3089
+ const annotations$1 = config.annotations || {};
3090
+ return this._loopInAnnotationsSpec(annotations$1, cb);
3091
+ }
3092
+ _loopInAnnotationsSpec(annotations$1, cb, prefix) {
3093
+ for (const [key, value] of Object.entries(annotations$1)) if (isAnnotationSpec(value)) cb(prefix ? `${prefix}.${key}` : key, value);
3094
+ else this._loopInAnnotationsSpec(value, cb, prefix ? `${prefix}.${key}` : key);
3095
+ }
3096
+ constructor(cfg) {
3097
+ _define_property$2(this, "cfg", void 0);
3098
+ _define_property$2(this, "_config", void 0);
3099
+ _define_property$2(this, "name", void 0);
3100
+ _define_property$2(this, "_docConfig", void 0);
3101
+ this.cfg = cfg;
3102
+ this.name = "plugin-manager";
3103
+ }
3104
+ };
3105
+
3106
+ //#endregion
3107
+ //#region packages/core/src/repo.ts
3108
+ function _define_property$1(obj, key, value) {
3109
+ if (key in obj) Object.defineProperty(obj, key, {
3110
+ value,
3111
+ enumerable: true,
3112
+ configurable: true,
3113
+ writable: true
3114
+ });
3115
+ else obj[key] = value;
3116
+ return obj;
3117
+ }
3118
+ var AtscriptRepo = class {
3119
+ getSharedPluginManager() {
3120
+ return this.sharedPluginManager?.manager;
3121
+ }
3122
+ async getPrimitivesTags() {
3123
+ const manager = await this.getSharedPluginManager();
3124
+ if (!manager) return undefined;
3125
+ const docConfig = await manager.getDocConfig();
3126
+ const primitives$1 = Array.from(docConfig.primitives?.entries() || []);
3127
+ const tags = [];
3128
+ const processed = new Set();
3129
+ for (const [, primitive] of primitives$1) tags.push(...primitive.getAllTags(processed));
3130
+ return new Set(tags);
3131
+ }
3132
+ async getUsedAnnotations() {
3133
+ const manager = await this.getSharedPluginManager();
3134
+ const annotations$1 = {};
3135
+ if (manager) await manager.loopInAnnotationsSpec((name, spec) => {
3136
+ const types = [];
3137
+ const multiple = !!spec.config.multiple;
3138
+ if (Array.isArray(spec.config.argument)) {
3139
+ const o = {
3140
+ type: "object",
3141
+ props: {}
3142
+ };
3143
+ for (const a of spec.arguments) o.props[a.name] = {
3144
+ type: a.type,
3145
+ optional: a.optional
3146
+ };
3147
+ types.push(o);
3148
+ } else if (spec.config.argument) types.push({
3149
+ type: spec.config.argument.type,
3150
+ optional: spec.config.argument.optional
3151
+ });
3152
+ else types.push({ type: "boolean" });
3153
+ annotations$1[name] = {
3154
+ multiple,
3155
+ fromSpec: true,
3156
+ typeSet: new Set(),
3157
+ types
3158
+ };
3159
+ });
3160
+ for (const doc of Array.from(this.atscripts.values())) {
3161
+ const awaited = await doc;
3162
+ for (const { name, token, args } of awaited.annotations) {
3163
+ if (annotations$1[name]?.fromSpec) continue;
3164
+ if (!annotations$1[name]) {
3165
+ let types = [];
3166
+ let multiple = false;
3167
+ annotations$1[name] = {
3168
+ multiple,
3169
+ fromSpec: false,
3170
+ typeSet: new Set(),
3171
+ types
3172
+ };
3173
+ }
3174
+ const isArray$1 = token.parentNode.countAnnotations(name) > 1;
3175
+ if (isArray$1) annotations$1[name].multiple = true;
3176
+ for (const arg of args) if (arg.type === "text") {
3177
+ if (!annotations$1[name].typeSet.has("string")) {
3178
+ annotations$1[name].typeSet.add("string");
3179
+ annotations$1[name].types.push({ type: "string" });
3180
+ }
3181
+ } else if (arg.type === "number") {
3182
+ if (!annotations$1[name].typeSet.has("number")) {
3183
+ annotations$1[name].typeSet.add("number");
3184
+ annotations$1[name].types.push({ type: "number" });
3185
+ }
3186
+ } else if (arg.type === "identifier" && ["true", "false"].includes(arg.text)) {
3187
+ if (!annotations$1[name].typeSet.has("boolean")) {
3188
+ annotations$1[name].typeSet.add("boolean");
3189
+ annotations$1[name].types.push({ type: "boolean" });
3190
+ }
3191
+ } else if (!annotations$1[name].typeSet.has("unknown")) {
3192
+ annotations$1[name].typeSet.add("unknown");
3193
+ annotations$1[name].types.push({ type: "unknown" });
3194
+ }
3195
+ if (args.length === 0 && !annotations$1[name].typeSet.has("boolean")) {
3196
+ annotations$1[name].typeSet.add("boolean");
3197
+ annotations$1[name].types.push({ type: "boolean" });
3198
+ }
3199
+ }
3200
+ }
3201
+ return annotations$1;
3202
+ }
3203
+ async loadPluginManagerFor(id) {
3204
+ if (this.sharedConfig) {
3205
+ if (!this.sharedPluginManager) this.sharedPluginManager = {
3206
+ manager: new PluginManager(this.sharedConfig),
3207
+ dependants: new Set()
3208
+ };
3209
+ return this.sharedPluginManager;
3210
+ }
3211
+ const configFile = await resolveConfigFile(id, this.root);
3212
+ if (configFile) {
3213
+ const globalPathToConfig = node_path.default.join(this.root, configFile);
3214
+ if (!this.configFiles.has(globalPathToConfig)) {
3215
+ const rawConfigPromise = loadConfig(configFile, this.configFormat);
3216
+ this.configFiles.set(globalPathToConfig, rawConfigPromise);
3217
+ }
3218
+ const rawConfig = await this.configFiles.get(globalPathToConfig);
3219
+ if (!rawConfig.rootDir) rawConfig.rootDir = node_path.default.dirname(configFile);
3220
+ const manager = new PluginManager(rawConfig);
3221
+ await manager.getDocConfig();
3222
+ return {
3223
+ file: globalPathToConfig,
3224
+ manager,
3225
+ dependants: new Set()
3226
+ };
3227
+ } else {
3228
+ const manager = new PluginManager({ rootDir: process.cwd() });
3229
+ await manager.getDocConfig();
3230
+ return {
3231
+ manager,
3232
+ dependants: new Set()
3233
+ };
3234
+ }
3235
+ }
3236
+ async resolveConfig(id) {
3237
+ let config = this.configs.get(id);
3238
+ if (!config) {
3239
+ config = this.loadPluginManagerFor(id);
3240
+ config.then((c) => {
3241
+ c.dependants.add(id);
3242
+ });
3243
+ this.configs.set(id, config);
3244
+ }
3245
+ return config;
3246
+ }
3247
+ async openDocument(id, text$2) {
3248
+ let atscript = this.atscripts.get(id);
3249
+ if (atscript) {
3250
+ if (text$2) atscript.then((d) => {
3251
+ d.update(text$2);
3252
+ return d;
3253
+ });
3254
+ } else {
3255
+ atscript = this._openDocument(id, text$2);
3256
+ atscript.catch(() => {
3257
+ this.atscripts.delete(id);
3258
+ });
3259
+ this.atscripts.set(id, atscript);
3260
+ }
3261
+ return atscript;
3262
+ }
3263
+ async _openDocument(id, text$2) {
3264
+ const { manager } = await this.resolveConfig(id);
3265
+ const newId = await manager.resolve(id);
3266
+ if (!newId) throw new Error(`Document not resolved: ${id}`);
3267
+ const content = text$2 || await manager.load(newId);
3268
+ if (typeof content !== "string") throw new Error(`Document not found: ${newId}`);
3269
+ const atscript = new AtscriptDoc(id, await manager.getDocConfig(), manager);
3270
+ atscript.update(content);
3271
+ await manager.onDocumnet(atscript);
3272
+ return atscript;
3273
+ }
3274
+ async checkDoc(atscript) {
3275
+ await this.checkImports(atscript);
3276
+ }
3277
+ async checkImports(atscript) {
3278
+ const promise = Promise.all(Array.from(atscript.imports.values(), async ({ from, imports }) => this.checkImport(atscript, from, imports)));
3279
+ const results = await promise;
3280
+ atscript.updateDependencies(results.filter(Boolean));
3281
+ }
3282
+ async checkImport(atscript, from, imports) {
3283
+ const forId = resolveAtscriptFromPath(from.text, atscript.id);
3284
+ if (forId === atscript.id) {
3285
+ const messages = atscript.getDiagMessages();
3286
+ messages.push({
3287
+ severity: 1,
3288
+ message: "\"import\" cannot import itself",
3289
+ range: from.range
3290
+ });
3291
+ return;
3292
+ }
3293
+ const errors = [];
3294
+ let external;
3295
+ try {
3296
+ external = await this.openDocument(forId);
3297
+ for (const token of imports) if (!external.exports.has(token.text)) errors.push({
3298
+ severity: 1,
3299
+ message: `"${from.text}" has no exported member "${token.text}"`,
3300
+ range: token.range
3301
+ });
3302
+ } catch (error) {
3303
+ errors.push({
3304
+ severity: 1,
3305
+ message: `"${from.text}" not found`,
3306
+ range: from.range
3307
+ });
3308
+ }
3309
+ if (errors.length > 0) {
3310
+ const messages = atscript.getDiagMessages();
3311
+ messages.push(...errors);
3312
+ }
3313
+ return external;
3314
+ }
3315
+ constructor(root$1 = process.cwd(), sharedConfig) {
3316
+ _define_property$1(this, "root", void 0);
3317
+ _define_property$1(this, "sharedConfig", void 0);
3318
+ _define_property$1(this, "configFormat", void 0);
3319
+ /**
3320
+ * Configs cache
3321
+ */ _define_property$1(this, "configs", void 0);
3322
+ /**
3323
+ * .as Documents cache
3324
+ */ _define_property$1(this, "atscripts", void 0);
3325
+ _define_property$1(this, "sharedPluginManager", void 0);
3326
+ /**
3327
+ * cache for raw content of config files
3328
+ */ _define_property$1(this, "configFiles", void 0);
3329
+ this.root = root$1;
3330
+ this.sharedConfig = sharedConfig;
3331
+ this.configs = new Map();
3332
+ this.atscripts = new Map();
3333
+ this.configFiles = new Map();
3334
+ }
3335
+ };
3336
+
3337
+ //#endregion
3338
+ //#region packages/core/src/plugin/types.ts
3339
+ const createAtscriptPlugin = (plugin) => plugin;
3340
+
3341
+ //#endregion
3342
+ //#region packages/core/src/build.ts
3343
+ function _define_property(obj, key, value) {
3344
+ if (key in obj) Object.defineProperty(obj, key, {
3345
+ value,
3346
+ enumerable: true,
3347
+ configurable: true,
3348
+ writable: true
3349
+ });
3350
+ else obj[key] = value;
3351
+ return obj;
3352
+ }
3353
+ async function build(config) {
3354
+ const rootDir = config.rootDir ? config.rootDir.startsWith("/") ? config.rootDir : path.default.join(process.cwd(), config.rootDir) : process.cwd();
3355
+ config.rootDir = rootDir;
3356
+ const repo = new AtscriptRepo(rootDir, config);
3357
+ const entries = [];
3358
+ if (config.entries && config.entries.length > 0) for (const entry of config.entries) entries.push(path.default.join(rootDir, entry));
3359
+ else {
3360
+ const includes = config.include && config.include.length > 0 ? config.include : ["**/*.as"];
3361
+ const excludes = config.exclude && config.exclude.length > 0 ? config.exclude : ["node_modules"];
3362
+ const found = await (0, glob.glob)(includes, {
3363
+ cwd: rootDir,
3364
+ absolute: true,
3365
+ ignore: excludes
3366
+ });
3367
+ entries.push(...found);
3368
+ }
3369
+ const documents = [];
3370
+ for (const entry of entries) documents.push(await repo.openDocument("file://" + entry));
3371
+ return new BuildRepo(rootDir, repo, documents.filter(Boolean));
3372
+ }
3373
+ var BuildRepo = class {
3374
+ async diagnostics() {
3375
+ const docMessages = new Map();
3376
+ for (const document of this.docs) {
3377
+ await this.repo.checkDoc(document);
3378
+ docMessages.set(document.id, document.getDiagMessages());
3379
+ }
3380
+ return docMessages;
3381
+ }
3382
+ async generate(config, docs = this.docs) {
3383
+ const outFiles = [];
3384
+ for (const document of docs) {
3385
+ const out = await document.render(config.format);
3386
+ if (out?.length) outFiles.push(...out);
3387
+ }
3388
+ for (const outFile of outFiles) {
3389
+ const docPath = outFile.source.replace(/^file:\/\//, "");
3390
+ if (config.outDir) {
3391
+ const rel = path.default.relative(this.rootDir, docPath);
3392
+ const relDir = path.default.dirname(rel);
3393
+ outFile.target = path.default.join(this.rootDir, config.outDir, relDir, outFile.fileName);
3394
+ } else outFile.target = path.default.join(path.default.dirname(docPath), outFile.fileName);
3395
+ }
3396
+ if (this.repo.sharedConfig && this.docs === docs && this.docs[0]) {
3397
+ const { manager } = await this.repo.loadPluginManagerFor(this.docs[0].id);
3398
+ await manager.buildEnd(outFiles, config.format, this.repo);
3399
+ }
3400
+ return outFiles;
3401
+ }
3402
+ async write(config, docs = this.docs) {
3403
+ const outFiles = await this.generate(config, docs);
3404
+ for (const o of outFiles) if (o.target) {
3405
+ await (0, fs_promises.mkdir)(path.default.dirname(o.target), { recursive: true });
3406
+ (0, fs_promises.writeFile)(o.target, o.content);
3407
+ }
3408
+ return outFiles;
3409
+ }
3410
+ constructor(rootDir, repo, docs) {
3411
+ _define_property(this, "rootDir", void 0);
3412
+ _define_property(this, "repo", void 0);
3413
+ _define_property(this, "docs", void 0);
3414
+ this.rootDir = rootDir;
3415
+ this.repo = repo;
3416
+ this.docs = docs;
3417
+ }
3418
+ };
3419
+
3420
+ //#endregion
3421
+ exports.$n = $n
3422
+ exports.AnnotationSpec = AnnotationSpec
3423
+ exports.AtscriptDoc = AtscriptDoc
3424
+ exports.AtscriptRepo = AtscriptRepo
3425
+ exports.BuildRepo = BuildRepo
3426
+ exports.PluginManager = PluginManager
3427
+ exports.SemanticArrayNode = SemanticArrayNode
3428
+ exports.SemanticConstNode = SemanticConstNode
3429
+ exports.SemanticGroup = SemanticGroup
3430
+ exports.SemanticImportNode = SemanticImportNode
3431
+ exports.SemanticInterfaceNode = SemanticInterfaceNode
3432
+ exports.SemanticNode = SemanticNode
3433
+ exports.SemanticPrimitiveNode = SemanticPrimitiveNode
3434
+ exports.SemanticPropNode = SemanticPropNode
3435
+ exports.SemanticRefNode = SemanticRefNode
3436
+ exports.SemanticStructureNode = SemanticStructureNode
3437
+ exports.SemanticTupleNode = SemanticTupleNode
3438
+ exports.SemanticTypeNode = SemanticTypeNode
3439
+ exports.Token = Token
3440
+ exports.build = build
3441
+ exports.createAtscriptPlugin = createAtscriptPlugin
3442
+ exports.defineConfig = defineConfig
3443
+ exports.getRelPath = getRelPath
3444
+ exports.isAnnotationSpec = isAnnotationSpec
3445
+ exports.isArray = isArray
3446
+ exports.isConst = isConst
3447
+ exports.isGroup = isGroup
3448
+ exports.isImport = isImport
3449
+ exports.isInterface = isInterface
3450
+ exports.isPrimitive = isPrimitive
3451
+ exports.isProp = isProp
3452
+ exports.isRef = isRef
3453
+ exports.isStructure = isStructure
3454
+ exports.isTuple = isTuple
3455
+ exports.isType = isType
3456
+ exports.loadConfig = loadConfig
3457
+ exports.loadTsConfig = loadTsConfig
3458
+ exports.resolveAnnotation = resolveAnnotation
3459
+ exports.resolveAtscriptFromPath = resolveAtscriptFromPath
3460
+ exports.resolveConfigFile = resolveConfigFile