@thigasdevelopment/luam 0.19.12 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lua/async.lua +6 -6
- package/lua/class.lua +239 -211
- package/lua/development-logs-client.lua +15 -9
- package/lua/development-logs-server.lua +41 -44
- package/lua/math.lua +21 -18
- package/lua/promise.lua +446 -0
- package/lua/string.lua +78 -62
- package/lua/table.lua +57 -49
- package/lua/threads.lua +326 -269
- package/lua/validate.lua +230 -185
- package/luam.mjs +969 -134
- package/package.json +1 -1
package/luam.mjs
CHANGED
|
@@ -3161,6 +3161,7 @@ var DEFAULT_COMPILER_OPTIONS = {
|
|
|
3161
3161
|
oop: false,
|
|
3162
3162
|
noUnusedLocals: false,
|
|
3163
3163
|
noUnusedParameters: false,
|
|
3164
|
+
noImplicitGlobals: false,
|
|
3164
3165
|
warningsAsErrors: false
|
|
3165
3166
|
};
|
|
3166
3167
|
var DEFAULT_SOURCE_MAPPING = {
|
|
@@ -3608,6 +3609,8 @@ var LUA_KEYWORDS = /* @__PURE__ */ new Set([
|
|
|
3608
3609
|
"while"
|
|
3609
3610
|
]);
|
|
3610
3611
|
var LUAM_KEYWORDS = /* @__PURE__ */ new Set([
|
|
3612
|
+
"async",
|
|
3613
|
+
"await",
|
|
3611
3614
|
"class",
|
|
3612
3615
|
"constructor",
|
|
3613
3616
|
"continue",
|
|
@@ -3838,7 +3841,21 @@ function parseTypeName(stream) {
|
|
|
3838
3841
|
}
|
|
3839
3842
|
return { kind: "type-name", name: token.value, typeArguments, position: token.position };
|
|
3840
3843
|
}
|
|
3844
|
+
function parseOptionalParameterType(stream) {
|
|
3845
|
+
const name = stream.next().value;
|
|
3846
|
+
const marker = stream.next();
|
|
3847
|
+
stream.next();
|
|
3848
|
+
const annotation = parseTypeAnnotation(stream);
|
|
3849
|
+
if (annotation.kind === "type-optional") {
|
|
3850
|
+
stream.report("parse-redundant-optional", 'The marker on the name already allows "nil". Remove the "?" after the type.', annotation.position);
|
|
3851
|
+
}
|
|
3852
|
+
const element = annotation.kind === "type-optional" ? annotation.element : annotation;
|
|
3853
|
+
return { name, annotation: { kind: "type-optional", element, position: marker.position } };
|
|
3854
|
+
}
|
|
3841
3855
|
function parseParameterType(stream) {
|
|
3856
|
+
if (stream.check("identifier") && stream.checkAhead(1, "operator", "?") && stream.checkAhead(2, "punctuation", ":")) {
|
|
3857
|
+
return parseOptionalParameterType(stream);
|
|
3858
|
+
}
|
|
3842
3859
|
let name = null;
|
|
3843
3860
|
if (stream.check("identifier") && stream.checkAhead(1, "punctuation", ":")) {
|
|
3844
3861
|
name = stream.next().value;
|
|
@@ -3889,7 +3906,7 @@ function parseGroupedType(stream) {
|
|
|
3889
3906
|
return { kind: "type-tuple", elements, position: position2 };
|
|
3890
3907
|
}
|
|
3891
3908
|
function parseObjectMember(stream) {
|
|
3892
|
-
const token = stream.
|
|
3909
|
+
const token = stream.expectMemberKey();
|
|
3893
3910
|
const annotation = parseNamedAnnotation(stream, "field");
|
|
3894
3911
|
if (annotation === null) {
|
|
3895
3912
|
throw stream.error(`Key "${token.value}" of an object type requires a type annotation.`, "parse-invalid-type");
|
|
@@ -4034,9 +4051,16 @@ var TokenStream = class {
|
|
|
4034
4051
|
index = 0;
|
|
4035
4052
|
erased = [];
|
|
4036
4053
|
spans = /* @__PURE__ */ new Map();
|
|
4054
|
+
breaksIndexAtNewline = false;
|
|
4037
4055
|
constructor(tokens) {
|
|
4038
4056
|
this.tokens = tokens;
|
|
4039
4057
|
}
|
|
4058
|
+
stopIndexAtNewline(active) {
|
|
4059
|
+
this.breaksIndexAtNewline = active;
|
|
4060
|
+
}
|
|
4061
|
+
indexContinues(bracket) {
|
|
4062
|
+
return !this.breaksIndexAtNewline || this.index === 0 || bracket.position.line === this.peek(-1).end.line;
|
|
4063
|
+
}
|
|
4040
4064
|
peek(offset = 0) {
|
|
4041
4065
|
const token = this.tokens[Math.min(this.index + offset, this.tokens.length - 1)];
|
|
4042
4066
|
return token;
|
|
@@ -4127,6 +4151,33 @@ var TokenStream = class {
|
|
|
4127
4151
|
const token = this.peek(offset);
|
|
4128
4152
|
return token.kind === "identifier" || token.kind === "keyword" && isLuamKeyword(token.value);
|
|
4129
4153
|
}
|
|
4154
|
+
checkMemberKey(offset = 0) {
|
|
4155
|
+
return this.checkName(offset) || this.peek(offset).kind === "punctuation" && this.peek(offset).value === "[";
|
|
4156
|
+
}
|
|
4157
|
+
expectMemberKey() {
|
|
4158
|
+
if (!this.check("punctuation", "[")) {
|
|
4159
|
+
return this.expectName();
|
|
4160
|
+
}
|
|
4161
|
+
const open = this.next();
|
|
4162
|
+
const literal2 = this.current();
|
|
4163
|
+
if (literal2.kind !== "string") {
|
|
4164
|
+
throw this.error(`Expected a quoted key but found "${this.describeCurrent()}".`, "parse-unexpected-token");
|
|
4165
|
+
}
|
|
4166
|
+
this.next();
|
|
4167
|
+
const close = this.expect("punctuation", "]");
|
|
4168
|
+
return { ...literal2, position: open.position, end: close.end };
|
|
4169
|
+
}
|
|
4170
|
+
reservedNameAt(subject, offset = 0) {
|
|
4171
|
+
const token = this.peek(offset);
|
|
4172
|
+
const next = this.peek(offset + 1);
|
|
4173
|
+
const continues = next.kind === "punctuation" && (next.value === "," || next.value === ")" || next.value === ":") || next.kind === "operator" && (next.value === "?" || next.value === "=");
|
|
4174
|
+
if (token.kind !== "keyword" || !continues) {
|
|
4175
|
+
return null;
|
|
4176
|
+
}
|
|
4177
|
+
const message = `"${token.value}" is a reserved word and cannot name a ${subject}. Rename it \u2014 a property of the same name is still legal, so "value.${token.value}" keeps working.`;
|
|
4178
|
+
this.report("parse-reserved-name", message, token.position);
|
|
4179
|
+
return this.next();
|
|
4180
|
+
}
|
|
4130
4181
|
expectName() {
|
|
4131
4182
|
if (this.checkName()) {
|
|
4132
4183
|
return this.next();
|
|
@@ -4214,7 +4265,8 @@ function parseParameter(stream) {
|
|
|
4214
4265
|
}
|
|
4215
4266
|
return { name: name2, annotation, isVararg: true, position: token.position };
|
|
4216
4267
|
}
|
|
4217
|
-
const
|
|
4268
|
+
const reserved = stream.reservedNameAt("parameter");
|
|
4269
|
+
const name = reserved === null ? stream.expect("identifier").value : reserved.value;
|
|
4218
4270
|
return { name, annotation: parseNamedAnnotation(stream, "parameter"), isVararg: false, position: token.position };
|
|
4219
4271
|
}
|
|
4220
4272
|
function parseParameters(stream) {
|
|
@@ -4229,7 +4281,20 @@ function parseParameters(stream) {
|
|
|
4229
4281
|
stream.expect("punctuation", ")");
|
|
4230
4282
|
return parameters;
|
|
4231
4283
|
}
|
|
4232
|
-
|
|
4284
|
+
var ASYNC_MODIFIER = "async";
|
|
4285
|
+
function isAsyncFunctionStart(stream, offset = 0) {
|
|
4286
|
+
return stream.checkAhead(offset, "keyword", ASYNC_MODIFIER) && stream.checkAhead(offset + 1, "keyword", "function");
|
|
4287
|
+
}
|
|
4288
|
+
function consumeAsyncModifier(stream) {
|
|
4289
|
+
if (!isAsyncFunctionStart(stream)) {
|
|
4290
|
+
return false;
|
|
4291
|
+
}
|
|
4292
|
+
const checkpoint = stream.checkpoint();
|
|
4293
|
+
stream.next();
|
|
4294
|
+
stream.eraseToCurrent(checkpoint);
|
|
4295
|
+
return true;
|
|
4296
|
+
}
|
|
4297
|
+
function parseFunctionExpression(stream, isAsync = false) {
|
|
4233
4298
|
const position2 = stream.expect("keyword", "function").position;
|
|
4234
4299
|
const typeParameters = parseTypeParameters(stream);
|
|
4235
4300
|
const parameters = parseParameters(stream);
|
|
@@ -4238,6 +4303,7 @@ function parseFunctionExpression(stream) {
|
|
|
4238
4303
|
stream.expect("keyword", "end");
|
|
4239
4304
|
return {
|
|
4240
4305
|
kind: "function-expression",
|
|
4306
|
+
isAsync,
|
|
4241
4307
|
typeParameters: typeParameters.names,
|
|
4242
4308
|
typeConstraints: typeParameters.constraints,
|
|
4243
4309
|
parameters,
|
|
@@ -4259,7 +4325,7 @@ function parseFunctionName(stream) {
|
|
|
4259
4325
|
const property = stream.expect("identifier").value;
|
|
4260
4326
|
return { name: { kind: "member-expression", object: name, property, position: token.position }, isMethod: true };
|
|
4261
4327
|
}
|
|
4262
|
-
function parseFunctionDeclaration(stream, isLocal, isExported = false, isHttpExport = false) {
|
|
4328
|
+
function parseFunctionDeclaration(stream, isLocal, isExported = false, isHttpExport = false, isAsync = false) {
|
|
4263
4329
|
const position2 = stream.expect("keyword", "function").position;
|
|
4264
4330
|
const { name, isMethod } = parseFunctionName(stream);
|
|
4265
4331
|
const typeParameters = parseTypeParameters(stream);
|
|
@@ -4270,6 +4336,7 @@ function parseFunctionDeclaration(stream, isLocal, isExported = false, isHttpExp
|
|
|
4270
4336
|
return {
|
|
4271
4337
|
kind: "function-declaration",
|
|
4272
4338
|
name,
|
|
4339
|
+
isAsync,
|
|
4273
4340
|
isLocal,
|
|
4274
4341
|
isExported,
|
|
4275
4342
|
isHttpExport,
|
|
@@ -4324,6 +4391,14 @@ function isRightAssociative(operator) {
|
|
|
4324
4391
|
|
|
4325
4392
|
// ../compiler/src/parser/expression.ts
|
|
4326
4393
|
var LITERAL_KEYWORDS = /* @__PURE__ */ new Set(["nil", "true", "false"]);
|
|
4394
|
+
var AWAIT_OPERATOR = "await";
|
|
4395
|
+
function isAwaitStart(stream) {
|
|
4396
|
+
return stream.check("keyword", AWAIT_OPERATOR);
|
|
4397
|
+
}
|
|
4398
|
+
function parseAwaitExpression(stream) {
|
|
4399
|
+
const position2 = stream.next().position;
|
|
4400
|
+
return { kind: "await-expression", operand: parseSuffixed(stream), position: position2 };
|
|
4401
|
+
}
|
|
4327
4402
|
function parseKeywordLiteral(token) {
|
|
4328
4403
|
if (token.value === "nil") {
|
|
4329
4404
|
return { kind: "nil-literal", position: token.position };
|
|
@@ -4382,6 +4457,10 @@ function parsePrimary(stream) {
|
|
|
4382
4457
|
stream.next();
|
|
4383
4458
|
return { kind: "identifier", name: token.value, position: token.position };
|
|
4384
4459
|
}
|
|
4460
|
+
if (isAsyncFunctionStart(stream)) {
|
|
4461
|
+
consumeAsyncModifier(stream);
|
|
4462
|
+
return parseFunctionExpression(stream, true);
|
|
4463
|
+
}
|
|
4385
4464
|
if (token.kind === "identifier") {
|
|
4386
4465
|
stream.next();
|
|
4387
4466
|
return { kind: "identifier", name: token.value, position: token.position };
|
|
@@ -4406,6 +4485,12 @@ function parsePrimary(stream) {
|
|
|
4406
4485
|
stream.expect("punctuation", ")");
|
|
4407
4486
|
return { kind: "group-expression", expression, position: token.position };
|
|
4408
4487
|
}
|
|
4488
|
+
if (token.kind === "keyword" && isLuamKeyword(token.value)) {
|
|
4489
|
+
const message = `"${token.value}" is a reserved word and cannot be read as a value. Rename the declaration \u2014 a property of the same name is still legal, so "value.${token.value}" keeps working.`;
|
|
4490
|
+
stream.report("parse-reserved-name", message, token.position);
|
|
4491
|
+
stream.next();
|
|
4492
|
+
return { kind: "identifier", name: token.value, position: token.position };
|
|
4493
|
+
}
|
|
4409
4494
|
throw stream.error(`Unexpected "${stream.describeCurrent()}" in expression.`, "parse-unexpected-token");
|
|
4410
4495
|
}
|
|
4411
4496
|
function parseArguments(stream) {
|
|
@@ -4440,6 +4525,9 @@ function parseSuffixed(stream) {
|
|
|
4440
4525
|
continue;
|
|
4441
4526
|
}
|
|
4442
4527
|
if (token.kind === "punctuation" && token.value === "[") {
|
|
4528
|
+
if (!stream.indexContinues(token)) {
|
|
4529
|
+
return expression;
|
|
4530
|
+
}
|
|
4443
4531
|
stream.next();
|
|
4444
4532
|
const index = parseExpression(stream);
|
|
4445
4533
|
stream.expect("punctuation", "]");
|
|
@@ -4465,6 +4553,9 @@ function parseSuffixed(stream) {
|
|
|
4465
4553
|
}
|
|
4466
4554
|
}
|
|
4467
4555
|
function parseUnary(stream) {
|
|
4556
|
+
if (isAwaitStart(stream)) {
|
|
4557
|
+
return parseAwaitExpression(stream);
|
|
4558
|
+
}
|
|
4468
4559
|
const token = stream.current();
|
|
4469
4560
|
const isUnary2 = (token.kind === "operator" || token.kind === "keyword") && UNARY_OPERATORS.has(token.value);
|
|
4470
4561
|
if (!isUnary2) {
|
|
@@ -4622,7 +4713,11 @@ function isDeclarationStart(stream) {
|
|
|
4622
4713
|
if (token.value === "class") {
|
|
4623
4714
|
return isClassHeader(stream, offset);
|
|
4624
4715
|
}
|
|
4625
|
-
|
|
4716
|
+
if (token.value === "interface") {
|
|
4717
|
+
const after = skipTypeParameters(stream, offset + 2);
|
|
4718
|
+
return stream.checkAhead(after, "punctuation", "{") || stream.checkAhead(after, "keyword", "extends");
|
|
4719
|
+
}
|
|
4720
|
+
return stream.checkAhead(offset + 2, "punctuation", "{");
|
|
4626
4721
|
}
|
|
4627
4722
|
function skipDecoratorArguments(stream) {
|
|
4628
4723
|
let depth = 0;
|
|
@@ -4652,12 +4747,14 @@ function parseDecorators(stream) {
|
|
|
4652
4747
|
}
|
|
4653
4748
|
return decorators;
|
|
4654
4749
|
}
|
|
4655
|
-
function parseClassMethod(stream, token, decorators, isStatic) {
|
|
4750
|
+
function parseClassMethod(stream, token, decorators, isStatic, isAsync) {
|
|
4656
4751
|
stream.expect("operator", "=");
|
|
4657
|
-
const
|
|
4752
|
+
const modified = consumeAsyncModifier(stream) || isAsync;
|
|
4753
|
+
const expression = parseFunctionExpression(stream, modified);
|
|
4658
4754
|
return {
|
|
4659
4755
|
kind: "class-method",
|
|
4660
4756
|
name: token.value,
|
|
4757
|
+
isAsync: modified,
|
|
4661
4758
|
isConstructor: token.value === "constructor",
|
|
4662
4759
|
isSynthetic: false,
|
|
4663
4760
|
isStatic,
|
|
@@ -4670,13 +4767,14 @@ function parseClassMethod(stream, token, decorators, isStatic) {
|
|
|
4670
4767
|
position: token.position
|
|
4671
4768
|
};
|
|
4672
4769
|
}
|
|
4673
|
-
function parseBraceClassMethod(stream, token, decorators, isStatic) {
|
|
4770
|
+
function parseBraceClassMethod(stream, token, decorators, isStatic, isAsync) {
|
|
4674
4771
|
const parameters = parseParameters(stream);
|
|
4675
4772
|
const returnAnnotation = parseOptionalAnnotation(stream);
|
|
4676
4773
|
const body = parseBraceBlock(stream);
|
|
4677
4774
|
return {
|
|
4678
4775
|
kind: "class-method",
|
|
4679
4776
|
name: token.value,
|
|
4777
|
+
isAsync,
|
|
4680
4778
|
isConstructor: token.value === "constructor",
|
|
4681
4779
|
isSynthetic: false,
|
|
4682
4780
|
isStatic,
|
|
@@ -4692,6 +4790,14 @@ function parseBraceClassMethod(stream, token, decorators, isStatic) {
|
|
|
4692
4790
|
function parseFieldAnnotation(stream) {
|
|
4693
4791
|
return parseNamedAnnotation(stream, "field");
|
|
4694
4792
|
}
|
|
4793
|
+
function parseFieldValue(stream) {
|
|
4794
|
+
stream.stopIndexAtNewline(true);
|
|
4795
|
+
try {
|
|
4796
|
+
return parseExpression(stream);
|
|
4797
|
+
} finally {
|
|
4798
|
+
stream.stopIndexAtNewline(false);
|
|
4799
|
+
}
|
|
4800
|
+
}
|
|
4695
4801
|
function expectClassFieldBoundary(stream, token) {
|
|
4696
4802
|
const current = stream.current();
|
|
4697
4803
|
const delimiter = current.kind === "punctuation" && (current.value === "}" || current.value === ";" || current.value === ",");
|
|
@@ -4701,12 +4807,12 @@ function expectClassFieldBoundary(stream, token) {
|
|
|
4701
4807
|
throw stream.error(`Expected a line break or separator after class member "${token.value}".`, "parse-unexpected-token");
|
|
4702
4808
|
}
|
|
4703
4809
|
var STATIC_MODIFIER = "static";
|
|
4704
|
-
function
|
|
4705
|
-
if (!stream.check(
|
|
4810
|
+
function parseMemberModifier(stream, modifier, kind = "identifier") {
|
|
4811
|
+
if (!stream.check(kind, modifier)) {
|
|
4706
4812
|
return false;
|
|
4707
4813
|
}
|
|
4708
|
-
const
|
|
4709
|
-
if (!stream.checkName(1) || stream.peek(1).position.line !==
|
|
4814
|
+
const token = stream.current();
|
|
4815
|
+
if (!stream.checkName(1) || stream.peek(1).position.line !== token.position.line) {
|
|
4710
4816
|
return false;
|
|
4711
4817
|
}
|
|
4712
4818
|
const checkpoint = stream.checkpoint();
|
|
@@ -4716,17 +4822,18 @@ function parseStaticModifier(stream) {
|
|
|
4716
4822
|
}
|
|
4717
4823
|
function parseClassMember(stream) {
|
|
4718
4824
|
const decorators = parseDecorators(stream);
|
|
4719
|
-
const isStatic =
|
|
4720
|
-
const
|
|
4825
|
+
const isStatic = parseMemberModifier(stream, STATIC_MODIFIER);
|
|
4826
|
+
const isAsync = parseMemberModifier(stream, ASYNC_MODIFIER, "keyword");
|
|
4827
|
+
const token = stream.expectMemberKey();
|
|
4721
4828
|
if (stream.check("punctuation", "(")) {
|
|
4722
4829
|
stream.report("parse-class-method-form", `Write class member "${token.value}" as "${token.value} = function (...) ... end".`, token.position);
|
|
4723
|
-
return parseBraceClassMethod(stream, token, decorators, isStatic);
|
|
4830
|
+
return parseBraceClassMethod(stream, token, decorators, isStatic, isAsync);
|
|
4724
4831
|
}
|
|
4725
|
-
if (stream.check("operator", "=") && stream.checkAhead(1, "keyword", "function")) {
|
|
4726
|
-
return parseClassMethod(stream, token, decorators, isStatic);
|
|
4832
|
+
if (stream.check("operator", "=") && (stream.checkAhead(1, "keyword", "function") || isAsyncFunctionStart(stream, 1))) {
|
|
4833
|
+
return parseClassMethod(stream, token, decorators, isStatic, isAsync);
|
|
4727
4834
|
}
|
|
4728
4835
|
const annotation = parseFieldAnnotation(stream);
|
|
4729
|
-
const value = stream.match("operator", "=") ?
|
|
4836
|
+
const value = stream.match("operator", "=") ? parseFieldValue(stream) : null;
|
|
4730
4837
|
expectClassFieldBoundary(stream, token);
|
|
4731
4838
|
return { kind: "class-field", name: token.value, annotation, value, decorators, isStatic, position: token.position };
|
|
4732
4839
|
}
|
|
@@ -4739,6 +4846,7 @@ function parseClassModifiers(stream, declaration) {
|
|
|
4739
4846
|
}
|
|
4740
4847
|
do {
|
|
4741
4848
|
declaration.interfaces.push(stream.expect("identifier").value);
|
|
4849
|
+
declaration.interfaceArguments.push(parseTypeArguments(stream));
|
|
4742
4850
|
} while (stream.match("punctuation", ","));
|
|
4743
4851
|
}
|
|
4744
4852
|
}
|
|
@@ -4754,6 +4862,7 @@ function parseClassDeclaration(stream, decorators) {
|
|
|
4754
4862
|
superClass: null,
|
|
4755
4863
|
superClassArguments: [],
|
|
4756
4864
|
interfaces: [],
|
|
4865
|
+
interfaceArguments: [],
|
|
4757
4866
|
members: [],
|
|
4758
4867
|
decorators,
|
|
4759
4868
|
position: position2
|
|
@@ -4780,7 +4889,7 @@ function parseClassDeclaration(stream, decorators) {
|
|
|
4780
4889
|
return declaration;
|
|
4781
4890
|
}
|
|
4782
4891
|
function parseInterfaceMember(stream) {
|
|
4783
|
-
const token = stream.
|
|
4892
|
+
const token = stream.expectMemberKey();
|
|
4784
4893
|
if (stream.check("punctuation", "(")) {
|
|
4785
4894
|
const parameters = parseParameters(stream);
|
|
4786
4895
|
const returnAnnotation = parseOptionalAnnotation(stream);
|
|
@@ -4796,6 +4905,7 @@ function parseInterfaceDeclaration(stream) {
|
|
|
4796
4905
|
const checkpoint = stream.checkpoint();
|
|
4797
4906
|
const position2 = stream.next().position;
|
|
4798
4907
|
const name = stream.expect("identifier").value;
|
|
4908
|
+
const typeParameters = parseTypeParameters(stream);
|
|
4799
4909
|
const superInterfaces = [];
|
|
4800
4910
|
const members = [];
|
|
4801
4911
|
if (stream.match("keyword", "extends")) {
|
|
@@ -4818,7 +4928,15 @@ function parseInterfaceDeclaration(stream) {
|
|
|
4818
4928
|
}
|
|
4819
4929
|
}
|
|
4820
4930
|
stream.expect("punctuation", "}");
|
|
4821
|
-
const declaration = {
|
|
4931
|
+
const declaration = {
|
|
4932
|
+
kind: "interface-declaration",
|
|
4933
|
+
name,
|
|
4934
|
+
typeParameters: typeParameters.names,
|
|
4935
|
+
typeConstraints: typeParameters.constraints,
|
|
4936
|
+
superInterfaces,
|
|
4937
|
+
members,
|
|
4938
|
+
position: position2
|
|
4939
|
+
};
|
|
4822
4940
|
stream.eraseFrom(checkpoint, "declaration");
|
|
4823
4941
|
return declaration;
|
|
4824
4942
|
}
|
|
@@ -4879,7 +4997,7 @@ function parseExpressionList(stream) {
|
|
|
4879
4997
|
return values;
|
|
4880
4998
|
}
|
|
4881
4999
|
function parseDeclarator(stream) {
|
|
4882
|
-
const token = stream.expect("identifier");
|
|
5000
|
+
const token = stream.reservedNameAt("local") ?? stream.expect("identifier");
|
|
4883
5001
|
return { name: token.value, annotation: parseNamedAnnotation(stream, "local"), position: token.position };
|
|
4884
5002
|
}
|
|
4885
5003
|
function parseLocalStatement(stream, position2) {
|
|
@@ -4973,7 +5091,34 @@ function invalidStatement(stream, target, start) {
|
|
|
4973
5091
|
const message = `${subject} is not a statement. Assign it with "=", pass it to a call, or remove the line.`;
|
|
4974
5092
|
return stream.errorAt(message, "parse-invalid-statement", start.position, start.end);
|
|
4975
5093
|
}
|
|
5094
|
+
function parseGlobalDeclaration(stream) {
|
|
5095
|
+
const marked = stream.checkAhead(1, "operator", "?") && stream.checkAhead(2, "punctuation", ":");
|
|
5096
|
+
if (!stream.check("identifier") || !marked && !stream.checkAhead(1, "punctuation", ":")) {
|
|
5097
|
+
return null;
|
|
5098
|
+
}
|
|
5099
|
+
const point = stream.speculate();
|
|
5100
|
+
try {
|
|
5101
|
+
const declaration = parseDeclarator(stream);
|
|
5102
|
+
if (declaration.annotation !== null && stream.match("operator", "=")) {
|
|
5103
|
+
return { kind: "global-statement", declaration, values: parseExpressionList(stream), position: declaration.position };
|
|
5104
|
+
}
|
|
5105
|
+
} catch (error) {
|
|
5106
|
+
if (!(error instanceof ParserError)) {
|
|
5107
|
+
throw error;
|
|
5108
|
+
}
|
|
5109
|
+
}
|
|
5110
|
+
stream.rewind(point);
|
|
5111
|
+
return null;
|
|
5112
|
+
}
|
|
4976
5113
|
function parseExpressionStatement(stream) {
|
|
5114
|
+
if (isAwaitStart(stream)) {
|
|
5115
|
+
const expression = parseAwaitExpression(stream);
|
|
5116
|
+
return { kind: "call-statement", expression, position: expression.position };
|
|
5117
|
+
}
|
|
5118
|
+
const declaration = parseGlobalDeclaration(stream);
|
|
5119
|
+
if (declaration !== null) {
|
|
5120
|
+
return declaration;
|
|
5121
|
+
}
|
|
4977
5122
|
const start = stream.current();
|
|
4978
5123
|
const position2 = start.position;
|
|
4979
5124
|
const targets = [parseSuffixed(stream)];
|
|
@@ -5001,7 +5146,12 @@ function parseKeywordStatement(stream, value) {
|
|
|
5001
5146
|
if (stream.check("keyword", "function")) {
|
|
5002
5147
|
return parseFunctionDeclaration(stream, true);
|
|
5003
5148
|
}
|
|
5004
|
-
|
|
5149
|
+
if (isAsyncFunctionStart(stream)) {
|
|
5150
|
+
consumeAsyncModifier(stream);
|
|
5151
|
+
return parseFunctionDeclaration(stream, true, false, false, true);
|
|
5152
|
+
}
|
|
5153
|
+
const isEnum = stream.check("keyword", "enum") && stream.checkAhead(1, "identifier");
|
|
5154
|
+
return isEnum ? parseEnumDeclaration(stream, true) : parseLocalStatement(stream, token.position);
|
|
5005
5155
|
}
|
|
5006
5156
|
if (value === "function") {
|
|
5007
5157
|
return parseFunctionDeclaration(stream, false);
|
|
@@ -5042,6 +5192,10 @@ function parseStatement(stream) {
|
|
|
5042
5192
|
return statement;
|
|
5043
5193
|
}
|
|
5044
5194
|
}
|
|
5195
|
+
if (isAsyncFunctionStart(stream)) {
|
|
5196
|
+
consumeAsyncModifier(stream);
|
|
5197
|
+
return parseFunctionDeclaration(stream, false, false, false, true);
|
|
5198
|
+
}
|
|
5045
5199
|
if (isTypeAlias(stream)) {
|
|
5046
5200
|
return parseTypeAlias(stream);
|
|
5047
5201
|
}
|
|
@@ -5266,10 +5420,21 @@ function isEmptyLiteral(type) {
|
|
|
5266
5420
|
return type.kind === "record" && type.isLiteral === true && type.members.size === 0;
|
|
5267
5421
|
}
|
|
5268
5422
|
function widenInferred(type) {
|
|
5423
|
+
if (type.kind === "array") {
|
|
5424
|
+
return createArray(widenInferred(type.element));
|
|
5425
|
+
}
|
|
5426
|
+
if (type.kind === "union") {
|
|
5427
|
+
return createUnion(type.options.map(widenInferred));
|
|
5428
|
+
}
|
|
5269
5429
|
if (type.kind !== "record" || type.isLiteral !== true) {
|
|
5270
5430
|
return widenLiteral(type);
|
|
5271
5431
|
}
|
|
5272
|
-
|
|
5432
|
+
if (type.members.size === 0) {
|
|
5433
|
+
return TABLE_TYPE;
|
|
5434
|
+
}
|
|
5435
|
+
const widened = new Map([...type.members].map(([name, member]) => [name, widenInferred(member)]));
|
|
5436
|
+
const record2 = createObjectType(widened);
|
|
5437
|
+
return record2.kind === "record" ? { ...record2, isInferred: true } : record2;
|
|
5273
5438
|
}
|
|
5274
5439
|
function createFunction(parameters, returnType, minimumArguments2, isVariadic = false, parameterNames, variadicType) {
|
|
5275
5440
|
return {
|
|
@@ -5428,7 +5593,7 @@ function isFunctionAssignable(source, target, options) {
|
|
|
5428
5593
|
return target.returnType.kind === "void" || isAssignable(source.returnType, target.returnType, options);
|
|
5429
5594
|
}
|
|
5430
5595
|
function isMapAssignable(source, target, options) {
|
|
5431
|
-
if (source.kind === "table") {
|
|
5596
|
+
if (source.kind === "table" || isEmptyLiteral(source)) {
|
|
5432
5597
|
return true;
|
|
5433
5598
|
}
|
|
5434
5599
|
if (source.kind === "array") {
|
|
@@ -5677,9 +5842,16 @@ var RUNTIME_HELPERS = {
|
|
|
5677
5842
|
},
|
|
5678
5843
|
env: { name: "env", file: "env.lua", injection: "manual", features: [], environment: "server" },
|
|
5679
5844
|
math: { name: "math", file: "math.lua", injection: "automatic", features: ["number-extension"] },
|
|
5845
|
+
promise: {
|
|
5846
|
+
name: "promise",
|
|
5847
|
+
file: "promise.lua",
|
|
5848
|
+
injection: "reference",
|
|
5849
|
+
features: ["async-function"],
|
|
5850
|
+
globals: ["Promise", "delay", "sleep"]
|
|
5851
|
+
},
|
|
5680
5852
|
string: { name: "string", file: "string.lua", injection: "automatic", features: ["string-extension", "template-string"] },
|
|
5681
5853
|
table: { name: "table", file: "table.lua", injection: "automatic", features: ["table-extension"] },
|
|
5682
|
-
threads: { name: "threads", file: "threads.lua", injection: "reference", features: ["thread"], globals: ["
|
|
5854
|
+
threads: { name: "threads", file: "threads.lua", injection: "reference", features: ["thread"], globals: ["Threads"], requires: ["promise"] },
|
|
5683
5855
|
validate: { name: "validate", file: "validate.lua", injection: "automatic", features: ["boundary-validation"] }
|
|
5684
5856
|
};
|
|
5685
5857
|
var DEVELOPMENT_RUNTIME_HELPERS = {
|
|
@@ -5741,6 +5913,9 @@ var COMPILER_OPTION_FIELDS = [
|
|
|
5741
5913
|
}),
|
|
5742
5914
|
field("oop", BOOLEAN_TYPE, "Enables the MTA OOP API in the checker and the generated meta.xml.", { defaultValue: DEFAULT_COMPILER_OPTIONS.oop }),
|
|
5743
5915
|
field("noUnusedLocals", BOOLEAN_TYPE, "Reports local declarations that are never read.", { defaultValue: DEFAULT_COMPILER_OPTIONS.noUnusedLocals }),
|
|
5916
|
+
field("noImplicitGlobals", BOOLEAN_TYPE, "Reports an assignment that creates a global the project never declares.", {
|
|
5917
|
+
defaultValue: DEFAULT_COMPILER_OPTIONS.noImplicitGlobals
|
|
5918
|
+
}),
|
|
5744
5919
|
field("noUnusedParameters", BOOLEAN_TYPE, "Reports function and method parameters that are never read.", {
|
|
5745
5920
|
defaultValue: DEFAULT_COMPILER_OPTIONS.noUnusedParameters
|
|
5746
5921
|
}),
|
|
@@ -6802,6 +6977,7 @@ function readCompilerOptions(value) {
|
|
|
6802
6977
|
strict: flag(source, "strict", DEFAULT_COMPILER_OPTIONS.strict),
|
|
6803
6978
|
oop: flag(source, "oop", DEFAULT_COMPILER_OPTIONS.oop),
|
|
6804
6979
|
noUnusedLocals: flag(source, "noUnusedLocals", DEFAULT_COMPILER_OPTIONS.noUnusedLocals),
|
|
6980
|
+
noImplicitGlobals: flag(source, "noImplicitGlobals", DEFAULT_COMPILER_OPTIONS.noImplicitGlobals),
|
|
6805
6981
|
noUnusedParameters: flag(source, "noUnusedParameters", DEFAULT_COMPILER_OPTIONS.noUnusedParameters),
|
|
6806
6982
|
warningsAsErrors: flag(source, "warningsAsErrors", DEFAULT_COMPILER_OPTIONS.warningsAsErrors)
|
|
6807
6983
|
};
|
|
@@ -6978,7 +7154,7 @@ import { tmpdir } from "node:os";
|
|
|
6978
7154
|
import { join as join2 } from "node:path";
|
|
6979
7155
|
|
|
6980
7156
|
// src/cli/version.ts
|
|
6981
|
-
var VERSION = true ? "0.
|
|
7157
|
+
var VERSION = true ? "1.0.1" : "0.0.0-dev";
|
|
6982
7158
|
var PROGRAM_NAME = "luam";
|
|
6983
7159
|
var PROGRAM_DESCRIPTION = "luam \u2014 the Luam compiler for Multi Theft Auto resources.";
|
|
6984
7160
|
|
|
@@ -7042,7 +7218,7 @@ function runEditorCommand(command, args) {
|
|
|
7042
7218
|
}
|
|
7043
7219
|
|
|
7044
7220
|
// src/editor/editor-service.ts
|
|
7045
|
-
var EXTENSION_ID = "
|
|
7221
|
+
var EXTENSION_ID = "luam.luam";
|
|
7046
7222
|
var SUPPORTED_EDITORS = [
|
|
7047
7223
|
{ id: "vscode", name: "Visual Studio Code", command: "code" },
|
|
7048
7224
|
{ id: "vscode-insiders", name: "Visual Studio Code Insiders", command: "code-insiders" },
|
|
@@ -8862,12 +9038,13 @@ var TEST_DECLARATIONS = [
|
|
|
8862
9038
|
|
|
8863
9039
|
// ../compiler/src/checker/ambient.ts
|
|
8864
9040
|
var EVENT_NAME_PREFIX = "event:";
|
|
8865
|
-
var EMPTY_AMBIENT = { classes: [], interfaces: [], enums: [], globals: [], events: [] };
|
|
9041
|
+
var EMPTY_AMBIENT = { classes: [], interfaces: [], enums: [], aliases: [], globals: [], events: [] };
|
|
8866
9042
|
function ambientFromRegistry(registry) {
|
|
8867
9043
|
return {
|
|
8868
9044
|
classes: registry.allClasses(),
|
|
8869
|
-
interfaces: registry.allInterfaces(),
|
|
9045
|
+
interfaces: registry.allInterfaces().filter((info) => info.isBuiltin !== true),
|
|
8870
9046
|
enums: registry.allEnums().filter((info) => info.isLocal !== true),
|
|
9047
|
+
aliases: registry.allAliases(),
|
|
8871
9048
|
globals: registry.allGlobals(),
|
|
8872
9049
|
events: registry.allEvents()
|
|
8873
9050
|
};
|
|
@@ -8885,6 +9062,7 @@ function ownDeclarations(registry, ambient) {
|
|
|
8885
9062
|
classes: withoutNames(all.classes, ambient.classes),
|
|
8886
9063
|
interfaces: withoutNames(all.interfaces, ambient.interfaces),
|
|
8887
9064
|
enums: withoutNames(all.enums, ambient.enums),
|
|
9065
|
+
aliases: withoutNames(all.aliases, ambient.aliases),
|
|
8888
9066
|
globals: withoutNames(all.globals, ambient.globals),
|
|
8889
9067
|
events: withoutNames(all.events, ambient.events)
|
|
8890
9068
|
};
|
|
@@ -8903,6 +9081,7 @@ function mergeAmbient(sources) {
|
|
|
8903
9081
|
classes: mergeByName(sources.map((source) => source.classes)),
|
|
8904
9082
|
interfaces: mergeByName(sources.map((source) => source.interfaces)),
|
|
8905
9083
|
enums: mergeByName(sources.map((source) => source.enums)),
|
|
9084
|
+
aliases: mergeByName(sources.map((source) => source.aliases)),
|
|
8906
9085
|
globals: mergeByName(sources.map((source) => source.globals)),
|
|
8907
9086
|
events: mergeByName(sources.map((source) => source.events))
|
|
8908
9087
|
};
|
|
@@ -8977,6 +9156,9 @@ function declareAll(catalog, environment, source) {
|
|
|
8977
9156
|
function isAvailableIn(declared, environment) {
|
|
8978
9157
|
return declared === "shared" || declared === environment;
|
|
8979
9158
|
}
|
|
9159
|
+
function isVisibleIn(declared, environment) {
|
|
9160
|
+
return environment === "shared" || isAvailableIn(declared, environment);
|
|
9161
|
+
}
|
|
8980
9162
|
|
|
8981
9163
|
// ../compiler/src/checker/api-types.ts
|
|
8982
9164
|
var PRIMITIVES = {
|
|
@@ -9028,6 +9210,74 @@ function descriptorToType(descriptor) {
|
|
|
9028
9210
|
return PRIMITIVES[descriptor.kind] ?? ANY_TYPE;
|
|
9029
9211
|
}
|
|
9030
9212
|
|
|
9213
|
+
// ../compiler/src/checker/async.ts
|
|
9214
|
+
var PROMISE_TYPE = "Promise";
|
|
9215
|
+
var SLEEP_FUNCTION = "sleep";
|
|
9216
|
+
var PROMISE_PARAMETER = "T";
|
|
9217
|
+
var ORIGIN = { line: 0, column: 0, offset: 0 };
|
|
9218
|
+
var AWAIT_OUTSIDE_MESSAGE = '"await" is only valid inside an async function. Declare the function "async function name()", or wait on the promise with ":next(...)".';
|
|
9219
|
+
var ASYNC_ANNOTATION_MESSAGE = 'An async function is annotated with the type it resolves to, not with "Promise". Write the inner type and the signature becomes a promise of it.';
|
|
9220
|
+
var SLEEP_OUTSIDE_MESSAGE = '"sleep" suspends a coroutine and there is none here. Declare the function "async function name()", or run the body as a thread pool job.';
|
|
9221
|
+
function promiseOf(inner) {
|
|
9222
|
+
return createNamed(PROMISE_TYPE, [inner]);
|
|
9223
|
+
}
|
|
9224
|
+
function isPromiseType(type) {
|
|
9225
|
+
return (type.kind === "named" || type.kind === "record") && type.name === PROMISE_TYPE;
|
|
9226
|
+
}
|
|
9227
|
+
function declarePromiseType(declarations) {
|
|
9228
|
+
const value = createNamed(PROMISE_PARAMETER);
|
|
9229
|
+
const onFulfilled = createFunction([value], ANY_TYPE, 1, false, ["value"]);
|
|
9230
|
+
const onRejected = createFunction([ANY_TYPE], ANY_TYPE, 1, false, ["reason"]);
|
|
9231
|
+
const chained = promiseOf(ANY_TYPE);
|
|
9232
|
+
const next = createFunction([onFulfilled, createOptional(onRejected)], chained, 1, false, ["onFulfilled", "onRejected"]);
|
|
9233
|
+
const failure3 = createFunction([onRejected], chained, 1, false, ["onRejected"]);
|
|
9234
|
+
declarations.declareInterface({
|
|
9235
|
+
name: PROMISE_TYPE,
|
|
9236
|
+
isBuiltin: true,
|
|
9237
|
+
typeParameters: [PROMISE_PARAMETER],
|
|
9238
|
+
typeConstraints: [null],
|
|
9239
|
+
superInterfaces: [],
|
|
9240
|
+
members: /* @__PURE__ */ new Map([
|
|
9241
|
+
["next", { name: "next", type: next, isMethod: true, position: ORIGIN }],
|
|
9242
|
+
["catch", { name: "catch", type: failure3, isMethod: true, position: ORIGIN }]
|
|
9243
|
+
]),
|
|
9244
|
+
position: ORIGIN
|
|
9245
|
+
});
|
|
9246
|
+
}
|
|
9247
|
+
function awaitedType(context, operand, expression) {
|
|
9248
|
+
if (!context.inAsyncBody()) {
|
|
9249
|
+
context.report("check-await-outside-async", AWAIT_OUTSIDE_MESSAGE, expression.position);
|
|
9250
|
+
return ANY_TYPE;
|
|
9251
|
+
}
|
|
9252
|
+
if (operand.kind === "any" || operand.kind === "unknown") {
|
|
9253
|
+
return ANY_TYPE;
|
|
9254
|
+
}
|
|
9255
|
+
if (isPromiseType(operand)) {
|
|
9256
|
+
return (operand.kind === "named" ? operand.typeArguments?.[0] : ANY_TYPE) ?? ANY_TYPE;
|
|
9257
|
+
}
|
|
9258
|
+
const message = `"await" expects a promise but received "${typeToString(operand)}". Only an async function or "new Promise(...)" produces one.`;
|
|
9259
|
+
context.report("check-await-non-promise", message, expression.position);
|
|
9260
|
+
return ANY_TYPE;
|
|
9261
|
+
}
|
|
9262
|
+
function isPromiseAnnotation(isAsync, annotation) {
|
|
9263
|
+
return isAsync && annotation !== null && annotation.kind === "type-name" && annotation.name === PROMISE_TYPE;
|
|
9264
|
+
}
|
|
9265
|
+
function asyncInnerAnnotation(isAsync, annotation) {
|
|
9266
|
+
return isPromiseAnnotation(isAsync, annotation) ? null : annotation;
|
|
9267
|
+
}
|
|
9268
|
+
function reportAsyncAnnotation(context, isAsync, annotation) {
|
|
9269
|
+
if (!isPromiseAnnotation(isAsync, annotation) || annotation === null) {
|
|
9270
|
+
return;
|
|
9271
|
+
}
|
|
9272
|
+
context.report("check-async-return-annotation", ASYNC_ANNOTATION_MESSAGE, annotation.position);
|
|
9273
|
+
}
|
|
9274
|
+
function reportSleepOutsideAsync(context, name, position2) {
|
|
9275
|
+
if (name !== SLEEP_FUNCTION || context.declaredGlobals.has(name) || context.binder.lookup(name)?.isLocal === true || context.suspendable()) {
|
|
9276
|
+
return;
|
|
9277
|
+
}
|
|
9278
|
+
context.warn("check-sleep-outside-async", SLEEP_OUTSIDE_MESSAGE, position2);
|
|
9279
|
+
}
|
|
9280
|
+
|
|
9031
9281
|
// ../compiler/src/checker/binder.ts
|
|
9032
9282
|
var Binder = class {
|
|
9033
9283
|
scopes = [/* @__PURE__ */ new Map()];
|
|
@@ -9195,6 +9445,9 @@ var MAX_DEPTH = 32;
|
|
|
9195
9445
|
function classSubstitutions(info, typeArguments) {
|
|
9196
9446
|
return new Map(info.typeParameters.map((parameter, index) => [parameter, typeArguments[index] ?? ANY_TYPE]));
|
|
9197
9447
|
}
|
|
9448
|
+
function parameterSubstitutions(typeParameters, typeArguments) {
|
|
9449
|
+
return new Map(typeParameters.map((parameter, index) => [parameter, typeArguments[index] ?? ANY_TYPE]));
|
|
9450
|
+
}
|
|
9198
9451
|
function parentSubstitutions(registry, info, current) {
|
|
9199
9452
|
const parent = info.superClass === null ? null : registry.lookupClass(info.superClass);
|
|
9200
9453
|
if (parent === null) {
|
|
@@ -9222,7 +9475,15 @@ function substitutionsFor(registry, receiver, owner) {
|
|
|
9222
9475
|
}
|
|
9223
9476
|
return /* @__PURE__ */ new Map();
|
|
9224
9477
|
}
|
|
9478
|
+
function interfaceSubstitutions(registry, receiver) {
|
|
9479
|
+
const contract = registry.lookupInterface(receiver.name);
|
|
9480
|
+
return contract === null ? null : parameterSubstitutions(contract.typeParameters, receiver.typeArguments ?? []);
|
|
9481
|
+
}
|
|
9225
9482
|
function specializeMember(context, receiver, member, property) {
|
|
9483
|
+
const contract = interfaceSubstitutions(context.declarations, receiver);
|
|
9484
|
+
if (contract !== null) {
|
|
9485
|
+
return contract.size === 0 ? member : { ...member, type: substituteType(member.type, contract) };
|
|
9486
|
+
}
|
|
9226
9487
|
const owner = context.declarations.lookupMemberOwner(receiver.name, property);
|
|
9227
9488
|
if (owner === null || owner === receiver.name) {
|
|
9228
9489
|
const own = context.declarations.lookupClass(receiver.name);
|
|
@@ -9307,6 +9568,11 @@ function reportConstraintViolations(context, owner, typeParameters, typeConstrai
|
|
|
9307
9568
|
});
|
|
9308
9569
|
}
|
|
9309
9570
|
function checkTypeConstraints(context, name, typeArguments, position2) {
|
|
9571
|
+
const contract = context.declarations.lookupInterface(name);
|
|
9572
|
+
if (contract !== null) {
|
|
9573
|
+
reportConstraintViolations(context, `interface "${name}"`, contract.typeParameters, contract.typeConstraints, typeArguments, position2);
|
|
9574
|
+
return;
|
|
9575
|
+
}
|
|
9310
9576
|
const info = context.declarations.lookupClass(name);
|
|
9311
9577
|
if (info === null) {
|
|
9312
9578
|
return;
|
|
@@ -9343,6 +9609,17 @@ var LUA_GLOBALS = {
|
|
|
9343
9609
|
};
|
|
9344
9610
|
|
|
9345
9611
|
// ../mta-types/src/luam-runtime.ts
|
|
9612
|
+
var PROMISE_VALUE = named("Promise");
|
|
9613
|
+
var RESOLVE = fn([ANY], VOID, 0, true, ["values"]);
|
|
9614
|
+
var REJECT = fn([ANY], VOID, 0, true, ["reason"]);
|
|
9615
|
+
var EXECUTOR = fn([RESOLVE, REJECT], ANY, 2, false, ["resolve", "reject"]);
|
|
9616
|
+
var ON_FULFILLED = fn([ANY], ANY, 0, true, ["value"]);
|
|
9617
|
+
var ON_REJECTED = fn([ANY], ANY, 1, false, ["reason"]);
|
|
9618
|
+
var PROMISE = record("Promise", [
|
|
9619
|
+
{ name: "next", type: fn([ON_FULFILLED, optionalOf(ON_REJECTED)], PROMISE_VALUE, 1, false, ["onFulfilled", "onRejected"]) },
|
|
9620
|
+
{ name: "catch", type: fn([ON_REJECTED], PROMISE_VALUE, 1, false, ["onRejected"]) }
|
|
9621
|
+
]);
|
|
9622
|
+
var JOB = tupleOf([NUMBER, PROMISE]);
|
|
9346
9623
|
var THREAD = record("Thread", [
|
|
9347
9624
|
{ name: "get", type: fn([], NUMBER, 0) },
|
|
9348
9625
|
{ name: "set", type: fn([NUMBER], BOOLEAN, 1) },
|
|
@@ -9351,8 +9628,10 @@ var THREAD = record("Thread", [
|
|
|
9351
9628
|
{ name: "isPaused", type: fn([], BOOLEAN, 0) },
|
|
9352
9629
|
{ name: "isStarted", type: fn([], BOOLEAN, 0) }
|
|
9353
9630
|
]);
|
|
9631
|
+
var JOB_BODY = fn([THREAD], ANY, 0, true, ["thread"]);
|
|
9632
|
+
var TASK_BODY = fn([ANY], ANY, 0, true, ["values"]);
|
|
9354
9633
|
var THREADS = record("Threads", [
|
|
9355
|
-
{ name: "add", type: fn([
|
|
9634
|
+
{ name: "add", type: fn([JOB_BODY, TABLE], JOB, 1, true, ["target", "options"]) },
|
|
9356
9635
|
{ name: "remove", type: fn([NUMBER], BOOLEAN, 1) },
|
|
9357
9636
|
{ name: "clear", type: fn([], BOOLEAN, 0) },
|
|
9358
9637
|
{ name: "start", type: fn([], BOOLEAN, 0) },
|
|
@@ -9360,18 +9639,31 @@ var THREADS = record("Threads", [
|
|
|
9360
9639
|
{ name: "getType", type: fn([], STRING, 0) }
|
|
9361
9640
|
]);
|
|
9362
9641
|
var ASYNC = record("Async", [
|
|
9363
|
-
{ name: "map", type: fn([TABLE, ANY, ANY],
|
|
9364
|
-
{ name: "iterate", type: fn([NUMBER, NUMBER, NUMBER, ANY, ANY],
|
|
9365
|
-
{ name: "foreach", type: fn([TABLE, ANY, ANY],
|
|
9642
|
+
{ name: "map", type: fn([TABLE, ANY, ANY], JOB, 2) },
|
|
9643
|
+
{ name: "iterate", type: fn([NUMBER, NUMBER, NUMBER, ANY, ANY], JOB, 4) },
|
|
9644
|
+
{ name: "foreach", type: fn([TABLE, ANY, ANY], JOB, 2) },
|
|
9366
9645
|
{ name: "getInterval", type: fn([], NUMBER, 0) },
|
|
9367
9646
|
{ name: "setInterval", type: fn([NUMBER], BOOLEAN, 1) }
|
|
9368
9647
|
]);
|
|
9648
|
+
var PROMISE_LIBRARY = record("PromiseLibrary", [
|
|
9649
|
+
{ name: "new", type: fn([EXECUTOR], PROMISE, 1, false, ["executor"]) },
|
|
9650
|
+
{ name: "spawn", type: fn([TASK_BODY], PROMISE, 1, true, ["target"]) },
|
|
9651
|
+
{ name: "resolve", type: fn([ANY], PROMISE, 0, true) },
|
|
9652
|
+
{ name: "reject", type: fn([ANY], PROMISE, 0, true) },
|
|
9653
|
+
{ name: "all", type: fn([arrayOf(ANY)], PROMISE, 1) },
|
|
9654
|
+
{ name: "race", type: fn([arrayOf(ANY)], PROMISE, 1) },
|
|
9655
|
+
{ name: "settle", type: fn([PROMISE], tupleOf([BOOLEAN, ANY]), 1) },
|
|
9656
|
+
{ name: "await", type: fn([PROMISE], ANY, 1) },
|
|
9657
|
+
{ name: "delay", type: fn([NUMBER], PROMISE, 1) }
|
|
9658
|
+
]);
|
|
9369
9659
|
var LUAM_RUNTIME_SERVER_GLOBALS = {};
|
|
9370
9660
|
var LUAM_RUNTIME_GLOBALS = {
|
|
9371
9661
|
bind: fn([ANY, ANY], ANY, 2),
|
|
9372
9662
|
getClass: fn([STRING], optionalOf(TABLE), 1),
|
|
9373
9663
|
getClasses: fn([], TABLE, 0),
|
|
9374
9664
|
sleep: fn([NUMBER], ANY, 1),
|
|
9665
|
+
delay: fn([NUMBER], PROMISE, 1),
|
|
9666
|
+
Promise: PROMISE_LIBRARY,
|
|
9375
9667
|
Thread: THREAD,
|
|
9376
9668
|
Threads: record("ThreadsLibrary", [{ name: "new", type: fn([STRING, STRING], THREADS, 0) }]),
|
|
9377
9669
|
Async: record("AsyncLibrary", [{ name: "new", type: fn([NUMBER], ASYNC, 0) }])
|
|
@@ -12233,10 +12525,14 @@ var MTA_EXACT = {
|
|
|
12233
12525
|
client: MTA_CLIENT_GLOBALS
|
|
12234
12526
|
};
|
|
12235
12527
|
function globalsFor(environment) {
|
|
12236
|
-
|
|
12528
|
+
const resolved2 = /* @__PURE__ */ new Map();
|
|
12529
|
+
for (const declaration of DECLARATIONS) {
|
|
12237
12530
|
const exact = findDeclaration(declaration.name, environment);
|
|
12238
|
-
|
|
12239
|
-
|
|
12531
|
+
if (exact !== null && !resolved2.has(exact.name)) {
|
|
12532
|
+
resolved2.set(exact.name, exact);
|
|
12533
|
+
}
|
|
12534
|
+
}
|
|
12535
|
+
return [...resolved2.values()];
|
|
12240
12536
|
}
|
|
12241
12537
|
function findDeclaration(name, environment) {
|
|
12242
12538
|
const declaration = BY_NAME.get(name);
|
|
@@ -12244,7 +12540,7 @@ function findDeclaration(name, environment) {
|
|
|
12244
12540
|
return declaration ?? null;
|
|
12245
12541
|
}
|
|
12246
12542
|
if (!isAvailableIn(declaration.environment, environment)) {
|
|
12247
|
-
return null;
|
|
12543
|
+
return environment === "shared" ? declaration : null;
|
|
12248
12544
|
}
|
|
12249
12545
|
if (declaration.source !== "mta") {
|
|
12250
12546
|
return declaration;
|
|
@@ -14049,11 +14345,15 @@ var DeclarationRegistry = class {
|
|
|
14049
14345
|
classes = /* @__PURE__ */ new Map();
|
|
14050
14346
|
interfaces = /* @__PURE__ */ new Map();
|
|
14051
14347
|
enums = /* @__PURE__ */ new Map();
|
|
14348
|
+
aliases = /* @__PURE__ */ new Map();
|
|
14052
14349
|
globals = /* @__PURE__ */ new Map();
|
|
14053
14350
|
events = /* @__PURE__ */ new Map();
|
|
14054
14351
|
declareGlobal(info) {
|
|
14055
14352
|
this.globals.set(info.name, info);
|
|
14056
14353
|
}
|
|
14354
|
+
lookupGlobal(name) {
|
|
14355
|
+
return this.globals.get(name) ?? null;
|
|
14356
|
+
}
|
|
14057
14357
|
allGlobals() {
|
|
14058
14358
|
return [...this.globals.values()];
|
|
14059
14359
|
}
|
|
@@ -14089,6 +14389,15 @@ var DeclarationRegistry = class {
|
|
|
14089
14389
|
declareEnum(info) {
|
|
14090
14390
|
this.enums.set(info.name, info);
|
|
14091
14391
|
}
|
|
14392
|
+
declareAlias(info) {
|
|
14393
|
+
this.aliases.set(info.name, info);
|
|
14394
|
+
}
|
|
14395
|
+
lookupAlias(name) {
|
|
14396
|
+
return this.aliases.get(name) ?? null;
|
|
14397
|
+
}
|
|
14398
|
+
allAliases() {
|
|
14399
|
+
return [...this.aliases.values()];
|
|
14400
|
+
}
|
|
14092
14401
|
lookupEnum(name) {
|
|
14093
14402
|
return this.enums.get(name) ?? null;
|
|
14094
14403
|
}
|
|
@@ -14229,6 +14538,7 @@ function buildRegistry() {
|
|
|
14229
14538
|
superClass: declaration.parent,
|
|
14230
14539
|
superArguments: [],
|
|
14231
14540
|
interfaces: [],
|
|
14541
|
+
interfaceArguments: [],
|
|
14232
14542
|
members,
|
|
14233
14543
|
statics: /* @__PURE__ */ new Map(),
|
|
14234
14544
|
position: MTA_POSITION
|
|
@@ -14430,16 +14740,23 @@ var CheckContext = class {
|
|
|
14430
14740
|
isDeclarationFile = false;
|
|
14431
14741
|
returnStack = [];
|
|
14432
14742
|
methodStack = [];
|
|
14743
|
+
functionStack = [];
|
|
14433
14744
|
projectEnvironments = /* @__PURE__ */ new Map();
|
|
14434
14745
|
predeclared = /* @__PURE__ */ new Map();
|
|
14435
14746
|
ambientClasses = /* @__PURE__ */ new Set();
|
|
14436
14747
|
ambientInterfaces = /* @__PURE__ */ new Set();
|
|
14437
14748
|
ambientEnums = /* @__PURE__ */ new Set();
|
|
14749
|
+
ambientAliases = /* @__PURE__ */ new Set();
|
|
14750
|
+
ambientGlobals = /* @__PURE__ */ new Set();
|
|
14751
|
+
obligations = /* @__PURE__ */ new Map();
|
|
14752
|
+
blockDepth = 0;
|
|
14753
|
+
noImplicitGlobals = false;
|
|
14438
14754
|
constructor(mode, environment, ambient = EMPTY_AMBIENT, project = EMPTY_PROJECT_DECLARATIONS, oop = false) {
|
|
14439
14755
|
this.mode = mode;
|
|
14440
14756
|
this.environment = environment;
|
|
14441
14757
|
this.mtaClasses = oop ? mtaClassRegistry() : null;
|
|
14442
14758
|
this.binder.useBuiltins(builtinSymbols(environment));
|
|
14759
|
+
declarePromiseType(this.declarations);
|
|
14443
14760
|
this.declareProject(project);
|
|
14444
14761
|
this.declareAmbient(ambient);
|
|
14445
14762
|
}
|
|
@@ -14510,6 +14827,24 @@ var CheckContext = class {
|
|
|
14510
14827
|
isAmbientEnum(name) {
|
|
14511
14828
|
return this.ambientEnums.has(name);
|
|
14512
14829
|
}
|
|
14830
|
+
isAmbientAlias(name) {
|
|
14831
|
+
return this.ambientAliases.has(name);
|
|
14832
|
+
}
|
|
14833
|
+
isAmbientGlobal(name) {
|
|
14834
|
+
return this.ambientGlobals.has(name);
|
|
14835
|
+
}
|
|
14836
|
+
openRecordObligation(obligation) {
|
|
14837
|
+
this.obligations.set(obligation.path, obligation);
|
|
14838
|
+
}
|
|
14839
|
+
recordObligation(path) {
|
|
14840
|
+
return this.obligations.get(path) ?? null;
|
|
14841
|
+
}
|
|
14842
|
+
closeRecordObligation(path) {
|
|
14843
|
+
this.obligations.delete(path);
|
|
14844
|
+
}
|
|
14845
|
+
recordObligationPaths() {
|
|
14846
|
+
return [...this.obligations.keys()];
|
|
14847
|
+
}
|
|
14513
14848
|
noteExternalReference(name, position2) {
|
|
14514
14849
|
if (!this.externalReferences.has(name)) {
|
|
14515
14850
|
this.externalReferences.set(name, position2);
|
|
@@ -14595,6 +14930,18 @@ var CheckContext = class {
|
|
|
14595
14930
|
currentClassMethod() {
|
|
14596
14931
|
return this.methodStack[this.methodStack.length - 1] ?? null;
|
|
14597
14932
|
}
|
|
14933
|
+
pushFunctionFrame(frame) {
|
|
14934
|
+
this.functionStack.push(frame);
|
|
14935
|
+
}
|
|
14936
|
+
popFunctionFrame() {
|
|
14937
|
+
this.functionStack.pop();
|
|
14938
|
+
}
|
|
14939
|
+
inAsyncBody() {
|
|
14940
|
+
return this.functionStack[this.functionStack.length - 1]?.isAsync === true;
|
|
14941
|
+
}
|
|
14942
|
+
suspendable() {
|
|
14943
|
+
return this.functionStack.some((frame) => frame.isAsync || frame.isExpression);
|
|
14944
|
+
}
|
|
14598
14945
|
resolveAnnotation(annotation) {
|
|
14599
14946
|
if (annotation === null) {
|
|
14600
14947
|
return ANY_TYPE;
|
|
@@ -14679,19 +15026,28 @@ var CheckContext = class {
|
|
|
14679
15026
|
assignability() {
|
|
14680
15027
|
return { allowNil: this.allowNil, resolveNominal: (name) => this.nominalShape(name) };
|
|
14681
15028
|
}
|
|
14682
|
-
|
|
15029
|
+
resolveValueAnnotation(annotation, subject) {
|
|
15030
|
+
const resolved2 = this.resolveAnnotation(annotation);
|
|
15031
|
+
if (resolved2.kind !== "tuple") {
|
|
15032
|
+
return resolved2;
|
|
15033
|
+
}
|
|
15034
|
+
const message = `A parenthesised list like "${typeToString(resolved2)}" is a return shape and cannot type ${subject}. Name one type instead.`;
|
|
15035
|
+
this.report("check-tuple-position", message, annotation.position);
|
|
15036
|
+
return firstValueOf(resolved2);
|
|
15037
|
+
}
|
|
15038
|
+
expectAssignable(source, target, position2, subject, printed = target) {
|
|
14683
15039
|
if (isAssignable(source, target, this.assignability())) {
|
|
14684
15040
|
return;
|
|
14685
15041
|
}
|
|
14686
15042
|
const received = isLiteralType(target) || target.kind === "union" ? source : widenLiteral(source);
|
|
14687
|
-
const message = `${subject} expects "${typeToString(
|
|
15043
|
+
const message = `${subject} expects "${typeToString(printed)}" but received "${typeToString(received)}".`;
|
|
14688
15044
|
const hint = `${nilHint(source, target, this.mode)}${missingKeyHint(source, target, (name) => this.nominalShape(name))}`;
|
|
14689
15045
|
this.report("check-type-mismatch", `${message}${hint}`, position2);
|
|
14690
15046
|
}
|
|
14691
15047
|
declareProject(project) {
|
|
14692
15048
|
for (const declaration of project.globals) {
|
|
14693
15049
|
this.projectEnvironments.set(declaration.name, declaration.environment);
|
|
14694
|
-
if (
|
|
15050
|
+
if (isVisibleIn(declaration.environment, this.environment)) {
|
|
14695
15051
|
const symbol = { name: declaration.name, type: descriptorToType(declaration.type), isLocal: false, position: PROJECT_POSITION };
|
|
14696
15052
|
this.binder.declareGlobal(symbol);
|
|
14697
15053
|
}
|
|
@@ -14712,7 +15068,14 @@ var CheckContext = class {
|
|
|
14712
15068
|
this.declarations.declareEnum(info);
|
|
14713
15069
|
this.binder.declareGlobal({ name: info.name, type: createNamed(info.name), isLocal: false, position: info.position });
|
|
14714
15070
|
}
|
|
15071
|
+
for (const info of ambient.aliases) {
|
|
15072
|
+
this.ambientAliases.add(info.name);
|
|
15073
|
+
this.binder.declareAlias(info.name, info.type, info.typeParameters);
|
|
15074
|
+
this.declarations.declareAlias(info);
|
|
15075
|
+
}
|
|
14715
15076
|
for (const info of ambient.globals) {
|
|
15077
|
+
this.ambientGlobals.add(info.name);
|
|
15078
|
+
this.declarations.declareGlobal(info);
|
|
14716
15079
|
this.binder.declareGlobal({ name: info.name, type: info.type, isLocal: false, position: info.position });
|
|
14717
15080
|
}
|
|
14718
15081
|
for (const info of ambient.events) {
|
|
@@ -14732,18 +15095,20 @@ var CheckContext = class {
|
|
|
14732
15095
|
return createMap(this.resolveAnnotation(key), this.resolveAnnotation(value));
|
|
14733
15096
|
}
|
|
14734
15097
|
resolveClassAnnotation(name, typeArguments, position2) {
|
|
14735
|
-
const
|
|
15098
|
+
const declaredInterface = this.declarations.lookupInterface(name);
|
|
15099
|
+
const owner = declaredInterface === null ? "Class" : "Interface";
|
|
15100
|
+
const declared = declaredInterface?.typeParameters ?? this.declarations.lookupClass(name)?.typeParameters ?? [];
|
|
14736
15101
|
const resolved2 = typeArguments.map((argument) => this.resolveAnnotation(argument));
|
|
14737
15102
|
if (declared.length === 0) {
|
|
14738
15103
|
return createNamed(name);
|
|
14739
15104
|
}
|
|
14740
15105
|
if (resolved2.length !== declared.length) {
|
|
14741
15106
|
const expected = declared.length === 1 ? "1 type argument" : `${declared.length} type arguments`;
|
|
14742
|
-
this.report("check-generic-arity",
|
|
15107
|
+
this.report("check-generic-arity", `${owner} "${name}" expects ${expected} but received ${resolved2.length}.`, position2);
|
|
14743
15108
|
}
|
|
14744
15109
|
const specialized = createNamed(name, declared.map((unused, index) => resolved2[index] ?? ANY_TYPE));
|
|
14745
15110
|
if (namedNesting(specialized) > MAX_GENERIC_DEPTH) {
|
|
14746
|
-
const message =
|
|
15111
|
+
const message = `${owner} "${name}" is nested more than ${MAX_GENERIC_DEPTH} levels deep here. Name the inner type with a "type" alias.`;
|
|
14747
15112
|
this.report("check-generic-depth", message, position2);
|
|
14748
15113
|
return createNamed(name);
|
|
14749
15114
|
}
|
|
@@ -14789,6 +15154,7 @@ var ALLOWED = /* @__PURE__ */ new Set([
|
|
|
14789
15154
|
var LABELS = {
|
|
14790
15155
|
"local-statement": 'A "local" declaration',
|
|
14791
15156
|
"assignment-statement": "An assignment",
|
|
15157
|
+
"global-statement": "A global declaration",
|
|
14792
15158
|
"call-statement": "A call",
|
|
14793
15159
|
"return-statement": 'A "return"',
|
|
14794
15160
|
"break-statement": 'A "break"',
|
|
@@ -14837,6 +15203,7 @@ function childExpressions(expression) {
|
|
|
14837
15203
|
case "binary-expression":
|
|
14838
15204
|
return [expression.left, expression.right];
|
|
14839
15205
|
case "unary-expression":
|
|
15206
|
+
case "await-expression":
|
|
14840
15207
|
return [expression.operand];
|
|
14841
15208
|
case "group-expression":
|
|
14842
15209
|
return [expression.expression];
|
|
@@ -14848,6 +15215,7 @@ function statementExpressions(statement) {
|
|
|
14848
15215
|
switch (statement.kind) {
|
|
14849
15216
|
case "local-statement":
|
|
14850
15217
|
case "return-statement":
|
|
15218
|
+
case "global-statement":
|
|
14851
15219
|
return statement.values;
|
|
14852
15220
|
case "assignment-statement":
|
|
14853
15221
|
return [...statement.targets, ...statement.values];
|
|
@@ -14995,18 +15363,28 @@ function checkContract(context, info, contract, member) {
|
|
|
14995
15363
|
const message = `${subject} expects "${typeToString(member.type)}" from interface "${contract}" but is "${typeToString(actual.type)}".`;
|
|
14996
15364
|
context.report("check-unimplemented-interface", message, actual.position);
|
|
14997
15365
|
}
|
|
15366
|
+
function contractName(name, typeArguments) {
|
|
15367
|
+
return typeArguments.length === 0 ? name : `${name}<${typeArguments.map(typeToString).join(", ")}>`;
|
|
15368
|
+
}
|
|
14998
15369
|
function checkInterfaces(context, info) {
|
|
14999
|
-
|
|
15370
|
+
info.interfaces.forEach((name, index) => {
|
|
15000
15371
|
const contract = context.declarations.lookupInterface(name);
|
|
15001
15372
|
if (contract === null) {
|
|
15002
15373
|
context.noteExternalReference(name, info.position);
|
|
15003
15374
|
context.report("check-unknown-interface", `Class "${info.name}" implements "${name}", which is not defined.`, info.position);
|
|
15004
|
-
|
|
15375
|
+
return;
|
|
15376
|
+
}
|
|
15377
|
+
const typeArguments = info.interfaceArguments[index] ?? [];
|
|
15378
|
+
if (contract.typeParameters.length > 0 && typeArguments.length !== contract.typeParameters.length) {
|
|
15379
|
+
const expected = contract.typeParameters.length === 1 ? "1 type argument" : `${contract.typeParameters.length} type arguments`;
|
|
15380
|
+
context.report("check-generic-arity", `Interface "${name}" expects ${expected} but received ${typeArguments.length}.`, info.position);
|
|
15005
15381
|
}
|
|
15382
|
+
const substitutions = parameterSubstitutions(contract.typeParameters, typeArguments);
|
|
15383
|
+
const label2 = contractName(name, typeArguments);
|
|
15006
15384
|
for (const member of context.declarations.collectInterfaceContract(contract.name)) {
|
|
15007
|
-
checkContract(context, info,
|
|
15385
|
+
checkContract(context, info, label2, substitutions.size === 0 ? member : { ...member, type: substituteType(member.type, substitutions) });
|
|
15008
15386
|
}
|
|
15009
|
-
}
|
|
15387
|
+
});
|
|
15010
15388
|
}
|
|
15011
15389
|
function checkOverrides(context, info, statement) {
|
|
15012
15390
|
for (const member of statement.members) {
|
|
@@ -15401,6 +15779,7 @@ function accessorMethod(field2, decorator, name) {
|
|
|
15401
15779
|
return {
|
|
15402
15780
|
kind: "class-method",
|
|
15403
15781
|
name,
|
|
15782
|
+
isAsync: false,
|
|
15404
15783
|
isConstructor: false,
|
|
15405
15784
|
isSynthetic: true,
|
|
15406
15785
|
isStatic: false,
|
|
@@ -15414,7 +15793,7 @@ function accessorMethod(field2, decorator, name) {
|
|
|
15414
15793
|
};
|
|
15415
15794
|
}
|
|
15416
15795
|
function generatedMethod(field2, name, parameters, returnAnnotation, kind, fields) {
|
|
15417
|
-
return { kind: "class-method", name, isConstructor: false, isSynthetic: true, isStatic: false, typeParameters: [], typeConstraints: [], parameters, returnAnnotation, body: [], decorators: [], generated: { kind, fields }, position: field2.position };
|
|
15796
|
+
return { kind: "class-method", name, isAsync: false, isConstructor: false, isSynthetic: true, isStatic: false, typeParameters: [], typeConstraints: [], parameters, returnAnnotation, body: [], decorators: [], generated: { kind, fields }, position: field2.position };
|
|
15418
15797
|
}
|
|
15419
15798
|
function typeName(name, node) {
|
|
15420
15799
|
return { kind: "type-name", name, typeArguments: [], position: node.position };
|
|
@@ -15449,6 +15828,7 @@ function staticMethod(statement, name, returnAnnotation, kind, descriptor) {
|
|
|
15449
15828
|
return {
|
|
15450
15829
|
kind: "class-method",
|
|
15451
15830
|
name,
|
|
15831
|
+
isAsync: false,
|
|
15452
15832
|
isConstructor: false,
|
|
15453
15833
|
isSynthetic: true,
|
|
15454
15834
|
isStatic: true,
|
|
@@ -15604,6 +15984,7 @@ function childExpressions2(expression) {
|
|
|
15604
15984
|
case "binary-expression":
|
|
15605
15985
|
return [expression.left, expression.right];
|
|
15606
15986
|
case "unary-expression":
|
|
15987
|
+
case "await-expression":
|
|
15607
15988
|
return [expression.operand];
|
|
15608
15989
|
case "group-expression":
|
|
15609
15990
|
return [expression.expression];
|
|
@@ -15615,6 +15996,7 @@ function statementExpressions2(statement) {
|
|
|
15615
15996
|
switch (statement.kind) {
|
|
15616
15997
|
case "local-statement":
|
|
15617
15998
|
case "return-statement":
|
|
15999
|
+
case "global-statement":
|
|
15618
16000
|
return statement.values;
|
|
15619
16001
|
case "assignment-statement":
|
|
15620
16002
|
return [...statement.targets, ...statement.values];
|
|
@@ -15672,6 +16054,9 @@ function addTargets(statement, paths) {
|
|
|
15672
16054
|
if (statement.kind === "local-statement") {
|
|
15673
16055
|
statement.declarations.forEach((declaration) => paths.add(declaration.name));
|
|
15674
16056
|
}
|
|
16057
|
+
if (statement.kind === "global-statement") {
|
|
16058
|
+
paths.add(statement.declaration.name);
|
|
16059
|
+
}
|
|
15675
16060
|
}
|
|
15676
16061
|
function collectPaths(body, paths) {
|
|
15677
16062
|
for (const statement of body) {
|
|
@@ -19083,21 +19468,42 @@ function eventHandler(name, environment) {
|
|
|
19083
19468
|
return MTA_EVENT_SIGNATURES[environment][name] ?? null;
|
|
19084
19469
|
}
|
|
19085
19470
|
|
|
19086
|
-
// ../compiler/src/checker/environment-
|
|
19087
|
-
var EVENT_FUNCTIONS = /* @__PURE__ */ new Set(["addEventHandler", "removeEventHandler", "triggerEvent"]);
|
|
19471
|
+
// ../compiler/src/checker/environment-message.ts
|
|
19088
19472
|
function scopeLabel(environment) {
|
|
19089
19473
|
return environment === "shared" ? "shared" : `${environment}-only`;
|
|
19090
19474
|
}
|
|
19475
|
+
function unavailableTail(environment) {
|
|
19476
|
+
return `is not available in a "${environment}" file.`;
|
|
19477
|
+
}
|
|
19478
|
+
function unusableTail(environment) {
|
|
19479
|
+
return `cannot be used in a "${environment}" file.`;
|
|
19480
|
+
}
|
|
19481
|
+
function reportEnvironment(context, code, message, position2) {
|
|
19482
|
+
if (context.environment === "shared") {
|
|
19483
|
+
return;
|
|
19484
|
+
}
|
|
19485
|
+
context.report(code, message, position2);
|
|
19486
|
+
}
|
|
19487
|
+
|
|
19488
|
+
// ../compiler/src/checker/environment-checks.ts
|
|
19489
|
+
var EVENT_FUNCTIONS = /* @__PURE__ */ new Set(["addEventHandler", "removeEventHandler", "triggerEvent"]);
|
|
19490
|
+
function reportProject(context, name, declared, position2) {
|
|
19491
|
+
const message = `"${name}" is declared by the project, is ${scopeLabel(declared)}, and ${unavailableTail(context.environment)}`;
|
|
19492
|
+
reportEnvironment(context, "check-environment-api", message, position2);
|
|
19493
|
+
}
|
|
19494
|
+
function reportApi(context, name, declared, position2) {
|
|
19495
|
+
const message = `API "${name}" is ${scopeLabel(declared)} and ${unavailableTail(context.environment)}`;
|
|
19496
|
+
reportEnvironment(context, "check-environment-api", message, position2);
|
|
19497
|
+
}
|
|
19091
19498
|
function checkGlobalReference(context, name, position2) {
|
|
19092
19499
|
if (name === "self") {
|
|
19093
|
-
const
|
|
19094
|
-
context.report("check-invalid-self",
|
|
19500
|
+
const message = 'A "self" is only bound inside a class method or a "function Name:method()"; here it reads a global that is "nil".';
|
|
19501
|
+
context.report("check-invalid-self", message, position2);
|
|
19095
19502
|
return;
|
|
19096
19503
|
}
|
|
19097
19504
|
const project = context.projectEnvironmentOf(name);
|
|
19098
19505
|
if (project !== null) {
|
|
19099
|
-
|
|
19100
|
-
context.report("check-environment-api", message2, position2);
|
|
19506
|
+
reportProject(context, name, project, position2);
|
|
19101
19507
|
return;
|
|
19102
19508
|
}
|
|
19103
19509
|
const declared = declarationEnvironment(name);
|
|
@@ -19105,8 +19511,26 @@ function checkGlobalReference(context, name, position2) {
|
|
|
19105
19511
|
context.noteExternalReference(name, position2);
|
|
19106
19512
|
return;
|
|
19107
19513
|
}
|
|
19108
|
-
|
|
19109
|
-
|
|
19514
|
+
reportApi(context, name, declared, position2);
|
|
19515
|
+
}
|
|
19516
|
+
function checkSharedReference(context, name, position2) {
|
|
19517
|
+
if (context.environment !== "shared" || context.moduleGlobals.has(name)) {
|
|
19518
|
+
return;
|
|
19519
|
+
}
|
|
19520
|
+
const project = context.projectEnvironmentOf(name);
|
|
19521
|
+
if (project !== null) {
|
|
19522
|
+
if (project !== "shared") {
|
|
19523
|
+
reportProject(context, name, project, position2);
|
|
19524
|
+
}
|
|
19525
|
+
return;
|
|
19526
|
+
}
|
|
19527
|
+
if (!context.binder.isBuiltinReference(name)) {
|
|
19528
|
+
return;
|
|
19529
|
+
}
|
|
19530
|
+
const declared = declarationEnvironment(name);
|
|
19531
|
+
if (declared !== null && declared !== "shared") {
|
|
19532
|
+
reportApi(context, name, declared, position2);
|
|
19533
|
+
}
|
|
19110
19534
|
}
|
|
19111
19535
|
function eventName(expression) {
|
|
19112
19536
|
const argument = expression.args[0];
|
|
@@ -19125,8 +19549,8 @@ function checkEventUsage(context, expression) {
|
|
|
19125
19549
|
if (name === null || custom?.environment === "shared" || custom?.environment === context.environment || declared === null || declared === context.environment) {
|
|
19126
19550
|
return;
|
|
19127
19551
|
}
|
|
19128
|
-
const message = `Event "${name}" is ${scopeLabel(declared)} and
|
|
19129
|
-
context
|
|
19552
|
+
const message = `Event "${name}" is ${scopeLabel(declared)} and ${unusableTail(context.environment)}`;
|
|
19553
|
+
reportEnvironment(context, "check-environment-event", message, expression.position);
|
|
19130
19554
|
}
|
|
19131
19555
|
|
|
19132
19556
|
// ../mta-types/src/event-call-semantics.ts
|
|
@@ -19307,6 +19731,136 @@ function withoutSelfParameter(signature2) {
|
|
|
19307
19731
|
return createFunction(signature2.parameters.slice(1), signature2.returnType, minimum, signature2.isVariadic, names.slice(1), signature2.variadicType);
|
|
19308
19732
|
}
|
|
19309
19733
|
|
|
19734
|
+
// ../compiler/src/checker/record-completion.ts
|
|
19735
|
+
function recordShapeOf(context, type) {
|
|
19736
|
+
if (type.kind === "record") {
|
|
19737
|
+
return type;
|
|
19738
|
+
}
|
|
19739
|
+
if (type.kind !== "named") {
|
|
19740
|
+
return null;
|
|
19741
|
+
}
|
|
19742
|
+
const shape = context.assignability().resolveNominal?.(type.name) ?? null;
|
|
19743
|
+
return shape === null ? null : { kind: "record", name: type.name, origin: null, members: shape.members };
|
|
19744
|
+
}
|
|
19745
|
+
function pendingKeys(context, source, target) {
|
|
19746
|
+
if (source.kind !== "record" || source.isLiteral !== true) {
|
|
19747
|
+
return null;
|
|
19748
|
+
}
|
|
19749
|
+
const shape = recordShapeOf(context, target);
|
|
19750
|
+
if (shape === null) {
|
|
19751
|
+
return null;
|
|
19752
|
+
}
|
|
19753
|
+
const missing2 = /* @__PURE__ */ new Map();
|
|
19754
|
+
const options = context.assignability();
|
|
19755
|
+
for (const [name, member] of shape.members) {
|
|
19756
|
+
const written = source.members.get(name);
|
|
19757
|
+
if (written === void 0) {
|
|
19758
|
+
if (member.kind !== "optional") {
|
|
19759
|
+
missing2.set(name, member);
|
|
19760
|
+
}
|
|
19761
|
+
continue;
|
|
19762
|
+
}
|
|
19763
|
+
if (!isAssignable(written, member, options)) {
|
|
19764
|
+
return null;
|
|
19765
|
+
}
|
|
19766
|
+
}
|
|
19767
|
+
for (const name of source.members.keys()) {
|
|
19768
|
+
if (!shape.members.has(name)) {
|
|
19769
|
+
return null;
|
|
19770
|
+
}
|
|
19771
|
+
}
|
|
19772
|
+
return missing2.size === 0 ? null : missing2;
|
|
19773
|
+
}
|
|
19774
|
+
function deferRecordCompletion(context, target, source, declared, subject, position2) {
|
|
19775
|
+
const path = pathOf2(target);
|
|
19776
|
+
if (path === null) {
|
|
19777
|
+
return false;
|
|
19778
|
+
}
|
|
19779
|
+
const missing2 = pendingKeys(context, source, declared);
|
|
19780
|
+
if (missing2 === null) {
|
|
19781
|
+
return false;
|
|
19782
|
+
}
|
|
19783
|
+
context.openRecordObligation({
|
|
19784
|
+
path,
|
|
19785
|
+
subject,
|
|
19786
|
+
source,
|
|
19787
|
+
target: declared,
|
|
19788
|
+
missing: missing2,
|
|
19789
|
+
discharged: 0,
|
|
19790
|
+
depth: context.blockDepth,
|
|
19791
|
+
line: position2.line,
|
|
19792
|
+
position: position2
|
|
19793
|
+
});
|
|
19794
|
+
return true;
|
|
19795
|
+
}
|
|
19796
|
+
function reportIncompleteRecord(context, obligation, position2) {
|
|
19797
|
+
if (obligation.discharged === 0) {
|
|
19798
|
+
context.closeRecordObligation(obligation.path);
|
|
19799
|
+
context.expectAssignable(obligation.source, obligation.target, obligation.position, obligation.subject);
|
|
19800
|
+
return;
|
|
19801
|
+
}
|
|
19802
|
+
const keys = [...obligation.missing.keys()].map((key) => `"${key}"`);
|
|
19803
|
+
const label2 = keys.length === 1 ? `Key ${keys[0]} is` : `Keys ${keys.join(", ")} are`;
|
|
19804
|
+
const built = `The table built on line ${obligation.line} is used before it is complete.`;
|
|
19805
|
+
const message = `${obligation.subject} expects "${typeToString(obligation.target)}". ${label2} never assigned. ${built}`;
|
|
19806
|
+
context.report("check-incomplete-record", message, position2);
|
|
19807
|
+
context.closeRecordObligation(obligation.path);
|
|
19808
|
+
}
|
|
19809
|
+
function dischargeRecordKey(context, target, valueType, position2) {
|
|
19810
|
+
if (target.kind !== "member-expression") {
|
|
19811
|
+
return false;
|
|
19812
|
+
}
|
|
19813
|
+
const path = pathOf2(target.object);
|
|
19814
|
+
const obligation = path === null ? null : context.recordObligation(path);
|
|
19815
|
+
if (obligation === null || obligation.depth !== context.blockDepth) {
|
|
19816
|
+
return false;
|
|
19817
|
+
}
|
|
19818
|
+
const expected = obligation.missing.get(target.property);
|
|
19819
|
+
if (expected === void 0) {
|
|
19820
|
+
return false;
|
|
19821
|
+
}
|
|
19822
|
+
context.expectAssignable(valueType, expected, position2, `Key "${target.property}"`);
|
|
19823
|
+
obligation.missing.delete(target.property);
|
|
19824
|
+
obligation.discharged += 1;
|
|
19825
|
+
if (obligation.missing.size === 0) {
|
|
19826
|
+
context.closeRecordObligation(obligation.path);
|
|
19827
|
+
}
|
|
19828
|
+
return true;
|
|
19829
|
+
}
|
|
19830
|
+
function extendInferredRecord(context, target, valueType) {
|
|
19831
|
+
if (target.kind !== "member-expression" || target.object.kind !== "identifier") {
|
|
19832
|
+
return false;
|
|
19833
|
+
}
|
|
19834
|
+
const symbol = context.binder.lookup(target.object.name);
|
|
19835
|
+
if (symbol === null || symbol.type.kind !== "record" || symbol.type.isInferred !== true || symbol.type.members.has(target.property)) {
|
|
19836
|
+
return false;
|
|
19837
|
+
}
|
|
19838
|
+
const members = new Map(symbol.type.members);
|
|
19839
|
+
members.set(target.property, widenInferred(valueType));
|
|
19840
|
+
const extended = createObjectType(members);
|
|
19841
|
+
symbol.type = extended.kind === "record" ? { ...extended, isInferred: true } : extended;
|
|
19842
|
+
return true;
|
|
19843
|
+
}
|
|
19844
|
+
function escapesRecordObligation(context, expression) {
|
|
19845
|
+
const path = pathOf2(expression);
|
|
19846
|
+
const obligation = path === null ? null : context.recordObligation(path);
|
|
19847
|
+
if (obligation !== null) {
|
|
19848
|
+
reportIncompleteRecord(context, obligation, expression.position);
|
|
19849
|
+
}
|
|
19850
|
+
}
|
|
19851
|
+
function settleRecordObligations(context, opened) {
|
|
19852
|
+
for (const path of context.recordObligationPaths()) {
|
|
19853
|
+
if (opened.has(path)) {
|
|
19854
|
+
continue;
|
|
19855
|
+
}
|
|
19856
|
+
const obligation = context.recordObligation(path);
|
|
19857
|
+
if (obligation === null) {
|
|
19858
|
+
continue;
|
|
19859
|
+
}
|
|
19860
|
+
reportIncompleteRecord(context, obligation, obligation.position);
|
|
19861
|
+
}
|
|
19862
|
+
}
|
|
19863
|
+
|
|
19310
19864
|
// ../compiler/src/checker/resource-exports.ts
|
|
19311
19865
|
var RESOURCE_LOOKUP = "getResourceFromName";
|
|
19312
19866
|
var EXPORTS_TABLE = "exports";
|
|
@@ -19516,9 +20070,6 @@ function isElementType(name) {
|
|
|
19516
20070
|
|
|
19517
20071
|
// ../compiler/src/checker/oop-members.ts
|
|
19518
20072
|
var OOP_HINT = 'Set "compiler = { oop = true }" in .luam.manifest to enable the MTA OOP API.';
|
|
19519
|
-
function scopeLabel2(environment) {
|
|
19520
|
-
return environment === "shared" ? "shared" : `${environment}-only`;
|
|
19521
|
-
}
|
|
19522
20073
|
function isMtaElementName(declarations, className) {
|
|
19523
20074
|
if (!isElementType(className)) {
|
|
19524
20075
|
return false;
|
|
@@ -19536,6 +20087,14 @@ function reportDisabled(context, className, name, position2) {
|
|
|
19536
20087
|
const subject = `"${className}.${name}" is part of the MTA OOP API, which this project does not enable.`;
|
|
19537
20088
|
context.report("check-oop-disabled", `${subject} Call "${member.procedural}" instead. ${OOP_HINT}`, position2);
|
|
19538
20089
|
}
|
|
20090
|
+
function acceptsMember(context, className, name, member, position2) {
|
|
20091
|
+
if (member.environment === void 0 || isAvailableIn(member.environment, context.environment)) {
|
|
20092
|
+
return true;
|
|
20093
|
+
}
|
|
20094
|
+
const subject = `"${className}.${name}" wraps "${member.procedural}", which is ${scopeLabel(member.environment)}`;
|
|
20095
|
+
reportEnvironment(context, "check-environment-api", `${subject} and ${unavailableTail(context.environment)}`, position2);
|
|
20096
|
+
return context.environment === "shared";
|
|
20097
|
+
}
|
|
19539
20098
|
function isMtaClassReference(context, className) {
|
|
19540
20099
|
return isMtaClass(className) && context.binder.lookup(className) === null && context.declarations.lookupClass(className) === null && context.declarations.lookupInterface(className) === null;
|
|
19541
20100
|
}
|
|
@@ -19551,12 +20110,7 @@ function resolveMtaStaticMember(context, className, name, position2) {
|
|
|
19551
20110
|
reportDisabled(context, className, name, position2);
|
|
19552
20111
|
return null;
|
|
19553
20112
|
}
|
|
19554
|
-
|
|
19555
|
-
const subject = `"${className}.${name}" wraps "${member.procedural}", which is ${scopeLabel2(member.environment)}`;
|
|
19556
|
-
context.report("check-environment-api", `${subject} and is not available in a "${context.environment}" file.`, position2);
|
|
19557
|
-
return null;
|
|
19558
|
-
}
|
|
19559
|
-
return member;
|
|
20113
|
+
return acceptsMember(context, className, name, member, position2) ? member : null;
|
|
19560
20114
|
}
|
|
19561
20115
|
function resolveMtaConstructor(context, className, position2) {
|
|
19562
20116
|
const constructor = mtaConstructor(className);
|
|
@@ -19571,9 +20125,11 @@ function resolveMtaConstructor(context, className, position2) {
|
|
|
19571
20125
|
return null;
|
|
19572
20126
|
}
|
|
19573
20127
|
if (!isAvailableIn(constructor.environment, context.environment)) {
|
|
19574
|
-
const subject = `"${className}(...)" is ${
|
|
19575
|
-
context
|
|
19576
|
-
|
|
20128
|
+
const subject = `"${className}(...)" is ${scopeLabel(constructor.environment)}`;
|
|
20129
|
+
reportEnvironment(context, "check-environment-api", `${subject} and ${unavailableTail(context.environment)}`, position2);
|
|
20130
|
+
if (context.environment !== "shared") {
|
|
20131
|
+
return null;
|
|
20132
|
+
}
|
|
19577
20133
|
}
|
|
19578
20134
|
return constructor.type;
|
|
19579
20135
|
}
|
|
@@ -19593,12 +20149,7 @@ function resolveMtaMember(context, className, name, position2) {
|
|
|
19593
20149
|
reportUnknown(context, className, name, position2);
|
|
19594
20150
|
return null;
|
|
19595
20151
|
}
|
|
19596
|
-
|
|
19597
|
-
const subject = `"${className}.${name}" wraps "${member.procedural}", which is ${scopeLabel2(member.environment)}`;
|
|
19598
|
-
context.report("check-environment-api", `${subject} and is not available in a "${context.environment}" file.`, position2);
|
|
19599
|
-
return null;
|
|
19600
|
-
}
|
|
19601
|
-
return member;
|
|
20152
|
+
return acceptsMember(context, className, name, member, position2) ? member : null;
|
|
19602
20153
|
}
|
|
19603
20154
|
|
|
19604
20155
|
// ../compiler/src/checker/members.ts
|
|
@@ -19724,7 +20275,9 @@ function resolveNamedMember(context, receiver, expression) {
|
|
|
19724
20275
|
if (contract === null) {
|
|
19725
20276
|
return null;
|
|
19726
20277
|
}
|
|
19727
|
-
const
|
|
20278
|
+
const substitutions = parameterSubstitutions(contract.typeParameters, receiver.typeArguments ?? []);
|
|
20279
|
+
const collected = context.declarations.collectMembers(name).map((entry) => substitutions.size === 0 ? entry : { ...entry, type: substituteType(entry.type, substitutions) });
|
|
20280
|
+
const members = new Map(collected.map((entry) => [entry.name, entry]));
|
|
19728
20281
|
return checkInterfaceMember(context, name, members, expression);
|
|
19729
20282
|
}
|
|
19730
20283
|
function reportUnknownMethod(context, receiver, callee, method, position2) {
|
|
@@ -19892,6 +20445,39 @@ function checkUnary(context, operator, operand, expression) {
|
|
|
19892
20445
|
return context.record(expression, NUMBER_TYPE);
|
|
19893
20446
|
}
|
|
19894
20447
|
|
|
20448
|
+
// ../compiler/src/checker/shadowing.ts
|
|
20449
|
+
var HELPER_TARGETS = new Map(
|
|
20450
|
+
NATIVE_EXTENSIONS.map((extension) => [
|
|
20451
|
+
extension.target,
|
|
20452
|
+
extension.style === "call" ? `${extension.receiver}.${extension.property}(...)` : `${extension.receiver}.${extension.property}`
|
|
20453
|
+
])
|
|
20454
|
+
);
|
|
20455
|
+
var SUPPRESSION = 'Rename the declaration, or record the new signature in a ".d.luam" file so later calls are checked against it.';
|
|
20456
|
+
function reportShadowedGlobal(context, name, position2) {
|
|
20457
|
+
if (context.isDeclarationFile || !context.binder.isBuiltinReference(name)) {
|
|
20458
|
+
return;
|
|
20459
|
+
}
|
|
20460
|
+
const message = `"${name}" is an API this environment declares. Later calls are still checked against the declared signature, not this one. ${SUPPRESSION}`;
|
|
20461
|
+
context.warn("check-shadowed-api", message, position2);
|
|
20462
|
+
}
|
|
20463
|
+
function reportShadowedHelper(context, library, member, position2) {
|
|
20464
|
+
if (context.isDeclarationFile || !isLibrary(library) || findLibraryMember(library, member) === null) {
|
|
20465
|
+
return;
|
|
20466
|
+
}
|
|
20467
|
+
const target = `${library}.${member}`;
|
|
20468
|
+
const rewrite = HELPER_TARGETS.get(target);
|
|
20469
|
+
const lowered = rewrite === void 0 ? "" : ` The extension "${rewrite}" lowers to it.`;
|
|
20470
|
+
const message = `"${target}" is part of the standard library this build models.${lowered} Later calls are still checked against the declared signature, not this one. ${SUPPRESSION}`;
|
|
20471
|
+
context.warn("check-shadowed-helper", message, position2);
|
|
20472
|
+
}
|
|
20473
|
+
function reportImplicitGlobal(context, name, position2) {
|
|
20474
|
+
if (context.isDeclarationFile || !context.noImplicitGlobals) {
|
|
20475
|
+
return;
|
|
20476
|
+
}
|
|
20477
|
+
const message = `"${name}" is not declared anywhere this file can reach, so this assignment creates a global. Declare it with "local", annotate it as a global, or describe it in a ".d.luam" file.`;
|
|
20478
|
+
context.warn("check-implicit-global", message, position2);
|
|
20479
|
+
}
|
|
20480
|
+
|
|
19895
20481
|
// ../compiler/src/checker/union-members.ts
|
|
19896
20482
|
function isShapeOption(context, option) {
|
|
19897
20483
|
if (option.kind === "record") {
|
|
@@ -20113,8 +20699,12 @@ function negatedFacts(context, condition) {
|
|
|
20113
20699
|
// ../compiler/src/checker/control-flow.ts
|
|
20114
20700
|
var ITERATOR_FUNCTIONS = /* @__PURE__ */ new Set(["pairs", "ipairs"]);
|
|
20115
20701
|
function checkBlock(context, body) {
|
|
20702
|
+
const opened = new Set(context.recordObligationPaths());
|
|
20116
20703
|
context.binder.pushScope();
|
|
20704
|
+
context.blockDepth += 1;
|
|
20117
20705
|
checkStatements(context, body);
|
|
20706
|
+
context.blockDepth -= 1;
|
|
20707
|
+
settleRecordObligations(context, opened);
|
|
20118
20708
|
const declared = context.binder.currentScopeNames();
|
|
20119
20709
|
context.binder.popScope();
|
|
20120
20710
|
for (const name of declared) {
|
|
@@ -20298,7 +20888,7 @@ function checkEventDeclaration(context, declaration) {
|
|
|
20298
20888
|
}
|
|
20299
20889
|
|
|
20300
20890
|
// ../compiler/src/checker/statements.ts
|
|
20301
|
-
var
|
|
20891
|
+
var ORIGIN2 = { line: 0, column: 0, offset: 0 };
|
|
20302
20892
|
function minimumArguments(context, parameters) {
|
|
20303
20893
|
const index = parameters.findIndex((parameter) => {
|
|
20304
20894
|
const type = context.resolveAnnotation(parameter.annotation);
|
|
@@ -20306,12 +20896,17 @@ function minimumArguments(context, parameters) {
|
|
|
20306
20896
|
});
|
|
20307
20897
|
return index === -1 ? parameters.length : index;
|
|
20308
20898
|
}
|
|
20309
|
-
function buildFunctionType(context, parameters, returnAnnotation, contextual = null) {
|
|
20899
|
+
function buildFunctionType(context, parameters, returnAnnotation, contextual = null, isAsync = false) {
|
|
20310
20900
|
const isVariadic = parameters.some((parameter) => parameter.isVararg);
|
|
20311
20901
|
const named2 = parameters.filter((parameter) => !parameter.isVararg);
|
|
20312
|
-
const types = named2.map(
|
|
20902
|
+
const types = named2.map(
|
|
20903
|
+
(parameter, index) => parameter.annotation === null ? contextual?.parameters[index] ?? ANY_TYPE : context.resolveValueAnnotation(parameter.annotation, "a parameter")
|
|
20904
|
+
);
|
|
20313
20905
|
const names = named2.map((parameter) => parameter.name);
|
|
20314
|
-
|
|
20906
|
+
reportAsyncAnnotation(context, isAsync, returnAnnotation);
|
|
20907
|
+
const declared = context.resolveAnnotation(asyncInnerAnnotation(isAsync, returnAnnotation));
|
|
20908
|
+
const returnType = isAsync ? promiseOf(declared) : declared;
|
|
20909
|
+
return createFunction(types, returnType, minimumArguments(context, parameters), isVariadic, names);
|
|
20315
20910
|
}
|
|
20316
20911
|
function applyTypeParameters(context, type, names, constraints) {
|
|
20317
20912
|
if (names.length === 0) {
|
|
@@ -20337,14 +20932,16 @@ function reportMissingReturn(context, declared, position2) {
|
|
|
20337
20932
|
const repair = declared.kind === "tuple" ? "Add a return on every path." : `Add a return on every path, or declare "${name}?".`;
|
|
20338
20933
|
context.report("check-missing-return", `This function declares "${name}" but can end without returning a value. ${repair}`, position2);
|
|
20339
20934
|
}
|
|
20340
|
-
function checkFunctionBody(context, parameters, returnAnnotation, body, signature2, selfType2, position2 =
|
|
20935
|
+
function checkFunctionBody(context, parameters, returnAnnotation, body, signature2, selfType2, position2 = ORIGIN2, frame = { isAsync: false, isExpression: false }) {
|
|
20341
20936
|
forgetAssignedPaths(context, body);
|
|
20342
20937
|
const entry = context.flowState;
|
|
20938
|
+
const annotation = asyncInnerAnnotation(frame.isAsync, returnAnnotation);
|
|
20343
20939
|
context.setFlow(cloneFlow(entry));
|
|
20344
20940
|
context.binder.pushScope();
|
|
20345
|
-
context.
|
|
20941
|
+
context.pushFunctionFrame(frame);
|
|
20942
|
+
context.pushReturnType(annotation === null ? null : context.resolveAnnotation(annotation));
|
|
20346
20943
|
if (selfType2 !== null) {
|
|
20347
|
-
context.binder.declare({ name: "self", type: selfType2, isLocal: true, position:
|
|
20944
|
+
context.binder.declare({ name: "self", type: selfType2, isLocal: true, position: ORIGIN2 });
|
|
20348
20945
|
}
|
|
20349
20946
|
let parameterIndex = 0;
|
|
20350
20947
|
for (const parameter of parameters) {
|
|
@@ -20354,15 +20951,20 @@ function checkFunctionBody(context, parameters, returnAnnotation, body, signatur
|
|
|
20354
20951
|
parameterIndex += 1;
|
|
20355
20952
|
}
|
|
20356
20953
|
}
|
|
20954
|
+
const opened = new Set(context.recordObligationPaths());
|
|
20955
|
+
context.blockDepth += 1;
|
|
20357
20956
|
checkStatements(context, body);
|
|
20957
|
+
context.blockDepth -= 1;
|
|
20958
|
+
settleRecordObligations(context, opened);
|
|
20358
20959
|
const declared = context.currentReturnType();
|
|
20359
20960
|
if (declared !== null && context.flowState.reachable && !toleratesFallthrough(declared)) {
|
|
20360
20961
|
reportMissingReturn(context, declared, position2);
|
|
20361
20962
|
}
|
|
20362
20963
|
const inferred = context.popReturnType();
|
|
20363
|
-
if (
|
|
20364
|
-
signature2.returnType = inferred;
|
|
20964
|
+
if (annotation === null) {
|
|
20965
|
+
signature2.returnType = frame.isAsync ? promiseOf(inferred) : inferred;
|
|
20365
20966
|
}
|
|
20967
|
+
context.popFunctionFrame();
|
|
20366
20968
|
context.binder.popScope();
|
|
20367
20969
|
context.setFlow(entry);
|
|
20368
20970
|
}
|
|
@@ -20383,9 +20985,11 @@ function checkLocal(context, statement) {
|
|
|
20383
20985
|
context.binder.declare({ name: declaration.name, type: inferred, isLocal: true, position: declaration.position, origin: "local" });
|
|
20384
20986
|
return;
|
|
20385
20987
|
}
|
|
20386
|
-
const declared = context.
|
|
20387
|
-
|
|
20388
|
-
|
|
20988
|
+
const declared = context.resolveValueAnnotation(declaration.annotation, "a local");
|
|
20989
|
+
const subject = `Variable "${declaration.name}"`;
|
|
20990
|
+
const deferred = value !== void 0 && deferRecordCompletion(context, { kind: "identifier", name: declaration.name, position: declaration.position }, valueType, declared, subject, value.position);
|
|
20991
|
+
if (value !== void 0 && !deferred) {
|
|
20992
|
+
context.expectAssignable(valueType, declared, value.position, subject);
|
|
20389
20993
|
}
|
|
20390
20994
|
context.binder.declare({ name: declaration.name, type: declared, isLocal: true, position: declaration.position, origin: "local" });
|
|
20391
20995
|
if (value !== void 0) {
|
|
@@ -20404,6 +21008,13 @@ function checkCompoundOperand(context, operator, type, position2) {
|
|
|
20404
21008
|
context.report("check-invalid-operand", `Operator "${operator}" cannot be applied to "${typeToString(type)}".`, position2);
|
|
20405
21009
|
}
|
|
20406
21010
|
}
|
|
21011
|
+
var DELETABLE_CONTAINERS = /* @__PURE__ */ new Set(["map", "array", "table"]);
|
|
21012
|
+
function deletesContainerKey(context, target, valueType) {
|
|
21013
|
+
if (valueType.kind !== "nil" || target.kind !== "index-expression" && target.kind !== "member-expression") {
|
|
21014
|
+
return false;
|
|
21015
|
+
}
|
|
21016
|
+
return DELETABLE_CONTAINERS.has(context.typeOf(target.object).kind);
|
|
21017
|
+
}
|
|
20407
21018
|
function recordAssignedFact(context, path, valueType, declared) {
|
|
20408
21019
|
if (path === null || valueType.kind === "any") {
|
|
20409
21020
|
return;
|
|
@@ -20420,9 +21031,12 @@ function checkAssignment(context, statement) {
|
|
|
20420
21031
|
if (assigned !== null) {
|
|
20421
21032
|
context.forgetNarrowing(assigned);
|
|
20422
21033
|
}
|
|
20423
|
-
const targetType = checkExpression(context, target);
|
|
20424
21034
|
const valueType = valueTypes[index] ?? NIL_TYPE;
|
|
20425
21035
|
const value = valueAt(statement.values, valueTypes, index);
|
|
21036
|
+
if (value !== void 0 && extendInferredRecord(context, target, valueType)) {
|
|
21037
|
+
return;
|
|
21038
|
+
}
|
|
21039
|
+
const targetType = checkExpression(context, target);
|
|
20426
21040
|
if (target.kind === "member-expression") {
|
|
20427
21041
|
const object = context.typeOf(target.object);
|
|
20428
21042
|
const frame = context.currentClassMethod();
|
|
@@ -20441,29 +21055,74 @@ function checkAssignment(context, statement) {
|
|
|
20441
21055
|
return;
|
|
20442
21056
|
}
|
|
20443
21057
|
if (target.kind === "identifier" && context.binder.lookup(target.name) === null) {
|
|
21058
|
+
reportImplicitGlobal(context, target.name, target.position);
|
|
20444
21059
|
context.declareModuleGlobal({ name: target.name, type: valueType, isLocal: false, position: target.position });
|
|
20445
21060
|
return;
|
|
20446
21061
|
}
|
|
21062
|
+
if (!context.insideFunction()) {
|
|
21063
|
+
reportShadowedAssignment(context, target);
|
|
21064
|
+
}
|
|
20447
21065
|
const declared = target.kind === "identifier" ? context.binder.lookup(target.name)?.type ?? targetType : targetType;
|
|
21066
|
+
if (deletesContainerKey(context, target, valueType)) {
|
|
21067
|
+
return;
|
|
21068
|
+
}
|
|
21069
|
+
if (value !== void 0 && dischargeRecordKey(context, target, valueType, value.position)) {
|
|
21070
|
+
return;
|
|
21071
|
+
}
|
|
21072
|
+
const path = pathOf2(target);
|
|
21073
|
+
if (path !== null) {
|
|
21074
|
+
context.closeRecordObligation(path);
|
|
21075
|
+
}
|
|
21076
|
+
if (value !== void 0 && deferRecordCompletion(context, target, valueType, declared, "Assignment", value.position)) {
|
|
21077
|
+
return;
|
|
21078
|
+
}
|
|
20448
21079
|
if (value !== void 0) {
|
|
20449
21080
|
context.expectAssignable(valueType, declared, value.position, "Assignment");
|
|
20450
21081
|
}
|
|
20451
21082
|
recordAssignedFact(context, pathOf2(target), valueType, declared);
|
|
20452
21083
|
});
|
|
20453
21084
|
}
|
|
21085
|
+
function rootIdentifier(expression) {
|
|
21086
|
+
if (expression.kind === "identifier") {
|
|
21087
|
+
return expression.name;
|
|
21088
|
+
}
|
|
21089
|
+
return expression.kind === "member-expression" || expression.kind === "index-expression" ? rootIdentifier(expression.object) : null;
|
|
21090
|
+
}
|
|
21091
|
+
function reportShadowedAssignment(context, target) {
|
|
21092
|
+
if (target.kind !== "identifier") {
|
|
21093
|
+
const root = rootIdentifier(target);
|
|
21094
|
+
if (root !== null && context.binder.lookup(root) === null) {
|
|
21095
|
+
reportImplicitGlobal(context, root, target.position);
|
|
21096
|
+
}
|
|
21097
|
+
}
|
|
21098
|
+
if (target.kind === "identifier") {
|
|
21099
|
+
reportShadowedGlobal(context, target.name, target.position);
|
|
21100
|
+
return;
|
|
21101
|
+
}
|
|
21102
|
+
if (target.kind === "member-expression" && target.object.kind === "identifier") {
|
|
21103
|
+
reportShadowedHelper(context, target.object.name, target.property, target.position);
|
|
21104
|
+
}
|
|
21105
|
+
}
|
|
20454
21106
|
function checkFunctionDeclaration(context, statement) {
|
|
20455
|
-
const built = buildFunctionType(context, statement.parameters, statement.returnAnnotation);
|
|
21107
|
+
const built = buildFunctionType(context, statement.parameters, statement.returnAnnotation, null, statement.isAsync);
|
|
20456
21108
|
const type = applyTypeParameters(context, built, statement.typeParameters, statement.typeConstraints);
|
|
20457
21109
|
if (statement.name.kind === "identifier") {
|
|
20458
21110
|
const symbol = { name: statement.name.name, type, isLocal: statement.isLocal, position: statement.position };
|
|
20459
21111
|
if (statement.isLocal) {
|
|
20460
21112
|
context.binder.declare({ ...symbol, origin: "local" });
|
|
20461
21113
|
} else {
|
|
21114
|
+
reportShadowedGlobal(context, statement.name.name, statement.position);
|
|
20462
21115
|
context.declareModuleGlobal(symbol);
|
|
20463
21116
|
}
|
|
20464
21117
|
}
|
|
21118
|
+
if (!statement.isLocal && statement.name.kind !== "identifier") {
|
|
21119
|
+
reportShadowedAssignment(context, statement.name);
|
|
21120
|
+
}
|
|
20465
21121
|
context.record(statement.name, type);
|
|
20466
|
-
checkFunctionBody(context, statement.parameters, statement.returnAnnotation, statement.body, type, statement.isMethod ? ANY_TYPE : null, statement.position
|
|
21122
|
+
checkFunctionBody(context, statement.parameters, statement.returnAnnotation, statement.body, type, statement.isMethod ? ANY_TYPE : null, statement.position, {
|
|
21123
|
+
isAsync: statement.isAsync,
|
|
21124
|
+
isExpression: false
|
|
21125
|
+
});
|
|
20467
21126
|
}
|
|
20468
21127
|
function checkReturn(context, statement) {
|
|
20469
21128
|
const valueTypes = checkValueList(context, statement.values);
|
|
@@ -20514,7 +21173,34 @@ function checkDeclareStatement(context, statement) {
|
|
|
20514
21173
|
}
|
|
20515
21174
|
const type = context.resolveAnnotation(statement.annotation);
|
|
20516
21175
|
context.declareModuleGlobal({ name: statement.name, type, isLocal: false, position: statement.position });
|
|
20517
|
-
context.declarations.declareGlobal({ name: statement.name, type, position: statement.position });
|
|
21176
|
+
context.declarations.declareGlobal({ name: statement.name, type, isDeclared: true, position: statement.position });
|
|
21177
|
+
}
|
|
21178
|
+
function checkGlobalStatement(context, statement) {
|
|
21179
|
+
const declaration = statement.declaration;
|
|
21180
|
+
const declared = declaration.annotation === null ? ANY_TYPE : context.resolveValueAnnotation(declaration.annotation, "a global");
|
|
21181
|
+
const valueTypes = checkValueList(context, statement.values);
|
|
21182
|
+
const value = valueAt(statement.values, valueTypes, 0);
|
|
21183
|
+
if (context.insideFunction()) {
|
|
21184
|
+
const message = `A type on global "${declaration.name}" is only valid at the top level of a file. Assign it without the annotation here.`;
|
|
21185
|
+
context.report("check-global-annotation-scope", message, statement.position);
|
|
21186
|
+
return;
|
|
21187
|
+
}
|
|
21188
|
+
const existing = context.declarations.lookupGlobal(declaration.name);
|
|
21189
|
+
const contract = existing !== null && existing.isDeclared === true ? existing.type : declared;
|
|
21190
|
+
if (existing !== null && existing.isDeclared !== true) {
|
|
21191
|
+
context.report("check-duplicate-global", `Global "${declaration.name}" is already declared with a type.`, statement.position);
|
|
21192
|
+
}
|
|
21193
|
+
if (value !== void 0) {
|
|
21194
|
+
context.expectAssignable(valueTypes[0] ?? NIL_TYPE, contract, value.position, `Global "${declaration.name}"`);
|
|
21195
|
+
}
|
|
21196
|
+
context.forgetNarrowing(declaration.name);
|
|
21197
|
+
context.declareModuleGlobal({ name: declaration.name, type: contract, isLocal: false, position: declaration.position });
|
|
21198
|
+
if (existing === null) {
|
|
21199
|
+
context.declarations.declareGlobal({ name: declaration.name, type: contract, position: declaration.position });
|
|
21200
|
+
}
|
|
21201
|
+
if (value !== void 0) {
|
|
21202
|
+
recordAssignedFact(context, declaration.name, valueTypes[0] ?? NIL_TYPE, contract);
|
|
21203
|
+
}
|
|
20518
21204
|
}
|
|
20519
21205
|
function checkStatement(context, statement) {
|
|
20520
21206
|
switch (statement.kind) {
|
|
@@ -20522,6 +21208,8 @@ function checkStatement(context, statement) {
|
|
|
20522
21208
|
return checkLocal(context, statement);
|
|
20523
21209
|
case "assignment-statement":
|
|
20524
21210
|
return checkAssignment(context, statement);
|
|
21211
|
+
case "global-statement":
|
|
21212
|
+
return checkGlobalStatement(context, statement);
|
|
20525
21213
|
case "call-statement":
|
|
20526
21214
|
checkExpression(context, statement.expression);
|
|
20527
21215
|
return;
|
|
@@ -20548,11 +21236,15 @@ function checkStatement(context, statement) {
|
|
|
20548
21236
|
case "generic-for-statement":
|
|
20549
21237
|
return checkGenericFor(context, statement);
|
|
20550
21238
|
case "type-alias-statement": {
|
|
20551
|
-
const resolved2 = context.
|
|
21239
|
+
const resolved2 = context.resolveValueAnnotation(statement.annotation, "a type alias");
|
|
20552
21240
|
const shape = statement.annotation.kind === "type-object" || statement.annotation.kind === "type-intersection";
|
|
20553
21241
|
const named2 = shape ? renameRecord(resolved2, statement.name) : resolved2;
|
|
21242
|
+
if (context.isAmbientAlias(statement.name)) {
|
|
21243
|
+
context.report("check-duplicate-type", `Type "${statement.name}" is already defined.`, statement.position);
|
|
21244
|
+
}
|
|
20554
21245
|
context.noteTypeParameters(statement.typeParameters);
|
|
20555
21246
|
context.binder.declareAlias(statement.name, named2, statement.typeParameters);
|
|
21247
|
+
context.declarations.declareAlias({ name: statement.name, typeParameters: statement.typeParameters, type: named2, position: statement.position });
|
|
20556
21248
|
return;
|
|
20557
21249
|
}
|
|
20558
21250
|
case "declare-statement":
|
|
@@ -20590,6 +21282,19 @@ function templateLiteralText(segments) {
|
|
|
20590
21282
|
return segments.map((segment) => segment.kind === "text" ? segment.value : `\${${segment.value}}`).join("");
|
|
20591
21283
|
}
|
|
20592
21284
|
|
|
21285
|
+
// ../compiler/src/checker/value-distribution.ts
|
|
21286
|
+
function distributeValueTypes(types) {
|
|
21287
|
+
const distributed = [];
|
|
21288
|
+
types.forEach((type, index) => {
|
|
21289
|
+
if (index === types.length - 1) {
|
|
21290
|
+
distributed.push(...valuesOf(type));
|
|
21291
|
+
return;
|
|
21292
|
+
}
|
|
21293
|
+
distributed.push(firstValueOf(type));
|
|
21294
|
+
});
|
|
21295
|
+
return distributed;
|
|
21296
|
+
}
|
|
21297
|
+
|
|
20593
21298
|
// ../compiler/src/checker/expressions.ts
|
|
20594
21299
|
var NAME_PATH_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*$/;
|
|
20595
21300
|
var EXTENSION_RESULTS = {
|
|
@@ -20633,7 +21338,8 @@ function checkMember(context, expression) {
|
|
|
20633
21338
|
checkExpression(context, expression.object);
|
|
20634
21339
|
return context.record(expression, library);
|
|
20635
21340
|
}
|
|
20636
|
-
const
|
|
21341
|
+
const received = checkExpression(context, expression.object);
|
|
21342
|
+
const objectType = received.kind === "optional" ? received.element : received;
|
|
20637
21343
|
if (objectType.kind === "record") {
|
|
20638
21344
|
return context.record(expression, resolveRecordMember(context, objectType, expression));
|
|
20639
21345
|
}
|
|
@@ -20656,26 +21362,44 @@ function checkMember(context, expression) {
|
|
|
20656
21362
|
}
|
|
20657
21363
|
return context.record(expression, extension === null ? ANY_TYPE : EXTENSION_RESULTS[extension.result]);
|
|
20658
21364
|
}
|
|
21365
|
+
function spreadsUnknownArity(args, argumentTypes) {
|
|
21366
|
+
if (args.length === 0 || args.length !== argumentTypes.length) {
|
|
21367
|
+
return false;
|
|
21368
|
+
}
|
|
21369
|
+
return args[args.length - 1]?.kind === "call-expression" && argumentTypes[argumentTypes.length - 1]?.kind === "any";
|
|
21370
|
+
}
|
|
21371
|
+
function resolveKeyedMember(context, objectType, expression) {
|
|
21372
|
+
if (expression.index.kind !== "string-literal" || objectType.kind !== "record" && objectType.kind !== "named") {
|
|
21373
|
+
return null;
|
|
21374
|
+
}
|
|
21375
|
+
const access = { kind: "member-expression", object: expression.object, property: expression.index.value, position: expression.index.position };
|
|
21376
|
+
return objectType.kind === "record" ? resolveRecordMember(context, objectType, access) : resolveNamedMember(context, objectType, access);
|
|
21377
|
+
}
|
|
20659
21378
|
function countArguments2(total) {
|
|
20660
21379
|
return total === 1 ? "1 argument" : `${total} arguments`;
|
|
20661
21380
|
}
|
|
20662
21381
|
function checkSignature(context, args, declared, position2, owner = "This call", typeArguments = []) {
|
|
20663
21382
|
const argumentTypes = checkValueList(context, args, declared.parameters);
|
|
20664
21383
|
const signature2 = specializeCall(context, owner, declared, argumentTypes, typeArguments, position2);
|
|
20665
|
-
|
|
21384
|
+
const spreads = spreadsUnknownArity(args, argumentTypes);
|
|
21385
|
+
const fixed = spreads ? argumentTypes.length - 1 : argumentTypes.length;
|
|
21386
|
+
if (!spreads && argumentTypes.length < signature2.minimumArguments) {
|
|
20666
21387
|
const message = `This call expects at least ${countArguments2(signature2.minimumArguments)} but received ${argumentTypes.length}.`;
|
|
20667
21388
|
context.report("check-argument-count", message, position2);
|
|
20668
21389
|
}
|
|
20669
|
-
if (!signature2.isVariadic &&
|
|
21390
|
+
if (!signature2.isVariadic && fixed > signature2.parameters.length) {
|
|
20670
21391
|
const message = `This call expects at most ${countArguments2(signature2.parameters.length)} but received ${argumentTypes.length}.`;
|
|
20671
21392
|
context.report("check-argument-count", message, position2);
|
|
20672
21393
|
}
|
|
20673
21394
|
signature2.parameters.forEach((parameter, index) => {
|
|
20674
21395
|
const argumentType = argumentTypes[index];
|
|
20675
21396
|
const argument = args[index];
|
|
20676
|
-
if (argumentType
|
|
20677
|
-
|
|
21397
|
+
if (argumentType === void 0 || argument === void 0) {
|
|
21398
|
+
return;
|
|
20678
21399
|
}
|
|
21400
|
+
const optional = index >= signature2.minimumArguments && parameter.kind !== "optional";
|
|
21401
|
+
const expected = optional ? createOptional(parameter) : parameter;
|
|
21402
|
+
context.expectAssignable(argumentType, expected, argument.position, `Argument ${index + 1}`, parameter);
|
|
20679
21403
|
});
|
|
20680
21404
|
if (signature2.isVariadic && signature2.variadicType !== void 0) {
|
|
20681
21405
|
for (let index = signature2.parameters.length; index < argumentTypes.length; index += 1) {
|
|
@@ -20688,6 +21412,20 @@ function checkSignature(context, args, declared, position2, owner = "This call",
|
|
|
20688
21412
|
}
|
|
20689
21413
|
return signature2.returnType;
|
|
20690
21414
|
}
|
|
21415
|
+
function reportClassReceiver(context, name, method, position2) {
|
|
21416
|
+
if (context.declarations.lookupStaticMember(name, method) !== null) {
|
|
21417
|
+
const message2 = `Call the static member "${method}" as "${name}.${method}(...)". A class value has no "self" to pass.`;
|
|
21418
|
+
context.report("check-static-receiver", message2, position2);
|
|
21419
|
+
return;
|
|
21420
|
+
}
|
|
21421
|
+
if (context.declarations.lookupMember(name, method) === null) {
|
|
21422
|
+
const message2 = `Call the static member "${method}" as "${name}.${method}(...)". A class value has no "self" to pass.`;
|
|
21423
|
+
context.report("check-static-receiver", message2, position2);
|
|
21424
|
+
return;
|
|
21425
|
+
}
|
|
21426
|
+
const message = `The receiver here is the class "${name}" itself, and "${method}" is one of its instance members. Create an instance \u2014 "local value = new ${name}()" \u2014 and call "value:${method}(...)", or read the member from a value of that class. Where the class and its single instance share one name, give the instance its own name.`;
|
|
21427
|
+
context.report("check-class-receiver", message, position2);
|
|
21428
|
+
}
|
|
20691
21429
|
function callOwner(expression) {
|
|
20692
21430
|
const name = expression.method ?? (expression.callee.kind === "identifier" ? expression.callee.name : null);
|
|
20693
21431
|
return name === null ? "This call" : `Function "${name}"`;
|
|
@@ -20737,6 +21475,9 @@ function checkMethodCall(context, expression, method, receiver) {
|
|
|
20737
21475
|
return checkSignature(context, expression.args, member.type, expression.position);
|
|
20738
21476
|
}
|
|
20739
21477
|
function checkCall(context, expression) {
|
|
21478
|
+
if (expression.method === null && expression.callee.kind === "identifier") {
|
|
21479
|
+
reportSleepOutsideAsync(context, expression.callee.name, expression.position);
|
|
21480
|
+
}
|
|
20740
21481
|
const contracted = checkResourceCall(context, expression);
|
|
20741
21482
|
if (contracted !== null) {
|
|
20742
21483
|
return context.record(expression, contracted);
|
|
@@ -20759,9 +21500,7 @@ function checkCall(context, expression) {
|
|
|
20759
21500
|
return context.record(expression, checkSignature(context, expression.args, constructor, expression.position));
|
|
20760
21501
|
}
|
|
20761
21502
|
if (expression.method !== null && expression.callee.kind === "identifier" && isUserClassReference(context, expression.callee.name)) {
|
|
20762
|
-
|
|
20763
|
-
const message = `Call the static member "${expression.method}" as "${name}.${expression.method}(...)". A class value has no "self" to pass.`;
|
|
20764
|
-
context.report("check-static-receiver", message, expression.position);
|
|
21503
|
+
reportClassReceiver(context, expression.callee.name, expression.method, expression.position);
|
|
20765
21504
|
checkValueList(context, expression.args);
|
|
20766
21505
|
return context.record(expression, ANY_TYPE);
|
|
20767
21506
|
}
|
|
@@ -20840,6 +21579,8 @@ function checkMultiValueExpression(context, expression, expected = null) {
|
|
|
20840
21579
|
const symbol = context.binder.lookup(expression.name);
|
|
20841
21580
|
if (symbol === null) {
|
|
20842
21581
|
checkGlobalReference(context, expression.name, expression.position);
|
|
21582
|
+
} else {
|
|
21583
|
+
checkSharedReference(context, expression.name, expression.position);
|
|
20843
21584
|
}
|
|
20844
21585
|
if (symbol === null || symbol.isLocal !== true) {
|
|
20845
21586
|
context.noteGlobalReference(expression.name);
|
|
@@ -20855,6 +21596,10 @@ function checkMultiValueExpression(context, expression, expected = null) {
|
|
|
20855
21596
|
context.expectAssignable(indexType, objectType.key, expression.index.position, "Key");
|
|
20856
21597
|
return context.record(expression, objectType.value);
|
|
20857
21598
|
}
|
|
21599
|
+
const keyed = resolveKeyedMember(context, objectType, expression);
|
|
21600
|
+
if (keyed !== null) {
|
|
21601
|
+
return context.record(expression, keyed);
|
|
21602
|
+
}
|
|
20858
21603
|
return context.record(expression, objectType.kind === "array" ? objectType.element : ANY_TYPE);
|
|
20859
21604
|
}
|
|
20860
21605
|
case "call-expression":
|
|
@@ -20864,9 +21609,12 @@ function checkMultiValueExpression(context, expression, expected = null) {
|
|
|
20864
21609
|
case "table-expression":
|
|
20865
21610
|
return checkTable(context, expression);
|
|
20866
21611
|
case "function-expression": {
|
|
20867
|
-
const built = buildFunctionType(context, expression.parameters, expression.returnAnnotation, contextualFunction(expected));
|
|
21612
|
+
const built = buildFunctionType(context, expression.parameters, expression.returnAnnotation, contextualFunction(expected), expression.isAsync);
|
|
20868
21613
|
const type = applyTypeParameters(context, built, expression.typeParameters, expression.typeConstraints);
|
|
20869
|
-
checkFunctionBody(context, expression.parameters, expression.returnAnnotation, expression.body, type, null, expression.position
|
|
21614
|
+
checkFunctionBody(context, expression.parameters, expression.returnAnnotation, expression.body, type, null, expression.position, {
|
|
21615
|
+
isAsync: expression.isAsync,
|
|
21616
|
+
isExpression: true
|
|
21617
|
+
});
|
|
20870
21618
|
return context.record(expression, type);
|
|
20871
21619
|
}
|
|
20872
21620
|
case "binary-expression": {
|
|
@@ -20876,6 +21624,8 @@ function checkMultiValueExpression(context, expression, expected = null) {
|
|
|
20876
21624
|
}
|
|
20877
21625
|
case "unary-expression":
|
|
20878
21626
|
return checkUnary(context, expression.operator, checkExpression(context, expression.operand), expression);
|
|
21627
|
+
case "await-expression":
|
|
21628
|
+
return context.record(expression, awaitedType(context, checkExpression(context, expression.operand), expression));
|
|
20879
21629
|
default:
|
|
20880
21630
|
return context.record(expression, checkExpression(context, expression.expression, expected));
|
|
20881
21631
|
}
|
|
@@ -20884,16 +21634,12 @@ function checkExpression(context, expression, expected = null) {
|
|
|
20884
21634
|
return firstValueOf(checkMultiValueExpression(context, expression, expected));
|
|
20885
21635
|
}
|
|
20886
21636
|
function checkValueList(context, values, expected = []) {
|
|
20887
|
-
const types =
|
|
20888
|
-
values.forEach((value, index) => {
|
|
21637
|
+
const types = values.map((value, index) => {
|
|
20889
21638
|
const type = checkMultiValueExpression(context, value, expected[index] ?? null);
|
|
20890
|
-
|
|
20891
|
-
|
|
20892
|
-
return;
|
|
20893
|
-
}
|
|
20894
|
-
types.push(firstValueOf(type));
|
|
21639
|
+
escapesRecordObligation(context, value);
|
|
21640
|
+
return type;
|
|
20895
21641
|
});
|
|
20896
|
-
return types;
|
|
21642
|
+
return distributeValueTypes(types);
|
|
20897
21643
|
}
|
|
20898
21644
|
|
|
20899
21645
|
// ../compiler/src/checker/classes.ts
|
|
@@ -20902,7 +21648,7 @@ function fieldType(context, member) {
|
|
|
20902
21648
|
if (member.annotation === null) {
|
|
20903
21649
|
return valueType === null ? ANY_TYPE : widenInferred(valueType);
|
|
20904
21650
|
}
|
|
20905
|
-
const declared = context.
|
|
21651
|
+
const declared = context.resolveValueAnnotation(member.annotation, "a field");
|
|
20906
21652
|
if (valueType !== null && member.value !== null) {
|
|
20907
21653
|
context.expectAssignable(valueType, declared, member.value.position, `Field "${member.name}"`);
|
|
20908
21654
|
}
|
|
@@ -20955,7 +21701,12 @@ function registerMembers(context, info, statement) {
|
|
|
20955
21701
|
}
|
|
20956
21702
|
const generated = expandClassDecorators(context, statement, fieldTypes);
|
|
20957
21703
|
for (const member of [...statement.members, ...generated]) {
|
|
20958
|
-
const type = member.kind === "class-field" ? fieldTypes.get(member) ?? ANY_TYPE : member.isSynthetic ? syntheticMethodType(context, member, fieldTypes) : applyTypeParameters(
|
|
21704
|
+
const type = member.kind === "class-field" ? fieldTypes.get(member) ?? ANY_TYPE : member.isSynthetic ? syntheticMethodType(context, member, fieldTypes) : applyTypeParameters(
|
|
21705
|
+
context,
|
|
21706
|
+
buildFunctionType(context, member.parameters, member.returnAnnotation, null, member.isAsync),
|
|
21707
|
+
member.typeParameters,
|
|
21708
|
+
member.typeConstraints
|
|
21709
|
+
);
|
|
20959
21710
|
const decorators = member.decorators.map((decorator) => decorator.name);
|
|
20960
21711
|
if (member.kind === "class-method" && isMetamethodMember(member)) {
|
|
20961
21712
|
checkMetamethod(context, info.name, member, type);
|
|
@@ -20996,6 +21747,7 @@ function declareBuilder(context, info, statement) {
|
|
|
20996
21747
|
superClass: null,
|
|
20997
21748
|
superArguments: [],
|
|
20998
21749
|
interfaces: [],
|
|
21750
|
+
interfaceArguments: [],
|
|
20999
21751
|
members,
|
|
21000
21752
|
statics: /* @__PURE__ */ new Map(),
|
|
21001
21753
|
position: statement.position
|
|
@@ -21014,17 +21766,19 @@ function checkMethodBody(context, info, member) {
|
|
|
21014
21766
|
if (signature2?.kind !== "function") {
|
|
21015
21767
|
return;
|
|
21016
21768
|
}
|
|
21769
|
+
const frame = { isAsync: member.isAsync, isExpression: false };
|
|
21017
21770
|
if (member.isStatic) {
|
|
21018
|
-
checkFunctionBody(context, member.parameters, member.returnAnnotation, member.body, signature2, null, member.position);
|
|
21771
|
+
checkFunctionBody(context, member.parameters, member.returnAnnotation, member.body, signature2, null, member.position, frame);
|
|
21019
21772
|
return;
|
|
21020
21773
|
}
|
|
21021
21774
|
context.pushClassMethod({ className: info.name, methodName: member.name });
|
|
21022
|
-
checkFunctionBody(context, member.parameters, member.returnAnnotation, member.body, signature2, selfType(info), member.position);
|
|
21775
|
+
checkFunctionBody(context, member.parameters, member.returnAnnotation, member.body, signature2, selfType(info), member.position, frame);
|
|
21023
21776
|
context.popClassMethod();
|
|
21024
21777
|
}
|
|
21025
21778
|
function assignSuperClass(context, info, statement) {
|
|
21026
|
-
|
|
21027
|
-
info.
|
|
21779
|
+
const resolved2 = resolveSuperClass(context, statement);
|
|
21780
|
+
info.superClass = resolved2 ?? statement.superClass;
|
|
21781
|
+
info.hasUnresolvedParent = statement.superClass !== null && resolved2 === null;
|
|
21028
21782
|
}
|
|
21029
21783
|
function resolveSuperClass(context, statement) {
|
|
21030
21784
|
if (statement.superClass === null) {
|
|
@@ -21066,6 +21820,7 @@ function declareClassInfo(context, statement) {
|
|
|
21066
21820
|
superClass: null,
|
|
21067
21821
|
superArguments: [],
|
|
21068
21822
|
interfaces: statement.interfaces,
|
|
21823
|
+
interfaceArguments: statement.interfaceArguments.map((args) => args.map((argument) => context.resolveAnnotation(argument))),
|
|
21069
21824
|
members: /* @__PURE__ */ new Map(),
|
|
21070
21825
|
statics: /* @__PURE__ */ new Map(),
|
|
21071
21826
|
position: statement.position
|
|
@@ -21100,10 +21855,12 @@ function checkClassDeclaration(context, statement) {
|
|
|
21100
21855
|
}
|
|
21101
21856
|
}
|
|
21102
21857
|
function checkInterfaceDeclaration(context, statement) {
|
|
21103
|
-
|
|
21858
|
+
const existing = context.declarations.lookupInterface(statement.name);
|
|
21859
|
+
if (existing !== null && existing.isBuiltin !== true) {
|
|
21104
21860
|
context.report("check-duplicate-interface", `Interface "${statement.name}" is already defined.`, statement.position);
|
|
21105
21861
|
return;
|
|
21106
21862
|
}
|
|
21863
|
+
context.noteTypeParameters(statement.typeParameters);
|
|
21107
21864
|
const members = /* @__PURE__ */ new Map();
|
|
21108
21865
|
for (const name of new Set(statement.superInterfaces)) {
|
|
21109
21866
|
const parent = context.declarations.lookupInterface(name);
|
|
@@ -21120,7 +21877,7 @@ function checkInterfaceDeclaration(context, statement) {
|
|
|
21120
21877
|
context.report("check-duplicate-interface-parent", `Interface "${statement.name}" extends the same interface more than once.`, statement.position);
|
|
21121
21878
|
}
|
|
21122
21879
|
for (const member of statement.members) {
|
|
21123
|
-
const type = member.kind === "interface-field" ? context.
|
|
21880
|
+
const type = member.kind === "interface-field" ? context.resolveValueAnnotation(member.annotation, "a member") : buildFunctionType(context, member.parameters, member.returnAnnotation);
|
|
21124
21881
|
const info = { name: member.name, type, isMethod: member.kind === "interface-method", position: member.position };
|
|
21125
21882
|
if (members.has(member.name)) {
|
|
21126
21883
|
context.report("check-duplicate-interface-member", `Interface "${statement.name}" declares member "${member.name}" more than once.`, member.position);
|
|
@@ -21131,16 +21888,18 @@ function checkInterfaceDeclaration(context, statement) {
|
|
|
21131
21888
|
const inherited = /* @__PURE__ */ new Map();
|
|
21132
21889
|
for (const parent of statement.superInterfaces) {
|
|
21133
21890
|
for (const member of context.declarations.collectInterfaceContract(parent)) {
|
|
21134
|
-
const
|
|
21135
|
-
if (
|
|
21891
|
+
const existing2 = members.get(member.name) ?? inherited.get(member.name);
|
|
21892
|
+
if (existing2 !== void 0 && (existing2.isMethod !== member.isMethod || typeToString(existing2.type) !== typeToString(member.type))) {
|
|
21136
21893
|
context.report("check-conflicting-interface-member", `Interface "${statement.name}" inherits conflicting declarations of "${member.name}".`, statement.position);
|
|
21137
|
-
} else if (
|
|
21894
|
+
} else if (existing2 === void 0) {
|
|
21138
21895
|
inherited.set(member.name, member);
|
|
21139
21896
|
}
|
|
21140
21897
|
}
|
|
21141
21898
|
}
|
|
21142
21899
|
context.declarations.declareInterface({
|
|
21143
21900
|
name: statement.name,
|
|
21901
|
+
typeParameters: statement.typeParameters,
|
|
21902
|
+
typeConstraints: statement.typeConstraints.map((constraint) => constraint === null ? null : context.resolveAnnotation(constraint)),
|
|
21144
21903
|
superInterfaces: statement.superInterfaces,
|
|
21145
21904
|
members,
|
|
21146
21905
|
position: statement.position
|
|
@@ -21263,12 +22022,14 @@ function check(program2, mode, environment = DEFAULT_ENVIRONMENT, options = {})
|
|
|
21263
22022
|
const ambient = options.ambient ?? EMPTY_AMBIENT;
|
|
21264
22023
|
const project = options.project ?? EMPTY_PROJECT_DECLARATIONS;
|
|
21265
22024
|
const context = new CheckContext(mode, environment, ambient, project, options.oop === true);
|
|
22025
|
+
context.noImplicitGlobals = options.noImplicitGlobals === true;
|
|
21266
22026
|
context.isDeclarationFile = options.isDeclarationFile === true;
|
|
21267
22027
|
context.contracts = options.contracts ?? [];
|
|
21268
22028
|
const structure = context.isDeclarationFile ? checkDeclarationFile(program2.body) : checkJumps(program2.body);
|
|
21269
22029
|
const directives = collectDirectives(program2.body, { isDeclarationFile: context.isDeclarationFile });
|
|
21270
22030
|
predeclareModule(context, program2.body);
|
|
21271
22031
|
checkStatements(context, program2.body);
|
|
22032
|
+
settleRecordObligations(context, /* @__PURE__ */ new Set());
|
|
21272
22033
|
reportUnknownTypes(context);
|
|
21273
22034
|
reportUnusedSymbols(context, options.noUnusedLocals === true, options.noUnusedParameters === true);
|
|
21274
22035
|
const external = externalReferences(context);
|
|
@@ -21517,7 +22278,24 @@ function emitString(value) {
|
|
|
21517
22278
|
function emitParameters(parameters) {
|
|
21518
22279
|
return parameters.map((parameter) => parameter.isVararg ? "..." : parameter.name).join(", ");
|
|
21519
22280
|
}
|
|
21520
|
-
function
|
|
22281
|
+
function emitAsyncFunctionBody(state, parameters, body, header, receiver) {
|
|
22282
|
+
requireHelper(state, "promise");
|
|
22283
|
+
const declared = emitParameters(parameters);
|
|
22284
|
+
const forwarded = (receiver === null ? [declared] : [receiver, declared]).filter((part) => part.length > 0).join(", ");
|
|
22285
|
+
const previous = state.loopWrap;
|
|
22286
|
+
state.indent += 1;
|
|
22287
|
+
state.loopWrap = false;
|
|
22288
|
+
const lines = emitBlock(state, body);
|
|
22289
|
+
state.loopWrap = previous;
|
|
22290
|
+
state.indent -= 1;
|
|
22291
|
+
const signature2 = `${header}(${declared}) return Promise.spawn(function(${forwarded})`;
|
|
22292
|
+
const closing = indentLine(state, `end${forwarded.length === 0 ? "" : `, ${forwarded}`}) end`);
|
|
22293
|
+
return [signature2, ...lines, closing].join("\n");
|
|
22294
|
+
}
|
|
22295
|
+
function emitFunctionBody(state, parameters, body, header, isAsync = false, receiver = null) {
|
|
22296
|
+
if (isAsync) {
|
|
22297
|
+
return emitAsyncFunctionBody(state, parameters, body, header, receiver);
|
|
22298
|
+
}
|
|
21521
22299
|
const previous = state.loopWrap;
|
|
21522
22300
|
state.indent += 1;
|
|
21523
22301
|
state.loopWrap = false;
|
|
@@ -21627,7 +22405,7 @@ function emitExpression(state, expression, limit = 0) {
|
|
|
21627
22405
|
case "table-expression":
|
|
21628
22406
|
return emitTable(state, expression);
|
|
21629
22407
|
case "function-expression":
|
|
21630
|
-
return emitFunctionBody(state, expression.parameters, expression.body, "function");
|
|
22408
|
+
return emitFunctionBody(state, expression.parameters, expression.body, "function", expression.isAsync);
|
|
21631
22409
|
case "binary-expression":
|
|
21632
22410
|
return emitBinary(state, expression, limit);
|
|
21633
22411
|
case "unary-expression": {
|
|
@@ -21635,19 +22413,26 @@ function emitExpression(state, expression, limit = 0) {
|
|
|
21635
22413
|
const text = expression.operator === "not" ? `not ${operand}` : `${expression.operator}${operand}`;
|
|
21636
22414
|
return UNARY_PRECEDENCE < limit ? `(${text})` : text;
|
|
21637
22415
|
}
|
|
22416
|
+
case "await-expression":
|
|
22417
|
+
requireHelper(state, "promise");
|
|
22418
|
+
return `Promise.await(${emitExpression(state, expression.operand)})`;
|
|
21638
22419
|
default:
|
|
21639
22420
|
return `(${emitExpression(state, expression.expression)})`;
|
|
21640
22421
|
}
|
|
21641
22422
|
}
|
|
21642
22423
|
|
|
21643
22424
|
// ../compiler/src/emitter/classes.ts
|
|
22425
|
+
var BARE_KEY = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
22426
|
+
function emitMemberKey(name) {
|
|
22427
|
+
return BARE_KEY.test(name) ? name : `[${emitString(name)}]`;
|
|
22428
|
+
}
|
|
21644
22429
|
function emitMethod(state, className, member) {
|
|
21645
22430
|
const self = { name: "self", annotation: null, isVararg: false, position: member.position };
|
|
21646
22431
|
if (member.generated !== void 0) {
|
|
21647
22432
|
return emitGeneratedMethod(state, className, member);
|
|
21648
22433
|
}
|
|
21649
22434
|
const parameters = member.isStatic ? member.parameters : [self, ...member.parameters];
|
|
21650
|
-
return withSymbol(state, `${className}${member.isStatic ? "." : ":"}${member.name}`, () => emitFunctionBody(state, parameters, member.body, `${member.name} = function
|
|
22435
|
+
return withSymbol(state, `${className}${member.isStatic ? "." : ":"}${member.name}`, () => emitFunctionBody(state, parameters, member.body, `${emitMemberKey(member.name)} = function`, member.isAsync));
|
|
21651
22436
|
}
|
|
21652
22437
|
function emitGeneratedMethod(state, className, member) {
|
|
21653
22438
|
const fields = member.generated?.fields ?? [];
|
|
@@ -21733,7 +22518,7 @@ function emitMembers(state, statement) {
|
|
|
21733
22518
|
continue;
|
|
21734
22519
|
}
|
|
21735
22520
|
const value = member.value === null ? "nil" : emitExpression(state, member.value);
|
|
21736
|
-
entries3.push(indentLine(state, `${markSource(state, member.position.line, statement.name)}${member.name} = ${value}`));
|
|
22521
|
+
entries3.push(indentLine(state, `${markSource(state, member.position.line, statement.name)}${emitMemberKey(member.name)} = ${value}`));
|
|
21737
22522
|
}
|
|
21738
22523
|
for (const generated of state.generatedMembers.get(statement) ?? []) {
|
|
21739
22524
|
entries3.push(indentLine(state, `${markSource(state, generated.position.line, `${statement.name}:${generated.name}`)}${emitMethod(state, statement.name, generated)}`));
|
|
@@ -21887,7 +22672,7 @@ function emitFunctionDeclaration(state, statement) {
|
|
|
21887
22672
|
const prefix = statement.isLocal ? "local function " : "function ";
|
|
21888
22673
|
const name = emitFunctionName(state, statement);
|
|
21889
22674
|
const header = `${prefix}${name}`;
|
|
21890
|
-
return withSymbol(state, name, () => emitFunctionBody(state, statement.parameters, statement.body, header));
|
|
22675
|
+
return withSymbol(state, name, () => emitFunctionBody(state, statement.parameters, statement.body, header, statement.isAsync, statement.isMethod ? "self" : null));
|
|
21891
22676
|
}
|
|
21892
22677
|
function emitNested2(state, body) {
|
|
21893
22678
|
state.indent += 1;
|
|
@@ -21926,6 +22711,8 @@ function emitStatement(state, statement) {
|
|
|
21926
22711
|
return emitLocal(state, statement);
|
|
21927
22712
|
case "assignment-statement":
|
|
21928
22713
|
return emitAssignment(state, statement);
|
|
22714
|
+
case "global-statement":
|
|
22715
|
+
return `${statement.declaration.name} = ${statement.values.map((value) => emitExpression(state, value)).join(", ")}`;
|
|
21929
22716
|
case "call-statement":
|
|
21930
22717
|
return emitExpression(state, statement.expression);
|
|
21931
22718
|
case "function-declaration":
|
|
@@ -22099,6 +22886,7 @@ function fromExpression(expression, blocks) {
|
|
|
22099
22886
|
fromExpression(expression.right, blocks);
|
|
22100
22887
|
return;
|
|
22101
22888
|
case "unary-expression":
|
|
22889
|
+
case "await-expression":
|
|
22102
22890
|
fromExpression(expression.operand, blocks);
|
|
22103
22891
|
return;
|
|
22104
22892
|
case "group-expression":
|
|
@@ -22133,6 +22921,9 @@ function nestedBlocks(statement) {
|
|
|
22133
22921
|
case "assignment-statement":
|
|
22134
22922
|
fromExpressions([...statement.targets, ...statement.values], blocks);
|
|
22135
22923
|
break;
|
|
22924
|
+
case "global-statement":
|
|
22925
|
+
fromExpressions(statement.values, blocks);
|
|
22926
|
+
break;
|
|
22136
22927
|
case "call-statement":
|
|
22137
22928
|
fromExpression(statement.expression, blocks);
|
|
22138
22929
|
break;
|
|
@@ -22211,6 +23002,16 @@ function reindent(code, indent) {
|
|
|
22211
23002
|
}
|
|
22212
23003
|
return code.split("\n").map((line2, index) => index === 0 || line2.length === 0 ? line2 : `${indent}${line2}`).join("\n");
|
|
22213
23004
|
}
|
|
23005
|
+
var CLOSING_LINE = /^\s*(?:end|\})/;
|
|
23006
|
+
function padAboveClosing(replacement, missing2) {
|
|
23007
|
+
const lines = replacement.split("\n");
|
|
23008
|
+
const closing = lines[lines.length - 1] ?? "";
|
|
23009
|
+
const blanks = Array.from({ length: missing2 }, () => "");
|
|
23010
|
+
if (lines.length < 2 || !CLOSING_LINE.test(closing)) {
|
|
23011
|
+
return [replacement, ...blanks].join("\n");
|
|
23012
|
+
}
|
|
23013
|
+
return [...lines.slice(0, -1), ...blanks, closing].join("\n");
|
|
23014
|
+
}
|
|
22214
23015
|
function erasedEnd(source, span) {
|
|
22215
23016
|
const trailing = TRAILING_SEMICOLON.exec(source.slice(span.end));
|
|
22216
23017
|
return trailing === null ? span.end : span.end + trailing[0].length;
|
|
@@ -22233,7 +23034,7 @@ function canonicalEdit(input, statement, span) {
|
|
|
22233
23034
|
if (missing2 < 0 && input.development) {
|
|
22234
23035
|
return null;
|
|
22235
23036
|
}
|
|
22236
|
-
const padded = missing2 > 0 && source.slice(end).trim().length > 0 ?
|
|
23037
|
+
const padded = missing2 > 0 && source.slice(end).trim().length > 0 ? padAboveClosing(replacement, missing2) : replacement;
|
|
22237
23038
|
return { start: span.start, end, replacement: padded, lines: emitted2.lines };
|
|
22238
23039
|
}
|
|
22239
23040
|
|
|
@@ -22262,7 +23063,10 @@ function isPreservableExpression(expression, types, statics = NO_STATIC_ACCESS)
|
|
|
22262
23063
|
switch (expression.kind) {
|
|
22263
23064
|
case "template-literal":
|
|
22264
23065
|
case "new-expression":
|
|
23066
|
+
case "await-expression":
|
|
22265
23067
|
return false;
|
|
23068
|
+
case "function-expression":
|
|
23069
|
+
return !expression.isAsync;
|
|
22266
23070
|
case "member-expression":
|
|
22267
23071
|
return !statics.has(expression) && resolvePropertyExtension(types.get(expression.object) ?? null, expression.property) === null && isPreservableExpression(expression.object, types, statics);
|
|
22268
23072
|
case "index-expression":
|
|
@@ -22311,11 +23115,12 @@ function isPreservableStatement(statement, types, statics = NO_STATIC_ACCESS) {
|
|
|
22311
23115
|
return isPreservableExpression(statement.start, types, statics) && isPreservableExpression(statement.limit, types, statics) && (statement.step === null || isPreservableExpression(statement.step, types, statics));
|
|
22312
23116
|
case "generic-for-statement":
|
|
22313
23117
|
return every(statement.iterators, types, statics);
|
|
23118
|
+
case "function-declaration":
|
|
23119
|
+
return !statement.isAsync;
|
|
22314
23120
|
case "break-statement":
|
|
22315
23121
|
case "declare-statement":
|
|
22316
23122
|
case "do-statement":
|
|
22317
23123
|
case "event-declaration":
|
|
22318
|
-
case "function-declaration":
|
|
22319
23124
|
case "interface-declaration":
|
|
22320
23125
|
case "type-alias-statement":
|
|
22321
23126
|
return true;
|
|
@@ -22491,6 +23296,7 @@ function children(expression) {
|
|
|
22491
23296
|
case "binary-expression":
|
|
22492
23297
|
return [expression.left, expression.right];
|
|
22493
23298
|
case "unary-expression":
|
|
23299
|
+
case "await-expression":
|
|
22494
23300
|
return [expression.operand];
|
|
22495
23301
|
case "group-expression":
|
|
22496
23302
|
return [expression.expression];
|
|
@@ -22543,6 +23349,22 @@ function statementExpressions3(statement) {
|
|
|
22543
23349
|
return null;
|
|
22544
23350
|
}
|
|
22545
23351
|
}
|
|
23352
|
+
function constructionEdit(input, expression, span) {
|
|
23353
|
+
const start = input.source.indexOf(expression.className, span.start);
|
|
23354
|
+
if (start === -1 || start >= span.end) {
|
|
23355
|
+
return null;
|
|
23356
|
+
}
|
|
23357
|
+
const isLibrary2 = input.types.get(expression)?.kind === "record";
|
|
23358
|
+
if (isLibrary2) {
|
|
23359
|
+
return { start: span.start, end: start + expression.className.length, replacement: `${expression.className}.new` };
|
|
23360
|
+
}
|
|
23361
|
+
const spacing = /^[ \t]*/.exec(input.source.slice(start + expression.className.length))?.[0] ?? "";
|
|
23362
|
+
return {
|
|
23363
|
+
start: span.start,
|
|
23364
|
+
end: start + expression.className.length + spacing.length,
|
|
23365
|
+
replacement: `new ${emitString(expression.className)} `
|
|
23366
|
+
};
|
|
23367
|
+
}
|
|
22546
23368
|
function expressionEdits(input, statement) {
|
|
22547
23369
|
const slots = input.development ? statementExpressions3(statement) : null;
|
|
22548
23370
|
if (slots === null) {
|
|
@@ -22555,7 +23377,18 @@ function expressionEdits(input, statement) {
|
|
|
22555
23377
|
const edits = [];
|
|
22556
23378
|
for (const expression of found) {
|
|
22557
23379
|
const span = input.spans.get(expression);
|
|
22558
|
-
if (span === void 0
|
|
23380
|
+
if (span === void 0) {
|
|
23381
|
+
return null;
|
|
23382
|
+
}
|
|
23383
|
+
if (expression.kind === "new-expression") {
|
|
23384
|
+
const edit = constructionEdit(input, expression, span);
|
|
23385
|
+
if (edit === null) {
|
|
23386
|
+
return null;
|
|
23387
|
+
}
|
|
23388
|
+
edits.push(edit);
|
|
23389
|
+
continue;
|
|
23390
|
+
}
|
|
23391
|
+
if (holdsFunction(expression)) {
|
|
22559
23392
|
return null;
|
|
22560
23393
|
}
|
|
22561
23394
|
const state = createEmitState(input.types, input.references, input.generatedMembers, input.staticAccess);
|
|
@@ -22824,6 +23657,7 @@ function compile(source, options = {}) {
|
|
|
22824
23657
|
isDeclarationFile,
|
|
22825
23658
|
oop: settings.oop,
|
|
22826
23659
|
noUnusedLocals: settings.noUnusedLocals,
|
|
23660
|
+
noImplicitGlobals: settings.noImplicitGlobals,
|
|
22827
23661
|
noUnusedParameters: settings.noUnusedParameters
|
|
22828
23662
|
});
|
|
22829
23663
|
const diagnostics = sortDiagnostics([...parsed.diagnostics, ...resolved2.diagnostics, ...checked.diagnostics]);
|
|
@@ -23067,11 +23901,12 @@ function createDependencyGraph(nodes) {
|
|
|
23067
23901
|
|
|
23068
23902
|
// ../compiler/src/project/ambient-scope.ts
|
|
23069
23903
|
function optionsKey(options) {
|
|
23070
|
-
|
|
23904
|
+
const flags = [options.strict ? "strict" : "", options.oop ? "oop" : "", options.noUnusedLocals ? "nul" : "", options.noUnusedParameters ? "nup" : ""];
|
|
23905
|
+
return `${flags.join("|")}|${options.noImplicitGlobals ? "nig" : ""}`;
|
|
23071
23906
|
}
|
|
23072
23907
|
function declaresNothing(declarations) {
|
|
23073
|
-
const { classes, interfaces, enums, globals, events } = declarations;
|
|
23074
|
-
return classes.length === 0 && interfaces.length === 0 && enums.length === 0 && globals.length === 0 && events.length === 0;
|
|
23908
|
+
const { classes, interfaces, enums, aliases, globals, events } = declarations;
|
|
23909
|
+
return classes.length === 0 && interfaces.length === 0 && enums.length === 0 && aliases.length === 0 && globals.length === 0 && events.length === 0;
|
|
23075
23910
|
}
|
|
23076
23911
|
function sharedEnums(collected) {
|
|
23077
23912
|
const declared = new Set(collected.flatMap((entry) => entry.declarations.enums.map((enumeration) => enumeration.name)));
|