@tilua/parser 2.2.0 → 2.4.0
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/README.md +11 -3
- package/dist/index.cjs +310 -208
- package/dist/index.d.cts +15 -11
- package/dist/index.d.ts +15 -11
- package/dist/index.js +310 -208
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -864,10 +864,10 @@ var Parser = class {
|
|
|
864
864
|
expressionOr(stop) {
|
|
865
865
|
return this.attempt(() => this.parseExpression(), stop, (start, from) => this.errorExpression(start, from));
|
|
866
866
|
}
|
|
867
|
-
/** A comma-separated list of values
|
|
868
|
-
*
|
|
869
|
-
*
|
|
870
|
-
*
|
|
867
|
+
/** A comma-separated list of values where one belongs — a `return`'s, a
|
|
868
|
+
* declaration's, an assignment's — read whole, so that writing several
|
|
869
|
+
* is reported once and the rest still means something. A spread belongs
|
|
870
|
+
* in a call's arguments or an array, and is reported here too. */
|
|
871
871
|
expressionListOr(stop) {
|
|
872
872
|
const until = () => stop() || this.checkPunctuator(",");
|
|
873
873
|
const item = () => {
|
|
@@ -1459,7 +1459,7 @@ var Parser = class {
|
|
|
1459
1459
|
}
|
|
1460
1460
|
this.error("Expected 'const', 'let', 'function', 'class', 'type', 'default', '{' or '*' after 'export'");
|
|
1461
1461
|
}
|
|
1462
|
-
// `const x = ...` / `let
|
|
1462
|
+
// `const x = ...` / `let [a, b] = ...`.
|
|
1463
1463
|
// tilua has no `local` — `const` bindings are immutable, `let` mutable.
|
|
1464
1464
|
/** `kind` reads the leading word as that keyword (recovery's `local`). */
|
|
1465
1465
|
parseVariableDeclaration(as) {
|
|
@@ -1473,14 +1473,34 @@ var Parser = class {
|
|
|
1473
1473
|
while (this.matchPunctuator(",")) {
|
|
1474
1474
|
names.push(this.parseBindingTarget(true));
|
|
1475
1475
|
}
|
|
1476
|
-
let
|
|
1476
|
+
let values = [];
|
|
1477
1477
|
if (this.matchOperator("=")) {
|
|
1478
|
-
|
|
1478
|
+
values = this.expressionListOr(() => false);
|
|
1479
1479
|
} else if (kind === "const") {
|
|
1480
1480
|
if (!this.recover) this.error("'const' declaration requires an initializer");
|
|
1481
1481
|
this.softError("'const' declaration requires an initializer");
|
|
1482
1482
|
}
|
|
1483
|
-
|
|
1483
|
+
let name = names[0];
|
|
1484
|
+
let init = values[0];
|
|
1485
|
+
if (names.length > 1 || values.length > 1) {
|
|
1486
|
+
this.problemAt(start, `A declaration takes one value: take several from an array, '${kind} [a, b] = [x, y]'`);
|
|
1487
|
+
if (names.length > 1) name = this.namesAsPattern(names);
|
|
1488
|
+
if (values.length > 1) init = this.valuesAsArray(values);
|
|
1489
|
+
}
|
|
1490
|
+
return { type: "VariableDeclaration", kind, name, init, ...spanFrom(start, this.previous()) };
|
|
1491
|
+
}
|
|
1492
|
+
/** `a, b` written where one name goes, read as `[a, b]`. */
|
|
1493
|
+
namesAsPattern(names) {
|
|
1494
|
+
const elements = names.map((value) => ({
|
|
1495
|
+
type: "ArrayPatternElement",
|
|
1496
|
+
value,
|
|
1497
|
+
...spanFrom(value, value)
|
|
1498
|
+
}));
|
|
1499
|
+
return { type: "ArrayPattern", elements, ...spanFrom(names[0], names[names.length - 1]) };
|
|
1500
|
+
}
|
|
1501
|
+
/** `x, y` written where one value goes, read as `[x, y]`. */
|
|
1502
|
+
valuesAsArray(values) {
|
|
1503
|
+
return { type: "ArrayExpression", elements: values, ...spanFrom(values[0], values[values.length - 1]) };
|
|
1484
1504
|
}
|
|
1485
1505
|
parseIfStatement() {
|
|
1486
1506
|
const start = this.current();
|
|
@@ -1961,7 +1981,7 @@ var Parser = class {
|
|
|
1961
1981
|
argument = values[0];
|
|
1962
1982
|
if (values.length > 1) {
|
|
1963
1983
|
this.problemAt(start, "A function returns one value: return several as an array, 'return [a, b]'");
|
|
1964
|
-
argument =
|
|
1984
|
+
argument = this.valuesAsArray(values);
|
|
1965
1985
|
}
|
|
1966
1986
|
}
|
|
1967
1987
|
return { type: "ReturnStatement", argument, ...spanFrom(start, this.previous()) };
|
|
@@ -1987,28 +2007,15 @@ var Parser = class {
|
|
|
1987
2007
|
parseExpressionStatement() {
|
|
1988
2008
|
const start = this.current();
|
|
1989
2009
|
if (this.checkPunctuator("{") || this.checkPunctuator("[")) {
|
|
1990
|
-
const
|
|
1991
|
-
|
|
1992
|
-
];
|
|
1993
|
-
while (this.matchPunctuator(",")) {
|
|
1994
|
-
targets.push(this.parseAssignTarget());
|
|
1995
|
-
}
|
|
1996
|
-
this.expectOperator("=");
|
|
1997
|
-
const values = this.expressionListOr(() => false);
|
|
1998
|
-
return { type: "AssignmentStatement", targets, values, ...spanFrom(start, this.previous()) };
|
|
2010
|
+
const target = this.checkPunctuator("{") ? this.parseObjectPattern(true) : this.parseArrayPattern(true);
|
|
2011
|
+
return this.parseAssignmentRest(start, target);
|
|
1999
2012
|
}
|
|
2000
2013
|
const statementStart = this.cursor;
|
|
2001
2014
|
const errorsAtStart = this.errors.length;
|
|
2002
2015
|
const first = this.parsePrefixExpression();
|
|
2003
2016
|
if (this.checkOperator("=") || this.checkPunctuator(",")) {
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
targets.push(this.parseAssignTarget());
|
|
2007
|
-
}
|
|
2008
|
-
for (const target of targets) this.rejectOptionalTarget(target);
|
|
2009
|
-
this.expectOperator("=");
|
|
2010
|
-
const values = this.expressionListOr(() => false);
|
|
2011
|
-
return { type: "AssignmentStatement", targets, values, ...spanFrom(start, this.previous()) };
|
|
2017
|
+
this.rejectOptionalTarget(first);
|
|
2018
|
+
return this.parseAssignmentRest(start, first);
|
|
2012
2019
|
}
|
|
2013
2020
|
const t = this.current();
|
|
2014
2021
|
if (t.type === "Operator" && COMPOUND_ASSIGN_OPS.has(t.value)) {
|
|
@@ -2034,6 +2041,21 @@ var Parser = class {
|
|
|
2034
2041
|
}
|
|
2035
2042
|
return { type: "ExpressionStatement", expression, ...spanFrom(start, this.previous()) };
|
|
2036
2043
|
}
|
|
2044
|
+
/** From after an assignment's target: `= value`. Luau's `a, b = x, y`
|
|
2045
|
+
* is reported, and read as its first target taking its first value. */
|
|
2046
|
+
parseAssignmentRest(start, target) {
|
|
2047
|
+
let several = false;
|
|
2048
|
+
while (this.matchPunctuator(",")) {
|
|
2049
|
+
this.parseAssignTarget();
|
|
2050
|
+
several = true;
|
|
2051
|
+
}
|
|
2052
|
+
this.expectOperator("=");
|
|
2053
|
+
const values = this.expressionListOr(() => false);
|
|
2054
|
+
if (several || values.length > 1) {
|
|
2055
|
+
this.problemAt(start, "An assignment takes one value: take several from an array, '[a, b] = [x, y]'");
|
|
2056
|
+
}
|
|
2057
|
+
return { type: "AssignmentStatement", target, value: values[0], ...spanFrom(start, this.previous()) };
|
|
2058
|
+
}
|
|
2037
2059
|
// ============================================================
|
|
2038
2060
|
// Expressions
|
|
2039
2061
|
// ============================================================
|
|
@@ -2517,8 +2539,8 @@ var Parser = class {
|
|
|
2517
2539
|
startsSuperUse() {
|
|
2518
2540
|
return this.punctuatorAt(1, "(") || this.punctuatorAt(1, ".") && this.peek(2).type === "Identifier";
|
|
2519
2541
|
}
|
|
2520
|
-
/** After `...`, is there something to spread?
|
|
2521
|
-
*
|
|
2542
|
+
/** After `...`, is there something to spread? tilua has no bare `...`:
|
|
2543
|
+
* a varying number of arguments is a rest parameter, `...args: T[]`. */
|
|
2522
2544
|
startsSpread() {
|
|
2523
2545
|
const next = this.peek(1);
|
|
2524
2546
|
if (next.type === "Punctuator") {
|
|
@@ -2537,11 +2559,11 @@ var Parser = class {
|
|
|
2537
2559
|
const token = this.peek(ahead);
|
|
2538
2560
|
return token.type === "Punctuator" && token.value === value;
|
|
2539
2561
|
}
|
|
2540
|
-
/** An assignment target after the first
|
|
2541
|
-
*
|
|
2562
|
+
/** An assignment target after the first — Luau's `a, b = ...`, read only
|
|
2563
|
+
* to be reported: a prefix expression or a destructuring pattern. */
|
|
2542
2564
|
parseAssignTarget() {
|
|
2543
|
-
if (this.checkPunctuator("{")) return this.parseObjectPattern();
|
|
2544
|
-
if (this.checkPunctuator("[")) return this.parseArrayPattern();
|
|
2565
|
+
if (this.checkPunctuator("{")) return this.parseObjectPattern(true);
|
|
2566
|
+
if (this.checkPunctuator("[")) return this.parseArrayPattern(true);
|
|
2545
2567
|
return this.parsePrefixExpression();
|
|
2546
2568
|
}
|
|
2547
2569
|
/** Does a call's argument list start here? Lua's three forms: `(`, a
|
|
@@ -2720,13 +2742,17 @@ var Parser = class {
|
|
|
2720
2742
|
/** Parses a binding target. When `topLevel`, also consumes a trailing
|
|
2721
2743
|
* `<attr>` list (identifier only) and a `: Type` annotation — these are
|
|
2722
2744
|
* only valid at the outermost level of a `local` / parameter binding,
|
|
2723
|
-
* never nested inside another pattern.
|
|
2724
|
-
|
|
2745
|
+
* never nested inside another pattern. When `assign`, the pattern is a
|
|
2746
|
+
* destructuring assignment's (`[t[i], t[j]] = ...`), and a leaf is any
|
|
2747
|
+
* place a value can be assigned to: a name, a member or an index. */
|
|
2748
|
+
parseBindingTarget(topLevel, assign = false) {
|
|
2725
2749
|
let target;
|
|
2726
2750
|
if (this.checkPunctuator("{")) {
|
|
2727
|
-
target = this.parseObjectPattern();
|
|
2751
|
+
target = this.parseObjectPattern(assign);
|
|
2728
2752
|
} else if (this.checkPunctuator("[")) {
|
|
2729
|
-
target = this.parseArrayPattern();
|
|
2753
|
+
target = this.parseArrayPattern(assign);
|
|
2754
|
+
} else if (assign) {
|
|
2755
|
+
return this.parseAssignPatternLeaf();
|
|
2730
2756
|
} else {
|
|
2731
2757
|
const nameTok = this.expectIdentifier();
|
|
2732
2758
|
let attributes;
|
|
@@ -2748,10 +2774,25 @@ var Parser = class {
|
|
|
2748
2774
|
}
|
|
2749
2775
|
return target;
|
|
2750
2776
|
}
|
|
2751
|
-
|
|
2752
|
-
|
|
2777
|
+
/** A leaf of a destructuring assignment: `a`, `a.b` or `a[i]`. */
|
|
2778
|
+
parseAssignPatternLeaf() {
|
|
2779
|
+
const expression = this.parsePrefixExpression();
|
|
2780
|
+
if (expression.type === "Identifier") {
|
|
2781
|
+
return { type: "IdentifierPattern", name: expression.name, line: expression.line, column: expression.column };
|
|
2782
|
+
}
|
|
2783
|
+
if (expression.type === "MemberExpression" || expression.type === "IndexExpression") {
|
|
2784
|
+
this.rejectOptionalTarget(expression);
|
|
2785
|
+
return expression;
|
|
2786
|
+
}
|
|
2787
|
+
const err = new ParseError("Only a name, a member or an index can be assigned to", expression.line.start, expression.column.start);
|
|
2788
|
+
if (!this.recover) throw err;
|
|
2789
|
+
this.record(err);
|
|
2790
|
+
return { type: "IdentifierPattern", name: "", line: expression.line, column: expression.column };
|
|
2791
|
+
}
|
|
2792
|
+
parseObjectPattern(assign = false) {
|
|
2793
|
+
return this.inBrackets(() => this.parseObjectPatternInner(assign));
|
|
2753
2794
|
}
|
|
2754
|
-
parseObjectPatternInner() {
|
|
2795
|
+
parseObjectPatternInner(assign) {
|
|
2755
2796
|
const start = this.current();
|
|
2756
2797
|
this.expectPunctuator("{");
|
|
2757
2798
|
const properties = [];
|
|
@@ -2759,7 +2800,7 @@ var Parser = class {
|
|
|
2759
2800
|
while (!this.checkPunctuator("}")) {
|
|
2760
2801
|
if (this.checkOperator("...")) {
|
|
2761
2802
|
this.advance();
|
|
2762
|
-
rest = this.parseBindingTarget(false);
|
|
2803
|
+
rest = this.parseBindingTarget(false, assign);
|
|
2763
2804
|
break;
|
|
2764
2805
|
}
|
|
2765
2806
|
const propStart = this.current();
|
|
@@ -2772,17 +2813,17 @@ var Parser = class {
|
|
|
2772
2813
|
key = this.parseExpression();
|
|
2773
2814
|
this.expectPunctuator("]");
|
|
2774
2815
|
this.expectPunctuator(":");
|
|
2775
|
-
value = this.parseBindingTarget(false);
|
|
2816
|
+
value = this.parseBindingTarget(false, assign);
|
|
2776
2817
|
} else if (this.checkType("Literal") && this.current().kind === "string") {
|
|
2777
2818
|
const t = this.advance();
|
|
2778
2819
|
key = { type: "StringLiteral", value: t.value, raw: t.raw, ...spanFrom(t, t) };
|
|
2779
2820
|
this.expectPunctuator(":");
|
|
2780
|
-
value = this.parseBindingTarget(false);
|
|
2821
|
+
value = this.parseBindingTarget(false, assign);
|
|
2781
2822
|
} else {
|
|
2782
2823
|
const nameTok = this.expectIdentifier();
|
|
2783
2824
|
key = { type: "Identifier", name: nameTok.value, ...spanFrom(nameTok, nameTok) };
|
|
2784
2825
|
if (this.matchPunctuator(":")) {
|
|
2785
|
-
value = this.parseBindingTarget(false);
|
|
2826
|
+
value = this.parseBindingTarget(false, assign);
|
|
2786
2827
|
} else {
|
|
2787
2828
|
shorthand = true;
|
|
2788
2829
|
value = { type: "IdentifierPattern", name: nameTok.value, ...spanFrom(nameTok, nameTok) };
|
|
@@ -2805,10 +2846,10 @@ var Parser = class {
|
|
|
2805
2846
|
this.expectPunctuator("}");
|
|
2806
2847
|
return { type: "ObjectPattern", properties, rest, ...spanFrom(start, this.previous()) };
|
|
2807
2848
|
}
|
|
2808
|
-
parseArrayPattern() {
|
|
2809
|
-
return this.inBrackets(() => this.parseArrayPatternInner());
|
|
2849
|
+
parseArrayPattern(assign = false) {
|
|
2850
|
+
return this.inBrackets(() => this.parseArrayPatternInner(assign));
|
|
2810
2851
|
}
|
|
2811
|
-
parseArrayPatternInner() {
|
|
2852
|
+
parseArrayPatternInner(assign) {
|
|
2812
2853
|
const start = this.current();
|
|
2813
2854
|
this.expectPunctuator("[");
|
|
2814
2855
|
const elements = [];
|
|
@@ -2816,7 +2857,7 @@ var Parser = class {
|
|
|
2816
2857
|
while (!this.checkPunctuator("]")) {
|
|
2817
2858
|
if (this.checkOperator("...")) {
|
|
2818
2859
|
this.advance();
|
|
2819
|
-
rest = this.parseBindingTarget(false);
|
|
2860
|
+
rest = this.parseBindingTarget(false, assign);
|
|
2820
2861
|
break;
|
|
2821
2862
|
}
|
|
2822
2863
|
if (this.checkPunctuator(",")) {
|
|
@@ -2825,7 +2866,7 @@ var Parser = class {
|
|
|
2825
2866
|
continue;
|
|
2826
2867
|
}
|
|
2827
2868
|
const elStart = this.current();
|
|
2828
|
-
const value = this.parseBindingTarget(false);
|
|
2869
|
+
const value = this.parseBindingTarget(false, assign);
|
|
2829
2870
|
let def;
|
|
2830
2871
|
if (this.matchOperator("=")) def = this.parseExpression();
|
|
2831
2872
|
elements.push({ type: "ArrayPatternElement", value, default: def, ...spanFrom(elStart, this.previous()) });
|
|
@@ -3029,7 +3070,7 @@ var Parser = class {
|
|
|
3029
3070
|
};
|
|
3030
3071
|
})() : this.parseFunctionHead();
|
|
3031
3072
|
this.expectPunctuator("=>");
|
|
3032
|
-
const body = this.checkPunctuator("{") ? this.parseBraceBlock() : this.
|
|
3073
|
+
const body = this.checkPunctuator("{") ? this.parseBraceBlock() : this.parseArrowExpressionBody();
|
|
3033
3074
|
const func = {
|
|
3034
3075
|
type: "FunctionBody",
|
|
3035
3076
|
generics: head.generics,
|
|
@@ -3042,6 +3083,29 @@ var Parser = class {
|
|
|
3042
3083
|
};
|
|
3043
3084
|
return { type: "FunctionExpression", func, ...spanFrom(start, this.previous()) };
|
|
3044
3085
|
}
|
|
3086
|
+
/** `() => value` returns the value. `() => a = 1` and `() => n += 1` are
|
|
3087
|
+
* an assignment, which is a statement: the body is that
|
|
3088
|
+
* statement, and the function returns nothing. */
|
|
3089
|
+
parseArrowExpressionBody() {
|
|
3090
|
+
const start = this.cursor;
|
|
3091
|
+
const errors = this.errors.length;
|
|
3092
|
+
const expression = this.parseExpression(0);
|
|
3093
|
+
const t = this.current();
|
|
3094
|
+
const assigns = t.type === "Operator" && (t.value === "=" || COMPOUND_ASSIGN_OPS.has(t.value));
|
|
3095
|
+
if (!assigns) return this.returnOf(expression);
|
|
3096
|
+
this.cursor = start;
|
|
3097
|
+
this.errors.length = errors;
|
|
3098
|
+
const first = this.current();
|
|
3099
|
+
const target = this.parsePrefixExpression();
|
|
3100
|
+
this.rejectOptionalTarget(target);
|
|
3101
|
+
const opToken = this.current();
|
|
3102
|
+
const op = opToken.value;
|
|
3103
|
+
if (opToken.type !== "Operator" || op !== "=" && !COMPOUND_ASSIGN_OPS.has(op)) this.error("Expected '='");
|
|
3104
|
+
this.advance();
|
|
3105
|
+
const value = this.expressionOr(() => false);
|
|
3106
|
+
const statement = op === "=" ? { type: "AssignmentStatement", target, value, ...spanFrom(first, this.previous()) } : { type: "CompoundAssignmentStatement", operator: op, target, value, ...spanFrom(first, this.previous()) };
|
|
3107
|
+
return { type: "Block", statements: [statement], ...spanFrom(statement, statement) };
|
|
3108
|
+
}
|
|
3045
3109
|
/** A one-expression body: the value is what the function returns. */
|
|
3046
3110
|
returnOf(expression) {
|
|
3047
3111
|
const statement = {
|
|
@@ -3939,6 +4003,10 @@ var Analyzer = class {
|
|
|
3939
4003
|
this.checkConstAssign(id, t);
|
|
3940
4004
|
return;
|
|
3941
4005
|
}
|
|
4006
|
+
case "MemberExpression":
|
|
4007
|
+
case "IndexExpression":
|
|
4008
|
+
this.visitExpression(t, scope);
|
|
4009
|
+
return;
|
|
3942
4010
|
case "ObjectPattern":
|
|
3943
4011
|
for (const p of t.properties) {
|
|
3944
4012
|
if (p.computed) this.visitExpression(p.key, scope);
|
|
@@ -3973,10 +4041,11 @@ var Analyzer = class {
|
|
|
3973
4041
|
visitStatement(stmt, scope) {
|
|
3974
4042
|
switch (stmt.type) {
|
|
3975
4043
|
case "VariableDeclaration": {
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
4044
|
+
if (stmt.init) this.visitExpression(stmt.init, scope);
|
|
4045
|
+
if (stmt.name.type !== "MemberExpression" && stmt.name.type !== "IndexExpression") {
|
|
4046
|
+
this.visitType(stmt.name.typeAnnotation, scope);
|
|
4047
|
+
}
|
|
4048
|
+
this.declarePattern(scope, stmt.name, "local", scope, stmt.kind === "const");
|
|
3980
4049
|
return;
|
|
3981
4050
|
}
|
|
3982
4051
|
case "FunctionDeclaration": {
|
|
@@ -4010,16 +4079,15 @@ var Analyzer = class {
|
|
|
4010
4079
|
return;
|
|
4011
4080
|
}
|
|
4012
4081
|
case "AssignmentStatement": {
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
}
|
|
4082
|
+
this.visitExpression(stmt.value, scope);
|
|
4083
|
+
const target = stmt.target;
|
|
4084
|
+
if (target.type === "Identifier") {
|
|
4085
|
+
this.referenceAsAssignmentTarget(scope, target);
|
|
4086
|
+
} else if (target.type === "ObjectPattern" || target.type === "ArrayPattern") {
|
|
4087
|
+
this.assignPattern(scope, target);
|
|
4088
|
+
} else {
|
|
4089
|
+
this.visitExpression(target, scope);
|
|
4090
|
+
this.checkModuleWrite(target);
|
|
4023
4091
|
}
|
|
4024
4092
|
return;
|
|
4025
4093
|
}
|
|
@@ -5343,7 +5411,7 @@ function moduleExports(program, scopes, types, resolveModule) {
|
|
|
5343
5411
|
params: declaration.typeParams.map((g) => g.name)
|
|
5344
5412
|
});
|
|
5345
5413
|
}
|
|
5346
|
-
} else
|
|
5414
|
+
} else exportPattern(declaration.name);
|
|
5347
5415
|
} else if (stmt.type === "ExportTypeAliasStatement") {
|
|
5348
5416
|
const name = stmt.alias.name.name;
|
|
5349
5417
|
const type = types.aliases.get(name);
|
|
@@ -5582,12 +5650,10 @@ function assignedFields(block) {
|
|
|
5582
5650
|
const names = /* @__PURE__ */ new Set();
|
|
5583
5651
|
walkNodes(block, (node) => {
|
|
5584
5652
|
const record = node;
|
|
5585
|
-
|
|
5586
|
-
|
|
5587
|
-
|
|
5588
|
-
|
|
5589
|
-
names.add(member.property.name);
|
|
5590
|
-
}
|
|
5653
|
+
if (record.type !== "AssignmentStatement" && record.type !== "CompoundAssignmentStatement") return;
|
|
5654
|
+
const member = record.target;
|
|
5655
|
+
if (member.type === "MemberExpression" && member.object?.type === "Identifier" && member.object.name === "this" && member.property?.name) {
|
|
5656
|
+
names.add(member.property.name);
|
|
5591
5657
|
}
|
|
5592
5658
|
});
|
|
5593
5659
|
return names;
|
|
@@ -6063,12 +6129,10 @@ var TypeAnalyzer = class {
|
|
|
6063
6129
|
classDisplayNames = /* @__PURE__ */ new WeakMap();
|
|
6064
6130
|
/** `const Name = class ... end` — the name the class will be known by. */
|
|
6065
6131
|
nameClassExpressions(stmt) {
|
|
6066
|
-
|
|
6067
|
-
|
|
6068
|
-
|
|
6069
|
-
|
|
6070
|
-
}
|
|
6071
|
-
});
|
|
6132
|
+
const value = stmt.init;
|
|
6133
|
+
if (stmt.name.type === "IdentifierPattern" && value?.type === "ClassExpression" && !value.name) {
|
|
6134
|
+
this.classDisplayNames.set(value, stmt.name.name);
|
|
6135
|
+
}
|
|
6072
6136
|
}
|
|
6073
6137
|
classTypeParams(stmt) {
|
|
6074
6138
|
return stmt.type === "ClassDeclaration" ? stmt.typeParams : [];
|
|
@@ -6397,6 +6461,14 @@ var TypeAnalyzer = class {
|
|
|
6397
6461
|
report(stmt.superclass, known ? `'${stmt.superclass.name}' is not a class; a class can only extend another class` : `Cannot find class '${stmt.superclass.name}'`);
|
|
6398
6462
|
}
|
|
6399
6463
|
}
|
|
6464
|
+
this.withClass(stmt, () => this.withTypeParams(this.classTypeParams(stmt), () => {
|
|
6465
|
+
this.withSelfType(this.selfTypeOf(stmt), () => {
|
|
6466
|
+
for (const member of stmt.members) {
|
|
6467
|
+
if (member.type !== "ClassMethod" || !member.signatures) continue;
|
|
6468
|
+
for (const signature of member.signatures) this.checkOverload(member.func, signature);
|
|
6469
|
+
}
|
|
6470
|
+
});
|
|
6471
|
+
}));
|
|
6400
6472
|
for (const member of stmt.members) {
|
|
6401
6473
|
if (member.type === "ClassConstructor") continue;
|
|
6402
6474
|
if (CLASS_RESERVED.has(member.name.name)) {
|
|
@@ -7351,35 +7423,30 @@ var TypeAnalyzer = class {
|
|
|
7351
7423
|
switch (stmt.type) {
|
|
7352
7424
|
case "VariableDeclaration": {
|
|
7353
7425
|
this.nameClassExpressions(stmt);
|
|
7354
|
-
|
|
7355
|
-
|
|
7356
|
-
|
|
7357
|
-
|
|
7358
|
-
}
|
|
7359
|
-
const
|
|
7360
|
-
this.
|
|
7361
|
-
|
|
7362
|
-
|
|
7363
|
-
|
|
7364
|
-
|
|
7365
|
-
|
|
7366
|
-
|
|
7367
|
-
|
|
7368
|
-
|
|
7369
|
-
message: `Type '${briefType(inferred)}' is not assignable to '${briefType(declared)}'` + this.explainMismatch(inferred, declared)
|
|
7370
|
-
});
|
|
7371
|
-
} else if (declared.kind !== "any") {
|
|
7372
|
-
this.reportExcessProperties(source, declared);
|
|
7373
|
-
}
|
|
7374
|
-
}
|
|
7375
|
-
const mode = this.initIsAsConst(source) ? "asconst" : !isFreshLiteralExpr(source) ? "keep" : stmt.kind === "const" ? "const" : "widen";
|
|
7376
|
-
this.bindPattern(target, inferred, env, mode);
|
|
7377
|
-
if (stmt.kind === "const") {
|
|
7378
|
-
this.correlateDestructuring(target, inferred, env);
|
|
7379
|
-
this.correlateIndexed(target, source, env);
|
|
7380
|
-
this.aliasReference(target, source);
|
|
7426
|
+
const target = stmt.name;
|
|
7427
|
+
const source = stmt.init;
|
|
7428
|
+
if (target.type === "IdentifierPattern" && target.typeAnnotation && source) {
|
|
7429
|
+
this.applyContext(source, this.resolveType(target.typeAnnotation));
|
|
7430
|
+
}
|
|
7431
|
+
const inferred = source ? this.infer(source, env) : nilType;
|
|
7432
|
+
if (this.emitDiagnostics && target.type === "IdentifierPattern" && target.typeAnnotation && source) {
|
|
7433
|
+
const declared = this.resolveType(target.typeAnnotation);
|
|
7434
|
+
if (declared.kind !== "any" && !this.namesNothing(declared) && !this.fitsAnnotation(source, declared, inferred, env)) {
|
|
7435
|
+
this.diagnostics.push({
|
|
7436
|
+
node: stmt,
|
|
7437
|
+
message: `Type '${briefType(inferred)}' is not assignable to '${briefType(declared)}'` + this.explainMismatch(inferred, declared)
|
|
7438
|
+
});
|
|
7439
|
+
} else if (declared.kind !== "any") {
|
|
7440
|
+
this.reportExcessProperties(source, declared);
|
|
7381
7441
|
}
|
|
7382
|
-
}
|
|
7442
|
+
}
|
|
7443
|
+
const mode = this.initIsAsConst(source) ? "asconst" : !isFreshLiteralExpr(source) ? "keep" : stmt.kind === "const" ? "const" : "widen";
|
|
7444
|
+
this.bindPattern(target, inferred, env, mode);
|
|
7445
|
+
if (stmt.kind === "const") {
|
|
7446
|
+
this.correlateDestructuring(target, inferred, env);
|
|
7447
|
+
this.correlateIndexed(target, source, env);
|
|
7448
|
+
this.aliasReference(target, source);
|
|
7449
|
+
}
|
|
7383
7450
|
return;
|
|
7384
7451
|
}
|
|
7385
7452
|
case "ClassDeclaration": {
|
|
@@ -7436,48 +7503,41 @@ var TypeAnalyzer = class {
|
|
|
7436
7503
|
return;
|
|
7437
7504
|
}
|
|
7438
7505
|
case "AssignmentStatement": {
|
|
7439
|
-
stmt.
|
|
7440
|
-
|
|
7441
|
-
|
|
7442
|
-
|
|
7443
|
-
|
|
7444
|
-
|
|
7445
|
-
|
|
7446
|
-
|
|
7447
|
-
|
|
7448
|
-
|
|
7449
|
-
|
|
7450
|
-
|
|
7451
|
-
|
|
7452
|
-
|
|
7453
|
-
|
|
7454
|
-
|
|
7455
|
-
|
|
7456
|
-
|
|
7457
|
-
|
|
7458
|
-
|
|
7459
|
-
|
|
7460
|
-
const declared = this.bindingType.get(id);
|
|
7461
|
-
if (this.emitDiagnostics && !isAssignable(next, declared) && declared.kind !== "any") {
|
|
7462
|
-
this.diagnostics.push({
|
|
7463
|
-
node: stmt,
|
|
7464
|
-
message: `Type '${briefType(next)}' is not assignable to '${briefType(declared)}'` + this.explainMismatch(next, declared)
|
|
7465
|
-
});
|
|
7466
|
-
}
|
|
7467
|
-
this.setBinding(env, id, narrowTo(declared, next));
|
|
7468
|
-
} else {
|
|
7469
|
-
this.setBinding(env, id, next);
|
|
7470
|
-
this.bindingType.set(id, union([this.bindingType.get(id) ?? next, next]));
|
|
7506
|
+
const target = stmt.target;
|
|
7507
|
+
const source = stmt.value;
|
|
7508
|
+
if (target.type === "MemberExpression" || target.type === "IndexExpression") {
|
|
7509
|
+
this.applyContext(source, this.infer(target, env));
|
|
7510
|
+
} else if (target.type === "Identifier") {
|
|
7511
|
+
const id = this.bindingIdOf(target);
|
|
7512
|
+
if (id !== void 0 && this.annotated.has(id)) this.applyContext(source, this.bindingType.get(id));
|
|
7513
|
+
}
|
|
7514
|
+
const vt = this.infer(source, env);
|
|
7515
|
+
if (target.type === "Identifier") {
|
|
7516
|
+
const id = this.bindingIdOf(target);
|
|
7517
|
+
if (id !== void 0) {
|
|
7518
|
+
this.uncorrelate(id);
|
|
7519
|
+
const next = isFreshLiteralExpr(source) ? widen(vt) : vt;
|
|
7520
|
+
if (this.annotated.has(id)) {
|
|
7521
|
+
const declared = this.bindingType.get(id);
|
|
7522
|
+
if (this.emitDiagnostics && !isAssignable(next, declared) && declared.kind !== "any") {
|
|
7523
|
+
this.diagnostics.push({
|
|
7524
|
+
node: stmt,
|
|
7525
|
+
message: `Type '${briefType(next)}' is not assignable to '${briefType(declared)}'` + this.explainMismatch(next, declared)
|
|
7526
|
+
});
|
|
7471
7527
|
}
|
|
7528
|
+
this.setBinding(env, id, narrowTo(declared, next));
|
|
7529
|
+
} else {
|
|
7530
|
+
this.setBinding(env, id, next);
|
|
7531
|
+
this.bindingType.set(id, union([this.bindingType.get(id) ?? next, next]));
|
|
7472
7532
|
}
|
|
7473
|
-
} else if (target.type === "MemberExpression" || target.type === "IndexExpression") {
|
|
7474
|
-
this.infer(target, env);
|
|
7475
|
-
this.checkReadonlyAssign(target, env);
|
|
7476
|
-
this.assignToRef(target, isFreshLiteralExpr(source) ? widen(vt) : vt, env);
|
|
7477
|
-
} else if (target.type === "ObjectPattern" || target.type === "ArrayPattern") {
|
|
7478
|
-
this.reassignPattern(target, vt, env);
|
|
7479
7533
|
}
|
|
7480
|
-
})
|
|
7534
|
+
} else if (target.type === "MemberExpression" || target.type === "IndexExpression") {
|
|
7535
|
+
this.infer(target, env);
|
|
7536
|
+
this.checkReadonlyAssign(target, env);
|
|
7537
|
+
this.assignToRef(target, isFreshLiteralExpr(source) ? widen(vt) : vt, env);
|
|
7538
|
+
} else if (target.type === "ObjectPattern" || target.type === "ArrayPattern") {
|
|
7539
|
+
this.reassignPattern(target, vt, env);
|
|
7540
|
+
}
|
|
7481
7541
|
return;
|
|
7482
7542
|
}
|
|
7483
7543
|
case "CompoundAssignmentStatement":
|
|
@@ -7641,55 +7701,6 @@ var TypeAnalyzer = class {
|
|
|
7641
7701
|
return;
|
|
7642
7702
|
}
|
|
7643
7703
|
}
|
|
7644
|
-
/** Flatten an expression list into the values it actually produces.
|
|
7645
|
-
*
|
|
7646
|
-
* Lua's adjustment rule: every expression but the last contributes one
|
|
7647
|
-
* value, and the last contributes all of its values if it is a call or
|
|
7648
|
-
* `...`. That is what makes `local ok, err = pcall(f)` work, and it is
|
|
7649
|
-
* why `local x = f()` takes only the first value.
|
|
7650
|
-
*
|
|
7651
|
-
* `sources` maps each produced value back to the expression it came from
|
|
7652
|
-
* (undefined for the 2nd and later values of a multi-value call), so the
|
|
7653
|
-
* caller can still do contextual typing against the written expression. */
|
|
7654
|
-
valueList(exprs, env) {
|
|
7655
|
-
const types = [];
|
|
7656
|
-
const sources = [];
|
|
7657
|
-
exprs.forEach((e, i) => {
|
|
7658
|
-
const t = this.infer(e, env);
|
|
7659
|
-
const last = i === exprs.length - 1;
|
|
7660
|
-
if (e.type === "SpreadElement") {
|
|
7661
|
-
const held = this.typeOf.get(e.argument);
|
|
7662
|
-
const expanded = held && this.expand(held);
|
|
7663
|
-
if (expanded?.kind === "tuple") {
|
|
7664
|
-
for (const element of expanded.elements) {
|
|
7665
|
-
types.push(element);
|
|
7666
|
-
sources.push(e);
|
|
7667
|
-
}
|
|
7668
|
-
return;
|
|
7669
|
-
}
|
|
7670
|
-
types.push(t);
|
|
7671
|
-
sources.push(e);
|
|
7672
|
-
return;
|
|
7673
|
-
}
|
|
7674
|
-
void last;
|
|
7675
|
-
types.push(t);
|
|
7676
|
-
sources.push(e);
|
|
7677
|
-
});
|
|
7678
|
-
return { types, sources };
|
|
7679
|
-
}
|
|
7680
|
-
/** `const a, b = x, y` pairs names with values, one each. A call is one
|
|
7681
|
-
* value — several come back as an array — so `const a, b = f()` is a
|
|
7682
|
-
* name short of a value, and says how to take them apart. */
|
|
7683
|
-
checkValueCount(node, names, values, types) {
|
|
7684
|
-
if (!this.emitDiagnostics || !values.length || types.length >= names) return;
|
|
7685
|
-
const last = values[values.length - 1];
|
|
7686
|
-
const lastType = types[types.length - 1] && this.expand(types[types.length - 1]);
|
|
7687
|
-
const call = last.type === "CallExpression" || last.type === "MethodCallExpression";
|
|
7688
|
-
this.diagnostics.push({
|
|
7689
|
-
node,
|
|
7690
|
-
message: call && (lastType?.kind === "tuple" || lastType?.kind === "array") ? `A call is one value, here an array: take its parts with '[${Array.from({ length: names }, (_, i) => String.fromCharCode(97 + i)).join(", ")}] = ...'` : `${names} names, but ${types.length} ${types.length === 1 ? "value" : "values"}: each name needs one`
|
|
7691
|
-
});
|
|
7692
|
-
}
|
|
7693
7704
|
/** Run `visit` with a fresh place to collect `break` states, and return
|
|
7694
7705
|
* what it collected. */
|
|
7695
7706
|
withBreakScope(visit) {
|
|
@@ -7964,7 +7975,7 @@ var TypeAnalyzer = class {
|
|
|
7964
7975
|
/** Synthesize a type from a destructuring pattern used without an
|
|
7965
7976
|
* annotation (`function f({ a, b = 1 })`). */
|
|
7966
7977
|
patternToType(target, env) {
|
|
7967
|
-
const leaf = (v, def) => v.type
|
|
7978
|
+
const leaf = (v, def) => v.type === "ObjectPattern" || v.type === "ArrayPattern" ? this.patternToType(v, env) : v.type !== "IdentifierPattern" ? anyType : v.typeAnnotation ? this.resolveType(v.typeAnnotation) : def ? widen(this.infer(def, env)) : anyType;
|
|
7968
7979
|
if (target.type === "ObjectPattern") {
|
|
7969
7980
|
const entries = [];
|
|
7970
7981
|
for (const p of target.properties) {
|
|
@@ -8370,6 +8381,7 @@ var TypeAnalyzer = class {
|
|
|
8370
8381
|
* can actually be. An annotation, a pattern or a default still wins. */
|
|
8371
8382
|
paramsFromSignatures(func, signatures) {
|
|
8372
8383
|
if (!signatures?.length) return;
|
|
8384
|
+
for (const signature of signatures) this.checkOverload(func, signature);
|
|
8373
8385
|
const resolved = signatures.map((sig) => this.signatureToFnType(sig));
|
|
8374
8386
|
func.params.forEach((param, i) => {
|
|
8375
8387
|
if (param.typeAnnotation || param.pattern || param.default) return;
|
|
@@ -8383,6 +8395,64 @@ var TypeAnalyzer = class {
|
|
|
8383
8395
|
if (candidates.length) this.contextualParams.set(param, union(candidates));
|
|
8384
8396
|
});
|
|
8385
8397
|
}
|
|
8398
|
+
/** The implementation is what runs for every signature of an overload
|
|
8399
|
+
* set, so each signature must be one it can serve: no parameter it does
|
|
8400
|
+
* not have, no fewer arguments than it requires, no argument type it does
|
|
8401
|
+
* not accept, and a return it can give. Stricter than TypeScript, which
|
|
8402
|
+
* lets a signature name parameters the implementation never reads. */
|
|
8403
|
+
checkOverload(func, signature) {
|
|
8404
|
+
if (!this.emitDiagnostics) return;
|
|
8405
|
+
const node = signature;
|
|
8406
|
+
const report = (message) => {
|
|
8407
|
+
this.diagnostics.push({ node, message });
|
|
8408
|
+
};
|
|
8409
|
+
const own = (params) => params.filter((p, i) => !p.rest && !(i === 0 && !p.typeAnnotation && (p.name === "self" || p.name === "this")));
|
|
8410
|
+
const implementation = own(func.params);
|
|
8411
|
+
const offered = own(signature.params);
|
|
8412
|
+
const implementationRest = func.params.some((p) => p.rest);
|
|
8413
|
+
const signatureRest = signature.params.some((p) => p.rest);
|
|
8414
|
+
const label = (p) => p.pattern ? "a destructured parameter" : `'${p.name}'`;
|
|
8415
|
+
if (!implementationRest) {
|
|
8416
|
+
const extra = offered[implementation.length];
|
|
8417
|
+
if (extra) {
|
|
8418
|
+
report(`This overload takes parameter ${label(extra)}, which the implementation does not have: it takes ${implementation.length} parameter${implementation.length === 1 ? "" : "s"}`);
|
|
8419
|
+
return;
|
|
8420
|
+
}
|
|
8421
|
+
if (signatureRest) {
|
|
8422
|
+
report("This overload takes a rest parameter, which the implementation does not have");
|
|
8423
|
+
return;
|
|
8424
|
+
}
|
|
8425
|
+
}
|
|
8426
|
+
if (!signatureRest) {
|
|
8427
|
+
let required = 0;
|
|
8428
|
+
implementation.forEach((p, i) => {
|
|
8429
|
+
if (!p.optional && p.default === void 0) required = i + 1;
|
|
8430
|
+
});
|
|
8431
|
+
if (offered.length < required) {
|
|
8432
|
+
report(`The implementation requires ${required} argument${required === 1 ? "" : "s"}, and this overload passes at most ${offered.length}`);
|
|
8433
|
+
return;
|
|
8434
|
+
}
|
|
8435
|
+
}
|
|
8436
|
+
if (signature.generics.length || func.generics.length) return;
|
|
8437
|
+
for (let i = 0; i < offered.length && i < implementation.length; i++) {
|
|
8438
|
+
const target = implementation[i];
|
|
8439
|
+
if (!target.typeAnnotation && target.default === void 0) continue;
|
|
8440
|
+
let accepted = this.paramType(target, /* @__PURE__ */ new Map());
|
|
8441
|
+
if (target.default !== void 0) accepted = optional(accepted);
|
|
8442
|
+
const given = this.paramType(offered[i], /* @__PURE__ */ new Map());
|
|
8443
|
+
if (!isAssignable(given, accepted)) {
|
|
8444
|
+
report(`Parameter ${label(offered[i])} of this overload is '${briefType(given)}', which the implementation's '${briefType(accepted)}' does not accept`);
|
|
8445
|
+
return;
|
|
8446
|
+
}
|
|
8447
|
+
}
|
|
8448
|
+
if (signature.returnType && func.returnType) {
|
|
8449
|
+
const promised = this.resolveType(signature.returnType);
|
|
8450
|
+
const returned = this.resolveType(func.returnType);
|
|
8451
|
+
if (!isAssignable(promised, returned) && !isAssignable(returned, promised)) {
|
|
8452
|
+
report(`This overload returns '${briefType(promised)}', which the implementation's '${briefType(returned)}' cannot be`);
|
|
8453
|
+
}
|
|
8454
|
+
}
|
|
8455
|
+
}
|
|
8386
8456
|
signatureToFnType(sig) {
|
|
8387
8457
|
const names = sig.generics.map((g) => g.name);
|
|
8388
8458
|
const record = (type) => {
|
|
@@ -8807,6 +8877,12 @@ var TypeAnalyzer = class {
|
|
|
8807
8877
|
}
|
|
8808
8878
|
return;
|
|
8809
8879
|
}
|
|
8880
|
+
case "MemberExpression":
|
|
8881
|
+
case "IndexExpression":
|
|
8882
|
+
this.infer(target, env);
|
|
8883
|
+
this.checkReadonlyAssign(target, env);
|
|
8884
|
+
this.assignToRef(target, widen(valueType), env);
|
|
8885
|
+
return;
|
|
8810
8886
|
case "ObjectPattern": {
|
|
8811
8887
|
for (const p of target.properties) {
|
|
8812
8888
|
const key = !p.computed && p.key.type === "Identifier" ? p.key.name : !p.computed && p.key.type === "StringLiteral" ? p.key.value : void 0;
|
|
@@ -9673,7 +9749,35 @@ var TypeAnalyzer = class {
|
|
|
9673
9749
|
}
|
|
9674
9750
|
const read = this.expand(type);
|
|
9675
9751
|
if (read.kind === "unknown" && read.declared) this.reportUnknownAccess(object);
|
|
9676
|
-
|
|
9752
|
+
const optionalNil = link.optional === true && this.mayBeNil(inChain ?? full);
|
|
9753
|
+
return { type, shortCircuits: inChain !== void 0 || optionalNil };
|
|
9754
|
+
}
|
|
9755
|
+
/** Whether a value of `raw` can be nil — `includesNil`, and also the types
|
|
9756
|
+
* that do not say: `any`, `unknown`, an unconstrained type parameter. */
|
|
9757
|
+
mayBeNil(raw) {
|
|
9758
|
+
const t = this.expand(raw);
|
|
9759
|
+
switch (t.kind) {
|
|
9760
|
+
case "primitive":
|
|
9761
|
+
return t.name === "nil";
|
|
9762
|
+
case "any":
|
|
9763
|
+
case "unknown":
|
|
9764
|
+
return true;
|
|
9765
|
+
case "typeParam":
|
|
9766
|
+
return t.constraint === void 0 || this.mayBeNil(t.constraint);
|
|
9767
|
+
case "union":
|
|
9768
|
+
return t.types.some((m) => this.mayBeNil(m));
|
|
9769
|
+
case "never":
|
|
9770
|
+
case "literal":
|
|
9771
|
+
case "array":
|
|
9772
|
+
case "tuple":
|
|
9773
|
+
case "object":
|
|
9774
|
+
case "function":
|
|
9775
|
+
case "intersection":
|
|
9776
|
+
case "templateLiteral":
|
|
9777
|
+
return false;
|
|
9778
|
+
default:
|
|
9779
|
+
return true;
|
|
9780
|
+
}
|
|
9677
9781
|
}
|
|
9678
9782
|
/** Objects already reported as possibly nil: a loop body is visited more
|
|
9679
9783
|
* than once. */
|
|
@@ -10595,13 +10699,12 @@ var TypeAnalyzer = class {
|
|
|
10595
10699
|
computingAhead = /* @__PURE__ */ new Set();
|
|
10596
10700
|
declaredAhead(id) {
|
|
10597
10701
|
this.aheadDeclarations ??= this.indexAheadDeclarations();
|
|
10598
|
-
const
|
|
10599
|
-
if (!
|
|
10702
|
+
const statement = this.aheadDeclarations.get(id);
|
|
10703
|
+
if (!statement || this.computingAhead.has(id)) return void 0;
|
|
10600
10704
|
this.computingAhead.add(id);
|
|
10601
10705
|
const wasEmitting = this.emitDiagnostics;
|
|
10602
10706
|
this.emitDiagnostics = false;
|
|
10603
10707
|
try {
|
|
10604
|
-
const { statement, index } = found;
|
|
10605
10708
|
let type;
|
|
10606
10709
|
if (statement.type === "DeclareStatement") {
|
|
10607
10710
|
type = this.resolveType(statement.valueType);
|
|
@@ -10610,11 +10713,11 @@ var TypeAnalyzer = class {
|
|
|
10610
10713
|
} else if (statement.type === "ClassDeclaration") {
|
|
10611
10714
|
type = this.classValueType(statement);
|
|
10612
10715
|
} else if (statement.type === "VariableDeclaration") {
|
|
10613
|
-
const target = statement.
|
|
10716
|
+
const target = statement.name;
|
|
10614
10717
|
if (target.type === "IdentifierPattern" && target.typeAnnotation) {
|
|
10615
10718
|
type = this.resolveType(target.typeAnnotation);
|
|
10616
|
-
} else if (statement.init
|
|
10617
|
-
const value = this.infer(statement.init
|
|
10719
|
+
} else if (statement.init) {
|
|
10720
|
+
const value = this.infer(statement.init, /* @__PURE__ */ new Map());
|
|
10618
10721
|
type = statement.kind === "const" ? value : widen(value);
|
|
10619
10722
|
}
|
|
10620
10723
|
}
|
|
@@ -10632,11 +10735,10 @@ var TypeAnalyzer = class {
|
|
|
10632
10735
|
for (const statement of this.program.body.statements) {
|
|
10633
10736
|
const declaration = statement.type === "ExportStatement" ? statement.declaration : statement;
|
|
10634
10737
|
if (declaration.type !== "VariableDeclaration") continue;
|
|
10635
|
-
|
|
10636
|
-
|
|
10637
|
-
|
|
10638
|
-
|
|
10639
|
-
});
|
|
10738
|
+
const target = declaration.name;
|
|
10739
|
+
if (target.type !== "IdentifierPattern") continue;
|
|
10740
|
+
const id = this.bindingIdByName(target.name, target);
|
|
10741
|
+
if (id !== void 0) out.set(id, declaration);
|
|
10640
10742
|
}
|
|
10641
10743
|
const visit = (node) => {
|
|
10642
10744
|
if (!node || typeof node !== "object") return;
|
|
@@ -10647,11 +10749,11 @@ var TypeAnalyzer = class {
|
|
|
10647
10749
|
const record = node;
|
|
10648
10750
|
if (record.type === "ClassDeclaration" && record.name) {
|
|
10649
10751
|
const id = this.bindingIdByName(record.name.name, record.name);
|
|
10650
|
-
if (id !== void 0) out.set(id,
|
|
10752
|
+
if (id !== void 0) out.set(id, node);
|
|
10651
10753
|
}
|
|
10652
10754
|
if (record.type === "FunctionDeclaration" && record.name) {
|
|
10653
10755
|
const id = this.bindingIdByName(record.name.name, record.name);
|
|
10654
|
-
if (id !== void 0) out.set(id,
|
|
10756
|
+
if (id !== void 0) out.set(id, node);
|
|
10655
10757
|
}
|
|
10656
10758
|
for (const [key, value] of Object.entries(node)) {
|
|
10657
10759
|
if (key !== "line" && key !== "column" && value && typeof value === "object") visit(value);
|
|
@@ -10660,7 +10762,7 @@ var TypeAnalyzer = class {
|
|
|
10660
10762
|
visit(this.program.body);
|
|
10661
10763
|
for (const [name, statement] of this.deferredDeclares) {
|
|
10662
10764
|
const id = this.scopes.globalsByName.get(name);
|
|
10663
|
-
if (id !== void 0) out.set(id,
|
|
10765
|
+
if (id !== void 0) out.set(id, statement);
|
|
10664
10766
|
}
|
|
10665
10767
|
return out;
|
|
10666
10768
|
}
|