@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/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.18.2" : "0.0.0-dev";
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("Element"), 1),
8459
- playSound3D: fn([STRING, NUMBER, NUMBER, NUMBER, BOOLEAN, BOOLEAN], named("Element"), 4),
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("Element"), 3),
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("Element"), 1),
8615
- dxCreateRenderTarget: fn([NUMBER, NUMBER, BOOLEAN], named("Element"), 2),
8616
- dxCreateScreenSource: fn([NUMBER, NUMBER], named("Element"), 2),
8617
- dxCreateShader: fn([STRING, NUMBER, NUMBER, BOOLEAN, STRING], tupleOf([named("Element"), STRING]), 1),
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("Element"), 5),
9236
- guiCreateCheckBox: fn([NUMBER, NUMBER, NUMBER, NUMBER, STRING, BOOLEAN, BOOLEAN, named("GuiElement")], named("Element"), 6),
9237
- guiCreateComboBox: fn([NUMBER, NUMBER, NUMBER, NUMBER, STRING, BOOLEAN, named("GuiElement")], named("Element"), 5),
9238
- guiCreateEdit: fn([NUMBER, NUMBER, NUMBER, NUMBER, STRING, BOOLEAN, named("GuiElement")], named("Element"), 5),
9239
- guiCreateFont: fn([STRING, NUMBER], named("Element"), 1),
9240
- guiCreateGridList: fn([NUMBER, NUMBER, NUMBER, NUMBER, BOOLEAN, named("GuiElement")], named("Element"), 4),
9241
- guiCreateLabel: fn([NUMBER, NUMBER, NUMBER, NUMBER, STRING, BOOLEAN, named("GuiElement")], named("Element"), 5),
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("Element"), 5),
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("Element"), 5),
9248
- guiCreateTab: fn([STRING, named("GuiElement")], named("Element"), 2),
9249
- guiCreateTabPanel: fn([NUMBER, NUMBER, NUMBER, NUMBER, BOOLEAN, named("GuiElement")], named("Element"), 4),
9250
- guiCreateWindow: fn([NUMBER, NUMBER, NUMBER, NUMBER, STRING, BOOLEAN], named("Element"), 5),
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
- null,
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
- null,
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
- null,
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
- null,
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
- null,
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
- null,
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
- null,
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
- null,
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
- null,
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
- null,
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 missing = [];
13344
+ const missing2 = [];
13300
13345
  for (const [name, member] of target.members) {
13301
13346
  if (member.kind !== "optional" && !source.members.has(name)) {
13302
- missing.push(`"${name}"`);
13347
+ missing2.push(`"${name}"`);
13303
13348
  }
13304
13349
  }
