@neocompose/cli 0.27.1 → 0.29.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
 
@@ -7752,7 +7891,7 @@ var NEOSCRIPT_COMPILER_REVISION;
7752
7891
  var init_strict_ir = __esm({
7753
7892
  "../packages/neoscript-language/src/strict-ir.ts"() {
7754
7893
  "use strict";
7755
- NEOSCRIPT_COMPILER_REVISION = 8;
7894
+ NEOSCRIPT_COMPILER_REVISION = 9;
7756
7895
  }
7757
7896
  });
7758
7897
 
@@ -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(
@@ -10452,9 +10597,34 @@ var init_strict_resolver = __esm({
10452
10597
  expression.pos
10453
10598
  );
10454
10599
  }
10455
- if (expression.args.length !== 1 || expression.argumentNames?.[0] !== "id" || expression.args[0]?.kind !== "litString" || expression.args[0].value.length === 0) {
10600
+ const hasProvenanceArgument = expression.args.length === 2;
10601
+ if (expression.args.length < 1 || expression.args.length > 2) {
10602
+ throw new CompileError(
10603
+ "Reference<T> requires id: string and optionally withProvenance: bool.",
10604
+ expression.pos
10605
+ );
10606
+ }
10607
+ if (expression.argumentNames?.[0] !== "id") {
10456
10608
  throw new CompileError(
10457
- "Reference<T> requires exactly one named id: string argument.",
10609
+ "Reference<T> requires id: as its first named argument.",
10610
+ expression.pos
10611
+ );
10612
+ }
10613
+ if (expression.args[0]?.kind !== "litString" || expression.args[0].value.length === 0) {
10614
+ throw new CompileError(
10615
+ "Reference<T> id must be a non-empty string literal.",
10616
+ expression.pos
10617
+ );
10618
+ }
10619
+ if (hasProvenanceArgument && expression.argumentNames?.[1] !== "withProvenance") {
10620
+ throw new CompileError(
10621
+ "Reference<T>'s second named argument must be withProvenance: bool.",
10622
+ expression.pos
10623
+ );
10624
+ }
10625
+ if (hasProvenanceArgument && expression.args[1]?.kind !== "litBool") {
10626
+ throw new CompileError(
10627
+ "Reference<T> withProvenance must be a boolean literal.",
10458
10628
  expression.pos
10459
10629
  );
10460
10630
  }
@@ -10468,7 +10638,8 @@ var init_strict_resolver = __esm({
10468
10638
  return {
10469
10639
  pointer: {
10470
10640
  type: "reference" /* Reference */,
10471
- valueId: expression.args[0].value
10641
+ valueId: expression.args[0].value,
10642
+ ...expression.args[1]?.kind === "litBool" && expression.args[1].value ? { withProvenance: true } : {}
10472
10643
  },
10473
10644
  type: referencedType
10474
10645
  };
@@ -12673,9 +12844,28 @@ var init_strict_resolver = __esm({
12673
12844
  }));
12674
12845
  }
12675
12846
  }
12676
- if (argumentsList2.length !== parameters.length) {
12847
+ const minimumArguments = parameters.filter(
12848
+ (parameter4) => !neoScriptParameterIsOmittable(parameter4)
12849
+ ).length;
12850
+ if (argumentsList2.length < minimumArguments) {
12677
12851
  throw new CompileError(
12678
- `Function '${symbol.name}' expects ${parameters.length} argument${parameters.length === 1 ? "" : "s"}, got ${argumentsList2.length}.`,
12852
+ functionArityMessage(
12853
+ symbol.name,
12854
+ minimumArguments,
12855
+ parameters.length,
12856
+ argumentsList2.length
12857
+ ),
12858
+ pos
12859
+ );
12860
+ }
12861
+ if (argumentsList2.length > parameters.length) {
12862
+ throw new CompileError(
12863
+ functionArityMessage(
12864
+ symbol.name,
12865
+ minimumArguments,
12866
+ parameters.length,
12867
+ argumentsList2.length
12868
+ ),
12679
12869
  pos
12680
12870
  );
12681
12871
  }
@@ -16595,12 +16785,25 @@ var init_project_source_parser = __esm({
16595
16785
  const annotations = this.parseAnnotations();
16596
16786
  const type = this.parseType();
16597
16787
  const name = this.expectName("parameter name");
16788
+ let defaultValue;
16789
+ if (this.eat("=")) {
16790
+ const expressionStart = this.peek();
16791
+ defaultValue = this.captureUntilTopLevel(/* @__PURE__ */ new Set([",", ")"]), false);
16792
+ if (defaultValue.text.trim().length === 0) {
16793
+ throw this.failure(
16794
+ "missing-parameter-default",
16795
+ `Parameter '${name.text}' declares '=' but no default value. Provide a constant expression or remove the '='.`,
16796
+ expressionStart
16797
+ );
16798
+ }
16799
+ }
16598
16800
  parameters.push({
16599
16801
  annotations,
16600
16802
  type,
16601
16803
  name: name.text,
16602
16804
  nameRange: name.range,
16603
- range: rangeFrom(start, name)
16805
+ ...defaultValue ? { defaultValue } : {},
16806
+ range: rangeFrom(start, this.previous())
16604
16807
  });
16605
16808
  if (!this.eat(",") && !this.at(")")) {
16606
16809
  throw this.failure(
@@ -17173,7 +17376,7 @@ var init_project_schema_contract_generated = __esm({
17173
17376
  "../packages/neoscript-language/src/project-schema-contract.generated.ts"() {
17174
17377
  "use strict";
17175
17378
  PROJECT_SCHEMA_MANIFEST_FORMAT_VERSION = 3;
17176
- PROJECT_SCHEMA_MANIFEST_CONTRACT_VERSION = "3.9";
17379
+ PROJECT_SCHEMA_MANIFEST_CONTRACT_VERSION = "3.10";
17177
17380
  PROJECT_FILE_UPLOAD_BATCH_SIZE = 32;
17178
17381
  NEO_PROJECT_SOURCE_RECORD_CONTRACT = {
17179
17382
  "recordFields": {
@@ -19272,6 +19475,24 @@ var init_project_source_construction_diagnostics = __esm({
19272
19475
  "unbound-constructor-argument": "error",
19273
19476
  /** §2.6. No overload's parameter-name set matches the call. */
19274
19477
  "no-matching-constructor-overload": "error",
19478
+ /**
19479
+ * P65 §2.2. Two overload candidates tie under the subset match after the
19480
+ * fewest-fill-ins betterness and the type tie-break; the message lists the
19481
+ * candidates the call could not choose between.
19482
+ */
19483
+ "ambiguous-constructor-call": "error",
19484
+ /**
19485
+ * P65 §1.3. A defaulted parameter declared before a non-defaulted one.
19486
+ * The code string is shared with `src/models/neoscript/parameter-defaults.ts`
19487
+ * so the push guards and the compiler name one rule identically.
19488
+ */
19489
+ "default-before-required-parameter": "error",
19490
+ /**
19491
+ * P65 §1.2. A parameter default that does not fit the parameter's declared
19492
+ * type — a `null` default on a non-nullable parameter included. Shared with
19493
+ * the push-guard validator, like the placement code above.
19494
+ */
19495
+ "parameter-default-type-mismatch": "error",
19275
19496
  /** §2.5 g. An initializer key naming no member of the constructed class. */
19276
19497
  "unknown-initializer-member": "error",
19277
19498
  /**
@@ -19541,9 +19762,13 @@ function resolveInvokedConstructor(declaration, call, diagnostics) {
19541
19762
  return true;
19542
19763
  }
19543
19764
  if (headerParameters.length === 0) return true;
19765
+ if (parameterListIsFullyDefaulted(headerParameters)) return true;
19766
+ const mandatory = headerParameters.filter(
19767
+ (parameter4) => parameter4.defaultValue === void 0
19768
+ );
19544
19769
  diagnostics.push({
19545
19770
  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))}.`,
19771
+ 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
19772
  anchor: { kind: "site" }
19548
19773
  });
19549
19774
  return true;
@@ -19553,7 +19778,7 @@ function resolveInvokedConstructor(declaration, call, diagnostics) {
19553
19778
  }
19554
19779
  if (call.argumentNames.length === 0) {
19555
19780
  return declaration.constructors.some(
19556
- (constructor2) => constructor2.parameters.length === 0
19781
+ (constructor2) => parameterListIsFullyDefaulted(constructor2.parameters)
19557
19782
  );
19558
19783
  }
19559
19784
  if (declaration.constructors.length === 1) {
@@ -19565,13 +19790,17 @@ function resolveInvokedConstructor(declaration, call, diagnostics) {
19565
19790
  );
19566
19791
  return true;
19567
19792
  }
19568
- const key = argumentNameSetKey(
19569
- call.argumentNames.filter((name) => name !== null)
19793
+ const suppliedNames = call.argumentNames.filter(
19794
+ (name) => name !== null
19570
19795
  );
19571
19796
  const matches = declaration.constructors.filter(
19572
- (constructor2) => argumentNameSetKey(
19573
- constructor2.parameters.map((parameter4) => parameter4.name)
19574
- ) === key
19797
+ (constructor2) => neoScriptCallMatchesParameters(
19798
+ suppliedNames,
19799
+ constructor2.parameters.map((parameter4) => ({
19800
+ name: parameter4.name,
19801
+ defaulted: parameter4.defaultValue !== void 0
19802
+ }))
19803
+ )
19575
19804
  );
19576
19805
  if (matches.length > 0) return true;
19577
19806
  diagnostics.push({
@@ -19606,7 +19835,7 @@ function validateArgumentsAgainstParameters(className, parameters, call, diagnos
19606
19835
  });
19607
19836
  });
19608
19837
  const missing = parameters.filter(
19609
- (parameter4) => !supplied.has(parameter4.name.toLowerCase())
19838
+ (parameter4) => parameter4.defaultValue === void 0 && !supplied.has(parameter4.name.toLowerCase())
19610
19839
  );
19611
19840
  if (missing.length === 0) return;
19612
19841
  diagnostics.push({
@@ -19615,6 +19844,9 @@ function validateArgumentsAgainstParameters(className, parameters, call, diagnos
19615
19844
  anchor: { kind: "site" }
19616
19845
  });
19617
19846
  }
19847
+ function parameterListIsFullyDefaulted(parameters) {
19848
+ return parameters.every((parameter4) => parameter4.defaultValue !== void 0);
19849
+ }
19618
19850
  function validateInitializerEntries(index, entry, call, diagnostics) {
19619
19851
  if (call.initializerNames.length === 0) return;
19620
19852
  const chain = baseChain(index, entry);
@@ -19746,13 +19978,12 @@ function substitute(type, bindings) {
19746
19978
  arguments: type.arguments.map((argument2) => substitute(argument2, bindings))
19747
19979
  };
19748
19980
  }
19749
- function argumentNameSetKey(names) {
19750
- return [...names].map((name) => name.toLowerCase()).sort().join(",");
19751
- }
19752
19981
  function describeParameterList(className, parameters) {
19753
- const rendered = parameters.map(
19754
- (parameter4) => `${parameter4.name}${parameter4.type.nullable ? "?" : ""}`
19755
- ).join(", ");
19982
+ const rendered = parameters.map((parameter4) => {
19983
+ const nullability = parameter4.type.nullable ? "?" : "";
19984
+ const defaulted = parameter4.defaultValue === void 0 ? "" : ` = ${parameter4.defaultValue.text}`;
19985
+ return `${parameter4.name}${nullability}${defaulted}`;
19986
+ }).join(", ");
19756
19987
  return `${className}(${rendered})`;
19757
19988
  }
19758
19989
  function describeNameList(names) {
@@ -19781,6 +20012,7 @@ function push(diagnostics, uri, range2, code, message, related2 = []) {
19781
20012
  var init_project_source_settlement = __esm({
19782
20013
  "../packages/neoscript-language/src/project-source-settlement.ts"() {
19783
20014
  "use strict";
20015
+ init_declared_constructors();
19784
20016
  init_project_source_construction_diagnostics();
19785
20017
  init_strict_compile_error();
19786
20018
  init_strict_parser();
@@ -21628,7 +21860,9 @@ function validateReferenceExpression(expression, expected, environment, uri, ran
21628
21860
  const typeArguments = expression.typeArguments ?? [];
21629
21861
  const names = expression.argumentNames ?? [];
21630
21862
  const idIndex = names.findIndex((name) => name === "id");
21863
+ const provenanceIndex = names.findIndex((name) => name === "withProvenance");
21631
21864
  const hasId = idIndex >= 0;
21865
+ const hasProvenance = provenanceIndex >= 0;
21632
21866
  const argument2 = expression.args[hasId ? idIndex : 0];
21633
21867
  const malformed = (message) => pushDiagnostic(
21634
21868
  diagnostics,
@@ -21672,9 +21906,11 @@ function validateReferenceExpression(expression, expected, environment, uri, ran
21672
21906
  }
21673
21907
  return;
21674
21908
  }
21675
- if (expression.args.length !== 1 || hasId && (idIndex !== 0 || names.some((name) => name !== "id")) || !hasId && names.some((name) => name !== null)) {
21909
+ const validIdShape = hasId && idIndex === 0 && expression.args.length === (hasProvenance ? 2 : 1) && (!hasProvenance || provenanceIndex === 1) && names.every((name) => name === "id" || name === "withProvenance");
21910
+ const validSymbolShape = !hasId && !hasProvenance && expression.args.length === 1 && names.every((name) => name === null);
21911
+ if (!validIdShape && !validSymbolShape) {
21676
21912
  malformed(
21677
- "Reference requires exactly one symbol argument or one named id: string argument."
21913
+ "Reference requires one symbol argument, or id: string followed by optional withProvenance: bool."
21678
21914
  );
21679
21915
  return;
21680
21916
  }
@@ -21684,6 +21920,10 @@ function validateReferenceExpression(expression, expected, environment, uri, ran
21684
21920
  malformed("Reference id must be one non-empty string literal.");
21685
21921
  return;
21686
21922
  }
21923
+ if (hasProvenance && expression.args[provenanceIndex]?.kind !== "litBool") {
21924
+ malformed("Reference withProvenance must be a boolean literal.");
21925
+ return;
21926
+ }
21687
21927
  if (!explicit && expected?.name !== "string") {
21688
21928
  malformed("Reference(id: ...) requires an explicit generic target type.");
21689
21929
  return;
@@ -24443,6 +24683,223 @@ var init_project_source_type_checker = __esm({
24443
24683
  }
24444
24684
  });
24445
24685
 
24686
+ // ../packages/neoscript-language/src/project-source-parameter-defaults.ts
24687
+ function validateProjectSourceParameterDefaults(documents) {
24688
+ const diagnostics = [];
24689
+ const enumOptions = collectEnumOptions(documents);
24690
+ for (const [uri, document] of documents) {
24691
+ for (const declaration of document.declarations) {
24692
+ if (declaration.kind === "class") {
24693
+ if (declaration.headerParameters !== void 0) {
24694
+ validateParameterList(
24695
+ uri,
24696
+ declaration.headerParameters,
24697
+ { deferred: false },
24698
+ enumOptions,
24699
+ diagnostics
24700
+ );
24701
+ }
24702
+ for (const constructor2 of declaration.constructors) {
24703
+ validateParameterList(
24704
+ uri,
24705
+ constructor2.parameters,
24706
+ { deferred: false },
24707
+ enumOptions,
24708
+ diagnostics
24709
+ );
24710
+ }
24711
+ }
24712
+ if (declaration.kind === "class" || declaration.kind === "interface") {
24713
+ for (const member of declaration.members) {
24714
+ if (member.kind !== "function") continue;
24715
+ validateParameterList(
24716
+ uri,
24717
+ member.parameters,
24718
+ { deferred: member.modifiers.includes("async") },
24719
+ enumOptions,
24720
+ diagnostics
24721
+ );
24722
+ }
24723
+ }
24724
+ }
24725
+ }
24726
+ return diagnostics;
24727
+ }
24728
+ function collectEnumOptions(documents) {
24729
+ const options = /* @__PURE__ */ new Map();
24730
+ for (const document of documents.values()) {
24731
+ for (const declaration of document.declarations) {
24732
+ if (declaration.kind !== "enum") continue;
24733
+ const names = options.get(declaration.name) ?? options.set(declaration.name, /* @__PURE__ */ new Set()).get(declaration.name);
24734
+ for (const option of declaration.options) names.add(option.name);
24735
+ }
24736
+ }
24737
+ return options;
24738
+ }
24739
+ function validateParameterList(uri, parameters, context, enumOptions, diagnostics) {
24740
+ let lastNonDefaultedIndex = -1;
24741
+ for (let index = parameters.length - 1; index >= 0; index -= 1) {
24742
+ if (parameters[index].defaultValue === void 0) {
24743
+ lastNonDefaultedIndex = index;
24744
+ break;
24745
+ }
24746
+ }
24747
+ parameters.forEach((parameter4, index) => {
24748
+ const defaultValue = parameter4.defaultValue;
24749
+ if (defaultValue === void 0) return;
24750
+ if (context.deferred) {
24751
+ diagnostics.push({
24752
+ uri,
24753
+ range: defaultValue.range,
24754
+ severity: "error",
24755
+ source: "neo-project",
24756
+ code: PARAMETER_DEFAULT_ON_DEFERRED_FUNCTION,
24757
+ 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.`
24758
+ });
24759
+ }
24760
+ if (index < lastNonDefaultedIndex) {
24761
+ diagnostics.push({
24762
+ uri,
24763
+ range: parameter4.range,
24764
+ severity: "error",
24765
+ source: "neo-project",
24766
+ code: DEFAULT_BEFORE_REQUIRED_PARAMETER,
24767
+ message: `Parameter '${parameter4.name}' declares a default before parameter '${parameters[lastNonDefaultedIndex].name}', which has none. Defaulted parameters must come after every non-defaulted parameter.`
24768
+ });
24769
+ }
24770
+ validateDefaultExpression(
24771
+ uri,
24772
+ parameter4,
24773
+ defaultValue,
24774
+ enumOptions,
24775
+ diagnostics
24776
+ );
24777
+ });
24778
+ }
24779
+ function validateDefaultExpression(uri, parameter4, defaultValue, enumOptions, diagnostics) {
24780
+ const constant = classifyConstantDefault(defaultValue.text);
24781
+ if (constant === null) {
24782
+ diagnostics.push({
24783
+ uri,
24784
+ range: defaultValue.range,
24785
+ severity: "error",
24786
+ source: "neo-project",
24787
+ code: NON_CONSTANT_PARAMETER_DEFAULT,
24788
+ message: `Parameter '${parameter4.name}' default must be a constant: a bool, number, or string literal, a leading-dot enum option, or null.`
24789
+ });
24790
+ return;
24791
+ }
24792
+ const mismatch = defaultTypeMismatch(
24793
+ parameter4.type,
24794
+ constant,
24795
+ enumOptions,
24796
+ parameter4.name
24797
+ );
24798
+ if (mismatch === null) return;
24799
+ diagnostics.push({
24800
+ uri,
24801
+ range: defaultValue.range,
24802
+ severity: "error",
24803
+ source: "neo-project",
24804
+ code: PARAMETER_DEFAULT_TYPE_MISMATCH,
24805
+ message: mismatch
24806
+ });
24807
+ }
24808
+ function classifyConstantDefault(text) {
24809
+ let expression;
24810
+ try {
24811
+ expression = parseExpression(text);
24812
+ } catch {
24813
+ return null;
24814
+ }
24815
+ return classifyConstantExpression(expression);
24816
+ }
24817
+ function classifyConstantExpression(expression) {
24818
+ switch (expression.kind) {
24819
+ case "litNull":
24820
+ return { kind: "null" };
24821
+ case "litBool":
24822
+ return { kind: "bool" };
24823
+ case "litInt":
24824
+ return { kind: "int" };
24825
+ case "litFloat":
24826
+ return { kind: "float" };
24827
+ case "litString":
24828
+ return { kind: "string" };
24829
+ case "contextualEnum":
24830
+ return { kind: "enumOption", optionName: expression.name };
24831
+ case "unary": {
24832
+ if (expression.op !== "-") return null;
24833
+ const operand = classifyConstantExpression(expression.operand);
24834
+ if (operand === null) return null;
24835
+ if (operand.kind !== "int" && operand.kind !== "float") return null;
24836
+ return operand;
24837
+ }
24838
+ default:
24839
+ return null;
24840
+ }
24841
+ }
24842
+ function defaultTypeMismatch(type, constant, enumOptions, parameterName) {
24843
+ if (constant.kind === "null") {
24844
+ if (type.nullable) return null;
24845
+ return `Parameter '${parameterName}' defaults to null, but its type '${formatSourceType(type)}' is not nullable.`;
24846
+ }
24847
+ const declaredEnumOptions = enumOptions.get(type.name);
24848
+ if (constant.kind === "enumOption") {
24849
+ if (declaredEnumOptions === void 0) {
24850
+ return `Parameter '${parameterName}' defaults to enum option '.${constant.optionName}', but its type '${formatSourceType(type)}' is not an enum.`;
24851
+ }
24852
+ if (!declaredEnumOptions.has(constant.optionName)) {
24853
+ return `Parameter '${parameterName}' defaults to '.${constant.optionName}', which enum '${type.name}' does not declare.`;
24854
+ }
24855
+ return null;
24856
+ }
24857
+ if (constantKindMatchesPrimitive(type.name, constant.kind)) return null;
24858
+ if (PRIMITIVE_PARAMETER_TYPES.has(type.name) || declaredEnumOptions !== void 0) {
24859
+ return `Parameter '${parameterName}' default is a ${describeConstant(constant)}, which does not match its declared type '${formatSourceType(type)}'.`;
24860
+ }
24861
+ return `Parameter '${parameterName}' of type '${formatSourceType(type)}' can only default to null${type.nullable ? "" : ", and only when the type is nullable"}.`;
24862
+ }
24863
+ function constantKindMatchesPrimitive(typeName, kind) {
24864
+ if (typeName === "bool") return kind === "bool";
24865
+ if (typeName === "int") return kind === "int";
24866
+ if (typeName === "float") return kind === "int" || kind === "float";
24867
+ if (typeName === "decimal") return kind === "int" || kind === "float";
24868
+ if (typeName === "string") return kind === "string";
24869
+ return false;
24870
+ }
24871
+ function describeConstant(constant) {
24872
+ if (constant.kind === "bool") return "bool literal";
24873
+ if (constant.kind === "string") return "string literal";
24874
+ if (constant.kind === "int") return "whole-number literal";
24875
+ return "fractional number literal";
24876
+ }
24877
+ function formatSourceType(type) {
24878
+ const argumentsText = type.typeArguments.length === 0 ? "" : `<${type.typeArguments.map(formatSourceType).join(", ")}>`;
24879
+ return `${type.name}${argumentsText}${type.nullable ? "?" : ""}`;
24880
+ }
24881
+ 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;
24882
+ var init_project_source_parameter_defaults = __esm({
24883
+ "../packages/neoscript-language/src/project-source-parameter-defaults.ts"() {
24884
+ "use strict";
24885
+ init_language_spec();
24886
+ init_strict_parser();
24887
+ PARAMETER_DEFAULT_DIAGNOSTIC_CODES = {
24888
+ defaultBeforeRequiredParameter: "default-before-required-parameter",
24889
+ parameterDefaultTypeMismatch: "parameter-default-type-mismatch",
24890
+ nonConstantParameterDefault: "non-constant-parameter-default",
24891
+ parameterDefaultOnDeferredFunction: "parameter-default-on-deferred-function"
24892
+ };
24893
+ ({
24894
+ defaultBeforeRequiredParameter: DEFAULT_BEFORE_REQUIRED_PARAMETER,
24895
+ parameterDefaultTypeMismatch: PARAMETER_DEFAULT_TYPE_MISMATCH,
24896
+ nonConstantParameterDefault: NON_CONSTANT_PARAMETER_DEFAULT,
24897
+ parameterDefaultOnDeferredFunction: PARAMETER_DEFAULT_ON_DEFERRED_FUNCTION
24898
+ } = PARAMETER_DEFAULT_DIAGNOSTIC_CODES);
24899
+ PRIMITIVE_PARAMETER_TYPES = new Set(NEOSCRIPT_PRIMITIVE_TYPES);
24900
+ }
24901
+ });
24902
+
24446
24903
  // ../packages/neoscript-language/src/project-source-analysis.ts
24447
24904
  function isSystemReservedRecordId(id2) {
24448
24905
  if (id2 === null) return false;
@@ -24500,6 +24957,7 @@ function analyzeNeoProjectSources(inputs, parsedDocuments = /* @__PURE__ */ new
24500
24957
  validateSystemAnnotationAuthoring(documents, diagnostics);
24501
24958
  validateTypeReferences(documents, symbols, diagnostics);
24502
24959
  diagnostics.push(...validateProjectSourceTypes(documents));
24960
+ diagnostics.push(...validateProjectSourceParameterDefaults(documents));
24503
24961
  diagnostics.push(...validateProjectSourceSettlement(documents));
24504
24962
  diagnostics.push(...validateProjectSourceSemantics(documents));
24505
24963
  const bodyCompilation = compileProjectSourceBodies(documents);
@@ -25108,6 +25566,7 @@ var init_project_source_analysis = __esm({
25108
25566
  init_project_source_settlement();
25109
25567
  init_project_source_script_compiler();
25110
25568
  init_project_source_type_checker();
25569
+ init_project_source_parameter_defaults();
25111
25570
  BUILTIN_TYPE_NAMES = /* @__PURE__ */ new Set([
25112
25571
  ...NEOSCRIPT_PRIMITIVE_TYPES,
25113
25572
  ...NEOSCRIPT_BUILTIN_TYPES,
@@ -25427,7 +25886,9 @@ function projectCompletions(analysis, document, position) {
25427
25886
  items: constructorFields.map((field) => ({
25428
25887
  label: field.name,
25429
25888
  kind: "property",
25430
- detail: field.type,
25889
+ // P65 §6. C#-style square brackets mark a defaulted parameter as
25890
+ // omittable at the call site.
25891
+ detail: field.defaultText === void 0 ? field.type : `[${field.type} = ${field.defaultText}]`,
25431
25892
  insertText: `${field.name}: `
25432
25893
  }))
25433
25894
  };
@@ -25862,7 +26323,11 @@ function declaredConstructorNamedArguments(analysis, typeName, used) {
25862
26323
  return [...fields.values()];
25863
26324
  }
25864
26325
  function parameterArgumentField(parameter4) {
25865
- return { name: parameter4.name, type: sourceTypeText(parameter4.type) };
26326
+ return {
26327
+ name: parameter4.name,
26328
+ type: sourceTypeText(parameter4.type),
26329
+ ...parameter4.defaultValue === void 0 ? {} : { defaultText: parameter4.defaultValue.text }
26330
+ };
25866
26331
  }
25867
26332
  function projectInitializerMemberCompletions(analysis, document, position) {
25868
26333
  const site = constructionSiteAt(analysis, document, position);
@@ -25922,6 +26387,13 @@ function constructibleMembers(analysis, typeName) {
25922
26387
  }
25923
26388
  return [...members.values()];
25924
26389
  }
26390
+ function sourceParameterSignatureText(parameter4) {
26391
+ return constructorParameterLabel(sourceParameterProjection(parameter4));
26392
+ }
26393
+ function functionParameterLabel(parameter4) {
26394
+ const suffix = parameter4.defaultValue === void 0 ? "" : ` = ${parameter4.defaultValue.text}`;
26395
+ return `${parameter4.type.name} ${parameter4.name}${suffix}`;
26396
+ }
25925
26397
  function sourceTypeText(type) {
25926
26398
  const args = type.typeArguments.length > 0 ? `<${type.typeArguments.map(sourceTypeText).join(", ")}>` : "";
25927
26399
  return `${type.name}${args}${type.nullable ? "?" : ""}`;
@@ -26048,7 +26520,7 @@ function projectConstructionContractMarkdown(analysis, className) {
26048
26520
  const contract = classConstructionContract(index, className);
26049
26521
  if (!contract) return "";
26050
26522
  if (contract.kind === "required") {
26051
- const parameters = contract.parameters.map((parameter4) => `${sourceTypeText(parameter4.type)} ${parameter4.name}`).join(", ");
26523
+ const parameters = contract.parameters.map(sourceParameterSignatureText).join(", ");
26052
26524
  return `
26053
26525
 
26054
26526
  Construct with \`new(${parameters})\` \u2014 this class declares a required constructor, so the implicit \`new\` is unavailable.`;
@@ -26063,9 +26535,7 @@ Construct with \`new(${parameters})\` \u2014 this class declares a required cons
26063
26535
  }
26064
26536
  if (contract.kind === "declared") {
26065
26537
  const overloads = contract.constructors.map(
26066
- (constructor2) => `\`${className}(${constructor2.parameters.map(
26067
- (parameter4) => `${sourceTypeText(parameter4.type)} ${parameter4.name}`
26068
- ).join(", ")})\``
26538
+ (constructor2) => `\`${className}(${constructor2.parameters.map(sourceParameterSignatureText).join(", ")})\``
26069
26539
  ).join(", ");
26070
26540
  lines.push(`Constructors: ${overloads}.`);
26071
26541
  }
@@ -26160,7 +26630,11 @@ function projectSignatureHelp(analysis, document, position) {
26160
26630
  return signatureResult(`@${callee.text}`, parameters, activeParameter);
26161
26631
  }
26162
26632
  if (callee.text === "Reference") {
26163
- return signatureResult("Reference", ["symbol", "id"], activeParameter);
26633
+ return signatureResult(
26634
+ "Reference",
26635
+ ["symbol or id", "withProvenance = false"],
26636
+ activeParameter
26637
+ );
26164
26638
  }
26165
26639
  if (callee.text === "Pause") {
26166
26640
  return signatureResult(
@@ -26187,13 +26661,11 @@ function projectSignatureHelp(analysis, document, position) {
26187
26661
  if (functions.length === 0) return null;
26188
26662
  return {
26189
26663
  signatures: functions.map(({ owner, member }) => {
26190
- const parameters = member.parameters.map(
26191
- (parameter4) => `${parameter4.type.name} ${parameter4.name}`
26192
- );
26664
+ const parameters = member.parameters.map(functionParameterLabel);
26193
26665
  return {
26194
26666
  label: `${member.type.name} ${owner}.${member.name}(${parameters.join(", ")})`,
26195
26667
  parameters: member.parameters.map((parameter4) => ({
26196
- label: `${parameter4.type.name} ${parameter4.name}`
26668
+ label: functionParameterLabel(parameter4)
26197
26669
  }))
26198
26670
  };
26199
26671
  }),
@@ -26959,7 +27431,10 @@ function findTypeDeclaration(analysis, name) {
26959
27431
  return void 0;
26960
27432
  }
26961
27433
  function constructorParameterLabel(parameter4) {
26962
- return `${parameter4.type} ${parameter4.name}`;
27434
+ return `${parameter4.type} ${parameter4.name}${parameterDefaultSuffix2(parameter4)}`;
27435
+ }
27436
+ function parameterDefaultSuffix2(parameter4) {
27437
+ return parameter4.defaultText === void 0 ? "" : ` = ${parameter4.defaultText}`;
26963
27438
  }
26964
27439
  function projectConstructorTypeName(analysis, document, callee, beforeCallee) {
26965
27440
  if (beforeCallee?.text === "new") return callee.text;
@@ -26985,7 +27460,11 @@ function declarationConstructorParameters(declaration) {
26985
27460
  ).map((member) => ({ type: member.type.name, name: member.name }));
26986
27461
  }
26987
27462
  function sourceParameterProjection(parameter4) {
26988
- return { type: sourceTypeText(parameter4.type), name: parameter4.name };
27463
+ return {
27464
+ type: sourceTypeText(parameter4.type),
27465
+ name: parameter4.name,
27466
+ ...parameter4.defaultValue === void 0 ? {} : { defaultText: parameter4.defaultValue.text }
27467
+ };
26989
27468
  }
26990
27469
  function graphConstructorParameters(typeName) {
26991
27470
  switch (typeName) {
@@ -27104,6 +27583,9 @@ function projectConstructionQuickFixes(analysis, document, diagnostic) {
27104
27583
  if (diagnostic.code === "unknown-identifier") {
27105
27584
  return moveParametersToClassHeaderFixes(analysis, document, diagnostic);
27106
27585
  }
27586
+ if (diagnostic.code === "default-before-required-parameter") {
27587
+ return moveDefaultedParameterFixes(analysis, document, diagnostic);
27588
+ }
27107
27589
  return [];
27108
27590
  }
27109
27591
  function settleRequiredMemberFixes(analysis, document, diagnostic) {
@@ -27209,10 +27691,13 @@ function placeholderValue(analysis, index, type, depth) {
27209
27691
  if (declaration.modifiers.includes("abstract")) return null;
27210
27692
  const contract = classConstructionContract(index, type.name);
27211
27693
  if (contract?.kind !== "required") return "new()";
27212
- if (contract.parameters.length === 0) return "new()";
27694
+ const mandatory = contract.parameters.filter(
27695
+ (parameter4) => parameter4.defaultValue === void 0
27696
+ );
27697
+ if (mandatory.length === 0) return "new()";
27213
27698
  if (depth > 0) return null;
27214
27699
  const args = [];
27215
- for (const parameter4 of contract.parameters) {
27700
+ for (const parameter4 of mandatory) {
27216
27701
  const value = placeholderValue(analysis, index, parameter4.type, depth + 1);
27217
27702
  if (value === null) return null;
27218
27703
  args.push(`${parameter4.name}: ${value}`);
@@ -27404,6 +27889,71 @@ function innerBodyText(constructor2) {
27404
27889
  const trimmed = constructor2.body.text.trim();
27405
27890
  return trimmed.startsWith("{") && trimmed.endsWith("}") ? trimmed.slice(1, -1) : trimmed;
27406
27891
  }
27892
+ function moveDefaultedParameterFixes(analysis, document, diagnostic) {
27893
+ const source = analysis.documents.get(document.uri);
27894
+ if (!source) return [];
27895
+ const parameters = parameterListAt(source.declarations, diagnostic.range);
27896
+ if (parameters === null) return [];
27897
+ const first = parameters[0];
27898
+ const last = parameters[parameters.length - 1];
27899
+ if (!first || !last) return [];
27900
+ const text = new SourceText(document.text);
27901
+ const authored = (parameter4) => text.text.slice(
27902
+ text.offsetAt(parameter4.range.start),
27903
+ text.offsetAt(parameter4.range.end)
27904
+ );
27905
+ const reordered = [
27906
+ ...parameters.filter((parameter4) => parameter4.defaultValue === void 0),
27907
+ ...parameters.filter((parameter4) => parameter4.defaultValue !== void 0)
27908
+ ];
27909
+ return [
27910
+ {
27911
+ title: "Move defaulted parameters after required parameters",
27912
+ kind: "quickfix",
27913
+ diagnostics: [diagnostic],
27914
+ edit: {
27915
+ changes: {
27916
+ [document.uri]: [
27917
+ {
27918
+ range: {
27919
+ start: first.range.start,
27920
+ end: last.range.end
27921
+ },
27922
+ newText: reordered.map(authored).join(", ")
27923
+ }
27924
+ ]
27925
+ }
27926
+ },
27927
+ preferred: true
27928
+ }
27929
+ ];
27930
+ }
27931
+ function parameterListAt(declarations, range2) {
27932
+ for (const declaration of declarations) {
27933
+ if (declaration.kind !== "class" && declaration.kind !== "interface") {
27934
+ continue;
27935
+ }
27936
+ const lists = [];
27937
+ if (declaration.kind === "class") {
27938
+ if (declaration.headerParameters !== void 0) {
27939
+ lists.push(declaration.headerParameters);
27940
+ }
27941
+ for (const constructor2 of declaration.constructors) {
27942
+ lists.push(constructor2.parameters);
27943
+ }
27944
+ }
27945
+ for (const member of declaration.members) {
27946
+ if (member.kind === "function") lists.push(member.parameters);
27947
+ }
27948
+ for (const list of lists) {
27949
+ const hit = list.some(
27950
+ (parameter4) => rangeContains(parameter4.range, range2.start)
27951
+ );
27952
+ if (hit) return list;
27953
+ }
27954
+ }
27955
+ return null;
27956
+ }
27407
27957
  var NEW_CONSTRUCTIBLE_BUILTIN_TYPES;
27408
27958
  var init_project_source_construction_quick_fixes = __esm({
27409
27959
  "../packages/neoscript-language/src/project-source-construction-quick-fixes.ts"() {
@@ -27560,6 +28110,7 @@ function manifestParameter(uri, parameter4) {
27560
28110
  name: parameter4.name,
27561
28111
  type: manifestType(parameter4.type),
27562
28112
  annotations: manifestAnnotations(parameter4.annotations),
28113
+ default: parameter4.defaultValue?.text ?? null,
27563
28114
  source: { uri, range: parameter4.range }
27564
28115
  };
27565
28116
  }
@@ -27970,12 +28521,21 @@ function assertBaseClauseArguments(value, path) {
27970
28521
  }
27971
28522
  function assertParameter(value, path) {
27972
28523
  const parameter4 = record(value, path);
27973
- exactKeys(parameter4, path, ["name", "type", "annotations", "source"]);
28524
+ exactKeys(parameter4, path, [
28525
+ "name",
28526
+ "type",
28527
+ "annotations",
28528
+ "default",
28529
+ "source"
28530
+ ]);
27974
28531
  string(parameter4.name, `${path}.name`);
27975
28532
  assertType(parameter4.type, `${path}.type`);
27976
28533
  array(parameter4.annotations, `${path}.annotations`).forEach(
27977
28534
  (annotation2, index) => assertAnnotation(annotation2, `${path}.annotations[${index}]`)
27978
28535
  );
28536
+ if (parameter4.default !== null) {
28537
+ string(parameter4.default, `${path}.default`);
28538
+ }
27979
28539
  assertLocation(parameter4.source, `${path}.source`);
27980
28540
  }
27981
28541
  function assertMember(value, path) {
@@ -28408,6 +28968,7 @@ function projectSchemaManifest(input, options = {}) {
28408
28968
  members: memberById,
28409
28969
  classes: schemaClassById,
28410
28970
  interfaces: interfaceById,
28971
+ enums: indexById(enums, "ProjectSchemaManifest.enums"),
28411
28972
  genericNames,
28412
28973
  effectiveWritabilityByMemberId: effectiveMemberWritability(
28413
28974
  members,
@@ -28469,7 +29030,8 @@ function groupDeclaredConstructors(declaredConstructors2, environment) {
28469
29030
  (parameter4) => ({
28470
29031
  name: parameter4.name,
28471
29032
  type: parameter4.type,
28472
- required: parameter4.type.nullable !== true
29033
+ required: parameter4.type.nullable !== true,
29034
+ ...parameter4.defaultValue === void 0 ? {} : { defaultValue: parameter4.defaultValue }
28473
29035
  })
28474
29036
  ),
28475
29037
  ...documentation === void 0 ? {} : { documentation },
@@ -29479,6 +30041,11 @@ function argumentsList(value, environment, field) {
29479
30041
  environment,
29480
30042
  `${field}.arguments[${index}].type`
29481
30043
  ),
30044
+ ...manifestParameterDefault(
30045
+ argument2,
30046
+ environment,
30047
+ `${field}.arguments[${index}]`
30048
+ ),
29482
30049
  ...spanAndSelectionLocations(
29483
30050
  argument2.source,
29484
30051
  argument2.selectionSpan ?? argument2.source,
@@ -29487,6 +30054,54 @@ function argumentsList(value, environment, field) {
29487
30054
  )
29488
30055
  }));
29489
30056
  }
30057
+ function neoScriptParameterDefaultDisplayText(options) {
30058
+ const { value, kind } = options;
30059
+ if (value === null) return "null";
30060
+ if (kind === "enum") return `.${options.enumOptionName ?? String(value)}`;
30061
+ if (kind === "decimal" && typeof value === "string") return value;
30062
+ if (typeof value === "string") return JSON.stringify(value);
30063
+ return String(value);
30064
+ }
30065
+ function manifestParameterDefault(argument2, environment, field) {
30066
+ const declared = optionalRecord(argument2.default);
30067
+ if (declared === void 0) return {};
30068
+ const value = constantDefaultValue(declared.value, `${field}.default.value`);
30069
+ const type = record2(argument2.type, `${field}.type`);
30070
+ const kind = string2(type.kind, `${field}.type.kind`);
30071
+ const enumOptionName = kind === "enum" && typeof value === "string" ? manifestEnumOptionName(
30072
+ string2(type.enumId, `${field}.type.enumId`),
30073
+ value,
30074
+ environment
30075
+ ) : void 0;
30076
+ return {
30077
+ defaultValue: {
30078
+ displayText: neoScriptParameterDefaultDisplayText({
30079
+ value,
30080
+ kind: kind === "enum" || kind === "decimal" ? kind : "other",
30081
+ ...enumOptionName === void 0 ? {} : { enumOptionName }
30082
+ }),
30083
+ value
30084
+ }
30085
+ };
30086
+ }
30087
+ function constantDefaultValue(value, field) {
30088
+ if (value !== null && typeof value !== "boolean" && typeof value !== "number" && typeof value !== "string") {
30089
+ throw new Error(
30090
+ `${field} must be a \xA71.2 constant (boolean, number, string, or null), received ${JSON.stringify(value)}.`
30091
+ );
30092
+ }
30093
+ return value;
30094
+ }
30095
+ function manifestEnumOptionName(enumId, optionId, environment) {
30096
+ const schemaEnum = environment.enums.get(enumId);
30097
+ if (schemaEnum === void 0) return void 0;
30098
+ const options = records(schemaEnum.options ?? [], `enum ${enumId}.options`);
30099
+ const option = options.find(
30100
+ (candidate) => candidate.id === optionId || candidate.key === optionId
30101
+ );
30102
+ if (option === void 0) return void 0;
30103
+ return typeof option.name === "string" ? option.name : void 0;
30104
+ }
29490
30105
  function sourceLocation(value, environment, field) {
29491
30106
  const source = optionalRecord(value);
29492
30107
  if (!source) return {};
@@ -30436,6 +31051,7 @@ var init_src = __esm({
30436
31051
  init_project_source_construction_diagnostics();
30437
31052
  init_project_source_construction_quick_fixes();
30438
31053
  init_project_source_manifest();
31054
+ init_project_source_parameter_defaults();
30439
31055
  init_project_source_settlement();
30440
31056
  init_project_source_parser();
30441
31057
  init_project_source_script_compiler();
@@ -32401,10 +33017,7 @@ function memberToDocumentFields(member, baseData3) {
32401
33017
  }
32402
33018
  if (member.kind === "function" || member.kind === "scriptFunction") {
32403
33019
  fields.returnTypeInfo = manifestReturnTypeToDocument(member.returnType);
32404
- fields.argumentTypes = member.arguments.map((argument2) => ({
32405
- name: argument2.name,
32406
- ...manifestTypeToDocument(argument2.type)
32407
- }));
33020
+ fields.argumentTypes = member.arguments.map(manifestArgumentToDocument);
32408
33021
  fields.deferred = member.deferred;
32409
33022
  if (member.kind === "scriptFunction" && member.script !== null && member.bodyMode !== "ui") {
32410
33023
  fields.code = member.script.sourceText;
@@ -32416,16 +33029,10 @@ function memberToDocumentFields(member, baseData3) {
32416
33029
  }
32417
33030
  if (member.kind === "delegate") {
32418
33031
  fields.returnTypeInfo = manifestReturnTypeToDocument(member.returnType);
32419
- fields.argumentTypes = member.arguments.map((argument2) => ({
32420
- name: argument2.name,
32421
- ...manifestTypeToDocument(argument2.type)
32422
- }));
33032
+ fields.argumentTypes = member.arguments.map(manifestArgumentToDocument);
32423
33033
  }
32424
33034
  if (member.kind === "action") {
32425
- fields.argumentTypes = member.arguments.map((argument2) => ({
32426
- name: argument2.name,
32427
- ...manifestTypeToDocument(argument2.type)
32428
- }));
33035
+ fields.argumentTypes = member.arguments.map(manifestArgumentToDocument);
32429
33036
  }
32430
33037
  if (member.kind === "generic") {
32431
33038
  fields.genericParamId = member.genericParamId;
@@ -32515,11 +33122,25 @@ function documentArgumentsToManifest(value, record3, source) {
32515
33122
  `argumentTypes[${index}].name`
32516
33123
  ),
32517
33124
  type: documentTypeToManifest(argument2, record3, `argumentTypes[${index}]`),
33125
+ default: documentParameterDefaultToManifest(
33126
+ argument2.defaultValue,
33127
+ record3,
33128
+ `argumentTypes[${index}].defaultValue`,
33129
+ source
33130
+ ),
32518
33131
  source,
32519
33132
  selectionSpan: source
32520
33133
  };
32521
33134
  });
32522
33135
  }
33136
+ function documentParameterDefaultToManifest(value, record3, path, source) {
33137
+ if (value === void 0 || value === null) return null;
33138
+ const wrapper = requireRecordValue(value, record3, path);
33139
+ if (!Object.hasOwn(wrapper, "value")) {
33140
+ throw invalidDocument(record3, path, 'must carry a "value" key');
33141
+ }
33142
+ return { value: wrapper.value, source };
33143
+ }
32523
33144
  function optionalDocumentType(value, record3, path) {
32524
33145
  if (value === null || value === void 0) return null;
32525
33146
  return documentTypeToManifest(value, record3, path);
@@ -32668,6 +33289,13 @@ function documentTypeToManifest(value, record3, path) {
32668
33289
  `unsupported type-info discriminator ${kind}`
32669
33290
  );
32670
33291
  }
33292
+ function manifestArgumentToDocument(argument2) {
33293
+ return {
33294
+ name: argument2.name,
33295
+ ...manifestTypeToDocument(argument2.type),
33296
+ ...argument2.default === null ? {} : { defaultValue: { value: argument2.default.value } }
33297
+ };
33298
+ }
32671
33299
  function manifestReturnTypeToDocument(type) {
32672
33300
  if (type.kind === "void") return { type: "Void", required: true };
32673
33301
  return manifestTypeToDocument(type);
@@ -33407,10 +34035,7 @@ function interfaceToDocument(neoInterface) {
33407
34035
  kind: "function",
33408
34036
  ...member.docsText === void 0 ? {} : { docsText: member.docsText },
33409
34037
  returnTypeInfo: manifestReturnTypeToDocument(member.returnType),
33410
- argumentTypes: member.arguments.map((argument2) => ({
33411
- name: argument2.name,
33412
- ...manifestTypeToDocument(argument2.type)
33413
- })),
34038
+ argumentTypes: member.arguments.map(manifestArgumentToDocument),
33414
34039
  deferred: member.deferred,
33415
34040
  accessModifierKind: member.accessModifier
33416
34041
  };
@@ -33909,10 +34534,7 @@ function constructorToDocument(declared) {
33909
34534
  return omitUndefined({
33910
34535
  id: declared.id,
33911
34536
  classId: declared.classId,
33912
- argumentTypes: declared.arguments.map((argument2) => ({
33913
- name: argument2.name,
33914
- ...manifestTypeToDocument(argument2.type)
33915
- })),
34537
+ argumentTypes: declared.arguments.map(manifestArgumentToDocument),
33916
34538
  code: declared.code,
33917
34539
  baseArguments: declared.baseArguments,
33918
34540
  baseInitializerFields: declared.baseInitializerFields,
@@ -35568,14 +36190,22 @@ function assertFunctionArgument(value, path) {
35568
36190
  const argument2 = objectAt(value, path, [
35569
36191
  "name",
35570
36192
  "type",
36193
+ "default",
35571
36194
  "source",
35572
36195
  "selectionSpan"
35573
36196
  ]);
35574
36197
  nonEmptyString(argument2.name, `${path}.name`);
35575
36198
  assertType2(argument2.type, `${path}.type`);
36199
+ assertParameterDefault(argument2.default, `${path}.default`);
35576
36200
  assertSpan(argument2.source, `${path}.source`);
35577
36201
  assertSpan(argument2.selectionSpan, `${path}.selectionSpan`);
35578
36202
  }
36203
+ function assertParameterDefault(value, path) {
36204
+ if (value === null) return;
36205
+ const parameterDefault = objectAt(value, path, ["value", "source"]);
36206
+ assertJsonValue(parameterDefault.value, `${path}.value`, 0);
36207
+ assertSpan(parameterDefault.source, `${path}.source`);
36208
+ }
35579
36209
  function assertAbstractScriptInvariant(value, path) {
35580
36210
  const isAbstract = value.modifier === "abstract" || value.modifier === "abstractOverride";
35581
36211
  const hasUiBody = value.bodyMode === "ui" && value.uiAction !== void 0;
@@ -37789,7 +38419,30 @@ function isNSFunctionReturnTypeInfo(value) {
37789
38419
  return isNSTypeInfo(value) || isNSTypeInfoVoid(value);
37790
38420
  }
37791
38421
  function isNSFunctionArgumentTypeInfo(value) {
37792
- return isNSArgumentTypeInfo(value) && !typeInfoContainsUnknown(value, /* @__PURE__ */ new Set());
38422
+ return isNSArgumentTypeInfo(value) && !typeInfoContainsUnknown(value, /* @__PURE__ */ new Set()) && hasValidParameterDefault(value);
38423
+ }
38424
+ function hasValidParameterDefault(value) {
38425
+ const wrapper = value.defaultValue;
38426
+ if (wrapper === void 0) return true;
38427
+ if (typeof wrapper !== "object" || wrapper === null) return false;
38428
+ const keys = Object.keys(wrapper);
38429
+ if (keys.length !== 1 || keys[0] !== "value") return false;
38430
+ const payload = wrapper.value;
38431
+ if (payload === null) return !value.required;
38432
+ switch (value.type) {
38433
+ case 1 /* Bool */:
38434
+ return typeof payload === "boolean";
38435
+ case 2 /* Int */:
38436
+ return typeof payload === "number" && Number.isInteger(payload);
38437
+ case 4 /* Float */:
38438
+ return typeof payload === "number" && Number.isFinite(payload);
38439
+ case 20 /* Decimal */:
38440
+ case 3 /* String */:
38441
+ case 8 /* Enum */:
38442
+ return typeof payload === "string";
38443
+ default:
38444
+ return false;
38445
+ }
37793
38446
  }
37794
38447
  function typeInfoContainsUnknown(value, ancestors) {
37795
38448
  if (value.type === NS_TYPE_UNKNOWN) return true;
@@ -37840,7 +38493,9 @@ function isNSKeyOf(value) {
37840
38493
  }
37841
38494
  function isNSPointerReference(value) {
37842
38495
  const v = value;
37843
- return v?.type === "reference" /* reference */ && typeof v?.valueId === "string";
38496
+ if (v?.type !== "reference" /* reference */) return false;
38497
+ if (typeof v.valueId !== "string") return false;
38498
+ return v.withProvenance === void 0 || typeof v.withProvenance === "boolean";
37844
38499
  }
37845
38500
  function isNSPointerVariable(value) {
37846
38501
  const v = value;
@@ -38590,6 +39245,51 @@ var init_neoscript_guards = __esm({
38590
39245
  }
38591
39246
  });
38592
39247
 
39248
+ // ../src/models/neoscript/parameter-defaults.ts
39249
+ function parameterHasDefault(argument2) {
39250
+ return argument2.defaultValue !== void 0;
39251
+ }
39252
+ function hasAnyParameterDefault(argumentTypes) {
39253
+ return argumentTypes.some(parameterHasDefault);
39254
+ }
39255
+ function validateParameterDefaults(argumentTypes) {
39256
+ const violations = [];
39257
+ let lastNonDefaultedIndex = -1;
39258
+ for (let index = argumentTypes.length - 1; index >= 0; index -= 1) {
39259
+ const argument2 = argumentTypes[index];
39260
+ if (argument2 !== void 0 && !parameterHasDefault(argument2)) {
39261
+ lastNonDefaultedIndex = index;
39262
+ break;
39263
+ }
39264
+ }
39265
+ for (let index = 0; index < argumentTypes.length; index += 1) {
39266
+ const argument2 = argumentTypes[index];
39267
+ if (argument2 === void 0) continue;
39268
+ const defaultValue = argument2.defaultValue;
39269
+ if (defaultValue === void 0) continue;
39270
+ if (index < lastNonDefaultedIndex) {
39271
+ violations.push({
39272
+ code: "default-before-required-parameter",
39273
+ index,
39274
+ name: argument2.name
39275
+ });
39276
+ }
39277
+ if (defaultValue.value === null && argument2.required) {
39278
+ violations.push({
39279
+ code: "parameter-default-type-mismatch",
39280
+ index,
39281
+ name: argument2.name
39282
+ });
39283
+ }
39284
+ }
39285
+ return violations;
39286
+ }
39287
+ var init_parameter_defaults = __esm({
39288
+ "../src/models/neoscript/parameter-defaults.ts"() {
39289
+ "use strict";
39290
+ }
39291
+ });
39292
+
38593
39293
  // ../src/models/interfaces/interface-graph.ts
38594
39294
  function resolveInterfaceClosure(interfaceId, interfaces) {
38595
39295
  const byId = new Map(
@@ -38726,6 +39426,7 @@ var init_neoscript = __esm({
38726
39426
  "use strict";
38727
39427
  init_neoscript_types();
38728
39428
  init_neoscript_guards();
39429
+ init_parameter_defaults();
38729
39430
  init_type_info_compatibility();
38730
39431
  }
38731
39432
  });
@@ -39384,14 +40085,20 @@ function isMemberFunctionBase(value) {
39384
40085
  if (!Array.isArray(v.argumentTypes)) return false;
39385
40086
  if (typeof v.deferred !== "boolean") return false;
39386
40087
  const names = /* @__PURE__ */ new Set();
40088
+ const argumentTypes = [];
39387
40089
  for (const arg of v.argumentTypes) {
39388
40090
  if (!isNSFunctionArgumentTypeInfo(arg)) return false;
39389
40091
  if (!isValidCallableIdentifier(arg.name)) return false;
39390
40092
  if (arg.type === NS_TYPE_UNKNOWN) return false;
39391
40093
  if (names.has(arg.name)) return false;
39392
40094
  names.add(arg.name);
40095
+ argumentTypes.push(arg);
39393
40096
  }
39394
- return true;
40097
+ return hasValidParameterDefaults(argumentTypes, v.deferred);
40098
+ }
40099
+ function hasValidParameterDefaults(argumentTypes, deferred) {
40100
+ if (deferred && hasAnyParameterDefault(argumentTypes)) return false;
40101
+ return validateParameterDefaults(argumentTypes).length === 0;
39395
40102
  }
39396
40103
  function normalizedCompiledFunctionReturnType(typeInfo) {
39397
40104
  if (typeInfo.type === NS_TYPE_VOID) {
@@ -39439,6 +40146,7 @@ function isMemberNSFunctionBase(value) {
39439
40146
  if (v.action !== void 0 && v.action !== null) return false;
39440
40147
  if (v.bodyMode !== void 0 && v.bodyMode !== "ui") return false;
39441
40148
  const names = /* @__PURE__ */ new Set();
40149
+ const argumentTypes = [];
39442
40150
  for (const argument2 of v.argumentTypes) {
39443
40151
  if (!isNSFunctionArgumentTypeInfo(argument2)) return false;
39444
40152
  if (argument2.type === NS_TYPE_UNKNOWN) return false;
@@ -39446,7 +40154,9 @@ function isMemberNSFunctionBase(value) {
39446
40154
  if (NSFunctionArgumentReservedNames.has(argument2.name)) return false;
39447
40155
  if (names.has(argument2.name)) return false;
39448
40156
  names.add(argument2.name);
40157
+ argumentTypes.push(argument2);
39449
40158
  }
40159
+ if (!hasValidParameterDefaults(argumentTypes, v.deferred)) return false;
39450
40160
  if (v.isAbstract === true) {
39451
40161
  if (v.bodyMode !== void 0) return false;
39452
40162
  if (v.uiAction !== void 0 && v.uiAction !== null) return false;
@@ -39523,6 +40233,7 @@ function isMemberDelegateBase(value) {
39523
40233
  if (argument2.type === NS_TYPE_UNKNOWN) return false;
39524
40234
  if (names.has(argument2.name)) return false;
39525
40235
  names.add(argument2.name);
40236
+ if (argument2.defaultValue !== void 0) return false;
39526
40237
  }
39527
40238
  const defaultValue = v.defaultValue;
39528
40239
  if (defaultValue === void 0 || defaultValue === null) return true;
@@ -39561,6 +40272,7 @@ function isMemberActionBase(value) {
39561
40272
  if (argument2.type === NS_TYPE_UNKNOWN) return false;
39562
40273
  if (names.has(argument2.name)) return false;
39563
40274
  names.add(argument2.name);
40275
+ if (argument2.defaultValue !== void 0) return false;
39564
40276
  }
39565
40277
  const defaultValue = v.defaultValue;
39566
40278
  if (defaultValue === void 0 || defaultValue === null) return true;
@@ -39792,6 +40504,7 @@ function isMemberOverrideBase(value) {
39792
40504
  if (v.argumentTypes !== void 0) {
39793
40505
  if (!Array.isArray(v.argumentTypes)) return false;
39794
40506
  if (!v.argumentTypes.every(isNSFunctionArgumentTypeInfo)) return false;
40507
+ if (hasAnyParameterDefault(v.argumentTypes)) return false;
39795
40508
  }
39796
40509
  if (v.deferred !== void 0 && typeof v.deferred !== "boolean") {
39797
40510
  return false;
@@ -43670,7 +44383,11 @@ function isNeoInterfaceMember(value) {
43670
44383
  if (!isNSFunctionArgumentTypeInfo(argumentType)) return false;
43671
44384
  if (containsForbiddenMemberTypeInfo(argumentType)) return false;
43672
44385
  }
43673
- return typeof member.deferred === "boolean";
44386
+ if (typeof member.deferred !== "boolean") return false;
44387
+ if (member.deferred && hasAnyParameterDefault(member.argumentTypes)) {
44388
+ return false;
44389
+ }
44390
+ return validateParameterDefaults(member.argumentTypes).length === 0;
43674
44391
  }
43675
44392
  function isInterfaceMembersRecord(value) {
43676
44393
  if (typeof value !== "object") return false;
@@ -43738,6 +44455,7 @@ var init_interface_types = __esm({
43738
44455
  init_neoscript_types();
43739
44456
  init_docs_text2();
43740
44457
  init_neoscript_guards();
44458
+ init_parameter_defaults();
43741
44459
  init_member_kinds();
43742
44460
  }
43743
44461
  });
@@ -46056,11 +46774,46 @@ function baseConstruction(requiredConstructor) {
46056
46774
  function renderHeaderParameters(context, requiredConstructor) {
46057
46775
  if (requiredConstructor === void 0) return "";
46058
46776
  const parameters = requiredConstructor.arguments.map(
46059
- (argument2) => `${renderType(context, argument2.type)} ${argument2.name}`
46777
+ (argument2) => renderParameter(context, argument2)
46060
46778
  );
46061
46779
  if (parameters.length === 0 && requiredConstructor.code !== null) return "";
46062
46780
  return `(${parameters.join(", ")})`;
46063
46781
  }
46782
+ function renderParameter(context, argument2) {
46783
+ const declaration = `${renderType(context, argument2.type)} ${argument2.name}`;
46784
+ if (argument2.default === null) return declaration;
46785
+ return `${declaration} = ${renderParameterDefault(context, argument2)}`;
46786
+ }
46787
+ function renderParameterDefault(context, argument2) {
46788
+ const value = argument2.default?.value;
46789
+ if (value === null || value === void 0) return "null";
46790
+ if (argument2.type.kind === "enum") {
46791
+ if (typeof value !== "string") {
46792
+ throw new Error(
46793
+ `Parameter ${argument2.name} stores an enum default that is not an option id.`
46794
+ );
46795
+ }
46796
+ const schemaEnum = required(context.enums, argument2.type.enumId, "enum");
46797
+ const option = schemaEnum.options.find(
46798
+ (candidate) => candidate.id === value || candidate.key === value
46799
+ );
46800
+ if (option === void 0) {
46801
+ throw new Error(
46802
+ `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.`
46803
+ );
46804
+ }
46805
+ return `.${option.name}`;
46806
+ }
46807
+ if (argument2.type.kind === "decimal" && typeof value === "string") {
46808
+ return value;
46809
+ }
46810
+ if (typeof value === "string") return quote(value);
46811
+ if (typeof value === "number") return formatNeoNumber(value);
46812
+ if (typeof value === "boolean") return String(value);
46813
+ throw new Error(
46814
+ `Parameter ${argument2.name} stores a default that is not a constant value.`
46815
+ );
46816
+ }
46064
46817
  function emitInitBlock(code) {
46065
46818
  if (code.trim().length === 0) return "init {\n}";
46066
46819
  return `init {
@@ -46075,7 +46828,7 @@ function emitConstructor(context, schemaClass2, declared) {
46075
46828
  ...docsTextLines(declared.docsText),
46076
46829
  id(declared.id).trimEnd()
46077
46830
  ];
46078
- const parameters = declared.arguments.map((argument2) => `${renderType(context, argument2.type)} ${argument2.name}`).join(", ");
46831
+ const parameters = declared.arguments.map((argument2) => renderParameter(context, argument2)).join(", ");
46079
46832
  const baseClause = declared.baseArguments === void 0 || declared.baseArguments.length === 0 ? "" : `
46080
46833
  : base(${declared.baseArguments.map((argument2) => `${argument2.name}: ${argument2.code}`).join(", ")})`;
46081
46834
  const code = declared.code ?? "";
@@ -46145,9 +46898,7 @@ function emitInterface(context, value) {
46145
46898
  return `${emitDocsText(member.docsText)}${id(member.id)}${access}${renderType(context, member.type)} ${member.name} { get;${member.settable ? " set;" : ""} }`;
46146
46899
  }
46147
46900
  const deferred = member.deferred ? "async " : "";
46148
- return `${emitDocsText(member.docsText)}${id(member.id)}${access}${deferred}${renderReturnType(context, member.returnType)} ${member.name}(${member.arguments.map(
46149
- (argument2) => `${renderType(context, argument2.type)} ${argument2.name}`
46150
- ).join(", ")});`;
46901
+ return `${emitDocsText(member.docsText)}${id(member.id)}${access}${deferred}${renderReturnType(context, member.returnType)} ${member.name}(${member.arguments.map((argument2) => renderParameter(context, argument2)).join(", ")});`;
46151
46902
  });
46152
46903
  return `${emitDocsText(value.docsText)}${id(value.id)}interface ${value.name}${bases.length ? ` : ${bases.join(", ")}` : ""} {
46153
46904
  ${members.map((member) => indentNeoSourceNonEmptyLines(member, 2)).join("\n\n")}
@@ -46195,9 +46946,7 @@ ${indentNeoSourceNonEmptyLines(setter, 4)}
46195
46946
  ${prefix}${renderType(context, member.returnType)} ${member.name}${body}`;
46196
46947
  }
46197
46948
  if (member.kind === "function" || member.kind === "scriptFunction") {
46198
- const signature = `${prefix}${member.deferred ? "async " : ""}${renderReturnType(context, member.returnType)} ${member.name}(${member.arguments.map(
46199
- (argument2) => `${renderType(context, argument2.type)} ${argument2.name}`
46200
- ).join(", ")})`;
46949
+ const signature = `${prefix}${member.deferred ? "async " : ""}${renderReturnType(context, member.returnType)} ${member.name}(${member.arguments.map((argument2) => renderParameter(context, argument2)).join(", ")})`;
46201
46950
  const tracked = member.kind === "scriptFunction" ? member.script?.sourceText ?? uiFunctionSource(context, member) : null;
46202
46951
  const body = tracked === null ? null : emitFunctionBody(tracked);
46203
46952
  const abstractContract = member.modifier === "abstract" || member.modifier === "abstractOverride";
@@ -50592,9 +51341,14 @@ function collectFunctions(args) {
50592
51341
  for (const action of node.actions) {
50593
51342
  if (!isObjectRecord2(action) || action.type !== 0 || !isObjectRecord2(action.logic))
50594
51343
  continue;
50595
- if (action.logic.sourceInline === true || action.logic.type === 0 && isCompleteUIAction(action.logic.action))
50596
- continue;
50597
51344
  const useId = stringField(action, "id");
51345
+ if (action.logic.sourceInline === true) continue;
51346
+ if (action.logic.type === 0) {
51347
+ if (isCompleteUIAction(action.logic.action)) continue;
51348
+ throw new Error(
51349
+ `Dialogue action "${useId}" on actions node "${nodeId}" is incomplete. Complete or remove the action in Neo Compose before pulling.`
51350
+ );
51351
+ }
50598
51352
  add(action.logic, `action:${useId}`, "void");
50599
51353
  }
50600
51354
  }
@@ -51280,13 +52034,13 @@ function withPersistedConstructorSignatures(index, classes, constructors) {
51280
52034
  if (required2 !== void 0) {
51281
52035
  persistedRequiredByClassName.set(
51282
52036
  schemaClass2.name,
51283
- required2.arguments.map((argument2) => argument2.name)
52037
+ required2.arguments.map(persistedParameter)
51284
52038
  );
51285
52039
  }
51286
52040
  }
51287
52041
  const overloads = (schemaClass2.constructorIds ?? []).flatMap((id2) => {
51288
52042
  const constructor2 = byId.get(id2);
51289
- return constructor2 === void 0 ? [] : [constructor2.arguments.map((argument2) => argument2.name)];
52043
+ return constructor2 === void 0 ? [] : [constructor2.arguments.map(persistedParameter)];
51290
52044
  });
51291
52045
  if (overloads.length > 0) {
51292
52046
  persistedByClassName.set(schemaClass2.name, overloads);
@@ -51298,6 +52052,10 @@ function withPersistedConstructorSignatures(index, classes, constructors) {
51298
52052
  persistedRequiredByClassName
51299
52053
  };
51300
52054
  }
52055
+ function persistedParameter(argument2) {
52056
+ const hasDefault = argument2.default !== null && argument2.default !== void 0;
52057
+ return { name: argument2.name, defaulted: hasDefault };
52058
+ }
51301
52059
  function declaresConstructors(index, className) {
51302
52060
  if (className === null) return false;
51303
52061
  if (index.requiredByClassName.has(className)) return true;
@@ -51307,16 +52065,24 @@ function declaresConstructors(index, className) {
51307
52065
  function declaresParameterlessConstructor(index, className) {
51308
52066
  if (className === null) return false;
51309
52067
  const required2 = index.requiredByClassName.get(className);
51310
- if (required2 !== void 0 && required2.parameters.length === 0) return true;
52068
+ if (required2 !== void 0 && manifestListIsCallableBare(required2.parameters)) {
52069
+ return true;
52070
+ }
51311
52071
  const persistedRequired = index.persistedRequiredByClassName.get(className);
51312
- if (persistedRequired !== void 0 && persistedRequired.length === 0) {
52072
+ if (persistedRequired !== void 0 && persistedListIsCallableBare(persistedRequired)) {
51313
52073
  return true;
51314
52074
  }
51315
52075
  const declared = index.byClassName.get(className);
51316
- if (declared?.some((entry) => entry.parameters.length === 0) === true) {
52076
+ if (declared?.some((entry) => manifestListIsCallableBare(entry.parameters)) === true) {
51317
52077
  return true;
51318
52078
  }
51319
- return index.persistedByClassName.get(className)?.some((parameters) => parameters.length === 0) ?? false;
52079
+ return index.persistedByClassName.get(className)?.some(persistedListIsCallableBare) ?? false;
52080
+ }
52081
+ function manifestListIsCallableBare(parameters) {
52082
+ return parameters.every((parameter4) => parameter4.default !== null);
52083
+ }
52084
+ function persistedListIsCallableBare(parameters) {
52085
+ return parameters.every((parameter4) => parameter4.defaulted);
51320
52086
  }
51321
52087
  function initializerRequiresEvaluation(index, expression, targetClassName, runtimeIdentifiers = /* @__PURE__ */ new Set()) {
51322
52088
  if (expression.kind === "annotated") {
@@ -51346,7 +52112,11 @@ function requiredConstructorParameterNames(index, className) {
51346
52112
  if (required2 !== void 0) {
51347
52113
  return new Set(required2.parameters.map((parameter4) => parameter4.name));
51348
52114
  }
51349
- return new Set(index.persistedRequiredByClassName.get(className) ?? []);
52115
+ return new Set(
52116
+ (index.persistedRequiredByClassName.get(className) ?? []).map(
52117
+ (parameter4) => parameter4.name
52118
+ )
52119
+ );
51350
52120
  }
51351
52121
  function expressionReadsRuntimeIdentifier(expression, runtimeIdentifiers) {
51352
52122
  if (runtimeIdentifiers.size === 0) return false;
@@ -51438,7 +52208,8 @@ function validateDeclaredConstructorOverloads(declaration) {
51438
52208
  id: declared.id ?? `${declaration.name}#${String(index)}`,
51439
52209
  parameters: declared.parameters.map((parameter4) => ({
51440
52210
  name: parameter4.name,
51441
- typeKey: positionalTypeKey(parameter4.type)
52211
+ typeKey: positionalTypeKey(parameter4.type),
52212
+ defaulted: parameter4.default !== null
51442
52213
  }))
51443
52214
  }))
51444
52215
  ).map((error) => ({
@@ -51464,6 +52235,102 @@ var init_declared_constructors2 = __esm({
51464
52235
  }
51465
52236
  });
51466
52237
 
52238
+ // src/project-source/lower-parameter-defaults.ts
52239
+ function lowerParameterDefault(context, parameter4, loweredType, path) {
52240
+ if (parameter4.default === null) return null;
52241
+ const expression = parseExpression(parameter4.default);
52242
+ return {
52243
+ value: lowerParameterDefaultValue(context, expression, loweredType, path),
52244
+ source: span({ source: parameter4.source })
52245
+ };
52246
+ }
52247
+ function lowerParameterDefaultValue(context, expression, type, path) {
52248
+ switch (expression.kind) {
52249
+ case "litNull":
52250
+ if (!type.nullable) {
52251
+ throw new Error(
52252
+ `Parameter ${path} defaults to null, but its type is not nullable.`
52253
+ );
52254
+ }
52255
+ return null;
52256
+ case "litBool":
52257
+ if (type.kind !== "bool") {
52258
+ throw new Error(
52259
+ `Parameter ${path} defaults to a bool literal, but its type is ${type.kind}.`
52260
+ );
52261
+ }
52262
+ return expression.value;
52263
+ case "litString":
52264
+ if (type.kind !== "string") {
52265
+ throw new Error(
52266
+ `Parameter ${path} defaults to a string literal, but its type is ${type.kind}.`
52267
+ );
52268
+ }
52269
+ return expression.value;
52270
+ case "litInt":
52271
+ if (type.kind === "decimal") return expression.raw;
52272
+ if (type.kind !== "int" && type.kind !== "float") {
52273
+ throw new Error(
52274
+ `Parameter ${path} defaults to a number literal, but its type is ${type.kind}.`
52275
+ );
52276
+ }
52277
+ return expression.value;
52278
+ case "litFloat":
52279
+ if (type.kind === "decimal") return expression.raw;
52280
+ if (type.kind !== "float") {
52281
+ throw new Error(
52282
+ `Parameter ${path} defaults to a fractional literal, but its type is ${type.kind}.`
52283
+ );
52284
+ }
52285
+ return expression.value;
52286
+ case "unary": {
52287
+ if (expression.op !== "-") {
52288
+ throw new Error(
52289
+ `Parameter ${path} default uses unary ${JSON.stringify(expression.op)}, which is not a constant spelling.`
52290
+ );
52291
+ }
52292
+ const operand = lowerParameterDefaultValue(
52293
+ context,
52294
+ expression.operand,
52295
+ type,
52296
+ path
52297
+ );
52298
+ if (typeof operand === "number") return -operand;
52299
+ if (type.kind === "decimal" && typeof operand === "string") {
52300
+ return operand.startsWith("-") ? operand.slice(1) : `-${operand}`;
52301
+ }
52302
+ throw new Error(
52303
+ `Parameter ${path} default applies unary minus to a non-numeric literal.`
52304
+ );
52305
+ }
52306
+ case "contextualEnum": {
52307
+ if (type.kind !== "enum") {
52308
+ throw new Error(
52309
+ `Parameter ${path} defaults to enum option .${expression.name}, but its type is ${type.kind}.`
52310
+ );
52311
+ }
52312
+ const optionId = context.enumOptionsByName.get(type.enumId)?.get(expression.name);
52313
+ if (optionId === void 0) {
52314
+ throw new Error(
52315
+ `Parameter ${path} defaults to .${expression.name}, which its enum does not declare.`
52316
+ );
52317
+ }
52318
+ return optionId;
52319
+ }
52320
+ default:
52321
+ throw new Error(
52322
+ `Parameter ${path} default is not a constant expression.`
52323
+ );
52324
+ }
52325
+ }
52326
+ var init_lower_parameter_defaults = __esm({
52327
+ "src/project-source/lower-parameter-defaults.ts"() {
52328
+ "use strict";
52329
+ init_src();
52330
+ init_lower_support();
52331
+ }
52332
+ });
52333
+
51467
52334
  // src/project-source/init-source.ts
51468
52335
  function commentEndIndex(source, index) {
51469
52336
  if (source[index] !== "/") return null;
@@ -51700,12 +52567,21 @@ function lowerClassConstructors(context, declaration, classId, lowerParameterTyp
51700
52567
  const declared = declaration.constructors.map((declared2) => {
51701
52568
  const id2 = declaredConstructorId2(declaration, declared2);
51702
52569
  const base = context.baseConstructors.get(id2);
51703
- const parameters = declared2.parameters.map((parameter4) => ({
51704
- name: parameter4.name,
51705
- type: lowerParameterType(parameter4.type, declaration),
51706
- source: span({ source: parameter4.source }),
51707
- selectionSpan: span({ source: parameter4.source })
51708
- }));
52570
+ const parameters = declared2.parameters.map((parameter4) => {
52571
+ const parameterType = lowerParameterType(parameter4.type, declaration);
52572
+ return {
52573
+ name: parameter4.name,
52574
+ type: parameterType,
52575
+ default: lowerParameterDefault(
52576
+ context,
52577
+ parameter4,
52578
+ parameterType,
52579
+ `${declaration.name}.${declared2.name}(${parameter4.name})`
52580
+ ),
52581
+ source: span({ source: parameter4.source }),
52582
+ selectionSpan: span({ source: parameter4.source })
52583
+ };
52584
+ });
51709
52585
  const baseArguments = (declared2.baseArguments ?? []).map((argument2) => ({
51710
52586
  name: argument2.name,
51711
52587
  code: argument2.expression.trim()
@@ -51746,12 +52622,21 @@ function lowerRequiredConstructor(context, declaration, classId, lowerParameterT
51746
52622
  selectionSpan: sourceSpan
51747
52623
  },
51748
52624
  classId,
51749
- arguments: required2.parameters.map((parameter4) => ({
51750
- name: parameter4.name,
51751
- type: lowerParameterType(parameter4.type, declaration),
51752
- source: span({ source: parameter4.source }),
51753
- selectionSpan: span({ source: parameter4.source })
51754
- })),
52625
+ arguments: required2.parameters.map((parameter4) => {
52626
+ const parameterType = lowerParameterType(parameter4.type, declaration);
52627
+ return {
52628
+ name: parameter4.name,
52629
+ type: parameterType,
52630
+ default: lowerParameterDefault(
52631
+ context,
52632
+ parameter4,
52633
+ parameterType,
52634
+ `${declaration.name}(${parameter4.name})`
52635
+ ),
52636
+ source: span({ source: parameter4.source }),
52637
+ selectionSpan: span({ source: parameter4.source })
52638
+ };
52639
+ }),
51755
52640
  code: requiredConstructorBody(required2.body, base?.code),
51756
52641
  ...baseArguments.length === 0 ? {} : {
51757
52642
  baseArguments: baseArguments.map(
@@ -51834,10 +52719,10 @@ function recordBaseParameterNames(context, baseName, suppliedNames) {
51834
52719
  function selectOverload(candidates, suppliedNames) {
51835
52720
  if (candidates.length === 0) return null;
51836
52721
  if (candidates.length === 1) return candidates[0];
51837
- const key = argumentNameSetKey2(suppliedNames);
51838
- return candidates.find((names) => argumentNameSetKey2(names) === key) ?? null;
52722
+ const key = argumentNameSetKey(suppliedNames);
52723
+ return candidates.find((names) => argumentNameSetKey(names) === key) ?? null;
51839
52724
  }
51840
- function argumentNameSetKey2(names) {
52725
+ function argumentNameSetKey(names) {
51841
52726
  return [...names].map((name) => name.toLowerCase()).sort().join(",");
51842
52727
  }
51843
52728
  function baseTypeName(declaration) {
@@ -51876,6 +52761,7 @@ var init_lower_constructors = __esm({
51876
52761
  init_src();
51877
52762
  init_required_constructor_id();
51878
52763
  init_declared_constructors2();
52764
+ init_lower_parameter_defaults();
51879
52765
  init_init_source();
51880
52766
  init_lower_support();
51881
52767
  }
@@ -52223,12 +53109,21 @@ function lowerMemberKind(context, ownerClass, declaration, id2, owner) {
52223
53109
  if (declaration.kind === "function") {
52224
53110
  const returnType = declaration.type.name === "void" ? { kind: "void", nullable: false } : lowerType(context, declaration.type, ownerClass);
52225
53111
  const argumentsValue = declaration.parameters.map(
52226
- (parameter4) => ({
52227
- name: parameter4.name,
52228
- type: lowerType(context, parameter4.type, ownerClass),
52229
- source: span(parameter4),
52230
- selectionSpan: span(parameter4)
52231
- })
53112
+ (parameter4) => {
53113
+ const parameterType = lowerType(context, parameter4.type, ownerClass);
53114
+ return {
53115
+ name: parameter4.name,
53116
+ type: parameterType,
53117
+ default: lowerParameterDefault(
53118
+ context,
53119
+ parameter4,
53120
+ parameterType,
53121
+ `${ownerClass.name}.${declaration.name}(${parameter4.name})`
53122
+ ),
53123
+ source: span(parameter4),
53124
+ selectionSpan: span(parameter4)
53125
+ };
53126
+ }
52232
53127
  );
52233
53128
  const settings = annotation(declaration.annotations, "settings");
52234
53129
  const logicMode = contextualEnumArgument(settings, "logic");
@@ -52458,6 +53353,7 @@ function lowerFieldMember(context, ownerClass, declaration, id2, commonInput, ba
52458
53353
  arguments: fieldType.arguments.slice(1).map((argumentType, index) => ({
52459
53354
  name: `p${index + 1}`,
52460
53355
  type: lowerType(context, argumentType, ownerClass),
53356
+ default: null,
52461
53357
  source: span(declaration),
52462
53358
  selectionSpan: span(declaration)
52463
53359
  }))
@@ -52482,6 +53378,7 @@ function lowerFieldMember(context, ownerClass, declaration, id2, commonInput, ba
52482
53378
  arguments: fieldType.arguments.map((argumentType, index) => ({
52483
53379
  name: `p${index + 1}`,
52484
53380
  type: lowerType(context, argumentType, ownerClass),
53381
+ default: null,
52485
53382
  source: span(declaration),
52486
53383
  selectionSpan: span(declaration)
52487
53384
  }))
@@ -52941,12 +53838,21 @@ function lowerInterface(context, declaration) {
52941
53838
  name: member.name,
52942
53839
  ...member.docsText === void 0 ? {} : { docsText: member.docsText },
52943
53840
  returnType: member.type.name === "void" ? { kind: "void", nullable: false } : lowerType(context, member.type),
52944
- arguments: member.parameters.map((parameter4) => ({
52945
- name: parameter4.name,
52946
- type: lowerType(context, parameter4.type),
52947
- source: span(parameter4),
52948
- selectionSpan: span(parameter4)
52949
- })),
53841
+ arguments: member.parameters.map((parameter4) => {
53842
+ const parameterType = lowerType(context, parameter4.type);
53843
+ return {
53844
+ name: parameter4.name,
53845
+ type: parameterType,
53846
+ default: lowerParameterDefault(
53847
+ context,
53848
+ parameter4,
53849
+ parameterType,
53850
+ `${declaration.name}.${member.name}(${parameter4.name})`
53851
+ ),
53852
+ source: span(parameter4),
53853
+ selectionSpan: span(parameter4)
53854
+ };
53855
+ }),
52950
53856
  deferred: member.modifiers.includes("async"),
52951
53857
  accessModifier,
52952
53858
  source
@@ -53471,6 +54377,16 @@ function lowerExpressionValue(context, expression, declaredExpected, ownerClass,
53471
54377
  if (expression.callee.kind === "ident" && expression.callee.name === "Reference") {
53472
54378
  const index = expression.argumentNames?.findIndex((name) => name === "id") ?? -1;
53473
54379
  if (index >= 0) {
54380
+ if (expression.argumentNames?.includes("withProvenance") === true) {
54381
+ throw new Error(
54382
+ `${path} writes Reference(id: ..., withProvenance: ...) as a persisted member value. Provenance-aware references are executable NeoScript values and must be used inside a function or delegate closure.`
54383
+ );
54384
+ }
54385
+ if (expression.args.length !== 1 || expression.argumentNames?.some((name) => name !== "id")) {
54386
+ throw new Error(
54387
+ `${path} writes Reference(id: ...) with unsupported arguments.`
54388
+ );
54389
+ }
53474
54390
  const idArgument = expression.args[index];
53475
54391
  if (idArgument?.kind === "litString") return idArgument.value;
53476
54392
  throw new Error(
@@ -54264,6 +55180,7 @@ var init_lower_members = __esm({
54264
55180
  init_src();
54265
55181
  init_lower_support();
54266
55182
  init_lower_constructors();
55183
+ init_lower_parameter_defaults();
54267
55184
  init_declared_constructors2();
54268
55185
  init_init_source();
54269
55186
  init_ui_action_source();
@@ -54399,7 +55316,8 @@ function createNeoScriptDocumentContext(context, projectOverride) {
54399
55316
  const parameters = context.functionArguments?.map((argument2, index) => ({
54400
55317
  id: `function-parameter:${index}:${argument2.name}`,
54401
55318
  name: argument2.name,
54402
- type: toLanguageType(argument2, context)
55319
+ type: toLanguageType(argument2, context),
55320
+ ...parameterDefaultDescriptor(argument2, context)
54403
55321
  }));
54404
55322
  return {
54405
55323
  kind: documentKind,
@@ -54421,6 +55339,32 @@ function createNeoScriptDocumentContext(context, projectOverride) {
54421
55339
  } : {}
54422
55340
  };
54423
55341
  }
55342
+ function parameterDefaultDescriptor(argument2, context) {
55343
+ if (argument2.defaultValue === void 0) return {};
55344
+ const value = argument2.defaultValue.value;
55345
+ const enumOptionName = argument2.type === 8 /* Enum */ && typeof value === "string" ? analyzerEnumOptionName(argument2.enumId, value, context) : void 0;
55346
+ return {
55347
+ defaultValue: {
55348
+ displayText: neoScriptParameterDefaultDisplayText({
55349
+ value,
55350
+ kind: parameterDefaultSpellingKind(argument2.type),
55351
+ ...enumOptionName === void 0 ? {} : { enumOptionName }
55352
+ }),
55353
+ value
55354
+ }
55355
+ };
55356
+ }
55357
+ function parameterDefaultSpellingKind(type) {
55358
+ if (type === 8 /* Enum */) return "enum";
55359
+ if (type === 20 /* Decimal */) return "decimal";
55360
+ return "other";
55361
+ }
55362
+ function analyzerEnumOptionName(enumId, optionId, context) {
55363
+ const enumDefinition = context.vm.enums.find(
55364
+ (candidate) => candidate.id === enumId
55365
+ );
55366
+ return enumDefinition?.options[optionId]?.name;
55367
+ }
54424
55368
  function createNeoScriptProject(context) {
54425
55369
  const languageTypes = [];
54426
55370
  for (const schemaClass2 of context.vm.classes) {
@@ -54708,7 +55652,8 @@ function declaredConstructors(schemaClass2, context) {
54708
55652
  parameters: record3.argumentTypes.map((argument2) => ({
54709
55653
  name: argument2.name,
54710
55654
  type: toLanguageType(argument2, context),
54711
- required: argument2.required
55655
+ required: argument2.required,
55656
+ ...parameterDefaultDescriptor(argument2, context)
54712
55657
  })),
54713
55658
  ...record3.docsText ? { documentation: record3.docsText } : {},
54714
55659
  ...record3.id === required2 ? { required: true } : {}
@@ -54784,7 +55729,8 @@ function memberToSymbol(record3, schemaKey, containingClass2, ownerClassId, inde
54784
55729
  (argument2, argumentIndex) => ({
54785
55730
  id: `${record3.id}:argument:${argumentIndex}`,
54786
55731
  name: argument2.name,
54787
- type: toLanguageType(argument2, context, genericEnvironment)
55732
+ type: toLanguageType(argument2, context, genericEnvironment),
55733
+ ...parameterDefaultDescriptor(argument2, context)
54788
55734
  })
54789
55735
  ),
54790
55736
  deferred: authoredCallable.deferred,
@@ -54955,7 +55901,8 @@ function interfaceMemberToSymbol(neoInterface, key, member, context, inherited)
54955
55901
  parameters: member.argumentTypes.map((argument2, index) => ({
54956
55902
  id: `${neoInterface.id}:member:${key}:argument:${index}`,
54957
55903
  name: argument2.name,
54958
- type: toLanguageType(argument2, context)
55904
+ type: toLanguageType(argument2, context),
55905
+ ...parameterDefaultDescriptor(argument2, context)
54959
55906
  })),
54960
55907
  deferred: member.deferred,
54961
55908
  abstract: true,
@@ -56535,13 +57482,13 @@ function resolveBaseConstructorOverload(args, owner) {
56535
57482
  `Constructor "${args.constructor.id}" declares a base call, but base class "${baseClass.name}" declares no constructors.`
56536
57483
  );
56537
57484
  }
56538
- const requested = argumentNameSetKey3(
57485
+ const requested = argumentNameSetKey2(
56539
57486
  (args.constructor.baseArguments ?? []).map(
56540
57487
  (baseArgument) => baseArgument.name
56541
57488
  )
56542
57489
  );
56543
57490
  const matches = candidates.filter(
56544
- (candidate) => argumentNameSetKey3(
57491
+ (candidate) => argumentNameSetKey2(
56545
57492
  candidate.argumentTypes.map((argument2) => argument2.name)
56546
57493
  ) === requested
56547
57494
  );
@@ -56597,7 +57544,7 @@ function declaredConstructorsOfClass(constructors, schemaClass2) {
56597
57544
  return [record3];
56598
57545
  });
56599
57546
  }
56600
- function argumentNameSetKey3(names) {
57547
+ function argumentNameSetKey2(names) {
56601
57548
  return [...names].map((name) => name.toLowerCase()).sort().join(", ");
56602
57549
  }
56603
57550
  function describeConstructorOverloads(constructors) {
@@ -59019,13 +59966,14 @@ function evaluatorOwnershipDistances(rowId, indexes) {
59019
59966
  indexes.ownershipDistancesByRowId.set(rowId, distances);
59020
59967
  return distances;
59021
59968
  }
59022
- function resolveRuntimeReferenceRow(sourceValueId, ctx) {
59969
+ function resolveRuntimeReferenceRow(sourceValueId, ctx, withProvenance) {
59023
59970
  const direct = evalValueById(
59024
59971
  ctx,
59025
59972
  sourceValueId,
59026
59973
  ctx.__runtimeSessionValues,
59027
59974
  ctx.__valueOverlay
59028
59975
  );
59976
+ if (!withProvenance) return direct;
59029
59977
  const receiver = trackedRowForValueReference(ctx.thisValue, ctx);
59030
59978
  if (receiver === null) return direct;
59031
59979
  const indexes = evaluatorIndexes(ctx);
@@ -59911,16 +60859,21 @@ function executeCompiledFunction(action, ctx, args, allowFallthroughReturn, runt
59911
60859
  `Corrupt NSFunction IR: compiled body has ${action.parameters.length - 2} argument parameter(s), but its runtime signature declares ${expectedCount}.`
59912
60860
  );
59913
60861
  }
59914
- if (args.length !== expectedCount) {
60862
+ const filledArgs = runtimeSignature === void 0 ? args : fillTrailingParameterDefaults(
60863
+ args,
60864
+ runtimeSignature.argumentTypes,
60865
+ "NSFunction"
60866
+ );
60867
+ if (filledArgs.length !== expectedCount) {
59915
60868
  throw new NSGetterRuntimeError(
59916
- `NSFunction expected ${expectedCount} argument(s), got ${args.length}.`
60869
+ `NSFunction expected ${expectedCount} argument(s), got ${filledArgs.length}.`
59917
60870
  );
59918
60871
  }
59919
60872
  const scope = createTopLevelScope(ctx);
59920
- for (let index = 0; index < args.length; index += 1) {
60873
+ for (let index = 0; index < filledArgs.length; index += 1) {
59921
60874
  const parameter4 = action.parameters[index + 2];
59922
60875
  const runtimeTypeInfo = runtimeArgumentTypes[index];
59923
- const value2 = args[index];
60876
+ const value2 = filledArgs[index];
59924
60877
  if (!runtimeValueMatchesType(value2, runtimeTypeInfo, ctx)) {
59925
60878
  throw new NSGetterRuntimeError(
59926
60879
  `NSFunction argument ${index + 1} does not match its declared runtime type.`
@@ -59961,6 +60914,57 @@ function executeCompiledFunction(action, ctx, args, allowFallthroughReturn, runt
59961
60914
  }
59962
60915
  return value;
59963
60916
  }
60917
+ function fillTrailingParameterDefaults(args, argumentTypes, subject) {
60918
+ const maxArity = argumentTypes.length;
60919
+ const minArity = argumentTypes.filter(
60920
+ (parameter4) => !parameterHasDefault(parameter4)
60921
+ ).length;
60922
+ const expectedArity = minArity === maxArity ? `${maxArity} argument(s)` : `between ${minArity} and ${maxArity} argument(s)`;
60923
+ if (args.length > maxArity) {
60924
+ throw new NSGetterRuntimeError(
60925
+ `${subject} expected ${expectedArity}, got ${args.length}.`
60926
+ );
60927
+ }
60928
+ if (args.length < minArity) {
60929
+ throw new NSGetterRuntimeError(
60930
+ `${subject} expected ${expectedArity}, got ${args.length}.`
60931
+ );
60932
+ }
60933
+ if (args.length === maxArity) return args;
60934
+ const filled = [...args];
60935
+ for (let index = args.length; index < maxArity; index += 1) {
60936
+ const parameter4 = argumentTypes[index];
60937
+ if (parameter4 === void 0) {
60938
+ throw new NSGetterRuntimeError(
60939
+ `${subject} has a hole in its argument types at position ${index}.`
60940
+ );
60941
+ }
60942
+ filled.push(parameterDefaultRuntimeValue(parameter4, subject));
60943
+ }
60944
+ return filled;
60945
+ }
60946
+ function parameterDefaultRuntimeValue(parameter4, subject) {
60947
+ const defaultValue = parameter4.defaultValue;
60948
+ if (defaultValue === void 0) {
60949
+ throw new NSGetterRuntimeError(
60950
+ `${subject} parameter '${parameter4.name}' was omitted but declares no default.`
60951
+ );
60952
+ }
60953
+ if (defaultValue.value === null) return null;
60954
+ if (parameter4.type === 8 /* Enum */) return [defaultValue.value];
60955
+ return defaultValue.value;
60956
+ }
60957
+ function fillCallableCallSiteArguments(args, member, ctx) {
60958
+ if (member === null) return args;
60959
+ if (member.kind !== 13 /* Function */ && member.kind !== 23 /* NSFunction */) {
60960
+ return args;
60961
+ }
60962
+ const signature = resolveCallableSignature(member.id, member.kind, ctx);
60963
+ if (signature === null) return args;
60964
+ if (!hasAnyParameterDefault(signature.argumentTypes)) return args;
60965
+ const subject = member.kind === 13 /* Function */ ? `Function '${member.name}'` : `NSFunction '${member.name}'`;
60966
+ return fillTrailingParameterDefaults(args, signature.argumentTypes, subject);
60967
+ }
59964
60968
  function createChildScope(parent) {
59965
60969
  return new NeoScriptScope(parent);
59966
60970
  }
@@ -61180,7 +62184,11 @@ function evalPointer(pointer, scope, ctx) {
61180
62184
  return scope.get(pointer.variableId);
61181
62185
  }
61182
62186
  case "reference" /* reference */: {
61183
- const row = resolveRuntimeReferenceRow(pointer.valueId, ctx);
62187
+ const row = resolveRuntimeReferenceRow(
62188
+ pointer.valueId,
62189
+ ctx,
62190
+ pointer.withProvenance === true
62191
+ );
61184
62192
  if (!row) {
61185
62193
  throw new NSGetterRuntimeError(
61186
62194
  `Missing value reference: ${pointer.valueId}`
@@ -61257,8 +62265,11 @@ function evalPointer(pointer, scope, ctx) {
61257
62265
  if (pointer.receiver.kind === "instance" && pointer.optional === true && (innerThis === null || innerThis === void 0)) {
61258
62266
  return null;
61259
62267
  }
61260
- const args = pointer.args.map((arg) => evalPointer(arg, scope, ctx));
62268
+ const suppliedArgs = pointer.args.map(
62269
+ (arg) => evalPointer(arg, scope, ctx)
62270
+ );
61261
62271
  const member = pointer.receiver.kind === "static" ? evalMemberById(ctx.vm, pointer.receiver.memberId) : resolveEffectiveCallableMember(pointer, innerThis, ctx);
62272
+ const args = fillCallableCallSiteArguments(suppliedArgs, member, ctx);
61262
62273
  const interceptedMemberId = member?.id ?? pointer.memberId ?? pointer.memberKey ?? pointer.callSiteId;
61263
62274
  consumeBudget(ctx, "workUnits", 1, "work unit");
61264
62275
  const intercepted = ctx.callInterceptor?.({
@@ -61781,13 +62792,21 @@ function substituteCallableSignatureForReceiver(signature, receiver, ctx) {
61781
62792
  ctx
61782
62793
  ),
61783
62794
  argumentTypes: signature.argumentTypes.map((argument2) => {
62795
+ if (!typeInfoContainsGeneric(argument2)) return argument2;
61784
62796
  const substituted = substituteRuntimeTypeInfo(argument2, env, ctx);
61785
62797
  if (substituted.type === NS_TYPE_VOID) {
61786
62798
  throw new NSGetterRuntimeError(
61787
62799
  `Generic NSFunction argument '${argument2.name}' resolved to Void.`
61788
62800
  );
61789
62801
  }
61790
- return { ...substituted, name: argument2.name };
62802
+ const named = { ...substituted, name: argument2.name };
62803
+ if (argument2.defaultValue === void 0) return named;
62804
+ if (argument2.defaultValue.value !== null) {
62805
+ throw new NSGetterRuntimeError(
62806
+ `Generic NSFunction parameter '${argument2.name}' carries a non-null constant default, which a generic parameter cannot declare.`
62807
+ );
62808
+ }
62809
+ return { ...named, defaultValue: { value: null } };
61791
62810
  })
61792
62811
  };
61793
62812
  } catch (error) {
@@ -64262,15 +65281,21 @@ function resolveDeclaredConstructorRecord(info, schemaClass2, ctx) {
64262
65281
  `Declared constructor call on '${schemaClass2.name}' passes the same argument name twice.`
64263
65282
  );
64264
65283
  }
64265
- if (suppliedNames.length !== record3.argumentTypes.length) {
65284
+ const supplied = new Set(suppliedNames);
65285
+ for (const parameter4 of record3.argumentTypes) {
65286
+ if (supplied.has(parameter4.name)) continue;
65287
+ if (parameterHasDefault(parameter4)) continue;
64266
65288
  throw new NSGetterRuntimeError(
64267
- `Constructor '${record3.id}' on '${schemaClass2.name}' declares ${record3.argumentTypes.length} parameter(s) but the call site passes ${suppliedNames.length}.`
65289
+ `Declared constructor call on '${schemaClass2.name}' has no argument for parameter '${parameter4.name}'.`
64268
65290
  );
64269
65291
  }
64270
- for (const parameter4 of record3.argumentTypes) {
64271
- if (suppliedNames.includes(parameter4.name)) continue;
65292
+ const declaredNames = new Set(
65293
+ record3.argumentTypes.map((parameter4) => parameter4.name)
65294
+ );
65295
+ for (const name of suppliedNames) {
65296
+ if (declaredNames.has(name)) continue;
64272
65297
  throw new NSGetterRuntimeError(
64273
- `Declared constructor call on '${schemaClass2.name}' has no argument for parameter '${parameter4.name}'.`
65298
+ `Declared constructor call on '${schemaClass2.name}' names unknown parameter '${name}'.`
64274
65299
  );
64275
65300
  }
64276
65301
  return record3;
@@ -64281,6 +65306,12 @@ function evaluateDeclaredConstructorArguments(info, record3, scope, ctx) {
64281
65306
  byName.set(argument2.name, evalPointer(argument2.valuePointer, scope, ctx));
64282
65307
  }
64283
65308
  return record3.argumentTypes.map((parameter4) => {
65309
+ if (!byName.has(parameter4.name)) {
65310
+ return parameterDefaultRuntimeValue(
65311
+ parameter4,
65312
+ `Constructor '${record3.id}'`
65313
+ );
65314
+ }
64284
65315
  const value = byName.get(parameter4.name);
64285
65316
  if (parameter4.type !== 20 /* Decimal */) return value;
64286
65317
  if (typeof value !== "number") return value;
@@ -64311,7 +65342,7 @@ function resolveBaseConstructorRecord(record3, ctx) {
64311
65342
  if (baseArguments.length === 0) {
64312
65343
  if (candidates.length === 0) return null;
64313
65344
  const parameterless = candidates.find(
64314
- (candidate) => candidate.argumentTypes.length === 0
65345
+ (candidate) => candidate.argumentTypes.every(parameterHasDefault)
64315
65346
  );
64316
65347
  if (parameterless === void 0) {
64317
65348
  throw new NSGetterRuntimeError(
@@ -64322,17 +65353,32 @@ function resolveBaseConstructorRecord(record3, ctx) {
64322
65353
  }
64323
65354
  const names = new Set(baseArguments.map((argument2) => argument2.name));
64324
65355
  const matches = candidates.filter(
64325
- (candidate) => candidate.argumentTypes.length === names.size && candidate.argumentTypes.every((parameter4) => names.has(parameter4.name))
65356
+ (candidate) => candidate.argumentTypes.every(
65357
+ (parameter4) => names.has(parameter4.name) || parameterHasDefault(parameter4)
65358
+ ) && [...names].every(
65359
+ (name) => candidate.argumentTypes.some((parameter4) => parameter4.name === name)
65360
+ )
64326
65361
  );
64327
- const firstMatch = matches[0];
64328
- if (firstMatch === void 0) {
65362
+ if (matches.length === 0) {
64329
65363
  throw new NSGetterRuntimeError(
64330
65364
  `Constructor '${record3.id}' on '${owningClass.name}' calls ': base(${[...names].join(", ")})', which matches no constructor on its base class.`
64331
65365
  );
64332
65366
  }
64333
- if (matches.length > 1) {
65367
+ const fewestFillIns = Math.min(
65368
+ ...matches.map((candidate) => candidate.argumentTypes.length - names.size)
65369
+ );
65370
+ const best = matches.filter(
65371
+ (candidate) => candidate.argumentTypes.length - names.size === fewestFillIns
65372
+ );
65373
+ const firstMatch = best[0];
65374
+ if (firstMatch === void 0) {
65375
+ throw new NSGetterRuntimeError(
65376
+ `Constructor '${record3.id}' on '${owningClass.name}' resolved ': base(${[...names].join(", ")})' to an empty betterness set.`
65377
+ );
65378
+ }
65379
+ if (best.length > 1) {
64334
65380
  throw new NSGetterRuntimeError(
64335
- `Constructor '${record3.id}' on '${owningClass.name}' calls ': base(${[...names].join(", ")})', which matches ${matches.length} base constructors: ${matches.map((candidate) => candidate.id).join(", ")}.`
65381
+ `Constructor '${record3.id}' on '${owningClass.name}' calls ': base(${[...names].join(", ")})', which matches ${best.length} base constructors: ${best.map((candidate) => candidate.id).join(", ")}.`
64336
65382
  );
64337
65383
  }
64338
65384
  return firstMatch;
@@ -64366,6 +65412,12 @@ function evaluateBaseConstructorArguments(record3, baseRecord, argumentValues, t
64366
65412
  }
64367
65413
  return baseRecord.argumentTypes.map((parameter4) => {
64368
65414
  if (!byName.has(parameter4.name)) {
65415
+ if (parameterHasDefault(parameter4)) {
65416
+ return parameterDefaultRuntimeValue(
65417
+ parameter4,
65418
+ `Constructor '${baseRecord.id}'`
65419
+ );
65420
+ }
64369
65421
  throw new NSGetterRuntimeError(
64370
65422
  `Constructor '${record3.id}' calls ': base(...)' without an argument for base parameter '${parameter4.name}'.`
64371
65423
  );
@@ -66479,12 +67531,15 @@ function isNeoClassConstructorBase(value) {
66479
67531
  if (typeof v.code !== "string" && v.code !== null) return false;
66480
67532
  if (!Array.isArray(v.argumentTypes)) return false;
66481
67533
  const parameterNames = /* @__PURE__ */ new Set();
67534
+ const argumentTypes = [];
66482
67535
  for (const argument2 of v.argumentTypes) {
66483
67536
  if (!isNSFunctionArgumentTypeInfo(argument2)) return false;
66484
67537
  if (!isValidCallableIdentifier(argument2.name)) return false;
66485
67538
  if (parameterNames.has(argument2.name)) return false;
66486
67539
  parameterNames.add(argument2.name);
67540
+ argumentTypes.push(argument2);
66487
67541
  }
67542
+ if (validateParameterDefaults(argumentTypes).length > 0) return false;
66488
67543
  if (v.baseArguments !== void 0 && v.baseArguments !== null) {
66489
67544
  if (!Array.isArray(v.baseArguments)) return false;
66490
67545
  const baseNames = /* @__PURE__ */ new Set();
@@ -76040,7 +77095,7 @@ function stableValue(value) {
76040
77095
  if (Array.isArray(value)) return value.map(stableValue);
76041
77096
  if (!isRecord7(value)) return value;
76042
77097
  const normalized = Object.fromEntries(
76043
- Object.entries(value).filter(([key]) => key !== "name").sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => [key, stableValue(entry)])
77098
+ Object.entries(value).filter(([key]) => key !== "name" && key !== "defaultValue").sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => [key, stableValue(entry)])
76044
77099
  );
76045
77100
  return normalized;
76046
77101
  }
@@ -76142,11 +77197,81 @@ function isOpaqueNSFunctionReturnTypeInfo(value) {
76142
77197
  return isOpaqueNSTypeInfo(value);
76143
77198
  }
76144
77199
  function isOpaqueNSFunctionArgumentTypeInfo(value) {
76145
- return isOpaqueNSTypeInfo(value) && isOpaqueCallableIdentifier(value.name) && !opaqueTypeInfoContainsUnknown(value);
77200
+ return isOpaqueNSTypeInfo(value) && isOpaqueCallableIdentifier(value.name) && !opaqueTypeInfoContainsUnknown(value) && hasValidOpaqueParameterDefault(value);
76146
77201
  }
76147
77202
  function isOpaqueConstructorArgumentTypeInfo(value) {
76148
77203
  if (!isRecord7(value)) return false;
76149
- return isOpaqueNSTypeInfo(value) && (value.name === "value" || isOpaqueCallableIdentifier(value.name)) && !opaqueTypeInfoContainsUnknown(value);
77204
+ return isOpaqueNSTypeInfo(value) && (value.name === "value" || isOpaqueCallableIdentifier(value.name)) && !opaqueTypeInfoContainsUnknown(value) && hasValidOpaqueParameterDefault(value);
77205
+ }
77206
+ function hasValidOpaqueParameterDefault(value) {
77207
+ const wrapper = value.defaultValue;
77208
+ if (wrapper === void 0) return true;
77209
+ if (!isRecord7(wrapper)) return false;
77210
+ const keys = Object.keys(wrapper);
77211
+ if (keys.length !== 1 || keys[0] !== "value") return false;
77212
+ const payload = wrapper.value;
77213
+ if (payload === null) return value.required === false;
77214
+ if (value.type === 1) return typeof payload === "boolean";
77215
+ if (value.type === 2) {
77216
+ return typeof payload === "number" && Number.isInteger(payload);
77217
+ }
77218
+ if (value.type === 4) {
77219
+ return typeof payload === "number" && Number.isFinite(payload);
77220
+ }
77221
+ if (value.type === 3 || value.type === 8 || value.type === 20) {
77222
+ return typeof payload === "string";
77223
+ }
77224
+ return false;
77225
+ }
77226
+ function opaqueParameterDefaultsPlacedLast(argumentTypes) {
77227
+ let seenDefault = false;
77228
+ for (const argument2 of argumentTypes) {
77229
+ if (argument2.defaultValue !== void 0) {
77230
+ seenDefault = true;
77231
+ continue;
77232
+ }
77233
+ if (seenDefault) return false;
77234
+ }
77235
+ return true;
77236
+ }
77237
+ function opaqueArgumentsHaveDefault(argumentTypes) {
77238
+ return argumentTypes.some(
77239
+ (argument2) => isRecord7(argument2) && argument2.defaultValue !== void 0
77240
+ );
77241
+ }
77242
+ function assertOpaqueParameterDefaultsValid(member) {
77243
+ const argumentTypes = member.argumentTypes;
77244
+ if (!Array.isArray(argumentTypes)) return;
77245
+ if (!opaqueArgumentsHaveDefault(argumentTypes)) return;
77246
+ if (member.kind === 25 || member.kind === 26) {
77247
+ throw new Error(
77248
+ `Member "${member.name}" (${member.id}) is a delegate or action, whose parameters are an unnamed positional type list and cannot carry a default value.`
77249
+ );
77250
+ }
77251
+ if (member.kind !== 13 && member.kind !== 23) {
77252
+ throw new Error(
77253
+ `Member "${member.name}" (${member.id}) is not callable and cannot declare parameter default values.`
77254
+ );
77255
+ }
77256
+ if (member.deferred === true) {
77257
+ throw new Error(
77258
+ `Function "${member.name}" (${member.id}) is deferred, and generated C# appends a trailing deferred parameter that a defaulted parameter cannot precede.`
77259
+ );
77260
+ }
77261
+ const parameters = [];
77262
+ for (const argument2 of argumentTypes) {
77263
+ if (!isRecord7(argument2) || !hasValidOpaqueParameterDefault(argument2)) {
77264
+ throw new Error(
77265
+ `Function "${member.name}" (${member.id}) declares a parameter default value that does not match the parameter's type.`
77266
+ );
77267
+ }
77268
+ parameters.push(argument2);
77269
+ }
77270
+ if (!opaqueParameterDefaultsPlacedLast(parameters)) {
77271
+ throw new Error(
77272
+ `Function "${member.name}" (${member.id}) declares a defaulted parameter before a non-defaulted one; defaulted parameters must come last.`
77273
+ );
77274
+ }
76150
77275
  }
76151
77276
  function memberSignature(member) {
76152
77277
  if (member.kind === "property") {
@@ -76180,6 +77305,7 @@ function assertProjectInterfaceDocumentValid(view, options = {}) {
76180
77305
  }
76181
77306
  for (const member of members) {
76182
77307
  assertOpaqueMemberDefaultValueValid(member);
77308
+ assertOpaqueParameterDefaultsValid(member);
76183
77309
  assertOpaqueCallableOverrideValid(member, membersById);
76184
77310
  assertOpaqueNSFunctionValid(member, membersById);
76185
77311
  if (member.isAbstract === true && member.defaultValue != null) {
@@ -77556,11 +78682,11 @@ function assertOpaqueConstructorValid(declaredConstructor) {
77556
78682
  );
77557
78683
  }
77558
78684
  names.add(name);
77559
- if (argument2.defaultValue !== void 0) {
77560
- throw new Error(
77561
- `Constructor "${declaredConstructor.id}" parameter "${name}" declares a default value, which constructors do not support; add an overload instead.`
77562
- );
77563
- }
78685
+ }
78686
+ if (!opaqueParameterDefaultsPlacedLast(argumentTypes)) {
78687
+ throw new Error(
78688
+ `Constructor "${declaredConstructor.id}" declares a defaulted parameter before a non-defaulted one; defaulted parameters must come last.`
78689
+ );
77564
78690
  }
77565
78691
  assertOpaqueCompiledConstructorAction(declaredConstructor, argumentTypes);
77566
78692
  assertOpaqueConstructorBaseClauseValid(declaredConstructor);
@@ -103403,8 +104529,8 @@ var init_registry2 = __esm({
103403
104529
  "use strict";
103404
104530
  PROJECT_SCHEMA_CONTRACT = Object.freeze({
103405
104531
  formatVersion: 3,
103406
- contractVersion: "3.9",
103407
- cliVersion: "0.27.1",
104532
+ contractVersion: "3.10",
104533
+ cliVersion: "0.29.0",
103408
104534
  projectFileUploadBatchSize: 32,
103409
104535
  documentRecords: {
103410
104536
  member: {
@@ -109970,7 +111096,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
109970
111096
  async function main() {
109971
111097
  const args = parseArgs(process.argv.slice(2));
109972
111098
  if (args.command === "--version") {
109973
- console.log("0.27.1");
111099
+ console.log("0.29.0");
109974
111100
  return;
109975
111101
  }
109976
111102
  if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {