@thigasdevelopment/luam 0.18.2 → 0.19.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/README.md +3 -3
- package/lua/class.lua +1 -1
- package/luam.mjs +514 -165
- package/package.json +1 -1
package/luam.mjs
CHANGED
|
@@ -4521,7 +4521,7 @@ function parseDecorators(stream) {
|
|
|
4521
4521
|
}
|
|
4522
4522
|
return decorators;
|
|
4523
4523
|
}
|
|
4524
|
-
function parseClassMethod(stream, token, decorators) {
|
|
4524
|
+
function parseClassMethod(stream, token, decorators, isStatic) {
|
|
4525
4525
|
stream.expect("operator", "=");
|
|
4526
4526
|
const expression = parseFunctionExpression(stream);
|
|
4527
4527
|
return {
|
|
@@ -4529,6 +4529,7 @@ function parseClassMethod(stream, token, decorators) {
|
|
|
4529
4529
|
name: token.value,
|
|
4530
4530
|
isConstructor: token.value === "constructor",
|
|
4531
4531
|
isSynthetic: false,
|
|
4532
|
+
isStatic,
|
|
4532
4533
|
parameters: expression.parameters,
|
|
4533
4534
|
returnAnnotation: expression.returnAnnotation,
|
|
4534
4535
|
body: expression.body,
|
|
@@ -4536,7 +4537,7 @@ function parseClassMethod(stream, token, decorators) {
|
|
|
4536
4537
|
position: token.position
|
|
4537
4538
|
};
|
|
4538
4539
|
}
|
|
4539
|
-
function parseBraceClassMethod(stream, token, decorators) {
|
|
4540
|
+
function parseBraceClassMethod(stream, token, decorators, isStatic) {
|
|
4540
4541
|
const parameters = parseParameters(stream);
|
|
4541
4542
|
const returnAnnotation = parseOptionalAnnotation(stream);
|
|
4542
4543
|
const body = parseBraceBlock(stream);
|
|
@@ -4545,6 +4546,7 @@ function parseBraceClassMethod(stream, token, decorators) {
|
|
|
4545
4546
|
name: token.value,
|
|
4546
4547
|
isConstructor: token.value === "constructor",
|
|
4547
4548
|
isSynthetic: false,
|
|
4549
|
+
isStatic,
|
|
4548
4550
|
parameters,
|
|
4549
4551
|
returnAnnotation,
|
|
4550
4552
|
body,
|
|
@@ -4563,20 +4565,35 @@ function expectClassFieldBoundary(stream, token) {
|
|
|
4563
4565
|
}
|
|
4564
4566
|
throw stream.error(`Expected a line break or separator after class member "${token.value}".`, "parse-unexpected-token");
|
|
4565
4567
|
}
|
|
4568
|
+
var STATIC_MODIFIER = "static";
|
|
4569
|
+
function parseStaticModifier(stream) {
|
|
4570
|
+
if (!stream.check("identifier", STATIC_MODIFIER)) {
|
|
4571
|
+
return false;
|
|
4572
|
+
}
|
|
4573
|
+
const modifier = stream.current();
|
|
4574
|
+
if (!stream.checkName(1) || stream.peek(1).position.line !== modifier.position.line) {
|
|
4575
|
+
return false;
|
|
4576
|
+
}
|
|
4577
|
+
const checkpoint = stream.checkpoint();
|
|
4578
|
+
stream.next();
|
|
4579
|
+
stream.eraseToCurrent(checkpoint);
|
|
4580
|
+
return true;
|
|
4581
|
+
}
|
|
4566
4582
|
function parseClassMember(stream) {
|
|
4567
4583
|
const decorators = parseDecorators(stream);
|
|
4584
|
+
const isStatic = parseStaticModifier(stream);
|
|
4568
4585
|
const token = stream.expectName();
|
|
4569
4586
|
if (stream.check("punctuation", "(")) {
|
|
4570
4587
|
stream.report("parse-class-method-form", `Write class member "${token.value}" as "${token.value} = function (...) ... end".`, token.position);
|
|
4571
|
-
return parseBraceClassMethod(stream, token, decorators);
|
|
4588
|
+
return parseBraceClassMethod(stream, token, decorators, isStatic);
|
|
4572
4589
|
}
|
|
4573
4590
|
if (stream.check("operator", "=") && stream.checkAhead(1, "keyword", "function")) {
|
|
4574
|
-
return parseClassMethod(stream, token, decorators);
|
|
4591
|
+
return parseClassMethod(stream, token, decorators, isStatic);
|
|
4575
4592
|
}
|
|
4576
4593
|
const annotation = parseFieldAnnotation(stream);
|
|
4577
4594
|
const value = stream.match("operator", "=") ? parseExpression(stream) : null;
|
|
4578
4595
|
expectClassFieldBoundary(stream, token);
|
|
4579
|
-
return { kind: "class-field", name: token.value, annotation, value, decorators, position: token.position };
|
|
4596
|
+
return { kind: "class-field", name: token.value, annotation, value, decorators, isStatic, position: token.position };
|
|
4580
4597
|
}
|
|
4581
4598
|
function parseClassModifiers(stream, declaration) {
|
|
4582
4599
|
while (stream.check("keyword") && CLASS_MODIFIERS.has(stream.current().value)) {
|
|
@@ -6584,7 +6601,7 @@ import { tmpdir } from "node:os";
|
|
|
6584
6601
|
import { join as join2 } from "node:path";
|
|
6585
6602
|
|
|
6586
6603
|
// src/cli/version.ts
|
|
6587
|
-
var VERSION = true ? "0.
|
|
6604
|
+
var VERSION = true ? "0.19.1" : "0.0.0-dev";
|
|
6588
6605
|
var PROGRAM_NAME = "luam";
|
|
6589
6606
|
var PROGRAM_DESCRIPTION = "luam \u2014 the Luam compiler for Multi Theft Auto resources.";
|
|
6590
6607
|
|
|
@@ -8455,8 +8472,8 @@ var MTA_AUDIO_CLIENT = {
|
|
|
8455
8472
|
isSoundPaused: fn([named("Element")], BOOLEAN, 1),
|
|
8456
8473
|
playSFX: fn([STRING, NUMBER, NUMBER, BOOLEAN], named("Element"), 3),
|
|
8457
8474
|
playSFX3D: fn([STRING, NUMBER, NUMBER, NUMBER, NUMBER, NUMBER, BOOLEAN], named("Element"), 6),
|
|
8458
|
-
playSound: fn([STRING, BOOLEAN, BOOLEAN], named("
|
|
8459
|
-
playSound3D: fn([STRING, NUMBER, NUMBER, NUMBER, BOOLEAN, BOOLEAN], named("
|
|
8475
|
+
playSound: fn([STRING, BOOLEAN, BOOLEAN], named("Sound"), 1),
|
|
8476
|
+
playSound3D: fn([STRING, NUMBER, NUMBER, NUMBER, BOOLEAN, BOOLEAN], named("Sound3D"), 4),
|
|
8460
8477
|
playSoundFrontEnd: fn([NUMBER], BOOLEAN, 1),
|
|
8461
8478
|
setRadioChannel: fn([NUMBER], BOOLEAN, 1),
|
|
8462
8479
|
setSoundEffectEnabled: fn(
|
|
@@ -8521,7 +8538,7 @@ var MTA_BLIP_CLIENT = {
|
|
|
8521
8538
|
var MTA_BROWSER_CLIENT = {
|
|
8522
8539
|
canBrowserNavigateBack: fn([named("Browser")], BOOLEAN, 1),
|
|
8523
8540
|
canBrowserNavigateForward: fn([named("Browser")], BOOLEAN, 1),
|
|
8524
|
-
createBrowser: fn([NUMBER, NUMBER, BOOLEAN, BOOLEAN], named("
|
|
8541
|
+
createBrowser: fn([NUMBER, NUMBER, BOOLEAN, BOOLEAN], named("Browser"), 3),
|
|
8525
8542
|
executeBrowserJavascript: fn([named("Browser"), STRING], BOOLEAN, 2),
|
|
8526
8543
|
focusBrowser: fn([named("Browser")], BOOLEAN, 1),
|
|
8527
8544
|
getBrowserProperty: fn([named("Browser"), STRING], BOOLEAN, 2),
|
|
@@ -8611,10 +8628,10 @@ var MTA_DISCORD_CLIENT = {
|
|
|
8611
8628
|
// ../mta-types/src/generated/api/mta-drawing-client.ts
|
|
8612
8629
|
var MTA_DRAWING_CLIENT = {
|
|
8613
8630
|
dxConvertPixels: fn([STRING, STRING, NUMBER], STRING, 2),
|
|
8614
|
-
dxCreateFont: fn([STRING, NUMBER, BOOLEAN, STRING], named("
|
|
8615
|
-
dxCreateRenderTarget: fn([NUMBER, NUMBER, BOOLEAN], named("
|
|
8616
|
-
dxCreateScreenSource: fn([NUMBER, NUMBER], named("
|
|
8617
|
-
dxCreateShader: fn([STRING, NUMBER, NUMBER, BOOLEAN, STRING], tupleOf([named("
|
|
8631
|
+
dxCreateFont: fn([STRING, NUMBER, BOOLEAN, STRING], named("DxFont"), 1),
|
|
8632
|
+
dxCreateRenderTarget: fn([NUMBER, NUMBER, BOOLEAN], named("DxRenderTarget"), 2),
|
|
8633
|
+
dxCreateScreenSource: fn([NUMBER, NUMBER], named("DxScreenSource"), 2),
|
|
8634
|
+
dxCreateShader: fn([STRING, NUMBER, NUMBER, BOOLEAN, STRING], tupleOf([named("DxShader"), STRING]), 1),
|
|
8618
8635
|
dxCreateTexture: fn(
|
|
8619
8636
|
[
|
|
8620
8637
|
STRING,
|
|
@@ -9232,22 +9249,22 @@ var MTA_GUI_CLIENT = {
|
|
|
9232
9249
|
guiComboBoxSetOpen: fn([named("Element"), BOOLEAN], BOOLEAN, 2),
|
|
9233
9250
|
guiComboBoxSetSelected: fn([named("Element"), NUMBER], BOOLEAN, 2),
|
|
9234
9251
|
guiCreateBrowser: fn([NUMBER, NUMBER, NUMBER, NUMBER, BOOLEAN, BOOLEAN, BOOLEAN, named("GuiElement")], named("GuiBrowser"), 6),
|
|
9235
|
-
guiCreateButton: fn([NUMBER, NUMBER, NUMBER, NUMBER, STRING, BOOLEAN, named("GuiElement")], named("
|
|
9236
|
-
guiCreateCheckBox: fn([NUMBER, NUMBER, NUMBER, NUMBER, STRING, BOOLEAN, BOOLEAN, named("GuiElement")], named("
|
|
9237
|
-
guiCreateComboBox: fn([NUMBER, NUMBER, NUMBER, NUMBER, STRING, BOOLEAN, named("GuiElement")], named("
|
|
9238
|
-
guiCreateEdit: fn([NUMBER, NUMBER, NUMBER, NUMBER, STRING, BOOLEAN, named("GuiElement")], named("
|
|
9239
|
-
guiCreateFont: fn([STRING, NUMBER], named("
|
|
9240
|
-
guiCreateGridList: fn([NUMBER, NUMBER, NUMBER, NUMBER, BOOLEAN, named("GuiElement")], named("
|
|
9241
|
-
guiCreateLabel: fn([NUMBER, NUMBER, NUMBER, NUMBER, STRING, BOOLEAN, named("GuiElement")], named("
|
|
9252
|
+
guiCreateButton: fn([NUMBER, NUMBER, NUMBER, NUMBER, STRING, BOOLEAN, named("GuiElement")], named("GuiButton"), 5),
|
|
9253
|
+
guiCreateCheckBox: fn([NUMBER, NUMBER, NUMBER, NUMBER, STRING, BOOLEAN, BOOLEAN, named("GuiElement")], named("GuiCheckbox"), 6),
|
|
9254
|
+
guiCreateComboBox: fn([NUMBER, NUMBER, NUMBER, NUMBER, STRING, BOOLEAN, named("GuiElement")], named("GuiCombobox"), 5),
|
|
9255
|
+
guiCreateEdit: fn([NUMBER, NUMBER, NUMBER, NUMBER, STRING, BOOLEAN, named("GuiElement")], named("GuiEdit"), 5),
|
|
9256
|
+
guiCreateFont: fn([STRING, NUMBER], named("GuiFont"), 1),
|
|
9257
|
+
guiCreateGridList: fn([NUMBER, NUMBER, NUMBER, NUMBER, BOOLEAN, named("GuiElement")], named("GuiGridList"), 4),
|
|
9258
|
+
guiCreateLabel: fn([NUMBER, NUMBER, NUMBER, NUMBER, STRING, BOOLEAN, named("GuiElement")], named("GuiLabel"), 5),
|
|
9242
9259
|
guiCreateMemo: fn([NUMBER, NUMBER, NUMBER, NUMBER, STRING, BOOLEAN, named("GuiElement")], named("GuiMemo"), 5),
|
|
9243
9260
|
guiCreateProgressBar: fn([NUMBER, NUMBER, NUMBER, NUMBER, BOOLEAN, named("GuiElement")], named("Element"), 4),
|
|
9244
|
-
guiCreateRadioButton: fn([NUMBER, NUMBER, NUMBER, NUMBER, STRING, BOOLEAN, named("GuiElement")], named("
|
|
9261
|
+
guiCreateRadioButton: fn([NUMBER, NUMBER, NUMBER, NUMBER, STRING, BOOLEAN, named("GuiElement")], named("GuiRadioButton"), 5),
|
|
9245
9262
|
guiCreateScrollBar: fn([NUMBER, NUMBER, NUMBER, NUMBER, BOOLEAN, BOOLEAN, named("GuiElement")], named("GuiElement"), 5),
|
|
9246
9263
|
guiCreateScrollPane: fn([NUMBER, NUMBER, NUMBER, NUMBER, BOOLEAN, named("GuiElement")], named("Element"), 4),
|
|
9247
|
-
guiCreateStaticImage: fn([NUMBER, NUMBER, NUMBER, NUMBER, STRING, BOOLEAN, named("GuiElement")], named("
|
|
9248
|
-
guiCreateTab: fn([STRING, named("GuiElement")], named("
|
|
9249
|
-
guiCreateTabPanel: fn([NUMBER, NUMBER, NUMBER, NUMBER, BOOLEAN, named("GuiElement")], named("
|
|
9250
|
-
guiCreateWindow: fn([NUMBER, NUMBER, NUMBER, NUMBER, STRING, BOOLEAN], named("
|
|
9264
|
+
guiCreateStaticImage: fn([NUMBER, NUMBER, NUMBER, NUMBER, STRING, BOOLEAN, named("GuiElement")], named("GuiStaticImage"), 5),
|
|
9265
|
+
guiCreateTab: fn([STRING, named("GuiElement")], named("GuiTab"), 2),
|
|
9266
|
+
guiCreateTabPanel: fn([NUMBER, NUMBER, NUMBER, NUMBER, BOOLEAN, named("GuiElement")], named("GuiTabPanel"), 4),
|
|
9267
|
+
guiCreateWindow: fn([NUMBER, NUMBER, NUMBER, NUMBER, STRING, BOOLEAN], named("GuiWindow"), 5),
|
|
9251
9268
|
guiDeleteTab: fn([named("Element"), named("Element")], BOOLEAN, 2),
|
|
9252
9269
|
guiEditGetCaretIndex: fn([named("Element")], NUMBER, 1),
|
|
9253
9270
|
guiEditGetMaxLength: fn([named("GuiEdit")], NUMBER, 1),
|
|
@@ -11590,7 +11607,7 @@ var MTA_OOP_1 = [
|
|
|
11590
11607
|
),
|
|
11591
11608
|
oopClass(
|
|
11592
11609
|
"DxFont",
|
|
11593
|
-
|
|
11610
|
+
"Element",
|
|
11594
11611
|
[
|
|
11595
11612
|
oopMethod("getHeight", "client", "dxGetFontHeight", fn([NUMBER, ANY], NUMBER, 0)),
|
|
11596
11613
|
oopMethod("getSize", "client", "dxGetTextSize", fn([STRING, NUMBER, NUMBER, NUMBER, ANY, BOOLEAN, BOOLEAN], tupleOf([NUMBER, NUMBER]), 1)),
|
|
@@ -11601,14 +11618,14 @@ var MTA_OOP_1 = [
|
|
|
11601
11618
|
),
|
|
11602
11619
|
oopClass(
|
|
11603
11620
|
"DxRenderTarget",
|
|
11604
|
-
|
|
11621
|
+
"Element",
|
|
11605
11622
|
[],
|
|
11606
11623
|
[],
|
|
11607
11624
|
oopConstructor("client", fn([NUMBER, NUMBER, BOOLEAN], named("DxRenderTarget"), 2), "dxCreateRenderTarget")
|
|
11608
11625
|
),
|
|
11609
11626
|
oopClass(
|
|
11610
11627
|
"DxScreenSource",
|
|
11611
|
-
|
|
11628
|
+
"Element",
|
|
11612
11629
|
[
|
|
11613
11630
|
oopMethod("update", "client", "dxUpdateScreenSource", fn([BOOLEAN], BOOLEAN, 0))
|
|
11614
11631
|
],
|
|
@@ -11621,14 +11638,14 @@ var MTA_OOP_1 = [
|
|
|
11621
11638
|
var MTA_OOP_2 = [
|
|
11622
11639
|
oopClass(
|
|
11623
11640
|
"DxShader",
|
|
11624
|
-
|
|
11641
|
+
"Element",
|
|
11625
11642
|
[],
|
|
11626
11643
|
[],
|
|
11627
11644
|
oopConstructor("client", fn([STRING, NUMBER, NUMBER, BOOLEAN, STRING], named("DxShader"), 1), "dxCreateShader")
|
|
11628
11645
|
),
|
|
11629
11646
|
oopClass(
|
|
11630
11647
|
"DxTexture",
|
|
11631
|
-
|
|
11648
|
+
"Element",
|
|
11632
11649
|
[
|
|
11633
11650
|
oopMethod("getPixels", "client", "dxGetTexturePixels", fn([ANY, ANY, NUMBER, NUMBER, NUMBER, ANY], STRING, 1)),
|
|
11634
11651
|
oopMethod("setEdge", "client", "dxSetTextureEdge", fn([STRING, NUMBER], BOOLEAN, 1)),
|
|
@@ -11917,7 +11934,7 @@ var MTA_OOP_3 = [
|
|
|
11917
11934
|
),
|
|
11918
11935
|
oopClass(
|
|
11919
11936
|
"GuiButton",
|
|
11920
|
-
|
|
11937
|
+
"GuiElement",
|
|
11921
11938
|
[],
|
|
11922
11939
|
[],
|
|
11923
11940
|
oopConstructor("client", fn([NUMBER, NUMBER, NUMBER, NUMBER, STRING, BOOLEAN, named("Element")], named("GuiButton"), 6), "guiCreateButton")
|
|
@@ -11974,7 +11991,7 @@ var MTA_OOP_3 = [
|
|
|
11974
11991
|
),
|
|
11975
11992
|
oopClass(
|
|
11976
11993
|
"GuiElement",
|
|
11977
|
-
|
|
11994
|
+
"Element",
|
|
11978
11995
|
[
|
|
11979
11996
|
oopProperty("alpha", "client", "guiGetAlpha", NUMBER),
|
|
11980
11997
|
oopMethod("blur", "client", "guiBlur", fn([], BOOLEAN, 0)),
|
|
@@ -12027,7 +12044,7 @@ var MTA_OOP_3 = [
|
|
|
12027
12044
|
),
|
|
12028
12045
|
oopClass(
|
|
12029
12046
|
"GuiFont",
|
|
12030
|
-
|
|
12047
|
+
"Element",
|
|
12031
12048
|
[],
|
|
12032
12049
|
[],
|
|
12033
12050
|
oopConstructor("client", fn([STRING, NUMBER], named("GuiFont"), 1), "guiCreateFont")
|
|
@@ -12115,7 +12132,7 @@ var MTA_OOP_3 = [
|
|
|
12115
12132
|
),
|
|
12116
12133
|
oopClass(
|
|
12117
12134
|
"GuiRadioButton",
|
|
12118
|
-
|
|
12135
|
+
"GuiElement",
|
|
12119
12136
|
[
|
|
12120
12137
|
oopMethod("getSelected", "client", "guiRadioButtonGetSelected", fn([], BOOLEAN, 0)),
|
|
12121
12138
|
oopProperty("selected", "client", "guiRadioButtonGetSelected", BOOLEAN),
|
|
@@ -12176,7 +12193,7 @@ var MTA_OOP_4 = [
|
|
|
12176
12193
|
),
|
|
12177
12194
|
oopClass(
|
|
12178
12195
|
"Light",
|
|
12179
|
-
|
|
12196
|
+
"Element",
|
|
12180
12197
|
[
|
|
12181
12198
|
oopProperty("color", "client", "getLightColor", tupleOf([NUMBER, NUMBER, NUMBER])),
|
|
12182
12199
|
oopProperty("direction", "client", "getLightDirection", tupleOf([NUMBER, NUMBER, NUMBER])),
|
|
@@ -13186,6 +13203,34 @@ var DeclarationRegistry = class {
|
|
|
13186
13203
|
}
|
|
13187
13204
|
return null;
|
|
13188
13205
|
}
|
|
13206
|
+
lookupStaticMember(name, member) {
|
|
13207
|
+
const visited = /* @__PURE__ */ new Set();
|
|
13208
|
+
let current = this.lookupClass(name);
|
|
13209
|
+
while (current !== null && !visited.has(current.name)) {
|
|
13210
|
+
const found = current.statics.get(member);
|
|
13211
|
+
if (found !== void 0) {
|
|
13212
|
+
return found;
|
|
13213
|
+
}
|
|
13214
|
+
visited.add(current.name);
|
|
13215
|
+
current = current.superClass === null ? null : this.lookupClass(current.superClass);
|
|
13216
|
+
}
|
|
13217
|
+
return null;
|
|
13218
|
+
}
|
|
13219
|
+
collectStatics(name) {
|
|
13220
|
+
const collected = /* @__PURE__ */ new Map();
|
|
13221
|
+
const visited = /* @__PURE__ */ new Set();
|
|
13222
|
+
let current = this.lookupClass(name);
|
|
13223
|
+
while (current !== null && !visited.has(current.name)) {
|
|
13224
|
+
for (const [member, info] of current.statics) {
|
|
13225
|
+
if (!collected.has(member)) {
|
|
13226
|
+
collected.set(member, info);
|
|
13227
|
+
}
|
|
13228
|
+
}
|
|
13229
|
+
visited.add(current.name);
|
|
13230
|
+
current = current.superClass === null ? null : this.lookupClass(current.superClass);
|
|
13231
|
+
}
|
|
13232
|
+
return [...collected.values()];
|
|
13233
|
+
}
|
|
13189
13234
|
lookupMember(name, member) {
|
|
13190
13235
|
const visited = /* @__PURE__ */ new Set();
|
|
13191
13236
|
const found = this.lookupClassMember(name, member, visited);
|
|
@@ -13217,7 +13262,7 @@ function buildRegistry() {
|
|
|
13217
13262
|
procedural: member.procedural
|
|
13218
13263
|
});
|
|
13219
13264
|
}
|
|
13220
|
-
registry.declareClass({ name: declaration.name, superClass: declaration.parent, interfaces: [], members, position: MTA_POSITION });
|
|
13265
|
+
registry.declareClass({ name: declaration.name, superClass: declaration.parent, interfaces: [], members, statics: /* @__PURE__ */ new Map(), position: MTA_POSITION });
|
|
13221
13266
|
}
|
|
13222
13267
|
return registry;
|
|
13223
13268
|
}
|
|
@@ -13296,13 +13341,13 @@ function chooseCandidate(source, candidates3) {
|
|
|
13296
13341
|
return matching.length === 1 && best !== void 0 ? best : null;
|
|
13297
13342
|
}
|
|
13298
13343
|
function missingKeys(source, target) {
|
|
13299
|
-
const
|
|
13344
|
+
const missing2 = [];
|
|
13300
13345
|
for (const [name, member] of target.members) {
|
|
13301
13346
|
if (member.kind !== "optional" && !source.members.has(name)) {
|
|
13302
|
-
|
|
13347
|
+
missing2.push(`"${name}"`);
|
|
13303
13348
|
}
|
|
13304
13349
|
}
|
|
13305
|
-
return
|
|
13350
|
+
return missing2;
|
|
13306
13351
|
}
|
|
13307
13352
|
function missingKeyHint(source, target) {
|
|
13308
13353
|
if (source.kind !== "record" || source.isLiteral !== true) {
|
|
@@ -13314,11 +13359,11 @@ function missingKeyHint(source, target) {
|
|
|
13314
13359
|
if (candidate === null) {
|
|
13315
13360
|
return "";
|
|
13316
13361
|
}
|
|
13317
|
-
const
|
|
13318
|
-
if (
|
|
13362
|
+
const missing2 = missingKeys(source, candidate);
|
|
13363
|
+
if (missing2.length === 0) {
|
|
13319
13364
|
return "";
|
|
13320
13365
|
}
|
|
13321
|
-
const label2 =
|
|
13366
|
+
const label2 = missing2.length === 1 ? `Key ${missing2[0]} is` : `Keys ${missing2.join(", ")} are`;
|
|
13322
13367
|
return ` ${label2} missing from "${typeToString(candidate)}".`;
|
|
13323
13368
|
}
|
|
13324
13369
|
|
|
@@ -13424,6 +13469,7 @@ var CheckContext = class {
|
|
|
13424
13469
|
externalReferences = /* @__PURE__ */ new Map();
|
|
13425
13470
|
unknownTypes = /* @__PURE__ */ new Map();
|
|
13426
13471
|
calledMembers = /* @__PURE__ */ new Set();
|
|
13472
|
+
staticAccess = /* @__PURE__ */ new Set();
|
|
13427
13473
|
typeParameters = /* @__PURE__ */ new Set();
|
|
13428
13474
|
generatedMembers = /* @__PURE__ */ new Map();
|
|
13429
13475
|
mode;
|
|
@@ -13458,17 +13504,24 @@ var CheckContext = class {
|
|
|
13458
13504
|
pushNarrowing(facts) {
|
|
13459
13505
|
this.narrowings.push(new Map(facts));
|
|
13460
13506
|
}
|
|
13507
|
+
get isNarrowed() {
|
|
13508
|
+
return this.narrowings.length > 0;
|
|
13509
|
+
}
|
|
13461
13510
|
popNarrowing() {
|
|
13462
13511
|
this.narrowings.pop();
|
|
13463
13512
|
}
|
|
13464
|
-
forgetNarrowing(
|
|
13513
|
+
forgetNarrowing(path) {
|
|
13465
13514
|
for (const frame of this.narrowings) {
|
|
13466
|
-
frame.
|
|
13515
|
+
for (const key of [...frame.keys()]) {
|
|
13516
|
+
if (key === path || key.startsWith(`${path}.`) || path.startsWith(`${key}.`)) {
|
|
13517
|
+
frame.delete(key);
|
|
13518
|
+
}
|
|
13519
|
+
}
|
|
13467
13520
|
}
|
|
13468
13521
|
}
|
|
13469
|
-
narrowedType(
|
|
13522
|
+
narrowedType(path) {
|
|
13470
13523
|
for (let index = this.narrowings.length - 1; index >= 0; index -= 1) {
|
|
13471
|
-
const found = this.narrowings[index]?.get(
|
|
13524
|
+
const found = this.narrowings[index]?.get(path);
|
|
13472
13525
|
if (found !== void 0) {
|
|
13473
13526
|
return found;
|
|
13474
13527
|
}
|
|
@@ -13483,20 +13536,20 @@ var CheckContext = class {
|
|
|
13483
13536
|
this.predeclared.delete(name);
|
|
13484
13537
|
return info;
|
|
13485
13538
|
}
|
|
13486
|
-
|
|
13487
|
-
return this.predeclared.has(name);
|
|
13488
|
-
}
|
|
13489
|
-
awaitsDeclaration(name) {
|
|
13539
|
+
pendingDeclarationOf(name) {
|
|
13490
13540
|
const seen = /* @__PURE__ */ new Set();
|
|
13491
13541
|
let current = this.declarations.lookupClass(name);
|
|
13492
13542
|
while (current !== null && !seen.has(current.name)) {
|
|
13493
13543
|
if (this.predeclared.has(current.name)) {
|
|
13494
|
-
return
|
|
13544
|
+
return current.name;
|
|
13495
13545
|
}
|
|
13496
13546
|
seen.add(current.name);
|
|
13497
13547
|
current = current.superClass === null ? null : this.declarations.lookupClass(current.superClass);
|
|
13498
13548
|
}
|
|
13499
|
-
return
|
|
13549
|
+
return null;
|
|
13550
|
+
}
|
|
13551
|
+
awaitsDeclaration(name) {
|
|
13552
|
+
return this.pendingDeclarationOf(name) !== null;
|
|
13500
13553
|
}
|
|
13501
13554
|
insideFunction() {
|
|
13502
13555
|
return this.returnStack.length > 0;
|
|
@@ -14156,6 +14209,7 @@ function accessorMethod(field2, decorator, name) {
|
|
|
14156
14209
|
name,
|
|
14157
14210
|
isConstructor: false,
|
|
14158
14211
|
isSynthetic: true,
|
|
14212
|
+
isStatic: false,
|
|
14159
14213
|
parameters: decorator === "Getter" ? [] : [value],
|
|
14160
14214
|
returnAnnotation: decorator === "Getter" ? field2.annotation : voidAnnotation,
|
|
14161
14215
|
body,
|
|
@@ -14164,7 +14218,7 @@ function accessorMethod(field2, decorator, name) {
|
|
|
14164
14218
|
};
|
|
14165
14219
|
}
|
|
14166
14220
|
function generatedMethod(field2, name, parameters, returnAnnotation, kind, fields) {
|
|
14167
|
-
return { kind: "class-method", name, isConstructor: false, isSynthetic: true, parameters, returnAnnotation, body: [], decorators: [], generated: { kind, fields }, position: field2.position };
|
|
14221
|
+
return { kind: "class-method", name, isConstructor: false, isSynthetic: true, isStatic: false, parameters, returnAnnotation, body: [], decorators: [], generated: { kind, fields }, position: field2.position };
|
|
14168
14222
|
}
|
|
14169
14223
|
function typeName(name, node) {
|
|
14170
14224
|
return { kind: "type-name", name, typeArguments: [], position: node.position };
|
|
@@ -14272,6 +14326,139 @@ function expandClassDecorators(context, statement, fieldTypes) {
|
|
|
14272
14326
|
return generated;
|
|
14273
14327
|
}
|
|
14274
14328
|
|
|
14329
|
+
// ../compiler/src/checker/access-path.ts
|
|
14330
|
+
function pathOf2(expression) {
|
|
14331
|
+
if (expression.kind === "identifier") {
|
|
14332
|
+
return expression.name;
|
|
14333
|
+
}
|
|
14334
|
+
if (expression.kind !== "member-expression") {
|
|
14335
|
+
return null;
|
|
14336
|
+
}
|
|
14337
|
+
const object = pathOf2(expression.object);
|
|
14338
|
+
return object === null ? null : `${object}.${expression.property}`;
|
|
14339
|
+
}
|
|
14340
|
+
function assignedPath(target) {
|
|
14341
|
+
const direct = pathOf2(target);
|
|
14342
|
+
if (direct !== null) {
|
|
14343
|
+
return direct;
|
|
14344
|
+
}
|
|
14345
|
+
return target.kind === "member-expression" || target.kind === "index-expression" ? assignedPath(target.object) : null;
|
|
14346
|
+
}
|
|
14347
|
+
function pathType(context, expression) {
|
|
14348
|
+
if (expression.kind === "identifier") {
|
|
14349
|
+
return context.binder.lookup(expression.name)?.type ?? null;
|
|
14350
|
+
}
|
|
14351
|
+
return expression.kind === "member-expression" ? context.types.get(expression) ?? null : null;
|
|
14352
|
+
}
|
|
14353
|
+
function childExpressions2(expression) {
|
|
14354
|
+
switch (expression.kind) {
|
|
14355
|
+
case "member-expression":
|
|
14356
|
+
return [expression.object];
|
|
14357
|
+
case "index-expression":
|
|
14358
|
+
return [expression.object, expression.index];
|
|
14359
|
+
case "call-expression":
|
|
14360
|
+
return [expression.callee, ...expression.args];
|
|
14361
|
+
case "new-expression":
|
|
14362
|
+
return expression.args;
|
|
14363
|
+
case "table-expression":
|
|
14364
|
+
return expression.fields.flatMap((field2) => field2.key === null ? [field2.value] : [field2.key, field2.value]);
|
|
14365
|
+
case "binary-expression":
|
|
14366
|
+
return [expression.left, expression.right];
|
|
14367
|
+
case "unary-expression":
|
|
14368
|
+
return [expression.operand];
|
|
14369
|
+
case "group-expression":
|
|
14370
|
+
return [expression.expression];
|
|
14371
|
+
default:
|
|
14372
|
+
return [];
|
|
14373
|
+
}
|
|
14374
|
+
}
|
|
14375
|
+
function statementExpressions2(statement) {
|
|
14376
|
+
switch (statement.kind) {
|
|
14377
|
+
case "local-statement":
|
|
14378
|
+
case "return-statement":
|
|
14379
|
+
return statement.values;
|
|
14380
|
+
case "assignment-statement":
|
|
14381
|
+
return [...statement.targets, ...statement.values];
|
|
14382
|
+
case "call-statement":
|
|
14383
|
+
return [statement.expression];
|
|
14384
|
+
case "while-statement":
|
|
14385
|
+
case "repeat-statement":
|
|
14386
|
+
return [statement.condition];
|
|
14387
|
+
case "if-statement":
|
|
14388
|
+
return statement.clauses.map((clause) => clause.condition);
|
|
14389
|
+
case "numeric-for-statement":
|
|
14390
|
+
return statement.step === null ? [statement.start, statement.limit] : [statement.start, statement.limit, statement.step];
|
|
14391
|
+
case "generic-for-statement":
|
|
14392
|
+
return statement.iterators;
|
|
14393
|
+
case "class-declaration":
|
|
14394
|
+
return statement.members.flatMap((member) => member.kind === "class-field" && member.value !== null ? [member.value] : []);
|
|
14395
|
+
default:
|
|
14396
|
+
return [];
|
|
14397
|
+
}
|
|
14398
|
+
}
|
|
14399
|
+
function blockBodies(statement) {
|
|
14400
|
+
switch (statement.kind) {
|
|
14401
|
+
case "do-statement":
|
|
14402
|
+
case "while-statement":
|
|
14403
|
+
case "repeat-statement":
|
|
14404
|
+
case "numeric-for-statement":
|
|
14405
|
+
case "generic-for-statement":
|
|
14406
|
+
case "function-declaration":
|
|
14407
|
+
return [statement.body];
|
|
14408
|
+
case "if-statement":
|
|
14409
|
+
return [...statement.clauses.map((clause) => clause.body), ...statement.alternate === null ? [] : [statement.alternate]];
|
|
14410
|
+
case "class-declaration":
|
|
14411
|
+
return statement.members.filter((member) => member.kind === "class-method").map((member) => member.body);
|
|
14412
|
+
default:
|
|
14413
|
+
return [];
|
|
14414
|
+
}
|
|
14415
|
+
}
|
|
14416
|
+
function collectExpressionPaths(expression, paths) {
|
|
14417
|
+
if (expression.kind === "function-expression") {
|
|
14418
|
+
collectPaths(expression.body, paths);
|
|
14419
|
+
}
|
|
14420
|
+
for (const child of childExpressions2(expression)) {
|
|
14421
|
+
collectExpressionPaths(child, paths);
|
|
14422
|
+
}
|
|
14423
|
+
}
|
|
14424
|
+
function addTargets(statement, paths) {
|
|
14425
|
+
if (statement.kind === "assignment-statement") {
|
|
14426
|
+
for (const target of statement.targets) {
|
|
14427
|
+
const path = assignedPath(target);
|
|
14428
|
+
if (path !== null) {
|
|
14429
|
+
paths.add(path);
|
|
14430
|
+
}
|
|
14431
|
+
}
|
|
14432
|
+
}
|
|
14433
|
+
if (statement.kind === "local-statement") {
|
|
14434
|
+
statement.declarations.forEach((declaration) => paths.add(declaration.name));
|
|
14435
|
+
}
|
|
14436
|
+
}
|
|
14437
|
+
function collectPaths(body, paths) {
|
|
14438
|
+
for (const statement of body) {
|
|
14439
|
+
addTargets(statement, paths);
|
|
14440
|
+
for (const expression of statementExpressions2(statement)) {
|
|
14441
|
+
collectExpressionPaths(expression, paths);
|
|
14442
|
+
}
|
|
14443
|
+
for (const block of blockBodies(statement)) {
|
|
14444
|
+
collectPaths(block, paths);
|
|
14445
|
+
}
|
|
14446
|
+
}
|
|
14447
|
+
}
|
|
14448
|
+
function assignedPaths(body) {
|
|
14449
|
+
const paths = /* @__PURE__ */ new Set();
|
|
14450
|
+
collectPaths(body, paths);
|
|
14451
|
+
return paths;
|
|
14452
|
+
}
|
|
14453
|
+
function forgetAssignedPaths(context, body) {
|
|
14454
|
+
if (!context.isNarrowed) {
|
|
14455
|
+
return;
|
|
14456
|
+
}
|
|
14457
|
+
for (const path of assignedPaths(body)) {
|
|
14458
|
+
context.forgetNarrowing(path);
|
|
14459
|
+
}
|
|
14460
|
+
}
|
|
14461
|
+
|
|
14275
14462
|
// ../compiler/src/extensions/native-extensions.ts
|
|
14276
14463
|
var NATIVE_EXTENSIONS = [
|
|
14277
14464
|
{ receiver: "table", property: "count", target: "table.size", style: "property", result: "number", helper: "table" },
|
|
@@ -17591,11 +17778,11 @@ var ELEMENT_TYPES = [
|
|
|
17591
17778
|
{ name: "Camera", parent: "Element" },
|
|
17592
17779
|
{ name: "ColShape", parent: "Element" },
|
|
17593
17780
|
{ name: "Connection", parent: null },
|
|
17594
|
-
{ name: "DxFont", parent:
|
|
17595
|
-
{ name: "DxRenderTarget", parent:
|
|
17596
|
-
{ name: "DxScreenSource", parent:
|
|
17597
|
-
{ name: "DxShader", parent:
|
|
17598
|
-
{ name: "DxTexture", parent:
|
|
17781
|
+
{ name: "DxFont", parent: "Element" },
|
|
17782
|
+
{ name: "DxRenderTarget", parent: "Element" },
|
|
17783
|
+
{ name: "DxScreenSource", parent: "Element" },
|
|
17784
|
+
{ name: "DxShader", parent: "Element" },
|
|
17785
|
+
{ name: "DxTexture", parent: "Element" },
|
|
17599
17786
|
{ name: "Effect", parent: "Element" },
|
|
17600
17787
|
{ name: "Element", parent: null },
|
|
17601
17788
|
{ name: "Engine", parent: null },
|
|
@@ -17604,21 +17791,21 @@ var ELEMENT_TYPES = [
|
|
|
17604
17791
|
{ name: "EngineTXD", parent: null },
|
|
17605
17792
|
{ name: "File", parent: null },
|
|
17606
17793
|
{ name: "GuiBrowser", parent: "GuiElement" },
|
|
17607
|
-
{ name: "GuiButton", parent:
|
|
17794
|
+
{ name: "GuiButton", parent: "GuiElement" },
|
|
17608
17795
|
{ name: "GuiCheckbox", parent: "GuiElement" },
|
|
17609
17796
|
{ name: "GuiCombobox", parent: "GuiElement" },
|
|
17610
17797
|
{ name: "GuiEdit", parent: "GuiElement" },
|
|
17611
|
-
{ name: "GuiElement", parent:
|
|
17612
|
-
{ name: "GuiFont", parent:
|
|
17798
|
+
{ name: "GuiElement", parent: "Element" },
|
|
17799
|
+
{ name: "GuiFont", parent: "Element" },
|
|
17613
17800
|
{ name: "GuiGridList", parent: "GuiElement" },
|
|
17614
17801
|
{ name: "GuiLabel", parent: "GuiElement" },
|
|
17615
17802
|
{ name: "GuiMemo", parent: "GuiElement" },
|
|
17616
|
-
{ name: "GuiRadioButton", parent:
|
|
17803
|
+
{ name: "GuiRadioButton", parent: "GuiElement" },
|
|
17617
17804
|
{ name: "GuiStaticImage", parent: "GuiElement" },
|
|
17618
17805
|
{ name: "GuiTab", parent: "GuiElement" },
|
|
17619
17806
|
{ name: "GuiTabPanel", parent: "GuiElement" },
|
|
17620
17807
|
{ name: "GuiWindow", parent: "GuiElement" },
|
|
17621
|
-
{ name: "Light", parent:
|
|
17808
|
+
{ name: "Light", parent: "Element" },
|
|
17622
17809
|
{ name: "Marker", parent: "Element" },
|
|
17623
17810
|
{ name: "Material", parent: "Element" },
|
|
17624
17811
|
{ name: "Object", parent: "Element" },
|
|
@@ -17774,6 +17961,28 @@ function checkInterfaceMember(context, name, members, expression) {
|
|
|
17774
17961
|
context.report("check-unknown-member", `Interface "${name}" has no member "${expression.property}". Declared members: ${keys}.`, expression.position);
|
|
17775
17962
|
return ANY_TYPE;
|
|
17776
17963
|
}
|
|
17964
|
+
function isUserClassReference(context, name) {
|
|
17965
|
+
const symbol = context.binder.lookup(name);
|
|
17966
|
+
return symbol !== null && !symbol.isLocal && context.declarations.lookupClass(name) !== null;
|
|
17967
|
+
}
|
|
17968
|
+
function resolveStaticMember(context, className, expression) {
|
|
17969
|
+
const member = context.declarations.lookupStaticMember(className, expression.property);
|
|
17970
|
+
if (member !== null) {
|
|
17971
|
+
if (member.deprecated === true) {
|
|
17972
|
+
context.warn("check-deprecated-use", `Member "${expression.property}" is deprecated.`, expression.position);
|
|
17973
|
+
}
|
|
17974
|
+
context.staticAccess.add(expression);
|
|
17975
|
+
return member.type;
|
|
17976
|
+
}
|
|
17977
|
+
if (context.awaitsDeclaration(className)) {
|
|
17978
|
+
context.staticAccess.add(expression);
|
|
17979
|
+
return ANY_TYPE;
|
|
17980
|
+
}
|
|
17981
|
+
const instance = context.declarations.lookupMember(className, expression.property);
|
|
17982
|
+
const hint = instance === null ? "" : ` It is an instance member, so read it from a value of "${className}".`;
|
|
17983
|
+
context.report("check-unknown-member", `Class "${className}" has no static member "${expression.property}".${hint}`, expression.position);
|
|
17984
|
+
return ANY_TYPE;
|
|
17985
|
+
}
|
|
17777
17986
|
function resolveNamedMember(context, name, expression) {
|
|
17778
17987
|
const enumeration = context.declarations.lookupEnum(name);
|
|
17779
17988
|
if (enumeration !== null) {
|
|
@@ -17789,6 +17998,12 @@ function resolveNamedMember(context, name, expression) {
|
|
|
17789
17998
|
if (isMtaElement(context, name)) {
|
|
17790
17999
|
return resolveMtaMember(context, name, expression.property, expression.position)?.type ?? ANY_TYPE;
|
|
17791
18000
|
}
|
|
18001
|
+
const staticMember = context.declarations.lookupStaticMember(name, expression.property);
|
|
18002
|
+
if (staticMember !== null) {
|
|
18003
|
+
const message = `"${expression.property}" is a static member of class "${name}". Read it as "${name}.${expression.property}".`;
|
|
18004
|
+
context.report("check-static-receiver", message, expression.position);
|
|
18005
|
+
return staticMember.type;
|
|
18006
|
+
}
|
|
17792
18007
|
if (context.awaitsDeclaration(name)) {
|
|
17793
18008
|
return ANY_TYPE;
|
|
17794
18009
|
}
|
|
@@ -17821,9 +18036,10 @@ function checkNewExpression(context, expression) {
|
|
|
17821
18036
|
context.report("check-unknown-class", `Class "${expression.className}" is not defined.`, expression.position);
|
|
17822
18037
|
return ANY_TYPE;
|
|
17823
18038
|
}
|
|
17824
|
-
|
|
17825
|
-
|
|
17826
|
-
|
|
18039
|
+
const pending = context.insideFunction() ? null : context.pendingDeclarationOf(expression.className);
|
|
18040
|
+
if (pending !== null) {
|
|
18041
|
+
const subject = pending === expression.className ? `Class "${pending}"` : `Class "${expression.className}" extends "${pending}", which`;
|
|
18042
|
+
context.report("check-class-before-declaration", `${subject} is declared further down this file, so it does not exist yet at this point.`, expression.position);
|
|
17827
18043
|
}
|
|
17828
18044
|
const constructor = context.declarations.lookupMember(expression.className, "constructor");
|
|
17829
18045
|
if (constructor !== null && constructor.type.kind === "function") {
|
|
@@ -17934,19 +18150,19 @@ function resolveUnionMember(context, type, expression) {
|
|
|
17934
18150
|
return null;
|
|
17935
18151
|
}
|
|
17936
18152
|
const resolved2 = [];
|
|
17937
|
-
const
|
|
18153
|
+
const missing2 = [];
|
|
17938
18154
|
for (const option of type.options) {
|
|
17939
18155
|
const member = memberOf(context, option, expression.property);
|
|
17940
18156
|
if (member === null) {
|
|
17941
|
-
|
|
18157
|
+
missing2.push(`"${typeToString(option)}"`);
|
|
17942
18158
|
} else {
|
|
17943
18159
|
resolved2.push(member);
|
|
17944
18160
|
}
|
|
17945
18161
|
}
|
|
17946
|
-
if (
|
|
18162
|
+
if (missing2.length === 0) {
|
|
17947
18163
|
return createUnion(resolved2);
|
|
17948
18164
|
}
|
|
17949
|
-
const message = `"${expression.property}" is not a key of every member of "${typeToString(type)}". It is missing from ${
|
|
18165
|
+
const message = `"${expression.property}" is not a key of every member of "${typeToString(type)}". It is missing from ${missing2.join(", ")}.`;
|
|
17950
18166
|
context.report("check-unknown-union-key", message, expression.position);
|
|
17951
18167
|
return ANY_TYPE;
|
|
17952
18168
|
}
|
|
@@ -17962,18 +18178,19 @@ function literalValue(expression) {
|
|
|
17962
18178
|
return expression.kind === "number-literal" ? createNumberLiteral(expression.value) : null;
|
|
17963
18179
|
}
|
|
17964
18180
|
function discriminantTest(left, right) {
|
|
17965
|
-
if (left.kind !== "member-expression"
|
|
18181
|
+
if (left.kind !== "member-expression") {
|
|
17966
18182
|
return null;
|
|
17967
18183
|
}
|
|
18184
|
+
const path = pathOf2(left.object);
|
|
17968
18185
|
const value = literalValue(right);
|
|
17969
|
-
return value === null ? null : {
|
|
18186
|
+
return path === null || value === null ? null : { path, subject: left.object, property: left.property, value };
|
|
17970
18187
|
}
|
|
17971
|
-
function subjectType(context,
|
|
17972
|
-
const type = context.narrowedType(
|
|
18188
|
+
function subjectType(context, test) {
|
|
18189
|
+
const type = context.narrowedType(test.path) ?? pathType(context, test.subject);
|
|
17973
18190
|
return type === null ? null : withoutNil(type);
|
|
17974
18191
|
}
|
|
17975
18192
|
function filterOptions(context, test, keep) {
|
|
17976
|
-
const subject = subjectType(context, test
|
|
18193
|
+
const subject = subjectType(context, test);
|
|
17977
18194
|
if (subject === null || subject.kind !== "union") {
|
|
17978
18195
|
return null;
|
|
17979
18196
|
}
|
|
@@ -17995,7 +18212,7 @@ function discriminantFact(context, left, right, keep) {
|
|
|
17995
18212
|
return null;
|
|
17996
18213
|
}
|
|
17997
18214
|
const narrowed = filterOptions(context, test, keep);
|
|
17998
|
-
return narrowed === null ? null : [test.
|
|
18215
|
+
return narrowed === null ? null : [test.path, narrowed];
|
|
17999
18216
|
}
|
|
18000
18217
|
|
|
18001
18218
|
// ../compiler/src/checker/narrowing.ts
|
|
@@ -18010,38 +18227,42 @@ var GUARD_TYPES = {
|
|
|
18010
18227
|
thread: THREAD_TYPE,
|
|
18011
18228
|
userdata: USERDATA_TYPE
|
|
18012
18229
|
};
|
|
18013
|
-
function
|
|
18014
|
-
return context.binder.lookup(name)?.type ?? null;
|
|
18015
|
-
}
|
|
18016
|
-
function guardedName(expression) {
|
|
18230
|
+
function guardedPath(expression) {
|
|
18017
18231
|
if (expression.kind !== "call-expression" || expression.callee.kind !== "identifier" || expression.callee.name !== GUARD_FUNCTION) {
|
|
18018
18232
|
return null;
|
|
18019
18233
|
}
|
|
18020
18234
|
const [argument] = expression.args;
|
|
18021
|
-
return argument
|
|
18235
|
+
return argument === void 0 ? null : pathOf2(argument);
|
|
18022
18236
|
}
|
|
18023
18237
|
function guardFact(left, right) {
|
|
18024
|
-
const
|
|
18238
|
+
const path = guardedPath(left);
|
|
18025
18239
|
const value = right.kind === "string-literal" ? GUARD_TYPES[right.value] : void 0;
|
|
18026
|
-
return
|
|
18240
|
+
return path === null || value === void 0 ? null : [path, value];
|
|
18027
18241
|
}
|
|
18028
18242
|
function nilComparison(left, right) {
|
|
18029
|
-
if (
|
|
18030
|
-
return left
|
|
18243
|
+
if (right.kind === "nil-literal" && pathOf2(left) !== null) {
|
|
18244
|
+
return left;
|
|
18245
|
+
}
|
|
18246
|
+
return left.kind === "nil-literal" && pathOf2(right) !== null ? right : null;
|
|
18247
|
+
}
|
|
18248
|
+
function present2(context, expression, facts) {
|
|
18249
|
+
const path = pathOf2(expression);
|
|
18250
|
+
const declared = path === null ? null : pathType(context, expression);
|
|
18251
|
+
if (path !== null && declared !== null) {
|
|
18252
|
+
facts.set(path, withoutNil(declared));
|
|
18031
18253
|
}
|
|
18032
|
-
return right.kind === "identifier" && left.kind === "nil-literal" ? right.name : null;
|
|
18033
18254
|
}
|
|
18034
|
-
function
|
|
18035
|
-
const
|
|
18036
|
-
if (
|
|
18037
|
-
facts.set(
|
|
18255
|
+
function missing(expression, facts) {
|
|
18256
|
+
const path = pathOf2(expression);
|
|
18257
|
+
if (path !== null) {
|
|
18258
|
+
facts.set(path, NIL_TYPE);
|
|
18038
18259
|
}
|
|
18039
18260
|
}
|
|
18040
18261
|
function mergeAlternatives(left, right, facts) {
|
|
18041
|
-
for (const [
|
|
18042
|
-
const other = right.get(
|
|
18262
|
+
for (const [path, type] of left) {
|
|
18263
|
+
const other = right.get(path);
|
|
18043
18264
|
if (other !== void 0) {
|
|
18044
|
-
facts.set(
|
|
18265
|
+
facts.set(path, createUnion([type, other]));
|
|
18045
18266
|
}
|
|
18046
18267
|
}
|
|
18047
18268
|
}
|
|
@@ -18056,8 +18277,8 @@ function collectFacts(context, expression, facts) {
|
|
|
18056
18277
|
collectFacts(context, expression.expression, facts);
|
|
18057
18278
|
return;
|
|
18058
18279
|
}
|
|
18059
|
-
if (expression.kind === "identifier") {
|
|
18060
|
-
present2(context, expression
|
|
18280
|
+
if (expression.kind === "identifier" || expression.kind === "member-expression") {
|
|
18281
|
+
present2(context, expression, facts);
|
|
18061
18282
|
return;
|
|
18062
18283
|
}
|
|
18063
18284
|
if (expression.kind !== "binary-expression") {
|
|
@@ -18074,20 +18295,20 @@ function collectFacts(context, expression, facts) {
|
|
|
18074
18295
|
}
|
|
18075
18296
|
if (expression.operator === "==") {
|
|
18076
18297
|
const guard = guardFact(expression.left, expression.right) ?? guardFact(expression.right, expression.left);
|
|
18077
|
-
const
|
|
18298
|
+
const absent = nilComparison(expression.left, expression.right);
|
|
18078
18299
|
if (guard !== null) {
|
|
18079
18300
|
facts.set(guard[0], guard[1]);
|
|
18080
|
-
} else if (
|
|
18081
|
-
|
|
18301
|
+
} else if (absent !== null) {
|
|
18302
|
+
missing(absent, facts);
|
|
18082
18303
|
} else {
|
|
18083
18304
|
applyDiscriminant(context, expression.left, expression.right, true, facts);
|
|
18084
18305
|
}
|
|
18085
18306
|
return;
|
|
18086
18307
|
}
|
|
18087
18308
|
if (expression.operator === "~=") {
|
|
18088
|
-
const
|
|
18089
|
-
if (
|
|
18090
|
-
present2(context,
|
|
18309
|
+
const tested = nilComparison(expression.left, expression.right);
|
|
18310
|
+
if (tested !== null) {
|
|
18311
|
+
present2(context, tested, facts);
|
|
18091
18312
|
} else {
|
|
18092
18313
|
applyDiscriminant(context, expression.left, expression.right, false, facts);
|
|
18093
18314
|
}
|
|
@@ -18121,15 +18342,15 @@ function guardFacts(context, statement) {
|
|
|
18121
18342
|
function negatedFacts(context, condition) {
|
|
18122
18343
|
const facts = /* @__PURE__ */ new Map();
|
|
18123
18344
|
if (condition.kind === "binary-expression" && condition.operator === "or") {
|
|
18124
|
-
for (const [
|
|
18125
|
-
facts.set(
|
|
18345
|
+
for (const [path, type] of [...negatedFacts(context, condition.left), ...negatedFacts(context, condition.right)]) {
|
|
18346
|
+
facts.set(path, type);
|
|
18126
18347
|
}
|
|
18127
18348
|
return facts;
|
|
18128
18349
|
}
|
|
18129
18350
|
if (condition.kind === "binary-expression" && condition.operator === "==") {
|
|
18130
|
-
const
|
|
18131
|
-
if (
|
|
18132
|
-
present2(context,
|
|
18351
|
+
const tested = nilComparison(condition.left, condition.right);
|
|
18352
|
+
if (tested !== null) {
|
|
18353
|
+
present2(context, tested, facts);
|
|
18133
18354
|
} else {
|
|
18134
18355
|
applyDiscriminant(context, condition.left, condition.right, false, facts);
|
|
18135
18356
|
}
|
|
@@ -18137,8 +18358,8 @@ function negatedFacts(context, condition) {
|
|
|
18137
18358
|
if (condition.kind === "binary-expression" && condition.operator === "~=") {
|
|
18138
18359
|
applyDiscriminant(context, condition.left, condition.right, true, facts);
|
|
18139
18360
|
}
|
|
18140
|
-
if (condition.kind === "unary-expression" && condition.operator === "not"
|
|
18141
|
-
present2(context, condition.operand
|
|
18361
|
+
if (condition.kind === "unary-expression" && condition.operator === "not") {
|
|
18362
|
+
present2(context, condition.operand, facts);
|
|
18142
18363
|
}
|
|
18143
18364
|
return facts;
|
|
18144
18365
|
}
|
|
@@ -18174,6 +18395,7 @@ function checkNumericFor(context, statement) {
|
|
|
18174
18395
|
context.report("check-invalid-operand", `Numeric "for" expects "number" but received "${typeToString(type)}".`, bound.position);
|
|
18175
18396
|
}
|
|
18176
18397
|
}
|
|
18398
|
+
forgetAssignedPaths(context, statement.body);
|
|
18177
18399
|
context.binder.pushScope();
|
|
18178
18400
|
context.binder.declare({ name: statement.variable.name, type: NUMBER_TYPE, isLocal: true, position: statement.variable.position, origin: "local" });
|
|
18179
18401
|
checkStatements(context, statement.body);
|
|
@@ -18197,6 +18419,7 @@ function iteratedTypes(context, iterators) {
|
|
|
18197
18419
|
function checkGenericFor(context, statement) {
|
|
18198
18420
|
statement.iterators.forEach((iterator) => checkExpression(context, iterator));
|
|
18199
18421
|
const iterated = iteratedTypes(context, statement.iterators);
|
|
18422
|
+
forgetAssignedPaths(context, statement.body);
|
|
18200
18423
|
context.binder.pushScope();
|
|
18201
18424
|
statement.variables.forEach((variable, index) => {
|
|
18202
18425
|
const inferred = iterated[index] ?? ANY_TYPE;
|
|
@@ -18269,6 +18492,7 @@ function buildFunctionType(context, parameters, returnAnnotation, contextual = n
|
|
|
18269
18492
|
return createFunction(types, context.resolveAnnotation(returnAnnotation), minimumArguments(context, parameters), isVariadic);
|
|
18270
18493
|
}
|
|
18271
18494
|
function checkFunctionBody(context, parameters, returnAnnotation, body, signature, selfType) {
|
|
18495
|
+
forgetAssignedPaths(context, body);
|
|
18272
18496
|
context.binder.pushScope();
|
|
18273
18497
|
context.pushReturnType(returnAnnotation === null ? null : context.resolveAnnotation(returnAnnotation));
|
|
18274
18498
|
if (selfType !== null) {
|
|
@@ -18327,6 +18551,10 @@ function checkCompoundOperand(context, operator, type, position2) {
|
|
|
18327
18551
|
function checkAssignment(context, statement) {
|
|
18328
18552
|
const valueTypes = checkValueList(context, statement.values);
|
|
18329
18553
|
statement.targets.forEach((target, index) => {
|
|
18554
|
+
const assigned = assignedPath(target);
|
|
18555
|
+
if (assigned !== null) {
|
|
18556
|
+
context.forgetNarrowing(assigned);
|
|
18557
|
+
}
|
|
18330
18558
|
const targetType = checkExpression(context, target);
|
|
18331
18559
|
const valueType = valueTypes[index] ?? NIL_TYPE;
|
|
18332
18560
|
const value = valueAt(statement.values, valueTypes, index);
|
|
@@ -18355,9 +18583,6 @@ function checkAssignment(context, statement) {
|
|
|
18355
18583
|
if (value !== void 0) {
|
|
18356
18584
|
context.expectAssignable(valueType, declared, value.position, "Assignment");
|
|
18357
18585
|
}
|
|
18358
|
-
if (target.kind === "identifier") {
|
|
18359
|
-
context.forgetNarrowing(target.name);
|
|
18360
|
-
}
|
|
18361
18586
|
});
|
|
18362
18587
|
}
|
|
18363
18588
|
function checkFunctionDeclaration(context, statement) {
|
|
@@ -18441,8 +18666,10 @@ function checkStatement(context, statement) {
|
|
|
18441
18666
|
return checkBlock(context, statement.body);
|
|
18442
18667
|
case "while-statement":
|
|
18443
18668
|
checkExpression(context, statement.condition);
|
|
18669
|
+
forgetAssignedPaths(context, statement.body);
|
|
18444
18670
|
return checkBlock(context, statement.body);
|
|
18445
18671
|
case "repeat-statement":
|
|
18672
|
+
forgetAssignedPaths(context, statement.body);
|
|
18446
18673
|
checkBlock(context, statement.body);
|
|
18447
18674
|
checkExpression(context, statement.condition);
|
|
18448
18675
|
return;
|
|
@@ -18501,20 +18728,12 @@ function parseInterpolation(segment) {
|
|
|
18501
18728
|
function collectInterpolations(segments) {
|
|
18502
18729
|
return segments.filter((segment) => segment.kind === "interpolation").map(parseInterpolation);
|
|
18503
18730
|
}
|
|
18504
|
-
function collectTemplateRoots(segments) {
|
|
18505
|
-
const roots = [];
|
|
18506
|
-
for (const interpolation of collectInterpolations(segments)) {
|
|
18507
|
-
if (interpolation.root.length > 0 && !roots.includes(interpolation.root)) {
|
|
18508
|
-
roots.push(interpolation.root);
|
|
18509
|
-
}
|
|
18510
|
-
}
|
|
18511
|
-
return roots;
|
|
18512
|
-
}
|
|
18513
18731
|
function templateLiteralText(segments) {
|
|
18514
18732
|
return segments.map((segment) => segment.kind === "text" ? segment.value : `\${${segment.value}}`).join("");
|
|
18515
18733
|
}
|
|
18516
18734
|
|
|
18517
18735
|
// ../compiler/src/checker/expressions.ts
|
|
18736
|
+
var NAME_PATH_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*$/;
|
|
18518
18737
|
var EXTENSION_RESULTS = {
|
|
18519
18738
|
boolean: BOOLEAN_TYPE,
|
|
18520
18739
|
number: NUMBER_TYPE,
|
|
@@ -18528,7 +18747,20 @@ function isNativeConstruction(context, expression) {
|
|
|
18528
18747
|
}
|
|
18529
18748
|
return nativeConstructor(context, object.name) !== null;
|
|
18530
18749
|
}
|
|
18750
|
+
function narrowedMember(context, expression) {
|
|
18751
|
+
const path = pathOf2(expression);
|
|
18752
|
+
return path === null ? null : context.narrowedType(path);
|
|
18753
|
+
}
|
|
18531
18754
|
function checkMember(context, expression) {
|
|
18755
|
+
const narrowed = narrowedMember(context, expression);
|
|
18756
|
+
if (narrowed !== null) {
|
|
18757
|
+
checkExpression(context, expression.object);
|
|
18758
|
+
return context.record(expression, narrowed);
|
|
18759
|
+
}
|
|
18760
|
+
if (expression.object.kind === "identifier" && isUserClassReference(context, expression.object.name)) {
|
|
18761
|
+
context.references.add(expression.object.name);
|
|
18762
|
+
return context.record(expression, resolveStaticMember(context, expression.object.name, expression));
|
|
18763
|
+
}
|
|
18532
18764
|
if (expression.object.kind === "identifier" && isMtaClassReference(context, expression.object.name)) {
|
|
18533
18765
|
context.references.add(expression.object.name);
|
|
18534
18766
|
return context.record(expression, resolveMtaStaticMember(context, expression.object.name, expression.property, expression.position)?.type ?? ANY_TYPE);
|
|
@@ -18652,6 +18884,13 @@ function checkCall(context, expression) {
|
|
|
18652
18884
|
}
|
|
18653
18885
|
return context.record(expression, checkSignature(context, expression.args, constructor, expression.position));
|
|
18654
18886
|
}
|
|
18887
|
+
if (expression.method !== null && expression.callee.kind === "identifier" && isUserClassReference(context, expression.callee.name)) {
|
|
18888
|
+
const name = expression.callee.name;
|
|
18889
|
+
const message = `Call the static member "${expression.method}" as "${name}.${expression.method}(...)". A class value has no "self" to pass.`;
|
|
18890
|
+
context.report("check-static-receiver", message, expression.position);
|
|
18891
|
+
checkValueList(context, expression.args);
|
|
18892
|
+
return context.record(expression, ANY_TYPE);
|
|
18893
|
+
}
|
|
18655
18894
|
if (expression.method === null) {
|
|
18656
18895
|
context.calledMembers.add(expression.callee);
|
|
18657
18896
|
}
|
|
@@ -18691,13 +18930,18 @@ function checkTable(context, expression) {
|
|
|
18691
18930
|
}
|
|
18692
18931
|
function checkTemplate(context, expression) {
|
|
18693
18932
|
for (const interpolation of collectInterpolations(expression.segments)) {
|
|
18694
|
-
if (interpolation.
|
|
18933
|
+
if (interpolation.path.length === 0) {
|
|
18695
18934
|
const message = 'Template interpolation is empty. Write "${name}", "${object.field}", or "${name:fallback}".';
|
|
18696
18935
|
context.report("check-empty-interpolation", message, interpolation.position);
|
|
18697
18936
|
continue;
|
|
18698
18937
|
}
|
|
18699
|
-
if (
|
|
18700
|
-
const message = `Template interpolation "${interpolation.path}"
|
|
18938
|
+
if (!NAME_PATH_PATTERN.test(interpolation.path)) {
|
|
18939
|
+
const message = `Template interpolation "${interpolation.path}" is not a name or a member path. Compute the value first, then interpolate the name.`;
|
|
18940
|
+
context.report("check-unknown-template-root", message, interpolation.position);
|
|
18941
|
+
continue;
|
|
18942
|
+
}
|
|
18943
|
+
if (interpolation.fallback === null && context.binder.lookup(interpolation.root) === null) {
|
|
18944
|
+
const message = `Template interpolation "${interpolation.path}" refers to "${interpolation.root}", which is not in scope. Write "\${${interpolation.path}:fallback}" to accept a value that may be missing.`;
|
|
18701
18945
|
context.report("check-unknown-template-root", message, interpolation.position);
|
|
18702
18946
|
}
|
|
18703
18947
|
}
|
|
@@ -18803,6 +19047,26 @@ function syntheticMethodType(context, member, fieldTypes) {
|
|
|
18803
19047
|
}
|
|
18804
19048
|
return buildFunctionType(context, member.parameters, member.returnAnnotation);
|
|
18805
19049
|
}
|
|
19050
|
+
function checkMemberSpaces(context, info, statement) {
|
|
19051
|
+
for (const member of statement.members) {
|
|
19052
|
+
if (member.isStatic && info.members.has(member.name)) {
|
|
19053
|
+
context.report("check-duplicate-class-member", `Class "${info.name}" declares "${member.name}" as both a static and an instance member.`, member.position);
|
|
19054
|
+
}
|
|
19055
|
+
if (!member.isStatic || info.superClass === null) {
|
|
19056
|
+
continue;
|
|
19057
|
+
}
|
|
19058
|
+
const inherited = context.declarations.lookupStaticMember(info.superClass, member.name);
|
|
19059
|
+
const declared = info.statics.get(member.name);
|
|
19060
|
+
if (inherited === void 0 || inherited === null || declared === void 0) {
|
|
19061
|
+
continue;
|
|
19062
|
+
}
|
|
19063
|
+
const options = { allowNil: context.allowNil };
|
|
19064
|
+
if (!isAssignable(declared.type, inherited.type, options) || !isAssignable(inherited.type, declared.type, options)) {
|
|
19065
|
+
const message = `Static member "${member.name}" must match "${typeToString(inherited.type)}" declared by class "${info.superClass}".`;
|
|
19066
|
+
context.report("check-invalid-override", message, member.position);
|
|
19067
|
+
}
|
|
19068
|
+
}
|
|
19069
|
+
}
|
|
18806
19070
|
function registerMembers(context, info, statement) {
|
|
18807
19071
|
const fieldTypes = /* @__PURE__ */ new Map();
|
|
18808
19072
|
for (const member of statement.members) {
|
|
@@ -18815,7 +19079,8 @@ function registerMembers(context, info, statement) {
|
|
|
18815
19079
|
for (const member of [...statement.members, ...generated]) {
|
|
18816
19080
|
const type = member.kind === "class-field" ? fieldTypes.get(member) ?? ANY_TYPE : member.isSynthetic ? syntheticMethodType(context, member, fieldTypes) : buildFunctionType(context, member.parameters, member.returnAnnotation);
|
|
18817
19081
|
const decorators = member.decorators.map((decorator) => decorator.name);
|
|
18818
|
-
info.members
|
|
19082
|
+
const space = member.isStatic ? info.statics : info.members;
|
|
19083
|
+
space.set(member.name, {
|
|
18819
19084
|
name: member.name,
|
|
18820
19085
|
type,
|
|
18821
19086
|
isMethod: member.kind === "class-method",
|
|
@@ -18824,6 +19089,7 @@ function registerMembers(context, info, statement) {
|
|
|
18824
19089
|
deprecated: decorators.includes("Deprecated")
|
|
18825
19090
|
});
|
|
18826
19091
|
}
|
|
19092
|
+
checkMemberSpaces(context, info, statement);
|
|
18827
19093
|
return generated;
|
|
18828
19094
|
}
|
|
18829
19095
|
function declareBuilder(context, info, statement) {
|
|
@@ -18840,7 +19106,7 @@ function declareBuilder(context, info, statement) {
|
|
|
18840
19106
|
}
|
|
18841
19107
|
}
|
|
18842
19108
|
members.set("build", { name: "build", type: { kind: "function", parameters: [], minimumArguments: 0, isVariadic: false, returnType: createNamed(statement.name) }, isMethod: true, position: statement.position });
|
|
18843
|
-
context.declarations.declareClass({ name, superClass: null, interfaces: [], members, position: statement.position });
|
|
19109
|
+
context.declarations.declareClass({ name, superClass: null, interfaces: [], members, statics: /* @__PURE__ */ new Map(), position: statement.position });
|
|
18844
19110
|
context.declareModuleGlobal({ name, type: createNamed(name), isLocal: false, position: statement.position });
|
|
18845
19111
|
}
|
|
18846
19112
|
function checkMethodBody(context, info, member) {
|
|
@@ -18848,10 +19114,14 @@ function checkMethodBody(context, info, member) {
|
|
|
18848
19114
|
if (explicitSelf !== void 0) {
|
|
18849
19115
|
context.report("check-explicit-self-parameter", 'Class methods receive "self" automatically; remove it from the parameter list.', explicitSelf.position);
|
|
18850
19116
|
}
|
|
18851
|
-
const signature = info.members.get(member.name)?.type;
|
|
19117
|
+
const signature = (member.isStatic ? info.statics : info.members).get(member.name)?.type;
|
|
18852
19118
|
if (signature?.kind !== "function") {
|
|
18853
19119
|
return;
|
|
18854
19120
|
}
|
|
19121
|
+
if (member.isStatic) {
|
|
19122
|
+
checkFunctionBody(context, member.parameters, member.returnAnnotation, member.body, signature, null);
|
|
19123
|
+
return;
|
|
19124
|
+
}
|
|
18855
19125
|
context.pushClassMethod({ className: info.name, methodName: member.name });
|
|
18856
19126
|
checkFunctionBody(context, member.parameters, member.returnAnnotation, member.body, signature, createNamed(info.name));
|
|
18857
19127
|
context.popClassMethod();
|
|
@@ -18890,6 +19160,7 @@ function declareClassInfo(context, statement) {
|
|
|
18890
19160
|
superClass: null,
|
|
18891
19161
|
interfaces: statement.interfaces,
|
|
18892
19162
|
members: /* @__PURE__ */ new Map(),
|
|
19163
|
+
statics: /* @__PURE__ */ new Map(),
|
|
18893
19164
|
position: statement.position
|
|
18894
19165
|
};
|
|
18895
19166
|
context.declarations.declareClass(info);
|
|
@@ -19089,6 +19360,7 @@ function check(program2, mode, environment = DEFAULT_ENVIRONMENT, options = {})
|
|
|
19089
19360
|
diagnostics: sortDiagnostics([...structure, ...directives.diagnostics, ...context.diagnostics]),
|
|
19090
19361
|
types: context.types,
|
|
19091
19362
|
references: context.references,
|
|
19363
|
+
staticAccess: context.staticAccess,
|
|
19092
19364
|
declarations: context.declarations,
|
|
19093
19365
|
aliases: context.binder.resolvedAliases(),
|
|
19094
19366
|
declaredGlobals: context.declaredGlobals,
|
|
@@ -19205,8 +19477,8 @@ function finalizeEmission(code, markers, sourceLineOffset = 0) {
|
|
|
19205
19477
|
|
|
19206
19478
|
// ../compiler/src/emitter/state.ts
|
|
19207
19479
|
var INDENT2 = " ";
|
|
19208
|
-
function createEmitState(types, references, generatedMembers) {
|
|
19209
|
-
return { types, references, generatedMembers, helpers: /* @__PURE__ */ new Set(), indent: 0, markers: [], symbol: void 0, loopWrap: false };
|
|
19480
|
+
function createEmitState(types, references, generatedMembers, staticAccess = /* @__PURE__ */ new Set()) {
|
|
19481
|
+
return { types, references, staticAccess, generatedMembers, helpers: /* @__PURE__ */ new Set(), indent: 0, markers: [], symbol: void 0, loopWrap: false };
|
|
19210
19482
|
}
|
|
19211
19483
|
function requireHelper(state, helper) {
|
|
19212
19484
|
if (helper !== null) {
|
|
@@ -19238,16 +19510,86 @@ function withSymbol(state, symbol, action) {
|
|
|
19238
19510
|
}
|
|
19239
19511
|
|
|
19240
19512
|
// ../compiler/src/emitter/template.ts
|
|
19513
|
+
var SELF_PATH_PATTERN = /^self((?:\.[A-Za-z_][A-Za-z0-9_]*)+)$/;
|
|
19514
|
+
function flattenedName(path) {
|
|
19515
|
+
const fields = SELF_PATH_PATTERN.exec(path)?.[1] ?? null;
|
|
19516
|
+
if (fields === null) {
|
|
19517
|
+
return null;
|
|
19518
|
+
}
|
|
19519
|
+
const name = fields.slice(1).split(".").join("_");
|
|
19520
|
+
return LUA_KEYWORDS.has(name) ? null : name;
|
|
19521
|
+
}
|
|
19522
|
+
function collectFlattened(segments) {
|
|
19523
|
+
const interpolations = collectInterpolations(segments);
|
|
19524
|
+
const reserved = /* @__PURE__ */ new Set();
|
|
19525
|
+
const claims = /* @__PURE__ */ new Map();
|
|
19526
|
+
const conflicting = /* @__PURE__ */ new Set();
|
|
19527
|
+
for (const interpolation of interpolations) {
|
|
19528
|
+
const name = flattenedName(interpolation.path);
|
|
19529
|
+
if (name === null) {
|
|
19530
|
+
reserved.add(interpolation.root);
|
|
19531
|
+
continue;
|
|
19532
|
+
}
|
|
19533
|
+
const claimed = claims.get(name) ?? null;
|
|
19534
|
+
if (claimed !== null && claimed !== interpolation.path) {
|
|
19535
|
+
conflicting.add(name);
|
|
19536
|
+
continue;
|
|
19537
|
+
}
|
|
19538
|
+
claims.set(name, interpolation.path);
|
|
19539
|
+
}
|
|
19540
|
+
const flattened = /* @__PURE__ */ new Map();
|
|
19541
|
+
for (const interpolation of interpolations) {
|
|
19542
|
+
const name = flattenedName(interpolation.path);
|
|
19543
|
+
if (name !== null && !reserved.has(name) && !conflicting.has(name)) {
|
|
19544
|
+
flattened.set(interpolation.raw, name);
|
|
19545
|
+
}
|
|
19546
|
+
}
|
|
19547
|
+
return flattened;
|
|
19548
|
+
}
|
|
19549
|
+
function rewriteInterpolation(raw, name) {
|
|
19550
|
+
const separator = raw.indexOf(":");
|
|
19551
|
+
const key = separator === -1 ? raw : raw.slice(0, separator);
|
|
19552
|
+
const rest = separator === -1 ? "" : raw.slice(separator);
|
|
19553
|
+
const path = key.trim();
|
|
19554
|
+
const start = key.indexOf(path);
|
|
19555
|
+
return `${key.slice(0, start)}${name}${key.slice(start + path.length)}${rest}`;
|
|
19556
|
+
}
|
|
19557
|
+
function flattenedLiteral(segments, flattened) {
|
|
19558
|
+
if (flattened.size === 0) {
|
|
19559
|
+
return templateLiteralText(segments);
|
|
19560
|
+
}
|
|
19561
|
+
return segments.map((segment) => {
|
|
19562
|
+
if (segment.kind === "text") {
|
|
19563
|
+
return segment.value;
|
|
19564
|
+
}
|
|
19565
|
+
const name = flattened.get(segment.value) ?? null;
|
|
19566
|
+
return `\${${name === null ? segment.value : rewriteInterpolation(segment.value, name)}}`;
|
|
19567
|
+
}).join("");
|
|
19568
|
+
}
|
|
19569
|
+
function collectBindings(segments, flattened) {
|
|
19570
|
+
const bindings = [];
|
|
19571
|
+
const seen = /* @__PURE__ */ new Set();
|
|
19572
|
+
for (const interpolation of collectInterpolations(segments)) {
|
|
19573
|
+
const flatName = flattened.get(interpolation.raw) ?? null;
|
|
19574
|
+
const name = flatName ?? interpolation.root;
|
|
19575
|
+
if (name.length === 0 || seen.has(name)) {
|
|
19576
|
+
continue;
|
|
19577
|
+
}
|
|
19578
|
+
seen.add(name);
|
|
19579
|
+
bindings.push({ name, value: flatName === null ? name : interpolation.path });
|
|
19580
|
+
}
|
|
19581
|
+
return bindings;
|
|
19582
|
+
}
|
|
19241
19583
|
function lowerTemplate(segments) {
|
|
19242
|
-
const
|
|
19584
|
+
const flattened = collectFlattened(segments);
|
|
19243
19585
|
const isInterpolated = segments.some((segment) => segment.kind === "interpolation");
|
|
19244
|
-
return { literal:
|
|
19586
|
+
return { literal: flattenedLiteral(segments, flattened), bindings: collectBindings(segments, flattened), isInterpolated };
|
|
19245
19587
|
}
|
|
19246
|
-
function templateContext(
|
|
19247
|
-
if (
|
|
19588
|
+
function templateContext(bindings) {
|
|
19589
|
+
if (bindings.length === 0) {
|
|
19248
19590
|
return "{}";
|
|
19249
19591
|
}
|
|
19250
|
-
return `{ ${
|
|
19592
|
+
return `{ ${bindings.map((binding) => `${binding.name} = ${binding.value}`).join(", ")} }`;
|
|
19251
19593
|
}
|
|
19252
19594
|
|
|
19253
19595
|
// ../compiler/src/emitter/expressions.ts
|
|
@@ -19288,6 +19630,10 @@ function emitTable(state, expression) {
|
|
|
19288
19630
|
return `{ ${fields.join(", ")} }`;
|
|
19289
19631
|
}
|
|
19290
19632
|
function emitMember(state, expression) {
|
|
19633
|
+
if (state.staticAccess.has(expression) && expression.object.kind === "identifier") {
|
|
19634
|
+
requireHelper(state, "class");
|
|
19635
|
+
return `getClass(${emitString(expression.object.name)}).${expression.property}`;
|
|
19636
|
+
}
|
|
19291
19637
|
const extension = resolvePropertyExtension(typeOf(state, expression.object), expression.property);
|
|
19292
19638
|
const object = emitExpression(state, expression.object, UNARY_PRECEDENCE);
|
|
19293
19639
|
if (extension === null) {
|
|
@@ -19320,7 +19666,7 @@ function emitTemplate(state, segments) {
|
|
|
19320
19666
|
return emitString(lowered.literal);
|
|
19321
19667
|
}
|
|
19322
19668
|
requireHelper(state, "string");
|
|
19323
|
-
return `string.template(${emitString(lowered.literal)}, ${templateContext(lowered.
|
|
19669
|
+
return `string.template(${emitString(lowered.literal)}, ${templateContext(lowered.bindings)})`;
|
|
19324
19670
|
}
|
|
19325
19671
|
function emitBinary(state, expression, limit) {
|
|
19326
19672
|
const precedence = binaryPrecedence(expression.operator);
|
|
@@ -19382,7 +19728,8 @@ function emitMethod(state, className, member) {
|
|
|
19382
19728
|
if (member.generated !== void 0) {
|
|
19383
19729
|
return emitGeneratedMethod(state, className, member);
|
|
19384
19730
|
}
|
|
19385
|
-
|
|
19731
|
+
const parameters = member.isStatic ? member.parameters : [self, ...member.parameters];
|
|
19732
|
+
return withSymbol(state, `${className}${member.isStatic ? "." : ":"}${member.name}`, () => emitFunctionBody(state, parameters, member.body, `${member.name} = function`));
|
|
19386
19733
|
}
|
|
19387
19734
|
function emitGeneratedMethod(state, className, member) {
|
|
19388
19735
|
const fields = member.generated?.fields ?? [];
|
|
@@ -19454,7 +19801,7 @@ function emitMembers(state, statement) {
|
|
|
19454
19801
|
state.indent += 1;
|
|
19455
19802
|
for (const member of statement.members) {
|
|
19456
19803
|
if (member.kind === "class-method") {
|
|
19457
|
-
entries2.push(indentLine(state, `${markSource(state, member.position.line, `${statement.name}
|
|
19804
|
+
entries2.push(indentLine(state, `${markSource(state, member.position.line, `${statement.name}${member.isStatic ? "." : ":"}${member.name}`)}${emitMethod(state, statement.name, member)}`));
|
|
19458
19805
|
continue;
|
|
19459
19806
|
}
|
|
19460
19807
|
if (member.decorators.some((decorator) => decorator.name === "Lazy")) {
|
|
@@ -19696,8 +20043,8 @@ function emitBlock(state, statements) {
|
|
|
19696
20043
|
}
|
|
19697
20044
|
return lines;
|
|
19698
20045
|
}
|
|
19699
|
-
function emit2(program2, types, references, generatedMembers = /* @__PURE__ */ new Map(), sourceLineOffset = 0) {
|
|
19700
|
-
const state = createEmitState(types, references, generatedMembers);
|
|
20046
|
+
function emit2(program2, types, references, generatedMembers = /* @__PURE__ */ new Map(), sourceLineOffset = 0, staticAccess = /* @__PURE__ */ new Set()) {
|
|
20047
|
+
const state = createEmitState(types, references, generatedMembers, staticAccess);
|
|
19701
20048
|
const lines = emitBlock(state, program2.body);
|
|
19702
20049
|
const markedCode = lines.length === 0 ? "" : `${lines.join("\n")}
|
|
19703
20050
|
`;
|
|
@@ -19949,18 +20296,18 @@ function erasedEdit(source, span) {
|
|
|
19949
20296
|
}
|
|
19950
20297
|
function canonicalEdit(input, statement, span) {
|
|
19951
20298
|
const { source } = input;
|
|
19952
|
-
const emitted = emit2({ ...input.program, body: [statement] }, input.types, input.references, input.generatedMembers, statement.position.line - 1);
|
|
20299
|
+
const emitted = emit2({ ...input.program, body: [statement] }, input.types, input.references, input.generatedMembers, statement.position.line - 1, input.staticAccess);
|
|
19953
20300
|
const trimmed = span.end < source.length && emitted.code.endsWith("\n") ? emitted.code.slice(0, -1) : emitted.code;
|
|
19954
20301
|
if (trimmed.length === 0) {
|
|
19955
20302
|
return erasedEdit(source, span);
|
|
19956
20303
|
}
|
|
19957
20304
|
const authored = source.slice(span.start, span.end);
|
|
19958
20305
|
const replacement = reindent(trimmed, indentOf(source, span.start));
|
|
19959
|
-
const
|
|
19960
|
-
if (
|
|
20306
|
+
const missing2 = lineCount2(authored) - lineCount2(replacement);
|
|
20307
|
+
if (missing2 < 0 && input.development) {
|
|
19961
20308
|
return null;
|
|
19962
20309
|
}
|
|
19963
|
-
const padded =
|
|
20310
|
+
const padded = missing2 > 0 && source.slice(span.end).trim().length > 0 ? `${replacement}${"\n".repeat(missing2)}` : replacement;
|
|
19964
20311
|
return { start: span.start, end: span.end, replacement: padded, lines: emitted.lines };
|
|
19965
20312
|
}
|
|
19966
20313
|
|
|
@@ -19984,15 +20331,16 @@ function builderClassText(input, statement) {
|
|
|
19984
20331
|
}
|
|
19985
20332
|
|
|
19986
20333
|
// ../compiler/src/emitter/preserve-guards.ts
|
|
19987
|
-
|
|
20334
|
+
var NO_STATIC_ACCESS = /* @__PURE__ */ new Set();
|
|
20335
|
+
function isPreservableExpression(expression, types, statics = NO_STATIC_ACCESS) {
|
|
19988
20336
|
switch (expression.kind) {
|
|
19989
20337
|
case "template-literal":
|
|
19990
20338
|
case "new-expression":
|
|
19991
20339
|
return false;
|
|
19992
20340
|
case "member-expression":
|
|
19993
|
-
return resolvePropertyExtension(types.get(expression.object) ?? null, expression.property) === null && isPreservableExpression(expression.object, types);
|
|
20341
|
+
return !statics.has(expression) && resolvePropertyExtension(types.get(expression.object) ?? null, expression.property) === null && isPreservableExpression(expression.object, types, statics);
|
|
19994
20342
|
case "index-expression":
|
|
19995
|
-
return isPreservableExpression(expression.object, types) && isPreservableExpression(expression.index, types);
|
|
20343
|
+
return isPreservableExpression(expression.object, types, statics) && isPreservableExpression(expression.index, types, statics);
|
|
19996
20344
|
case "call-expression":
|
|
19997
20345
|
if (expression.method === null && expression.callee.kind === "identifier" && expression.callee.name === "super") {
|
|
19998
20346
|
return false;
|
|
@@ -20000,43 +20348,43 @@ function isPreservableExpression(expression, types) {
|
|
|
20000
20348
|
if (expression.callee.kind === "member-expression" && resolveCallExtension(types.get(expression.callee.object) ?? null, expression.callee.property) !== null) {
|
|
20001
20349
|
return false;
|
|
20002
20350
|
}
|
|
20003
|
-
return isPreservableExpression(expression.callee, types) && expression.args.every((argument) => isPreservableExpression(argument, types));
|
|
20351
|
+
return isPreservableExpression(expression.callee, types, statics) && expression.args.every((argument) => isPreservableExpression(argument, types, statics));
|
|
20004
20352
|
case "table-expression":
|
|
20005
20353
|
return expression.fields.every(
|
|
20006
|
-
(field2) => (field2.key === null || isPreservableExpression(field2.key, types)) && isPreservableExpression(field2.value, types)
|
|
20354
|
+
(field2) => (field2.key === null || isPreservableExpression(field2.key, types, statics)) && isPreservableExpression(field2.value, types, statics)
|
|
20007
20355
|
);
|
|
20008
20356
|
case "binary-expression":
|
|
20009
|
-
return isPreservableExpression(expression.left, types) && isPreservableExpression(expression.right, types);
|
|
20357
|
+
return isPreservableExpression(expression.left, types, statics) && isPreservableExpression(expression.right, types, statics);
|
|
20010
20358
|
case "unary-expression":
|
|
20011
|
-
return isPreservableExpression(expression.operand, types);
|
|
20359
|
+
return isPreservableExpression(expression.operand, types, statics);
|
|
20012
20360
|
case "group-expression":
|
|
20013
|
-
return isPreservableExpression(expression.expression, types);
|
|
20361
|
+
return isPreservableExpression(expression.expression, types, statics);
|
|
20014
20362
|
default:
|
|
20015
20363
|
return true;
|
|
20016
20364
|
}
|
|
20017
20365
|
}
|
|
20018
|
-
function every(expressions, types) {
|
|
20019
|
-
return expressions.every((expression) => isPreservableExpression(expression, types));
|
|
20366
|
+
function every(expressions, types, statics) {
|
|
20367
|
+
return expressions.every((expression) => isPreservableExpression(expression, types, statics));
|
|
20020
20368
|
}
|
|
20021
|
-
function isPreservableStatement(statement, types) {
|
|
20369
|
+
function isPreservableStatement(statement, types, statics = NO_STATIC_ACCESS) {
|
|
20022
20370
|
switch (statement.kind) {
|
|
20023
20371
|
case "local-statement":
|
|
20024
|
-
return every(statement.values, types);
|
|
20372
|
+
return every(statement.values, types, statics);
|
|
20025
20373
|
case "assignment-statement":
|
|
20026
|
-
return statement.operator === "=" && every(statement.targets, types) && every(statement.values, types);
|
|
20374
|
+
return statement.operator === "=" && every(statement.targets, types, statics) && every(statement.values, types, statics);
|
|
20027
20375
|
case "call-statement":
|
|
20028
|
-
return isPreservableExpression(statement.expression, types);
|
|
20376
|
+
return isPreservableExpression(statement.expression, types, statics);
|
|
20029
20377
|
case "return-statement":
|
|
20030
|
-
return every(statement.values, types);
|
|
20378
|
+
return every(statement.values, types, statics);
|
|
20031
20379
|
case "while-statement":
|
|
20032
20380
|
case "repeat-statement":
|
|
20033
|
-
return isPreservableExpression(statement.condition, types);
|
|
20381
|
+
return isPreservableExpression(statement.condition, types, statics);
|
|
20034
20382
|
case "if-statement":
|
|
20035
|
-
return statement.clauses.every((clause) => isPreservableExpression(clause.condition, types));
|
|
20383
|
+
return statement.clauses.every((clause) => isPreservableExpression(clause.condition, types, statics));
|
|
20036
20384
|
case "numeric-for-statement":
|
|
20037
|
-
return isPreservableExpression(statement.start, types) && isPreservableExpression(statement.limit, types) && (statement.step === null || isPreservableExpression(statement.step, types));
|
|
20385
|
+
return isPreservableExpression(statement.start, types, statics) && isPreservableExpression(statement.limit, types, statics) && (statement.step === null || isPreservableExpression(statement.step, types, statics));
|
|
20038
20386
|
case "generic-for-statement":
|
|
20039
|
-
return every(statement.iterators, types);
|
|
20387
|
+
return every(statement.iterators, types, statics);
|
|
20040
20388
|
case "break-statement":
|
|
20041
20389
|
case "declare-statement":
|
|
20042
20390
|
case "do-statement":
|
|
@@ -20164,7 +20512,7 @@ function classEdits(input, statement, spans) {
|
|
|
20164
20512
|
edits.push({ start: span.start, end, replacement: isLazyField(member) ? longComment(text) : blankSpan(text) });
|
|
20165
20513
|
continue;
|
|
20166
20514
|
}
|
|
20167
|
-
if (member.kind === "class-method") {
|
|
20515
|
+
if (member.kind === "class-method" && !member.isStatic) {
|
|
20168
20516
|
const self = selfEdit(source, member, span);
|
|
20169
20517
|
if (self === null) {
|
|
20170
20518
|
return null;
|
|
@@ -20278,7 +20626,7 @@ function surgery(collector, statement) {
|
|
|
20278
20626
|
const edits2 = classEdits(input, statement, { span, members: input.spans });
|
|
20279
20627
|
return edits2 === null ? null : { edits: edits2, wrapsBody: false };
|
|
20280
20628
|
}
|
|
20281
|
-
if (loopBody(statement) === null || !isPreservableStatement(statement, input.types)) {
|
|
20629
|
+
if (loopBody(statement) === null || !isPreservableStatement(statement, input.types, input.staticAccess)) {
|
|
20282
20630
|
return null;
|
|
20283
20631
|
}
|
|
20284
20632
|
const edits = loopEdits(input, statement);
|
|
@@ -20307,7 +20655,7 @@ function visit(collector, statement, wrapped) {
|
|
|
20307
20655
|
descend(collector, statement, false, surgical.wrapsBody);
|
|
20308
20656
|
return;
|
|
20309
20657
|
}
|
|
20310
|
-
if (isPreservableStatement(statement, collector.input.types) && keepsScaffolding(statement)) {
|
|
20658
|
+
if (isPreservableStatement(statement, collector.input.types, collector.input.staticAccess) && keepsScaffolding(statement)) {
|
|
20311
20659
|
const inherited = statement.kind === "do-statement" || statement.kind === "if-statement" ? wrapped : false;
|
|
20312
20660
|
descend(collector, statement, inherited, false);
|
|
20313
20661
|
return;
|
|
@@ -20460,7 +20808,7 @@ function compile(source, options = {}) {
|
|
|
20460
20808
|
return { ...shared, code: null, requiredHelpers: [], lines: [] };
|
|
20461
20809
|
}
|
|
20462
20810
|
const references = reachedNames(checked.references, options.projectReferences);
|
|
20463
|
-
const emitted = emit2(parsed.program, checked.types, references, checked.generatedMembers);
|
|
20811
|
+
const emitted = emit2(parsed.program, checked.types, references, checked.generatedMembers, 0, checked.staticAccess);
|
|
20464
20812
|
const preserved = emitPreservingSource({
|
|
20465
20813
|
source,
|
|
20466
20814
|
program: parsed.program,
|
|
@@ -20470,6 +20818,7 @@ function compile(source, options = {}) {
|
|
|
20470
20818
|
types: checked.types,
|
|
20471
20819
|
references,
|
|
20472
20820
|
generatedMembers: checked.generatedMembers,
|
|
20821
|
+
staticAccess: checked.staticAccess,
|
|
20473
20822
|
development: options.development === true
|
|
20474
20823
|
});
|
|
20475
20824
|
const required = new Set(emitted.requiredHelpers);
|