@atscript/core 0.0.17 → 0.0.19
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 +163 -15
- package/dist/index.d.ts +169 -4
- package/dist/index.mjs +163 -15
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -334,11 +334,11 @@ var Token = class Token {
|
|
|
334
334
|
* All the import tokens must be marked with this flag
|
|
335
335
|
*/ _define_property$12(this, "imported", void 0);
|
|
336
336
|
/**
|
|
337
|
-
* All the props must be marked with this flag
|
|
338
|
-
*/ _define_property$12(this, "isProp", void 0);
|
|
339
|
-
/**
|
|
340
337
|
* Refs chained via . or ["propName"] are marked with this flag
|
|
341
338
|
*/ _define_property$12(this, "isChain", void 0);
|
|
339
|
+
/**
|
|
340
|
+
* Prop patterns ([*] or [regexp]) are storing patterns here
|
|
341
|
+
*/ _define_property$12(this, "pattern", void 0);
|
|
342
342
|
_define_property$12(this, "parentNode", void 0);
|
|
343
343
|
/**
|
|
344
344
|
* Only for annotation arguments: reference to their annotation token
|
|
@@ -509,6 +509,9 @@ var SemanticPropNode = class extends SemanticNode {
|
|
|
509
509
|
const token = this.token("identifier");
|
|
510
510
|
if (token && token.type === "text" && token.multiline) doc.registerMessage(token, "Unexpected end of string");
|
|
511
511
|
}
|
|
512
|
+
get isPattern() {
|
|
513
|
+
return !!this.token("identifier")?.pattern;
|
|
514
|
+
}
|
|
512
515
|
get nestedProps() {
|
|
513
516
|
if (this.definition && isStructure(this.definition)) return this.definition.props;
|
|
514
517
|
}
|
|
@@ -966,7 +969,10 @@ async function findConfigFileName(d) {
|
|
|
966
969
|
async function loadTsConfig(configFile, forceFormat) {
|
|
967
970
|
const file = await bundleTsConfig(configFile, forceFormat);
|
|
968
971
|
try {
|
|
969
|
-
return (await import(
|
|
972
|
+
return (await import(
|
|
973
|
+
/* @vite-ignore */
|
|
974
|
+
(0, node_url.pathToFileURL)(file).href
|
|
975
|
+
)).default;
|
|
970
976
|
} catch (error) {
|
|
971
977
|
console.error("Could not load config file", file, error);
|
|
972
978
|
return {};
|
|
@@ -977,7 +983,10 @@ async function loadTsConfig(configFile, forceFormat) {
|
|
|
977
983
|
async function loadConfig(configPath, forceFormat) {
|
|
978
984
|
const ext = node_path.default.extname(configPath);
|
|
979
985
|
try {
|
|
980
|
-
if (SUPPORTED_JS_CONFIG_FORMATS.includes(ext)) return forceFormat ? await loadTsConfig(node_path.default.resolve(configPath), forceFormat) : (await import(
|
|
986
|
+
if (SUPPORTED_JS_CONFIG_FORMATS.includes(ext)) return forceFormat ? await loadTsConfig(node_path.default.resolve(configPath), forceFormat) : (await import(
|
|
987
|
+
/* @vite-ignore */
|
|
988
|
+
(0, node_url.pathToFileURL)(configPath).href
|
|
989
|
+
)).default;
|
|
981
990
|
else if (SUPPORTED_TS_CONFIG_FORMATS.includes(ext)) {
|
|
982
991
|
const rawConfigPath = node_path.default.resolve(configPath);
|
|
983
992
|
return await loadTsConfig(rawConfigPath, forceFormat);
|
|
@@ -1088,9 +1097,6 @@ var NodeIterator = class NodeIterator {
|
|
|
1088
1097
|
this.$ = this.nodes[this.i];
|
|
1089
1098
|
return this;
|
|
1090
1099
|
}
|
|
1091
|
-
/** @deprecated */ killNextNode(n = 1) {
|
|
1092
|
-
this.nodes.splice(this.i + 1, n);
|
|
1093
|
-
}
|
|
1094
1100
|
next(skip) {
|
|
1095
1101
|
return this.fork().move().skip(skip);
|
|
1096
1102
|
}
|
|
@@ -1270,8 +1276,8 @@ const IdentifierToken = new __prostojs_parser.BasicNode({
|
|
|
1270
1276
|
//#region packages/core/src/tokenizer/tokens/number.token.ts
|
|
1271
1277
|
const NumberToken = new __prostojs_parser.BasicNode({
|
|
1272
1278
|
icon: "N",
|
|
1273
|
-
tokens: [
|
|
1274
|
-
tokenOE: "
|
|
1279
|
+
tokens: [/[-+]?(?:\d*\.\d+|\d+)(?:[eE][-+]?\d+)?/u, /[^\d]/u],
|
|
1280
|
+
tokenOE: "-eject"
|
|
1275
1281
|
}).mapContent("text", "join-clear").onMatch((context) => {
|
|
1276
1282
|
context.customData.type = "number";
|
|
1277
1283
|
});
|
|
@@ -1279,7 +1285,7 @@ const NumberToken = new __prostojs_parser.BasicNode({
|
|
|
1279
1285
|
//#endregion
|
|
1280
1286
|
//#region packages/core/src/tokenizer/tokens/punctuation.token.ts
|
|
1281
1287
|
const PunctuationToken = new __prostojs_parser.BasicNode({
|
|
1282
|
-
tokens: [RegExp("(?<text>[\\n
|
|
1288
|
+
tokens: [RegExp("(?<text>[\\n!&+,./:;=?|])", "u"), ""],
|
|
1283
1289
|
tokenOE: "omit-omit",
|
|
1284
1290
|
icon: "..."
|
|
1285
1291
|
}).onMatch((context) => {
|
|
@@ -1299,6 +1305,19 @@ const TextToken = new __prostojs_parser.BasicNode({
|
|
|
1299
1305
|
context.customData.multiline = context.customData.end === "\n";
|
|
1300
1306
|
});
|
|
1301
1307
|
|
|
1308
|
+
//#endregion
|
|
1309
|
+
//#region packages/core/src/tokenizer/tokens/regexp.token.ts
|
|
1310
|
+
const REGEXP_LITERAL_RE = /\/(?![/*])(?:\\.|\[.*?]|[^/\\\n\r[])*\/[dgimsuy]*/;
|
|
1311
|
+
const RegExpToken = new __prostojs_parser.BasicNode({
|
|
1312
|
+
label: "regexp",
|
|
1313
|
+
icon: "RG",
|
|
1314
|
+
tokens: [REGEXP_LITERAL_RE, ""],
|
|
1315
|
+
tokenOE: "omit-omit"
|
|
1316
|
+
}).onMatch((ctx) => {
|
|
1317
|
+
ctx.customData.type = "regexp";
|
|
1318
|
+
ctx.customData.text = ctx.matched[0];
|
|
1319
|
+
});
|
|
1320
|
+
|
|
1302
1321
|
//#endregion
|
|
1303
1322
|
//#region packages/core/src/tokenizer/tokens/index.ts
|
|
1304
1323
|
const tokens = {
|
|
@@ -1311,6 +1330,7 @@ const tokens = {
|
|
|
1311
1330
|
identifier: IdentifierToken,
|
|
1312
1331
|
number: NumberToken,
|
|
1313
1332
|
text: TextToken,
|
|
1333
|
+
regexp: RegExpToken,
|
|
1314
1334
|
root: undefined
|
|
1315
1335
|
};
|
|
1316
1336
|
const root = new __prostojs_parser.BasicNode({
|
|
@@ -1318,7 +1338,7 @@ const root = new __prostojs_parser.BasicNode({
|
|
|
1318
1338
|
skipToken: /\s/u
|
|
1319
1339
|
}).addRecognizes(...tokens.comments, tokens.block, tokens.aIdentifier, tokens.identifier, tokens.text, tokens.number, tokens.punctuation);
|
|
1320
1340
|
tokens.root = root;
|
|
1321
|
-
BlockToken.addRecognizes(...tokens.comments, tokens.block, tokens.aIdentifier, tokens.identifier, tokens.text, tokens.number, tokens.punctuation);
|
|
1341
|
+
BlockToken.addRecognizes(tokens.regexp, ...tokens.comments, tokens.block, tokens.aIdentifier, tokens.identifier, tokens.text, tokens.number, tokens.punctuation);
|
|
1322
1342
|
const mapContent = (content) => content.map((item) => {
|
|
1323
1343
|
if (typeof item === "string") return {
|
|
1324
1344
|
type: "unknown",
|
|
@@ -1353,6 +1373,7 @@ function $token(name, text$2) {
|
|
|
1353
1373
|
node: name,
|
|
1354
1374
|
text: text$2
|
|
1355
1375
|
}],
|
|
1376
|
+
contains: undefined,
|
|
1356
1377
|
isGlobal: false,
|
|
1357
1378
|
empty: false,
|
|
1358
1379
|
wrapper: undefined,
|
|
@@ -1387,6 +1408,16 @@ function $token(name, text$2) {
|
|
|
1387
1408
|
ni.unexpected(false, `Expected empty block`);
|
|
1388
1409
|
return opts.optional;
|
|
1389
1410
|
}
|
|
1411
|
+
if (opts.contains) {
|
|
1412
|
+
if (!ni.$.children?.length) {
|
|
1413
|
+
ni.unexpected(false, `Expected ${opts.contains.map((v) => v.text).join(", ")}`);
|
|
1414
|
+
return opts.optional;
|
|
1415
|
+
}
|
|
1416
|
+
if (ni.$.children[0].type !== opts.contains[0].node || ni.$.children[0].text !== opts.contains[0].text) {
|
|
1417
|
+
ni.unexpected(false, `Expected ${opts.contains.map((v) => v.text).join(", ")}`);
|
|
1418
|
+
return opts.optional;
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1390
1421
|
if (opts.saveAs) target.node.saveToken(new Token(ni.$), opts.saveAs);
|
|
1391
1422
|
ni.accepted();
|
|
1392
1423
|
if (opts.wrapper) {
|
|
@@ -1421,6 +1452,10 @@ else return true;
|
|
|
1421
1452
|
opts.empty = true;
|
|
1422
1453
|
return this;
|
|
1423
1454
|
},
|
|
1455
|
+
contains(t) {
|
|
1456
|
+
opts.contains = t.expect;
|
|
1457
|
+
return this;
|
|
1458
|
+
},
|
|
1424
1459
|
skip(...p) {
|
|
1425
1460
|
opts.skip = p;
|
|
1426
1461
|
return this;
|
|
@@ -1825,6 +1860,52 @@ function unwrap(attr) {
|
|
|
1825
1860
|
}
|
|
1826
1861
|
};
|
|
1827
1862
|
}
|
|
1863
|
+
function propName() {
|
|
1864
|
+
return { handler(ni, target) {
|
|
1865
|
+
switch (ni.$?.type) {
|
|
1866
|
+
case "identifier":
|
|
1867
|
+
case "text":
|
|
1868
|
+
target.node.saveToken(new Token(ni.$), "identifier");
|
|
1869
|
+
ni.accepted();
|
|
1870
|
+
ni.move();
|
|
1871
|
+
ni.skip(["\n"]);
|
|
1872
|
+
return true;
|
|
1873
|
+
case "block":
|
|
1874
|
+
const childrenLength = ni.$.children?.length || 0;
|
|
1875
|
+
const firstText = ni.$.children?.[0]?.text;
|
|
1876
|
+
if (ni.$.text === "[" && ni.$.children?.[0]?.type === "unknown" && childrenLength === 1 && ni.$.children[0].text === "*" || ni.$.text === "[" && ni.$.children?.[0]?.type === "regexp" && childrenLength === 1) {
|
|
1877
|
+
const t = new Token({
|
|
1878
|
+
...ni.$,
|
|
1879
|
+
...ni.$.children[0]
|
|
1880
|
+
});
|
|
1881
|
+
try {
|
|
1882
|
+
t.pattern = firstText === "*" ? /./ : parseRegExpLiteral(firstText);
|
|
1883
|
+
} catch (e) {
|
|
1884
|
+
ni.unexpected(false, e.message);
|
|
1885
|
+
return false;
|
|
1886
|
+
}
|
|
1887
|
+
target.node.saveToken(t, "identifier");
|
|
1888
|
+
ni.accepted();
|
|
1889
|
+
ni.move();
|
|
1890
|
+
ni.skip(["\n"]);
|
|
1891
|
+
return true;
|
|
1892
|
+
}
|
|
1893
|
+
if (ni.$.text === "[" && !childrenLength) ni.unexpected(false, "Wildcard \"*\" or a Regular Expression expected");
|
|
1894
|
+
if (ni.$.text === "[" && childrenLength > 1) ni.unexpected(false, firstText?.startsWith("/") ? "Invalid Regular Expression" : "To many arguments in prop pattern []");
|
|
1895
|
+
else ni.unexpected(false, "Unexpected identifier at property name");
|
|
1896
|
+
return false;
|
|
1897
|
+
default:
|
|
1898
|
+
ni.unexpected(false, "Unexpected identifier at property name");
|
|
1899
|
+
return false;
|
|
1900
|
+
}
|
|
1901
|
+
} };
|
|
1902
|
+
}
|
|
1903
|
+
function parseRegExpLiteral(literal) {
|
|
1904
|
+
const match = literal.match(/^\/(.+)\/([dgimsuy]*)$/);
|
|
1905
|
+
if (!match) throw new Error(`Invalid regexp literal: ${literal}`);
|
|
1906
|
+
const [, pattern, flags] = match;
|
|
1907
|
+
return new RegExp(pattern.replace(/\\\//g, "/"), flags);
|
|
1908
|
+
}
|
|
1828
1909
|
|
|
1829
1910
|
//#endregion
|
|
1830
1911
|
//#region packages/core/src/parser/pipes/pipes.ts
|
|
@@ -1832,9 +1913,9 @@ const ref = $pipe("ref", [refWithChain()]);
|
|
|
1832
1913
|
const constText = defineValuePipe("const", "text", false);
|
|
1833
1914
|
const constNumber = defineValuePipe("const", "number", false);
|
|
1834
1915
|
const allowedValuesPipeArray = [
|
|
1916
|
+
constNumber,
|
|
1835
1917
|
ref,
|
|
1836
|
-
constText
|
|
1837
|
-
constNumber
|
|
1918
|
+
constText
|
|
1838
1919
|
];
|
|
1839
1920
|
const tuplePipeArray = [
|
|
1840
1921
|
block("[]").saveAs("identifier"),
|
|
@@ -1860,7 +1941,7 @@ const type = $pipe("type", [
|
|
|
1860
1941
|
]).skip("\n", ";");
|
|
1861
1942
|
const props = $pipe("prop", [
|
|
1862
1943
|
annotations(),
|
|
1863
|
-
|
|
1944
|
+
propName(),
|
|
1864
1945
|
pun("?").saveAs("optional").optional().skip("\n"),
|
|
1865
1946
|
pun(":").skip("\n"),
|
|
1866
1947
|
definition(allowedValuesPipeArray).separatedBy("&", "|").skip("\n").respectPriority(),
|
|
@@ -1902,6 +1983,16 @@ const pipes = {
|
|
|
1902
1983
|
tuple
|
|
1903
1984
|
};
|
|
1904
1985
|
|
|
1986
|
+
//#endregion
|
|
1987
|
+
//#region packages/core/src/parser/types.ts
|
|
1988
|
+
var TSeverity = /*#__PURE__*/ function(TSeverity$1) {
|
|
1989
|
+
TSeverity$1[TSeverity$1["Error"] = 1] = "Error";
|
|
1990
|
+
TSeverity$1[TSeverity$1["Warning"] = 2] = "Warning";
|
|
1991
|
+
TSeverity$1[TSeverity$1["Info"] = 3] = "Info";
|
|
1992
|
+
TSeverity$1[TSeverity$1["Hint"] = 4] = "Hint";
|
|
1993
|
+
return TSeverity$1;
|
|
1994
|
+
}({});
|
|
1995
|
+
|
|
1905
1996
|
//#endregion
|
|
1906
1997
|
//#region packages/core/src/token-index/blocks-index.ts
|
|
1907
1998
|
function _define_property$5(obj, key, value) {
|
|
@@ -2448,6 +2539,63 @@ else if (isStructure(def) || isInterface(def) || isPrimitive(def)) def = def.pro
|
|
|
2448
2539
|
for (const [key, token] of Array.from(this.registry.definitions.entries())) if (!refSet.has(key) && !this.exports.has(key)) tokens$1.push(token);
|
|
2449
2540
|
return tokens$1;
|
|
2450
2541
|
}
|
|
2542
|
+
renderDiagMessage(m, addSourceLinses = false, colors = false) {
|
|
2543
|
+
const c = {
|
|
2544
|
+
red: colors ? "\x1B[31m" : "",
|
|
2545
|
+
blue: colors ? "\x1B[34m" : "",
|
|
2546
|
+
cyan: colors ? "\x1B[36m" : "",
|
|
2547
|
+
yellow: colors ? "\x1B[33m" : "",
|
|
2548
|
+
dim: colors ? "\x1B[2m" : "",
|
|
2549
|
+
reset: colors ? "\x1B[0m" : ""
|
|
2550
|
+
};
|
|
2551
|
+
let sc = "";
|
|
2552
|
+
let banner = "[atscript]";
|
|
2553
|
+
switch (m.severity) {
|
|
2554
|
+
case TSeverity.Error:
|
|
2555
|
+
sc = c.red;
|
|
2556
|
+
banner += "[Error]";
|
|
2557
|
+
break;
|
|
2558
|
+
case TSeverity.Warning:
|
|
2559
|
+
sc = c.yellow;
|
|
2560
|
+
banner += "[Warning]";
|
|
2561
|
+
break;
|
|
2562
|
+
case TSeverity.Info:
|
|
2563
|
+
sc = "";
|
|
2564
|
+
banner += "[Info]";
|
|
2565
|
+
break;
|
|
2566
|
+
case TSeverity.Hint:
|
|
2567
|
+
sc = c.dim;
|
|
2568
|
+
banner += "[Hint]";
|
|
2569
|
+
break;
|
|
2570
|
+
default: sc = "";
|
|
2571
|
+
}
|
|
2572
|
+
const n = m.range.start.line + 1;
|
|
2573
|
+
let out = `\n${sc}${banner} ${m.message}${c.reset}` + `\nin ${c.blue}${this.id}:${n}:${m.range.start.character + 1}${c.reset}`;
|
|
2574
|
+
if (addSourceLinses) {
|
|
2575
|
+
const lines = this.text.split("\n");
|
|
2576
|
+
const renderLines = [
|
|
2577
|
+
{
|
|
2578
|
+
l: lines[n - 3],
|
|
2579
|
+
i: n - 3
|
|
2580
|
+
},
|
|
2581
|
+
{
|
|
2582
|
+
l: lines[n - 2],
|
|
2583
|
+
i: n - 2
|
|
2584
|
+
},
|
|
2585
|
+
{
|
|
2586
|
+
l: lines[n - 1],
|
|
2587
|
+
i: n - 1
|
|
2588
|
+
}
|
|
2589
|
+
].filter(Boolean);
|
|
2590
|
+
const nl = String(n).length + 1;
|
|
2591
|
+
for (const { l, i } of renderLines) {
|
|
2592
|
+
const prefix = `${c.dim + c.cyan}${("0" + i).slice(-nl)} | ${c.reset}`;
|
|
2593
|
+
out += `\n${prefix}${l}${c.reset}`;
|
|
2594
|
+
}
|
|
2595
|
+
out += `\n${" ".repeat(nl + 3 + m.range.start.character)}${c.red}${"^".repeat(m.range.end.character - m.range.start.character)}${c.reset}`;
|
|
2596
|
+
}
|
|
2597
|
+
return out + "\n";
|
|
2598
|
+
}
|
|
2451
2599
|
getDiagMessages() {
|
|
2452
2600
|
if (!this._allMessages) {
|
|
2453
2601
|
this._allMessages = [
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
interface TLexicalToken {
|
|
2
|
-
type: 'annotation' | 'comment' | 'punctuation' | 'identifier' | 'text' | 'number' | 'block' | 'unknown';
|
|
2
|
+
type: 'annotation' | 'comment' | 'punctuation' | 'identifier' | 'text' | 'number' | 'block' | 'unknown' | 'regexp';
|
|
3
3
|
text: string;
|
|
4
4
|
children?: TLexicalToken[];
|
|
5
5
|
startOffset?: number;
|
|
@@ -24,7 +24,7 @@ declare class Token {
|
|
|
24
24
|
toString(): string;
|
|
25
25
|
clone(replace: Partial<TLexicalToken>): Token;
|
|
26
26
|
get text(): string;
|
|
27
|
-
get type(): "number" | "annotation" | "comment" | "punctuation" | "identifier" | "text" | "block" | "unknown";
|
|
27
|
+
get type(): "number" | "annotation" | "comment" | "punctuation" | "identifier" | "text" | "block" | "unknown" | "regexp";
|
|
28
28
|
get range(): {
|
|
29
29
|
start: {
|
|
30
30
|
line: number;
|
|
@@ -37,18 +37,48 @@ declare class Token {
|
|
|
37
37
|
};
|
|
38
38
|
get children(): TLexicalToken[];
|
|
39
39
|
get hasChildren(): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* This is truth if the text token was ended with a newline character
|
|
42
|
+
*/
|
|
40
43
|
get multiline(): boolean | undefined;
|
|
44
|
+
/**
|
|
45
|
+
* Set this to file path (e.g. "./src/file.as") for path token in import statement
|
|
46
|
+
*/
|
|
41
47
|
fromPath?: string;
|
|
48
|
+
/**
|
|
49
|
+
* All definitions that exported must be marked with this flag
|
|
50
|
+
*/
|
|
42
51
|
exported?: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* All the definitions must be marked with this flag
|
|
54
|
+
*/
|
|
43
55
|
isDefinition?: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* All the references must be marked with this flag
|
|
58
|
+
*/
|
|
44
59
|
isReference?: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* All the import tokens must be marked with this flag
|
|
62
|
+
*/
|
|
45
63
|
imported?: boolean;
|
|
46
|
-
|
|
64
|
+
/**
|
|
65
|
+
* Refs chained via . or ["propName"] are marked with this flag
|
|
66
|
+
*/
|
|
47
67
|
isChain?: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Prop patterns ([*] or [regexp]) are storing patterns here
|
|
70
|
+
*/
|
|
71
|
+
pattern?: RegExp;
|
|
48
72
|
parentNode?: SemanticNode;
|
|
49
73
|
get isAnnotation(): boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Only for annotation arguments: reference to their annotation token
|
|
76
|
+
*/
|
|
50
77
|
annotationRef?: Token;
|
|
51
78
|
index?: number;
|
|
79
|
+
/**
|
|
80
|
+
* Block type
|
|
81
|
+
*/
|
|
52
82
|
blockType?: 'structure' | 'type' | 'import';
|
|
53
83
|
}
|
|
54
84
|
|
|
@@ -62,9 +92,18 @@ declare class AtscriptRepo {
|
|
|
62
92
|
readonly sharedConfig?: TAtscriptConfigInput | undefined;
|
|
63
93
|
constructor(root?: string, sharedConfig?: TAtscriptConfigInput | undefined);
|
|
64
94
|
protected configFormat?: 'esm' | 'cjs';
|
|
95
|
+
/**
|
|
96
|
+
* Configs cache
|
|
97
|
+
*/
|
|
65
98
|
protected readonly configs: Map<string, Promise<TPluginManagers>>;
|
|
99
|
+
/**
|
|
100
|
+
* .as Documents cache
|
|
101
|
+
*/
|
|
66
102
|
protected readonly atscripts: Map<string, Promise<AtscriptDoc>>;
|
|
67
103
|
sharedPluginManager: TPluginManagers | undefined;
|
|
104
|
+
/**
|
|
105
|
+
* cache for raw content of config files
|
|
106
|
+
*/
|
|
68
107
|
protected configFiles: Map<string, Promise<Partial<TAtscriptConfigInput & TAtscriptConfigOutput>>>;
|
|
69
108
|
getSharedPluginManager(): PluginManager | undefined;
|
|
70
109
|
getPrimitivesTags(): Promise<Set<string> | undefined>;
|
|
@@ -92,7 +131,7 @@ declare class AtscriptRepo {
|
|
|
92
131
|
checkImport(atscript: AtscriptDoc, from: Token, imports: Token[]): Promise<AtscriptDoc | undefined>;
|
|
93
132
|
}
|
|
94
133
|
|
|
95
|
-
type TPunctuation = '\n' | '&' | '+' | ',' | '\\' | '
|
|
134
|
+
type TPunctuation = '\n' | '&' | '+' | ',' | '\\' | '.' | '/' | ':' | '=' | '?' | '|' | ';';
|
|
96
135
|
|
|
97
136
|
declare enum TSeverity {
|
|
98
137
|
Error = 1,
|
|
@@ -219,6 +258,7 @@ interface TPrimitiveTypeArray {
|
|
|
219
258
|
interface TPrimitiveTypeObject {
|
|
220
259
|
kind: 'object';
|
|
221
260
|
props: Record<string, TPrimitiveTypeDef>;
|
|
261
|
+
propsPatterns: Record<string, TPrimitiveTypeDef>;
|
|
222
262
|
optional?: boolean;
|
|
223
263
|
}
|
|
224
264
|
type TPrimitiveTypeFinal = 'string' | 'number' | 'boolean' | 'void' | 'null';
|
|
@@ -245,9 +285,28 @@ declare class SemanticPrimitiveNode extends SemanticNode {
|
|
|
245
285
|
toString(level?: number, prefix?: string): string;
|
|
246
286
|
}
|
|
247
287
|
|
|
288
|
+
/**
|
|
289
|
+
* Interface for a token index system that allows adding tokens and querying the most nested token at a specific position.
|
|
290
|
+
*/
|
|
248
291
|
interface ITokensIndex {
|
|
292
|
+
/**
|
|
293
|
+
* Adds a new token to the index.
|
|
294
|
+
* @param token - The token to add.
|
|
295
|
+
*/
|
|
249
296
|
add: (token: Token) => void;
|
|
297
|
+
/**
|
|
298
|
+
* Finds token at a specific position.
|
|
299
|
+
* @param line - The line number of the position.
|
|
300
|
+
* @param character - The character number of the position.
|
|
301
|
+
* @returns The token at the given position, or `undefined` if no token is found.
|
|
302
|
+
*/
|
|
250
303
|
at: (line: number, character: number) => Token | undefined;
|
|
304
|
+
/**
|
|
305
|
+
* Finds token before specific position.
|
|
306
|
+
* @param line - The line number of the position.
|
|
307
|
+
* @param character - The character number of the position.
|
|
308
|
+
* @returns The token at the given position, or `undefined` if no token is found.
|
|
309
|
+
*/
|
|
251
310
|
before: (line: number, character: number) => Token | undefined;
|
|
252
311
|
}
|
|
253
312
|
|
|
@@ -266,17 +325,44 @@ declare class AtscriptDoc {
|
|
|
266
325
|
readonly registry: IdRegistry;
|
|
267
326
|
semanticMessages: TMessages;
|
|
268
327
|
messages: TMessages;
|
|
328
|
+
/**
|
|
329
|
+
* All the non-blocks tokens, that could be referred
|
|
330
|
+
*/
|
|
269
331
|
tokensIndex: ITokensIndex;
|
|
332
|
+
/**
|
|
333
|
+
* All the block-tokens
|
|
334
|
+
*/
|
|
270
335
|
blocksIndex: ITokensIndex;
|
|
336
|
+
/**
|
|
337
|
+
* Imports map by URI, contains from Token and imports[] tokens
|
|
338
|
+
*/
|
|
271
339
|
imports: Map<string, {
|
|
272
340
|
from: Token;
|
|
273
341
|
imports: Token[];
|
|
274
342
|
}>;
|
|
343
|
+
/**
|
|
344
|
+
* Map of imported definitions by type/interface identifier
|
|
345
|
+
*/
|
|
275
346
|
importedDefs: Map<string, Token>;
|
|
347
|
+
/**
|
|
348
|
+
* Exported nodes by identifier
|
|
349
|
+
*/
|
|
276
350
|
readonly exports: Map<string, SemanticNode>;
|
|
351
|
+
/**
|
|
352
|
+
* Set of documents that this document depend on
|
|
353
|
+
*/
|
|
277
354
|
readonly dependencies: Set<AtscriptDoc>;
|
|
355
|
+
/**
|
|
356
|
+
* Set of documents that depend on this document
|
|
357
|
+
*/
|
|
278
358
|
readonly dependants: Set<AtscriptDoc>;
|
|
359
|
+
/**
|
|
360
|
+
* List of tokens that refer to some type or interface
|
|
361
|
+
*/
|
|
279
362
|
referred: Token[];
|
|
363
|
+
/**
|
|
364
|
+
* Map of dependencies (documents) by URI
|
|
365
|
+
*/
|
|
280
366
|
readonly dependenciesMap: Map<string, AtscriptDoc>;
|
|
281
367
|
get primitives(): SemanticPrimitiveNode[];
|
|
282
368
|
render(format: TAtscriptRenderFormat): Promise<TOutputWithSource[] | undefined>;
|
|
@@ -291,6 +377,27 @@ declare class AtscriptDoc {
|
|
|
291
377
|
resolvedAnnotations: Token[];
|
|
292
378
|
annotations: TAnnotationTokens[];
|
|
293
379
|
registerAnnotation(annotationTokens: TAnnotationTokens): void;
|
|
380
|
+
/**
|
|
381
|
+
* Recursively resolves a type reference (and any property chain) to find the final underlying definition.
|
|
382
|
+
*
|
|
383
|
+
* This method performs a **multi-step** resolution:
|
|
384
|
+
* 1. Locates the declaration owner of the type (via `getDeclarationOwnerNode`).
|
|
385
|
+
* 2. Follows references, type aliases, or nested property chains:
|
|
386
|
+
* - For “Ref” nodes, it uses the identifier to look up the next type.
|
|
387
|
+
* - For “Type” nodes, it calls `getDefinition()` to move to the underlying structure.
|
|
388
|
+
* - For property chains (`chain`), it navigates nested properties or nested types,
|
|
389
|
+
* resolving each level until the final type is reached.
|
|
390
|
+
*
|
|
391
|
+
* @param {string} name - The name of the type or identifier to resolve.
|
|
392
|
+
* @param {Array<string | Token>} [chain=[]] - An optional chain of properties or tokens, each of which
|
|
393
|
+
* refines the path to the final type (e.g., for `SomeType.prop1.prop2`, `chain` might be `[ "prop1", "prop2" ]`).
|
|
394
|
+
* @returns {Object | undefined} An object containing:
|
|
395
|
+
* - `doc`: The `AtscriptDoc` where the final definition is located.
|
|
396
|
+
* - `node`: The last encountered `SemanticNode` before reaching the final underlying definition (often a `Prop` node).
|
|
397
|
+
* - `def`: The final resolved `SemanticNode`.
|
|
398
|
+
*
|
|
399
|
+
* If the type cannot be resolved or does not exist, returns `undefined`.
|
|
400
|
+
*/
|
|
294
401
|
unwindType(name: string, chain?: string[] | Token[], watchCb?: (def: SemanticNode) => void, _tracked?: Set<SemanticNode>): {
|
|
295
402
|
doc: AtscriptDoc;
|
|
296
403
|
node?: SemanticNode;
|
|
@@ -307,6 +414,22 @@ declare class AtscriptDoc {
|
|
|
307
414
|
range: Token['range'];
|
|
308
415
|
token: Token;
|
|
309
416
|
}> | undefined;
|
|
417
|
+
/**
|
|
418
|
+
* Retrieves the definition (i.e., the “go to definition” target) for a given token.
|
|
419
|
+
*
|
|
420
|
+
* This method provides a **single-step** resolution of the defining token:
|
|
421
|
+
* - If the token is defined in the same document, returns that definition.
|
|
422
|
+
* - If the token is imported, follows the import to return the defining token from the relevant document.
|
|
423
|
+
* - If the token is a reference to a locally defined identifier, retrieves the local definition.
|
|
424
|
+
*
|
|
425
|
+
* @param {Token} token - The token for which to locate the definition.
|
|
426
|
+
* @returns {Object | undefined} An object containing:
|
|
427
|
+
* - `uri`: The file path (URI) of the document where the definition is found.
|
|
428
|
+
* - `doc`: The `AtscriptDoc` instance that owns the definition (if found).
|
|
429
|
+
* - `token`: The defining token itself (if found).
|
|
430
|
+
*
|
|
431
|
+
* If no definition is found, returns `undefined`.
|
|
432
|
+
*/
|
|
310
433
|
getDefinitionFor(token: Token): {
|
|
311
434
|
uri: string;
|
|
312
435
|
doc?: AtscriptDoc;
|
|
@@ -351,6 +474,25 @@ declare class AtscriptDoc {
|
|
|
351
474
|
block: Token;
|
|
352
475
|
}): void;
|
|
353
476
|
registerDefinition(token?: Token, asImport?: boolean): void;
|
|
477
|
+
/**
|
|
478
|
+
* Finds the owning document and semantic node responsible for declaring a given identifier.
|
|
479
|
+
*
|
|
480
|
+
* This method checks:
|
|
481
|
+
* 1. Whether the identifier is a known primitive (from this document’s config).
|
|
482
|
+
* 2. If there's a local definition in this document's registry.
|
|
483
|
+
* - If the definition is imported, it resolves the `fromPath`, locates the correct `AtscriptDoc`
|
|
484
|
+
* in the dependency map, and recursively tries to get the declaration owner there.
|
|
485
|
+
* - If the definition is local (not imported), it returns the current document (`this`) along with
|
|
486
|
+
* the parent node that owns the definition and the token itself.
|
|
487
|
+
*
|
|
488
|
+
* @param {string} identifier - The name/identifier whose declaring node should be found.
|
|
489
|
+
* @returns {{ doc: AtscriptDoc; node?: SemanticNode; token?: Token } | undefined} An object containing:
|
|
490
|
+
* - `doc`: The `AtscriptDoc` in which the identifier was ultimately declared.
|
|
491
|
+
* - `node`: The parent `SemanticNode` that defines or owns the declaration (if applicable).
|
|
492
|
+
* - `token`: The specific token for the declaration (if applicable).
|
|
493
|
+
*
|
|
494
|
+
* If no declaration is found, returns `undefined`.
|
|
495
|
+
*/
|
|
354
496
|
getDeclarationOwnerNode(identifier: string): {
|
|
355
497
|
doc: AtscriptDoc;
|
|
356
498
|
node?: SemanticNode;
|
|
@@ -362,9 +504,22 @@ declare class AtscriptDoc {
|
|
|
362
504
|
private _allMessages;
|
|
363
505
|
clearMessages(): void;
|
|
364
506
|
getUnusedTokens(): Token[];
|
|
507
|
+
renderDiagMessage(m: TMessages[number], addSourceLinses?: boolean, colors?: boolean): string;
|
|
365
508
|
getDiagMessages(): TMessages;
|
|
366
509
|
mergeIntersection(node: SemanticNode): SemanticNode;
|
|
367
510
|
mergeDefs(_left: SemanticNode, _right: SemanticNode): [SemanticNode] | [SemanticNode, SemanticNode];
|
|
511
|
+
/**
|
|
512
|
+
* Merges two arrays of annotation tokens, ensuring that annotations from the
|
|
513
|
+
* `right` array take precedence over those from the `left` array.
|
|
514
|
+
*
|
|
515
|
+
* - Annotations from `right` are always included.
|
|
516
|
+
* - Annotations from `left` are included only if they are not already present in `right`.
|
|
517
|
+
* - This ensures that if an annotation exists in both arrays, the one from `right` is kept.
|
|
518
|
+
*
|
|
519
|
+
* @param left - An optional array of annotation tokens to merge (lower priority).
|
|
520
|
+
* @param right - An optional array of annotation tokens to merge (higher priority).
|
|
521
|
+
* @returns A merged array of annotation tokens, preserving order while preventing duplicates.
|
|
522
|
+
*/
|
|
368
523
|
mergeNodesAnnotations(left?: TAnnotationTokens[], right?: TAnnotationTokens[]): TAnnotationTokens[];
|
|
369
524
|
}
|
|
370
525
|
|
|
@@ -445,6 +600,7 @@ declare class SemanticRefNode extends SemanticNode {
|
|
|
445
600
|
declare class SemanticPropNode extends SemanticNode {
|
|
446
601
|
constructor();
|
|
447
602
|
registerAtDocument(doc: AtscriptDoc): void;
|
|
603
|
+
get isPattern(): boolean;
|
|
448
604
|
get nestedProps(): Map<string, SemanticPropNode> | undefined;
|
|
449
605
|
get nestedType(): SemanticRefNode | undefined;
|
|
450
606
|
}
|
|
@@ -458,6 +614,9 @@ declare class SemanticInterfaceNode extends SemanticNode {
|
|
|
458
614
|
declare class SemanticStructureNode extends SemanticGroup {
|
|
459
615
|
constructor();
|
|
460
616
|
readonly props: Map<string, SemanticPropNode>;
|
|
617
|
+
/**
|
|
618
|
+
* Shortcut to set props, used as utility
|
|
619
|
+
*/
|
|
461
620
|
setProps(props: SemanticPropNode[]): void;
|
|
462
621
|
registerAtDocument(doc: AtscriptDoc): void;
|
|
463
622
|
addVirtualProp(opts: {
|
|
@@ -522,8 +681,14 @@ interface TAnnotationsTree {
|
|
|
522
681
|
[key: string]: AnnotationSpec | TAnnotationsTree;
|
|
523
682
|
}
|
|
524
683
|
|
|
684
|
+
/**
|
|
685
|
+
* Defines the configuration for the Intertation parser
|
|
686
|
+
*/
|
|
525
687
|
declare function defineConfig(config: TAtscriptConfig): TAtscriptConfig;
|
|
526
688
|
|
|
689
|
+
/**
|
|
690
|
+
* Resolves nearest config file
|
|
691
|
+
*/
|
|
527
692
|
declare function resolveConfigFile(docUri: string, _root?: string): Promise<string | undefined>;
|
|
528
693
|
declare function loadTsConfig(configFile: string, forceFormat?: 'cjs' | 'esm'): Promise<TAtscriptConfig>;
|
|
529
694
|
declare function loadConfig(configPath: string, forceFormat?: 'cjs' | 'esm'): Promise<TAtscriptConfig>;
|
package/dist/index.mjs
CHANGED
|
@@ -310,11 +310,11 @@ var Token = class Token {
|
|
|
310
310
|
* All the import tokens must be marked with this flag
|
|
311
311
|
*/ _define_property$12(this, "imported", void 0);
|
|
312
312
|
/**
|
|
313
|
-
* All the props must be marked with this flag
|
|
314
|
-
*/ _define_property$12(this, "isProp", void 0);
|
|
315
|
-
/**
|
|
316
313
|
* Refs chained via . or ["propName"] are marked with this flag
|
|
317
314
|
*/ _define_property$12(this, "isChain", void 0);
|
|
315
|
+
/**
|
|
316
|
+
* Prop patterns ([*] or [regexp]) are storing patterns here
|
|
317
|
+
*/ _define_property$12(this, "pattern", void 0);
|
|
318
318
|
_define_property$12(this, "parentNode", void 0);
|
|
319
319
|
/**
|
|
320
320
|
* Only for annotation arguments: reference to their annotation token
|
|
@@ -485,6 +485,9 @@ var SemanticPropNode = class extends SemanticNode {
|
|
|
485
485
|
const token = this.token("identifier");
|
|
486
486
|
if (token && token.type === "text" && token.multiline) doc.registerMessage(token, "Unexpected end of string");
|
|
487
487
|
}
|
|
488
|
+
get isPattern() {
|
|
489
|
+
return !!this.token("identifier")?.pattern;
|
|
490
|
+
}
|
|
488
491
|
get nestedProps() {
|
|
489
492
|
if (this.definition && isStructure(this.definition)) return this.definition.props;
|
|
490
493
|
}
|
|
@@ -942,7 +945,10 @@ async function findConfigFileName(d) {
|
|
|
942
945
|
async function loadTsConfig(configFile, forceFormat) {
|
|
943
946
|
const file = await bundleTsConfig(configFile, forceFormat);
|
|
944
947
|
try {
|
|
945
|
-
return (await import(
|
|
948
|
+
return (await import(
|
|
949
|
+
/* @vite-ignore */
|
|
950
|
+
pathToFileURL(file).href
|
|
951
|
+
)).default;
|
|
946
952
|
} catch (error) {
|
|
947
953
|
console.error("Could not load config file", file, error);
|
|
948
954
|
return {};
|
|
@@ -953,7 +959,10 @@ async function loadTsConfig(configFile, forceFormat) {
|
|
|
953
959
|
async function loadConfig(configPath, forceFormat) {
|
|
954
960
|
const ext = path.extname(configPath);
|
|
955
961
|
try {
|
|
956
|
-
if (SUPPORTED_JS_CONFIG_FORMATS.includes(ext)) return forceFormat ? await loadTsConfig(path.resolve(configPath), forceFormat) : (await import(
|
|
962
|
+
if (SUPPORTED_JS_CONFIG_FORMATS.includes(ext)) return forceFormat ? await loadTsConfig(path.resolve(configPath), forceFormat) : (await import(
|
|
963
|
+
/* @vite-ignore */
|
|
964
|
+
pathToFileURL(configPath).href
|
|
965
|
+
)).default;
|
|
957
966
|
else if (SUPPORTED_TS_CONFIG_FORMATS.includes(ext)) {
|
|
958
967
|
const rawConfigPath = path.resolve(configPath);
|
|
959
968
|
return await loadTsConfig(rawConfigPath, forceFormat);
|
|
@@ -1064,9 +1073,6 @@ var NodeIterator = class NodeIterator {
|
|
|
1064
1073
|
this.$ = this.nodes[this.i];
|
|
1065
1074
|
return this;
|
|
1066
1075
|
}
|
|
1067
|
-
/** @deprecated */ killNextNode(n = 1) {
|
|
1068
|
-
this.nodes.splice(this.i + 1, n);
|
|
1069
|
-
}
|
|
1070
1076
|
next(skip) {
|
|
1071
1077
|
return this.fork().move().skip(skip);
|
|
1072
1078
|
}
|
|
@@ -1246,8 +1252,8 @@ const IdentifierToken = new BasicNode({
|
|
|
1246
1252
|
//#region packages/core/src/tokenizer/tokens/number.token.ts
|
|
1247
1253
|
const NumberToken = new BasicNode({
|
|
1248
1254
|
icon: "N",
|
|
1249
|
-
tokens: [
|
|
1250
|
-
tokenOE: "
|
|
1255
|
+
tokens: [/[-+]?(?:\d*\.\d+|\d+)(?:[eE][-+]?\d+)?/u, /[^\d]/u],
|
|
1256
|
+
tokenOE: "-eject"
|
|
1251
1257
|
}).mapContent("text", "join-clear").onMatch((context) => {
|
|
1252
1258
|
context.customData.type = "number";
|
|
1253
1259
|
});
|
|
@@ -1255,7 +1261,7 @@ const NumberToken = new BasicNode({
|
|
|
1255
1261
|
//#endregion
|
|
1256
1262
|
//#region packages/core/src/tokenizer/tokens/punctuation.token.ts
|
|
1257
1263
|
const PunctuationToken = new BasicNode({
|
|
1258
|
-
tokens: [RegExp("(?<text>[\\n
|
|
1264
|
+
tokens: [RegExp("(?<text>[\\n!&+,./:;=?|])", "u"), ""],
|
|
1259
1265
|
tokenOE: "omit-omit",
|
|
1260
1266
|
icon: "..."
|
|
1261
1267
|
}).onMatch((context) => {
|
|
@@ -1275,6 +1281,19 @@ const TextToken = new BasicNode({
|
|
|
1275
1281
|
context.customData.multiline = context.customData.end === "\n";
|
|
1276
1282
|
});
|
|
1277
1283
|
|
|
1284
|
+
//#endregion
|
|
1285
|
+
//#region packages/core/src/tokenizer/tokens/regexp.token.ts
|
|
1286
|
+
const REGEXP_LITERAL_RE = /\/(?![/*])(?:\\.|\[.*?]|[^/\\\n\r[])*\/[dgimsuy]*/;
|
|
1287
|
+
const RegExpToken = new BasicNode({
|
|
1288
|
+
label: "regexp",
|
|
1289
|
+
icon: "RG",
|
|
1290
|
+
tokens: [REGEXP_LITERAL_RE, ""],
|
|
1291
|
+
tokenOE: "omit-omit"
|
|
1292
|
+
}).onMatch((ctx) => {
|
|
1293
|
+
ctx.customData.type = "regexp";
|
|
1294
|
+
ctx.customData.text = ctx.matched[0];
|
|
1295
|
+
});
|
|
1296
|
+
|
|
1278
1297
|
//#endregion
|
|
1279
1298
|
//#region packages/core/src/tokenizer/tokens/index.ts
|
|
1280
1299
|
const tokens = {
|
|
@@ -1287,6 +1306,7 @@ const tokens = {
|
|
|
1287
1306
|
identifier: IdentifierToken,
|
|
1288
1307
|
number: NumberToken,
|
|
1289
1308
|
text: TextToken,
|
|
1309
|
+
regexp: RegExpToken,
|
|
1290
1310
|
root: undefined
|
|
1291
1311
|
};
|
|
1292
1312
|
const root = new BasicNode({
|
|
@@ -1294,7 +1314,7 @@ const root = new BasicNode({
|
|
|
1294
1314
|
skipToken: /\s/u
|
|
1295
1315
|
}).addRecognizes(...tokens.comments, tokens.block, tokens.aIdentifier, tokens.identifier, tokens.text, tokens.number, tokens.punctuation);
|
|
1296
1316
|
tokens.root = root;
|
|
1297
|
-
BlockToken.addRecognizes(...tokens.comments, tokens.block, tokens.aIdentifier, tokens.identifier, tokens.text, tokens.number, tokens.punctuation);
|
|
1317
|
+
BlockToken.addRecognizes(tokens.regexp, ...tokens.comments, tokens.block, tokens.aIdentifier, tokens.identifier, tokens.text, tokens.number, tokens.punctuation);
|
|
1298
1318
|
const mapContent = (content) => content.map((item) => {
|
|
1299
1319
|
if (typeof item === "string") return {
|
|
1300
1320
|
type: "unknown",
|
|
@@ -1329,6 +1349,7 @@ function $token(name, text$2) {
|
|
|
1329
1349
|
node: name,
|
|
1330
1350
|
text: text$2
|
|
1331
1351
|
}],
|
|
1352
|
+
contains: undefined,
|
|
1332
1353
|
isGlobal: false,
|
|
1333
1354
|
empty: false,
|
|
1334
1355
|
wrapper: undefined,
|
|
@@ -1363,6 +1384,16 @@ function $token(name, text$2) {
|
|
|
1363
1384
|
ni.unexpected(false, `Expected empty block`);
|
|
1364
1385
|
return opts.optional;
|
|
1365
1386
|
}
|
|
1387
|
+
if (opts.contains) {
|
|
1388
|
+
if (!ni.$.children?.length) {
|
|
1389
|
+
ni.unexpected(false, `Expected ${opts.contains.map((v) => v.text).join(", ")}`);
|
|
1390
|
+
return opts.optional;
|
|
1391
|
+
}
|
|
1392
|
+
if (ni.$.children[0].type !== opts.contains[0].node || ni.$.children[0].text !== opts.contains[0].text) {
|
|
1393
|
+
ni.unexpected(false, `Expected ${opts.contains.map((v) => v.text).join(", ")}`);
|
|
1394
|
+
return opts.optional;
|
|
1395
|
+
}
|
|
1396
|
+
}
|
|
1366
1397
|
if (opts.saveAs) target.node.saveToken(new Token(ni.$), opts.saveAs);
|
|
1367
1398
|
ni.accepted();
|
|
1368
1399
|
if (opts.wrapper) {
|
|
@@ -1397,6 +1428,10 @@ else return true;
|
|
|
1397
1428
|
opts.empty = true;
|
|
1398
1429
|
return this;
|
|
1399
1430
|
},
|
|
1431
|
+
contains(t) {
|
|
1432
|
+
opts.contains = t.expect;
|
|
1433
|
+
return this;
|
|
1434
|
+
},
|
|
1400
1435
|
skip(...p) {
|
|
1401
1436
|
opts.skip = p;
|
|
1402
1437
|
return this;
|
|
@@ -1801,6 +1836,52 @@ function unwrap(attr) {
|
|
|
1801
1836
|
}
|
|
1802
1837
|
};
|
|
1803
1838
|
}
|
|
1839
|
+
function propName() {
|
|
1840
|
+
return { handler(ni, target) {
|
|
1841
|
+
switch (ni.$?.type) {
|
|
1842
|
+
case "identifier":
|
|
1843
|
+
case "text":
|
|
1844
|
+
target.node.saveToken(new Token(ni.$), "identifier");
|
|
1845
|
+
ni.accepted();
|
|
1846
|
+
ni.move();
|
|
1847
|
+
ni.skip(["\n"]);
|
|
1848
|
+
return true;
|
|
1849
|
+
case "block":
|
|
1850
|
+
const childrenLength = ni.$.children?.length || 0;
|
|
1851
|
+
const firstText = ni.$.children?.[0]?.text;
|
|
1852
|
+
if (ni.$.text === "[" && ni.$.children?.[0]?.type === "unknown" && childrenLength === 1 && ni.$.children[0].text === "*" || ni.$.text === "[" && ni.$.children?.[0]?.type === "regexp" && childrenLength === 1) {
|
|
1853
|
+
const t = new Token({
|
|
1854
|
+
...ni.$,
|
|
1855
|
+
...ni.$.children[0]
|
|
1856
|
+
});
|
|
1857
|
+
try {
|
|
1858
|
+
t.pattern = firstText === "*" ? /./ : parseRegExpLiteral(firstText);
|
|
1859
|
+
} catch (e) {
|
|
1860
|
+
ni.unexpected(false, e.message);
|
|
1861
|
+
return false;
|
|
1862
|
+
}
|
|
1863
|
+
target.node.saveToken(t, "identifier");
|
|
1864
|
+
ni.accepted();
|
|
1865
|
+
ni.move();
|
|
1866
|
+
ni.skip(["\n"]);
|
|
1867
|
+
return true;
|
|
1868
|
+
}
|
|
1869
|
+
if (ni.$.text === "[" && !childrenLength) ni.unexpected(false, "Wildcard \"*\" or a Regular Expression expected");
|
|
1870
|
+
if (ni.$.text === "[" && childrenLength > 1) ni.unexpected(false, firstText?.startsWith("/") ? "Invalid Regular Expression" : "To many arguments in prop pattern []");
|
|
1871
|
+
else ni.unexpected(false, "Unexpected identifier at property name");
|
|
1872
|
+
return false;
|
|
1873
|
+
default:
|
|
1874
|
+
ni.unexpected(false, "Unexpected identifier at property name");
|
|
1875
|
+
return false;
|
|
1876
|
+
}
|
|
1877
|
+
} };
|
|
1878
|
+
}
|
|
1879
|
+
function parseRegExpLiteral(literal) {
|
|
1880
|
+
const match = literal.match(/^\/(.+)\/([dgimsuy]*)$/);
|
|
1881
|
+
if (!match) throw new Error(`Invalid regexp literal: ${literal}`);
|
|
1882
|
+
const [, pattern, flags] = match;
|
|
1883
|
+
return new RegExp(pattern.replace(/\\\//g, "/"), flags);
|
|
1884
|
+
}
|
|
1804
1885
|
|
|
1805
1886
|
//#endregion
|
|
1806
1887
|
//#region packages/core/src/parser/pipes/pipes.ts
|
|
@@ -1808,9 +1889,9 @@ const ref = $pipe("ref", [refWithChain()]);
|
|
|
1808
1889
|
const constText = defineValuePipe("const", "text", false);
|
|
1809
1890
|
const constNumber = defineValuePipe("const", "number", false);
|
|
1810
1891
|
const allowedValuesPipeArray = [
|
|
1892
|
+
constNumber,
|
|
1811
1893
|
ref,
|
|
1812
|
-
constText
|
|
1813
|
-
constNumber
|
|
1894
|
+
constText
|
|
1814
1895
|
];
|
|
1815
1896
|
const tuplePipeArray = [
|
|
1816
1897
|
block("[]").saveAs("identifier"),
|
|
@@ -1836,7 +1917,7 @@ const type = $pipe("type", [
|
|
|
1836
1917
|
]).skip("\n", ";");
|
|
1837
1918
|
const props = $pipe("prop", [
|
|
1838
1919
|
annotations(),
|
|
1839
|
-
|
|
1920
|
+
propName(),
|
|
1840
1921
|
pun("?").saveAs("optional").optional().skip("\n"),
|
|
1841
1922
|
pun(":").skip("\n"),
|
|
1842
1923
|
definition(allowedValuesPipeArray).separatedBy("&", "|").skip("\n").respectPriority(),
|
|
@@ -1878,6 +1959,16 @@ const pipes = {
|
|
|
1878
1959
|
tuple
|
|
1879
1960
|
};
|
|
1880
1961
|
|
|
1962
|
+
//#endregion
|
|
1963
|
+
//#region packages/core/src/parser/types.ts
|
|
1964
|
+
var TSeverity = /*#__PURE__*/ function(TSeverity$1) {
|
|
1965
|
+
TSeverity$1[TSeverity$1["Error"] = 1] = "Error";
|
|
1966
|
+
TSeverity$1[TSeverity$1["Warning"] = 2] = "Warning";
|
|
1967
|
+
TSeverity$1[TSeverity$1["Info"] = 3] = "Info";
|
|
1968
|
+
TSeverity$1[TSeverity$1["Hint"] = 4] = "Hint";
|
|
1969
|
+
return TSeverity$1;
|
|
1970
|
+
}({});
|
|
1971
|
+
|
|
1881
1972
|
//#endregion
|
|
1882
1973
|
//#region packages/core/src/token-index/blocks-index.ts
|
|
1883
1974
|
function _define_property$5(obj, key, value) {
|
|
@@ -2424,6 +2515,63 @@ else if (isStructure(def) || isInterface(def) || isPrimitive(def)) def = def.pro
|
|
|
2424
2515
|
for (const [key, token] of Array.from(this.registry.definitions.entries())) if (!refSet.has(key) && !this.exports.has(key)) tokens$1.push(token);
|
|
2425
2516
|
return tokens$1;
|
|
2426
2517
|
}
|
|
2518
|
+
renderDiagMessage(m, addSourceLinses = false, colors = false) {
|
|
2519
|
+
const c = {
|
|
2520
|
+
red: colors ? "\x1B[31m" : "",
|
|
2521
|
+
blue: colors ? "\x1B[34m" : "",
|
|
2522
|
+
cyan: colors ? "\x1B[36m" : "",
|
|
2523
|
+
yellow: colors ? "\x1B[33m" : "",
|
|
2524
|
+
dim: colors ? "\x1B[2m" : "",
|
|
2525
|
+
reset: colors ? "\x1B[0m" : ""
|
|
2526
|
+
};
|
|
2527
|
+
let sc = "";
|
|
2528
|
+
let banner = "[atscript]";
|
|
2529
|
+
switch (m.severity) {
|
|
2530
|
+
case TSeverity.Error:
|
|
2531
|
+
sc = c.red;
|
|
2532
|
+
banner += "[Error]";
|
|
2533
|
+
break;
|
|
2534
|
+
case TSeverity.Warning:
|
|
2535
|
+
sc = c.yellow;
|
|
2536
|
+
banner += "[Warning]";
|
|
2537
|
+
break;
|
|
2538
|
+
case TSeverity.Info:
|
|
2539
|
+
sc = "";
|
|
2540
|
+
banner += "[Info]";
|
|
2541
|
+
break;
|
|
2542
|
+
case TSeverity.Hint:
|
|
2543
|
+
sc = c.dim;
|
|
2544
|
+
banner += "[Hint]";
|
|
2545
|
+
break;
|
|
2546
|
+
default: sc = "";
|
|
2547
|
+
}
|
|
2548
|
+
const n = m.range.start.line + 1;
|
|
2549
|
+
let out = `\n${sc}${banner} ${m.message}${c.reset}` + `\nin ${c.blue}${this.id}:${n}:${m.range.start.character + 1}${c.reset}`;
|
|
2550
|
+
if (addSourceLinses) {
|
|
2551
|
+
const lines = this.text.split("\n");
|
|
2552
|
+
const renderLines = [
|
|
2553
|
+
{
|
|
2554
|
+
l: lines[n - 3],
|
|
2555
|
+
i: n - 3
|
|
2556
|
+
},
|
|
2557
|
+
{
|
|
2558
|
+
l: lines[n - 2],
|
|
2559
|
+
i: n - 2
|
|
2560
|
+
},
|
|
2561
|
+
{
|
|
2562
|
+
l: lines[n - 1],
|
|
2563
|
+
i: n - 1
|
|
2564
|
+
}
|
|
2565
|
+
].filter(Boolean);
|
|
2566
|
+
const nl = String(n).length + 1;
|
|
2567
|
+
for (const { l, i } of renderLines) {
|
|
2568
|
+
const prefix = `${c.dim + c.cyan}${("0" + i).slice(-nl)} | ${c.reset}`;
|
|
2569
|
+
out += `\n${prefix}${l}${c.reset}`;
|
|
2570
|
+
}
|
|
2571
|
+
out += `\n${" ".repeat(nl + 3 + m.range.start.character)}${c.red}${"^".repeat(m.range.end.character - m.range.start.character)}${c.reset}`;
|
|
2572
|
+
}
|
|
2573
|
+
return out + "\n";
|
|
2574
|
+
}
|
|
2427
2575
|
getDiagMessages() {
|
|
2428
2576
|
if (!this._allMessages) {
|
|
2429
2577
|
this._allMessages = [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atscript/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.19",
|
|
4
4
|
"description": "Core library for Atscript parsing and file generation.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.mjs",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@types/node": "^22.10.5",
|
|
45
|
-
"vitest": "
|
|
45
|
+
"vitest": "3.2.4"
|
|
46
46
|
},
|
|
47
47
|
"scripts": {
|
|
48
48
|
"pub": "pnpm publish --access public",
|