13305
- return missing;
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 missing = missingKeys(source, candidate);
13318
- if (missing.length === 0) {
13362
+ const missing2 = missingKeys(source, candidate);
13363
+ if (missing2.length === 0) {
13319
13364
  return "";
13320
13365
  }
13321
- const label2 = missing.length === 1 ? `Key ${missing[0]} is` : `Keys ${missing.join(", ")} are`;
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(name) {
13513
+ forgetNarrowing(path) {
13465
13514
  for (const frame of this.narrowings) {
13466
- frame.delete(name);
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(name) {
13522
+ narrowedType(path) {
13470
13523
  for (let index = this.narrowings.length - 1; index >= 0; index -= 1) {
13471
- const found = this.narrowings[index]?.get(name);
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
- isPredeclaredClass(name) {
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 true;
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 false;
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: null },
17595
- { name: "DxRenderTarget", parent: null },
17596
- { name: "DxScreenSource", parent: null },
17597
- { name: "DxShader", parent: null },
17598
- { name: "DxTexture", parent: null },
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: null },
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: null },
17612
- { name: "GuiFont", parent: null },
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: null },
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: null },
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
- if (context.isPredeclaredClass(expression.className) && !context.insideFunction()) {
17825
- const message = `Class "${expression.className}" is declared further down this file, so it does not exist yet at this point.`;
17826
- context.report("check-class-before-declaration", message, expression.position);
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 missing = [];
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
- missing.push(`"${typeToString(option)}"`);
18157
+ missing2.push(`"${typeToString(option)}"`);
17942
18158
  } else {
17943
18159
  resolved2.push(member);
17944
18160
  }
17945
18161
  }
17946
- if (missing.length === 0) {
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 ${missing.join(", ")}.`;
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" || left.object.kind !== "identifier") {
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 : { name: left.object.name, property: left.property, value };
18186
+ return path === null || value === null ? null : { path, subject: left.object, property: left.property, value };
17970
18187
  }
17971
- function subjectType(context, name) {
17972
- const type = context.narrowedType(name) ?? context.binder.lookup(name)?.type ?? null;
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.name);
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.name, narrowed];
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 declaredType(context, name) {
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 !== void 0 && argument.kind === "identifier" ? argument.name : null;
18235
+ return argument === void 0 ? null : pathOf2(argument);
18022
18236
  }
18023
18237
  function guardFact(left, right) {
18024
- const name = guardedName(left);
18238
+ const path = guardedPath(left);
18025
18239
  const value = right.kind === "string-literal" ? GUARD_TYPES[right.value] : void 0;
18026
- return name === null || value === void 0 ? null : [name, value];
18240
+ return path === null || value === void 0 ? null : [path, value];
18027
18241
  }
18028
18242
  function nilComparison(left, right) {
18029
- if (left.kind === "identifier" && right.kind === "nil-literal") {
18030
- return left.name;
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 present2(context, name, facts) {
18035
- const declared = declaredType(context, name);
18036
- if (declared !== null) {
18037
- facts.set(name, withoutNil(declared));
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 [name, type] of left) {
18042
- const other = right.get(name);
18262
+ for (const [path, type] of left) {
18263
+ const other = right.get(path);
18043
18264
  if (other !== void 0) {
18044
- facts.set(name, createUnion([type, other]));
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.name, facts);
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 missing = nilComparison(expression.left, expression.right);
18298
+ const absent = nilComparison(expression.left, expression.right);
18078
18299
  if (guard !== null) {
18079
18300
  facts.set(guard[0], guard[1]);
18080
- } else if (missing !== null) {
18081
- facts.set(missing, NIL_TYPE);
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 name = nilComparison(expression.left, expression.right);
18089
- if (name !== null) {
18090
- present2(context, name, facts);
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 [name, type] of [...negatedFacts(context, condition.left), ...negatedFacts(context, condition.right)]) {
18125
- facts.set(name, type);
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 name = nilComparison(condition.left, condition.right);
18131
- if (name !== null) {
18132
- present2(context, name, facts);
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" && condition.operand.kind === "identifier") {
18141
- present2(context, condition.operand.name, facts);
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.root.length === 0) {
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 (context.binder.lookup(interpolation.root) === null) {
18700
- const message = `Template interpolation "${interpolation.path}" refers to "${interpolation.root}", which is not in scope.`;
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.set(member.name, {
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 roots = collectTemplateRoots(segments);
19584
+ const flattened = collectFlattened(segments);
19243
19585
  const isInterpolated = segments.some((segment) => segment.kind === "interpolation");
19244
- return { literal: templateLiteralText(segments), roots, isInterpolated };
19586
+ return { literal: flattenedLiteral(segments, flattened), bindings: collectBindings(segments, flattened), isInterpolated };
19245
19587
  }
19246
- function templateContext(roots) {
19247
- if (roots.length === 0) {
19588
+ function templateContext(bindings) {
19589
+ if (bindings.length === 0) {
19248
19590
  return "{}";
19249
19591
  }
19250
- return `{ ${roots.map((root) => `${root} = ${root}`).join(", ")} }`;
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.roots)})`;
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
- return withSymbol(state, `${className}:${member.name}`, () => emitFunctionBody(state, [self, ...member.parameters], member.body, `${member.name} = function`));
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}:${member.name}`)}${emitMethod(state, statement.name, member)}`));
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 missing = lineCount2(authored) - lineCount2(replacement);
19960
- if (missing < 0 && input.development) {
20306
+ const missing2 = lineCount2(authored) - lineCount2(replacement);
20307
+ if (missing2 < 0 && input.development) {
19961
20308
  return null;
19962
20309
  }
19963
- const padded = missing > 0 && source.slice(span.end).trim().length > 0 ? `${replacement}${"\n".repeat(missing)}` : replacement;
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
- function isPreservableExpression(expression, types) {
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);