@thigasdevelopment/luam 0.19.5 → 0.19.6
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/luam.mjs +366 -202
- package/package.json +1 -1
package/luam.mjs
CHANGED
|
@@ -4008,6 +4008,188 @@ function parseNamedAnnotation(stream, declaration) {
|
|
|
4008
4008
|
return { kind: "type-optional", element, position: optional.position };
|
|
4009
4009
|
}
|
|
4010
4010
|
|
|
4011
|
+
// ../compiler/src/parser/token-stream.ts
|
|
4012
|
+
var ParserError = class extends Error {
|
|
4013
|
+
diagnostic;
|
|
4014
|
+
constructor(diagnostic) {
|
|
4015
|
+
super(diagnostic.message);
|
|
4016
|
+
this.name = "ParserError";
|
|
4017
|
+
this.diagnostic = diagnostic;
|
|
4018
|
+
}
|
|
4019
|
+
};
|
|
4020
|
+
var TokenStream = class {
|
|
4021
|
+
diagnostics = [];
|
|
4022
|
+
tokens;
|
|
4023
|
+
index = 0;
|
|
4024
|
+
erased = [];
|
|
4025
|
+
spans = /* @__PURE__ */ new Map();
|
|
4026
|
+
constructor(tokens) {
|
|
4027
|
+
this.tokens = tokens;
|
|
4028
|
+
}
|
|
4029
|
+
peek(offset = 0) {
|
|
4030
|
+
const token = this.tokens[Math.min(this.index + offset, this.tokens.length - 1)];
|
|
4031
|
+
return token;
|
|
4032
|
+
}
|
|
4033
|
+
current() {
|
|
4034
|
+
return this.peek();
|
|
4035
|
+
}
|
|
4036
|
+
isEof() {
|
|
4037
|
+
return this.current().kind === "eof";
|
|
4038
|
+
}
|
|
4039
|
+
next() {
|
|
4040
|
+
const token = this.current();
|
|
4041
|
+
if (!this.isEof()) {
|
|
4042
|
+
this.index += 1;
|
|
4043
|
+
}
|
|
4044
|
+
return token;
|
|
4045
|
+
}
|
|
4046
|
+
checkpoint() {
|
|
4047
|
+
return this.index;
|
|
4048
|
+
}
|
|
4049
|
+
speculate() {
|
|
4050
|
+
return { index: this.index, erasures: this.erased.length, diagnostics: this.diagnostics.length };
|
|
4051
|
+
}
|
|
4052
|
+
rewind(point) {
|
|
4053
|
+
this.index = point.index;
|
|
4054
|
+
this.erased.length = point.erasures;
|
|
4055
|
+
this.diagnostics.length = point.diagnostics;
|
|
4056
|
+
}
|
|
4057
|
+
eraseFrom(checkpoint, kind = "annotation") {
|
|
4058
|
+
const first = this.tokens[checkpoint];
|
|
4059
|
+
const last = this.tokens[this.index - 1];
|
|
4060
|
+
if (first !== void 0 && last !== void 0 && first.kind !== "eof") {
|
|
4061
|
+
this.erased.push({ start: first.position.offset, end: last.end.offset, kind });
|
|
4062
|
+
}
|
|
4063
|
+
}
|
|
4064
|
+
eraseToCurrent(checkpoint) {
|
|
4065
|
+
const first = this.tokens[checkpoint];
|
|
4066
|
+
if (first !== void 0 && first.kind !== "eof") {
|
|
4067
|
+
this.erased.push({ start: first.position.offset, end: this.current().position.offset, kind: "annotation" });
|
|
4068
|
+
}
|
|
4069
|
+
}
|
|
4070
|
+
extendDeclarationErasure(end) {
|
|
4071
|
+
const last = this.erased[this.erased.length - 1];
|
|
4072
|
+
if (last !== void 0 && last.kind === "declaration" && last.end <= end) {
|
|
4073
|
+
last.end = end;
|
|
4074
|
+
}
|
|
4075
|
+
}
|
|
4076
|
+
erasures() {
|
|
4077
|
+
return [...this.erased];
|
|
4078
|
+
}
|
|
4079
|
+
recordSpan(node, checkpoint) {
|
|
4080
|
+
const span = this.sourceSpanFrom(checkpoint);
|
|
4081
|
+
if (span !== null) {
|
|
4082
|
+
this.spans.set(node, span);
|
|
4083
|
+
}
|
|
4084
|
+
}
|
|
4085
|
+
nodeSpans() {
|
|
4086
|
+
return this.spans;
|
|
4087
|
+
}
|
|
4088
|
+
sourceSpanFrom(checkpoint) {
|
|
4089
|
+
const first = this.tokens[checkpoint];
|
|
4090
|
+
const last = this.tokens[this.index - 1];
|
|
4091
|
+
return first === void 0 || last === void 0 || first.kind === "eof" ? null : { start: first.position.offset, end: last.end.offset };
|
|
4092
|
+
}
|
|
4093
|
+
check(kind, value) {
|
|
4094
|
+
const token = this.current();
|
|
4095
|
+
return token.kind === kind && (value === void 0 || token.value === value);
|
|
4096
|
+
}
|
|
4097
|
+
checkAhead(offset, kind, value) {
|
|
4098
|
+
const token = this.peek(offset);
|
|
4099
|
+
return token.kind === kind && (value === void 0 || token.value === value);
|
|
4100
|
+
}
|
|
4101
|
+
match(kind, value) {
|
|
4102
|
+
if (!this.check(kind, value)) {
|
|
4103
|
+
return false;
|
|
4104
|
+
}
|
|
4105
|
+
this.next();
|
|
4106
|
+
return true;
|
|
4107
|
+
}
|
|
4108
|
+
expect(kind, value) {
|
|
4109
|
+
if (this.check(kind, value)) {
|
|
4110
|
+
return this.next();
|
|
4111
|
+
}
|
|
4112
|
+
const expected = value === void 0 ? kind : `"${value}"`;
|
|
4113
|
+
throw this.error(`Expected ${expected} but found "${this.describeCurrent()}".`, "parse-unexpected-token");
|
|
4114
|
+
}
|
|
4115
|
+
checkName(offset = 0) {
|
|
4116
|
+
const token = this.peek(offset);
|
|
4117
|
+
return token.kind === "identifier" || token.kind === "keyword" && isLuamKeyword(token.value);
|
|
4118
|
+
}
|
|
4119
|
+
expectName() {
|
|
4120
|
+
if (this.checkName()) {
|
|
4121
|
+
return this.next();
|
|
4122
|
+
}
|
|
4123
|
+
throw this.error(`Expected a name but found "${this.describeCurrent()}".`, "parse-unexpected-token");
|
|
4124
|
+
}
|
|
4125
|
+
describeCurrent() {
|
|
4126
|
+
const token = this.current();
|
|
4127
|
+
return token.kind === "eof" ? "<end of file>" : token.value;
|
|
4128
|
+
}
|
|
4129
|
+
error(message, code = "parse-error") {
|
|
4130
|
+
const token = this.current();
|
|
4131
|
+
return new ParserError(createDiagnostic("parser", code, message, token.position, "error", token.end));
|
|
4132
|
+
}
|
|
4133
|
+
errorAt(message, code, position2, end) {
|
|
4134
|
+
return new ParserError(createDiagnostic("parser", code, message, position2, "error", end));
|
|
4135
|
+
}
|
|
4136
|
+
report(code, message, position2) {
|
|
4137
|
+
this.diagnostics.push(createDiagnostic("parser", code, message, position2));
|
|
4138
|
+
}
|
|
4139
|
+
};
|
|
4140
|
+
|
|
4141
|
+
// ../compiler/src/parser/type-parameters.ts
|
|
4142
|
+
function emptyTypeParameters() {
|
|
4143
|
+
return { names: [], constraints: [] };
|
|
4144
|
+
}
|
|
4145
|
+
function parseTypeParameters(stream) {
|
|
4146
|
+
const list = emptyTypeParameters();
|
|
4147
|
+
if (!stream.check("operator", "<")) {
|
|
4148
|
+
return list;
|
|
4149
|
+
}
|
|
4150
|
+
const checkpoint = stream.checkpoint();
|
|
4151
|
+
stream.next();
|
|
4152
|
+
do {
|
|
4153
|
+
list.names.push(stream.expect("identifier").value);
|
|
4154
|
+
list.constraints.push(stream.match("keyword", "extends") ? parseTypeAnnotation(stream) : null);
|
|
4155
|
+
} while (stream.match("punctuation", ","));
|
|
4156
|
+
stream.expect("operator", ">");
|
|
4157
|
+
stream.eraseFrom(checkpoint);
|
|
4158
|
+
return list;
|
|
4159
|
+
}
|
|
4160
|
+
function parseTypeArguments(stream) {
|
|
4161
|
+
const args = [];
|
|
4162
|
+
if (!stream.check("operator", "<")) {
|
|
4163
|
+
return args;
|
|
4164
|
+
}
|
|
4165
|
+
const checkpoint = stream.checkpoint();
|
|
4166
|
+
stream.next();
|
|
4167
|
+
do {
|
|
4168
|
+
args.push(parseTypeAnnotation(stream));
|
|
4169
|
+
} while (stream.match("punctuation", ","));
|
|
4170
|
+
stream.expect("operator", ">");
|
|
4171
|
+
stream.eraseFrom(checkpoint);
|
|
4172
|
+
return args;
|
|
4173
|
+
}
|
|
4174
|
+
function parseCallTypeArguments(stream) {
|
|
4175
|
+
if (!stream.check("operator", "<")) {
|
|
4176
|
+
return [];
|
|
4177
|
+
}
|
|
4178
|
+
const point = stream.speculate();
|
|
4179
|
+
try {
|
|
4180
|
+
const args = parseTypeArguments(stream);
|
|
4181
|
+
if (args.length > 0 && stream.check("punctuation", "(")) {
|
|
4182
|
+
return args;
|
|
4183
|
+
}
|
|
4184
|
+
} catch (error) {
|
|
4185
|
+
if (!(error instanceof ParserError)) {
|
|
4186
|
+
throw error;
|
|
4187
|
+
}
|
|
4188
|
+
}
|
|
4189
|
+
stream.rewind(point);
|
|
4190
|
+
return [];
|
|
4191
|
+
}
|
|
4192
|
+
|
|
4011
4193
|
// ../compiler/src/parser/function-expression.ts
|
|
4012
4194
|
function parseParameter(stream) {
|
|
4013
4195
|
const token = stream.current();
|
|
@@ -4038,11 +4220,20 @@ function parseParameters(stream) {
|
|
|
4038
4220
|
}
|
|
4039
4221
|
function parseFunctionExpression(stream) {
|
|
4040
4222
|
const position2 = stream.expect("keyword", "function").position;
|
|
4223
|
+
const typeParameters = parseTypeParameters(stream);
|
|
4041
4224
|
const parameters = parseParameters(stream);
|
|
4042
4225
|
const returnAnnotation = parseOptionalAnnotation(stream);
|
|
4043
4226
|
const body = parseBlock(stream, ["end"]);
|
|
4044
4227
|
stream.expect("keyword", "end");
|
|
4045
|
-
return {
|
|
4228
|
+
return {
|
|
4229
|
+
kind: "function-expression",
|
|
4230
|
+
typeParameters: typeParameters.names,
|
|
4231
|
+
typeConstraints: typeParameters.constraints,
|
|
4232
|
+
parameters,
|
|
4233
|
+
returnAnnotation,
|
|
4234
|
+
body,
|
|
4235
|
+
position: position2
|
|
4236
|
+
};
|
|
4046
4237
|
}
|
|
4047
4238
|
function parseFunctionName(stream) {
|
|
4048
4239
|
const token = stream.expect("identifier");
|
|
@@ -4060,11 +4251,25 @@ function parseFunctionName(stream) {
|
|
|
4060
4251
|
function parseFunctionDeclaration(stream, isLocal, isExported = false, isHttpExport = false) {
|
|
4061
4252
|
const position2 = stream.expect("keyword", "function").position;
|
|
4062
4253
|
const { name, isMethod } = parseFunctionName(stream);
|
|
4254
|
+
const typeParameters = parseTypeParameters(stream);
|
|
4063
4255
|
const parameters = parseParameters(stream);
|
|
4064
4256
|
const returnAnnotation = parseOptionalAnnotation(stream);
|
|
4065
4257
|
const body = parseBlock(stream, ["end"]);
|
|
4066
4258
|
stream.expect("keyword", "end");
|
|
4067
|
-
return {
|
|
4259
|
+
return {
|
|
4260
|
+
kind: "function-declaration",
|
|
4261
|
+
name,
|
|
4262
|
+
isLocal,
|
|
4263
|
+
isExported,
|
|
4264
|
+
isHttpExport,
|
|
4265
|
+
isMethod,
|
|
4266
|
+
typeParameters: typeParameters.names,
|
|
4267
|
+
typeConstraints: typeParameters.constraints,
|
|
4268
|
+
parameters,
|
|
4269
|
+
returnAnnotation,
|
|
4270
|
+
body,
|
|
4271
|
+
position: position2
|
|
4272
|
+
};
|
|
4068
4273
|
}
|
|
4069
4274
|
|
|
4070
4275
|
// ../compiler/src/parser/precedence.ts
|
|
@@ -4159,7 +4364,7 @@ function parsePrimary(stream) {
|
|
|
4159
4364
|
if (token.kind === "keyword" && token.value === "new" && stream.checkAhead(1, "identifier")) {
|
|
4160
4365
|
stream.next();
|
|
4161
4366
|
const className = stream.next().value;
|
|
4162
|
-
const typeArguments =
|
|
4367
|
+
const typeArguments = parseTypeArguments(stream);
|
|
4163
4368
|
return { kind: "new-expression", className, typeArguments, args: parseArguments(stream), position: token.position };
|
|
4164
4369
|
}
|
|
4165
4370
|
if (token.kind === "keyword" && CALLABLE_KEYWORDS.has(token.value) && stream.checkAhead(1, "punctuation", "(")) {
|
|
@@ -4192,20 +4397,6 @@ function parsePrimary(stream) {
|
|
|
4192
4397
|
}
|
|
4193
4398
|
throw stream.error(`Unexpected "${stream.describeCurrent()}" in expression.`, "parse-unexpected-token");
|
|
4194
4399
|
}
|
|
4195
|
-
function parseNewTypeArguments(stream) {
|
|
4196
|
-
const args = [];
|
|
4197
|
-
if (!stream.check("operator", "<")) {
|
|
4198
|
-
return args;
|
|
4199
|
-
}
|
|
4200
|
-
const checkpoint = stream.checkpoint();
|
|
4201
|
-
stream.next();
|
|
4202
|
-
do {
|
|
4203
|
-
args.push(parseTypeAnnotation(stream));
|
|
4204
|
-
} while (stream.match("punctuation", ","));
|
|
4205
|
-
stream.expect("operator", ">");
|
|
4206
|
-
stream.eraseFrom(checkpoint);
|
|
4207
|
-
return args;
|
|
4208
|
-
}
|
|
4209
4400
|
function parseArguments(stream) {
|
|
4210
4401
|
if (stream.check("string") || stream.check("template") || stream.check("punctuation", "{")) {
|
|
4211
4402
|
return [parsePrimary(stream)];
|
|
@@ -4244,11 +4435,13 @@ function parseSuffixed(stream) {
|
|
|
4244
4435
|
if (token.kind === "punctuation" && token.value === ":" && stream.checkName(1)) {
|
|
4245
4436
|
stream.next();
|
|
4246
4437
|
const method = stream.next().value;
|
|
4247
|
-
|
|
4438
|
+
const typeArguments2 = parseCallTypeArguments(stream);
|
|
4439
|
+
expression = { kind: "call-expression", callee: expression, method, typeArguments: typeArguments2, args: parseArguments(stream), position: token.position };
|
|
4248
4440
|
continue;
|
|
4249
4441
|
}
|
|
4250
|
-
|
|
4251
|
-
|
|
4442
|
+
const typeArguments = parseCallTypeArguments(stream);
|
|
4443
|
+
if (typeArguments.length > 0 || isCallStart(stream)) {
|
|
4444
|
+
expression = { kind: "call-expression", callee: expression, method: null, typeArguments, args: parseArguments(stream), position: token.position };
|
|
4252
4445
|
continue;
|
|
4253
4446
|
}
|
|
4254
4447
|
return expression;
|
|
@@ -4367,128 +4560,6 @@ function recoverInBlock(stream, error, terminators = BRACE_TERMINATORS) {
|
|
|
4367
4560
|
}
|
|
4368
4561
|
}
|
|
4369
4562
|
|
|
4370
|
-
// ../compiler/src/parser/token-stream.ts
|
|
4371
|
-
var ParserError = class extends Error {
|
|
4372
|
-
diagnostic;
|
|
4373
|
-
constructor(diagnostic) {
|
|
4374
|
-
super(diagnostic.message);
|
|
4375
|
-
this.name = "ParserError";
|
|
4376
|
-
this.diagnostic = diagnostic;
|
|
4377
|
-
}
|
|
4378
|
-
};
|
|
4379
|
-
var TokenStream = class {
|
|
4380
|
-
diagnostics = [];
|
|
4381
|
-
tokens;
|
|
4382
|
-
index = 0;
|
|
4383
|
-
erased = [];
|
|
4384
|
-
spans = /* @__PURE__ */ new Map();
|
|
4385
|
-
constructor(tokens) {
|
|
4386
|
-
this.tokens = tokens;
|
|
4387
|
-
}
|
|
4388
|
-
peek(offset = 0) {
|
|
4389
|
-
const token = this.tokens[Math.min(this.index + offset, this.tokens.length - 1)];
|
|
4390
|
-
return token;
|
|
4391
|
-
}
|
|
4392
|
-
current() {
|
|
4393
|
-
return this.peek();
|
|
4394
|
-
}
|
|
4395
|
-
isEof() {
|
|
4396
|
-
return this.current().kind === "eof";
|
|
4397
|
-
}
|
|
4398
|
-
next() {
|
|
4399
|
-
const token = this.current();
|
|
4400
|
-
if (!this.isEof()) {
|
|
4401
|
-
this.index += 1;
|
|
4402
|
-
}
|
|
4403
|
-
return token;
|
|
4404
|
-
}
|
|
4405
|
-
checkpoint() {
|
|
4406
|
-
return this.index;
|
|
4407
|
-
}
|
|
4408
|
-
eraseFrom(checkpoint, kind = "annotation") {
|
|
4409
|
-
const first = this.tokens[checkpoint];
|
|
4410
|
-
const last = this.tokens[this.index - 1];
|
|
4411
|
-
if (first !== void 0 && last !== void 0 && first.kind !== "eof") {
|
|
4412
|
-
this.erased.push({ start: first.position.offset, end: last.end.offset, kind });
|
|
4413
|
-
}
|
|
4414
|
-
}
|
|
4415
|
-
eraseToCurrent(checkpoint) {
|
|
4416
|
-
const first = this.tokens[checkpoint];
|
|
4417
|
-
if (first !== void 0 && first.kind !== "eof") {
|
|
4418
|
-
this.erased.push({ start: first.position.offset, end: this.current().position.offset, kind: "annotation" });
|
|
4419
|
-
}
|
|
4420
|
-
}
|
|
4421
|
-
extendDeclarationErasure(end) {
|
|
4422
|
-
const last = this.erased[this.erased.length - 1];
|
|
4423
|
-
if (last !== void 0 && last.kind === "declaration" && last.end <= end) {
|
|
4424
|
-
last.end = end;
|
|
4425
|
-
}
|
|
4426
|
-
}
|
|
4427
|
-
erasures() {
|
|
4428
|
-
return [...this.erased];
|
|
4429
|
-
}
|
|
4430
|
-
recordSpan(node, checkpoint) {
|
|
4431
|
-
const span = this.sourceSpanFrom(checkpoint);
|
|
4432
|
-
if (span !== null) {
|
|
4433
|
-
this.spans.set(node, span);
|
|
4434
|
-
}
|
|
4435
|
-
}
|
|
4436
|
-
nodeSpans() {
|
|
4437
|
-
return this.spans;
|
|
4438
|
-
}
|
|
4439
|
-
sourceSpanFrom(checkpoint) {
|
|
4440
|
-
const first = this.tokens[checkpoint];
|
|
4441
|
-
const last = this.tokens[this.index - 1];
|
|
4442
|
-
return first === void 0 || last === void 0 || first.kind === "eof" ? null : { start: first.position.offset, end: last.end.offset };
|
|
4443
|
-
}
|
|
4444
|
-
check(kind, value) {
|
|
4445
|
-
const token = this.current();
|
|
4446
|
-
return token.kind === kind && (value === void 0 || token.value === value);
|
|
4447
|
-
}
|
|
4448
|
-
checkAhead(offset, kind, value) {
|
|
4449
|
-
const token = this.peek(offset);
|
|
4450
|
-
return token.kind === kind && (value === void 0 || token.value === value);
|
|
4451
|
-
}
|
|
4452
|
-
match(kind, value) {
|
|
4453
|
-
if (!this.check(kind, value)) {
|
|
4454
|
-
return false;
|
|
4455
|
-
}
|
|
4456
|
-
this.next();
|
|
4457
|
-
return true;
|
|
4458
|
-
}
|
|
4459
|
-
expect(kind, value) {
|
|
4460
|
-
if (this.check(kind, value)) {
|
|
4461
|
-
return this.next();
|
|
4462
|
-
}
|
|
4463
|
-
const expected = value === void 0 ? kind : `"${value}"`;
|
|
4464
|
-
throw this.error(`Expected ${expected} but found "${this.describeCurrent()}".`, "parse-unexpected-token");
|
|
4465
|
-
}
|
|
4466
|
-
checkName(offset = 0) {
|
|
4467
|
-
const token = this.peek(offset);
|
|
4468
|
-
return token.kind === "identifier" || token.kind === "keyword" && isLuamKeyword(token.value);
|
|
4469
|
-
}
|
|
4470
|
-
expectName() {
|
|
4471
|
-
if (this.checkName()) {
|
|
4472
|
-
return this.next();
|
|
4473
|
-
}
|
|
4474
|
-
throw this.error(`Expected a name but found "${this.describeCurrent()}".`, "parse-unexpected-token");
|
|
4475
|
-
}
|
|
4476
|
-
describeCurrent() {
|
|
4477
|
-
const token = this.current();
|
|
4478
|
-
return token.kind === "eof" ? "<end of file>" : token.value;
|
|
4479
|
-
}
|
|
4480
|
-
error(message, code = "parse-error") {
|
|
4481
|
-
const token = this.current();
|
|
4482
|
-
return new ParserError(createDiagnostic("parser", code, message, token.position, "error", token.end));
|
|
4483
|
-
}
|
|
4484
|
-
errorAt(message, code, position2, end) {
|
|
4485
|
-
return new ParserError(createDiagnostic("parser", code, message, position2, "error", end));
|
|
4486
|
-
}
|
|
4487
|
-
report(code, message, position2) {
|
|
4488
|
-
this.diagnostics.push(createDiagnostic("parser", code, message, position2));
|
|
4489
|
-
}
|
|
4490
|
-
};
|
|
4491
|
-
|
|
4492
4563
|
// ../compiler/src/parser/declarations.ts
|
|
4493
4564
|
var DECLARATION_NAMES = /* @__PURE__ */ new Set(["class", "interface", "enum"]);
|
|
4494
4565
|
var CLASS_MODIFIERS = /* @__PURE__ */ new Set(["extends", "implements"]);
|
|
@@ -4573,6 +4644,8 @@ function parseClassMethod(stream, token, decorators, isStatic) {
|
|
|
4573
4644
|
isConstructor: token.value === "constructor",
|
|
4574
4645
|
isSynthetic: false,
|
|
4575
4646
|
isStatic,
|
|
4647
|
+
typeParameters: expression.typeParameters,
|
|
4648
|
+
typeConstraints: expression.typeConstraints,
|
|
4576
4649
|
parameters: expression.parameters,
|
|
4577
4650
|
returnAnnotation: expression.returnAnnotation,
|
|
4578
4651
|
body: expression.body,
|
|
@@ -4590,6 +4663,8 @@ function parseBraceClassMethod(stream, token, decorators, isStatic) {
|
|
|
4590
4663
|
isConstructor: token.value === "constructor",
|
|
4591
4664
|
isSynthetic: false,
|
|
4592
4665
|
isStatic,
|
|
4666
|
+
typeParameters: [],
|
|
4667
|
+
typeConstraints: [],
|
|
4593
4668
|
parameters,
|
|
4594
4669
|
returnAnnotation,
|
|
4595
4670
|
body,
|
|
@@ -4638,35 +4713,6 @@ function parseClassMember(stream) {
|
|
|
4638
4713
|
expectClassFieldBoundary(stream, token);
|
|
4639
4714
|
return { kind: "class-field", name: token.value, annotation, value, decorators, isStatic, position: token.position };
|
|
4640
4715
|
}
|
|
4641
|
-
function parseTypeParameters(stream) {
|
|
4642
|
-
const list = { names: [], constraints: [] };
|
|
4643
|
-
if (!stream.check("operator", "<")) {
|
|
4644
|
-
return list;
|
|
4645
|
-
}
|
|
4646
|
-
const checkpoint = stream.checkpoint();
|
|
4647
|
-
stream.next();
|
|
4648
|
-
do {
|
|
4649
|
-
list.names.push(stream.expect("identifier").value);
|
|
4650
|
-
list.constraints.push(stream.match("keyword", "extends") ? parseTypeAnnotation(stream) : null);
|
|
4651
|
-
} while (stream.match("punctuation", ","));
|
|
4652
|
-
stream.expect("operator", ">");
|
|
4653
|
-
stream.eraseFrom(checkpoint);
|
|
4654
|
-
return list;
|
|
4655
|
-
}
|
|
4656
|
-
function parseTypeArguments(stream) {
|
|
4657
|
-
const args = [];
|
|
4658
|
-
if (!stream.check("operator", "<")) {
|
|
4659
|
-
return args;
|
|
4660
|
-
}
|
|
4661
|
-
const checkpoint = stream.checkpoint();
|
|
4662
|
-
stream.next();
|
|
4663
|
-
do {
|
|
4664
|
-
args.push(parseTypeAnnotation(stream));
|
|
4665
|
-
} while (stream.match("punctuation", ","));
|
|
4666
|
-
stream.expect("operator", ">");
|
|
4667
|
-
stream.eraseFrom(checkpoint);
|
|
4668
|
-
return args;
|
|
4669
|
-
}
|
|
4670
4716
|
function parseClassModifiers(stream, declaration) {
|
|
4671
4717
|
while (stream.check("keyword") && CLASS_MODIFIERS.has(stream.current().value)) {
|
|
4672
4718
|
if (stream.next().value === "extends") {
|
|
@@ -5305,10 +5351,12 @@ function typeToString(type) {
|
|
|
5305
5351
|
}
|
|
5306
5352
|
if (type.kind === "function") {
|
|
5307
5353
|
const parameters = type.parameters.map(typeToString);
|
|
5354
|
+
const names = type.typeParameters ?? [];
|
|
5308
5355
|
if (type.isVariadic) {
|
|
5309
5356
|
parameters.push(type.variadicType === void 0 ? "..." : `...: ${typeToString(type.variadicType)}`);
|
|
5310
5357
|
}
|
|
5311
|
-
|
|
5358
|
+
const generic = names.length === 0 ? "" : `<${names.join(", ")}>`;
|
|
5359
|
+
return `fun${generic}(${parameters.join(", ")}): ${typeToString(type.returnType)}`;
|
|
5312
5360
|
}
|
|
5313
5361
|
return type.kind;
|
|
5314
5362
|
}
|
|
@@ -6762,7 +6810,7 @@ import { tmpdir } from "node:os";
|
|
|
6762
6810
|
import { join as join2 } from "node:path";
|
|
6763
6811
|
|
|
6764
6812
|
// src/cli/version.ts
|
|
6765
|
-
var VERSION = true ? "0.19.
|
|
6813
|
+
var VERSION = true ? "0.19.6" : "0.0.0-dev";
|
|
6766
6814
|
var PROGRAM_NAME = "luam";
|
|
6767
6815
|
var PROGRAM_DESCRIPTION = "luam \u2014 the Luam compiler for Multi Theft Auto resources.";
|
|
6768
6816
|
|
|
@@ -8780,6 +8828,13 @@ function assignmentFact(narrowed, declared) {
|
|
|
8780
8828
|
}
|
|
8781
8829
|
|
|
8782
8830
|
// ../compiler/src/checker/type-substitution.ts
|
|
8831
|
+
function shadowed(substitutions, names) {
|
|
8832
|
+
const remaining = new Map(substitutions);
|
|
8833
|
+
for (const name of names) {
|
|
8834
|
+
remaining.delete(name);
|
|
8835
|
+
}
|
|
8836
|
+
return remaining;
|
|
8837
|
+
}
|
|
8783
8838
|
function substituteType(type, substitutions) {
|
|
8784
8839
|
if (type.kind === "named") {
|
|
8785
8840
|
const args = type.typeArguments ?? [];
|
|
@@ -8801,10 +8856,17 @@ function substituteType(type, substitutions) {
|
|
|
8801
8856
|
return createUnion(type.options.map((option) => substituteType(option, substitutions)));
|
|
8802
8857
|
}
|
|
8803
8858
|
if (type.kind === "function") {
|
|
8804
|
-
const
|
|
8805
|
-
const
|
|
8806
|
-
const
|
|
8807
|
-
|
|
8859
|
+
const own = type.typeParameters ?? [];
|
|
8860
|
+
const outer = own.length === 0 ? substitutions : shadowed(substitutions, own);
|
|
8861
|
+
const parameters = type.parameters.map((parameter) => substituteType(parameter, outer));
|
|
8862
|
+
const returnType = substituteType(type.returnType, outer);
|
|
8863
|
+
const variadicType = type.variadicType === void 0 ? void 0 : substituteType(type.variadicType, outer);
|
|
8864
|
+
const substituted = createFunction(parameters, returnType, type.minimumArguments, type.isVariadic, type.parameterNames, variadicType);
|
|
8865
|
+
if (own.length > 0) {
|
|
8866
|
+
substituted.typeParameters = [...own];
|
|
8867
|
+
substituted.typeConstraints = (type.typeConstraints ?? []).map((constraint) => constraint === null ? null : substituteType(constraint, outer));
|
|
8868
|
+
}
|
|
8869
|
+
return substituted;
|
|
8808
8870
|
}
|
|
8809
8871
|
if (type.kind === "tuple") {
|
|
8810
8872
|
return createTuple(type.elements.map((element) => substituteType(element, substitutions)));
|
|
@@ -8921,21 +8983,24 @@ function satisfies(context, argument, constraint) {
|
|
|
8921
8983
|
}
|
|
8922
8984
|
return isAssignable(argument, constraint, { allowNil: false });
|
|
8923
8985
|
}
|
|
8924
|
-
function
|
|
8925
|
-
|
|
8926
|
-
if (info === null) {
|
|
8927
|
-
return;
|
|
8928
|
-
}
|
|
8929
|
-
info.typeConstraints.forEach((constraint, index) => {
|
|
8986
|
+
function reportConstraintViolations(context, owner, typeParameters, typeConstraints, typeArguments, position2) {
|
|
8987
|
+
typeConstraints.forEach((constraint, index) => {
|
|
8930
8988
|
const argument = typeArguments[index];
|
|
8931
8989
|
if (constraint === null || argument === void 0 || argument.kind === "any" || satisfies(context, argument, constraint)) {
|
|
8932
8990
|
return;
|
|
8933
8991
|
}
|
|
8934
|
-
const parameter =
|
|
8935
|
-
const message = `Type argument "${typeToString(argument)}" does not satisfy "${parameter} extends ${typeToString(constraint)}" on
|
|
8992
|
+
const parameter = typeParameters[index] ?? "T";
|
|
8993
|
+
const message = `Type argument "${typeToString(argument)}" does not satisfy "${parameter} extends ${typeToString(constraint)}" on ${owner}.`;
|
|
8936
8994
|
context.report("check-generic-constraint", message, position2);
|
|
8937
8995
|
});
|
|
8938
8996
|
}
|
|
8997
|
+
function checkTypeConstraints(context, name, typeArguments, position2) {
|
|
8998
|
+
const info = context.declarations.lookupClass(name);
|
|
8999
|
+
if (info === null) {
|
|
9000
|
+
return;
|
|
9001
|
+
}
|
|
9002
|
+
reportConstraintViolations(context, `class "${name}"`, info.typeParameters, info.typeConstraints, typeArguments, position2);
|
|
9003
|
+
}
|
|
8939
9004
|
|
|
8940
9005
|
// ../mta-types/src/lua-standard.ts
|
|
8941
9006
|
var LUA_GLOBALS = {
|
|
@@ -15027,6 +15092,8 @@ function accessorMethod(field2, decorator, name) {
|
|
|
15027
15092
|
isConstructor: false,
|
|
15028
15093
|
isSynthetic: true,
|
|
15029
15094
|
isStatic: false,
|
|
15095
|
+
typeParameters: [],
|
|
15096
|
+
typeConstraints: [],
|
|
15030
15097
|
parameters: decorator === "Getter" ? [] : [value],
|
|
15031
15098
|
returnAnnotation: decorator === "Getter" ? field2.annotation : voidAnnotation,
|
|
15032
15099
|
body,
|
|
@@ -15035,7 +15102,7 @@ function accessorMethod(field2, decorator, name) {
|
|
|
15035
15102
|
};
|
|
15036
15103
|
}
|
|
15037
15104
|
function generatedMethod(field2, name, parameters, returnAnnotation, kind, fields) {
|
|
15038
|
-
return { kind: "class-method", name, isConstructor: false, isSynthetic: true, isStatic: false, parameters, returnAnnotation, body: [], decorators: [], generated: { kind, fields }, position: field2.position };
|
|
15105
|
+
return { kind: "class-method", name, isConstructor: false, isSynthetic: true, isStatic: false, typeParameters: [], typeConstraints: [], parameters, returnAnnotation, body: [], decorators: [], generated: { kind, fields }, position: field2.position };
|
|
15039
15106
|
}
|
|
15040
15107
|
function typeName(name, node) {
|
|
15041
15108
|
return { kind: "type-name", name, typeArguments: [], position: node.position };
|
|
@@ -15073,6 +15140,8 @@ function staticMethod(statement, name, returnAnnotation, kind, descriptor) {
|
|
|
15073
15140
|
isConstructor: false,
|
|
15074
15141
|
isSynthetic: true,
|
|
15075
15142
|
isStatic: true,
|
|
15143
|
+
typeParameters: [],
|
|
15144
|
+
typeConstraints: [],
|
|
15076
15145
|
parameters: [value],
|
|
15077
15146
|
returnAnnotation,
|
|
15078
15147
|
body: [],
|
|
@@ -18570,6 +18639,33 @@ function specializeEventCall(context, expression, signature) {
|
|
|
18570
18639
|
return candidate === null ? null : specialize(signature, candidate);
|
|
18571
18640
|
}
|
|
18572
18641
|
|
|
18642
|
+
// ../compiler/src/checker/generic-call.ts
|
|
18643
|
+
function countArguments(total) {
|
|
18644
|
+
return total === 1 ? "1 type argument" : `${total} type arguments`;
|
|
18645
|
+
}
|
|
18646
|
+
function substituteSignature(signature, substitutions) {
|
|
18647
|
+
const parameters = signature.parameters.map((parameter) => substituteType(parameter, substitutions));
|
|
18648
|
+
const returnType = substituteType(signature.returnType, substitutions);
|
|
18649
|
+
const variadicType = signature.variadicType === void 0 ? void 0 : substituteType(signature.variadicType, substitutions);
|
|
18650
|
+
return createFunction(parameters, returnType, signature.minimumArguments, signature.isVariadic, signature.parameterNames, variadicType);
|
|
18651
|
+
}
|
|
18652
|
+
function specializeCall(context, owner, signature, argumentTypes, typeArguments, position2) {
|
|
18653
|
+
const names = signature.typeParameters ?? [];
|
|
18654
|
+
if (names.length === 0) {
|
|
18655
|
+
if (typeArguments.length > 0) {
|
|
18656
|
+
context.report("check-generic-arity", `${owner} does not accept type arguments.`, position2);
|
|
18657
|
+
}
|
|
18658
|
+
return signature;
|
|
18659
|
+
}
|
|
18660
|
+
const explicit = typeArguments.map((argument) => context.resolveAnnotation(argument));
|
|
18661
|
+
if (typeArguments.length > 0 && explicit.length !== names.length) {
|
|
18662
|
+
context.report("check-generic-arity", `${owner} expects ${countArguments(names.length)} but received ${explicit.length}.`, position2);
|
|
18663
|
+
}
|
|
18664
|
+
const resolved2 = typeArguments.length > 0 ? names.map((unused, index) => explicit[index] ?? ANY_TYPE) : inferTypeArguments(names, signature.parameters, argumentTypes);
|
|
18665
|
+
reportConstraintViolations(context, owner, names, signature.typeConstraints ?? [], resolved2, position2);
|
|
18666
|
+
return substituteSignature(signature, new Map(names.map((name, index) => [name, resolved2[index] ?? ANY_TYPE])));
|
|
18667
|
+
}
|
|
18668
|
+
|
|
18573
18669
|
// ../compiler/src/checker/method-receiver.ts
|
|
18574
18670
|
var SELF_PARAMETER = "self";
|
|
18575
18671
|
function resolveNonNominalMethod(receiver, method) {
|
|
@@ -19383,15 +19479,48 @@ function checkLoopBody(context, body, facts) {
|
|
|
19383
19479
|
checkBlock(context, body);
|
|
19384
19480
|
context.setFlow(entry);
|
|
19385
19481
|
}
|
|
19482
|
+
function isTruthyLiteral(condition) {
|
|
19483
|
+
if (condition.kind === "group-expression") {
|
|
19484
|
+
return isTruthyLiteral(condition.expression);
|
|
19485
|
+
}
|
|
19486
|
+
const literal2 = condition.kind === "number-literal" || condition.kind === "string-literal" || condition.kind === "template-literal";
|
|
19487
|
+
return literal2 || condition.kind === "boolean-literal" && condition.value;
|
|
19488
|
+
}
|
|
19489
|
+
function isFalsyLiteral(condition) {
|
|
19490
|
+
if (condition.kind === "group-expression") {
|
|
19491
|
+
return isFalsyLiteral(condition.expression);
|
|
19492
|
+
}
|
|
19493
|
+
return condition.kind === "nil-literal" || condition.kind === "boolean-literal" && !condition.value;
|
|
19494
|
+
}
|
|
19495
|
+
function hasBreak(body) {
|
|
19496
|
+
return body.some((statement) => {
|
|
19497
|
+
if (statement.kind === "break-statement") {
|
|
19498
|
+
return true;
|
|
19499
|
+
}
|
|
19500
|
+
if (statement.kind === "do-statement") {
|
|
19501
|
+
return hasBreak(statement.body);
|
|
19502
|
+
}
|
|
19503
|
+
if (statement.kind === "if-statement") {
|
|
19504
|
+
return statement.clauses.some((clause) => hasBreak(clause.body)) || statement.alternate !== null && hasBreak(statement.alternate);
|
|
19505
|
+
}
|
|
19506
|
+
return false;
|
|
19507
|
+
});
|
|
19508
|
+
}
|
|
19386
19509
|
function checkWhile(context, statement) {
|
|
19387
19510
|
forgetAssignedPaths(context, statement.body);
|
|
19388
19511
|
checkExpression(context, statement.condition);
|
|
19389
19512
|
checkLoopBody(context, statement.body, conditionFacts(context, statement.condition));
|
|
19390
19513
|
context.applyFlowFacts(negatedFacts(context, statement.condition));
|
|
19514
|
+
if (isTruthyLiteral(statement.condition) && !hasBreak(statement.body)) {
|
|
19515
|
+
context.markUnreachable();
|
|
19516
|
+
}
|
|
19391
19517
|
}
|
|
19392
19518
|
function checkRepeat(context, statement) {
|
|
19393
19519
|
checkLoopBody(context, statement.body, /* @__PURE__ */ new Map());
|
|
19394
19520
|
checkExpression(context, statement.condition);
|
|
19521
|
+
if (isFalsyLiteral(statement.condition) && !hasBreak(statement.body)) {
|
|
19522
|
+
context.markUnreachable();
|
|
19523
|
+
}
|
|
19395
19524
|
}
|
|
19396
19525
|
function checkNumericFor(context, statement) {
|
|
19397
19526
|
const bounds = [statement.start, statement.limit, statement.step].filter((value) => value !== null);
|
|
@@ -19505,7 +19634,31 @@ function buildFunctionType(context, parameters, returnAnnotation, contextual = n
|
|
|
19505
19634
|
const names = named2.map((parameter) => parameter.name);
|
|
19506
19635
|
return createFunction(types, context.resolveAnnotation(returnAnnotation), minimumArguments(context, parameters), isVariadic, names);
|
|
19507
19636
|
}
|
|
19508
|
-
function
|
|
19637
|
+
function applyTypeParameters(context, type, names, constraints) {
|
|
19638
|
+
if (names.length === 0) {
|
|
19639
|
+
return type;
|
|
19640
|
+
}
|
|
19641
|
+
context.noteTypeParameters(names);
|
|
19642
|
+
type.typeParameters = [...names];
|
|
19643
|
+
type.typeConstraints = names.map((unused, index) => {
|
|
19644
|
+
const constraint = constraints[index];
|
|
19645
|
+
return constraint === void 0 || constraint === null ? null : context.resolveAnnotation(constraint);
|
|
19646
|
+
});
|
|
19647
|
+
return type;
|
|
19648
|
+
}
|
|
19649
|
+
var FALLTHROUGH_KINDS = /* @__PURE__ */ new Set(["any", "void", "nil", "optional", "unknown"]);
|
|
19650
|
+
function toleratesFallthrough(declared) {
|
|
19651
|
+
if (FALLTHROUGH_KINDS.has(declared.kind)) {
|
|
19652
|
+
return true;
|
|
19653
|
+
}
|
|
19654
|
+
return declared.kind === "union" && declared.options.some((option) => option.kind === "nil");
|
|
19655
|
+
}
|
|
19656
|
+
function reportMissingReturn(context, declared, position2) {
|
|
19657
|
+
const name = typeToString(declared);
|
|
19658
|
+
const repair = declared.kind === "tuple" ? "Add a return on every path." : `Add a return on every path, or declare "${name}?".`;
|
|
19659
|
+
context.report("check-missing-return", `This function declares "${name}" but can end without returning a value. ${repair}`, position2);
|
|
19660
|
+
}
|
|
19661
|
+
function checkFunctionBody(context, parameters, returnAnnotation, body, signature, selfType2, position2 = ORIGIN) {
|
|
19509
19662
|
forgetAssignedPaths(context, body);
|
|
19510
19663
|
const entry = context.flowState;
|
|
19511
19664
|
context.setFlow(cloneFlow(entry));
|
|
@@ -19523,6 +19676,10 @@ function checkFunctionBody(context, parameters, returnAnnotation, body, signatur
|
|
|
19523
19676
|
}
|
|
19524
19677
|
}
|
|
19525
19678
|
checkStatements(context, body);
|
|
19679
|
+
const declared = context.currentReturnType();
|
|
19680
|
+
if (declared !== null && context.flowState.reachable && !toleratesFallthrough(declared)) {
|
|
19681
|
+
reportMissingReturn(context, declared, position2);
|
|
19682
|
+
}
|
|
19526
19683
|
const inferred = context.popReturnType();
|
|
19527
19684
|
if (returnAnnotation === null) {
|
|
19528
19685
|
signature.returnType = inferred;
|
|
@@ -19616,7 +19773,8 @@ function checkAssignment(context, statement) {
|
|
|
19616
19773
|
});
|
|
19617
19774
|
}
|
|
19618
19775
|
function checkFunctionDeclaration(context, statement) {
|
|
19619
|
-
const
|
|
19776
|
+
const built = buildFunctionType(context, statement.parameters, statement.returnAnnotation);
|
|
19777
|
+
const type = applyTypeParameters(context, built, statement.typeParameters, statement.typeConstraints);
|
|
19620
19778
|
if (statement.name.kind === "identifier") {
|
|
19621
19779
|
const symbol = { name: statement.name.name, type, isLocal: statement.isLocal, position: statement.position };
|
|
19622
19780
|
if (statement.isLocal) {
|
|
@@ -19626,7 +19784,7 @@ function checkFunctionDeclaration(context, statement) {
|
|
|
19626
19784
|
}
|
|
19627
19785
|
}
|
|
19628
19786
|
context.record(statement.name, type);
|
|
19629
|
-
checkFunctionBody(context, statement.parameters, statement.returnAnnotation, statement.body, type, statement.isMethod ? ANY_TYPE : null);
|
|
19787
|
+
checkFunctionBody(context, statement.parameters, statement.returnAnnotation, statement.body, type, statement.isMethod ? ANY_TYPE : null, statement.position);
|
|
19630
19788
|
}
|
|
19631
19789
|
function checkReturn(context, statement) {
|
|
19632
19790
|
const valueTypes = checkValueList(context, statement.values);
|
|
@@ -19819,17 +19977,18 @@ function checkMember(context, expression) {
|
|
|
19819
19977
|
}
|
|
19820
19978
|
return context.record(expression, extension === null ? ANY_TYPE : EXTENSION_RESULTS[extension.result]);
|
|
19821
19979
|
}
|
|
19822
|
-
function
|
|
19980
|
+
function countArguments2(total) {
|
|
19823
19981
|
return total === 1 ? "1 argument" : `${total} arguments`;
|
|
19824
19982
|
}
|
|
19825
|
-
function checkSignature(context, args,
|
|
19826
|
-
const argumentTypes = checkValueList(context, args,
|
|
19983
|
+
function checkSignature(context, args, declared, position2, owner = "This call", typeArguments = []) {
|
|
19984
|
+
const argumentTypes = checkValueList(context, args, declared.parameters);
|
|
19985
|
+
const signature = specializeCall(context, owner, declared, argumentTypes, typeArguments, position2);
|
|
19827
19986
|
if (argumentTypes.length < signature.minimumArguments) {
|
|
19828
|
-
const message = `This call expects at least ${
|
|
19987
|
+
const message = `This call expects at least ${countArguments2(signature.minimumArguments)} but received ${argumentTypes.length}.`;
|
|
19829
19988
|
context.report("check-argument-count", message, position2);
|
|
19830
19989
|
}
|
|
19831
19990
|
if (!signature.isVariadic && argumentTypes.length > signature.parameters.length) {
|
|
19832
|
-
const message = `This call expects at most ${
|
|
19991
|
+
const message = `This call expects at most ${countArguments2(signature.parameters.length)} but received ${argumentTypes.length}.`;
|
|
19833
19992
|
context.report("check-argument-count", message, position2);
|
|
19834
19993
|
}
|
|
19835
19994
|
signature.parameters.forEach((parameter, index) => {
|
|
@@ -19850,13 +20009,17 @@ function checkSignature(context, args, signature, position2) {
|
|
|
19850
20009
|
}
|
|
19851
20010
|
return signature.returnType;
|
|
19852
20011
|
}
|
|
20012
|
+
function callOwner(expression) {
|
|
20013
|
+
const name = expression.method ?? (expression.callee.kind === "identifier" ? expression.callee.name : null);
|
|
20014
|
+
return name === null ? "This call" : `Function "${name}"`;
|
|
20015
|
+
}
|
|
19853
20016
|
function checkArguments(context, expression, calleeType) {
|
|
19854
20017
|
if (calleeType.kind !== "function") {
|
|
19855
20018
|
checkValueList(context, expression.args);
|
|
19856
20019
|
reportNotCallable(context, expression, calleeType);
|
|
19857
20020
|
return ANY_TYPE;
|
|
19858
20021
|
}
|
|
19859
|
-
return checkSignature(context, expression.args, calleeType, expression.position);
|
|
20022
|
+
return checkSignature(context, expression.args, calleeType, expression.position, callOwner(expression), expression.typeArguments);
|
|
19860
20023
|
}
|
|
19861
20024
|
function isSuperCall(expression) {
|
|
19862
20025
|
return expression.method === null && expression.callee.kind === "identifier" && expression.callee.name === "super";
|
|
@@ -19871,14 +20034,14 @@ function checkMethodCall(context, expression, method, receiver) {
|
|
|
19871
20034
|
checkValueList(context, expression.args);
|
|
19872
20035
|
return ANY_TYPE;
|
|
19873
20036
|
}
|
|
19874
|
-
return checkSignature(context, expression.args, withoutSelfParameter(signature), expression.position);
|
|
20037
|
+
return checkSignature(context, expression.args, withoutSelfParameter(signature), expression.position, callOwner(expression), expression.typeArguments);
|
|
19875
20038
|
}
|
|
19876
20039
|
const declared = memberOf(context, receiver, method);
|
|
19877
20040
|
if (declared?.type.kind === "function") {
|
|
19878
20041
|
if (declared.deprecated === true) {
|
|
19879
20042
|
context.warn("check-deprecated-use", `Member "${method}" is deprecated.`, expression.position);
|
|
19880
20043
|
}
|
|
19881
|
-
return checkSignature(context, expression.args, declared.type, expression.position);
|
|
20044
|
+
return checkSignature(context, expression.args, declared.type, expression.position, callOwner(expression), expression.typeArguments);
|
|
19882
20045
|
}
|
|
19883
20046
|
if (!isMtaElement(context, receiver.name)) {
|
|
19884
20047
|
checkValueList(context, expression.args);
|
|
@@ -20019,8 +20182,9 @@ function checkMultiValueExpression(context, expression, expected = null) {
|
|
|
20019
20182
|
case "table-expression":
|
|
20020
20183
|
return checkTable(context, expression);
|
|
20021
20184
|
case "function-expression": {
|
|
20022
|
-
const
|
|
20023
|
-
|
|
20185
|
+
const built = buildFunctionType(context, expression.parameters, expression.returnAnnotation, contextualFunction(expected));
|
|
20186
|
+
const type = applyTypeParameters(context, built, expression.typeParameters, expression.typeConstraints);
|
|
20187
|
+
checkFunctionBody(context, expression.parameters, expression.returnAnnotation, expression.body, type, null, expression.position);
|
|
20024
20188
|
return context.record(expression, type);
|
|
20025
20189
|
}
|
|
20026
20190
|
case "binary-expression": {
|
|
@@ -20109,7 +20273,7 @@ function registerMembers(context, info, statement) {
|
|
|
20109
20273
|
}
|
|
20110
20274
|
const generated = expandClassDecorators(context, statement, fieldTypes);
|
|
20111
20275
|
for (const member of [...statement.members, ...generated]) {
|
|
20112
|
-
const type = member.kind === "class-field" ? fieldTypes.get(member) ?? ANY_TYPE : member.isSynthetic ? syntheticMethodType(context, member, fieldTypes) : buildFunctionType(context, member.parameters, member.returnAnnotation);
|
|
20276
|
+
const type = member.kind === "class-field" ? fieldTypes.get(member) ?? ANY_TYPE : member.isSynthetic ? syntheticMethodType(context, member, fieldTypes) : applyTypeParameters(context, buildFunctionType(context, member.parameters, member.returnAnnotation), member.typeParameters, member.typeConstraints);
|
|
20113
20277
|
const decorators = member.decorators.map((decorator) => decorator.name);
|
|
20114
20278
|
if (member.kind === "class-method" && isMetamethodMember(member)) {
|
|
20115
20279
|
checkMetamethod(context, info.name, member, type);
|
|
@@ -20169,11 +20333,11 @@ function checkMethodBody(context, info, member) {
|
|
|
20169
20333
|
return;
|
|
20170
20334
|
}
|
|
20171
20335
|
if (member.isStatic) {
|
|
20172
|
-
checkFunctionBody(context, member.parameters, member.returnAnnotation, member.body, signature, null);
|
|
20336
|
+
checkFunctionBody(context, member.parameters, member.returnAnnotation, member.body, signature, null, member.position);
|
|
20173
20337
|
return;
|
|
20174
20338
|
}
|
|
20175
20339
|
context.pushClassMethod({ className: info.name, methodName: member.name });
|
|
20176
|
-
checkFunctionBody(context, member.parameters, member.returnAnnotation, member.body, signature, selfType(info));
|
|
20340
|
+
checkFunctionBody(context, member.parameters, member.returnAnnotation, member.body, signature, selfType(info), member.position);
|
|
20177
20341
|
context.popClassMethod();
|
|
20178
20342
|
}
|
|
20179
20343
|
function resolveSuperClass(context, statement) {
|