@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.cjs
CHANGED
|
@@ -969,10 +969,10 @@ var Parser = class {
|
|
|
969
969
|
expressionOr(stop) {
|
|
970
970
|
return this.attempt(() => this.parseExpression(), stop, (start, from) => this.errorExpression(start, from));
|
|
971
971
|
}
|
|
972
|
-
/** A comma-separated list of values
|
|
973
|
-
*
|
|
974
|
-
*
|
|
975
|
-
*
|
|
972
|
+
/** A comma-separated list of values where one belongs — a `return`'s, a
|
|
973
|
+
* declaration's, an assignment's — read whole, so that writing several
|
|
974
|
+
* is reported once and the rest still means something. A spread belongs
|
|
975
|
+
* in a call's arguments or an array, and is reported here too. */
|
|
976
976
|
expressionListOr(stop) {
|
|
977
977
|
const until = () => stop() || this.checkPunctuator(",");
|
|
978
978
|
const item = () => {
|
|
@@ -1564,7 +1564,7 @@ var Parser = class {
|
|
|
1564
1564
|
}
|
|
1565
1565
|
this.error("Expected 'const', 'let', 'function', 'class', 'type', 'default', '{' or '*' after 'export'");
|
|
1566
1566
|
}
|
|
1567
|
-
// `const x = ...` / `let
|
|
1567
|
+
// `const x = ...` / `let [a, b] = ...`.
|
|
1568
1568
|
// tilua has no `local` — `const` bindings are immutable, `let` mutable.
|
|
1569
1569
|
/** `kind` reads the leading word as that keyword (recovery's `local`). */
|
|
1570
1570
|
parseVariableDeclaration(as) {
|
|
@@ -1578,14 +1578,34 @@ var Parser = class {
|
|
|
1578
1578
|
while (this.matchPunctuator(",")) {
|
|
1579
1579
|
names.push(this.parseBindingTarget(true));
|
|
1580
1580
|
}
|
|
1581
|
-
let
|
|
1581
|
+
let values = [];
|
|
1582
1582
|
if (this.matchOperator("=")) {
|
|
1583
|
-
|
|
1583
|
+
values = this.expressionListOr(() => false);
|
|
1584
1584
|
} else if (kind === "const") {
|
|
1585
1585
|
if (!this.recover) this.error("'const' declaration requires an initializer");
|
|
1586
1586
|
this.softError("'const' declaration requires an initializer");
|
|
1587
1587
|
}
|
|
1588
|
-
|
|
1588
|
+
let name = names[0];
|
|
1589
|
+
let init = values[0];
|
|
1590
|
+
if (names.length > 1 || values.length > 1) {
|
|
1591
|
+
this.problemAt(start, `A declaration takes one value: take several from an array, '${kind} [a, b] = [x, y]'`);
|
|
1592
|
+
if (names.length > 1) name = this.namesAsPattern(names);
|
|
1593
|
+
if (values.length > 1) init = this.valuesAsArray(values);
|
|
1594
|
+
}
|
|
1595
|
+
return { type: "VariableDeclaration", kind, name, init, ...spanFrom(start, this.previous()) };
|
|
1596
|
+
}
|
|
1597
|
+
/** `a, b` written where one name goes, read as `[a, b]`. */
|
|
1598
|
+
namesAsPattern(names) {
|
|
1599
|
+
const elements = names.map((value) => ({
|
|
1600
|
+
type: "ArrayPatternElement",
|
|
1601
|
+
value,
|
|
1602
|
+
...spanFrom(value, value)
|
|
1603
|
+
}));
|
|
1604
|
+
return { type: "ArrayPattern", elements, ...spanFrom(names[0], names[names.length - 1]) };
|
|
1605
|
+
}
|
|
1606
|
+
/** `x, y` written where one value goes, read as `[x, y]`. */
|
|
1607
|
+
valuesAsArray(values) {
|
|
1608
|
+
return { type: "ArrayExpression", elements: values, ...spanFrom(values[0], values[values.length - 1]) };
|
|
1589
1609
|
}
|
|
1590
1610
|
parseIfStatement() {
|
|
1591
1611
|
const start = this.current();
|
|
@@ -2066,7 +2086,7 @@ var Parser = class {
|
|
|
2066
2086
|
argument = values[0];
|
|
2067
2087
|
if (values.length > 1) {
|
|
2068
2088
|
this.problemAt(start, "A function returns one value: return several as an array, 'return [a, b]'");
|
|
2069
|
-
argument =
|
|
2089
|
+
argument = this.valuesAsArray(values);
|
|
2070
2090
|
}
|
|
2071
2091
|
}
|
|
2072
2092
|
return { type: "ReturnStatement", argument, ...spanFrom(start, this.previous()) };
|
|
@@ -2092,28 +2112,15 @@ var Parser = class {
|
|
|
2092
2112
|
parseExpressionStatement() {
|
|
2093
2113
|
const start = this.current();
|
|
2094
2114
|
if (this.checkPunctuator("{") || this.checkPunctuator("[")) {
|
|
2095
|
-
const
|
|
2096
|
-
|
|
2097
|
-
];
|
|
2098
|
-
while (this.matchPunctuator(",")) {
|
|
2099
|
-
targets.push(this.parseAssignTarget());
|
|
2100
|
-
}
|
|
2101
|
-
this.expectOperator("=");
|
|
2102
|
-
const values = this.expressionListOr(() => false);
|
|
2103
|
-
return { type: "AssignmentStatement", targets, values, ...spanFrom(start, this.previous()) };
|
|
2115
|
+
const target = this.checkPunctuator("{") ? this.parseObjectPattern(true) : this.parseArrayPattern(true);
|
|
2116
|
+
return this.parseAssignmentRest(start, target);
|
|
2104
2117
|
}
|
|
2105
2118
|
const statementStart = this.cursor;
|
|
2106
2119
|
const errorsAtStart = this.errors.length;
|
|
2107
2120
|
const first = this.parsePrefixExpression();
|
|
2108
2121
|
if (this.checkOperator("=") || this.checkPunctuator(",")) {
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
targets.push(this.parseAssignTarget());
|
|
2112
|
-
}
|
|
2113
|
-
for (const target of targets) this.rejectOptionalTarget(target);
|
|
2114
|
-
this.expectOperator("=");
|
|
2115
|
-
const values = this.expressionListOr(() => false);
|
|
2116
|
-
return { type: "AssignmentStatement", targets, values, ...spanFrom(start, this.previous()) };
|
|
2122
|
+
this.rejectOptionalTarget(first);
|
|
2123
|
+
return this.parseAssignmentRest(start, first);
|
|
2117
2124
|
}
|
|
2118
2125
|
const t = this.current();
|
|
2119
2126
|
if (t.type === "Operator" && COMPOUND_ASSIGN_OPS.has(t.value)) {
|
|
@@ -2139,6 +2146,21 @@ var Parser = class {
|
|
|
2139
2146
|
}
|
|
2140
2147
|
return { type: "ExpressionStatement", expression, ...spanFrom(start, this.previous()) };
|
|
2141
2148
|
}
|
|
2149
|
+
/** From after an assignment's target: `= value`. Luau's `a, b = x, y`
|
|
2150
|
+
* is reported, and read as its first target taking its first value. */
|
|
2151
|
+
parseAssignmentRest(start, target) {
|
|
2152
|
+
let several = false;
|
|
2153
|
+
while (this.matchPunctuator(",")) {
|
|
2154
|
+
this.parseAssignTarget();
|
|
2155
|
+
several = true;
|
|
2156
|
+
}
|
|
2157
|
+
this.expectOperator("=");
|
|
2158
|
+
const values = this.expressionListOr(() => false);
|
|
2159
|
+
if (several || values.length > 1) {
|
|
2160
|
+
this.problemAt(start, "An assignment takes one value: take several from an array, '[a, b] = [x, y]'");
|
|
2161
|
+
}
|
|
2162
|
+
return { type: "AssignmentStatement", target, value: values[0], ...spanFrom(start, this.previous()) };
|
|
2163
|
+
}
|
|
2142
2164
|
// ============================================================
|
|
2143
2165
|
// Expressions
|
|
2144
2166
|
// ============================================================
|
|
@@ -2622,8 +2644,8 @@ var Parser = class {
|
|
|
2622
2644
|
startsSuperUse() {
|
|
2623
2645
|
return this.punctuatorAt(1, "(") || this.punctuatorAt(1, ".") && this.peek(2).type === "Identifier";
|
|
2624
2646
|
}
|
|
2625
|
-
/** After `...`, is there something to spread?
|
|
2626
|
-
*
|
|
2647
|
+
/** After `...`, is there something to spread? tilua has no bare `...`:
|
|
2648
|
+
* a varying number of arguments is a rest parameter, `...args: T[]`. */
|
|
2627
2649
|
startsSpread() {
|
|
2628
2650
|
const next = this.peek(1);
|
|
2629
2651
|
if (next.type === "Punctuator") {
|
|
@@ -2642,11 +2664,11 @@ var Parser = class {
|
|
|
2642
2664
|
const token = this.peek(ahead);
|
|
2643
2665
|
return token.type === "Punctuator" && token.value === value;
|
|
2644
2666
|
}
|
|
2645
|
-
/** An assignment target after the first
|
|
2646
|
-
*
|
|
2667
|
+
/** An assignment target after the first — Luau's `a, b = ...`, read only
|
|
2668
|
+
* to be reported: a prefix expression or a destructuring pattern. */
|
|
2647
2669
|
parseAssignTarget() {
|
|
2648
|
-
if (this.checkPunctuator("{")) return this.parseObjectPattern();
|
|
2649
|
-
if (this.checkPunctuator("[")) return this.parseArrayPattern();
|
|
2670
|
+
if (this.checkPunctuator("{")) return this.parseObjectPattern(true);
|
|
2671
|
+
if (this.checkPunctuator("[")) return this.parseArrayPattern(true);
|
|
2650
2672
|
return this.parsePrefixExpression();
|
|
2651
2673
|
}
|
|
2652
2674
|
/** Does a call's argument list start here? Lua's three forms: `(`, a
|
|
@@ -2825,13 +2847,17 @@ var Parser = class {
|
|
|
2825
2847
|
/** Parses a binding target. When `topLevel`, also consumes a trailing
|
|
2826
2848
|
* `<attr>` list (identifier only) and a `: Type` annotation — these are
|
|
2827
2849
|
* only valid at the outermost level of a `local` / parameter binding,
|
|
2828
|
-
* never nested inside another pattern.
|
|
2829
|
-
|
|
2850
|
+
* never nested inside another pattern. When `assign`, the pattern is a
|
|
2851
|
+
* destructuring assignment's (`[t[i], t[j]] = ...`), and a leaf is any
|
|
2852
|
+
* place a value can be assigned to: a name, a member or an index. */
|
|
2853
|
+
parseBindingTarget(topLevel, assign = false) {
|
|
2830
2854
|
let target;
|
|
2831
2855
|
if (this.checkPunctuator("{")) {
|
|
2832
|
-
target = this.parseObjectPattern();
|
|
2856
|
+
target = this.parseObjectPattern(assign);
|
|
2833
2857
|
} else if (this.checkPunctuator("[")) {
|
|
2834
|
-
target = this.parseArrayPattern();
|
|
2858
|
+
target = this.parseArrayPattern(assign);
|
|
2859
|
+
} else if (assign) {
|
|
2860
|
+
return this.parseAssignPatternLeaf();
|
|
2835
2861
|
} else {
|
|
2836
2862
|
const nameTok = this.expectIdentifier();
|
|
2837
2863
|
let attributes;
|
|
@@ -2853,10 +2879,25 @@ var Parser = class {
|
|
|
2853
2879
|
}
|
|
2854
2880
|
return target;
|
|
2855
2881
|
}
|
|
2856
|
-
|
|
2857
|
-
|
|
2882
|
+
/** A leaf of a destructuring assignment: `a`, `a.b` or `a[i]`. */
|
|
2883
|
+
parseAssignPatternLeaf() {
|
|
2884
|
+
const expression = this.parsePrefixExpression();
|
|
2885
|
+
if (expression.type === "Identifier") {
|
|
2886
|
+
return { type: "IdentifierPattern", name: expression.name, line: expression.line, column: expression.column };
|
|
2887
|
+
}
|
|
2888
|
+
if (expression.type === "MemberExpression" || expression.type === "IndexExpression") {
|
|
2889
|
+
this.rejectOptionalTarget(expression);
|
|
2890
|
+
return expression;
|
|
2891
|
+
}
|
|
2892
|
+
const err = new ParseError("Only a name, a member or an index can be assigned to", expression.line.start, expression.column.start);
|
|
2893
|
+
if (!this.recover) throw err;
|
|
2894
|
+
this.record(err);
|
|
2895
|
+
return { type: "IdentifierPattern", name: "", line: expression.line, column: expression.column };
|
|
2896
|
+
}
|
|
2897
|
+
parseObjectPattern(assign = false) {
|
|
2898
|
+
return this.inBrackets(() => this.parseObjectPatternInner(assign));
|
|
2858
2899
|
}
|
|
2859
|
-
parseObjectPatternInner() {
|
|
2900
|
+
parseObjectPatternInner(assign) {
|
|
2860
2901
|
const start = this.current();
|
|
2861
2902
|
this.expectPunctuator("{");
|
|
2862
2903
|
const properties = [];
|
|
@@ -2864,7 +2905,7 @@ var Parser = class {
|
|
|
2864
2905
|
while (!this.checkPunctuator("}")) {
|
|
2865
2906
|
if (this.checkOperator("...")) {
|
|
2866
2907
|
this.advance();
|
|
2867
|
-
rest = this.parseBindingTarget(false);
|
|
2908
|
+
rest = this.parseBindingTarget(false, assign);
|
|
2868
2909
|
break;
|
|
2869
2910
|
}
|
|
2870
2911
|
const propStart = this.current();
|
|
@@ -2877,17 +2918,17 @@ var Parser = class {
|
|
|
2877
2918
|
key = this.parseExpression();
|
|
2878
2919
|
this.expectPunctuator("]");
|
|
2879
2920
|
this.expectPunctuator(":");
|
|
2880
|
-
value = this.parseBindingTarget(false);
|
|
2921
|
+
value = this.parseBindingTarget(false, assign);
|
|
2881
2922
|
} else if (this.checkType("Literal") && this.current().kind === "string") {
|
|
2882
2923
|
const t = this.advance();
|
|
2883
2924
|
key = { type: "StringLiteral", value: t.value, raw: t.raw, ...spanFrom(t, t) };
|
|
2884
2925
|
this.expectPunctuator(":");
|
|
2885
|
-
value = this.parseBindingTarget(false);
|
|
2926
|
+
value = this.parseBindingTarget(false, assign);
|
|
2886
2927
|
} else {
|
|
2887
2928
|
const nameTok = this.expectIdentifier();
|
|
2888
2929
|
key = { type: "Identifier", name: nameTok.value, ...spanFrom(nameTok, nameTok) };
|
|
2889
2930
|
if (this.matchPunctuator(":")) {
|
|
2890
|
-
value = this.parseBindingTarget(false);
|
|
2931
|
+
value = this.parseBindingTarget(false, assign);
|
|
2891
2932
|
} else {
|
|
2892
2933
|
shorthand = true;
|
|
2893
2934
|
value = { type: "IdentifierPattern", name: nameTok.value, ...spanFrom(nameTok, nameTok) };
|
|
@@ -2910,10 +2951,10 @@ var Parser = class {
|
|
|
2910
2951
|
this.expectPunctuator("}");
|
|
2911
2952
|
return { type: "ObjectPattern", properties, rest, ...spanFrom(start, this.previous()) };
|
|
2912
2953
|
}
|
|
2913
|
-
parseArrayPattern() {
|
|
2914
|
-
return this.inBrackets(() => this.parseArrayPatternInner());
|
|
2954
|
+
parseArrayPattern(assign = false) {
|
|
2955
|
+
return this.inBrackets(() => this.parseArrayPatternInner(assign));
|
|
2915
2956
|
}
|
|
2916
|
-
parseArrayPatternInner() {
|
|
2957
|
+
parseArrayPatternInner(assign) {
|
|
2917
2958
|
const start = this.current();
|
|
2918
2959
|
this.expectPunctuator("[");
|
|
2919
2960
|
const elements = [];
|
|
@@ -2921,7 +2962,7 @@ var Parser = class {
|
|
|
2921
2962
|
while (!this.checkPunctuator("]")) {
|
|
2922
2963
|
if (this.checkOperator("...")) {
|
|
2923
2964
|
this.advance();
|
|
2924
|
-
rest = this.parseBindingTarget(false);
|
|
2965
|
+
rest = this.parseBindingTarget(false, assign);
|
|
2925
2966
|
break;
|
|
2926
2967
|
}
|
|
2927
2968
|
if (this.checkPunctuator(",")) {
|
|
@@ -2930,7 +2971,7 @@ var Parser = class {
|
|
|
2930
2971
|
continue;
|
|
2931
2972
|
}
|
|
2932
2973
|
const elStart = this.current();
|
|
2933
|
-
const value = this.parseBindingTarget(false);
|
|
2974
|
+
const value = this.parseBindingTarget(false, assign);
|
|
2934
2975
|
let def;
|
|
2935
2976
|
if (this.matchOperator("=")) def = this.parseExpression();
|
|
2936
2977
|
elements.push({ type: "ArrayPatternElement", value, default: def, ...spanFrom(elStart, this.previous()) });
|
|
@@ -3134,7 +3175,7 @@ var Parser = class {
|
|
|
3134
3175
|
};
|
|
3135
3176
|
})() : this.parseFunctionHead();
|
|
3136
3177
|
this.expectPunctuator("=>");
|
|
3137
|
-
const body = this.checkPunctuator("{") ? this.parseBraceBlock() : this.
|
|
3178
|
+
const body = this.checkPunctuator("{") ? this.parseBraceBlock() : this.parseArrowExpressionBody();
|
|
3138
3179
|
const func = {
|
|
3139
3180
|
type: "FunctionBody",
|
|
3140
3181
|
generics: head.generics,
|
|
@@ -3147,6 +3188,29 @@ var Parser = class {
|
|
|
3147
3188
|
};
|
|
3148
3189
|
return { type: "FunctionExpression", func, ...spanFrom(start, this.previous()) };
|
|
3149
3190
|
}
|
|
3191
|
+
/** `() => value` returns the value. `() => a = 1` and `() => n += 1` are
|
|
3192
|
+
* an assignment, which is a statement: the body is that
|
|
3193
|
+
* statement, and the function returns nothing. */
|
|
3194
|
+
parseArrowExpressionBody() {
|
|
3195
|
+
const start = this.cursor;
|
|
3196
|
+
const errors = this.errors.length;
|
|
3197
|
+
const expression = this.parseExpression(0);
|
|
3198
|
+
const t = this.current();
|
|
3199
|
+
const assigns = t.type === "Operator" && (t.value === "=" || COMPOUND_ASSIGN_OPS.has(t.value));
|
|
3200
|
+
if (!assigns) return this.returnOf(expression);
|
|
3201
|
+
this.cursor = start;
|
|
3202
|
+
this.errors.length = errors;
|
|
3203
|
+
const first = this.current();
|
|
3204
|
+
const target = this.parsePrefixExpression();
|
|
3205
|
+
this.rejectOptionalTarget(target);
|
|
3206
|
+
const opToken = this.current();
|
|
3207
|
+
const op = opToken.value;
|
|
3208
|
+
if (opToken.type !== "Operator" || op !== "=" && !COMPOUND_ASSIGN_OPS.has(op)) this.error("Expected '='");
|
|
3209
|
+
this.advance();
|
|
3210
|
+
const value = this.expressionOr(() => false);
|
|
3211
|
+
const statement = op === "=" ? { type: "AssignmentStatement", target, value, ...spanFrom(first, this.previous()) } : { type: "CompoundAssignmentStatement", operator: op, target, value, ...spanFrom(first, this.previous()) };
|
|
3212
|
+
return { type: "Block", statements: [statement], ...spanFrom(statement, statement) };
|
|
3213
|
+
}
|
|
3150
3214
|
/** A one-expression body: the value is what the function returns. */
|
|
3151
3215
|
returnOf(expression) {
|
|
3152
3216
|
const statement = {
|
|
@@ -4044,6 +4108,10 @@ var Analyzer = class {
|
|
|
4044
4108
|
this.checkConstAssign(id, t);
|
|
4045
4109
|
return;
|
|
4046
4110
|
}
|
|
4111
|
+
case "MemberExpression":
|
|
4112
|
+
case "IndexExpression":
|
|
4113
|
+
this.visitExpression(t, scope);
|
|
4114
|
+
return;
|
|
4047
4115
|
case "ObjectPattern":
|
|
4048
4116
|
for (const p of t.properties) {
|
|
4049
4117
|
if (p.computed) this.visitExpression(p.key, scope);
|
|
@@ -4078,10 +4146,11 @@ var Analyzer = class {
|
|
|
4078
4146
|
visitStatement(stmt, scope) {
|
|
4079
4147
|
switch (stmt.type) {
|
|
4080
4148
|
case "VariableDeclaration": {
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4149
|
+
if (stmt.init) this.visitExpression(stmt.init, scope);
|
|
4150
|
+
if (stmt.name.type !== "MemberExpression" && stmt.name.type !== "IndexExpression") {
|
|
4151
|
+
this.visitType(stmt.name.typeAnnotation, scope);
|
|
4152
|
+
}
|
|
4153
|
+
this.declarePattern(scope, stmt.name, "local", scope, stmt.kind === "const");
|
|
4085
4154
|
return;
|
|
4086
4155
|
}
|
|
4087
4156
|
case "FunctionDeclaration": {
|
|
@@ -4115,16 +4184,15 @@ var Analyzer = class {
|
|
|
4115
4184
|
return;
|
|
4116
4185
|
}
|
|
4117
4186
|
case "AssignmentStatement": {
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
}
|
|
4187
|
+
this.visitExpression(stmt.value, scope);
|
|
4188
|
+
const target = stmt.target;
|
|
4189
|
+
if (target.type === "Identifier") {
|
|
4190
|
+
this.referenceAsAssignmentTarget(scope, target);
|
|
4191
|
+
} else if (target.type === "ObjectPattern" || target.type === "ArrayPattern") {
|
|
4192
|
+
this.assignPattern(scope, target);
|
|
4193
|
+
} else {
|
|
4194
|
+
this.visitExpression(target, scope);
|
|
4195
|
+
this.checkModuleWrite(target);
|
|
4128
4196
|
}
|
|
4129
4197
|
return;
|
|
4130
4198
|
}
|
|
@@ -5448,7 +5516,7 @@ function moduleExports(program, scopes, types, resolveModule) {
|
|
|
5448
5516
|
params: declaration.typeParams.map((g) => g.name)
|
|
5449
5517
|
});
|
|
5450
5518
|
}
|
|
5451
|
-
} else
|
|
5519
|
+
} else exportPattern(declaration.name);
|
|
5452
5520
|
} else if (stmt.type === "ExportTypeAliasStatement") {
|
|
5453
5521
|
const name = stmt.alias.name.name;
|
|
5454
5522
|
const type = types.aliases.get(name);
|
|
@@ -5687,12 +5755,10 @@ function assignedFields(block) {
|
|
|
5687
5755
|
const names = /* @__PURE__ */ new Set();
|
|
5688
5756
|
walkNodes(block, (node) => {
|
|
5689
5757
|
const record = node;
|
|
5690
|
-
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
|
|
5694
|
-
names.add(member.property.name);
|
|
5695
|
-
}
|
|
5758
|
+
if (record.type !== "AssignmentStatement" && record.type !== "CompoundAssignmentStatement") return;
|
|
5759
|
+
const member = record.target;
|
|
5760
|
+
if (member.type === "MemberExpression" && member.object?.type === "Identifier" && member.object.name === "this" && member.property?.name) {
|
|
5761
|
+
names.add(member.property.name);
|
|
5696
5762
|
}
|
|
5697
5763
|
});
|
|
5698
5764
|
return names;
|
|
@@ -6168,12 +6234,10 @@ var TypeAnalyzer = class {
|
|
|
6168
6234
|
classDisplayNames = /* @__PURE__ */ new WeakMap();
|
|
6169
6235
|
/** `const Name = class ... end` — the name the class will be known by. */
|
|
6170
6236
|
nameClassExpressions(stmt) {
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
}
|
|
6176
|
-
});
|
|
6237
|
+
const value = stmt.init;
|
|
6238
|
+
if (stmt.name.type === "IdentifierPattern" && value?.type === "ClassExpression" && !value.name) {
|
|
6239
|
+
this.classDisplayNames.set(value, stmt.name.name);
|
|
6240
|
+
}
|
|
6177
6241
|
}
|
|
6178
6242
|
classTypeParams(stmt) {
|
|
6179
6243
|
return stmt.type === "ClassDeclaration" ? stmt.typeParams : [];
|
|
@@ -6502,6 +6566,14 @@ var TypeAnalyzer = class {
|
|
|
6502
6566
|
report(stmt.superclass, known ? `'${stmt.superclass.name}' is not a class; a class can only extend another class` : `Cannot find class '${stmt.superclass.name}'`);
|
|
6503
6567
|
}
|
|
6504
6568
|
}
|
|
6569
|
+
this.withClass(stmt, () => this.withTypeParams(this.classTypeParams(stmt), () => {
|
|
6570
|
+
this.withSelfType(this.selfTypeOf(stmt), () => {
|
|
6571
|
+
for (const member of stmt.members) {
|
|
6572
|
+
if (member.type !== "ClassMethod" || !member.signatures) continue;
|
|
6573
|
+
for (const signature of member.signatures) this.checkOverload(member.func, signature);
|
|
6574
|
+
}
|
|
6575
|
+
});
|
|
6576
|
+
}));
|
|
6505
6577
|
for (const member of stmt.members) {
|
|
6506
6578
|
if (member.type === "ClassConstructor") continue;
|
|
6507
6579
|
if (CLASS_RESERVED.has(member.name.name)) {
|
|
@@ -7456,35 +7528,30 @@ var TypeAnalyzer = class {
|
|
|
7456
7528
|
switch (stmt.type) {
|
|
7457
7529
|
case "VariableDeclaration": {
|
|
7458
7530
|
this.nameClassExpressions(stmt);
|
|
7459
|
-
|
|
7460
|
-
|
|
7461
|
-
|
|
7462
|
-
|
|
7463
|
-
}
|
|
7464
|
-
const
|
|
7465
|
-
this.
|
|
7466
|
-
|
|
7467
|
-
|
|
7468
|
-
|
|
7469
|
-
|
|
7470
|
-
|
|
7471
|
-
|
|
7472
|
-
|
|
7473
|
-
|
|
7474
|
-
message: `Type '${briefType(inferred)}' is not assignable to '${briefType(declared)}'` + this.explainMismatch(inferred, declared)
|
|
7475
|
-
});
|
|
7476
|
-
} else if (declared.kind !== "any") {
|
|
7477
|
-
this.reportExcessProperties(source, declared);
|
|
7478
|
-
}
|
|
7479
|
-
}
|
|
7480
|
-
const mode = this.initIsAsConst(source) ? "asconst" : !isFreshLiteralExpr(source) ? "keep" : stmt.kind === "const" ? "const" : "widen";
|
|
7481
|
-
this.bindPattern(target, inferred, env, mode);
|
|
7482
|
-
if (stmt.kind === "const") {
|
|
7483
|
-
this.correlateDestructuring(target, inferred, env);
|
|
7484
|
-
this.correlateIndexed(target, source, env);
|
|
7485
|
-
this.aliasReference(target, source);
|
|
7531
|
+
const target = stmt.name;
|
|
7532
|
+
const source = stmt.init;
|
|
7533
|
+
if (target.type === "IdentifierPattern" && target.typeAnnotation && source) {
|
|
7534
|
+
this.applyContext(source, this.resolveType(target.typeAnnotation));
|
|
7535
|
+
}
|
|
7536
|
+
const inferred = source ? this.infer(source, env) : nilType;
|
|
7537
|
+
if (this.emitDiagnostics && target.type === "IdentifierPattern" && target.typeAnnotation && source) {
|
|
7538
|
+
const declared = this.resolveType(target.typeAnnotation);
|
|
7539
|
+
if (declared.kind !== "any" && !this.namesNothing(declared) && !this.fitsAnnotation(source, declared, inferred, env)) {
|
|
7540
|
+
this.diagnostics.push({
|
|
7541
|
+
node: stmt,
|
|
7542
|
+
message: `Type '${briefType(inferred)}' is not assignable to '${briefType(declared)}'` + this.explainMismatch(inferred, declared)
|
|
7543
|
+
});
|
|
7544
|
+
} else if (declared.kind !== "any") {
|
|
7545
|
+
this.reportExcessProperties(source, declared);
|
|
7486
7546
|
}
|
|
7487
|
-
}
|
|
7547
|
+
}
|
|
7548
|
+
const mode = this.initIsAsConst(source) ? "asconst" : !isFreshLiteralExpr(source) ? "keep" : stmt.kind === "const" ? "const" : "widen";
|
|
7549
|
+
this.bindPattern(target, inferred, env, mode);
|
|
7550
|
+
if (stmt.kind === "const") {
|
|
7551
|
+
this.correlateDestructuring(target, inferred, env);
|
|
7552
|
+
this.correlateIndexed(target, source, env);
|
|
7553
|
+
this.aliasReference(target, source);
|
|
7554
|
+
}
|
|
7488
7555
|
return;
|
|
7489
7556
|
}
|
|
7490
7557
|
case "ClassDeclaration": {
|
|
@@ -7541,48 +7608,41 @@ var TypeAnalyzer = class {
|
|
|
7541
7608
|
return;
|
|
7542
7609
|
}
|
|
7543
7610
|
case "AssignmentStatement": {
|
|
7544
|
-
stmt.
|
|
7545
|
-
|
|
7546
|
-
|
|
7547
|
-
|
|
7548
|
-
|
|
7549
|
-
|
|
7550
|
-
|
|
7551
|
-
|
|
7552
|
-
|
|
7553
|
-
|
|
7554
|
-
|
|
7555
|
-
|
|
7556
|
-
|
|
7557
|
-
|
|
7558
|
-
|
|
7559
|
-
|
|
7560
|
-
|
|
7561
|
-
|
|
7562
|
-
|
|
7563
|
-
|
|
7564
|
-
|
|
7565
|
-
const declared = this.bindingType.get(id);
|
|
7566
|
-
if (this.emitDiagnostics && !isAssignable(next, declared) && declared.kind !== "any") {
|
|
7567
|
-
this.diagnostics.push({
|
|
7568
|
-
node: stmt,
|
|
7569
|
-
message: `Type '${briefType(next)}' is not assignable to '${briefType(declared)}'` + this.explainMismatch(next, declared)
|
|
7570
|
-
});
|
|
7571
|
-
}
|
|
7572
|
-
this.setBinding(env, id, narrowTo(declared, next));
|
|
7573
|
-
} else {
|
|
7574
|
-
this.setBinding(env, id, next);
|
|
7575
|
-
this.bindingType.set(id, union([this.bindingType.get(id) ?? next, next]));
|
|
7611
|
+
const target = stmt.target;
|
|
7612
|
+
const source = stmt.value;
|
|
7613
|
+
if (target.type === "MemberExpression" || target.type === "IndexExpression") {
|
|
7614
|
+
this.applyContext(source, this.infer(target, env));
|
|
7615
|
+
} else if (target.type === "Identifier") {
|
|
7616
|
+
const id = this.bindingIdOf(target);
|
|
7617
|
+
if (id !== void 0 && this.annotated.has(id)) this.applyContext(source, this.bindingType.get(id));
|
|
7618
|
+
}
|
|
7619
|
+
const vt = this.infer(source, env);
|
|
7620
|
+
if (target.type === "Identifier") {
|
|
7621
|
+
const id = this.bindingIdOf(target);
|
|
7622
|
+
if (id !== void 0) {
|
|
7623
|
+
this.uncorrelate(id);
|
|
7624
|
+
const next = isFreshLiteralExpr(source) ? widen(vt) : vt;
|
|
7625
|
+
if (this.annotated.has(id)) {
|
|
7626
|
+
const declared = this.bindingType.get(id);
|
|
7627
|
+
if (this.emitDiagnostics && !isAssignable(next, declared) && declared.kind !== "any") {
|
|
7628
|
+
this.diagnostics.push({
|
|
7629
|
+
node: stmt,
|
|
7630
|
+
message: `Type '${briefType(next)}' is not assignable to '${briefType(declared)}'` + this.explainMismatch(next, declared)
|
|
7631
|
+
});
|
|
7576
7632
|
}
|
|
7633
|
+
this.setBinding(env, id, narrowTo(declared, next));
|
|
7634
|
+
} else {
|
|
7635
|
+
this.setBinding(env, id, next);
|
|
7636
|
+
this.bindingType.set(id, union([this.bindingType.get(id) ?? next, next]));
|
|
7577
7637
|
}
|
|
7578
|
-
} else if (target.type === "MemberExpression" || target.type === "IndexExpression") {
|
|
7579
|
-
this.infer(target, env);
|
|
7580
|
-
this.checkReadonlyAssign(target, env);
|
|
7581
|
-
this.assignToRef(target, isFreshLiteralExpr(source) ? widen(vt) : vt, env);
|
|
7582
|
-
} else if (target.type === "ObjectPattern" || target.type === "ArrayPattern") {
|
|
7583
|
-
this.reassignPattern(target, vt, env);
|
|
7584
7638
|
}
|
|
7585
|
-
})
|
|
7639
|
+
} else if (target.type === "MemberExpression" || target.type === "IndexExpression") {
|
|
7640
|
+
this.infer(target, env);
|
|
7641
|
+
this.checkReadonlyAssign(target, env);
|
|
7642
|
+
this.assignToRef(target, isFreshLiteralExpr(source) ? widen(vt) : vt, env);
|
|
7643
|
+
} else if (target.type === "ObjectPattern" || target.type === "ArrayPattern") {
|
|
7644
|
+
this.reassignPattern(target, vt, env);
|
|
7645
|
+
}
|
|
7586
7646
|
return;
|
|
7587
7647
|
}
|
|
7588
7648
|
case "CompoundAssignmentStatement":
|
|
@@ -7746,55 +7806,6 @@ var TypeAnalyzer = class {
|
|
|
7746
7806
|
return;
|
|
7747
7807
|
}
|
|
7748
7808
|
}
|
|
7749
|
-
/** Flatten an expression list into the values it actually produces.
|
|
7750
|
-
*
|
|
7751
|
-
* Lua's adjustment rule: every expression but the last contributes one
|
|
7752
|
-
* value, and the last contributes all of its values if it is a call or
|
|
7753
|
-
* `...`. That is what makes `local ok, err = pcall(f)` work, and it is
|
|
7754
|
-
* why `local x = f()` takes only the first value.
|
|
7755
|
-
*
|
|
7756
|
-
* `sources` maps each produced value back to the expression it came from
|
|
7757
|
-
* (undefined for the 2nd and later values of a multi-value call), so the
|
|
7758
|
-
* caller can still do contextual typing against the written expression. */
|
|
7759
|
-
valueList(exprs, env) {
|
|
7760
|
-
const types = [];
|
|
7761
|
-
const sources = [];
|
|
7762
|
-
exprs.forEach((e, i) => {
|
|
7763
|
-
const t = this.infer(e, env);
|
|
7764
|
-
const last = i === exprs.length - 1;
|
|
7765
|
-
if (e.type === "SpreadElement") {
|
|
7766
|
-
const held = this.typeOf.get(e.argument);
|
|
7767
|
-
const expanded = held && this.expand(held);
|
|
7768
|
-
if (expanded?.kind === "tuple") {
|
|
7769
|
-
for (const element of expanded.elements) {
|
|
7770
|
-
types.push(element);
|
|
7771
|
-
sources.push(e);
|
|
7772
|
-
}
|
|
7773
|
-
return;
|
|
7774
|
-
}
|
|
7775
|
-
types.push(t);
|
|
7776
|
-
sources.push(e);
|
|
7777
|
-
return;
|
|
7778
|
-
}
|
|
7779
|
-
void last;
|
|
7780
|
-
types.push(t);
|
|
7781
|
-
sources.push(e);
|
|
7782
|
-
});
|
|
7783
|
-
return { types, sources };
|
|
7784
|
-
}
|
|
7785
|
-
/** `const a, b = x, y` pairs names with values, one each. A call is one
|
|
7786
|
-
* value — several come back as an array — so `const a, b = f()` is a
|
|
7787
|
-
* name short of a value, and says how to take them apart. */
|
|
7788
|
-
checkValueCount(node, names, values, types) {
|
|
7789
|
-
if (!this.emitDiagnostics || !values.length || types.length >= names) return;
|
|
7790
|
-
const last = values[values.length - 1];
|
|
7791
|
-
const lastType = types[types.length - 1] && this.expand(types[types.length - 1]);
|
|
7792
|
-
const call = last.type === "CallExpression" || last.type === "MethodCallExpression";
|
|
7793
|
-
this.diagnostics.push({
|
|
7794
|
-
node,
|
|
7795
|
-
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`
|
|
7796
|
-
});
|
|
7797
|
-
}
|
|
7798
7809
|
/** Run `visit` with a fresh place to collect `break` states, and return
|
|
7799
7810
|
* what it collected. */
|
|
7800
7811
|
withBreakScope(visit) {
|
|
@@ -8069,7 +8080,7 @@ var TypeAnalyzer = class {
|
|
|
8069
8080
|
/** Synthesize a type from a destructuring pattern used without an
|
|
8070
8081
|
* annotation (`function f({ a, b = 1 })`). */
|
|
8071
8082
|
patternToType(target, env) {
|
|
8072
|
-
const leaf = (v, def) => v.type
|
|
8083
|
+
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;
|
|
8073
8084
|
if (target.type === "ObjectPattern") {
|
|
8074
8085
|
const entries = [];
|
|
8075
8086
|
for (const p of target.properties) {
|
|
@@ -8475,6 +8486,7 @@ var TypeAnalyzer = class {
|
|
|
8475
8486
|
* can actually be. An annotation, a pattern or a default still wins. */
|
|
8476
8487
|
paramsFromSignatures(func, signatures) {
|
|
8477
8488
|
if (!signatures?.length) return;
|
|
8489
|
+
for (const signature of signatures) this.checkOverload(func, signature);
|
|
8478
8490
|
const resolved = signatures.map((sig) => this.signatureToFnType(sig));
|
|
8479
8491
|
func.params.forEach((param, i) => {
|
|
8480
8492
|
if (param.typeAnnotation || param.pattern || param.default) return;
|
|
@@ -8488,6 +8500,64 @@ var TypeAnalyzer = class {
|
|
|
8488
8500
|
if (candidates.length) this.contextualParams.set(param, union(candidates));
|
|
8489
8501
|
});
|
|
8490
8502
|
}
|
|
8503
|
+
/** The implementation is what runs for every signature of an overload
|
|
8504
|
+
* set, so each signature must be one it can serve: no parameter it does
|
|
8505
|
+
* not have, no fewer arguments than it requires, no argument type it does
|
|
8506
|
+
* not accept, and a return it can give. Stricter than TypeScript, which
|
|
8507
|
+
* lets a signature name parameters the implementation never reads. */
|
|
8508
|
+
checkOverload(func, signature) {
|
|
8509
|
+
if (!this.emitDiagnostics) return;
|
|
8510
|
+
const node = signature;
|
|
8511
|
+
const report = (message) => {
|
|
8512
|
+
this.diagnostics.push({ node, message });
|
|
8513
|
+
};
|
|
8514
|
+
const own = (params) => params.filter((p, i) => !p.rest && !(i === 0 && !p.typeAnnotation && (p.name === "self" || p.name === "this")));
|
|
8515
|
+
const implementation = own(func.params);
|
|
8516
|
+
const offered = own(signature.params);
|
|
8517
|
+
const implementationRest = func.params.some((p) => p.rest);
|
|
8518
|
+
const signatureRest = signature.params.some((p) => p.rest);
|
|
8519
|
+
const label = (p) => p.pattern ? "a destructured parameter" : `'${p.name}'`;
|
|
8520
|
+
if (!implementationRest) {
|
|
8521
|
+
const extra = offered[implementation.length];
|
|
8522
|
+
if (extra) {
|
|
8523
|
+
report(`This overload takes parameter ${label(extra)}, which the implementation does not have: it takes ${implementation.length} parameter${implementation.length === 1 ? "" : "s"}`);
|
|
8524
|
+
return;
|
|
8525
|
+
}
|
|
8526
|
+
if (signatureRest) {
|
|
8527
|
+
report("This overload takes a rest parameter, which the implementation does not have");
|
|
8528
|
+
return;
|
|
8529
|
+
}
|
|
8530
|
+
}
|
|
8531
|
+
if (!signatureRest) {
|
|
8532
|
+
let required = 0;
|
|
8533
|
+
implementation.forEach((p, i) => {
|
|
8534
|
+
if (!p.optional && p.default === void 0) required = i + 1;
|
|
8535
|
+
});
|
|
8536
|
+
if (offered.length < required) {
|
|
8537
|
+
report(`The implementation requires ${required} argument${required === 1 ? "" : "s"}, and this overload passes at most ${offered.length}`);
|
|
8538
|
+
return;
|
|
8539
|
+
}
|
|
8540
|
+
}
|
|
8541
|
+
if (signature.generics.length || func.generics.length) return;
|
|
8542
|
+
for (let i = 0; i < offered.length && i < implementation.length; i++) {
|
|
8543
|
+
const target = implementation[i];
|
|
8544
|
+
if (!target.typeAnnotation && target.default === void 0) continue;
|
|
8545
|
+
let accepted = this.paramType(target, /* @__PURE__ */ new Map());
|
|
8546
|
+
if (target.default !== void 0) accepted = optional(accepted);
|
|
8547
|
+
const given = this.paramType(offered[i], /* @__PURE__ */ new Map());
|
|
8548
|
+
if (!isAssignable(given, accepted)) {
|
|
8549
|
+
report(`Parameter ${label(offered[i])} of this overload is '${briefType(given)}', which the implementation's '${briefType(accepted)}' does not accept`);
|
|
8550
|
+
return;
|
|
8551
|
+
}
|
|
8552
|
+
}
|
|
8553
|
+
if (signature.returnType && func.returnType) {
|
|
8554
|
+
const promised = this.resolveType(signature.returnType);
|
|
8555
|
+
const returned = this.resolveType(func.returnType);
|
|
8556
|
+
if (!isAssignable(promised, returned) && !isAssignable(returned, promised)) {
|
|
8557
|
+
report(`This overload returns '${briefType(promised)}', which the implementation's '${briefType(returned)}' cannot be`);
|
|
8558
|
+
}
|
|
8559
|
+
}
|
|
8560
|
+
}
|
|
8491
8561
|
signatureToFnType(sig) {
|
|
8492
8562
|
const names = sig.generics.map((g) => g.name);
|
|
8493
8563
|
const record = (type) => {
|
|
@@ -8912,6 +8982,12 @@ var TypeAnalyzer = class {
|
|
|
8912
8982
|
}
|
|
8913
8983
|
return;
|
|
8914
8984
|
}
|
|
8985
|
+
case "MemberExpression":
|
|
8986
|
+
case "IndexExpression":
|
|
8987
|
+
this.infer(target, env);
|
|
8988
|
+
this.checkReadonlyAssign(target, env);
|
|
8989
|
+
this.assignToRef(target, widen(valueType), env);
|
|
8990
|
+
return;
|
|
8915
8991
|
case "ObjectPattern": {
|
|
8916
8992
|
for (const p of target.properties) {
|
|
8917
8993
|
const key = !p.computed && p.key.type === "Identifier" ? p.key.name : !p.computed && p.key.type === "StringLiteral" ? p.key.value : void 0;
|
|
@@ -9778,7 +9854,35 @@ var TypeAnalyzer = class {
|
|
|
9778
9854
|
}
|
|
9779
9855
|
const read = this.expand(type);
|
|
9780
9856
|
if (read.kind === "unknown" && read.declared) this.reportUnknownAccess(object);
|
|
9781
|
-
|
|
9857
|
+
const optionalNil = link.optional === true && this.mayBeNil(inChain ?? full);
|
|
9858
|
+
return { type, shortCircuits: inChain !== void 0 || optionalNil };
|
|
9859
|
+
}
|
|
9860
|
+
/** Whether a value of `raw` can be nil — `includesNil`, and also the types
|
|
9861
|
+
* that do not say: `any`, `unknown`, an unconstrained type parameter. */
|
|
9862
|
+
mayBeNil(raw) {
|
|
9863
|
+
const t = this.expand(raw);
|
|
9864
|
+
switch (t.kind) {
|
|
9865
|
+
case "primitive":
|
|
9866
|
+
return t.name === "nil";
|
|
9867
|
+
case "any":
|
|
9868
|
+
case "unknown":
|
|
9869
|
+
return true;
|
|
9870
|
+
case "typeParam":
|
|
9871
|
+
return t.constraint === void 0 || this.mayBeNil(t.constraint);
|
|
9872
|
+
case "union":
|
|
9873
|
+
return t.types.some((m) => this.mayBeNil(m));
|
|
9874
|
+
case "never":
|
|
9875
|
+
case "literal":
|
|
9876
|
+
case "array":
|
|
9877
|
+
case "tuple":
|
|
9878
|
+
case "object":
|
|
9879
|
+
case "function":
|
|
9880
|
+
case "intersection":
|
|
9881
|
+
case "templateLiteral":
|
|
9882
|
+
return false;
|
|
9883
|
+
default:
|
|
9884
|
+
return true;
|
|
9885
|
+
}
|
|
9782
9886
|
}
|
|
9783
9887
|
/** Objects already reported as possibly nil: a loop body is visited more
|
|
9784
9888
|
* than once. */
|
|
@@ -10700,13 +10804,12 @@ var TypeAnalyzer = class {
|
|
|
10700
10804
|
computingAhead = /* @__PURE__ */ new Set();
|
|
10701
10805
|
declaredAhead(id) {
|
|
10702
10806
|
this.aheadDeclarations ??= this.indexAheadDeclarations();
|
|
10703
|
-
const
|
|
10704
|
-
if (!
|
|
10807
|
+
const statement = this.aheadDeclarations.get(id);
|
|
10808
|
+
if (!statement || this.computingAhead.has(id)) return void 0;
|
|
10705
10809
|
this.computingAhead.add(id);
|
|
10706
10810
|
const wasEmitting = this.emitDiagnostics;
|
|
10707
10811
|
this.emitDiagnostics = false;
|
|
10708
10812
|
try {
|
|
10709
|
-
const { statement, index } = found;
|
|
10710
10813
|
let type;
|
|
10711
10814
|
if (statement.type === "DeclareStatement") {
|
|
10712
10815
|
type = this.resolveType(statement.valueType);
|
|
@@ -10715,11 +10818,11 @@ var TypeAnalyzer = class {
|
|
|
10715
10818
|
} else if (statement.type === "ClassDeclaration") {
|
|
10716
10819
|
type = this.classValueType(statement);
|
|
10717
10820
|
} else if (statement.type === "VariableDeclaration") {
|
|
10718
|
-
const target = statement.
|
|
10821
|
+
const target = statement.name;
|
|
10719
10822
|
if (target.type === "IdentifierPattern" && target.typeAnnotation) {
|
|
10720
10823
|
type = this.resolveType(target.typeAnnotation);
|
|
10721
|
-
} else if (statement.init
|
|
10722
|
-
const value = this.infer(statement.init
|
|
10824
|
+
} else if (statement.init) {
|
|
10825
|
+
const value = this.infer(statement.init, /* @__PURE__ */ new Map());
|
|
10723
10826
|
type = statement.kind === "const" ? value : widen(value);
|
|
10724
10827
|
}
|
|
10725
10828
|
}
|
|
@@ -10737,11 +10840,10 @@ var TypeAnalyzer = class {
|
|
|
10737
10840
|
for (const statement of this.program.body.statements) {
|
|
10738
10841
|
const declaration = statement.type === "ExportStatement" ? statement.declaration : statement;
|
|
10739
10842
|
if (declaration.type !== "VariableDeclaration") continue;
|
|
10740
|
-
|
|
10741
|
-
|
|
10742
|
-
|
|
10743
|
-
|
|
10744
|
-
});
|
|
10843
|
+
const target = declaration.name;
|
|
10844
|
+
if (target.type !== "IdentifierPattern") continue;
|
|
10845
|
+
const id = this.bindingIdByName(target.name, target);
|
|
10846
|
+
if (id !== void 0) out.set(id, declaration);
|
|
10745
10847
|
}
|
|
10746
10848
|
const visit = (node) => {
|
|
10747
10849
|
if (!node || typeof node !== "object") return;
|
|
@@ -10752,11 +10854,11 @@ var TypeAnalyzer = class {
|
|
|
10752
10854
|
const record = node;
|
|
10753
10855
|
if (record.type === "ClassDeclaration" && record.name) {
|
|
10754
10856
|
const id = this.bindingIdByName(record.name.name, record.name);
|
|
10755
|
-
if (id !== void 0) out.set(id,
|
|
10857
|
+
if (id !== void 0) out.set(id, node);
|
|
10756
10858
|
}
|
|
10757
10859
|
if (record.type === "FunctionDeclaration" && record.name) {
|
|
10758
10860
|
const id = this.bindingIdByName(record.name.name, record.name);
|
|
10759
|
-
if (id !== void 0) out.set(id,
|
|
10861
|
+
if (id !== void 0) out.set(id, node);
|
|
10760
10862
|
}
|
|
10761
10863
|
for (const [key, value] of Object.entries(node)) {
|
|
10762
10864
|
if (key !== "line" && key !== "column" && value && typeof value === "object") visit(value);
|
|
@@ -10765,7 +10867,7 @@ var TypeAnalyzer = class {
|
|
|
10765
10867
|
visit(this.program.body);
|
|
10766
10868
|
for (const [name, statement] of this.deferredDeclares) {
|
|
10767
10869
|
const id = this.scopes.globalsByName.get(name);
|
|
10768
|
-
if (id !== void 0) out.set(id,
|
|
10870
|
+
if (id !== void 0) out.set(id, statement);
|
|
10769
10871
|
}
|
|
10770
10872
|
return out;
|
|
10771
10873
|
}
|