@neocompose/cli 0.27.0 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/neo.mjs CHANGED
@@ -1813,6 +1813,9 @@ var init_generated_csharp_identifiers = __esm({
1813
1813
  });
1814
1814
 
1815
1815
  // ../packages/neoscript-language/src/project.ts
1816
+ function neoScriptParameterIsOmittable(parameter4) {
1817
+ return parameter4.defaultValue !== void 0;
1818
+ }
1816
1819
  function neoScriptRequiredConstructor(type) {
1817
1820
  return type?.declaredConstructors?.find(
1818
1821
  (candidate) => candidate.required === true
@@ -1820,7 +1823,7 @@ function neoScriptRequiredConstructor(type) {
1820
1823
  }
1821
1824
  function neoScriptParameterlessConstructor(type) {
1822
1825
  return type.declaredConstructors?.find(
1823
- (candidate) => candidate.parameters.length === 0
1826
+ (candidate) => candidate.parameters.every(neoScriptParameterIsOmittable)
1824
1827
  ) ?? null;
1825
1828
  }
1826
1829
  function isNeoScriptConstructionDocumentKind(kind) {
@@ -2357,11 +2360,11 @@ function signatureHelp(snapshot, position) {
2357
2360
  return {
2358
2361
  signatures: declared.map((candidate) => ({
2359
2362
  label: `${type.name}(${candidate.parameters.map(
2360
- (parameter4) => `${formatType(parameter4.type, snapshot.project)} ${parameter4.name}`
2363
+ (parameter4) => `${formatType(parameter4.type, snapshot.project)} ${parameter4.name}${parameterDefaultSuffix(parameter4)}`
2361
2364
  ).join(", ")})`,
2362
2365
  ...candidate.documentation ? { documentation: candidate.documentation } : {},
2363
2366
  parameters: candidate.parameters.map((parameter4) => ({
2364
- label: `${formatType(parameter4.type, snapshot.project)} ${parameter4.name}`,
2367
+ label: `${formatType(parameter4.type, snapshot.project)} ${parameter4.name}${parameterDefaultSuffix(parameter4)}`,
2365
2368
  ...parameter4.documentation ? { documentation: parameter4.documentation } : {}
2366
2369
  }))
2367
2370
  })),
@@ -2404,7 +2407,7 @@ function signatureHelp(snapshot, position) {
2404
2407
  label: formatSymbolSignature(symbol, snapshot.project),
2405
2408
  ...symbol.documentation ? { documentation: symbol.documentation } : {},
2406
2409
  parameters: symbol.parameters.map((parameter4) => ({
2407
- label: `${formatType(parameter4.type, snapshot.project)} ${parameter4.name}`,
2410
+ label: `${formatType(parameter4.type, snapshot.project)} ${parameter4.name}${parameterDefaultSuffix(parameter4)}`,
2408
2411
  ...parameter4.documentation ? { documentation: parameter4.documentation } : {}
2409
2412
  }))
2410
2413
  }
@@ -4140,9 +4143,14 @@ function displaySymbolKind(symbol) {
4140
4143
  }
4141
4144
  return symbol.kind.charAt(0).toUpperCase() + symbol.kind.slice(1);
4142
4145
  }
4146
+ function parameterDefaultSuffix(parameter4) {
4147
+ return parameter4.defaultValue === void 0 ? "" : ` = ${parameter4.defaultValue.displayText}`;
4148
+ }
4143
4149
  function formatSymbolSignature(symbol, project) {
4144
4150
  if (symbol.parameters !== void 0) {
4145
- const parameters = symbol.parameters.map((item) => `${formatType(item.type, project)} ${item.name}`).join(", ");
4151
+ const parameters = symbol.parameters.map(
4152
+ (item) => `${formatType(item.type, project)} ${item.name}${parameterDefaultSuffix(item)}`
4153
+ ).join(", ");
4146
4154
  const returnType = symbol.returnType ?? symbol.type;
4147
4155
  const deferred = symbol.deferred ? "Task<" : "";
4148
4156
  const end = symbol.deferred ? ">" : "";
@@ -7323,11 +7331,24 @@ var init_strict_parser = __esm({
7323
7331
  function neoScriptArgumentNameSetKey(names) {
7324
7332
  return [...names].map((name) => name.toLowerCase()).sort().join(",");
7325
7333
  }
7326
- function parameterNameSetKey(parameters) {
7327
- return neoScriptArgumentNameSetKey(
7328
- parameters.map((parameter4) => parameter4.name)
7334
+ function neoScriptCallMatchesParameters(suppliedNames, parameters) {
7335
+ const supplied = new Set(suppliedNames.map((name) => name.toLowerCase()));
7336
+ const declared = new Set(
7337
+ parameters.map((parameter4) => parameter4.name.toLowerCase())
7338
+ );
7339
+ for (const name of supplied) {
7340
+ if (!declared.has(name)) return false;
7341
+ }
7342
+ return parameters.every(
7343
+ (parameter4) => parameter4.defaulted || supplied.has(parameter4.name.toLowerCase())
7329
7344
  );
7330
7345
  }
7346
+ function callableShape(parameters) {
7347
+ return parameters.map((parameter4) => ({
7348
+ name: parameter4.name,
7349
+ defaulted: neoScriptParameterIsOmittable(parameter4)
7350
+ }));
7351
+ }
7331
7352
  function neoScriptPositionalTypeKey(type) {
7332
7353
  switch (type.kind) {
7333
7354
  case "primitive":
@@ -7385,8 +7406,108 @@ function validateNeoScriptOverloadSignatures(className, signatures) {
7385
7406
  message: `Class '${className}' declares constructors (${parameterLists.join(") and (")}) that differ only by parameter name; generated C# would emit the same constructor signature twice.`
7386
7407
  });
7387
7408
  }
7409
+ errors.push(...defaultedTieErrors(className, signatures));
7410
+ errors.push(...effectiveArityCollisionErrors(className, signatures));
7388
7411
  return errors;
7389
7412
  }
7413
+ function defaultedTieErrors(className, signatures) {
7414
+ const errors = [];
7415
+ for (let first = 0; first < signatures.length; first += 1) {
7416
+ for (let second = first + 1; second < signatures.length; second += 1) {
7417
+ const left = signatures[first];
7418
+ const right = signatures[second];
7419
+ if (left === void 0 || right === void 0) continue;
7420
+ if (namedSignatureKey(left) === namedSignatureKey(right)) continue;
7421
+ if (left.parameters.length !== right.parameters.length) continue;
7422
+ const leftHasDefault = left.parameters.some(
7423
+ (parameter4) => parameter4.defaulted === true
7424
+ );
7425
+ const rightHasDefault = right.parameters.some(
7426
+ (parameter4) => parameter4.defaulted === true
7427
+ );
7428
+ if (!leftHasDefault && !rightHasDefault) continue;
7429
+ const tyingCall = tyingCallNames(left, right);
7430
+ if (tyingCall === null) continue;
7431
+ const callDescription = tyingCall.length === 0 ? "`new()`" : `\`new(${tyingCall.join(": \u2026, ")}: \u2026)\``;
7432
+ errors.push({
7433
+ kind: "duplicateNameSet",
7434
+ constructorIds: [left.id, right.id],
7435
+ message: `Class '${className}' declares constructors (${describeSignatureParameters(left)}) and (${describeSignatureParameters(right)}) that the call ${callDescription} would match with the same number of defaulted fill-ins and the same argument types; no call site could resolve between them.`
7436
+ });
7437
+ }
7438
+ }
7439
+ return errors;
7440
+ }
7441
+ function tyingCallNames(left, right) {
7442
+ const leftTypes = new Map(
7443
+ left.parameters.map((parameter4) => [
7444
+ parameter4.name.toLowerCase(),
7445
+ parameter4.typeKey
7446
+ ])
7447
+ );
7448
+ const rightTypes = new Map(
7449
+ right.parameters.map((parameter4) => [
7450
+ parameter4.name.toLowerCase(),
7451
+ parameter4.typeKey
7452
+ ])
7453
+ );
7454
+ const tying = /* @__PURE__ */ new Map();
7455
+ for (const parameter4 of [...left.parameters, ...right.parameters]) {
7456
+ if (parameter4.defaulted === true) continue;
7457
+ tying.set(parameter4.name.toLowerCase(), parameter4.name);
7458
+ }
7459
+ for (const name of tying.keys()) {
7460
+ const leftType = leftTypes.get(name);
7461
+ const rightType = rightTypes.get(name);
7462
+ if (leftType === void 0) return null;
7463
+ if (rightType === void 0) return null;
7464
+ if (leftType !== rightType) return null;
7465
+ }
7466
+ return [...tying.values()];
7467
+ }
7468
+ function effectiveArityCollisionErrors(className, signatures) {
7469
+ const errors = [];
7470
+ const byEffectiveKey = /* @__PURE__ */ new Map();
7471
+ for (const signature of signatures) {
7472
+ const minimumArity = signature.parameters.filter(
7473
+ (parameter4) => parameter4.defaulted !== true
7474
+ ).length;
7475
+ for (let arity = minimumArity; arity <= signature.parameters.length; arity += 1) {
7476
+ const key = signature.parameters.slice(0, arity).map((parameter4) => parameter4.typeKey).join(",");
7477
+ byEffectiveKey.set(key, [
7478
+ ...byEffectiveKey.get(key) ?? [],
7479
+ { signature, arity }
7480
+ ]);
7481
+ }
7482
+ }
7483
+ const reportedPairs = /* @__PURE__ */ new Set();
7484
+ for (const entries of byEffectiveKey.values()) {
7485
+ if (entries.length < 2) continue;
7486
+ const shortened = entries.some(
7487
+ (entry) => entry.arity < entry.signature.parameters.length
7488
+ );
7489
+ if (!shortened) continue;
7490
+ const ids = entries.map((entry) => entry.signature.id);
7491
+ const pairKey = [...ids].sort().join("|");
7492
+ if (reportedPairs.has(pairKey)) continue;
7493
+ reportedPairs.add(pairKey);
7494
+ const parameterLists = entries.map(
7495
+ (entry) => describeSignatureParameters(entry.signature)
7496
+ );
7497
+ errors.push({
7498
+ kind: "positionalCollision",
7499
+ constructorIds: ids,
7500
+ message: `Class '${className}' declares constructors (${parameterLists.join(") and (")}) that expose the same C# positional signature once defaulted parameters are omitted; C# would resolve the shared arity differently from NeoScript's named overloads.`
7501
+ });
7502
+ }
7503
+ return errors;
7504
+ }
7505
+ function describeSignatureParameters(signature) {
7506
+ return signature.parameters.map((parameter4) => {
7507
+ const defaulted = parameter4.defaulted === true ? " = \u2026" : "";
7508
+ return `${parameter4.name}${defaulted}`;
7509
+ }).join(", ");
7510
+ }
7390
7511
  function namedSignatureKey(signature) {
7391
7512
  return [...signature.parameters].map((parameter4) => `${parameter4.name.toLowerCase()}:${parameter4.typeKey}`).sort().join(",");
7392
7513
  }
@@ -7397,23 +7518,35 @@ function validateNeoScriptDeclaredConstructorOverloads(className, constructors)
7397
7518
  id: constructor2.id,
7398
7519
  parameters: constructor2.parameters.map((parameter4) => ({
7399
7520
  name: parameter4.name,
7400
- typeKey: neoScriptPositionalTypeKey(parameter4.type)
7521
+ typeKey: neoScriptPositionalTypeKey(parameter4.type),
7522
+ defaulted: parameter4.defaultValue !== void 0
7401
7523
  }))
7402
7524
  }))
7403
7525
  );
7404
7526
  }
7405
7527
  function resolveNeoScriptDeclaredConstructorOverload(constructors, args) {
7406
- const callKey = neoScriptArgumentNameSetKey(args.map((entry) => entry.name));
7407
- const byName = constructors.filter(
7408
- (constructor2) => parameterNameSetKey(constructor2.parameters) === callKey
7528
+ const suppliedNames = args.map((entry) => entry.name);
7529
+ const applicable = constructors.filter(
7530
+ (constructor2) => neoScriptCallMatchesParameters(
7531
+ suppliedNames,
7532
+ callableShape(constructor2.parameters)
7533
+ )
7534
+ );
7535
+ if (applicable.length === 0) return { kind: "noMatch" };
7536
+ const fewestFillIns = Math.min(
7537
+ ...applicable.map(
7538
+ (constructor2) => constructor2.parameters.length - args.length
7539
+ )
7540
+ );
7541
+ const best = applicable.filter(
7542
+ (constructor2) => constructor2.parameters.length - args.length === fewestFillIns
7409
7543
  );
7410
- if (byName.length === 0) return { kind: "noMatch" };
7411
- if (byName.length === 1) {
7412
- const only = byName[0];
7544
+ if (best.length === 1) {
7545
+ const only = best[0];
7413
7546
  if (!only) return { kind: "noMatch" };
7414
7547
  return { kind: "resolved", constructor: only };
7415
7548
  }
7416
- const byType = byName.filter(
7549
+ const byType = best.filter(
7417
7550
  (constructor2) => args.every((argument2) => {
7418
7551
  const parameter4 = constructor2.parameters.find(
7419
7552
  (candidate) => candidate.name.toLowerCase() === argument2.name.toLowerCase()
@@ -7428,17 +7561,23 @@ function resolveNeoScriptDeclaredConstructorOverload(constructors, args) {
7428
7561
  if (!only) return { kind: "noMatch" };
7429
7562
  return { kind: "resolved", constructor: only };
7430
7563
  }
7431
- if (byType.length === 0) return { kind: "ambiguous", candidates: byName };
7564
+ if (byType.length === 0) return { kind: "ambiguous", candidates: best };
7432
7565
  return { kind: "ambiguous", candidates: byType };
7433
7566
  }
7434
7567
  function describeNeoScriptDeclaredConstructors(className, constructors) {
7435
7568
  return constructors.map(
7436
- (constructor2) => `${className}(${constructor2.parameters.map((parameter4) => `${parameter4.name}${parameter4.required ? "" : "?"}`).join(", ")})`
7569
+ (constructor2) => `${className}(${constructor2.parameters.map(describeParameter).join(", ")})`
7437
7570
  ).join(", ");
7438
7571
  }
7572
+ function describeParameter(parameter4) {
7573
+ const nullability = parameter4.required ? "" : "?";
7574
+ const defaulted = parameter4.defaultValue === void 0 ? "" : ` = ${parameter4.defaultValue.displayText}`;
7575
+ return `${parameter4.name}${nullability}${defaulted}`;
7576
+ }
7439
7577
  var init_declared_constructors = __esm({
7440
7578
  "../packages/neoscript-language/src/declared-constructors.ts"() {
7441
7579
  "use strict";
7580
+ init_project();
7442
7581
  }
7443
7582
  });
7444
7583
 
@@ -8829,6 +8968,12 @@ function collectReturns(statements) {
8829
8968
  }
8830
8969
  return result;
8831
8970
  }
8971
+ function functionArityMessage(name, minimum, maximum, got) {
8972
+ if (minimum === maximum) {
8973
+ return `Function '${name}' expects ${maximum} argument${maximum === 1 ? "" : "s"}, got ${got}.`;
8974
+ }
8975
+ return `Function '${name}' expects between ${minimum} and ${maximum} arguments, got ${got}.`;
8976
+ }
8832
8977
  function requireArgCount(name, args, expected, pos) {
8833
8978
  if (args.length === expected) return;
8834
8979
  throw new CompileError(
@@ -12673,9 +12818,28 @@ var init_strict_resolver = __esm({
12673
12818
  }));
12674
12819
  }
12675
12820
  }
12676
- if (argumentsList2.length !== parameters.length) {
12821
+ const minimumArguments = parameters.filter(
12822
+ (parameter4) => !neoScriptParameterIsOmittable(parameter4)
12823
+ ).length;
12824
+ if (argumentsList2.length < minimumArguments) {
12825
+ throw new CompileError(
12826
+ functionArityMessage(
12827
+ symbol.name,
12828
+ minimumArguments,
12829
+ parameters.length,
12830
+ argumentsList2.length
12831
+ ),
12832
+ pos
12833
+ );
12834
+ }
12835
+ if (argumentsList2.length > parameters.length) {
12677
12836
  throw new CompileError(
12678
- `Function '${symbol.name}' expects ${parameters.length} argument${parameters.length === 1 ? "" : "s"}, got ${argumentsList2.length}.`,
12837
+ functionArityMessage(
12838
+ symbol.name,
12839
+ minimumArguments,
12840
+ parameters.length,
12841
+ argumentsList2.length
12842
+ ),
12679
12843
  pos
12680
12844
  );
12681
12845
  }
@@ -12890,13 +13054,13 @@ var init_strict_resolver = __esm({
12890
13054
  scope,
12891
13055
  pos
12892
13056
  );
12893
- const selected2 = intrinsic(
13057
+ const selected = intrinsic(
12894
13058
  "select" /* Select */,
12895
13059
  { collectionPointer: receiver.pointer, function: fn },
12896
13060
  { kind: "list", elementType: resultType, readOnly: true }
12897
13061
  );
12898
13062
  return {
12899
- ...selected2,
13063
+ ...selected,
12900
13064
  entryWritability: inferredReturn.writability,
12901
13065
  writeRoot: inferredReturn.writeRoot
12902
13066
  };
@@ -16595,12 +16759,25 @@ var init_project_source_parser = __esm({
16595
16759
  const annotations = this.parseAnnotations();
16596
16760
  const type = this.parseType();
16597
16761
  const name = this.expectName("parameter name");
16762
+ let defaultValue;
16763
+ if (this.eat("=")) {
16764
+ const expressionStart = this.peek();
16765
+ defaultValue = this.captureUntilTopLevel(/* @__PURE__ */ new Set([",", ")"]), false);
16766
+ if (defaultValue.text.trim().length === 0) {
16767
+ throw this.failure(
16768
+ "missing-parameter-default",
16769
+ `Parameter '${name.text}' declares '=' but no default value. Provide a constant expression or remove the '='.`,
16770
+ expressionStart
16771
+ );
16772
+ }
16773
+ }
16598
16774
  parameters.push({
16599
16775
  annotations,
16600
16776
  type,
16601
16777
  name: name.text,
16602
16778
  nameRange: name.range,
16603
- range: rangeFrom(start, name)
16779
+ ...defaultValue ? { defaultValue } : {},
16780
+ range: rangeFrom(start, this.previous())
16604
16781
  });
16605
16782
  if (!this.eat(",") && !this.at(")")) {
16606
16783
  throw this.failure(
@@ -17173,7 +17350,7 @@ var init_project_schema_contract_generated = __esm({
17173
17350
  "../packages/neoscript-language/src/project-schema-contract.generated.ts"() {
17174
17351
  "use strict";
17175
17352
  PROJECT_SCHEMA_MANIFEST_FORMAT_VERSION = 3;
17176
- PROJECT_SCHEMA_MANIFEST_CONTRACT_VERSION = "3.9";
17353
+ PROJECT_SCHEMA_MANIFEST_CONTRACT_VERSION = "3.10";
17177
17354
  PROJECT_FILE_UPLOAD_BATCH_SIZE = 32;
17178
17355
  NEO_PROJECT_SOURCE_RECORD_CONTRACT = {
17179
17356
  "recordFields": {
@@ -19272,6 +19449,24 @@ var init_project_source_construction_diagnostics = __esm({
19272
19449
  "unbound-constructor-argument": "error",
19273
19450
  /** §2.6. No overload's parameter-name set matches the call. */
19274
19451
  "no-matching-constructor-overload": "error",
19452
+ /**
19453
+ * P65 §2.2. Two overload candidates tie under the subset match after the
19454
+ * fewest-fill-ins betterness and the type tie-break; the message lists the
19455
+ * candidates the call could not choose between.
19456
+ */
19457
+ "ambiguous-constructor-call": "error",
19458
+ /**
19459
+ * P65 §1.3. A defaulted parameter declared before a non-defaulted one.
19460
+ * The code string is shared with `src/models/neoscript/parameter-defaults.ts`
19461
+ * so the push guards and the compiler name one rule identically.
19462
+ */
19463
+ "default-before-required-parameter": "error",
19464
+ /**
19465
+ * P65 §1.2. A parameter default that does not fit the parameter's declared
19466
+ * type — a `null` default on a non-nullable parameter included. Shared with
19467
+ * the push-guard validator, like the placement code above.
19468
+ */
19469
+ "parameter-default-type-mismatch": "error",
19275
19470
  /** §2.5 g. An initializer key naming no member of the constructed class. */
19276
19471
  "unknown-initializer-member": "error",
19277
19472
  /**
@@ -19541,9 +19736,13 @@ function resolveInvokedConstructor(declaration, call, diagnostics) {
19541
19736
  return true;
19542
19737
  }
19543
19738
  if (headerParameters.length === 0) return true;
19739
+ if (parameterListIsFullyDefaulted(headerParameters)) return true;
19740
+ const mandatory = headerParameters.filter(
19741
+ (parameter4) => parameter4.defaultValue === void 0
19742
+ );
19544
19743
  diagnostics.push({
19545
19744
  code: "required-constructor-not-invoked",
19546
- message: `Class '${declaration.name}' declares the required constructor ${describeParameterList(declaration.name, headerParameters)}, so it cannot be constructed without passing ${describeNameList(headerParameters.map((parameter4) => parameter4.name))}.`,
19745
+ message: `Class '${declaration.name}' declares the required constructor ${describeParameterList(declaration.name, headerParameters)}, so it cannot be constructed without passing ${describeNameList(mandatory.map((parameter4) => parameter4.name))}.`,
19547
19746
  anchor: { kind: "site" }
19548
19747
  });
19549
19748
  return true;
@@ -19553,7 +19752,7 @@ function resolveInvokedConstructor(declaration, call, diagnostics) {
19553
19752
  }
19554
19753
  if (call.argumentNames.length === 0) {
19555
19754
  return declaration.constructors.some(
19556
- (constructor2) => constructor2.parameters.length === 0
19755
+ (constructor2) => parameterListIsFullyDefaulted(constructor2.parameters)
19557
19756
  );
19558
19757
  }
19559
19758
  if (declaration.constructors.length === 1) {
@@ -19565,13 +19764,17 @@ function resolveInvokedConstructor(declaration, call, diagnostics) {
19565
19764
  );
19566
19765
  return true;
19567
19766
  }
19568
- const key = argumentNameSetKey(
19569
- call.argumentNames.filter((name) => name !== null)
19767
+ const suppliedNames = call.argumentNames.filter(
19768
+ (name) => name !== null
19570
19769
  );
19571
19770
  const matches = declaration.constructors.filter(
19572
- (constructor2) => argumentNameSetKey(
19573
- constructor2.parameters.map((parameter4) => parameter4.name)
19574
- ) === key
19771
+ (constructor2) => neoScriptCallMatchesParameters(
19772
+ suppliedNames,
19773
+ constructor2.parameters.map((parameter4) => ({
19774
+ name: parameter4.name,
19775
+ defaulted: parameter4.defaultValue !== void 0
19776
+ }))
19777
+ )
19575
19778
  );
19576
19779
  if (matches.length > 0) return true;
19577
19780
  diagnostics.push({
@@ -19606,7 +19809,7 @@ function validateArgumentsAgainstParameters(className, parameters, call, diagnos
19606
19809
  });
19607
19810
  });
19608
19811
  const missing = parameters.filter(
19609
- (parameter4) => !supplied.has(parameter4.name.toLowerCase())
19812
+ (parameter4) => parameter4.defaultValue === void 0 && !supplied.has(parameter4.name.toLowerCase())
19610
19813
  );
19611
19814
  if (missing.length === 0) return;
19612
19815
  diagnostics.push({
@@ -19615,6 +19818,9 @@ function validateArgumentsAgainstParameters(className, parameters, call, diagnos
19615
19818
  anchor: { kind: "site" }
19616
19819
  });
19617
19820
  }
19821
+ function parameterListIsFullyDefaulted(parameters) {
19822
+ return parameters.every((parameter4) => parameter4.defaultValue !== void 0);
19823
+ }
19618
19824
  function validateInitializerEntries(index, entry, call, diagnostics) {
19619
19825
  if (call.initializerNames.length === 0) return;
19620
19826
  const chain = baseChain(index, entry);
@@ -19746,13 +19952,12 @@ function substitute(type, bindings) {
19746
19952
  arguments: type.arguments.map((argument2) => substitute(argument2, bindings))
19747
19953
  };
19748
19954
  }
19749
- function argumentNameSetKey(names) {
19750
- return [...names].map((name) => name.toLowerCase()).sort().join(",");
19751
- }
19752
19955
  function describeParameterList(className, parameters) {
19753
- const rendered = parameters.map(
19754
- (parameter4) => `${parameter4.name}${parameter4.type.nullable ? "?" : ""}`
19755
- ).join(", ");
19956
+ const rendered = parameters.map((parameter4) => {
19957
+ const nullability = parameter4.type.nullable ? "?" : "";
19958
+ const defaulted = parameter4.defaultValue === void 0 ? "" : ` = ${parameter4.defaultValue.text}`;
19959
+ return `${parameter4.name}${nullability}${defaulted}`;
19960
+ }).join(", ");
19756
19961
  return `${className}(${rendered})`;
19757
19962
  }
19758
19963
  function describeNameList(names) {
@@ -19781,6 +19986,7 @@ function push(diagnostics, uri, range2, code, message, related2 = []) {
19781
19986
  var init_project_source_settlement = __esm({
19782
19987
  "../packages/neoscript-language/src/project-source-settlement.ts"() {
19783
19988
  "use strict";
19989
+ init_declared_constructors();
19784
19990
  init_project_source_construction_diagnostics();
19785
19991
  init_strict_compile_error();
19786
19992
  init_strict_parser();
@@ -24443,6 +24649,223 @@ var init_project_source_type_checker = __esm({
24443
24649
  }
24444
24650
  });
24445
24651
 
24652
+ // ../packages/neoscript-language/src/project-source-parameter-defaults.ts
24653
+ function validateProjectSourceParameterDefaults(documents) {
24654
+ const diagnostics = [];
24655
+ const enumOptions = collectEnumOptions(documents);
24656
+ for (const [uri, document] of documents) {
24657
+ for (const declaration of document.declarations) {
24658
+ if (declaration.kind === "class") {
24659
+ if (declaration.headerParameters !== void 0) {
24660
+ validateParameterList(
24661
+ uri,
24662
+ declaration.headerParameters,
24663
+ { deferred: false },
24664
+ enumOptions,
24665
+ diagnostics
24666
+ );
24667
+ }
24668
+ for (const constructor2 of declaration.constructors) {
24669
+ validateParameterList(
24670
+ uri,
24671
+ constructor2.parameters,
24672
+ { deferred: false },
24673
+ enumOptions,
24674
+ diagnostics
24675
+ );
24676
+ }
24677
+ }
24678
+ if (declaration.kind === "class" || declaration.kind === "interface") {
24679
+ for (const member of declaration.members) {
24680
+ if (member.kind !== "function") continue;
24681
+ validateParameterList(
24682
+ uri,
24683
+ member.parameters,
24684
+ { deferred: member.modifiers.includes("async") },
24685
+ enumOptions,
24686
+ diagnostics
24687
+ );
24688
+ }
24689
+ }
24690
+ }
24691
+ }
24692
+ return diagnostics;
24693
+ }
24694
+ function collectEnumOptions(documents) {
24695
+ const options = /* @__PURE__ */ new Map();
24696
+ for (const document of documents.values()) {
24697
+ for (const declaration of document.declarations) {
24698
+ if (declaration.kind !== "enum") continue;
24699
+ const names = options.get(declaration.name) ?? options.set(declaration.name, /* @__PURE__ */ new Set()).get(declaration.name);
24700
+ for (const option of declaration.options) names.add(option.name);
24701
+ }
24702
+ }
24703
+ return options;
24704
+ }
24705
+ function validateParameterList(uri, parameters, context, enumOptions, diagnostics) {
24706
+ let lastNonDefaultedIndex = -1;
24707
+ for (let index = parameters.length - 1; index >= 0; index -= 1) {
24708
+ if (parameters[index].defaultValue === void 0) {
24709
+ lastNonDefaultedIndex = index;
24710
+ break;
24711
+ }
24712
+ }
24713
+ parameters.forEach((parameter4, index) => {
24714
+ const defaultValue = parameter4.defaultValue;
24715
+ if (defaultValue === void 0) return;
24716
+ if (context.deferred) {
24717
+ diagnostics.push({
24718
+ uri,
24719
+ range: defaultValue.range,
24720
+ severity: "error",
24721
+ source: "neo-project",
24722
+ code: PARAMETER_DEFAULT_ON_DEFERRED_FUNCTION,
24723
+ message: `Parameter '${parameter4.name}' of a deferred function cannot declare a default: generated C# appends a trailing deferred-completion parameter, which a defaulted parameter may not precede.`
24724
+ });
24725
+ }
24726
+ if (index < lastNonDefaultedIndex) {
24727
+ diagnostics.push({
24728
+ uri,
24729
+ range: parameter4.range,
24730
+ severity: "error",
24731
+ source: "neo-project",
24732
+ code: DEFAULT_BEFORE_REQUIRED_PARAMETER,
24733
+ message: `Parameter '${parameter4.name}' declares a default before parameter '${parameters[lastNonDefaultedIndex].name}', which has none. Defaulted parameters must come after every non-defaulted parameter.`
24734
+ });
24735
+ }
24736
+ validateDefaultExpression(
24737
+ uri,
24738
+ parameter4,
24739
+ defaultValue,
24740
+ enumOptions,
24741
+ diagnostics
24742
+ );
24743
+ });
24744
+ }
24745
+ function validateDefaultExpression(uri, parameter4, defaultValue, enumOptions, diagnostics) {
24746
+ const constant = classifyConstantDefault(defaultValue.text);
24747
+ if (constant === null) {
24748
+ diagnostics.push({
24749
+ uri,
24750
+ range: defaultValue.range,
24751
+ severity: "error",
24752
+ source: "neo-project",
24753
+ code: NON_CONSTANT_PARAMETER_DEFAULT,
24754
+ message: `Parameter '${parameter4.name}' default must be a constant: a bool, number, or string literal, a leading-dot enum option, or null.`
24755
+ });
24756
+ return;
24757
+ }
24758
+ const mismatch = defaultTypeMismatch(
24759
+ parameter4.type,
24760
+ constant,
24761
+ enumOptions,
24762
+ parameter4.name
24763
+ );
24764
+ if (mismatch === null) return;
24765
+ diagnostics.push({
24766
+ uri,
24767
+ range: defaultValue.range,
24768
+ severity: "error",
24769
+ source: "neo-project",
24770
+ code: PARAMETER_DEFAULT_TYPE_MISMATCH,
24771
+ message: mismatch
24772
+ });
24773
+ }
24774
+ function classifyConstantDefault(text) {
24775
+ let expression;
24776
+ try {
24777
+ expression = parseExpression(text);
24778
+ } catch {
24779
+ return null;
24780
+ }
24781
+ return classifyConstantExpression(expression);
24782
+ }
24783
+ function classifyConstantExpression(expression) {
24784
+ switch (expression.kind) {
24785
+ case "litNull":
24786
+ return { kind: "null" };
24787
+ case "litBool":
24788
+ return { kind: "bool" };
24789
+ case "litInt":
24790
+ return { kind: "int" };
24791
+ case "litFloat":
24792
+ return { kind: "float" };
24793
+ case "litString":
24794
+ return { kind: "string" };
24795
+ case "contextualEnum":
24796
+ return { kind: "enumOption", optionName: expression.name };
24797
+ case "unary": {
24798
+ if (expression.op !== "-") return null;
24799
+ const operand = classifyConstantExpression(expression.operand);
24800
+ if (operand === null) return null;
24801
+ if (operand.kind !== "int" && operand.kind !== "float") return null;
24802
+ return operand;
24803
+ }
24804
+ default:
24805
+ return null;
24806
+ }
24807
+ }
24808
+ function defaultTypeMismatch(type, constant, enumOptions, parameterName) {
24809
+ if (constant.kind === "null") {
24810
+ if (type.nullable) return null;
24811
+ return `Parameter '${parameterName}' defaults to null, but its type '${formatSourceType(type)}' is not nullable.`;
24812
+ }
24813
+ const declaredEnumOptions = enumOptions.get(type.name);
24814
+ if (constant.kind === "enumOption") {
24815
+ if (declaredEnumOptions === void 0) {
24816
+ return `Parameter '${parameterName}' defaults to enum option '.${constant.optionName}', but its type '${formatSourceType(type)}' is not an enum.`;
24817
+ }
24818
+ if (!declaredEnumOptions.has(constant.optionName)) {
24819
+ return `Parameter '${parameterName}' defaults to '.${constant.optionName}', which enum '${type.name}' does not declare.`;
24820
+ }
24821
+ return null;
24822
+ }
24823
+ if (constantKindMatchesPrimitive(type.name, constant.kind)) return null;
24824
+ if (PRIMITIVE_PARAMETER_TYPES.has(type.name) || declaredEnumOptions !== void 0) {
24825
+ return `Parameter '${parameterName}' default is a ${describeConstant(constant)}, which does not match its declared type '${formatSourceType(type)}'.`;
24826
+ }
24827
+ return `Parameter '${parameterName}' of type '${formatSourceType(type)}' can only default to null${type.nullable ? "" : ", and only when the type is nullable"}.`;
24828
+ }
24829
+ function constantKindMatchesPrimitive(typeName, kind) {
24830
+ if (typeName === "bool") return kind === "bool";
24831
+ if (typeName === "int") return kind === "int";
24832
+ if (typeName === "float") return kind === "int" || kind === "float";
24833
+ if (typeName === "decimal") return kind === "int" || kind === "float";
24834
+ if (typeName === "string") return kind === "string";
24835
+ return false;
24836
+ }
24837
+ function describeConstant(constant) {
24838
+ if (constant.kind === "bool") return "bool literal";
24839
+ if (constant.kind === "string") return "string literal";
24840
+ if (constant.kind === "int") return "whole-number literal";
24841
+ return "fractional number literal";
24842
+ }
24843
+ function formatSourceType(type) {
24844
+ const argumentsText = type.typeArguments.length === 0 ? "" : `<${type.typeArguments.map(formatSourceType).join(", ")}>`;
24845
+ return `${type.name}${argumentsText}${type.nullable ? "?" : ""}`;
24846
+ }
24847
+ var PARAMETER_DEFAULT_DIAGNOSTIC_CODES, DEFAULT_BEFORE_REQUIRED_PARAMETER, PARAMETER_DEFAULT_TYPE_MISMATCH, NON_CONSTANT_PARAMETER_DEFAULT, PARAMETER_DEFAULT_ON_DEFERRED_FUNCTION, PRIMITIVE_PARAMETER_TYPES;
24848
+ var init_project_source_parameter_defaults = __esm({
24849
+ "../packages/neoscript-language/src/project-source-parameter-defaults.ts"() {
24850
+ "use strict";
24851
+ init_language_spec();
24852
+ init_strict_parser();
24853
+ PARAMETER_DEFAULT_DIAGNOSTIC_CODES = {
24854
+ defaultBeforeRequiredParameter: "default-before-required-parameter",
24855
+ parameterDefaultTypeMismatch: "parameter-default-type-mismatch",
24856
+ nonConstantParameterDefault: "non-constant-parameter-default",
24857
+ parameterDefaultOnDeferredFunction: "parameter-default-on-deferred-function"
24858
+ };
24859
+ ({
24860
+ defaultBeforeRequiredParameter: DEFAULT_BEFORE_REQUIRED_PARAMETER,
24861
+ parameterDefaultTypeMismatch: PARAMETER_DEFAULT_TYPE_MISMATCH,
24862
+ nonConstantParameterDefault: NON_CONSTANT_PARAMETER_DEFAULT,
24863
+ parameterDefaultOnDeferredFunction: PARAMETER_DEFAULT_ON_DEFERRED_FUNCTION
24864
+ } = PARAMETER_DEFAULT_DIAGNOSTIC_CODES);
24865
+ PRIMITIVE_PARAMETER_TYPES = new Set(NEOSCRIPT_PRIMITIVE_TYPES);
24866
+ }
24867
+ });
24868
+
24446
24869
  // ../packages/neoscript-language/src/project-source-analysis.ts
24447
24870
  function isSystemReservedRecordId(id2) {
24448
24871
  if (id2 === null) return false;
@@ -24500,6 +24923,7 @@ function analyzeNeoProjectSources(inputs, parsedDocuments = /* @__PURE__ */ new
24500
24923
  validateSystemAnnotationAuthoring(documents, diagnostics);
24501
24924
  validateTypeReferences(documents, symbols, diagnostics);
24502
24925
  diagnostics.push(...validateProjectSourceTypes(documents));
24926
+ diagnostics.push(...validateProjectSourceParameterDefaults(documents));
24503
24927
  diagnostics.push(...validateProjectSourceSettlement(documents));
24504
24928
  diagnostics.push(...validateProjectSourceSemantics(documents));
24505
24929
  const bodyCompilation = compileProjectSourceBodies(documents);
@@ -25108,6 +25532,7 @@ var init_project_source_analysis = __esm({
25108
25532
  init_project_source_settlement();
25109
25533
  init_project_source_script_compiler();
25110
25534
  init_project_source_type_checker();
25535
+ init_project_source_parameter_defaults();
25111
25536
  BUILTIN_TYPE_NAMES = /* @__PURE__ */ new Set([
25112
25537
  ...NEOSCRIPT_PRIMITIVE_TYPES,
25113
25538
  ...NEOSCRIPT_BUILTIN_TYPES,
@@ -25427,7 +25852,9 @@ function projectCompletions(analysis, document, position) {
25427
25852
  items: constructorFields.map((field) => ({
25428
25853
  label: field.name,
25429
25854
  kind: "property",
25430
- detail: field.type,
25855
+ // P65 §6. C#-style square brackets mark a defaulted parameter as
25856
+ // omittable at the call site.
25857
+ detail: field.defaultText === void 0 ? field.type : `[${field.type} = ${field.defaultText}]`,
25431
25858
  insertText: `${field.name}: `
25432
25859
  }))
25433
25860
  };
@@ -25851,9 +26278,9 @@ function declaredConstructorNamedArguments(analysis, typeName, used) {
25851
26278
  )
25852
26279
  )
25853
26280
  );
25854
- const selected2 = reachable.length > 0 ? reachable : contract.constructors;
26281
+ const selected = reachable.length > 0 ? reachable : contract.constructors;
25855
26282
  const fields = /* @__PURE__ */ new Map();
25856
- for (const constructor2 of selected2) {
26283
+ for (const constructor2 of selected) {
25857
26284
  for (const parameter4 of constructor2.parameters) {
25858
26285
  if (fields.has(parameter4.name)) continue;
25859
26286
  fields.set(parameter4.name, parameterArgumentField(parameter4));
@@ -25862,7 +26289,11 @@ function declaredConstructorNamedArguments(analysis, typeName, used) {
25862
26289
  return [...fields.values()];
25863
26290
  }
25864
26291
  function parameterArgumentField(parameter4) {
25865
- return { name: parameter4.name, type: sourceTypeText(parameter4.type) };
26292
+ return {
26293
+ name: parameter4.name,
26294
+ type: sourceTypeText(parameter4.type),
26295
+ ...parameter4.defaultValue === void 0 ? {} : { defaultText: parameter4.defaultValue.text }
26296
+ };
25866
26297
  }
25867
26298
  function projectInitializerMemberCompletions(analysis, document, position) {
25868
26299
  const site = constructionSiteAt(analysis, document, position);
@@ -25922,6 +26353,13 @@ function constructibleMembers(analysis, typeName) {
25922
26353
  }
25923
26354
  return [...members.values()];
25924
26355
  }
26356
+ function sourceParameterSignatureText(parameter4) {
26357
+ return constructorParameterLabel(sourceParameterProjection(parameter4));
26358
+ }
26359
+ function functionParameterLabel(parameter4) {
26360
+ const suffix = parameter4.defaultValue === void 0 ? "" : ` = ${parameter4.defaultValue.text}`;
26361
+ return `${parameter4.type.name} ${parameter4.name}${suffix}`;
26362
+ }
25925
26363
  function sourceTypeText(type) {
25926
26364
  const args = type.typeArguments.length > 0 ? `<${type.typeArguments.map(sourceTypeText).join(", ")}>` : "";
25927
26365
  return `${type.name}${args}${type.nullable ? "?" : ""}`;
@@ -26048,7 +26486,7 @@ function projectConstructionContractMarkdown(analysis, className) {
26048
26486
  const contract = classConstructionContract(index, className);
26049
26487
  if (!contract) return "";
26050
26488
  if (contract.kind === "required") {
26051
- const parameters = contract.parameters.map((parameter4) => `${sourceTypeText(parameter4.type)} ${parameter4.name}`).join(", ");
26489
+ const parameters = contract.parameters.map(sourceParameterSignatureText).join(", ");
26052
26490
  return `
26053
26491
 
26054
26492
  Construct with \`new(${parameters})\` \u2014 this class declares a required constructor, so the implicit \`new\` is unavailable.`;
@@ -26063,9 +26501,7 @@ Construct with \`new(${parameters})\` \u2014 this class declares a required cons
26063
26501
  }
26064
26502
  if (contract.kind === "declared") {
26065
26503
  const overloads = contract.constructors.map(
26066
- (constructor2) => `\`${className}(${constructor2.parameters.map(
26067
- (parameter4) => `${sourceTypeText(parameter4.type)} ${parameter4.name}`
26068
- ).join(", ")})\``
26504
+ (constructor2) => `\`${className}(${constructor2.parameters.map(sourceParameterSignatureText).join(", ")})\``
26069
26505
  ).join(", ");
26070
26506
  lines.push(`Constructors: ${overloads}.`);
26071
26507
  }
@@ -26187,13 +26623,11 @@ function projectSignatureHelp(analysis, document, position) {
26187
26623
  if (functions.length === 0) return null;
26188
26624
  return {
26189
26625
  signatures: functions.map(({ owner, member }) => {
26190
- const parameters = member.parameters.map(
26191
- (parameter4) => `${parameter4.type.name} ${parameter4.name}`
26192
- );
26626
+ const parameters = member.parameters.map(functionParameterLabel);
26193
26627
  return {
26194
26628
  label: `${member.type.name} ${owner}.${member.name}(${parameters.join(", ")})`,
26195
26629
  parameters: member.parameters.map((parameter4) => ({
26196
- label: `${parameter4.type.name} ${parameter4.name}`
26630
+ label: functionParameterLabel(parameter4)
26197
26631
  }))
26198
26632
  };
26199
26633
  }),
@@ -26959,7 +27393,10 @@ function findTypeDeclaration(analysis, name) {
26959
27393
  return void 0;
26960
27394
  }
26961
27395
  function constructorParameterLabel(parameter4) {
26962
- return `${parameter4.type} ${parameter4.name}`;
27396
+ return `${parameter4.type} ${parameter4.name}${parameterDefaultSuffix2(parameter4)}`;
27397
+ }
27398
+ function parameterDefaultSuffix2(parameter4) {
27399
+ return parameter4.defaultText === void 0 ? "" : ` = ${parameter4.defaultText}`;
26963
27400
  }
26964
27401
  function projectConstructorTypeName(analysis, document, callee, beforeCallee) {
26965
27402
  if (beforeCallee?.text === "new") return callee.text;
@@ -26985,7 +27422,11 @@ function declarationConstructorParameters(declaration) {
26985
27422
  ).map((member) => ({ type: member.type.name, name: member.name }));
26986
27423
  }
26987
27424
  function sourceParameterProjection(parameter4) {
26988
- return { type: sourceTypeText(parameter4.type), name: parameter4.name };
27425
+ return {
27426
+ type: sourceTypeText(parameter4.type),
27427
+ name: parameter4.name,
27428
+ ...parameter4.defaultValue === void 0 ? {} : { defaultText: parameter4.defaultValue.text }
27429
+ };
26989
27430
  }
26990
27431
  function graphConstructorParameters(typeName) {
26991
27432
  switch (typeName) {
@@ -27104,6 +27545,9 @@ function projectConstructionQuickFixes(analysis, document, diagnostic) {
27104
27545
  if (diagnostic.code === "unknown-identifier") {
27105
27546
  return moveParametersToClassHeaderFixes(analysis, document, diagnostic);
27106
27547
  }
27548
+ if (diagnostic.code === "default-before-required-parameter") {
27549
+ return moveDefaultedParameterFixes(analysis, document, diagnostic);
27550
+ }
27107
27551
  return [];
27108
27552
  }
27109
27553
  function settleRequiredMemberFixes(analysis, document, diagnostic) {
@@ -27209,10 +27653,13 @@ function placeholderValue(analysis, index, type, depth) {
27209
27653
  if (declaration.modifiers.includes("abstract")) return null;
27210
27654
  const contract = classConstructionContract(index, type.name);
27211
27655
  if (contract?.kind !== "required") return "new()";
27212
- if (contract.parameters.length === 0) return "new()";
27656
+ const mandatory = contract.parameters.filter(
27657
+ (parameter4) => parameter4.defaultValue === void 0
27658
+ );
27659
+ if (mandatory.length === 0) return "new()";
27213
27660
  if (depth > 0) return null;
27214
27661
  const args = [];
27215
- for (const parameter4 of contract.parameters) {
27662
+ for (const parameter4 of mandatory) {
27216
27663
  const value = placeholderValue(analysis, index, parameter4.type, depth + 1);
27217
27664
  if (value === null) return null;
27218
27665
  args.push(`${parameter4.name}: ${value}`);
@@ -27404,6 +27851,71 @@ function innerBodyText(constructor2) {
27404
27851
  const trimmed = constructor2.body.text.trim();
27405
27852
  return trimmed.startsWith("{") && trimmed.endsWith("}") ? trimmed.slice(1, -1) : trimmed;
27406
27853
  }
27854
+ function moveDefaultedParameterFixes(analysis, document, diagnostic) {
27855
+ const source = analysis.documents.get(document.uri);
27856
+ if (!source) return [];
27857
+ const parameters = parameterListAt(source.declarations, diagnostic.range);
27858
+ if (parameters === null) return [];
27859
+ const first = parameters[0];
27860
+ const last = parameters[parameters.length - 1];
27861
+ if (!first || !last) return [];
27862
+ const text = new SourceText(document.text);
27863
+ const authored = (parameter4) => text.text.slice(
27864
+ text.offsetAt(parameter4.range.start),
27865
+ text.offsetAt(parameter4.range.end)
27866
+ );
27867
+ const reordered = [
27868
+ ...parameters.filter((parameter4) => parameter4.defaultValue === void 0),
27869
+ ...parameters.filter((parameter4) => parameter4.defaultValue !== void 0)
27870
+ ];
27871
+ return [
27872
+ {
27873
+ title: "Move defaulted parameters after required parameters",
27874
+ kind: "quickfix",
27875
+ diagnostics: [diagnostic],
27876
+ edit: {
27877
+ changes: {
27878
+ [document.uri]: [
27879
+ {
27880
+ range: {
27881
+ start: first.range.start,
27882
+ end: last.range.end
27883
+ },
27884
+ newText: reordered.map(authored).join(", ")
27885
+ }
27886
+ ]
27887
+ }
27888
+ },
27889
+ preferred: true
27890
+ }
27891
+ ];
27892
+ }
27893
+ function parameterListAt(declarations, range2) {
27894
+ for (const declaration of declarations) {
27895
+ if (declaration.kind !== "class" && declaration.kind !== "interface") {
27896
+ continue;
27897
+ }
27898
+ const lists = [];
27899
+ if (declaration.kind === "class") {
27900
+ if (declaration.headerParameters !== void 0) {
27901
+ lists.push(declaration.headerParameters);
27902
+ }
27903
+ for (const constructor2 of declaration.constructors) {
27904
+ lists.push(constructor2.parameters);
27905
+ }
27906
+ }
27907
+ for (const member of declaration.members) {
27908
+ if (member.kind === "function") lists.push(member.parameters);
27909
+ }
27910
+ for (const list of lists) {
27911
+ const hit = list.some(
27912
+ (parameter4) => rangeContains(parameter4.range, range2.start)
27913
+ );
27914
+ if (hit) return list;
27915
+ }
27916
+ }
27917
+ return null;
27918
+ }
27407
27919
  var NEW_CONSTRUCTIBLE_BUILTIN_TYPES;
27408
27920
  var init_project_source_construction_quick_fixes = __esm({
27409
27921
  "../packages/neoscript-language/src/project-source-construction-quick-fixes.ts"() {
@@ -27560,6 +28072,7 @@ function manifestParameter(uri, parameter4) {
27560
28072
  name: parameter4.name,
27561
28073
  type: manifestType(parameter4.type),
27562
28074
  annotations: manifestAnnotations(parameter4.annotations),
28075
+ default: parameter4.defaultValue?.text ?? null,
27563
28076
  source: { uri, range: parameter4.range }
27564
28077
  };
27565
28078
  }
@@ -27970,12 +28483,21 @@ function assertBaseClauseArguments(value, path) {
27970
28483
  }
27971
28484
  function assertParameter(value, path) {
27972
28485
  const parameter4 = record(value, path);
27973
- exactKeys(parameter4, path, ["name", "type", "annotations", "source"]);
28486
+ exactKeys(parameter4, path, [
28487
+ "name",
28488
+ "type",
28489
+ "annotations",
28490
+ "default",
28491
+ "source"
28492
+ ]);
27974
28493
  string(parameter4.name, `${path}.name`);
27975
28494
  assertType(parameter4.type, `${path}.type`);
27976
28495
  array(parameter4.annotations, `${path}.annotations`).forEach(
27977
28496
  (annotation2, index) => assertAnnotation(annotation2, `${path}.annotations[${index}]`)
27978
28497
  );
28498
+ if (parameter4.default !== null) {
28499
+ string(parameter4.default, `${path}.default`);
28500
+ }
27979
28501
  assertLocation(parameter4.source, `${path}.source`);
27980
28502
  }
27981
28503
  function assertMember(value, path) {
@@ -28408,6 +28930,7 @@ function projectSchemaManifest(input, options = {}) {
28408
28930
  members: memberById,
28409
28931
  classes: schemaClassById,
28410
28932
  interfaces: interfaceById,
28933
+ enums: indexById(enums, "ProjectSchemaManifest.enums"),
28411
28934
  genericNames,
28412
28935
  effectiveWritabilityByMemberId: effectiveMemberWritability(
28413
28936
  members,
@@ -28469,7 +28992,8 @@ function groupDeclaredConstructors(declaredConstructors2, environment) {
28469
28992
  (parameter4) => ({
28470
28993
  name: parameter4.name,
28471
28994
  type: parameter4.type,
28472
- required: parameter4.type.nullable !== true
28995
+ required: parameter4.type.nullable !== true,
28996
+ ...parameter4.defaultValue === void 0 ? {} : { defaultValue: parameter4.defaultValue }
28473
28997
  })
28474
28998
  ),
28475
28999
  ...documentation === void 0 ? {} : { documentation },
@@ -29479,6 +30003,11 @@ function argumentsList(value, environment, field) {
29479
30003
  environment,
29480
30004
  `${field}.arguments[${index}].type`
29481
30005
  ),
30006
+ ...manifestParameterDefault(
30007
+ argument2,
30008
+ environment,
30009
+ `${field}.arguments[${index}]`
30010
+ ),
29482
30011
  ...spanAndSelectionLocations(
29483
30012
  argument2.source,
29484
30013
  argument2.selectionSpan ?? argument2.source,
@@ -29487,6 +30016,54 @@ function argumentsList(value, environment, field) {
29487
30016
  )
29488
30017
  }));
29489
30018
  }
30019
+ function neoScriptParameterDefaultDisplayText(options) {
30020
+ const { value, kind } = options;
30021
+ if (value === null) return "null";
30022
+ if (kind === "enum") return `.${options.enumOptionName ?? String(value)}`;
30023
+ if (kind === "decimal" && typeof value === "string") return value;
30024
+ if (typeof value === "string") return JSON.stringify(value);
30025
+ return String(value);
30026
+ }
30027
+ function manifestParameterDefault(argument2, environment, field) {
30028
+ const declared = optionalRecord(argument2.default);
30029
+ if (declared === void 0) return {};
30030
+ const value = constantDefaultValue(declared.value, `${field}.default.value`);
30031
+ const type = record2(argument2.type, `${field}.type`);
30032
+ const kind = string2(type.kind, `${field}.type.kind`);
30033
+ const enumOptionName = kind === "enum" && typeof value === "string" ? manifestEnumOptionName(
30034
+ string2(type.enumId, `${field}.type.enumId`),
30035
+ value,
30036
+ environment
30037
+ ) : void 0;
30038
+ return {
30039
+ defaultValue: {
30040
+ displayText: neoScriptParameterDefaultDisplayText({
30041
+ value,
30042
+ kind: kind === "enum" || kind === "decimal" ? kind : "other",
30043
+ ...enumOptionName === void 0 ? {} : { enumOptionName }
30044
+ }),
30045
+ value
30046
+ }
30047
+ };
30048
+ }
30049
+ function constantDefaultValue(value, field) {
30050
+ if (value !== null && typeof value !== "boolean" && typeof value !== "number" && typeof value !== "string") {
30051
+ throw new Error(
30052
+ `${field} must be a \xA71.2 constant (boolean, number, string, or null), received ${JSON.stringify(value)}.`
30053
+ );
30054
+ }
30055
+ return value;
30056
+ }
30057
+ function manifestEnumOptionName(enumId, optionId, environment) {
30058
+ const schemaEnum = environment.enums.get(enumId);
30059
+ if (schemaEnum === void 0) return void 0;
30060
+ const options = records(schemaEnum.options ?? [], `enum ${enumId}.options`);
30061
+ const option = options.find(
30062
+ (candidate) => candidate.id === optionId || candidate.key === optionId
30063
+ );
30064
+ if (option === void 0) return void 0;
30065
+ return typeof option.name === "string" ? option.name : void 0;
30066
+ }
29490
30067
  function sourceLocation(value, environment, field) {
29491
30068
  const source = optionalRecord(value);
29492
30069
  if (!source) return {};
@@ -29499,14 +30076,14 @@ function sourceLocation(value, environment, field) {
29499
30076
  }
29500
30077
  function spanAndSelectionLocations(spanValue, selectionValue, environment, field) {
29501
30078
  const navigation = spanLocation(spanValue, environment, field);
29502
- const selection = spanLocation(
30079
+ const selection2 = spanLocation(
29503
30080
  selectionValue,
29504
30081
  environment,
29505
30082
  `${field}.selection`
29506
30083
  );
29507
30084
  return {
29508
30085
  ...navigation,
29509
- ...selection.location ? { selectionLocation: selection.location } : {}
30086
+ ...selection2.location ? { selectionLocation: selection2.location } : {}
29510
30087
  };
29511
30088
  }
29512
30089
  function scriptDefinitionLocations(member, environment, field) {
@@ -30436,6 +31013,7 @@ var init_src = __esm({
30436
31013
  init_project_source_construction_diagnostics();
30437
31014
  init_project_source_construction_quick_fixes();
30438
31015
  init_project_source_manifest();
31016
+ init_project_source_parameter_defaults();
30439
31017
  init_project_source_settlement();
30440
31018
  init_project_source_parser();
30441
31019
  init_project_source_script_compiler();
@@ -31222,6 +31800,9 @@ function normalizeDocumentFields(recordKind, value) {
31222
31800
  if (current === void 0) normalized[field] = null;
31223
31801
  }
31224
31802
  if (recordKind === "member") {
31803
+ if (CALLABLE_MEMBER_KINDS.has(normalized.kind)) {
31804
+ normalized.required = false;
31805
+ }
31225
31806
  normalizeTypeInfoBindings(normalized.returnTypeInfo);
31226
31807
  if (Array.isArray(normalized.argumentTypes)) {
31227
31808
  for (const argument2 of normalized.argumentTypes) {
@@ -31333,13 +31914,14 @@ function deepNormalizeValue(value) {
31333
31914
  function isRecord(value) {
31334
31915
  return typeof value === "object" && value !== null && !Array.isArray(value);
31335
31916
  }
31336
- var SchemaDocumentContractError;
31917
+ var CALLABLE_MEMBER_KINDS, SchemaDocumentContractError;
31337
31918
  var init_contracts = __esm({
31338
31919
  "src/project-manifest/contracts.ts"() {
31339
31920
  "use strict";
31340
31921
  init_document_contracts();
31341
31922
  init_machine_strings();
31342
31923
  init_document_contracts();
31924
+ CALLABLE_MEMBER_KINDS = /* @__PURE__ */ new Set([13, 23]);
31343
31925
  SchemaDocumentContractError = class extends Error {
31344
31926
  constructor(recordKind, field) {
31345
31927
  super(
@@ -31365,6 +31947,8 @@ function threeWayMergeRecord(base, server, local, policy = {}) {
31365
31947
  const comparisonServer = policy.comparison?.server ?? serverRecord;
31366
31948
  const comparisonLocal = policy.comparison?.local ?? localRecord;
31367
31949
  const merged = {};
31950
+ const localVariant = {};
31951
+ const serverVariant = {};
31368
31952
  const conflictFields = [];
31369
31953
  const keys = /* @__PURE__ */ new Set([
31370
31954
  ...Object.keys(serverRecord),
@@ -31375,7 +31959,11 @@ function threeWayMergeRecord(base, server, local, policy = {}) {
31375
31959
  const rawServerValue = serverRecord[key];
31376
31960
  const rawLocalValue = localRecord[key];
31377
31961
  if (policy.serverWinsFields?.has(key) === true) {
31378
- if (rawServerValue !== void 0) merged[key] = rawServerValue;
31962
+ if (rawServerValue !== void 0) {
31963
+ merged[key] = rawServerValue;
31964
+ localVariant[key] = rawServerValue;
31965
+ serverVariant[key] = rawServerValue;
31966
+ }
31379
31967
  continue;
31380
31968
  }
31381
31969
  const baseValue = comparisonBase[key];
@@ -31396,25 +31984,31 @@ function threeWayMergeRecord(base, server, local, policy = {}) {
31396
31984
  } else if (result.present) {
31397
31985
  merged[key] = result.value;
31398
31986
  }
31987
+ if (result.local.present) localVariant[key] = result.local.value;
31988
+ if (result.server.present) serverVariant[key] = result.server.value;
31399
31989
  }
31400
- return { merged, conflictFields };
31990
+ return { merged, localVariant, serverVariant, conflictFields };
31401
31991
  }
31402
31992
  function mergeValue(args) {
31403
31993
  if (canonicallyEqual(args.server, args.base)) {
31404
- return selected(args.rawLocal);
31994
+ return sharedSelection(args.rawLocal);
31405
31995
  }
31406
31996
  if (canonicallyEqual(args.local, args.base)) {
31407
- return selected(args.rawServer);
31997
+ return sharedSelection(args.rawServer);
31408
31998
  }
31409
31999
  if (canonicallyEqual(args.local, args.server)) {
31410
- return selected(args.rawLocal);
32000
+ return sharedSelection(args.rawLocal);
32001
+ }
32002
+ if (!args.recursive) {
32003
+ return conflict(args.path, args.rawLocal, args.rawServer);
31411
32004
  }
31412
- if (!args.recursive) return conflict(args.path);
31413
32005
  if (isObjectRecord2(args.rawBase) && isObjectRecord2(args.rawServer) && isObjectRecord2(args.rawLocal)) {
31414
32006
  const comparisonBase = isObjectRecord2(args.base) ? args.base : args.rawBase;
31415
32007
  const comparisonServer = isObjectRecord2(args.server) ? args.server : args.rawServer;
31416
32008
  const comparisonLocal = isObjectRecord2(args.local) ? args.local : args.rawLocal;
31417
32009
  const value = {};
32010
+ const localVariant = {};
32011
+ const serverVariant = {};
31418
32012
  const conflicts = [];
31419
32013
  const keys = /* @__PURE__ */ new Set([
31420
32014
  ...Object.keys(args.rawBase),
@@ -31434,8 +32028,16 @@ function mergeValue(args) {
31434
32028
  });
31435
32029
  conflicts.push(...nested.conflicts);
31436
32030
  if (nested.present) value[key] = nested.value;
32031
+ if (nested.local.present) localVariant[key] = nested.local.value;
32032
+ if (nested.server.present) serverVariant[key] = nested.server.value;
31437
32033
  }
31438
- return { present: true, value, conflicts };
32034
+ return {
32035
+ present: true,
32036
+ value,
32037
+ local: { present: true, value: localVariant },
32038
+ server: { present: true, value: serverVariant },
32039
+ conflicts
32040
+ };
31439
32041
  }
31440
32042
  if (Array.isArray(args.rawBase) && Array.isArray(args.rawServer) && Array.isArray(args.rawLocal)) {
31441
32043
  return mergeIdentityArray(
@@ -31445,17 +32047,24 @@ function mergeValue(args) {
31445
32047
  args.path
31446
32048
  );
31447
32049
  }
31448
- return conflict(args.path);
32050
+ return conflict(args.path, args.rawLocal, args.rawServer);
31449
32051
  }
31450
32052
  function mergeIdentityArray(base, server, local, path) {
31451
32053
  const baseItems = indexIdentityArray(base);
31452
32054
  const serverItems = indexIdentityArray(server);
31453
32055
  const localItems = indexIdentityArray(local);
31454
32056
  if (baseItems === null || serverItems === null || localItems === null) {
31455
- return conflict(path);
32057
+ return conflict(path, local, server);
31456
32058
  }
31457
- const retained = /* @__PURE__ */ new Map();
32059
+ const mergedValues = /* @__PURE__ */ new Map();
32060
+ const localValues = /* @__PURE__ */ new Map();
32061
+ const serverValues = /* @__PURE__ */ new Map();
31458
32062
  const conflicts = [];
32063
+ const retainShared = (id2, value2) => {
32064
+ mergedValues.set(id2, value2);
32065
+ localValues.set(id2, value2);
32066
+ serverValues.set(id2, value2);
32067
+ };
31459
32068
  const ids = /* @__PURE__ */ new Set([
31460
32069
  ...baseItems.order,
31461
32070
  ...serverItems.order,
@@ -31471,46 +32080,79 @@ function mergeIdentityArray(base, server, local, path) {
31471
32080
  if (baseHas && !serverHas && !localHas) continue;
31472
32081
  if (baseHas && !serverHas) {
31473
32082
  if (canonicallyEqual(localValue, baseValue)) continue;
31474
- conflicts.push(`${path}[${JSON.stringify(id2)}]`);
32083
+ conflicts.push(path + "[" + JSON.stringify(id2) + "]");
32084
+ localValues.set(id2, localValue);
31475
32085
  continue;
31476
32086
  }
31477
32087
  if (baseHas && !localHas) {
31478
32088
  if (canonicallyEqual(serverValue, baseValue)) continue;
31479
- conflicts.push(`${path}[${JSON.stringify(id2)}]`);
32089
+ conflicts.push(path + "[" + JSON.stringify(id2) + "]");
32090
+ serverValues.set(id2, serverValue);
31480
32091
  continue;
31481
32092
  }
31482
32093
  if (!serverHas && localHas) {
31483
- retained.set(id2, localValue);
32094
+ retainShared(id2, localValue);
31484
32095
  continue;
31485
32096
  }
31486
32097
  if (!localHas && serverHas) {
31487
- retained.set(id2, serverValue);
32098
+ retainShared(id2, serverValue);
31488
32099
  continue;
31489
32100
  }
31490
- const merged = mergeValue({
32101
+ const item = mergeValue({
31491
32102
  rawBase: baseValue,
31492
32103
  rawServer: serverValue,
31493
32104
  rawLocal: localValue,
31494
32105
  base: baseValue,
31495
32106
  server: serverValue,
31496
32107
  local: localValue,
31497
- path: `${path}[${JSON.stringify(id2)}]`,
32108
+ path: path + "[" + JSON.stringify(id2) + "]",
31498
32109
  recursive: true
31499
32110
  });
31500
- conflicts.push(...merged.conflicts);
31501
- if (merged.present) retained.set(id2, merged.value);
32111
+ conflicts.push(...item.conflicts);
32112
+ if (item.present) mergedValues.set(id2, item.value);
32113
+ if (item.local.present) localValues.set(id2, item.local.value);
32114
+ if (item.server.present) serverValues.set(id2, item.server.value);
31502
32115
  }
31503
- if (conflicts.length > 0) return { present: true, value: [], conflicts };
31504
- const order = mergeIdentityOrder(
32116
+ const retainedIds = /* @__PURE__ */ new Set([...localValues.keys(), ...serverValues.keys()]);
32117
+ const sharedOrder = mergeIdentityOrder(
32118
+ baseItems.order,
32119
+ serverItems.order,
32120
+ localItems.order,
32121
+ retainedIds
32122
+ );
32123
+ if (sharedOrder === null) conflicts.push(path + ".$order");
32124
+ const localOrder = sharedOrder?.filter((id2) => localValues.has(id2)) ?? completeVariantOrder(
32125
+ localItems.order,
32126
+ serverItems.order,
31505
32127
  baseItems.order,
32128
+ new Set(localValues.keys())
32129
+ );
32130
+ const serverOrder = sharedOrder?.filter((id2) => serverValues.has(id2)) ?? completeVariantOrder(
31506
32131
  serverItems.order,
31507
32132
  localItems.order,
31508
- new Set(retained.keys())
32133
+ baseItems.order,
32134
+ new Set(serverValues.keys())
31509
32135
  );
31510
- if (order === null) return conflict(`${path}.$order`);
32136
+ const localVariant = localOrder.map((id2) => localValues.get(id2));
32137
+ const serverVariant = serverOrder.map((id2) => serverValues.get(id2));
32138
+ if (conflicts.length > 0) {
32139
+ return {
32140
+ present: true,
32141
+ value: [],
32142
+ local: { present: true, value: localVariant },
32143
+ server: { present: true, value: serverVariant },
32144
+ conflicts
32145
+ };
32146
+ }
32147
+ if (sharedOrder === null) {
32148
+ throw new Error("A conflict-free identity merge must have a shared order.");
32149
+ }
32150
+ const value = sharedOrder.map((id2) => mergedValues.get(id2));
31511
32151
  return {
31512
32152
  present: true,
31513
- value: order.map((id2) => retained.get(id2)),
32153
+ value,
32154
+ local: { present: true, value },
32155
+ server: { present: true, value },
31514
32156
  conflicts: []
31515
32157
  };
31516
32158
  }
@@ -31567,11 +32209,51 @@ function mergeIdentityOrder(base, server, local, retained) {
31567
32209
  }
31568
32210
  return result.length === nodes.length ? result : null;
31569
32211
  }
31570
- function selected(value) {
31571
- return value === void 0 ? { present: false, conflicts: [] } : { present: true, value, conflicts: [] };
32212
+ function completeVariantOrder(preferred, fallback, base, retained) {
32213
+ const result = preferred.filter((id2) => retained.has(id2));
32214
+ const included = new Set(result);
32215
+ for (const source of [fallback, base]) {
32216
+ for (let index = 0; index < source.length; index += 1) {
32217
+ const id2 = source[index];
32218
+ if (!retained.has(id2) || included.has(id2)) continue;
32219
+ let insertionIndex = -1;
32220
+ for (let next = index + 1; next < source.length; next += 1) {
32221
+ const nextIndex = result.indexOf(source[next]);
32222
+ if (nextIndex !== -1) {
32223
+ insertionIndex = nextIndex;
32224
+ break;
32225
+ }
32226
+ }
32227
+ if (insertionIndex === -1) {
32228
+ for (let previous = index - 1; previous >= 0; previous -= 1) {
32229
+ const previousIndex = result.indexOf(source[previous]);
32230
+ if (previousIndex !== -1) {
32231
+ insertionIndex = previousIndex + 1;
32232
+ break;
32233
+ }
32234
+ }
32235
+ }
32236
+ if (insertionIndex === -1) insertionIndex = result.length;
32237
+ result.splice(insertionIndex, 0, id2);
32238
+ included.add(id2);
32239
+ }
32240
+ }
32241
+ return result;
31572
32242
  }
31573
- function conflict(path) {
31574
- return { present: false, conflicts: [path] };
32243
+ function selection(value) {
32244
+ return value === void 0 ? { present: false } : { present: true, value };
32245
+ }
32246
+ function sharedSelection(value) {
32247
+ const selected = selection(value);
32248
+ return { ...selected, local: selected, server: selected, conflicts: [] };
32249
+ }
32250
+ function conflict(path, localValue, serverValue) {
32251
+ return {
32252
+ present: false,
32253
+ local: selection(localValue),
32254
+ server: selection(serverValue),
32255
+ conflicts: [path]
32256
+ };
31575
32257
  }
31576
32258
  var init_merge = __esm({
31577
32259
  "src/project-sync/merge.ts"() {
@@ -32297,10 +32979,7 @@ function memberToDocumentFields(member, baseData3) {
32297
32979
  }
32298
32980
  if (member.kind === "function" || member.kind === "scriptFunction") {
32299
32981
  fields.returnTypeInfo = manifestReturnTypeToDocument(member.returnType);
32300
- fields.argumentTypes = member.arguments.map((argument2) => ({
32301
- name: argument2.name,
32302
- ...manifestTypeToDocument(argument2.type)
32303
- }));
32982
+ fields.argumentTypes = member.arguments.map(manifestArgumentToDocument);
32304
32983
  fields.deferred = member.deferred;
32305
32984
  if (member.kind === "scriptFunction" && member.script !== null && member.bodyMode !== "ui") {
32306
32985
  fields.code = member.script.sourceText;
@@ -32312,16 +32991,10 @@ function memberToDocumentFields(member, baseData3) {
32312
32991
  }
32313
32992
  if (member.kind === "delegate") {
32314
32993
  fields.returnTypeInfo = manifestReturnTypeToDocument(member.returnType);
32315
- fields.argumentTypes = member.arguments.map((argument2) => ({
32316
- name: argument2.name,
32317
- ...manifestTypeToDocument(argument2.type)
32318
- }));
32994
+ fields.argumentTypes = member.arguments.map(manifestArgumentToDocument);
32319
32995
  }
32320
32996
  if (member.kind === "action") {
32321
- fields.argumentTypes = member.arguments.map((argument2) => ({
32322
- name: argument2.name,
32323
- ...manifestTypeToDocument(argument2.type)
32324
- }));
32997
+ fields.argumentTypes = member.arguments.map(manifestArgumentToDocument);
32325
32998
  }
32326
32999
  if (member.kind === "generic") {
32327
33000
  fields.genericParamId = member.genericParamId;
@@ -32411,11 +33084,25 @@ function documentArgumentsToManifest(value, record3, source) {
32411
33084
  `argumentTypes[${index}].name`
32412
33085
  ),
32413
33086
  type: documentTypeToManifest(argument2, record3, `argumentTypes[${index}]`),
33087
+ default: documentParameterDefaultToManifest(
33088
+ argument2.defaultValue,
33089
+ record3,
33090
+ `argumentTypes[${index}].defaultValue`,
33091
+ source
33092
+ ),
32414
33093
  source,
32415
33094
  selectionSpan: source
32416
33095
  };
32417
33096
  });
32418
33097
  }
33098
+ function documentParameterDefaultToManifest(value, record3, path, source) {
33099
+ if (value === void 0 || value === null) return null;
33100
+ const wrapper = requireRecordValue(value, record3, path);
33101
+ if (!Object.hasOwn(wrapper, "value")) {
33102
+ throw invalidDocument(record3, path, 'must carry a "value" key');
33103
+ }
33104
+ return { value: wrapper.value, source };
33105
+ }
32419
33106
  function optionalDocumentType(value, record3, path) {
32420
33107
  if (value === null || value === void 0) return null;
32421
33108
  return documentTypeToManifest(value, record3, path);
@@ -32564,6 +33251,13 @@ function documentTypeToManifest(value, record3, path) {
32564
33251
  `unsupported type-info discriminator ${kind}`
32565
33252
  );
32566
33253
  }
33254
+ function manifestArgumentToDocument(argument2) {
33255
+ return {
33256
+ name: argument2.name,
33257
+ ...manifestTypeToDocument(argument2.type),
33258
+ ...argument2.default === null ? {} : { defaultValue: { value: argument2.default.value } }
33259
+ };
33260
+ }
32567
33261
  function manifestReturnTypeToDocument(type) {
32568
33262
  if (type.kind === "void") return { type: "Void", required: true };
32569
33263
  return manifestTypeToDocument(type);
@@ -33303,10 +33997,7 @@ function interfaceToDocument(neoInterface) {
33303
33997
  kind: "function",
33304
33998
  ...member.docsText === void 0 ? {} : { docsText: member.docsText },
33305
33999
  returnTypeInfo: manifestReturnTypeToDocument(member.returnType),
33306
- argumentTypes: member.arguments.map((argument2) => ({
33307
- name: argument2.name,
33308
- ...manifestTypeToDocument(argument2.type)
33309
- })),
34000
+ argumentTypes: member.arguments.map(manifestArgumentToDocument),
33310
34001
  deferred: member.deferred,
33311
34002
  accessModifierKind: member.accessModifier
33312
34003
  };
@@ -33805,10 +34496,7 @@ function constructorToDocument(declared) {
33805
34496
  return omitUndefined({
33806
34497
  id: declared.id,
33807
34498
  classId: declared.classId,
33808
- argumentTypes: declared.arguments.map((argument2) => ({
33809
- name: argument2.name,
33810
- ...manifestTypeToDocument(argument2.type)
33811
- })),
34499
+ argumentTypes: declared.arguments.map(manifestArgumentToDocument),
33812
34500
  code: declared.code,
33813
34501
  baseArguments: declared.baseArguments,
33814
34502
  baseInitializerFields: declared.baseInitializerFields,
@@ -35464,14 +36152,22 @@ function assertFunctionArgument(value, path) {
35464
36152
  const argument2 = objectAt(value, path, [
35465
36153
  "name",
35466
36154
  "type",
36155
+ "default",
35467
36156
  "source",
35468
36157
  "selectionSpan"
35469
36158
  ]);
35470
36159
  nonEmptyString(argument2.name, `${path}.name`);
35471
36160
  assertType2(argument2.type, `${path}.type`);
36161
+ assertParameterDefault(argument2.default, `${path}.default`);
35472
36162
  assertSpan(argument2.source, `${path}.source`);
35473
36163
  assertSpan(argument2.selectionSpan, `${path}.selectionSpan`);
35474
36164
  }
36165
+ function assertParameterDefault(value, path) {
36166
+ if (value === null) return;
36167
+ const parameterDefault = objectAt(value, path, ["value", "source"]);
36168
+ assertJsonValue(parameterDefault.value, `${path}.value`, 0);
36169
+ assertSpan(parameterDefault.source, `${path}.source`);
36170
+ }
35475
36171
  function assertAbstractScriptInvariant(value, path) {
35476
36172
  const isAbstract = value.modifier === "abstract" || value.modifier === "abstractOverride";
35477
36173
  const hasUiBody = value.bodyMode === "ui" && value.uiAction !== void 0;
@@ -37685,7 +38381,30 @@ function isNSFunctionReturnTypeInfo(value) {
37685
38381
  return isNSTypeInfo(value) || isNSTypeInfoVoid(value);
37686
38382
  }
37687
38383
  function isNSFunctionArgumentTypeInfo(value) {
37688
- return isNSArgumentTypeInfo(value) && !typeInfoContainsUnknown(value, /* @__PURE__ */ new Set());
38384
+ return isNSArgumentTypeInfo(value) && !typeInfoContainsUnknown(value, /* @__PURE__ */ new Set()) && hasValidParameterDefault(value);
38385
+ }
38386
+ function hasValidParameterDefault(value) {
38387
+ const wrapper = value.defaultValue;
38388
+ if (wrapper === void 0) return true;
38389
+ if (typeof wrapper !== "object" || wrapper === null) return false;
38390
+ const keys = Object.keys(wrapper);
38391
+ if (keys.length !== 1 || keys[0] !== "value") return false;
38392
+ const payload = wrapper.value;
38393
+ if (payload === null) return !value.required;
38394
+ switch (value.type) {
38395
+ case 1 /* Bool */:
38396
+ return typeof payload === "boolean";
38397
+ case 2 /* Int */:
38398
+ return typeof payload === "number" && Number.isInteger(payload);
38399
+ case 4 /* Float */:
38400
+ return typeof payload === "number" && Number.isFinite(payload);
38401
+ case 20 /* Decimal */:
38402
+ case 3 /* String */:
38403
+ case 8 /* Enum */:
38404
+ return typeof payload === "string";
38405
+ default:
38406
+ return false;
38407
+ }
37689
38408
  }
37690
38409
  function typeInfoContainsUnknown(value, ancestors) {
37691
38410
  if (value.type === NS_TYPE_UNKNOWN) return true;
@@ -38486,6 +39205,51 @@ var init_neoscript_guards = __esm({
38486
39205
  }
38487
39206
  });
38488
39207
 
39208
+ // ../src/models/neoscript/parameter-defaults.ts
39209
+ function parameterHasDefault(argument2) {
39210
+ return argument2.defaultValue !== void 0;
39211
+ }
39212
+ function hasAnyParameterDefault(argumentTypes) {
39213
+ return argumentTypes.some(parameterHasDefault);
39214
+ }
39215
+ function validateParameterDefaults(argumentTypes) {
39216
+ const violations = [];
39217
+ let lastNonDefaultedIndex = -1;
39218
+ for (let index = argumentTypes.length - 1; index >= 0; index -= 1) {
39219
+ const argument2 = argumentTypes[index];
39220
+ if (argument2 !== void 0 && !parameterHasDefault(argument2)) {
39221
+ lastNonDefaultedIndex = index;
39222
+ break;
39223
+ }
39224
+ }
39225
+ for (let index = 0; index < argumentTypes.length; index += 1) {
39226
+ const argument2 = argumentTypes[index];
39227
+ if (argument2 === void 0) continue;
39228
+ const defaultValue = argument2.defaultValue;
39229
+ if (defaultValue === void 0) continue;
39230
+ if (index < lastNonDefaultedIndex) {
39231
+ violations.push({
39232
+ code: "default-before-required-parameter",
39233
+ index,
39234
+ name: argument2.name
39235
+ });
39236
+ }
39237
+ if (defaultValue.value === null && argument2.required) {
39238
+ violations.push({
39239
+ code: "parameter-default-type-mismatch",
39240
+ index,
39241
+ name: argument2.name
39242
+ });
39243
+ }
39244
+ }
39245
+ return violations;
39246
+ }
39247
+ var init_parameter_defaults = __esm({
39248
+ "../src/models/neoscript/parameter-defaults.ts"() {
39249
+ "use strict";
39250
+ }
39251
+ });
39252
+
38489
39253
  // ../src/models/interfaces/interface-graph.ts
38490
39254
  function resolveInterfaceClosure(interfaceId, interfaces) {
38491
39255
  const byId = new Map(
@@ -38622,6 +39386,7 @@ var init_neoscript = __esm({
38622
39386
  "use strict";
38623
39387
  init_neoscript_types();
38624
39388
  init_neoscript_guards();
39389
+ init_parameter_defaults();
38625
39390
  init_type_info_compatibility();
38626
39391
  }
38627
39392
  });
@@ -39280,14 +40045,20 @@ function isMemberFunctionBase(value) {
39280
40045
  if (!Array.isArray(v.argumentTypes)) return false;
39281
40046
  if (typeof v.deferred !== "boolean") return false;
39282
40047
  const names = /* @__PURE__ */ new Set();
40048
+ const argumentTypes = [];
39283
40049
  for (const arg of v.argumentTypes) {
39284
40050
  if (!isNSFunctionArgumentTypeInfo(arg)) return false;
39285
40051
  if (!isValidCallableIdentifier(arg.name)) return false;
39286
40052
  if (arg.type === NS_TYPE_UNKNOWN) return false;
39287
40053
  if (names.has(arg.name)) return false;
39288
40054
  names.add(arg.name);
40055
+ argumentTypes.push(arg);
39289
40056
  }
39290
- return true;
40057
+ return hasValidParameterDefaults(argumentTypes, v.deferred);
40058
+ }
40059
+ function hasValidParameterDefaults(argumentTypes, deferred) {
40060
+ if (deferred && hasAnyParameterDefault(argumentTypes)) return false;
40061
+ return validateParameterDefaults(argumentTypes).length === 0;
39291
40062
  }
39292
40063
  function normalizedCompiledFunctionReturnType(typeInfo) {
39293
40064
  if (typeInfo.type === NS_TYPE_VOID) {
@@ -39335,6 +40106,7 @@ function isMemberNSFunctionBase(value) {
39335
40106
  if (v.action !== void 0 && v.action !== null) return false;
39336
40107
  if (v.bodyMode !== void 0 && v.bodyMode !== "ui") return false;
39337
40108
  const names = /* @__PURE__ */ new Set();
40109
+ const argumentTypes = [];
39338
40110
  for (const argument2 of v.argumentTypes) {
39339
40111
  if (!isNSFunctionArgumentTypeInfo(argument2)) return false;
39340
40112
  if (argument2.type === NS_TYPE_UNKNOWN) return false;
@@ -39342,7 +40114,9 @@ function isMemberNSFunctionBase(value) {
39342
40114
  if (NSFunctionArgumentReservedNames.has(argument2.name)) return false;
39343
40115
  if (names.has(argument2.name)) return false;
39344
40116
  names.add(argument2.name);
40117
+ argumentTypes.push(argument2);
39345
40118
  }
40119
+ if (!hasValidParameterDefaults(argumentTypes, v.deferred)) return false;
39346
40120
  if (v.isAbstract === true) {
39347
40121
  if (v.bodyMode !== void 0) return false;
39348
40122
  if (v.uiAction !== void 0 && v.uiAction !== null) return false;
@@ -39419,6 +40193,7 @@ function isMemberDelegateBase(value) {
39419
40193
  if (argument2.type === NS_TYPE_UNKNOWN) return false;
39420
40194
  if (names.has(argument2.name)) return false;
39421
40195
  names.add(argument2.name);
40196
+ if (argument2.defaultValue !== void 0) return false;
39422
40197
  }
39423
40198
  const defaultValue = v.defaultValue;
39424
40199
  if (defaultValue === void 0 || defaultValue === null) return true;
@@ -39457,6 +40232,7 @@ function isMemberActionBase(value) {
39457
40232
  if (argument2.type === NS_TYPE_UNKNOWN) return false;
39458
40233
  if (names.has(argument2.name)) return false;
39459
40234
  names.add(argument2.name);
40235
+ if (argument2.defaultValue !== void 0) return false;
39460
40236
  }
39461
40237
  const defaultValue = v.defaultValue;
39462
40238
  if (defaultValue === void 0 || defaultValue === null) return true;
@@ -39688,6 +40464,7 @@ function isMemberOverrideBase(value) {
39688
40464
  if (v.argumentTypes !== void 0) {
39689
40465
  if (!Array.isArray(v.argumentTypes)) return false;
39690
40466
  if (!v.argumentTypes.every(isNSFunctionArgumentTypeInfo)) return false;
40467
+ if (hasAnyParameterDefault(v.argumentTypes)) return false;
39691
40468
  }
39692
40469
  if (v.deferred !== void 0 && typeof v.deferred !== "boolean") {
39693
40470
  return false;
@@ -43566,7 +44343,11 @@ function isNeoInterfaceMember(value) {
43566
44343
  if (!isNSFunctionArgumentTypeInfo(argumentType)) return false;
43567
44344
  if (containsForbiddenMemberTypeInfo(argumentType)) return false;
43568
44345
  }
43569
- return typeof member.deferred === "boolean";
44346
+ if (typeof member.deferred !== "boolean") return false;
44347
+ if (member.deferred && hasAnyParameterDefault(member.argumentTypes)) {
44348
+ return false;
44349
+ }
44350
+ return validateParameterDefaults(member.argumentTypes).length === 0;
43570
44351
  }
43571
44352
  function isInterfaceMembersRecord(value) {
43572
44353
  if (typeof value !== "object") return false;
@@ -43634,6 +44415,7 @@ var init_interface_types = __esm({
43634
44415
  init_neoscript_types();
43635
44416
  init_docs_text2();
43636
44417
  init_neoscript_guards();
44418
+ init_parameter_defaults();
43637
44419
  init_member_kinds();
43638
44420
  }
43639
44421
  });
@@ -45952,11 +46734,46 @@ function baseConstruction(requiredConstructor) {
45952
46734
  function renderHeaderParameters(context, requiredConstructor) {
45953
46735
  if (requiredConstructor === void 0) return "";
45954
46736
  const parameters = requiredConstructor.arguments.map(
45955
- (argument2) => `${renderType(context, argument2.type)} ${argument2.name}`
46737
+ (argument2) => renderParameter(context, argument2)
45956
46738
  );
45957
46739
  if (parameters.length === 0 && requiredConstructor.code !== null) return "";
45958
46740
  return `(${parameters.join(", ")})`;
45959
46741
  }
46742
+ function renderParameter(context, argument2) {
46743
+ const declaration = `${renderType(context, argument2.type)} ${argument2.name}`;
46744
+ if (argument2.default === null) return declaration;
46745
+ return `${declaration} = ${renderParameterDefault(context, argument2)}`;
46746
+ }
46747
+ function renderParameterDefault(context, argument2) {
46748
+ const value = argument2.default?.value;
46749
+ if (value === null || value === void 0) return "null";
46750
+ if (argument2.type.kind === "enum") {
46751
+ if (typeof value !== "string") {
46752
+ throw new Error(
46753
+ `Parameter ${argument2.name} stores an enum default that is not an option id.`
46754
+ );
46755
+ }
46756
+ const schemaEnum = required(context.enums, argument2.type.enumId, "enum");
46757
+ const option = schemaEnum.options.find(
46758
+ (candidate) => candidate.id === value || candidate.key === value
46759
+ );
46760
+ if (option === void 0) {
46761
+ throw new Error(
46762
+ `Parameter ${argument2.name} defaults to option id ${quote(value)}, which its enum does not declare. Emitting it as null would delete the default on the next push.`
46763
+ );
46764
+ }
46765
+ return `.${option.name}`;
46766
+ }
46767
+ if (argument2.type.kind === "decimal" && typeof value === "string") {
46768
+ return value;
46769
+ }
46770
+ if (typeof value === "string") return quote(value);
46771
+ if (typeof value === "number") return formatNeoNumber(value);
46772
+ if (typeof value === "boolean") return String(value);
46773
+ throw new Error(
46774
+ `Parameter ${argument2.name} stores a default that is not a constant value.`
46775
+ );
46776
+ }
45960
46777
  function emitInitBlock(code) {
45961
46778
  if (code.trim().length === 0) return "init {\n}";
45962
46779
  return `init {
@@ -45971,7 +46788,7 @@ function emitConstructor(context, schemaClass2, declared) {
45971
46788
  ...docsTextLines(declared.docsText),
45972
46789
  id(declared.id).trimEnd()
45973
46790
  ];
45974
- const parameters = declared.arguments.map((argument2) => `${renderType(context, argument2.type)} ${argument2.name}`).join(", ");
46791
+ const parameters = declared.arguments.map((argument2) => renderParameter(context, argument2)).join(", ");
45975
46792
  const baseClause = declared.baseArguments === void 0 || declared.baseArguments.length === 0 ? "" : `
45976
46793
  : base(${declared.baseArguments.map((argument2) => `${argument2.name}: ${argument2.code}`).join(", ")})`;
45977
46794
  const code = declared.code ?? "";
@@ -46041,9 +46858,7 @@ function emitInterface(context, value) {
46041
46858
  return `${emitDocsText(member.docsText)}${id(member.id)}${access}${renderType(context, member.type)} ${member.name} { get;${member.settable ? " set;" : ""} }`;
46042
46859
  }
46043
46860
  const deferred = member.deferred ? "async " : "";
46044
- return `${emitDocsText(member.docsText)}${id(member.id)}${access}${deferred}${renderReturnType(context, member.returnType)} ${member.name}(${member.arguments.map(
46045
- (argument2) => `${renderType(context, argument2.type)} ${argument2.name}`
46046
- ).join(", ")});`;
46861
+ return `${emitDocsText(member.docsText)}${id(member.id)}${access}${deferred}${renderReturnType(context, member.returnType)} ${member.name}(${member.arguments.map((argument2) => renderParameter(context, argument2)).join(", ")});`;
46047
46862
  });
46048
46863
  return `${emitDocsText(value.docsText)}${id(value.id)}interface ${value.name}${bases.length ? ` : ${bases.join(", ")}` : ""} {
46049
46864
  ${members.map((member) => indentNeoSourceNonEmptyLines(member, 2)).join("\n\n")}
@@ -46091,9 +46906,7 @@ ${indentNeoSourceNonEmptyLines(setter, 4)}
46091
46906
  ${prefix}${renderType(context, member.returnType)} ${member.name}${body}`;
46092
46907
  }
46093
46908
  if (member.kind === "function" || member.kind === "scriptFunction") {
46094
- const signature = `${prefix}${member.deferred ? "async " : ""}${renderReturnType(context, member.returnType)} ${member.name}(${member.arguments.map(
46095
- (argument2) => `${renderType(context, argument2.type)} ${argument2.name}`
46096
- ).join(", ")})`;
46909
+ const signature = `${prefix}${member.deferred ? "async " : ""}${renderReturnType(context, member.returnType)} ${member.name}(${member.arguments.map((argument2) => renderParameter(context, argument2)).join(", ")})`;
46097
46910
  const tracked = member.kind === "scriptFunction" ? member.script?.sourceText ?? uiFunctionSource(context, member) : null;
46098
46911
  const body = tracked === null ? null : emitFunctionBody(tracked);
46099
46912
  const abstractContract = member.modifier === "abstract" || member.modifier === "abstractOverride";
@@ -51176,13 +51989,13 @@ function withPersistedConstructorSignatures(index, classes, constructors) {
51176
51989
  if (required2 !== void 0) {
51177
51990
  persistedRequiredByClassName.set(
51178
51991
  schemaClass2.name,
51179
- required2.arguments.map((argument2) => argument2.name)
51992
+ required2.arguments.map(persistedParameter)
51180
51993
  );
51181
51994
  }
51182
51995
  }
51183
51996
  const overloads = (schemaClass2.constructorIds ?? []).flatMap((id2) => {
51184
51997
  const constructor2 = byId.get(id2);
51185
- return constructor2 === void 0 ? [] : [constructor2.arguments.map((argument2) => argument2.name)];
51998
+ return constructor2 === void 0 ? [] : [constructor2.arguments.map(persistedParameter)];
51186
51999
  });
51187
52000
  if (overloads.length > 0) {
51188
52001
  persistedByClassName.set(schemaClass2.name, overloads);
@@ -51194,6 +52007,10 @@ function withPersistedConstructorSignatures(index, classes, constructors) {
51194
52007
  persistedRequiredByClassName
51195
52008
  };
51196
52009
  }
52010
+ function persistedParameter(argument2) {
52011
+ const hasDefault = argument2.default !== null && argument2.default !== void 0;
52012
+ return { name: argument2.name, defaulted: hasDefault };
52013
+ }
51197
52014
  function declaresConstructors(index, className) {
51198
52015
  if (className === null) return false;
51199
52016
  if (index.requiredByClassName.has(className)) return true;
@@ -51203,16 +52020,24 @@ function declaresConstructors(index, className) {
51203
52020
  function declaresParameterlessConstructor(index, className) {
51204
52021
  if (className === null) return false;
51205
52022
  const required2 = index.requiredByClassName.get(className);
51206
- if (required2 !== void 0 && required2.parameters.length === 0) return true;
52023
+ if (required2 !== void 0 && manifestListIsCallableBare(required2.parameters)) {
52024
+ return true;
52025
+ }
51207
52026
  const persistedRequired = index.persistedRequiredByClassName.get(className);
51208
- if (persistedRequired !== void 0 && persistedRequired.length === 0) {
52027
+ if (persistedRequired !== void 0 && persistedListIsCallableBare(persistedRequired)) {
51209
52028
  return true;
51210
52029
  }
51211
52030
  const declared = index.byClassName.get(className);
51212
- if (declared?.some((entry) => entry.parameters.length === 0) === true) {
52031
+ if (declared?.some((entry) => manifestListIsCallableBare(entry.parameters)) === true) {
51213
52032
  return true;
51214
52033
  }
51215
- return index.persistedByClassName.get(className)?.some((parameters) => parameters.length === 0) ?? false;
52034
+ return index.persistedByClassName.get(className)?.some(persistedListIsCallableBare) ?? false;
52035
+ }
52036
+ function manifestListIsCallableBare(parameters) {
52037
+ return parameters.every((parameter4) => parameter4.default !== null);
52038
+ }
52039
+ function persistedListIsCallableBare(parameters) {
52040
+ return parameters.every((parameter4) => parameter4.defaulted);
51216
52041
  }
51217
52042
  function initializerRequiresEvaluation(index, expression, targetClassName, runtimeIdentifiers = /* @__PURE__ */ new Set()) {
51218
52043
  if (expression.kind === "annotated") {
@@ -51242,7 +52067,11 @@ function requiredConstructorParameterNames(index, className) {
51242
52067
  if (required2 !== void 0) {
51243
52068
  return new Set(required2.parameters.map((parameter4) => parameter4.name));
51244
52069
  }
51245
- return new Set(index.persistedRequiredByClassName.get(className) ?? []);
52070
+ return new Set(
52071
+ (index.persistedRequiredByClassName.get(className) ?? []).map(
52072
+ (parameter4) => parameter4.name
52073
+ )
52074
+ );
51246
52075
  }
51247
52076
  function expressionReadsRuntimeIdentifier(expression, runtimeIdentifiers) {
51248
52077
  if (runtimeIdentifiers.size === 0) return false;
@@ -51334,7 +52163,8 @@ function validateDeclaredConstructorOverloads(declaration) {
51334
52163
  id: declared.id ?? `${declaration.name}#${String(index)}`,
51335
52164
  parameters: declared.parameters.map((parameter4) => ({
51336
52165
  name: parameter4.name,
51337
- typeKey: positionalTypeKey(parameter4.type)
52166
+ typeKey: positionalTypeKey(parameter4.type),
52167
+ defaulted: parameter4.default !== null
51338
52168
  }))
51339
52169
  }))
51340
52170
  ).map((error) => ({
@@ -51360,6 +52190,102 @@ var init_declared_constructors2 = __esm({
51360
52190
  }
51361
52191
  });
51362
52192
 
52193
+ // src/project-source/lower-parameter-defaults.ts
52194
+ function lowerParameterDefault(context, parameter4, loweredType, path) {
52195
+ if (parameter4.default === null) return null;
52196
+ const expression = parseExpression(parameter4.default);
52197
+ return {
52198
+ value: lowerParameterDefaultValue(context, expression, loweredType, path),
52199
+ source: span({ source: parameter4.source })
52200
+ };
52201
+ }
52202
+ function lowerParameterDefaultValue(context, expression, type, path) {
52203
+ switch (expression.kind) {
52204
+ case "litNull":
52205
+ if (!type.nullable) {
52206
+ throw new Error(
52207
+ `Parameter ${path} defaults to null, but its type is not nullable.`
52208
+ );
52209
+ }
52210
+ return null;
52211
+ case "litBool":
52212
+ if (type.kind !== "bool") {
52213
+ throw new Error(
52214
+ `Parameter ${path} defaults to a bool literal, but its type is ${type.kind}.`
52215
+ );
52216
+ }
52217
+ return expression.value;
52218
+ case "litString":
52219
+ if (type.kind !== "string") {
52220
+ throw new Error(
52221
+ `Parameter ${path} defaults to a string literal, but its type is ${type.kind}.`
52222
+ );
52223
+ }
52224
+ return expression.value;
52225
+ case "litInt":
52226
+ if (type.kind === "decimal") return expression.raw;
52227
+ if (type.kind !== "int" && type.kind !== "float") {
52228
+ throw new Error(
52229
+ `Parameter ${path} defaults to a number literal, but its type is ${type.kind}.`
52230
+ );
52231
+ }
52232
+ return expression.value;
52233
+ case "litFloat":
52234
+ if (type.kind === "decimal") return expression.raw;
52235
+ if (type.kind !== "float") {
52236
+ throw new Error(
52237
+ `Parameter ${path} defaults to a fractional literal, but its type is ${type.kind}.`
52238
+ );
52239
+ }
52240
+ return expression.value;
52241
+ case "unary": {
52242
+ if (expression.op !== "-") {
52243
+ throw new Error(
52244
+ `Parameter ${path} default uses unary ${JSON.stringify(expression.op)}, which is not a constant spelling.`
52245
+ );
52246
+ }
52247
+ const operand = lowerParameterDefaultValue(
52248
+ context,
52249
+ expression.operand,
52250
+ type,
52251
+ path
52252
+ );
52253
+ if (typeof operand === "number") return -operand;
52254
+ if (type.kind === "decimal" && typeof operand === "string") {
52255
+ return operand.startsWith("-") ? operand.slice(1) : `-${operand}`;
52256
+ }
52257
+ throw new Error(
52258
+ `Parameter ${path} default applies unary minus to a non-numeric literal.`
52259
+ );
52260
+ }
52261
+ case "contextualEnum": {
52262
+ if (type.kind !== "enum") {
52263
+ throw new Error(
52264
+ `Parameter ${path} defaults to enum option .${expression.name}, but its type is ${type.kind}.`
52265
+ );
52266
+ }
52267
+ const optionId = context.enumOptionsByName.get(type.enumId)?.get(expression.name);
52268
+ if (optionId === void 0) {
52269
+ throw new Error(
52270
+ `Parameter ${path} defaults to .${expression.name}, which its enum does not declare.`
52271
+ );
52272
+ }
52273
+ return optionId;
52274
+ }
52275
+ default:
52276
+ throw new Error(
52277
+ `Parameter ${path} default is not a constant expression.`
52278
+ );
52279
+ }
52280
+ }
52281
+ var init_lower_parameter_defaults = __esm({
52282
+ "src/project-source/lower-parameter-defaults.ts"() {
52283
+ "use strict";
52284
+ init_src();
52285
+ init_lower_support();
52286
+ }
52287
+ });
52288
+
51363
52289
  // src/project-source/init-source.ts
51364
52290
  function commentEndIndex(source, index) {
51365
52291
  if (source[index] !== "/") return null;
@@ -51596,12 +52522,21 @@ function lowerClassConstructors(context, declaration, classId, lowerParameterTyp
51596
52522
  const declared = declaration.constructors.map((declared2) => {
51597
52523
  const id2 = declaredConstructorId2(declaration, declared2);
51598
52524
  const base = context.baseConstructors.get(id2);
51599
- const parameters = declared2.parameters.map((parameter4) => ({
51600
- name: parameter4.name,
51601
- type: lowerParameterType(parameter4.type, declaration),
51602
- source: span({ source: parameter4.source }),
51603
- selectionSpan: span({ source: parameter4.source })
51604
- }));
52525
+ const parameters = declared2.parameters.map((parameter4) => {
52526
+ const parameterType = lowerParameterType(parameter4.type, declaration);
52527
+ return {
52528
+ name: parameter4.name,
52529
+ type: parameterType,
52530
+ default: lowerParameterDefault(
52531
+ context,
52532
+ parameter4,
52533
+ parameterType,
52534
+ `${declaration.name}.${declared2.name}(${parameter4.name})`
52535
+ ),
52536
+ source: span({ source: parameter4.source }),
52537
+ selectionSpan: span({ source: parameter4.source })
52538
+ };
52539
+ });
51605
52540
  const baseArguments = (declared2.baseArguments ?? []).map((argument2) => ({
51606
52541
  name: argument2.name,
51607
52542
  code: argument2.expression.trim()
@@ -51642,12 +52577,21 @@ function lowerRequiredConstructor(context, declaration, classId, lowerParameterT
51642
52577
  selectionSpan: sourceSpan
51643
52578
  },
51644
52579
  classId,
51645
- arguments: required2.parameters.map((parameter4) => ({
51646
- name: parameter4.name,
51647
- type: lowerParameterType(parameter4.type, declaration),
51648
- source: span({ source: parameter4.source }),
51649
- selectionSpan: span({ source: parameter4.source })
51650
- })),
52580
+ arguments: required2.parameters.map((parameter4) => {
52581
+ const parameterType = lowerParameterType(parameter4.type, declaration);
52582
+ return {
52583
+ name: parameter4.name,
52584
+ type: parameterType,
52585
+ default: lowerParameterDefault(
52586
+ context,
52587
+ parameter4,
52588
+ parameterType,
52589
+ `${declaration.name}(${parameter4.name})`
52590
+ ),
52591
+ source: span({ source: parameter4.source }),
52592
+ selectionSpan: span({ source: parameter4.source })
52593
+ };
52594
+ }),
51651
52595
  code: requiredConstructorBody(required2.body, base?.code),
51652
52596
  ...baseArguments.length === 0 ? {} : {
51653
52597
  baseArguments: baseArguments.map(
@@ -51702,13 +52646,13 @@ function sourceBaseParameterNames(context, baseName, suppliedNames) {
51702
52646
  return required2.parameters.map((parameter4) => parameter4.name);
51703
52647
  }
51704
52648
  const declared = context.declaredConstructors.byClassName.get(baseName) ?? [];
51705
- const selected2 = selectOverload(
52649
+ const selected = selectOverload(
51706
52650
  declared.map(
51707
52651
  (constructor2) => constructor2.parameters.map((parameter4) => parameter4.name)
51708
52652
  ),
51709
52653
  suppliedNames
51710
52654
  );
51711
- return selected2;
52655
+ return selected;
51712
52656
  }
51713
52657
  function recordBaseParameterNames(context, baseName, suppliedNames) {
51714
52658
  const baseClassId = context.classIdsByName.get(baseName);
@@ -51730,10 +52674,10 @@ function recordBaseParameterNames(context, baseName, suppliedNames) {
51730
52674
  function selectOverload(candidates, suppliedNames) {
51731
52675
  if (candidates.length === 0) return null;
51732
52676
  if (candidates.length === 1) return candidates[0];
51733
- const key = argumentNameSetKey2(suppliedNames);
51734
- return candidates.find((names) => argumentNameSetKey2(names) === key) ?? null;
52677
+ const key = argumentNameSetKey(suppliedNames);
52678
+ return candidates.find((names) => argumentNameSetKey(names) === key) ?? null;
51735
52679
  }
51736
- function argumentNameSetKey2(names) {
52680
+ function argumentNameSetKey(names) {
51737
52681
  return [...names].map((name) => name.toLowerCase()).sort().join(",");
51738
52682
  }
51739
52683
  function baseTypeName(declaration) {
@@ -51772,6 +52716,7 @@ var init_lower_constructors = __esm({
51772
52716
  init_src();
51773
52717
  init_required_constructor_id();
51774
52718
  init_declared_constructors2();
52719
+ init_lower_parameter_defaults();
51775
52720
  init_init_source();
51776
52721
  init_lower_support();
51777
52722
  }
@@ -52119,12 +53064,21 @@ function lowerMemberKind(context, ownerClass, declaration, id2, owner) {
52119
53064
  if (declaration.kind === "function") {
52120
53065
  const returnType = declaration.type.name === "void" ? { kind: "void", nullable: false } : lowerType(context, declaration.type, ownerClass);
52121
53066
  const argumentsValue = declaration.parameters.map(
52122
- (parameter4) => ({
52123
- name: parameter4.name,
52124
- type: lowerType(context, parameter4.type, ownerClass),
52125
- source: span(parameter4),
52126
- selectionSpan: span(parameter4)
52127
- })
53067
+ (parameter4) => {
53068
+ const parameterType = lowerType(context, parameter4.type, ownerClass);
53069
+ return {
53070
+ name: parameter4.name,
53071
+ type: parameterType,
53072
+ default: lowerParameterDefault(
53073
+ context,
53074
+ parameter4,
53075
+ parameterType,
53076
+ `${ownerClass.name}.${declaration.name}(${parameter4.name})`
53077
+ ),
53078
+ source: span(parameter4),
53079
+ selectionSpan: span(parameter4)
53080
+ };
53081
+ }
52128
53082
  );
52129
53083
  const settings = annotation(declaration.annotations, "settings");
52130
53084
  const logicMode = contextualEnumArgument(settings, "logic");
@@ -52354,6 +53308,7 @@ function lowerFieldMember(context, ownerClass, declaration, id2, commonInput, ba
52354
53308
  arguments: fieldType.arguments.slice(1).map((argumentType, index) => ({
52355
53309
  name: `p${index + 1}`,
52356
53310
  type: lowerType(context, argumentType, ownerClass),
53311
+ default: null,
52357
53312
  source: span(declaration),
52358
53313
  selectionSpan: span(declaration)
52359
53314
  }))
@@ -52378,6 +53333,7 @@ function lowerFieldMember(context, ownerClass, declaration, id2, commonInput, ba
52378
53333
  arguments: fieldType.arguments.map((argumentType, index) => ({
52379
53334
  name: `p${index + 1}`,
52380
53335
  type: lowerType(context, argumentType, ownerClass),
53336
+ default: null,
52381
53337
  source: span(declaration),
52382
53338
  selectionSpan: span(declaration)
52383
53339
  }))
@@ -52837,12 +53793,21 @@ function lowerInterface(context, declaration) {
52837
53793
  name: member.name,
52838
53794
  ...member.docsText === void 0 ? {} : { docsText: member.docsText },
52839
53795
  returnType: member.type.name === "void" ? { kind: "void", nullable: false } : lowerType(context, member.type),
52840
- arguments: member.parameters.map((parameter4) => ({
52841
- name: parameter4.name,
52842
- type: lowerType(context, parameter4.type),
52843
- source: span(parameter4),
52844
- selectionSpan: span(parameter4)
52845
- })),
53796
+ arguments: member.parameters.map((parameter4) => {
53797
+ const parameterType = lowerType(context, parameter4.type);
53798
+ return {
53799
+ name: parameter4.name,
53800
+ type: parameterType,
53801
+ default: lowerParameterDefault(
53802
+ context,
53803
+ parameter4,
53804
+ parameterType,
53805
+ `${declaration.name}.${member.name}(${parameter4.name})`
53806
+ ),
53807
+ source: span(parameter4),
53808
+ selectionSpan: span(parameter4)
53809
+ };
53810
+ }),
52846
53811
  deferred: member.modifiers.includes("async"),
52847
53812
  accessModifier,
52848
53813
  source
@@ -54160,6 +55125,7 @@ var init_lower_members = __esm({
54160
55125
  init_src();
54161
55126
  init_lower_support();
54162
55127
  init_lower_constructors();
55128
+ init_lower_parameter_defaults();
54163
55129
  init_declared_constructors2();
54164
55130
  init_init_source();
54165
55131
  init_ui_action_source();
@@ -54295,7 +55261,8 @@ function createNeoScriptDocumentContext(context, projectOverride) {
54295
55261
  const parameters = context.functionArguments?.map((argument2, index) => ({
54296
55262
  id: `function-parameter:${index}:${argument2.name}`,
54297
55263
  name: argument2.name,
54298
- type: toLanguageType(argument2, context)
55264
+ type: toLanguageType(argument2, context),
55265
+ ...parameterDefaultDescriptor(argument2, context)
54299
55266
  }));
54300
55267
  return {
54301
55268
  kind: documentKind,
@@ -54317,6 +55284,32 @@ function createNeoScriptDocumentContext(context, projectOverride) {
54317
55284
  } : {}
54318
55285
  };
54319
55286
  }
55287
+ function parameterDefaultDescriptor(argument2, context) {
55288
+ if (argument2.defaultValue === void 0) return {};
55289
+ const value = argument2.defaultValue.value;
55290
+ const enumOptionName = argument2.type === 8 /* Enum */ && typeof value === "string" ? analyzerEnumOptionName(argument2.enumId, value, context) : void 0;
55291
+ return {
55292
+ defaultValue: {
55293
+ displayText: neoScriptParameterDefaultDisplayText({
55294
+ value,
55295
+ kind: parameterDefaultSpellingKind(argument2.type),
55296
+ ...enumOptionName === void 0 ? {} : { enumOptionName }
55297
+ }),
55298
+ value
55299
+ }
55300
+ };
55301
+ }
55302
+ function parameterDefaultSpellingKind(type) {
55303
+ if (type === 8 /* Enum */) return "enum";
55304
+ if (type === 20 /* Decimal */) return "decimal";
55305
+ return "other";
55306
+ }
55307
+ function analyzerEnumOptionName(enumId, optionId, context) {
55308
+ const enumDefinition = context.vm.enums.find(
55309
+ (candidate) => candidate.id === enumId
55310
+ );
55311
+ return enumDefinition?.options[optionId]?.name;
55312
+ }
54320
55313
  function createNeoScriptProject(context) {
54321
55314
  const languageTypes = [];
54322
55315
  for (const schemaClass2 of context.vm.classes) {
@@ -54604,7 +55597,8 @@ function declaredConstructors(schemaClass2, context) {
54604
55597
  parameters: record3.argumentTypes.map((argument2) => ({
54605
55598
  name: argument2.name,
54606
55599
  type: toLanguageType(argument2, context),
54607
- required: argument2.required
55600
+ required: argument2.required,
55601
+ ...parameterDefaultDescriptor(argument2, context)
54608
55602
  })),
54609
55603
  ...record3.docsText ? { documentation: record3.docsText } : {},
54610
55604
  ...record3.id === required2 ? { required: true } : {}
@@ -54680,7 +55674,8 @@ function memberToSymbol(record3, schemaKey, containingClass2, ownerClassId, inde
54680
55674
  (argument2, argumentIndex) => ({
54681
55675
  id: `${record3.id}:argument:${argumentIndex}`,
54682
55676
  name: argument2.name,
54683
- type: toLanguageType(argument2, context, genericEnvironment)
55677
+ type: toLanguageType(argument2, context, genericEnvironment),
55678
+ ...parameterDefaultDescriptor(argument2, context)
54684
55679
  })
54685
55680
  ),
54686
55681
  deferred: authoredCallable.deferred,
@@ -54851,7 +55846,8 @@ function interfaceMemberToSymbol(neoInterface, key, member, context, inherited)
54851
55846
  parameters: member.argumentTypes.map((argument2, index) => ({
54852
55847
  id: `${neoInterface.id}:member:${key}:argument:${index}`,
54853
55848
  name: argument2.name,
54854
- type: toLanguageType(argument2, context)
55849
+ type: toLanguageType(argument2, context),
55850
+ ...parameterDefaultDescriptor(argument2, context)
54855
55851
  })),
54856
55852
  deferred: member.deferred,
54857
55853
  abstract: true,
@@ -56431,13 +57427,13 @@ function resolveBaseConstructorOverload(args, owner) {
56431
57427
  `Constructor "${args.constructor.id}" declares a base call, but base class "${baseClass.name}" declares no constructors.`
56432
57428
  );
56433
57429
  }
56434
- const requested = argumentNameSetKey3(
57430
+ const requested = argumentNameSetKey2(
56435
57431
  (args.constructor.baseArguments ?? []).map(
56436
57432
  (baseArgument) => baseArgument.name
56437
57433
  )
56438
57434
  );
56439
57435
  const matches = candidates.filter(
56440
- (candidate) => argumentNameSetKey3(
57436
+ (candidate) => argumentNameSetKey2(
56441
57437
  candidate.argumentTypes.map((argument2) => argument2.name)
56442
57438
  ) === requested
56443
57439
  );
@@ -56493,7 +57489,7 @@ function declaredConstructorsOfClass(constructors, schemaClass2) {
56493
57489
  return [record3];
56494
57490
  });
56495
57491
  }
56496
- function argumentNameSetKey3(names) {
57492
+ function argumentNameSetKey2(names) {
56497
57493
  return [...names].map((name) => name.toLowerCase()).sort().join(", ");
56498
57494
  }
56499
57495
  function describeConstructorOverloads(constructors) {
@@ -59807,16 +60803,21 @@ function executeCompiledFunction(action, ctx, args, allowFallthroughReturn, runt
59807
60803
  `Corrupt NSFunction IR: compiled body has ${action.parameters.length - 2} argument parameter(s), but its runtime signature declares ${expectedCount}.`
59808
60804
  );
59809
60805
  }
59810
- if (args.length !== expectedCount) {
60806
+ const filledArgs = runtimeSignature === void 0 ? args : fillTrailingParameterDefaults(
60807
+ args,
60808
+ runtimeSignature.argumentTypes,
60809
+ "NSFunction"
60810
+ );
60811
+ if (filledArgs.length !== expectedCount) {
59811
60812
  throw new NSGetterRuntimeError(
59812
- `NSFunction expected ${expectedCount} argument(s), got ${args.length}.`
60813
+ `NSFunction expected ${expectedCount} argument(s), got ${filledArgs.length}.`
59813
60814
  );
59814
60815
  }
59815
60816
  const scope = createTopLevelScope(ctx);
59816
- for (let index = 0; index < args.length; index += 1) {
60817
+ for (let index = 0; index < filledArgs.length; index += 1) {
59817
60818
  const parameter4 = action.parameters[index + 2];
59818
60819
  const runtimeTypeInfo = runtimeArgumentTypes[index];
59819
- const value2 = args[index];
60820
+ const value2 = filledArgs[index];
59820
60821
  if (!runtimeValueMatchesType(value2, runtimeTypeInfo, ctx)) {
59821
60822
  throw new NSGetterRuntimeError(
59822
60823
  `NSFunction argument ${index + 1} does not match its declared runtime type.`
@@ -59857,6 +60858,57 @@ function executeCompiledFunction(action, ctx, args, allowFallthroughReturn, runt
59857
60858
  }
59858
60859
  return value;
59859
60860
  }
60861
+ function fillTrailingParameterDefaults(args, argumentTypes, subject) {
60862
+ const maxArity = argumentTypes.length;
60863
+ const minArity = argumentTypes.filter(
60864
+ (parameter4) => !parameterHasDefault(parameter4)
60865
+ ).length;
60866
+ const expectedArity = minArity === maxArity ? `${maxArity} argument(s)` : `between ${minArity} and ${maxArity} argument(s)`;
60867
+ if (args.length > maxArity) {
60868
+ throw new NSGetterRuntimeError(
60869
+ `${subject} expected ${expectedArity}, got ${args.length}.`
60870
+ );
60871
+ }
60872
+ if (args.length < minArity) {
60873
+ throw new NSGetterRuntimeError(
60874
+ `${subject} expected ${expectedArity}, got ${args.length}.`
60875
+ );
60876
+ }
60877
+ if (args.length === maxArity) return args;
60878
+ const filled = [...args];
60879
+ for (let index = args.length; index < maxArity; index += 1) {
60880
+ const parameter4 = argumentTypes[index];
60881
+ if (parameter4 === void 0) {
60882
+ throw new NSGetterRuntimeError(
60883
+ `${subject} has a hole in its argument types at position ${index}.`
60884
+ );
60885
+ }
60886
+ filled.push(parameterDefaultRuntimeValue(parameter4, subject));
60887
+ }
60888
+ return filled;
60889
+ }
60890
+ function parameterDefaultRuntimeValue(parameter4, subject) {
60891
+ const defaultValue = parameter4.defaultValue;
60892
+ if (defaultValue === void 0) {
60893
+ throw new NSGetterRuntimeError(
60894
+ `${subject} parameter '${parameter4.name}' was omitted but declares no default.`
60895
+ );
60896
+ }
60897
+ if (defaultValue.value === null) return null;
60898
+ if (parameter4.type === 8 /* Enum */) return [defaultValue.value];
60899
+ return defaultValue.value;
60900
+ }
60901
+ function fillCallableCallSiteArguments(args, member, ctx) {
60902
+ if (member === null) return args;
60903
+ if (member.kind !== 13 /* Function */ && member.kind !== 23 /* NSFunction */) {
60904
+ return args;
60905
+ }
60906
+ const signature = resolveCallableSignature(member.id, member.kind, ctx);
60907
+ if (signature === null) return args;
60908
+ if (!hasAnyParameterDefault(signature.argumentTypes)) return args;
60909
+ const subject = member.kind === 13 /* Function */ ? `Function '${member.name}'` : `NSFunction '${member.name}'`;
60910
+ return fillTrailingParameterDefaults(args, signature.argumentTypes, subject);
60911
+ }
59860
60912
  function createChildScope(parent) {
59861
60913
  return new NeoScriptScope(parent);
59862
60914
  }
@@ -61153,8 +62205,11 @@ function evalPointer(pointer, scope, ctx) {
61153
62205
  if (pointer.receiver.kind === "instance" && pointer.optional === true && (innerThis === null || innerThis === void 0)) {
61154
62206
  return null;
61155
62207
  }
61156
- const args = pointer.args.map((arg) => evalPointer(arg, scope, ctx));
62208
+ const suppliedArgs = pointer.args.map(
62209
+ (arg) => evalPointer(arg, scope, ctx)
62210
+ );
61157
62211
  const member = pointer.receiver.kind === "static" ? evalMemberById(ctx.vm, pointer.receiver.memberId) : resolveEffectiveCallableMember(pointer, innerThis, ctx);
62212
+ const args = fillCallableCallSiteArguments(suppliedArgs, member, ctx);
61158
62213
  const interceptedMemberId = member?.id ?? pointer.memberId ?? pointer.memberKey ?? pointer.callSiteId;
61159
62214
  consumeBudget(ctx, "workUnits", 1, "work unit");
61160
62215
  const intercepted = ctx.callInterceptor?.({
@@ -61677,13 +62732,21 @@ function substituteCallableSignatureForReceiver(signature, receiver, ctx) {
61677
62732
  ctx
61678
62733
  ),
61679
62734
  argumentTypes: signature.argumentTypes.map((argument2) => {
62735
+ if (!typeInfoContainsGeneric(argument2)) return argument2;
61680
62736
  const substituted = substituteRuntimeTypeInfo(argument2, env, ctx);
61681
62737
  if (substituted.type === NS_TYPE_VOID) {
61682
62738
  throw new NSGetterRuntimeError(
61683
62739
  `Generic NSFunction argument '${argument2.name}' resolved to Void.`
61684
62740
  );
61685
62741
  }
61686
- return { ...substituted, name: argument2.name };
62742
+ const named = { ...substituted, name: argument2.name };
62743
+ if (argument2.defaultValue === void 0) return named;
62744
+ if (argument2.defaultValue.value !== null) {
62745
+ throw new NSGetterRuntimeError(
62746
+ `Generic NSFunction parameter '${argument2.name}' carries a non-null constant default, which a generic parameter cannot declare.`
62747
+ );
62748
+ }
62749
+ return { ...named, defaultValue: { value: null } };
61687
62750
  })
61688
62751
  };
61689
62752
  } catch (error) {
@@ -64158,15 +65221,21 @@ function resolveDeclaredConstructorRecord(info, schemaClass2, ctx) {
64158
65221
  `Declared constructor call on '${schemaClass2.name}' passes the same argument name twice.`
64159
65222
  );
64160
65223
  }
64161
- if (suppliedNames.length !== record3.argumentTypes.length) {
65224
+ const supplied = new Set(suppliedNames);
65225
+ for (const parameter4 of record3.argumentTypes) {
65226
+ if (supplied.has(parameter4.name)) continue;
65227
+ if (parameterHasDefault(parameter4)) continue;
64162
65228
  throw new NSGetterRuntimeError(
64163
- `Constructor '${record3.id}' on '${schemaClass2.name}' declares ${record3.argumentTypes.length} parameter(s) but the call site passes ${suppliedNames.length}.`
65229
+ `Declared constructor call on '${schemaClass2.name}' has no argument for parameter '${parameter4.name}'.`
64164
65230
  );
64165
65231
  }
64166
- for (const parameter4 of record3.argumentTypes) {
64167
- if (suppliedNames.includes(parameter4.name)) continue;
65232
+ const declaredNames = new Set(
65233
+ record3.argumentTypes.map((parameter4) => parameter4.name)
65234
+ );
65235
+ for (const name of suppliedNames) {
65236
+ if (declaredNames.has(name)) continue;
64168
65237
  throw new NSGetterRuntimeError(
64169
- `Declared constructor call on '${schemaClass2.name}' has no argument for parameter '${parameter4.name}'.`
65238
+ `Declared constructor call on '${schemaClass2.name}' names unknown parameter '${name}'.`
64170
65239
  );
64171
65240
  }
64172
65241
  return record3;
@@ -64177,6 +65246,12 @@ function evaluateDeclaredConstructorArguments(info, record3, scope, ctx) {
64177
65246
  byName.set(argument2.name, evalPointer(argument2.valuePointer, scope, ctx));
64178
65247
  }
64179
65248
  return record3.argumentTypes.map((parameter4) => {
65249
+ if (!byName.has(parameter4.name)) {
65250
+ return parameterDefaultRuntimeValue(
65251
+ parameter4,
65252
+ `Constructor '${record3.id}'`
65253
+ );
65254
+ }
64180
65255
  const value = byName.get(parameter4.name);
64181
65256
  if (parameter4.type !== 20 /* Decimal */) return value;
64182
65257
  if (typeof value !== "number") return value;
@@ -64207,7 +65282,7 @@ function resolveBaseConstructorRecord(record3, ctx) {
64207
65282
  if (baseArguments.length === 0) {
64208
65283
  if (candidates.length === 0) return null;
64209
65284
  const parameterless = candidates.find(
64210
- (candidate) => candidate.argumentTypes.length === 0
65285
+ (candidate) => candidate.argumentTypes.every(parameterHasDefault)
64211
65286
  );
64212
65287
  if (parameterless === void 0) {
64213
65288
  throw new NSGetterRuntimeError(
@@ -64218,17 +65293,32 @@ function resolveBaseConstructorRecord(record3, ctx) {
64218
65293
  }
64219
65294
  const names = new Set(baseArguments.map((argument2) => argument2.name));
64220
65295
  const matches = candidates.filter(
64221
- (candidate) => candidate.argumentTypes.length === names.size && candidate.argumentTypes.every((parameter4) => names.has(parameter4.name))
65296
+ (candidate) => candidate.argumentTypes.every(
65297
+ (parameter4) => names.has(parameter4.name) || parameterHasDefault(parameter4)
65298
+ ) && [...names].every(
65299
+ (name) => candidate.argumentTypes.some((parameter4) => parameter4.name === name)
65300
+ )
64222
65301
  );
64223
- const firstMatch = matches[0];
64224
- if (firstMatch === void 0) {
65302
+ if (matches.length === 0) {
64225
65303
  throw new NSGetterRuntimeError(
64226
65304
  `Constructor '${record3.id}' on '${owningClass.name}' calls ': base(${[...names].join(", ")})', which matches no constructor on its base class.`
64227
65305
  );
64228
65306
  }
64229
- if (matches.length > 1) {
65307
+ const fewestFillIns = Math.min(
65308
+ ...matches.map((candidate) => candidate.argumentTypes.length - names.size)
65309
+ );
65310
+ const best = matches.filter(
65311
+ (candidate) => candidate.argumentTypes.length - names.size === fewestFillIns
65312
+ );
65313
+ const firstMatch = best[0];
65314
+ if (firstMatch === void 0) {
65315
+ throw new NSGetterRuntimeError(
65316
+ `Constructor '${record3.id}' on '${owningClass.name}' resolved ': base(${[...names].join(", ")})' to an empty betterness set.`
65317
+ );
65318
+ }
65319
+ if (best.length > 1) {
64230
65320
  throw new NSGetterRuntimeError(
64231
- `Constructor '${record3.id}' on '${owningClass.name}' calls ': base(${[...names].join(", ")})', which matches ${matches.length} base constructors: ${matches.map((candidate) => candidate.id).join(", ")}.`
65321
+ `Constructor '${record3.id}' on '${owningClass.name}' calls ': base(${[...names].join(", ")})', which matches ${best.length} base constructors: ${best.map((candidate) => candidate.id).join(", ")}.`
64232
65322
  );
64233
65323
  }
64234
65324
  return firstMatch;
@@ -64262,6 +65352,12 @@ function evaluateBaseConstructorArguments(record3, baseRecord, argumentValues, t
64262
65352
  }
64263
65353
  return baseRecord.argumentTypes.map((parameter4) => {
64264
65354
  if (!byName.has(parameter4.name)) {
65355
+ if (parameterHasDefault(parameter4)) {
65356
+ return parameterDefaultRuntimeValue(
65357
+ parameter4,
65358
+ `Constructor '${baseRecord.id}'`
65359
+ );
65360
+ }
64265
65361
  throw new NSGetterRuntimeError(
64266
65362
  `Constructor '${record3.id}' calls ': base(...)' without an argument for base parameter '${parameter4.name}'.`
64267
65363
  );
@@ -64639,7 +65735,7 @@ function evaluateInitializerInContext(init, member, ctx, createdValues, argument
64639
65735
  };
64640
65736
  }
64641
65737
  function encodeLookupInitializerResult(member, value, created, ctx) {
64642
- const selection = encodeLookupInitializerSelection(
65738
+ const selection2 = encodeLookupInitializerSelection(
64643
65739
  member,
64644
65740
  value,
64645
65741
  created,
@@ -64651,7 +65747,7 @@ function encodeLookupInitializerResult(member, value, created, ctx) {
64651
65747
  ctx.__executionState?.constructorGroups.delete(row.id);
64652
65748
  }
64653
65749
  }
64654
- return { value: selection, classId: null };
65750
+ return { value: selection2, classId: null };
64655
65751
  }
64656
65752
  function encodeLookupInitializerSelection(member, value, created, ctx) {
64657
65753
  if (value === null) return null;
@@ -66375,12 +67471,15 @@ function isNeoClassConstructorBase(value) {
66375
67471
  if (typeof v.code !== "string" && v.code !== null) return false;
66376
67472
  if (!Array.isArray(v.argumentTypes)) return false;
66377
67473
  const parameterNames = /* @__PURE__ */ new Set();
67474
+ const argumentTypes = [];
66378
67475
  for (const argument2 of v.argumentTypes) {
66379
67476
  if (!isNSFunctionArgumentTypeInfo(argument2)) return false;
66380
67477
  if (!isValidCallableIdentifier(argument2.name)) return false;
66381
67478
  if (parameterNames.has(argument2.name)) return false;
66382
67479
  parameterNames.add(argument2.name);
67480
+ argumentTypes.push(argument2);
66383
67481
  }
67482
+ if (validateParameterDefaults(argumentTypes).length > 0) return false;
66384
67483
  if (v.baseArguments !== void 0 && v.baseArguments !== null) {
66385
67484
  if (!Array.isArray(v.baseArguments)) return false;
66386
67485
  const baseNames = /* @__PURE__ */ new Set();
@@ -72583,7 +73682,7 @@ var init_animation_clips = __esm({
72583
73682
  const seenChildren = /* @__PURE__ */ new Set();
72584
73683
  for (const row of rows) {
72585
73684
  const rowClassId = this.requireNodeClassId(row, "animationChildOverride");
72586
- const selected2 = this.resolveSelector(
73685
+ const selected = this.resolveSelector(
72587
73686
  row,
72588
73687
  rowClassId,
72589
73688
  WORLD_ANIMATION_CHILD_OVERRIDE_SELECTOR_MEMBER_ID,
@@ -72591,8 +73690,8 @@ var init_animation_clips = __esm({
72591
73690
  args.selectorOwnerNode,
72592
73691
  `Animation clip "${args.clipName}" frame ${args.frameIndex} child override`
72593
73692
  );
72594
- if (selected2 === null) continue;
72595
- const { childId, childClassId, childNode: child } = selected2;
73693
+ if (selected === null) continue;
73694
+ const { childId, childClassId, childNode: child } = selected;
72596
73695
  if (!args.childIds.has(childId)) {
72597
73696
  throw new Error(
72598
73697
  `Animation clip "${args.clipName}" frame ${args.frameIndex} references child "${childId}" outside the owner's authored Children graph.`
@@ -72758,7 +73857,7 @@ var init_animation_clips = __esm({
72758
73857
  * segment's length is instance data this document does not have.
72759
73858
  */
72760
73859
  validateTrackBase(args) {
72761
- const selected2 = this.resolveSelector(
73860
+ const selected = this.resolveSelector(
72762
73861
  args.track,
72763
73862
  args.trackClassId,
72764
73863
  WORLD_ANIMATION_TRACK_SELECTOR_MEMBER_ID,
@@ -72766,9 +73865,9 @@ var init_animation_clips = __esm({
72766
73865
  args.selectorOwnerNode,
72767
73866
  args.label
72768
73867
  );
72769
- if (selected2 !== null && !args.childIds.has(selected2.childId)) {
73868
+ if (selected !== null && !args.childIds.has(selected.childId)) {
72770
73869
  throw new Error(
72771
- `${args.label} references child "${selected2.childId}" outside the owner's authored Children graph.`
73870
+ `${args.label} references child "${selected.childId}" outside the owner's authored Children graph.`
72772
73871
  );
72773
73872
  }
72774
73873
  const startFrame = this.requireIntegerField(
@@ -72787,7 +73886,7 @@ var init_animation_clips = __esm({
72787
73886
  }
72788
73887
  this.validateTrackDirection(args.track, args.trackClassId, args.label);
72789
73888
  this.validateTrackCropWindow(args.track, args.trackClassId, args.label);
72790
- return selected2;
73889
+ return selected;
72791
73890
  }
72792
73891
  resolveSelector(parent, classId, selectorMemberId, refreshMemberId, _selectorOwnerNode, label) {
72793
73892
  this.validateSelectorRefresh(parent, classId, refreshMemberId, label);
@@ -74258,7 +75357,7 @@ function explicitTargetIds(changes) {
74258
75357
  return result;
74259
75358
  }
74260
75359
  function selectedRecordIds(records2, explicitIds, impactedIds, impactedTypeNames, constructedClassIds, impactedSourceNames, ownerId = () => null) {
74261
- const selected2 = new Set(explicitIds);
75360
+ const selected = new Set(explicitIds);
74262
75361
  for (const record3 of records2) {
74263
75362
  const owner = ownerId(record3);
74264
75363
  if (owner !== null && impactedIds.has(owner) || recordDependsOnChangedContract(
@@ -74268,10 +75367,10 @@ function selectedRecordIds(records2, explicitIds, impactedIds, impactedTypeNames
74268
75367
  constructedClassIds,
74269
75368
  impactedSourceNames
74270
75369
  )) {
74271
- selected2.add(record3.id);
75370
+ selected.add(record3.id);
74272
75371
  }
74273
75372
  }
74274
- return selected2;
75373
+ return selected;
74275
75374
  }
74276
75375
  function recordDependsOnChangedContract(record3, impactedIds, impactedTypeNames, constructedClassIds, impactedSourceNames) {
74277
75376
  const recordId = isObjectRecord3(record3) ? record3.id : void 0;
@@ -75936,7 +77035,7 @@ function stableValue(value) {
75936
77035
  if (Array.isArray(value)) return value.map(stableValue);
75937
77036
  if (!isRecord7(value)) return value;
75938
77037
  const normalized = Object.fromEntries(
75939
- Object.entries(value).filter(([key]) => key !== "name").sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => [key, stableValue(entry)])
77038
+ Object.entries(value).filter(([key]) => key !== "name" && key !== "defaultValue").sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => [key, stableValue(entry)])
75940
77039
  );
75941
77040
  return normalized;
75942
77041
  }
@@ -76038,11 +77137,81 @@ function isOpaqueNSFunctionReturnTypeInfo(value) {
76038
77137
  return isOpaqueNSTypeInfo(value);
76039
77138
  }
76040
77139
  function isOpaqueNSFunctionArgumentTypeInfo(value) {
76041
- return isOpaqueNSTypeInfo(value) && isOpaqueCallableIdentifier(value.name) && !opaqueTypeInfoContainsUnknown(value);
77140
+ return isOpaqueNSTypeInfo(value) && isOpaqueCallableIdentifier(value.name) && !opaqueTypeInfoContainsUnknown(value) && hasValidOpaqueParameterDefault(value);
76042
77141
  }
76043
77142
  function isOpaqueConstructorArgumentTypeInfo(value) {
76044
77143
  if (!isRecord7(value)) return false;
76045
- return isOpaqueNSTypeInfo(value) && (value.name === "value" || isOpaqueCallableIdentifier(value.name)) && !opaqueTypeInfoContainsUnknown(value);
77144
+ return isOpaqueNSTypeInfo(value) && (value.name === "value" || isOpaqueCallableIdentifier(value.name)) && !opaqueTypeInfoContainsUnknown(value) && hasValidOpaqueParameterDefault(value);
77145
+ }
77146
+ function hasValidOpaqueParameterDefault(value) {
77147
+ const wrapper = value.defaultValue;
77148
+ if (wrapper === void 0) return true;
77149
+ if (!isRecord7(wrapper)) return false;
77150
+ const keys = Object.keys(wrapper);
77151
+ if (keys.length !== 1 || keys[0] !== "value") return false;
77152
+ const payload = wrapper.value;
77153
+ if (payload === null) return value.required === false;
77154
+ if (value.type === 1) return typeof payload === "boolean";
77155
+ if (value.type === 2) {
77156
+ return typeof payload === "number" && Number.isInteger(payload);
77157
+ }
77158
+ if (value.type === 4) {
77159
+ return typeof payload === "number" && Number.isFinite(payload);
77160
+ }
77161
+ if (value.type === 3 || value.type === 8 || value.type === 20) {
77162
+ return typeof payload === "string";
77163
+ }
77164
+ return false;
77165
+ }
77166
+ function opaqueParameterDefaultsPlacedLast(argumentTypes) {
77167
+ let seenDefault = false;
77168
+ for (const argument2 of argumentTypes) {
77169
+ if (argument2.defaultValue !== void 0) {
77170
+ seenDefault = true;
77171
+ continue;
77172
+ }
77173
+ if (seenDefault) return false;
77174
+ }
77175
+ return true;
77176
+ }
77177
+ function opaqueArgumentsHaveDefault(argumentTypes) {
77178
+ return argumentTypes.some(
77179
+ (argument2) => isRecord7(argument2) && argument2.defaultValue !== void 0
77180
+ );
77181
+ }
77182
+ function assertOpaqueParameterDefaultsValid(member) {
77183
+ const argumentTypes = member.argumentTypes;
77184
+ if (!Array.isArray(argumentTypes)) return;
77185
+ if (!opaqueArgumentsHaveDefault(argumentTypes)) return;
77186
+ if (member.kind === 25 || member.kind === 26) {
77187
+ throw new Error(
77188
+ `Member "${member.name}" (${member.id}) is a delegate or action, whose parameters are an unnamed positional type list and cannot carry a default value.`
77189
+ );
77190
+ }
77191
+ if (member.kind !== 13 && member.kind !== 23) {
77192
+ throw new Error(
77193
+ `Member "${member.name}" (${member.id}) is not callable and cannot declare parameter default values.`
77194
+ );
77195
+ }
77196
+ if (member.deferred === true) {
77197
+ throw new Error(
77198
+ `Function "${member.name}" (${member.id}) is deferred, and generated C# appends a trailing deferred parameter that a defaulted parameter cannot precede.`
77199
+ );
77200
+ }
77201
+ const parameters = [];
77202
+ for (const argument2 of argumentTypes) {
77203
+ if (!isRecord7(argument2) || !hasValidOpaqueParameterDefault(argument2)) {
77204
+ throw new Error(
77205
+ `Function "${member.name}" (${member.id}) declares a parameter default value that does not match the parameter's type.`
77206
+ );
77207
+ }
77208
+ parameters.push(argument2);
77209
+ }
77210
+ if (!opaqueParameterDefaultsPlacedLast(parameters)) {
77211
+ throw new Error(
77212
+ `Function "${member.name}" (${member.id}) declares a defaulted parameter before a non-defaulted one; defaulted parameters must come last.`
77213
+ );
77214
+ }
76046
77215
  }
76047
77216
  function memberSignature(member) {
76048
77217
  if (member.kind === "property") {
@@ -76076,6 +77245,7 @@ function assertProjectInterfaceDocumentValid(view, options = {}) {
76076
77245
  }
76077
77246
  for (const member of members) {
76078
77247
  assertOpaqueMemberDefaultValueValid(member);
77248
+ assertOpaqueParameterDefaultsValid(member);
76079
77249
  assertOpaqueCallableOverrideValid(member, membersById);
76080
77250
  assertOpaqueNSFunctionValid(member, membersById);
76081
77251
  if (member.isAbstract === true && member.defaultValue != null) {
@@ -77452,11 +78622,11 @@ function assertOpaqueConstructorValid(declaredConstructor) {
77452
78622
  );
77453
78623
  }
77454
78624
  names.add(name);
77455
- if (argument2.defaultValue !== void 0) {
77456
- throw new Error(
77457
- `Constructor "${declaredConstructor.id}" parameter "${name}" declares a default value, which constructors do not support; add an overload instead.`
77458
- );
77459
- }
78625
+ }
78626
+ if (!opaqueParameterDefaultsPlacedLast(argumentTypes)) {
78627
+ throw new Error(
78628
+ `Constructor "${declaredConstructor.id}" declares a defaulted parameter before a non-defaulted one; defaulted parameters must come last.`
78629
+ );
77460
78630
  }
77461
78631
  assertOpaqueCompiledConstructorAction(declaredConstructor, argumentTypes);
77462
78632
  assertOpaqueConstructorBaseClauseValid(declaredConstructor);
@@ -85325,11 +86495,11 @@ var init_project_version_whole_graph_validation = __esm({
85325
86495
 
85326
86496
  // src/project-source/workspace-status-core.ts
85327
86497
  function listVirtualProjectSourceFilesV4(files) {
85328
- const selected2 = files.filter((file) => {
86498
+ const selected = files.filter((file) => {
85329
86499
  const kind = neoProjectSourceKind(file.path);
85330
86500
  return kind !== null && isNeoProjectProductionSourceKind(kind) && !neoProjectPathHasIgnoredDirectory(file.path);
85331
86501
  });
85332
- const sorted = [...selected2].sort(
86502
+ const sorted = [...selected].sort(
85333
86503
  (left, right) => compareWorkspacePaths(left.path, right.path)
85334
86504
  );
85335
86505
  for (let index = 1; index < sorted.length; index += 1) {
@@ -91393,9 +92563,6 @@ function resolveLookupCollectionValueIds(context, member, collection, ownerValue
91393
92563
  member.collectionMemberId,
91394
92564
  collection.name
91395
92565
  );
91396
- if (declaredRows.size > 0) {
91397
- return { valueIds: [...declaredRows], origin: "collectionMember" };
91398
- }
91399
92566
  const candidates = /* @__PURE__ */ new Set();
91400
92567
  const collectionState = context.state[`member:${member.collectionMemberId}`];
91401
92568
  const collectionMemberData = isObjectRecord2(collectionState?.data) ? collectionState.data : {};
@@ -91407,6 +92574,12 @@ function resolveLookupCollectionValueIds(context, member, collection, ownerValue
91407
92574
  ) ?? []) {
91408
92575
  candidates.add(placedValueId);
91409
92576
  }
92577
+ if (declaredRows.size > 0) {
92578
+ return {
92579
+ valueIds: [.../* @__PURE__ */ new Set([...declaredRows, ...candidates])],
92580
+ origin: "collectionMember"
92581
+ };
92582
+ }
91410
92583
  return { valueIds: [...candidates], origin: "nameScan" };
91411
92584
  }
91412
92585
  function collectionRowsOfDeclaredMember(context, collectionMemberId, schemaKey) {
@@ -92369,13 +93542,13 @@ function storedValueConstructor(context, schemaClass2, constructorArgs) {
92369
93542
  `Stored construction for ${schemaClass2.name} cannot select one constructor from ${candidates.length} ${count}-argument candidates.`
92370
93543
  );
92371
93544
  }
92372
- const selected2 = candidates[0];
92373
- if (selected2 === void 0) {
93545
+ const selected = candidates[0];
93546
+ if (selected === void 0) {
92374
93547
  throw new Error(
92375
93548
  `Stored construction for ${schemaClass2.name} resolved no constructor.`
92376
93549
  );
92377
93550
  }
92378
- return selected2;
93551
+ return selected;
92379
93552
  }
92380
93553
  function storedConstructorArgumentSource(context, type, value, environment, visited, cloneAggregateArguments = false) {
92381
93554
  if (value === null) {
@@ -96073,7 +97246,7 @@ ${blockingErrors.map((error) => ` ${error.message}`).join("\n")}`
96073
97246
  continue;
96074
97247
  }
96075
97248
  const localSide = locallyDeleted ? {} : local;
96076
- const { merged, conflictFields } = mergeProjectDocumentRecord(
97249
+ const { merged, localVariant, serverVariant, conflictFields } = mergeProjectDocumentRecord(
96077
97250
  serverRecord.recordKind,
96078
97251
  baseState.data,
96079
97252
  serverRecord.data,
@@ -96086,11 +97259,11 @@ ${blockingErrors.map((error) => ` ${error.message}`).join("\n")}`
96086
97259
  plans.set(key, {
96087
97260
  // The working copy renders the LOCAL side; the marker's other half
96088
97261
  // comes from the server-variant emission.
96089
- emitData: locallyDeleted ? void 0 : localSide,
97262
+ emitData: locallyDeleted ? void 0 : localVariant,
96090
97263
  serverHash: serverRecord.contentHash,
96091
97264
  serverData: serverRecord.data,
96092
97265
  conflicted: true,
96093
- localData: locallyDeleted ? void 0 : localSide
97266
+ serverEmitData: locallyDeleted ? serverRecord.data : serverVariant
96094
97267
  });
96095
97268
  } else {
96096
97269
  mergedCount += 1;
@@ -96125,8 +97298,7 @@ ${blockingErrors.map((error) => ` ${error.message}`).join("\n")}`
96125
97298
  emitData: local,
96126
97299
  serverHash: baseState.contentHash,
96127
97300
  serverData: void 0,
96128
- conflicted: true,
96129
- localData: local
97301
+ conflicted: true
96130
97302
  });
96131
97303
  continue;
96132
97304
  }
@@ -96621,7 +97793,7 @@ function sourceComparableObjectRecord(recordKind, value, mainLocale) {
96621
97793
  function buildEmitRecordSet(document, plans, side) {
96622
97794
  const records2 = /* @__PURE__ */ new Map();
96623
97795
  for (const [key, plan] of plans) {
96624
- const data = side === "emit" ? plan.emitData : plan.serverData;
97796
+ const data = side === "emit" ? plan.emitData : plan.serverEmitData ?? plan.serverData;
96625
97797
  if (data === void 0) continue;
96626
97798
  const serverRecord = document.records.get(key);
96627
97799
  const [recordKind, recordId] = key.split(/:(.+)/, 2);
@@ -103297,8 +104469,8 @@ var init_registry2 = __esm({
103297
104469
  "use strict";
103298
104470
  PROJECT_SCHEMA_CONTRACT = Object.freeze({
103299
104471
  formatVersion: 3,
103300
- contractVersion: "3.9",
103301
- cliVersion: "0.27.0",
104472
+ contractVersion: "3.10",
104473
+ cliVersion: "0.28.0",
103302
104474
  projectFileUploadBatchSize: 32,
103303
104475
  documentRecords: {
103304
104476
  member: {
@@ -105054,8 +106226,8 @@ function selectedSpecPaths(workspace, selectors) {
105054
106226
  const selectedPaths = all.filter((absolutePath) => {
105055
106227
  const path = relativePaths.get(absolutePath);
105056
106228
  const configured = configuredIncludes.length === 0 || configuredIncludes.some((pattern) => globMatches(pattern, path));
105057
- const selected2 = normalizedSelectors.length === 0 || normalizedSelectors.some((selector) => selectorMatches(selector, path));
105058
- return configured && selected2 && !(workspace.config.test?.exclude ?? []).some(
106229
+ const selected = normalizedSelectors.length === 0 || normalizedSelectors.some((selector) => selectorMatches(selector, path));
106230
+ return configured && selected && !(workspace.config.test?.exclude ?? []).some(
105059
106231
  (pattern) => globMatches(pattern.replaceAll("\\", "/"), path)
105060
106232
  );
105061
106233
  });
@@ -105256,22 +106428,22 @@ function registerSpec(spec, document) {
105256
106428
  );
105257
106429
  return { spec, root, tests };
105258
106430
  }
105259
- function mockResponse(environment, mock, selected2, call) {
105260
- if (selected2 === null) {
106431
+ function mockResponse(environment, mock, selected, call) {
106432
+ if (selected === null) {
105261
106433
  if (mock.callThrough) return { handled: false };
105262
106434
  throw new NeoTestAssertionError(
105263
106435
  `Mock for Function '${mock.memberId}' has no configured behavior. Add returns, throws, doesNothing, or implementation.`
105264
106436
  );
105265
106437
  }
105266
- if (selected2.kind === "throw") {
105267
- throw new NSGetterRuntimeError(selected2.message);
106438
+ if (selected.kind === "throw") {
106439
+ throw new NSGetterRuntimeError(selected.message);
105268
106440
  }
105269
- if (selected2.kind === "implementation") {
106441
+ if (selected.kind === "implementation") {
105270
106442
  return {
105271
106443
  handled: true,
105272
106444
  value: call.invokeDelegate(
105273
106445
  bindNeoScriptDelegateToContext(
105274
- selected2.delegate,
106446
+ selected.delegate,
105275
106447
  environment.context
105276
106448
  ),
105277
106449
  mock.isStatic ? call.args : [call.receiver, ...call.args]
@@ -105280,7 +106452,7 @@ function mockResponse(environment, mock, selected2, call) {
105280
106452
  }
105281
106453
  return {
105282
106454
  handled: true,
105283
- value: selected2.kind === "return" ? selected2.value : null
106455
+ value: selected.kind === "return" ? selected.value : null
105284
106456
  };
105285
106457
  }
105286
106458
  function partialObjectMatch(actual, expected) {
@@ -105297,16 +106469,16 @@ function matchingMock(environment, call) {
105297
106469
  (candidate) => candidate.receiverValueId !== void 0
105298
106470
  );
105299
106471
  const receiverValueId = needsReceiverLookup ? mockReceiverValueId(environment, call.receiver) : null;
105300
- let selected2;
106472
+ let selected;
105301
106473
  for (const candidate of candidates) {
105302
106474
  if (candidate.receiverValueId !== void 0 && candidate.receiverValueId !== receiverValueId) {
105303
106475
  continue;
105304
106476
  }
105305
- if (selected2 === void 0 || candidate.id > selected2.id) {
105306
- selected2 = candidate;
106477
+ if (selected === void 0 || candidate.id > selected.id) {
106478
+ selected = candidate;
105307
106479
  }
105308
106480
  }
105309
- return selected2;
106481
+ return selected;
105310
106482
  }
105311
106483
  function mockReceiverValueId(environment, receiver) {
105312
106484
  if (typeof receiver !== "object" || receiver === null) return null;
@@ -105651,15 +106823,15 @@ function failureFor(error, file, position, member = null) {
105651
106823
  ]
105652
106824
  };
105653
106825
  }
105654
- function suiteHasSelectedTests(suite, selected2) {
105655
- return suite.tests.some((test) => selected2.has(test.id)) || suite.suites.some((child) => suiteHasSelectedTests(child, selected2));
106826
+ function suiteHasSelectedTests(suite, selected) {
106827
+ return suite.tests.some((test) => selected.has(test.id)) || suite.suites.some((child) => suiteHasSelectedTests(child, selected));
105656
106828
  }
105657
- async function executeRegisteredSpec(registered, document, selected2, timeoutMs, interrupted) {
106829
+ async function executeRegisteredSpec(registered, document, selected, timeoutMs, interrupted) {
105658
106830
  const results = [];
105659
106831
  const fileFailures = [];
105660
106832
  let testDurationMs = 0;
105661
106833
  const executeSuite = async (suite, parentEnvironment, inheritedFailures) => {
105662
- if (!suiteHasSelectedTests(suite, selected2)) return;
106834
+ if (!suiteHasSelectedTests(suite, selected)) return;
105663
106835
  const fixture = cloneTestEnvironment(parentEnvironment);
105664
106836
  const suiteFailures = [...inheritedFailures];
105665
106837
  const suiteDeadline = Date.now() + timeoutMs;
@@ -105676,7 +106848,7 @@ async function executeRegisteredSpec(registered, document, selected2, timeoutMs,
105676
106848
  }
105677
106849
  }
105678
106850
  for (const test of suite.tests) {
105679
- if (!selected2.has(test.id)) continue;
106851
+ if (!selected.has(test.id)) continue;
105680
106852
  const started = performance.now();
105681
106853
  const deadline = Date.now() + timeoutMs;
105682
106854
  const environment = cloneTestEnvironment(fixture);
@@ -109864,7 +111036,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
109864
111036
  async function main() {
109865
111037
  const args = parseArgs(process.argv.slice(2));
109866
111038
  if (args.command === "--version") {
109867
- console.log("0.27.0");
111039
+ console.log("0.28.0");
109868
111040
  return;
109869
111041
  }
109870
111042
  if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {