@neocompose/cli 0.89.1 → 0.89.3

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.
@@ -19377,7 +19377,7 @@ var init_registry = __esm({
19377
19377
  "../packages/manifest/schema-contract/registry.mjs"() {
19378
19378
  "use strict";
19379
19379
  PROJECT_SCHEMA_CONTRACT = Object.freeze({
19380
- cliVersion: "0.89.1",
19380
+ cliVersion: "0.89.3",
19381
19381
  projectFileUploadBatchSize: 32,
19382
19382
  documentRecords: {
19383
19383
  member: {
@@ -28182,7 +28182,7 @@ function suppressesInheritedSetter(contract) {
28182
28182
  function generatedValueTypeInfo(ctx, member) {
28183
28183
  const required2 = isRequiredMember(member);
28184
28184
  if (isMemberTupleBase(member)) return memberTypeInfoForCodegen(ctx, member);
28185
- const slotType = classSlotTypeInfo(member, required2);
28185
+ const slotType = classSlotTypeInfo(ctx, member, required2);
28186
28186
  if (slotType !== null) return slotType;
28187
28187
  const returnType = nsPropertyReturnTypeInfo(member);
28188
28188
  if (returnType !== null) return returnType;
@@ -28191,19 +28191,64 @@ function generatedValueTypeInfo(ctx, member) {
28191
28191
  if (declaredType !== null) return declaredType;
28192
28192
  const entry = resolveLookupEntryMember(ctx, member);
28193
28193
  if (entry === null) return null;
28194
- return classSlotTypeInfo(entry, required2);
28194
+ return classSlotTypeInfo(ctx, entry, required2);
28195
28195
  }
28196
28196
  return null;
28197
28197
  }
28198
- function classSlotTypeInfo(member, required2) {
28198
+ function genericParamTypeInfo(ctx, genericParamId, required2) {
28199
+ const declaration = findGenericParamDeclaration(genericParamId, ctx.classes);
28200
+ if (declaration === null) {
28201
+ ctx.diagnostics.push({
28202
+ severity: "error",
28203
+ message: `Generic param "${genericParamId}" is not declared by any type in the export.`,
28204
+ path: "genericParamId"
28205
+ });
28206
+ return null;
28207
+ }
28208
+ return {
28209
+ type: 21 /* Generic */,
28210
+ required: required2,
28211
+ ownerClassId: declaration.declaringClass.id,
28212
+ genericParamId
28213
+ };
28214
+ }
28215
+ function classSlotTypeInfo(ctx, member, required2) {
28216
+ if (!isClassSlotMember(member)) return null;
28217
+ const typeArguments = {};
28218
+ for (const [parameterId, binding] of Object.entries(
28219
+ declaredSlotArguments(member) ?? {}
28220
+ )) {
28221
+ if (isForwardedGenericBinding(binding)) {
28222
+ const typeInfo = genericParamTypeInfo(ctx, binding.genericParamId, true);
28223
+ if (typeInfo === null) return null;
28224
+ typeArguments[parameterId] = typeInfo;
28225
+ } else {
28226
+ const argument2 = resolveMemberById(
28227
+ ctx,
28228
+ binding.memberId,
28229
+ "classArguments"
28230
+ );
28231
+ if (argument2 === null) return null;
28232
+ const typeInfo = memberTypeInfoForCodegen(ctx, argument2);
28233
+ if (typeInfo === null) return null;
28234
+ typeArguments[parameterId] = typeInfo;
28235
+ }
28236
+ }
28237
+ const argumentsField = Object.keys(typeArguments).length === 0 ? {} : { typeArguments };
28199
28238
  if (isClassTypedMember(member)) {
28200
- return { type: 7 /* Class */, classId: member.classId, required: required2 };
28239
+ return {
28240
+ type: 7 /* Class */,
28241
+ classId: member.classId,
28242
+ required: required2,
28243
+ ...argumentsField
28244
+ };
28201
28245
  }
28202
28246
  if (isInterfaceTypedMember(member)) {
28203
28247
  return {
28204
28248
  type: 22 /* Interface */,
28205
28249
  interfaceId: member.interfaceId,
28206
- required: required2
28250
+ required: required2,
28251
+ ...argumentsField
28207
28252
  };
28208
28253
  }
28209
28254
  return null;
@@ -30341,6 +30386,8 @@ function pointerOwnershipForStorage(storage) {
30341
30386
  }
30342
30387
  function memberTypeInfoForCodegen(ctx, member) {
30343
30388
  const required2 = isRequiredMember(member);
30389
+ if (isMemberGenericBase(member))
30390
+ return genericParamTypeInfo(ctx, member.genericParamId, required2);
30344
30391
  if (isMemberTupleBase(member)) {
30345
30392
  const elements = [];
30346
30393
  for (const [index, id2] of member.elementMemberIds.entries()) {
@@ -30355,7 +30402,7 @@ function memberTypeInfoForCodegen(ctx, member) {
30355
30402
  }
30356
30403
  return { type: 30 /* Tuple */, required: required2, elements };
30357
30404
  }
30358
- const slotType = classSlotTypeInfo(member, required2);
30405
+ const slotType = classSlotTypeInfo(ctx, member, required2);
30359
30406
  if (slotType !== null) return slotType;
30360
30407
  if (isMemberLookupBase(member)) {
30361
30408
  if (member.collectionMemberId === void 0) {
@@ -30880,6 +30927,337 @@ var init_NSGetterRuntimeError = __esm({
30880
30927
  }
30881
30928
  });
30882
30929
 
30930
+ // ../packages/models/src/decimal/decimal-math.ts
30931
+ function pow10(exponent) {
30932
+ return TEN ** BigInt(exponent);
30933
+ }
30934
+ function assertCanonicalInput(value, argName) {
30935
+ const violation = getDecimalStringViolation(value);
30936
+ if (violation !== null) {
30937
+ throw new Error(
30938
+ `Decimal argument "${argName}" (${JSON.stringify(value)}) ${violation}.`
30939
+ );
30940
+ }
30941
+ }
30942
+ function parseDecimalString(value) {
30943
+ return parseDecimalArg(value, "value");
30944
+ }
30945
+ function parseDecimalArg(value, argName) {
30946
+ assertCanonicalInput(value, argName);
30947
+ const negative = value.startsWith("-");
30948
+ const unsigned = negative ? value.slice(1) : value;
30949
+ const pointIndex = unsigned.indexOf(".");
30950
+ const digits = pointIndex === -1 ? unsigned : unsigned.slice(0, pointIndex) + unsigned.slice(pointIndex + 1);
30951
+ const scale = pointIndex === -1 ? 0 : unsigned.length - pointIndex - 1;
30952
+ const magnitude = BigInt(digits);
30953
+ return { coefficient: negative ? -magnitude : magnitude, scale };
30954
+ }
30955
+ function formatDecimalParts(parts) {
30956
+ const negative = parts.coefficient < 0n;
30957
+ const digits = (negative ? -parts.coefficient : parts.coefficient).toString();
30958
+ let unsigned;
30959
+ if (parts.scale === 0) {
30960
+ unsigned = digits;
30961
+ } else {
30962
+ const padded = digits.padStart(parts.scale + 1, "0");
30963
+ const pointIndex = padded.length - parts.scale;
30964
+ unsigned = `${padded.slice(0, pointIndex)}.${padded.slice(pointIndex)}`;
30965
+ }
30966
+ if (parts.coefficient === 0n) return unsigned;
30967
+ return negative ? `-${unsigned}` : unsigned;
30968
+ }
30969
+ function significantDigitCount(coefficient) {
30970
+ const magnitude = coefficient < 0n ? -coefficient : coefficient;
30971
+ return magnitude.toString().length;
30972
+ }
30973
+ function assertWithinEnvelope(parts, operation) {
30974
+ if (significantDigitCount(parts.coefficient) > DECIMAL_MAX_SIGNIFICANT_DIGITS) {
30975
+ throw new DecimalOverflowError(
30976
+ `Decimal overflow in ${operation}: the exact result exceeds ${DECIMAL_MAX_SIGNIFICANT_DIGITS} significant digits. Round explicitly (Round/Divide) to reduce precision.`
30977
+ );
30978
+ }
30979
+ if (parts.scale > DECIMAL_MAX_SCALE) {
30980
+ throw new DecimalOverflowError(
30981
+ `Decimal overflow in ${operation}: the exact result exceeds scale ${DECIMAL_MAX_SCALE}. Round explicitly (Round/Divide) to reduce precision.`
30982
+ );
30983
+ }
30984
+ return parts;
30985
+ }
30986
+ function alignScales(a, b) {
30987
+ const scale = Math.max(a.scale, b.scale);
30988
+ return {
30989
+ a: a.coefficient * pow10(scale - a.scale),
30990
+ b: b.coefficient * pow10(scale - b.scale),
30991
+ scale
30992
+ };
30993
+ }
30994
+ function compareDecimalStrings(a, b) {
30995
+ const aligned = alignScales(parseDecimalArg(a, "a"), parseDecimalArg(b, "b"));
30996
+ if (aligned.a < aligned.b) return -1;
30997
+ if (aligned.a > aligned.b) return 1;
30998
+ return 0;
30999
+ }
31000
+ function minDecimalStrings(a, b) {
31001
+ return compareDecimalStrings(a, b) <= 0 ? a : b;
31002
+ }
31003
+ function maxDecimalStrings(a, b) {
31004
+ return compareDecimalStrings(a, b) >= 0 ? a : b;
31005
+ }
31006
+ function clampDecimalStrings(value, min, max) {
31007
+ if (compareDecimalStrings(min, max) > 0) {
31008
+ throw new DecimalClampRangeError(MATH_CLAMP_RANGE_MESSAGE);
31009
+ }
31010
+ if (compareDecimalStrings(value, min) < 0) return min;
31011
+ if (compareDecimalStrings(value, max) > 0) return max;
31012
+ return value;
31013
+ }
31014
+ function absDecimalString(value) {
31015
+ const parts = parseDecimalArg(value, "value");
31016
+ const magnitude = parts.coefficient < 0n ? -parts.coefficient : parts.coefficient;
31017
+ return formatDecimalParts({ coefficient: magnitude, scale: parts.scale });
31018
+ }
31019
+ function addDecimalStrings(a, b) {
31020
+ const aligned = alignScales(parseDecimalArg(a, "a"), parseDecimalArg(b, "b"));
31021
+ return formatDecimalParts(
31022
+ assertWithinEnvelope(
31023
+ { coefficient: aligned.a + aligned.b, scale: aligned.scale },
31024
+ "addition"
31025
+ )
31026
+ );
31027
+ }
31028
+ function subtractDecimalStrings(a, b) {
31029
+ const aligned = alignScales(parseDecimalArg(a, "a"), parseDecimalArg(b, "b"));
31030
+ return formatDecimalParts(
31031
+ assertWithinEnvelope(
31032
+ { coefficient: aligned.a - aligned.b, scale: aligned.scale },
31033
+ "subtraction"
31034
+ )
31035
+ );
31036
+ }
31037
+ function multiplyDecimalStrings(a, b) {
31038
+ const left = parseDecimalArg(a, "a");
31039
+ const right = parseDecimalArg(b, "b");
31040
+ return formatDecimalParts(
31041
+ assertWithinEnvelope(
31042
+ {
31043
+ coefficient: left.coefficient * right.coefficient,
31044
+ scale: left.scale + right.scale
31045
+ },
31046
+ "multiplication"
31047
+ )
31048
+ );
31049
+ }
31050
+ function assertDigitsInRange(digits, operation) {
31051
+ if (!Number.isInteger(digits)) {
31052
+ throw new DecimalDigitsRangeError(
31053
+ `Decimal ${operation} digits must be an integer (received ${digits}).`
31054
+ );
31055
+ }
31056
+ if (digits < 0 || digits > DECIMAL_MAX_SCALE) {
31057
+ throw new DecimalDigitsRangeError(
31058
+ `Decimal ${operation} digits must be between 0 and ${DECIMAL_MAX_SCALE} (received ${digits}).`
31059
+ );
31060
+ }
31061
+ }
31062
+ function roundDecimalParts(parts, digits, midpoint) {
31063
+ if (digits >= parts.scale) return parts;
31064
+ const divisor = pow10(parts.scale - digits);
31065
+ const negative = parts.coefficient < 0n;
31066
+ const magnitude = negative ? -parts.coefficient : parts.coefficient;
31067
+ let quotient = magnitude / divisor;
31068
+ const doubled = magnitude % divisor * 2n;
31069
+ const tieRoundsUp = midpoint === "awayFromZero" || quotient % 2n === 1n;
31070
+ if (doubled > divisor || doubled === divisor && tieRoundsUp) {
31071
+ quotient += 1n;
31072
+ }
31073
+ return { coefficient: negative ? -quotient : quotient, scale: digits };
31074
+ }
31075
+ function roundDecimalString(value, digits) {
31076
+ assertDigitsInRange(digits, "round");
31077
+ const rounded = roundDecimalParts(
31078
+ parseDecimalArg(value, "value"),
31079
+ digits,
31080
+ "toEven"
31081
+ );
31082
+ return formatDecimalParts(assertWithinEnvelope(rounded, "round"));
31083
+ }
31084
+ function toIntegralParts(parts, direction) {
31085
+ if (parts.scale === 0) return parts;
31086
+ const divisor = pow10(parts.scale);
31087
+ const quotient = parts.coefficient / divisor;
31088
+ const remainder = parts.coefficient % divisor;
31089
+ if (remainder === 0n) return { coefficient: quotient, scale: 0 };
31090
+ if (direction === "floor" && remainder < 0n) {
31091
+ return { coefficient: quotient - 1n, scale: 0 };
31092
+ }
31093
+ if (direction === "ceiling" && remainder > 0n) {
31094
+ return { coefficient: quotient + 1n, scale: 0 };
31095
+ }
31096
+ return { coefficient: quotient, scale: 0 };
31097
+ }
31098
+ function floorDecimalString(value) {
31099
+ const parts = toIntegralParts(parseDecimalArg(value, "value"), "floor");
31100
+ return formatDecimalParts(assertWithinEnvelope(parts, "floor"));
31101
+ }
31102
+ function ceilingDecimalString(value) {
31103
+ const parts = toIntegralParts(parseDecimalArg(value, "value"), "ceiling");
31104
+ return formatDecimalParts(assertWithinEnvelope(parts, "ceiling"));
31105
+ }
31106
+ function truncateDecimalString(value) {
31107
+ const parts = toIntegralParts(parseDecimalArg(value, "value"), "truncate");
31108
+ return formatDecimalParts(assertWithinEnvelope(parts, "truncate"));
31109
+ }
31110
+ function divideDecimalStrings(a, b, digits) {
31111
+ assertDigitsInRange(digits, "divide");
31112
+ const dividend = parseDecimalArg(a, "a");
31113
+ const divisor = parseDecimalArg(b, "b");
31114
+ if (divisor.coefficient === 0n) {
31115
+ throw new DecimalDivisionByZeroError(
31116
+ `Decimal division by zero: ${JSON.stringify(a)} / ${JSON.stringify(b)}.`
31117
+ );
31118
+ }
31119
+ const exponent = divisor.scale - dividend.scale + digits;
31120
+ let numerator = dividend.coefficient;
31121
+ let denominator = divisor.coefficient;
31122
+ if (exponent >= 0) {
31123
+ numerator *= pow10(exponent);
31124
+ } else {
31125
+ denominator *= pow10(-exponent);
31126
+ }
31127
+ const negative = numerator < 0n !== denominator < 0n;
31128
+ const absNumerator = numerator < 0n ? -numerator : numerator;
31129
+ const absDenominator = denominator < 0n ? -denominator : denominator;
31130
+ let quotient = absNumerator / absDenominator;
31131
+ const remainder = absNumerator % absDenominator;
31132
+ const doubled = remainder * 2n;
31133
+ if (doubled > absDenominator || doubled === absDenominator && quotient % 2n === 1n) {
31134
+ quotient += 1n;
31135
+ }
31136
+ const parts = {
31137
+ coefficient: negative ? -quotient : quotient,
31138
+ scale: digits
31139
+ };
31140
+ return formatDecimalParts(assertWithinEnvelope(parts, "division"));
31141
+ }
31142
+ function exactPartsFromFloat(value) {
31143
+ if (Number.isNaN(value)) {
31144
+ throw new DecimalNonFiniteError("Cannot convert NaN to a decimal.");
31145
+ }
31146
+ if (!Number.isFinite(value)) {
31147
+ throw new DecimalNonFiniteError(
31148
+ `Cannot convert ${value > 0 ? "Infinity" : "-Infinity"} to a decimal.`
31149
+ );
31150
+ }
31151
+ const view = new DataView(new ArrayBuffer(8));
31152
+ view.setFloat64(0, value);
31153
+ const bits = view.getBigUint64(0);
31154
+ const negative = bits >> 63n === 1n;
31155
+ const exponentBits = Number(bits >> 52n & 0x7ffn);
31156
+ const mantissaBits = bits & 0xfffffffffffffn;
31157
+ let mantissa;
31158
+ let exponent;
31159
+ if (exponentBits === 0) {
31160
+ mantissa = mantissaBits;
31161
+ exponent = -1074;
31162
+ } else {
31163
+ mantissa = mantissaBits | 1n << 52n;
31164
+ exponent = exponentBits - 1075;
31165
+ }
31166
+ if (mantissa === 0n) return { coefficient: 0n, scale: 0 };
31167
+ if (negative) mantissa = -mantissa;
31168
+ let parts;
31169
+ if (exponent >= 0) {
31170
+ parts = { coefficient: mantissa * (1n << BigInt(exponent)), scale: 0 };
31171
+ } else {
31172
+ parts = {
31173
+ coefficient: mantissa * 5n ** BigInt(-exponent),
31174
+ scale: -exponent
31175
+ };
31176
+ }
31177
+ while (parts.scale > 0 && parts.coefficient % TEN === 0n) {
31178
+ parts = { coefficient: parts.coefficient / TEN, scale: parts.scale - 1 };
31179
+ }
31180
+ return parts;
31181
+ }
31182
+ function decimalStringFromFloat(value, digits) {
31183
+ assertDigitsInRange(digits, "float conversion");
31184
+ const rounded = roundDecimalParts(
31185
+ exactPartsFromFloat(value),
31186
+ digits,
31187
+ "toEven"
31188
+ );
31189
+ return formatDecimalParts(assertWithinEnvelope(rounded, "float conversion"));
31190
+ }
31191
+ function floatFromDecimalString(value) {
31192
+ assertCanonicalInput(value, "value");
31193
+ return Number(value);
31194
+ }
31195
+ var DecimalOverflowError, DecimalDivisionByZeroError, DecimalDigitsRangeError, DecimalNonFiniteError, DecimalClampRangeError, MATH_CLAMP_RANGE_MESSAGE, TEN;
31196
+ var init_decimal_math = __esm({
31197
+ "../packages/models/src/decimal/decimal-math.ts"() {
31198
+ "use strict";
31199
+ init_member_kinds();
31200
+ DecimalOverflowError = class extends Error {
31201
+ };
31202
+ DecimalDivisionByZeroError = class extends Error {
31203
+ };
31204
+ DecimalDigitsRangeError = class extends Error {
31205
+ };
31206
+ DecimalNonFiniteError = class extends Error {
31207
+ };
31208
+ DecimalClampRangeError = class extends Error {
31209
+ };
31210
+ MATH_CLAMP_RANGE_MESSAGE = "Math.Clamp requires min <= max.";
31211
+ TEN = 10n;
31212
+ }
31213
+ });
31214
+
31215
+ // ../packages/neoscript-runtime/src/neoscript/unity-value-format.ts
31216
+ function formatUnityFloat(value, digits) {
31217
+ const single = Math.fround(value);
31218
+ if (!Number.isFinite(single)) return String(single);
31219
+ const [mantissa, exponent] = single.toExponential(6).split("e");
31220
+ const coefficient = BigInt(mantissa.replace(".", ""));
31221
+ const scale = 6 - Number(exponent);
31222
+ const parts = scale < 0 ? { coefficient: coefficient * 10n ** BigInt(-scale), scale: 0 } : { coefficient, scale };
31223
+ const rounded = roundDecimalParts(parts, digits, "awayFromZero");
31224
+ return formatDecimalParts({
31225
+ coefficient: rounded.coefficient * 10n ** BigInt(digits - rounded.scale),
31226
+ scale: digits
31227
+ });
31228
+ }
31229
+ function formatUnityValue(value, kind) {
31230
+ if (typeof value !== "object" || value === null)
31231
+ throw new NSGetterRuntimeError(
31232
+ `Cannot interpolate an invalid ${MemberKind[kind]} value.`
31233
+ );
31234
+ const components2 = structuredLeafFields(kind).map((field) => {
31235
+ const component = Reflect.get(value, field.key);
31236
+ if (typeof component !== "number")
31237
+ throw new NSGetterRuntimeError(
31238
+ `${MemberKind[kind]}.${field.key} must be a number for interpolation.`
31239
+ );
31240
+ if (field.type === "int") {
31241
+ if (!Number.isInteger(component))
31242
+ throw new NSGetterRuntimeError(
31243
+ `${MemberKind[kind]}.${field.key} must be an integer for interpolation.`
31244
+ );
31245
+ return String(component);
31246
+ }
31247
+ return formatUnityFloat(component, kind === 19 /* Color */ ? 3 : 2);
31248
+ });
31249
+ return `${kind === 19 /* Color */ ? "RGBA" : ""}(${components2.join(", ")})`;
31250
+ }
31251
+ var init_unity_value_format = __esm({
31252
+ "../packages/neoscript-runtime/src/neoscript/unity-value-format.ts"() {
31253
+ "use strict";
31254
+ init_member_kind_enum();
31255
+ init_structured_leaf_fields();
31256
+ init_NSGetterRuntimeError();
31257
+ init_decimal_math();
31258
+ }
31259
+ });
31260
+
30883
31261
  // ../packages/neoscript-runtime/src/world-grid-query-reads.ts
30884
31262
  function worldGridQueryReadKey(read) {
30885
31263
  return read.kind === "placement" ? JSON.stringify([read.kind, read.valueId]) : JSON.stringify([read.kind, read.gridId, read.cell.x, read.cell.y]);
@@ -33871,6 +34249,8 @@ function tupleKeyFragment(entryMember, entry, graph) {
33871
34249
  ];
33872
34250
  case 30 /* Tuple */:
33873
34251
  return [member.kind, tupleKeyFragment(member, child2, graph)];
34252
+ case 3 /* String */:
34253
+ return [member.kind, requireString(child2.value, member)];
33874
34254
  default:
33875
34255
  return [member.kind, setEntryKey(member, child2, graph)];
33876
34256
  }
@@ -34864,291 +35244,6 @@ var init_cell_pattern2 = __esm({
34864
35244
  }
34865
35245
  });
34866
35246
 
34867
- // ../packages/models/src/decimal/decimal-math.ts
34868
- function pow10(exponent) {
34869
- return TEN ** BigInt(exponent);
34870
- }
34871
- function assertCanonicalInput(value, argName) {
34872
- const violation = getDecimalStringViolation(value);
34873
- if (violation !== null) {
34874
- throw new Error(
34875
- `Decimal argument "${argName}" (${JSON.stringify(value)}) ${violation}.`
34876
- );
34877
- }
34878
- }
34879
- function parseDecimalString(value) {
34880
- return parseDecimalArg(value, "value");
34881
- }
34882
- function parseDecimalArg(value, argName) {
34883
- assertCanonicalInput(value, argName);
34884
- const negative = value.startsWith("-");
34885
- const unsigned = negative ? value.slice(1) : value;
34886
- const pointIndex = unsigned.indexOf(".");
34887
- const digits = pointIndex === -1 ? unsigned : unsigned.slice(0, pointIndex) + unsigned.slice(pointIndex + 1);
34888
- const scale = pointIndex === -1 ? 0 : unsigned.length - pointIndex - 1;
34889
- const magnitude = BigInt(digits);
34890
- return { coefficient: negative ? -magnitude : magnitude, scale };
34891
- }
34892
- function formatDecimalParts(parts) {
34893
- const negative = parts.coefficient < 0n;
34894
- const digits = (negative ? -parts.coefficient : parts.coefficient).toString();
34895
- let unsigned;
34896
- if (parts.scale === 0) {
34897
- unsigned = digits;
34898
- } else {
34899
- const padded = digits.padStart(parts.scale + 1, "0");
34900
- const pointIndex = padded.length - parts.scale;
34901
- unsigned = `${padded.slice(0, pointIndex)}.${padded.slice(pointIndex)}`;
34902
- }
34903
- if (parts.coefficient === 0n) return unsigned;
34904
- return negative ? `-${unsigned}` : unsigned;
34905
- }
34906
- function significantDigitCount(coefficient) {
34907
- const magnitude = coefficient < 0n ? -coefficient : coefficient;
34908
- return magnitude.toString().length;
34909
- }
34910
- function assertWithinEnvelope(parts, operation) {
34911
- if (significantDigitCount(parts.coefficient) > DECIMAL_MAX_SIGNIFICANT_DIGITS) {
34912
- throw new DecimalOverflowError(
34913
- `Decimal overflow in ${operation}: the exact result exceeds ${DECIMAL_MAX_SIGNIFICANT_DIGITS} significant digits. Round explicitly (Round/Divide) to reduce precision.`
34914
- );
34915
- }
34916
- if (parts.scale > DECIMAL_MAX_SCALE) {
34917
- throw new DecimalOverflowError(
34918
- `Decimal overflow in ${operation}: the exact result exceeds scale ${DECIMAL_MAX_SCALE}. Round explicitly (Round/Divide) to reduce precision.`
34919
- );
34920
- }
34921
- return parts;
34922
- }
34923
- function alignScales(a, b) {
34924
- const scale = Math.max(a.scale, b.scale);
34925
- return {
34926
- a: a.coefficient * pow10(scale - a.scale),
34927
- b: b.coefficient * pow10(scale - b.scale),
34928
- scale
34929
- };
34930
- }
34931
- function compareDecimalStrings(a, b) {
34932
- const aligned = alignScales(parseDecimalArg(a, "a"), parseDecimalArg(b, "b"));
34933
- if (aligned.a < aligned.b) return -1;
34934
- if (aligned.a > aligned.b) return 1;
34935
- return 0;
34936
- }
34937
- function minDecimalStrings(a, b) {
34938
- return compareDecimalStrings(a, b) <= 0 ? a : b;
34939
- }
34940
- function maxDecimalStrings(a, b) {
34941
- return compareDecimalStrings(a, b) >= 0 ? a : b;
34942
- }
34943
- function clampDecimalStrings(value, min, max) {
34944
- if (compareDecimalStrings(min, max) > 0) {
34945
- throw new DecimalClampRangeError(MATH_CLAMP_RANGE_MESSAGE);
34946
- }
34947
- if (compareDecimalStrings(value, min) < 0) return min;
34948
- if (compareDecimalStrings(value, max) > 0) return max;
34949
- return value;
34950
- }
34951
- function absDecimalString(value) {
34952
- const parts = parseDecimalArg(value, "value");
34953
- const magnitude = parts.coefficient < 0n ? -parts.coefficient : parts.coefficient;
34954
- return formatDecimalParts({ coefficient: magnitude, scale: parts.scale });
34955
- }
34956
- function addDecimalStrings(a, b) {
34957
- const aligned = alignScales(parseDecimalArg(a, "a"), parseDecimalArg(b, "b"));
34958
- return formatDecimalParts(
34959
- assertWithinEnvelope(
34960
- { coefficient: aligned.a + aligned.b, scale: aligned.scale },
34961
- "addition"
34962
- )
34963
- );
34964
- }
34965
- function subtractDecimalStrings(a, b) {
34966
- const aligned = alignScales(parseDecimalArg(a, "a"), parseDecimalArg(b, "b"));
34967
- return formatDecimalParts(
34968
- assertWithinEnvelope(
34969
- { coefficient: aligned.a - aligned.b, scale: aligned.scale },
34970
- "subtraction"
34971
- )
34972
- );
34973
- }
34974
- function multiplyDecimalStrings(a, b) {
34975
- const left = parseDecimalArg(a, "a");
34976
- const right = parseDecimalArg(b, "b");
34977
- return formatDecimalParts(
34978
- assertWithinEnvelope(
34979
- {
34980
- coefficient: left.coefficient * right.coefficient,
34981
- scale: left.scale + right.scale
34982
- },
34983
- "multiplication"
34984
- )
34985
- );
34986
- }
34987
- function assertDigitsInRange(digits, operation) {
34988
- if (!Number.isInteger(digits)) {
34989
- throw new DecimalDigitsRangeError(
34990
- `Decimal ${operation} digits must be an integer (received ${digits}).`
34991
- );
34992
- }
34993
- if (digits < 0 || digits > DECIMAL_MAX_SCALE) {
34994
- throw new DecimalDigitsRangeError(
34995
- `Decimal ${operation} digits must be between 0 and ${DECIMAL_MAX_SCALE} (received ${digits}).`
34996
- );
34997
- }
34998
- }
34999
- function roundDecimalParts(parts, digits, midpoint) {
35000
- if (digits >= parts.scale) return parts;
35001
- const divisor = pow10(parts.scale - digits);
35002
- const negative = parts.coefficient < 0n;
35003
- const magnitude = negative ? -parts.coefficient : parts.coefficient;
35004
- let quotient = magnitude / divisor;
35005
- const doubled = magnitude % divisor * 2n;
35006
- const tieRoundsUp = midpoint === "awayFromZero" || quotient % 2n === 1n;
35007
- if (doubled > divisor || doubled === divisor && tieRoundsUp) {
35008
- quotient += 1n;
35009
- }
35010
- return { coefficient: negative ? -quotient : quotient, scale: digits };
35011
- }
35012
- function roundDecimalString(value, digits) {
35013
- assertDigitsInRange(digits, "round");
35014
- const rounded = roundDecimalParts(
35015
- parseDecimalArg(value, "value"),
35016
- digits,
35017
- "toEven"
35018
- );
35019
- return formatDecimalParts(assertWithinEnvelope(rounded, "round"));
35020
- }
35021
- function toIntegralParts(parts, direction) {
35022
- if (parts.scale === 0) return parts;
35023
- const divisor = pow10(parts.scale);
35024
- const quotient = parts.coefficient / divisor;
35025
- const remainder = parts.coefficient % divisor;
35026
- if (remainder === 0n) return { coefficient: quotient, scale: 0 };
35027
- if (direction === "floor" && remainder < 0n) {
35028
- return { coefficient: quotient - 1n, scale: 0 };
35029
- }
35030
- if (direction === "ceiling" && remainder > 0n) {
35031
- return { coefficient: quotient + 1n, scale: 0 };
35032
- }
35033
- return { coefficient: quotient, scale: 0 };
35034
- }
35035
- function floorDecimalString(value) {
35036
- const parts = toIntegralParts(parseDecimalArg(value, "value"), "floor");
35037
- return formatDecimalParts(assertWithinEnvelope(parts, "floor"));
35038
- }
35039
- function ceilingDecimalString(value) {
35040
- const parts = toIntegralParts(parseDecimalArg(value, "value"), "ceiling");
35041
- return formatDecimalParts(assertWithinEnvelope(parts, "ceiling"));
35042
- }
35043
- function truncateDecimalString(value) {
35044
- const parts = toIntegralParts(parseDecimalArg(value, "value"), "truncate");
35045
- return formatDecimalParts(assertWithinEnvelope(parts, "truncate"));
35046
- }
35047
- function divideDecimalStrings(a, b, digits) {
35048
- assertDigitsInRange(digits, "divide");
35049
- const dividend = parseDecimalArg(a, "a");
35050
- const divisor = parseDecimalArg(b, "b");
35051
- if (divisor.coefficient === 0n) {
35052
- throw new DecimalDivisionByZeroError(
35053
- `Decimal division by zero: ${JSON.stringify(a)} / ${JSON.stringify(b)}.`
35054
- );
35055
- }
35056
- const exponent = divisor.scale - dividend.scale + digits;
35057
- let numerator = dividend.coefficient;
35058
- let denominator = divisor.coefficient;
35059
- if (exponent >= 0) {
35060
- numerator *= pow10(exponent);
35061
- } else {
35062
- denominator *= pow10(-exponent);
35063
- }
35064
- const negative = numerator < 0n !== denominator < 0n;
35065
- const absNumerator = numerator < 0n ? -numerator : numerator;
35066
- const absDenominator = denominator < 0n ? -denominator : denominator;
35067
- let quotient = absNumerator / absDenominator;
35068
- const remainder = absNumerator % absDenominator;
35069
- const doubled = remainder * 2n;
35070
- if (doubled > absDenominator || doubled === absDenominator && quotient % 2n === 1n) {
35071
- quotient += 1n;
35072
- }
35073
- const parts = {
35074
- coefficient: negative ? -quotient : quotient,
35075
- scale: digits
35076
- };
35077
- return formatDecimalParts(assertWithinEnvelope(parts, "division"));
35078
- }
35079
- function exactPartsFromFloat(value) {
35080
- if (Number.isNaN(value)) {
35081
- throw new DecimalNonFiniteError("Cannot convert NaN to a decimal.");
35082
- }
35083
- if (!Number.isFinite(value)) {
35084
- throw new DecimalNonFiniteError(
35085
- `Cannot convert ${value > 0 ? "Infinity" : "-Infinity"} to a decimal.`
35086
- );
35087
- }
35088
- const view = new DataView(new ArrayBuffer(8));
35089
- view.setFloat64(0, value);
35090
- const bits = view.getBigUint64(0);
35091
- const negative = bits >> 63n === 1n;
35092
- const exponentBits = Number(bits >> 52n & 0x7ffn);
35093
- const mantissaBits = bits & 0xfffffffffffffn;
35094
- let mantissa;
35095
- let exponent;
35096
- if (exponentBits === 0) {
35097
- mantissa = mantissaBits;
35098
- exponent = -1074;
35099
- } else {
35100
- mantissa = mantissaBits | 1n << 52n;
35101
- exponent = exponentBits - 1075;
35102
- }
35103
- if (mantissa === 0n) return { coefficient: 0n, scale: 0 };
35104
- if (negative) mantissa = -mantissa;
35105
- let parts;
35106
- if (exponent >= 0) {
35107
- parts = { coefficient: mantissa * (1n << BigInt(exponent)), scale: 0 };
35108
- } else {
35109
- parts = {
35110
- coefficient: mantissa * 5n ** BigInt(-exponent),
35111
- scale: -exponent
35112
- };
35113
- }
35114
- while (parts.scale > 0 && parts.coefficient % TEN === 0n) {
35115
- parts = { coefficient: parts.coefficient / TEN, scale: parts.scale - 1 };
35116
- }
35117
- return parts;
35118
- }
35119
- function decimalStringFromFloat(value, digits) {
35120
- assertDigitsInRange(digits, "float conversion");
35121
- const rounded = roundDecimalParts(
35122
- exactPartsFromFloat(value),
35123
- digits,
35124
- "toEven"
35125
- );
35126
- return formatDecimalParts(assertWithinEnvelope(rounded, "float conversion"));
35127
- }
35128
- function floatFromDecimalString(value) {
35129
- assertCanonicalInput(value, "value");
35130
- return Number(value);
35131
- }
35132
- var DecimalOverflowError, DecimalDivisionByZeroError, DecimalDigitsRangeError, DecimalNonFiniteError, DecimalClampRangeError, MATH_CLAMP_RANGE_MESSAGE, TEN;
35133
- var init_decimal_math = __esm({
35134
- "../packages/models/src/decimal/decimal-math.ts"() {
35135
- "use strict";
35136
- init_member_kinds();
35137
- DecimalOverflowError = class extends Error {
35138
- };
35139
- DecimalDivisionByZeroError = class extends Error {
35140
- };
35141
- DecimalDigitsRangeError = class extends Error {
35142
- };
35143
- DecimalNonFiniteError = class extends Error {
35144
- };
35145
- DecimalClampRangeError = class extends Error {
35146
- };
35147
- MATH_CLAMP_RANGE_MESSAGE = "Math.Clamp requires min <= max.";
35148
- TEN = 10n;
35149
- }
35150
- });
35151
-
35152
35247
  // ../packages/neoscript-language/src/text-formats.ts
35153
35248
  function formatSpecifier(letter) {
35154
35249
  switch (letter) {
@@ -43212,13 +43307,6 @@ function evalCollectionMutationInstruction(ins, scope, ctx, options) {
43212
43307
  } else if (ins.mutation === "Add" /* Add */ && !isArrayCollection(targetValue)) {
43213
43308
  overlayArgs[1] = findKnownRowIdByValueReference(args[1], ctx) ?? args[1];
43214
43309
  }
43215
- if (ins.mutation === "Add" /* Add */ && isArrayCollection(targetValue) && unorderedContainerValueId !== null && !isLookupSet && findKnownRowIdByValueReference(args[0], ctx) === null) {
43216
- overlayArgs[0] = createUnorderedScalarProjectionEntry(
43217
- unorderedContainerValueId,
43218
- args[0] instanceof NSSlotReference ? [args[0].targetId] : args[0],
43219
- ctx
43220
- );
43221
- }
43222
43310
  const unorderedEntriesBeforeMutation = unorderedContainerValueId === null || !Array.isArray(targetValue) || ins.mutation === "Add" /* Add */ ? null : [...targetValue];
43223
43311
  const writesEntry = (ins.mutation === "Add" /* Add */ || ins.mutation === "Insert" /* Insert */) && !isLookupSet;
43224
43312
  let attachedValueId = null;
@@ -43253,6 +43341,13 @@ function evalCollectionMutationInstruction(ins, scope, ctx, options) {
43253
43341
  );
43254
43342
  }
43255
43343
  }
43344
+ if (ins.mutation === "Add" /* Add */ && isArrayCollection(targetValue) && unorderedContainerValueId !== null && !isLookupSet && findKnownRowIdByValueReference(args[0], ctx) === null) {
43345
+ overlayArgs[0] = createUnorderedScalarProjectionEntry(
43346
+ unorderedContainerValueId,
43347
+ args[0] instanceof NSSlotReference ? [args[0].targetId] : args[0],
43348
+ ctx
43349
+ );
43350
+ }
43256
43351
  const removableRowIds = isLookupSet || ins.reference === true ? null : removableEntryRowIds(targetValue, ins.mutation, overlayArgs, ctx);
43257
43352
  const removedIndex = applyLocalCollectionMutation(
43258
43353
  targetValue,
@@ -45970,9 +46065,16 @@ function formatDebugValue(value, type2, ctx) {
45970
46065
  }
45971
46066
  function formatForInterp(value, sourceType, ctx) {
45972
46067
  if (value === null || value === void 0) return "";
46068
+ sourceType = runtimeConcreteTypeInfo(sourceType, ctx);
45973
46069
  const sequenceType = inspectNeoScriptSequenceType(ctx, sourceType);
45974
- if (sequenceType !== null) return `(${sequenceType}, unenumerated)`;
46070
+ if (sequenceType !== null) return `<${sequenceType} unenumerated>`;
45975
46071
  switch (sourceType.type) {
46072
+ case 14 /* Vector2 */:
46073
+ case 16 /* Vector3 */:
46074
+ case 15 /* Vector2Int */:
46075
+ case 17 /* Vector3Int */:
46076
+ case 19 /* Color */:
46077
+ return formatUnityValue(value, sourceType.type);
45976
46078
  case 8 /* Enum */: {
45977
46079
  const cbId = sourceType.enumId;
45978
46080
  const cb = evaluatorSchemaIndex(ctx).enum(cbId);
@@ -53965,6 +54067,7 @@ var DELEGATE_LEXICAL_THIS, DELEGATE_LEXICAL_ROOT, DELEGATE_LEXICAL_TYPE_ARGUMENT
53965
54067
  var init_evaluateNSGetter = __esm({
53966
54068
  "../packages/neoscript-runtime/src/neoscript/evaluateNSGetter.ts"() {
53967
54069
  "use strict";
54070
+ init_unity_value_format();
53968
54071
  init_sequence_dependencies();
53969
54072
  init_sequence_contract();
53970
54073
  init_type_info_compatibility();
@@ -55733,7 +55836,7 @@ function resolveMemberDeclaredTypeInfoInternal(member, members2, seen, ownerClas
55733
55836
  Object.entries(declaredSlotArguments(resolved) ?? {}).flatMap(
55734
55837
  ([genericParamId, binding]) => {
55735
55838
  if (!isMemberGenericBinding(binding)) {
55736
- const forwarded = genericParamTypeInfo(
55839
+ const forwarded = genericParamTypeInfo2(
55737
55840
  ownerClass,
55738
55841
  binding.genericParamId,
55739
55842
  true
@@ -55881,7 +55984,7 @@ function resolveMemberDeclaredTypeInfoInternal(member, members2, seen, ownerClas
55881
55984
  if (resolved.kind === 9 /* Lookup */) return null;
55882
55985
  if (!memberKindSupportsStorage(resolved.kind)) return null;
55883
55986
  if (isMemberGenericBase(resolved)) {
55884
- return genericParamTypeInfo(
55987
+ return genericParamTypeInfo2(
55885
55988
  ownerClass,
55886
55989
  resolved.genericParamId,
55887
55990
  isRequiredMember(resolved)
@@ -55892,7 +55995,7 @@ function resolveMemberDeclaredTypeInfoInternal(member, members2, seen, ownerClas
55892
55995
  required: isRequiredMember(resolved)
55893
55996
  };
55894
55997
  }
55895
- function genericParamTypeInfo(ownerClass, genericParamId, required2) {
55998
+ function genericParamTypeInfo2(ownerClass, genericParamId, required2) {
55896
55999
  if (ownerClass === null) return null;
55897
56000
  const declaration = ownerClass.genericParams?.find(
55898
56001
  (parameter4) => parameter4.id === genericParamId
@@ -62535,18 +62638,19 @@ function buildNeoScriptEditorIndex(lexed, kind) {
62535
62638
  lexed,
62536
62639
  diagnostics
62537
62640
  );
62641
+ const regionCalls = indexCalls(executable, executablePairs, lexed);
62538
62642
  const regionLocals = applySwitchSectionScopes(
62539
62643
  indexLocals(
62540
62644
  executable,
62541
62645
  executablePairs,
62542
62646
  lexed,
62543
62647
  diagnostics,
62544
- lambdaBodies
62648
+ lambdaBodies,
62649
+ regionCalls
62545
62650
  ),
62546
62651
  regionSwitches,
62547
62652
  lexed
62548
62653
  );
62549
- const regionCalls = indexCalls(executable, executablePairs, lexed);
62550
62654
  const declarations = new Set(
62551
62655
  regionLocals.map(
62552
62656
  (local) => `${local.nameRange.start.line}:${local.nameRange.start.character}`
@@ -62999,9 +63103,10 @@ function duplicateUnitDiagnostic(label, units, diagnostics) {
62999
63103
  ]
63000
63104
  });
63001
63105
  }
63002
- function indexLocals(tokens, pairs, lexed, diagnostics, lambdaBodies) {
63106
+ function indexLocals(tokens, pairs, lexed, diagnostics, lambdaBodies, calls) {
63003
63107
  const locals = [];
63004
63108
  const braceScope = braceScopeIndex(tokens, lexed.end);
63109
+ const switchArrows = switchExpressionArrowIndexes(tokens, calls);
63005
63110
  for (let index = 0; index < tokens.length; index++) {
63006
63111
  const caught = tryParseCatchParameter(tokens, index, pairs, lexed);
63007
63112
  if (caught) {
@@ -63022,7 +63127,13 @@ function indexLocals(tokens, pairs, lexed, diagnostics, lambdaBodies) {
63022
63127
  index = loop.resumeTokenIndex;
63023
63128
  continue;
63024
63129
  }
63025
- const lambda = tryParseLambdaParameters(tokens, index, pairs, lexed);
63130
+ const lambda = tryParseLambdaParameters(
63131
+ tokens,
63132
+ index,
63133
+ pairs,
63134
+ lexed,
63135
+ switchArrows
63136
+ );
63026
63137
  if (lambda) {
63027
63138
  locals.push(...lambda.locals);
63028
63139
  lambdaBodies.push(lambda.body);
@@ -63183,7 +63294,35 @@ function statementEndTokenIndex(tokens, start) {
63183
63294
  }
63184
63295
  return tokens.length;
63185
63296
  }
63186
- function tryParseLambdaParameters(tokens, start, pairs, lexed) {
63297
+ function switchExpressionArrowIndexes(tokens, calls) {
63298
+ const enclosing = enclosingOpenerIndex(tokens);
63299
+ const inResult = /* @__PURE__ */ new Set();
63300
+ const arrows = /* @__PURE__ */ new Set();
63301
+ const genericEnds = /* @__PURE__ */ new Map();
63302
+ for (const call of calls) {
63303
+ const first = call.typeArgumentTokens?.[0];
63304
+ if (first) genericEnds.set(first.start, call.openParenOffset);
63305
+ }
63306
+ for (let index = 0; index < tokens.length; index++) {
63307
+ const token = tokens[index];
63308
+ const genericEnd = genericEnds.get(token.start);
63309
+ if (genericEnd !== void 0) {
63310
+ while (tokens[index + 1] && tokens[index + 1].start < genericEnd)
63311
+ index++;
63312
+ continue;
63313
+ }
63314
+ const opener = enclosing[index];
63315
+ if (tokens[opener]?.text !== "{" || tokens[opener - 1]?.text !== "switch")
63316
+ continue;
63317
+ if (token.text === ",") inResult.delete(opener);
63318
+ else if (token.text === "=>" && !inResult.has(opener)) {
63319
+ arrows.add(index);
63320
+ inResult.add(opener);
63321
+ }
63322
+ }
63323
+ return arrows;
63324
+ }
63325
+ function tryParseLambdaParameters(tokens, start, pairs, lexed, switchArrows) {
63187
63326
  const open2 = tokens[start];
63188
63327
  if (!open2) return null;
63189
63328
  if (open2.kind === "identifier") {
@@ -63191,6 +63330,7 @@ function tryParseLambdaParameters(tokens, start, pairs, lexed) {
63191
63330
  if (!arrow2 || arrow2.kind !== "operator" || arrow2.text !== "=>") {
63192
63331
  return null;
63193
63332
  }
63333
+ if (switchArrows.has(start + 1)) return null;
63194
63334
  const body2 = lambdaBodySpan(tokens, start + 1, pairs, lexed);
63195
63335
  return {
63196
63336
  locals: [
@@ -63215,6 +63355,7 @@ function tryParseLambdaParameters(tokens, start, pairs, lexed) {
63215
63355
  if (closeIndex === void 0) return null;
63216
63356
  const arrow = tokens[closeIndex + 1];
63217
63357
  if (!arrow || arrow.kind !== "operator" || arrow.text !== "=>") return null;
63358
+ if (switchArrows.has(closeIndex + 1)) return null;
63218
63359
  const body = lambdaBodySpan(tokens, closeIndex + 1, pairs, lexed);
63219
63360
  const locals = [];
63220
63361
  for (const [parameterIndex, [from, to]] of patternSegments(
@@ -85559,6 +85700,20 @@ function substituteManifestType(type2, genericEnvironment, environment, seenPara
85559
85700
  )
85560
85701
  };
85561
85702
  }
85703
+ if (type2.kind === "tuple") {
85704
+ return {
85705
+ ...type2,
85706
+ elements: type2.elements.map((element) => ({
85707
+ ...element,
85708
+ type: substituteManifestType(
85709
+ element.type,
85710
+ genericEnvironment,
85711
+ environment,
85712
+ seenParameters
85713
+ )
85714
+ }))
85715
+ };
85716
+ }
85562
85717
  if (type2.kind === "dictionary") {
85563
85718
  return {
85564
85719
  ...type2,
@@ -87287,6 +87442,10 @@ function createNeoScriptDocumentContextInScope(context, projectOverride) {
87287
87442
  ...parameterDefaultDescriptor(argument2, context)
87288
87443
  }));
87289
87444
  const member = context.memberId ? analyzerMemberById(context, context.memberId) : void 0;
87445
+ const declaringClass2 = context.declaringClass ?? context.thisClass ?? (member && isStaticMember(member) ? context.vm.classes.find(
87446
+ (candidate) => Object.values(candidate.schema).includes(member.id)
87447
+ ) : void 0);
87448
+ const declaringType = declaringClass2 ? namedType(declaringClass2.id, true) : void 0;
87290
87449
  let functionName = context.functionName;
87291
87450
  if (functionName === void 0 && member) {
87292
87451
  const accessor = documentKind === "getter" || documentKind === "setter" ? documentKind : void 0;
@@ -87296,10 +87455,15 @@ function createNeoScriptDocumentContextInScope(context, projectOverride) {
87296
87455
  kind: documentKind,
87297
87456
  project,
87298
87457
  ...thisClass ? { thisClass } : {},
87458
+ ...declaringType ? {
87459
+ declaringType,
87460
+ implicitMemberAccess: true,
87461
+ staticMember: context.staticMember ?? isStaticMember(member) === true
87462
+ } : {},
87299
87463
  ...isExtensionMember(member) ? {
87300
87464
  declaringType: null,
87301
87465
  implicitMemberAccess: false,
87302
- staticMember: isStaticMember(member) === true,
87466
+ staticMember: context.staticMember ?? isStaticMember(member) === true,
87303
87467
  extensionReceiver: toLanguageType(
87304
87468
  member.extension.receiverType,
87305
87469
  context
@@ -88895,7 +89059,9 @@ function projectLanguageVersion(context) {
88895
89059
  context.vm.project.id,
88896
89060
  context.vm.project.updatedAt,
88897
89061
  ...projectRootMemberIds(context.vm.project),
88898
- ...records3.map((record7) => `${record7.id}:${record7.updatedAt}`).sort()
89062
+ ...records3.map((record7) => `${record7.id}:${record7.updatedAt}`).sort(),
89063
+ JSON.stringify(context.variants ?? []),
89064
+ JSON.stringify(context.variantFolders ?? [])
88899
89065
  ].join("|");
88900
89066
  }
88901
89067
  function virtualSourceUri(context, directory, fileName2) {
@@ -89390,6 +89556,8 @@ function createContext(ctx, options) {
89390
89556
  const analyzer = {
89391
89557
  vm: prepared ?? createAnalyzerProject(ctx),
89392
89558
  thisClass: ctx.thisClass,
89559
+ declaringClass: ctx.declaringClass,
89560
+ staticMember: ctx.staticMember,
89393
89561
  memberId: ctx.memberId,
89394
89562
  functionName: ctx.functionName,
89395
89563
  ...ctx.valueAliases ? { valueAliases: ctx.valueAliases } : {},
@@ -89409,6 +89577,8 @@ function createContext(ctx, options) {
89409
89577
  );
89410
89578
  const replayContext = ctx.storedConstructionReplay === true ? { ...adapted, storedConstructionReplay: true } : adapted;
89411
89579
  if (adapted.extensionReceiver) return replayContext;
89580
+ if (ctx.implicitMemberAccess === false)
89581
+ return { ...replayContext, implicitMemberAccess: false };
89412
89582
  if (ctx.implicitMemberAccess !== true) return replayContext;
89413
89583
  return {
89414
89584
  ...replayContext,
@@ -89532,6 +89702,48 @@ var init_compiler_adapter = __esm({
89532
89702
  }
89533
89703
  });
89534
89704
 
89705
+ // ../src/database/neoscript/initializer-context.ts
89706
+ function memberInitializerContext(code, declaringClass2, isStatic, constructors) {
89707
+ const instanceClass = isStatic ? null : declaringClass2;
89708
+ let lexicalThisClass = null;
89709
+ try {
89710
+ if (parseExpression(code).kind === "lambda")
89711
+ lexicalThisClass = instanceClass;
89712
+ } catch {
89713
+ }
89714
+ return {
89715
+ declaringClass: declaringClass2,
89716
+ lexicalThisClass,
89717
+ argumentTypes: initializerArgumentTypes(instanceClass, constructors)
89718
+ };
89719
+ }
89720
+ function initializerArgumentTypes(ownerClass, constructors) {
89721
+ if (ownerClass === null) return void 0;
89722
+ const requiredConstructorId2 = ownerClass.requiredConstructorId;
89723
+ if (requiredConstructorId2 === void 0) return void 0;
89724
+ if (requiredConstructorId2 === null) return void 0;
89725
+ const required2 = constructors.find(
89726
+ (constructor2) => constructor2.id === requiredConstructorId2
89727
+ );
89728
+ if (required2 === void 0) {
89729
+ throw new Error(
89730
+ `Class "${ownerClass.name}" names required constructor "${requiredConstructorId2}", but no such constructor record was loaded.`
89731
+ );
89732
+ }
89733
+ if (required2.classId !== ownerClass.id) {
89734
+ throw new Error(
89735
+ `Class "${ownerClass.name}" names required constructor "${requiredConstructorId2}", which is owned by class "${required2.classId}".`
89736
+ );
89737
+ }
89738
+ return required2.argumentTypes.map((argument2) => ({ ...argument2 }));
89739
+ }
89740
+ var init_initializer_context2 = __esm({
89741
+ "../src/database/neoscript/initializer-context.ts"() {
89742
+ "use strict";
89743
+ init_executable_parser();
89744
+ }
89745
+ });
89746
+
89535
89747
  // ../src/database/compile-ns-property.ts
89536
89748
  function compilationProjectContext(args, members2 = args.members) {
89537
89749
  return {
@@ -89726,7 +89938,6 @@ function compileMemberInitializerBody(args) {
89726
89938
  `Member "${args.member.name}" has an initializer but no resolvable declared type.`
89727
89939
  );
89728
89940
  }
89729
- const instanceClass = isStaticMember(args.member) ? null : args.thisClass;
89730
89941
  let compiled;
89731
89942
  try {
89732
89943
  compiled = compileUnit2(
@@ -89738,10 +89949,10 @@ function compileMemberInitializerBody(args) {
89738
89949
  variantFolders: args.variantFolders ?? [],
89739
89950
  returnTypeInfo,
89740
89951
  initializerName: args.member.name,
89741
- lexicalThisClass: parseExpression(defaultValue.init.code).kind === "lambda" ? instanceClass : null,
89742
- declaringClass: args.thisClass,
89743
- argumentTypes: initializerArgumentTypes(
89744
- instanceClass,
89952
+ ...memberInitializerContext(
89953
+ defaultValue.init.code,
89954
+ args.thisClass,
89955
+ isStaticMember(args.member) === true,
89745
89956
  args.constructors ?? []
89746
89957
  )
89747
89958
  })
@@ -89805,26 +90016,6 @@ function compileValueRowInitializerBody(args) {
89805
90016
  }
89806
90017
  Object.assign(container.init, { compiled });
89807
90018
  }
89808
- function initializerArgumentTypes(ownerClass, constructors) {
89809
- if (ownerClass === null) return void 0;
89810
- const requiredConstructorId2 = ownerClass.requiredConstructorId;
89811
- if (requiredConstructorId2 === void 0) return void 0;
89812
- if (requiredConstructorId2 === null) return void 0;
89813
- const required2 = constructors.find(
89814
- (constructor2) => constructor2.id === requiredConstructorId2
89815
- );
89816
- if (required2 === void 0) {
89817
- throw new Error(
89818
- `Class "${ownerClass.name}" names required constructor "${requiredConstructorId2}", but no such constructor record was loaded.`
89819
- );
89820
- }
89821
- if (required2.classId !== ownerClass.id) {
89822
- throw new Error(
89823
- `Class "${ownerClass.name}" names required constructor "${requiredConstructorId2}", which is owned by class "${required2.classId}".`
89824
- );
89825
- }
89826
- return required2.argumentTypes.map((argument2) => ({ ...argument2 }));
89827
- }
89828
90019
  function compileAuthoredMemberBodies(args) {
89829
90020
  compileNSPropertyBodies(args);
89830
90021
  compileNSFunctionBody(args);
@@ -90203,7 +90394,7 @@ var init_compile_ns_property = __esm({
90203
90394
  init_compile_delegate_closure();
90204
90395
  init_compiler_adapter();
90205
90396
  init_compiler_adapter();
90206
- init_executable_parser();
90397
+ init_initializer_context2();
90207
90398
  NeoScriptBodyCompileError = class extends Error {
90208
90399
  memberId;
90209
90400
  memberName;
@@ -95922,6 +96113,8 @@ function validateOwnedStaticDefault(uri, member, ownerName, scope, environment,
95922
96113
  const initializer = member.initializer;
95923
96114
  if (initializer === void 0) return;
95924
96115
  if (member.type.name === "Reference") return;
96116
+ if (member.type.name === "Set" && member.type.typeArguments[0]?.name === "Reference")
96117
+ return;
95925
96118
  let expression;
95926
96119
  try {
95927
96120
  expression = parseExpression(initializer.text);
@@ -97044,6 +97237,21 @@ function knownGeneratorExpression(expression, scope, environment) {
97044
97237
  return candidates !== void 0 && candidates.length > 0 && candidates.every((member) => member.generator === true);
97045
97238
  }
97046
97239
  function validateExpression(expression, expected, scope, environment, uri, range2, diagnostics, anchor, storedValue = true) {
97240
+ if (anchor !== void 0 && expression.kind === "call") {
97241
+ const error = sourceCallBinding(expression, scope, environment)?.error;
97242
+ if (error?.message.includes(
97243
+ "Named arguments are not supported for this call."
97244
+ )) {
97245
+ pushDiagnostic(
97246
+ diagnostics,
97247
+ uri,
97248
+ anchorSpan(anchor, error, 1),
97249
+ "invalid-function-call",
97250
+ error.message.replace(/^\d+:\d+: /, "")
97251
+ );
97252
+ return;
97253
+ }
97254
+ }
97047
97255
  if (expression.kind === "new" && expression.typeArguments?.length) {
97048
97256
  const { context } = initializerResolver(
97049
97257
  environment,
@@ -100825,6 +101033,15 @@ function substituteInheritedSourceMember(member, baseInfo, resolvedBaseType) {
100825
101033
  if (type2.kind === "list" || type2.kind === "set") {
100826
101034
  return { ...type2, elementType: substitute2(type2.elementType) };
100827
101035
  }
101036
+ if (type2.kind === "tuple") {
101037
+ return {
101038
+ ...type2,
101039
+ elements: type2.elements.map((element) => ({
101040
+ ...element,
101041
+ type: substitute2(element.type)
101042
+ }))
101043
+ };
101044
+ }
100828
101045
  if (type2.kind === "dictionary") {
100829
101046
  return {
100830
101047
  ...type2,
@@ -119786,7 +120003,7 @@ function genericEnvironmentKey(env) {
119786
120003
  [...env].sort(([left], [right]) => left.localeCompare(right))
119787
120004
  );
119788
120005
  }
119789
- function createTypedValueNormalizer(reader, document, childrenByContainerId, parameterTypesForRow, memberById2, memberTypeInfo2, genericEnvironmentForRow, rowIdentities, readTracking, referenceTargets, localizedTexts) {
120006
+ function createTypedValueNormalizer(reader, document, childrenByContainerId, parameterTypesForRow, memberById2, memberTypeInfo2, genericEnvironmentForRow, rowIdentities, readTracking, referenceTargets, localizedTexts, classMemberIdentities) {
119790
120007
  const visiting = /* @__PURE__ */ new Set();
119791
120008
  const completed = /* @__PURE__ */ new Map();
119792
120009
  const compare2 = createEffectiveValueComparator();
@@ -119993,23 +120210,26 @@ function createTypedValueNormalizer(reader, document, childrenByContainerId, par
119993
120210
  document.members
119994
120211
  );
119995
120212
  const members2 = /* @__PURE__ */ new Map();
119996
- const keys = /* @__PURE__ */ new Set();
120213
+ const keys = /* @__PURE__ */ new Map();
119997
120214
  for (const entry of merged) {
119998
120215
  if (entry.memberId === null) continue;
119999
120216
  const member = memberById2(entry.memberId);
120000
120217
  if (member === void 0) continue;
120001
120218
  members2.set(entry.schemaKey, member);
120002
- keys.add(entry.schemaKey);
120219
+ keys.set(entry.schemaKey, `member:${entry.memberId}`);
120220
+ }
120221
+ for (const key of Object.keys(row.value)) {
120222
+ if (!keys.has(key)) keys.set(key, `key:${key}`);
120003
120223
  }
120004
- for (const key of Object.keys(row.value)) keys.add(key);
120005
120224
  const result = /* @__PURE__ */ Object.create(null);
120006
- for (const schemaKey of keys) {
120225
+ for (const [schemaKey, identity3] of keys) {
120226
+ const outputKey = classMemberIdentities ? identity3 : schemaKey;
120007
120227
  const rawMember = members2.get(schemaKey);
120008
120228
  const member = rawMember === void 0 ? void 0 : substituteMember(rawMember, env, document.members);
120009
120229
  if (member === void 0) {
120010
120230
  const childId2 = row.value[schemaKey];
120011
120231
  if (childId2 !== void 0)
120012
- result[schemaKey] = normalizeOpaqueOwnedRow(childId2);
120232
+ result[outputKey] = normalizeOpaqueOwnedRow(childId2);
120013
120233
  continue;
120014
120234
  }
120015
120235
  if (!memberKindOwnsStoredValue(member.kind)) continue;
@@ -120022,17 +120242,17 @@ function createTypedValueNormalizer(reader, document, childrenByContainerId, par
120022
120242
  });
120023
120243
  if (slot.kind === "missing") continue;
120024
120244
  if (slot.kind === "null") {
120025
- result[schemaKey] = { value: null };
120245
+ result[outputKey] = { value: null };
120026
120246
  continue;
120027
120247
  }
120028
120248
  const childId = slot.kind === "declaration" ? reader.declarationRow(member, env).id : slot.value;
120029
120249
  const type2 = memberTypeInfo2(member, env);
120030
120250
  if (typeof childId !== "string") {
120031
- result[schemaKey] = normalizeLiteral(childId);
120251
+ result[outputKey] = normalizeLiteral(childId);
120032
120252
  } else if (type2 === null) {
120033
- result[schemaKey] = normalizeOpaqueOwnedRow(childId);
120253
+ result[outputKey] = normalizeOpaqueOwnedRow(childId);
120034
120254
  } else {
120035
- result[schemaKey] = normalizeTypedRow(childId, type2, member, env);
120255
+ result[outputKey] = normalizeTypedRow(childId, type2, member, env);
120036
120256
  }
120037
120257
  }
120038
120258
  return result;
@@ -120142,7 +120362,8 @@ var init_effective_value_reader = __esm({
120142
120362
  materializedIndex;
120143
120363
  storedPlacements;
120144
120364
  graphCache;
120145
- createNormalizer(rowIdentities, referenceTargets) {
120365
+ constructorArgumentNormalizer;
120366
+ createNormalizer(rowIdentities, referenceTargets, classMemberIdentities = false) {
120146
120367
  return createTypedValueNormalizer(
120147
120368
  this,
120148
120369
  this.document,
@@ -120154,7 +120375,8 @@ var init_effective_value_reader = __esm({
120154
120375
  rowIdentities,
120155
120376
  this.context.readTracking,
120156
120377
  referenceTargets,
120157
- this.localizedTextsById()
120378
+ this.localizedTextsById(),
120379
+ classMemberIdentities
120158
120380
  );
120159
120381
  }
120160
120382
  localizedTextsById() {
@@ -120574,7 +120796,15 @@ var init_effective_value_reader = __esm({
120574
120796
  normalizeConstructorArguments(args, root, placement) {
120575
120797
  if (placement !== void 0) this.placements.set(root.id, placement);
120576
120798
  assertStoredConstructionStamp(root);
120577
- return this.normalizer.normalizeConstructorArgs(args, root);
120799
+ this.constructorArgumentNormalizer ??= this.createNormalizer(
120800
+ void 0,
120801
+ void 0,
120802
+ true
120803
+ );
120804
+ return this.constructorArgumentNormalizer.normalizeConstructorArgs(
120805
+ args,
120806
+ root
120807
+ );
120578
120808
  }
120579
120809
  normalizeTypedRow(valueId, typeInfo, placement, env, rowIdentities, referenceTargets) {
120580
120810
  if (placement !== void 0) this.placements.set(valueId, placement);
@@ -123968,7 +124198,7 @@ function lowerFieldMember(context, ownerClass, declaration, id2, commonInput, ba
123968
124198
  storesSelectionArray,
123969
124199
  `${ownerClass.name}.${declaration.name}`,
123970
124200
  !declaration.modifiers.includes("static") && contextualEnumArgument(settings, "kind") === "Unordered",
123971
- reference2 !== null
124201
+ reference2 !== null ? fieldType : null
123972
124202
  )
123973
124203
  };
123974
124204
  if (fieldType.tupleElements) {
@@ -125246,7 +125476,7 @@ function spellsReference(expression) {
125246
125476
  }
125247
125477
  return expression.kind === "call" && expression.callee.kind === "ident" && expression.callee.name === "Reference";
125248
125478
  }
125249
- function lowerDefault(context, initializer, type2, ownerClass, base, memberId, storesSelectionArray, path, unorderedList = false, reference2 = false) {
125479
+ function lowerDefault(context, initializer, type2, ownerClass, base, memberId, storesSelectionArray, path, unorderedList = false, referenceType = null) {
125250
125480
  if (initializer === null) {
125251
125481
  return base?.defaultValue && "serverValueId" in base.defaultValue ? base.defaultValue : null;
125252
125482
  }
@@ -125268,9 +125498,14 @@ function lowerDefault(context, initializer, type2, ownerClass, base, memberId, s
125268
125498
  }
125269
125499
  if (base?.defaultValue != null && matchesStoredInitializer(base.defaultValue, initializer))
125270
125500
  return base.defaultValue;
125271
- const deferred = reference2 ? deferredReferenceDefault(context, expression) : null;
125501
+ const deferred = referenceType !== null && (referenceType.name !== "Set" || expression.kind === "litList") ? deferredReferenceDefault(context, expression) : null;
125272
125502
  if (deferred !== null) return { value: deferred, classId: null };
125273
- if (unorderedList && expression.kind === "litList" && expression.elements.length > 0 || constructsValue(expression) && slotForwardsTypeParameter(context, type2, ownerClass) || positionRequiresEvaluation(context, expression, type2, ownerClass)) {
125503
+ if (unorderedList && expression.kind === "litList" && expression.elements.length > 0 || constructsValue(expression) && slotForwardsTypeParameter(context, type2, ownerClass) || positionRequiresEvaluation(
125504
+ context,
125505
+ expression,
125506
+ referenceType ?? type2,
125507
+ ownerClass
125508
+ )) {
125274
125509
  return {
125275
125510
  init: {
125276
125511
  code: context.settleInitializerReferences(
@@ -125286,7 +125521,7 @@ function lowerDefault(context, initializer, type2, ownerClass, base, memberId, s
125286
125521
  if (context.rowBackedDefaultMemberIds.has(memberId) && base?.defaultValue && !("serverValueId" in base.defaultValue)) {
125287
125522
  return base.defaultValue;
125288
125523
  }
125289
- const slot = reference2 ? slotReferenceType(type2) : null;
125524
+ const slot = referenceType !== null ? slotReferenceType(type2) : null;
125290
125525
  if (slot !== null && !spellsReference(expression)) {
125291
125526
  throw new Error(
125292
125527
  `A ${formatManifestType(slot)} default names a stored ${formatManifestType(requiredTypeArgument(slot, 0))}, not a value. Wrap a member path in Reference(), or give a row id.`
@@ -140476,22 +140711,23 @@ var init_project_commit_preparation_scoped_loader = __esm({
140476
140711
  // ../src/database/compiled-construction-types.ts
140477
140712
  function compiledConstructionTypeMembers(members2, bodies, projectId) {
140478
140713
  const created = [];
140714
+ const createdKeys = [];
140479
140715
  let existingIds;
140480
140716
  const byType = /* @__PURE__ */ new Map();
140481
140717
  const key = (type2) => canonicalJsonStringify(type2);
140482
- const intern = (type2) => {
140483
- const signature2 = key(type2);
140484
- const existing = byType.get(signature2);
140718
+ const intern = (type2, slot) => {
140719
+ const cacheKey = slot?.id ?? key(type2);
140720
+ const existing = byType.get(cacheKey);
140485
140721
  if (existing !== void 0) return existing;
140486
140722
  if (type2.type === 21 /* Generic */ || type2.type === NS_TYPE_UNKNOWN)
140487
140723
  return null;
140488
- const id2 = v5_default(
140489
- `neo:compiled-construction-type:${projectId}:${signature2}`,
140724
+ const id2 = slot?.id ?? v5_default(
140725
+ `neo:compiled-construction-type:${projectId}:${cacheKey}`,
140490
140726
  v5_default.URL
140491
140727
  );
140492
140728
  existingIds ??= new Set(members2.map((member) => member.id));
140493
140729
  if (existingIds.has(id2)) {
140494
- byType.set(signature2, id2);
140730
+ byType.set(cacheKey, id2);
140495
140731
  return id2;
140496
140732
  }
140497
140733
  const common = {
@@ -140499,11 +140735,24 @@ function compiledConstructionTypeMembers(members2, bodies, projectId) {
140499
140735
  projectId,
140500
140736
  createdAt: 0,
140501
140737
  updatedAt: 0,
140502
- name: "Type argument",
140738
+ name: slot?.name ?? "Type argument",
140503
140739
  kind: type2.type,
140504
140740
  requirement: type2.required ? 1 /* Required */ : 0 /* Optional */
140505
140741
  };
140742
+ const mark = created.length;
140506
140743
  const fields = (() => {
140744
+ if (type2.type === 30 /* Tuple */) {
140745
+ const elementMemberIds = [];
140746
+ for (const [index, element] of type2.elements.entries()) {
140747
+ const memberId = intern(element.typeInfo, {
140748
+ id: derivedTupleElementMemberId(id2, index),
140749
+ name: element.name ?? `Item${index + 1}`
140750
+ });
140751
+ if (memberId === null) return null;
140752
+ elementMemberIds.push(memberId);
140753
+ }
140754
+ return { elementMemberIds };
140755
+ }
140507
140756
  if (type2.type === 6 /* List */ || type2.type === 28 /* Set */ || type2.type === 5 /* Dictionary */) {
140508
140757
  const entryMemberId = intern(type2.entryTypeInfo);
140509
140758
  if (entryMemberId === null) return null;
@@ -140547,10 +140796,15 @@ function compiledConstructionTypeMembers(members2, bodies, projectId) {
140547
140796
  return {};
140548
140797
  }
140549
140798
  })();
140550
- if (fields === null) return null;
140799
+ if (fields === null) {
140800
+ for (const member of created.splice(mark)) existingIds.delete(member.id);
140801
+ for (const key2 of createdKeys.splice(mark)) byType.delete(key2);
140802
+ return null;
140803
+ }
140551
140804
  created.push({ ...common, ...fields });
140805
+ createdKeys.push(cacheKey);
140552
140806
  existingIds.add(id2);
140553
- byType.set(signature2, id2);
140807
+ byType.set(cacheKey, id2);
140554
140808
  return id2;
140555
140809
  };
140556
140810
  const visited = /* @__PURE__ */ new Set();
@@ -140604,6 +140858,7 @@ var init_compiled_construction_types = __esm({
140604
140858
  init_neoscript_guards();
140605
140859
  init_neoscript();
140606
140860
  init_project_content_hash();
140861
+ init_tuple_element_member_id();
140607
140862
  }
140608
140863
  });
140609
140864
 
@@ -141524,7 +141779,7 @@ var init_stored_closure_captures = __esm({
141524
141779
  });
141525
141780
 
141526
141781
  // ../src/database/construction-replay-equality.ts
141527
- function createConstructionReplayComparer(reader, ownedValueIds) {
141782
+ function createConstructionReplayComparer(reader, ownedValueIds, replayReader = reader) {
141528
141783
  let graph;
141529
141784
  return (args) => {
141530
141785
  if (!isLiteralValueContent(args.currentRoot)) return false;
@@ -141561,7 +141816,7 @@ function createConstructionReplayComparer(reader, ownedValueIds) {
141561
141816
  args.currentRoot,
141562
141817
  args.rootMember
141563
141818
  ),
141564
- reader.withRowOverrides(args.replayRows).normalizeConstructorArguments(
141819
+ replayReader.withRowOverrides(args.replayRows).normalizeConstructorArguments(
141565
141820
  replayed,
141566
141821
  args.replayRoot,
141567
141822
  args.rootMember
@@ -158604,6 +158859,12 @@ function compilePulledUncompiledConstructorsV4(document, compilationProject, rep
158604
158859
  }
158605
158860
  function compilePulledProjectDocumentForEvaluationV4(document, compilationProject, targets) {
158606
158861
  const compiled = [];
158862
+ for (let index = 0; index < document.values.length; index += 1) {
158863
+ const row = document.values[index];
158864
+ if (targets !== void 0 && !targets.valueIds?.has(row.id)) continue;
158865
+ if (!isInitValueContent(row) || row.init.compiled === void 0) continue;
158866
+ document.values[index] = { ...row, init: { code: row.init.code } };
158867
+ }
158607
158868
  const sharedCompilationProject = compilationProject ?? createNeoScriptCompilationProject({
158608
158869
  project: document.project,
158609
158870
  projectFiles: document.projectFiles,
@@ -162374,8 +162635,14 @@ function memberInitializerRequiresEvaluation(context, member, expression, source
162374
162635
  return false;
162375
162636
  }
162376
162637
  if (member.kind === "lookup" && expression.kind === "litList") {
162638
+ const elementMember = { ...member, multiselect: false };
162377
162639
  return expression.elements.some(
162378
- (element) => memberInitializerRequiresEvaluation(context, member, element, source)
162640
+ (element) => memberInitializerRequiresEvaluation(
162641
+ context,
162642
+ elementMember,
162643
+ element,
162644
+ source
162645
+ )
162379
162646
  );
162380
162647
  }
162381
162648
  const unorderedDefault = source.purpose === "memberDefault" && member.id === source.memberId && member.kind === "list" && member.listKind === "unordered" && expression.kind === "litList" && expression.elements.length > 0;
@@ -162416,6 +162683,7 @@ function deferredPathSpelling(context, expression, expected) {
162416
162683
  }
162417
162684
  function isDeferredPathReferenceValue(context, sourceExpression, expected) {
162418
162685
  const expression = annotatedValue(sourceExpression).expression;
162686
+ if (expected.multiselect && expression.kind !== "litList") return false;
162419
162687
  const elements = expression.kind === "litList" ? expression.elements : [expression];
162420
162688
  let indexPaths = 0;
162421
162689
  for (const element of elements) {
@@ -166292,9 +166560,13 @@ function lowerEnum2(context, member, expression) {
166292
166560
  });
166293
166561
  }
166294
166562
  function lowerReferences(context, member, expression, ownerValueId, source) {
166563
+ function refuse(message, at3 = expression) {
166564
+ context.loweringFailures.push({ message, site: referenceSite(source, at3) });
166565
+ throw new ReportedLoweringFailure(message);
166566
+ }
166295
166567
  const elements = member.multiselect ? expression.kind === "litList" ? expression.elements : null : [expression];
166296
166568
  if (elements === null) {
166297
- throw new Error(`Reference member ${member.name} requires [...].`);
166569
+ refuse(`Reference member ${member.name} requires [...].`);
166298
166570
  }
166299
166571
  const ids = [];
166300
166572
  for (const [index, entry] of elements.entries()) {
@@ -166312,7 +166584,7 @@ function lowerReferences(context, member, expression, ownerValueId, source) {
166312
166584
  }
166313
166585
  const target = referenceTargetSpelling(context, entry);
166314
166586
  if (target === null) {
166315
- throw new Error(`Reference member ${member.name} has an invalid target.`);
166587
+ refuse(`Reference member ${member.name} has an invalid target.`, entry);
166316
166588
  }
166317
166589
  if (target.spelling === "key" || target.spelling === "local") {
166318
166590
  ids.push(`${PENDING_ID_PREFIX}reference-key:${source.label}:${index}`);
@@ -166335,9 +166607,7 @@ function lowerReferences(context, member, expression, ownerValueId, source) {
166335
166607
  ids.push(target.spelling === "id" ? target.id : target.resolved.id);
166336
166608
  }
166337
166609
  if (new Set(ids).size !== ids.length) {
166338
- throw new Error(
166339
- `Reference member ${member.name} cannot contain duplicate targets.`
166340
- );
166610
+ refuse(`Reference member ${member.name} cannot contain duplicate targets.`);
166341
166611
  }
166342
166612
  return ids;
166343
166613
  }
@@ -171728,19 +171998,24 @@ function reconcileMaterializedInitializersV4(args) {
171728
171998
  continue;
171729
171999
  }
171730
172000
  assertPulledConstructorsCompiled(replayDocument, replayContext);
171731
- currentRows ??= storedRowsWithRenamedKeys(
171732
- currentState().document,
171733
- replayDocument
171734
- );
171735
- compareConstruction ??= createConstructionReplayComparer(
171736
- new EffectiveValueReader(storedRowsDocument(replayDocument, currentRows)),
171737
- (root, member) => {
171738
- return storedOwnedValues().collect({
171739
- rootIds: [root.id],
171740
- rootMembers: /* @__PURE__ */ new Map([[root.id, member]])
171741
- });
171742
- }
171743
- );
172001
+ currentRows ??= new Map(
172002
+ currentState().document.values.map((row) => [row.id, row])
172003
+ );
172004
+ if (compareConstruction === void 0) {
172005
+ const storedDocument = currentState().document;
172006
+ compilePulledUncompiledConstructorsV4(storedDocument);
172007
+ assertPulledConstructorsCompiled(storedDocument);
172008
+ compareConstruction = createConstructionReplayComparer(
172009
+ new EffectiveValueReader(storedDocument),
172010
+ (root, member) => {
172011
+ return storedOwnedValues().collect({
172012
+ rootIds: [root.id],
172013
+ rootMembers: /* @__PURE__ */ new Map([[root.id, member]])
172014
+ });
172015
+ },
172016
+ new EffectiveValueReader(replayDocument)
172017
+ );
172018
+ }
171744
172019
  const replay = replayRows.get(reconciliation.valueId);
171745
172020
  if (replay === void 0) {
171746
172021
  throw new Error(
@@ -171901,51 +172176,6 @@ function retainedLiteralFailure(args, records3, document, replayContext, compile
171901
172176
  );
171902
172177
  }
171903
172178
  }
171904
- function storedRowsDocument(document, rows) {
171905
- const values = [];
171906
- for (const row of document.values) {
171907
- if (rows.has(row.id)) continue;
171908
- if (row.containerId && rows.has(row.containerId)) continue;
171909
- values.push(row);
171910
- }
171911
- for (const row of rows.values()) values.push(row);
171912
- return { ...document, values: freezeJsonData(values) };
171913
- }
171914
- function storedRowsWithRenamedKeys(before, after) {
171915
- const renamesByClass = /* @__PURE__ */ new Map();
171916
- const rows = /* @__PURE__ */ new Map();
171917
- for (const row of before.values) {
171918
- let renamed = row;
171919
- if (typeof row.classId === "string" && isObjectRecord(row.value)) {
171920
- const classId = row.classId;
171921
- let renames = renamesByClass.get(classId);
171922
- if (renames === void 0) {
171923
- const entries = (document) => mergeInstanceSurfaceSchema(
171924
- classId,
171925
- document.classes,
171926
- document.members
171927
- ).map((entry) => [entry.schemaKey, entry.memberId]);
171928
- renames = schemaKeyRenamesByMemberId(entries(before), entries(after));
171929
- renamesByClass.set(row.classId, renames);
171930
- }
171931
- if (renames.size > 0) {
171932
- const value = {};
171933
- let collision = false;
171934
- for (const [key, child2] of Object.entries(row.value)) {
171935
- const target = renames.get(key) ?? key;
171936
- if (target !== key && Object.hasOwn(row.value, target) && !renames.has(target)) {
171937
- collision = true;
171938
- break;
171939
- }
171940
- value[target] = child2;
171941
- }
171942
- if (!collision) renamed = { ...row, value };
171943
- }
171944
- }
171945
- rows.set(row.id, renamed);
171946
- }
171947
- return rows;
171948
- }
171949
172179
  function pulledStateDocumentV4(workspace) {
171950
172180
  const state = workspace.state.records;
171951
172181
  const remembered = pulledStateDocuments.get(state);
@@ -172042,7 +172272,8 @@ function materializeInitializersLocallyV4(args) {
172042
172272
  const compilationProject = createNeoScriptCompilationProject(authoredDocument);
172043
172273
  const changedBodies = {
172044
172274
  memberIds: /* @__PURE__ */ new Set(),
172045
- constructorIds: /* @__PURE__ */ new Set()
172275
+ constructorIds: /* @__PURE__ */ new Set(),
172276
+ valueIds: new Set(valueBodyIds)
172046
172277
  };
172047
172278
  for (const change of args.changes) {
172048
172279
  if (change.operation === "delete") continue;
@@ -172071,6 +172302,7 @@ function materializeInitializersLocallyV4(args) {
172071
172302
  for (const id2 of dependentBodies.constructorIds) {
172072
172303
  changedBodies.constructorIds.add(id2);
172073
172304
  }
172305
+ for (const id2 of dependentBodies.valueIds) changedBodies.valueIds.add(id2);
172074
172306
  }
172075
172307
  const compiledBodies = compilePulledProjectDocumentForEvaluationV4(
172076
172308
  authoredDocument,
@@ -172432,7 +172664,6 @@ var init_local_initializer_materialization = __esm({
172432
172664
  init_variant_value_graph();
172433
172665
  init_members();
172434
172666
  init_member_value_id();
172435
- init_inheritance();
172436
172667
  init_effective_value_reader();
172437
172668
  init_virtual_instance_values();
172438
172669
  init_declared_binding_targets();
@@ -185150,43 +185381,6 @@ var init_export_state = __esm({
185150
185381
  }
185151
185382
  });
185152
185383
 
185153
- // ../packages/neoscript-language/src/argument-name-completions.ts
185154
- function argumentNameCompletions(fields, tokens, start, prefixEnd, position) {
185155
- const edit = argumentNameCompletionEdit(tokens, start, prefixEnd, position);
185156
- if (!edit) return [];
185157
- const { range: range2, hasColon } = edit;
185158
- const items = [];
185159
- for (const field of fields) {
185160
- const insertText = hasColon ? field.name : `${field.name}: `;
185161
- items.push({
185162
- label: field.name,
185163
- kind: "property",
185164
- detail: field.defaultText === void 0 ? field.type : `[${field.type} = ${field.defaultText}]`,
185165
- insertText,
185166
- textEdit: { range: range2, newText: insertText }
185167
- });
185168
- }
185169
- return items;
185170
- }
185171
- function argumentNameCompletionEdit(tokens, start, prefixEnd, position) {
185172
- const first = tokens[start];
185173
- if (prefixEnd > start + 1) return null;
185174
- if (prefixEnd > start && (!first || !isCallArgumentLabelToken(first)))
185175
- return null;
185176
- const editingName = first !== void 0 && isCallArgumentLabelToken(first) && positionCompare(first.range.start, position) <= 0 && positionCompare(position, first.range.end) <= 0;
185177
- if (first && isCallArgumentLabelToken(first) && !editingName) return null;
185178
- const hasColon = editingName && tokens[start + 1]?.text === ":";
185179
- const range2 = editingName ? first.range : { start: position, end: position };
185180
- return { range: range2, hasColon };
185181
- }
185182
- var init_argument_name_completions = __esm({
185183
- "../packages/neoscript-language/src/argument-name-completions.ts"() {
185184
- "use strict";
185185
- init_executable_parser();
185186
- init_project_source_tokens();
185187
- }
185188
- });
185189
-
185190
185384
  // ../packages/neoscript-language/src/tuple-symbols.ts
185191
185385
  function tupleElementSymbol(element, index, alias = false) {
185192
185386
  const location3 = alias ? void 0 : element.labelLocation;
@@ -185528,15 +185722,7 @@ function complete(snapshot, position) {
185528
185722
  const tokens = significantTokensBefore(snapshot.lexed.tokens, word.start);
185529
185723
  const tail = tokens[tokens.length - 1];
185530
185724
  let candidates;
185531
- const genericMember = tail?.text === "<" ? resolveChain(
185532
- snapshot,
185533
- expressionTokensBefore(tokens, tokens.length - 1),
185534
- offset
185535
- )?.symbol : void 0;
185536
- const genericMemberId = genericMember?.id;
185537
- const firstTypeParameter = genericMember?.typeParameters?.[0]?.type;
185538
- const functionConstraint = firstTypeParameter?.kind === "typeParameter" && firstTypeParameter.constraint?.kind === "named" ? firstTypeParameter.constraint.typeId : void 0;
185539
- const nativeGenericClassId = genericMemberId === NEO_TILE_CONVERT_MEMBER_ID ? NEO_TILE_CLASS_ID : functionConstraint;
185725
+ const genericTypes = typeArgumentCompletionItems(snapshot, tokens, word);
185540
185726
  const catchFilterCandidates = catchFilterCompletionItems(
185541
185727
  snapshot,
185542
185728
  word.start,
@@ -185553,7 +185739,9 @@ function complete(snapshot, position) {
185553
185739
  prefix,
185554
185740
  word
185555
185741
  );
185556
- if (catchFilterCandidates) {
185742
+ if (genericTypes) {
185743
+ candidates = genericTypes;
185744
+ } else if (catchFilterCandidates) {
185557
185745
  candidates = catchFilterCandidates;
185558
185746
  } else if (catchClauseCandidates) {
185559
185747
  candidates = catchClauseCandidates;
@@ -185580,14 +185768,6 @@ function complete(snapshot, position) {
185580
185768
  word,
185581
185769
  expectedValueAt(snapshot, word.start)
185582
185770
  );
185583
- } else if (nativeGenericClassId) {
185584
- candidates = [...snapshot.project.typeByName.values()].filter(
185585
- (type2) => type2.kind === "class" && (genericMemberId !== NEO_TILE_CONVERT_MEMBER_ID || !type2.abstract && !type2.typeParameters?.length) && isNeoScriptTypeAssignable(
185586
- { kind: "named", typeId: type2.id },
185587
- { kind: "named", typeId: nativeGenericClassId },
185588
- snapshot.project
185589
- )
185590
- ).map((type2) => typeCompletion(type2, word, snapshot));
185591
185771
  } else if (isTypePosition(tokens)) {
185592
185772
  candidates = typeCompletionItems(snapshot, word);
185593
185773
  } else if (isLambdaParameterPosition(tokens)) {
@@ -185600,6 +185780,88 @@ function complete(snapshot, position) {
185600
185780
  items: rankAndDeduplicate(candidates, prefix)
185601
185781
  };
185602
185782
  }
185783
+ function completeTypeArgument(snapshot, position) {
185784
+ const offset = snapshot.source.offsetAt(position);
185785
+ if (insidePlainString(snapshot.lexed.tokens, offset)) return null;
185786
+ const word = {
185787
+ start: wordRangeAt(snapshot.source.text, offset).start,
185788
+ end: offset
185789
+ };
185790
+ const tokens = significantTokensBefore(snapshot.lexed.tokens, word.start);
185791
+ const items = typeArgumentCompletionItems(snapshot, tokens, word);
185792
+ return items === null ? null : {
185793
+ isIncomplete: hasUnclosedConstruct(snapshot.lexed.tokens, offset),
185794
+ items: rankAndDeduplicate(
185795
+ items,
185796
+ snapshot.source.text.slice(word.start, offset)
185797
+ )
185798
+ };
185799
+ }
185800
+ function typeArgumentCompletionItems(snapshot, tokens, word) {
185801
+ let depth = 0;
185802
+ let argumentIndex = 0;
185803
+ let tupleDepth = 0;
185804
+ let inTuple = false;
185805
+ for (let index = tokens.length - 1; index >= 0; index--) {
185806
+ const token = tokens[index];
185807
+ if (token.text === ")") tupleDepth++;
185808
+ else if (token.text === "(") {
185809
+ if (!["<", ",", "("].includes(tokens[index - 1]?.text ?? "")) return null;
185810
+ if (tupleDepth > 0) tupleDepth--;
185811
+ else inTuple = true;
185812
+ } else if (/^>+$/.test(token.text)) depth += token.text.length;
185813
+ else if (token.text === "<") {
185814
+ if (depth > 0) {
185815
+ depth--;
185816
+ continue;
185817
+ }
185818
+ const name = tokens[index - 1]?.text;
185819
+ const resolution = resolveChain(
185820
+ snapshot,
185821
+ expressionTokensBefore(tokens, index),
185822
+ word.start
185823
+ );
185824
+ const member = resolution?.symbol;
185825
+ const declaration = (tokens[index - 2]?.text === "new" || resolution === null) && name ? snapshot.project.typeByName.get(name) : resolution?.staticType;
185826
+ const parameters = member?.typeParameters ?? declaration?.typeParameters;
185827
+ const builtin = name !== void 0 && member === void 0 && tokens[index - 2]?.text !== "." && [
185828
+ "List",
185829
+ "Set",
185830
+ "Dictionary",
185831
+ "Reference",
185832
+ "Partial",
185833
+ "FunctionRef",
185834
+ "NeoDelegate",
185835
+ "NeoAction"
185836
+ ].includes(name);
185837
+ const tileConversion = member?.id === NEO_TILE_CONVERT_MEMBER_ID && argumentIndex === 0;
185838
+ if (!parameters?.length && !builtin && !tileConversion) return null;
185839
+ const parameter4 = inTuple ? void 0 : parameters?.[argumentIndex]?.type;
185840
+ const constraint = parameter4?.kind === "typeParameter" ? parameter4.constraint : void 0;
185841
+ const constraintId = constraint?.kind === "named" ? constraint.typeId : void 0;
185842
+ const classId = tileConversion ? NEO_TILE_CLASS_ID : constraintId;
185843
+ if (!classId) return typeCompletionItems(snapshot, word);
185844
+ const candidates = [...snapshot.project.typeByName.values()].filter(
185845
+ (type2) => type2.kind === "class" && (!tileConversion || !type2.abstract && !type2.typeParameters?.length) && isNeoScriptTypeAssignable(
185846
+ { kind: "named", typeId: type2.id },
185847
+ { kind: "named", typeId: classId },
185848
+ snapshot.project
185849
+ )
185850
+ ).map((type2) => typeCompletion(type2, word, snapshot));
185851
+ if (!tileConversion)
185852
+ candidates.push(
185853
+ ...typeParameterCompletionItems(snapshot, word, constraint)
185854
+ );
185855
+ return candidates;
185856
+ } else if (!isCallTypeArgumentToken(token)) return null;
185857
+ else if (depth === 0 && tupleDepth === 0 && token.text === ",")
185858
+ argumentIndex++;
185859
+ }
185860
+ return null;
185861
+ }
185862
+ function completeLambdaBody(snapshot, position) {
185863
+ return lambdaBodyAt(snapshot, snapshot.source.offsetAt(position)) ? complete(snapshot, position) : null;
185864
+ }
185603
185865
  function completeFunctionArgument(snapshot, position) {
185604
185866
  const argument2 = callArgumentAt(snapshot, snapshot.source.offsetAt(position));
185605
185867
  if (!argument2 || argument2.call.kind === "constructor" || !callSymbol(snapshot, argument2.call))
@@ -185608,76 +185870,7 @@ function completeFunctionArgument(snapshot, position) {
185608
185870
  for (let opener = innermostOpener(features, snapshot.source.offsetAt(position)); opener >= 0 && features.tokens[opener].start > argument2.call.openParenOffset; opener = features.enclosingOpener[opener]) {
185609
185871
  if (features.tokens[opener].text === "{") return null;
185610
185872
  }
185611
- const values = complete(snapshot, position);
185612
- const names2 = functionArgumentNames(snapshot, position);
185613
- if (!names2) return values;
185614
- const offset = snapshot.source.offsetAt(position);
185615
- const word = wordRangeAt(snapshot.source.text, offset);
185616
- return {
185617
- ...values,
185618
- items: rankAndDeduplicate(
185619
- names2.onlyNames ? names2.items : [...names2.items, ...values.items],
185620
- snapshot.source.text.slice(word.start, offset)
185621
- )
185622
- };
185623
- }
185624
- function functionArgumentNames(snapshot, position) {
185625
- const offset = snapshot.source.offsetAt(position);
185626
- if (lambdaBodyAt(snapshot, offset)) return null;
185627
- const argument2 = callArgumentAt(snapshot, offset);
185628
- if (argument2?.call.kind !== "function") return null;
185629
- const { call, index } = argument2;
185630
- const { tokens } = scriptFeatureIndex(snapshot);
185631
- const startOffset = call.argumentRanges[index] ? snapshot.source.offsetAt(call.argumentRanges[index].start) : offset;
185632
- const start = firstIndex(tokens, (token) => token.start >= startOffset);
185633
- const prefixEnd = firstIndex(tokens, (token) => token.start >= offset);
185634
- const edit = argumentNameCompletionEdit(tokens, start, prefixEnd, position);
185635
- if (!edit) return null;
185636
- const symbol = callSymbol(snapshot, call);
185637
- if (!symbol?.parameters) return null;
185638
- const labels = [...call.argumentNames];
185639
- labels[index] = null;
185640
- const bound = boundOverloadId(
185641
- snapshot,
185642
- snapshot.source.offsetAt(call.nameRange.start),
185643
- call.name
185644
- );
185645
- const overloads = callOverloads(snapshot, call, symbol, bound).map(
185646
- (overload) => ({ parameters: overload.parameters ?? [] })
185647
- );
185648
- const reachable = neoScriptApplicableSignatures(overloads, labels);
185649
- const fields = /* @__PURE__ */ new Map();
185650
- for (const { parameters } of reachable) {
185651
- const used = /* @__PURE__ */ new Set();
185652
- call.argumentNames.forEach((name, argumentIndex) => {
185653
- if (argumentIndex === index) return;
185654
- const parameter4 = neoScriptArgumentParameter(
185655
- parameters,
185656
- name,
185657
- argumentIndex
185658
- );
185659
- if (parameter4) used.add(parameter4.name.toLowerCase());
185660
- });
185661
- for (const parameter4 of parameters) {
185662
- const key = parameter4.name.toLowerCase();
185663
- if (used.has(key) || fields.has(key)) continue;
185664
- fields.set(key, {
185665
- name: parameter4.name,
185666
- type: formatType(parameter4.type, snapshot.project),
185667
- ...parameter4.defaultValue ? { defaultText: parameter4.defaultValue.displayText } : {}
185668
- });
185669
- }
185670
- }
185671
- return {
185672
- items: argumentNameCompletions(
185673
- [...fields.values()],
185674
- tokens,
185675
- start,
185676
- prefixEnd,
185677
- position
185678
- ),
185679
- onlyNames: edit.hasColon
185680
- };
185873
+ return complete(snapshot, position);
185681
185874
  }
185682
185875
  function hover(snapshot, position) {
185683
185876
  const offset = snapshot.source.offsetAt(position);
@@ -187071,6 +187264,32 @@ function initializerConstruction(snapshot, brace, constructor2) {
187071
187264
  }
187072
187265
  return construction;
187073
187266
  }
187267
+ function initializerKeyContextAt(snapshot, position) {
187268
+ const features = scriptFeatureIndex(snapshot);
187269
+ const offset = snapshot.source.offsetAt(position);
187270
+ const brace = innermostOpener(features, offset);
187271
+ const constructor2 = features.objectInitializers.get(brace);
187272
+ if (constructor2 === void 0) return null;
187273
+ const keys = [];
187274
+ let atKey = true;
187275
+ for (let index = brace + 1; index < features.tokens.length; index++) {
187276
+ const token = features.tokens[index];
187277
+ if (token.start >= offset) break;
187278
+ if (features.enclosingOpener[index] !== brace) continue;
187279
+ const call = features.calls.get(token.start);
187280
+ if (call?.typeArgumentTokens?.length) {
187281
+ index = (features.tokenIndexes.get(call.openParenOffset) ?? index + 1) - 1;
187282
+ continue;
187283
+ }
187284
+ if (token.text === "=") {
187285
+ keys.push(features.tokens[index - 1].text);
187286
+ atKey = false;
187287
+ } else if (token.text === ",") atKey = true;
187288
+ }
187289
+ if (!atKey) return null;
187290
+ const construction = initializerConstruction(snapshot, brace, constructor2);
187291
+ return construction ? { typeName: construction.declaration.name, keys } : null;
187292
+ }
187074
187293
  function initializerExpectedType(snapshot, offset, bodyStart) {
187075
187294
  const features = scriptFeatureIndex(snapshot);
187076
187295
  const { tokens, enclosingOpener, callOpenings, objectInitializers } = features;
@@ -187484,6 +187703,27 @@ function matchingCloseBraceIndex(tokens, openIndex) {
187484
187703
  }
187485
187704
  return null;
187486
187705
  }
187706
+ function typeParameterCompletionItems(snapshot, word, constraint) {
187707
+ const items = [];
187708
+ for (const parameter4 of [
187709
+ ...contextualTypeParameters(snapshot),
187710
+ ...snapshot.context.typeParameters ?? []
187711
+ ]) {
187712
+ if (constraint && !isNeoScriptTypeAssignable(parameter4.type, constraint, snapshot.project))
187713
+ continue;
187714
+ items.push(
187715
+ completion(
187716
+ parameter4.name,
187717
+ "typeParameter",
187718
+ parameter4.name,
187719
+ "Type parameter",
187720
+ word,
187721
+ snapshot
187722
+ )
187723
+ );
187724
+ }
187725
+ return items;
187726
+ }
187487
187727
  function typeCompletionItems(snapshot, word) {
187488
187728
  const items = NEOSCRIPT_PRIMITIVE_TYPES.map(
187489
187729
  (name) => completion(name, "keyword", name, "Primitive type", word, snapshot)
@@ -187499,8 +187739,9 @@ function typeCompletionItems(snapshot, word) {
187499
187739
  "snippet"
187500
187740
  )
187501
187741
  );
187742
+ items.push(...typeParameterCompletionItems(snapshot, word));
187502
187743
  for (const type2 of snapshot.project.typeByName.values()) {
187503
- if (type2.id === NEOSCRIPT_MATH_TYPE_ID || type2.id === "builtin:Debug")
187744
+ if (type2.kind === "builtin" && !ANNOTATION_TYPE_NAMES.has(type2.name))
187504
187745
  continue;
187505
187746
  items.push(typeCompletion(type2, word, snapshot));
187506
187747
  }
@@ -189301,6 +189542,18 @@ function inferLambdaParameterType(local, snapshot) {
189301
189542
  if (declarationIndex < 0) return UNKNOWN_TYPE;
189302
189543
  const arrow = tokens[declarationIndex + 1];
189303
189544
  let opener = enclosingOpener[declarationIndex];
189545
+ let lambdaStart = arrow?.text === "=>" ? declarationIndex : opener;
189546
+ for (let depth = 0; depth < (local.tuplePath?.length ?? 0); depth++)
189547
+ lambdaStart = enclosingOpener[lambdaStart] ?? -1;
189548
+ if (lambdaStart >= 0) {
189549
+ const offset = tokens[lambdaStart].start;
189550
+ const argument2 = resolvedCallArgumentAt(snapshot, offset);
189551
+ const expected = isCollectionCallbackArgument(argument2) ? null : expectedTypeAt(snapshot, offset, void 0, argument2);
189552
+ if (expected?.kind === "delegate") {
189553
+ const parameter4 = expected.parameterTypes[local.lambdaParameterIndex ?? 0];
189554
+ if (parameter4) return tuplePathType(parameter4, local.tuplePath);
189555
+ }
189556
+ }
189304
189557
  if (!(arrow?.kind === "operator" && arrow.text === "=>")) {
189305
189558
  if (opener < 0 || tokens[opener]?.text !== "(") return UNKNOWN_TYPE;
189306
189559
  opener = enclosingOpener[opener];
@@ -189571,17 +189824,20 @@ function expressionTokensBefore(tokens, endExclusive) {
189571
189824
  for (; start >= 0; start--) {
189572
189825
  const token = tokens[start];
189573
189826
  if (!token) continue;
189574
- if (token.kind === "punctuation" && [")", "]"].includes(token.text)) {
189827
+ if (token.kind === "punctuation" && [")", "]", "}"].includes(token.text)) {
189828
+ if (token.text === "}" && depth === 0 && start < endExclusive - 1 && ![".", "?.", "!"].includes(tokens[start + 1]?.text ?? ""))
189829
+ break;
189575
189830
  if (depth === 0) groupEnd = start;
189576
189831
  depth++;
189577
189832
  }
189578
- if (token.kind === "punctuation" && ["(", "["].includes(token.text)) {
189833
+ if (token.kind === "punctuation" && ["(", "[", "{"].includes(token.text)) {
189579
189834
  if (depth > 0) depth--;
189580
189835
  else break;
189581
189836
  if (depth === 0 && ["if", "while", "for", "foreach"].includes(
189582
189837
  tokens[start - 1]?.text ?? ""
189583
189838
  ))
189584
189839
  return tokens.slice(groupEnd + 1, endExclusive);
189840
+ continue;
189585
189841
  }
189586
189842
  if (depth === 0 && token.kind === "operator" && token.text === ">") {
189587
189843
  const name = genericCallNameIndex(tokens, start);
@@ -189598,8 +189854,7 @@ function expressionTokensBefore(tokens, endExclusive) {
189598
189854
  return tokens.slice(start + 1, endExclusive);
189599
189855
  }
189600
189856
  function genericCallNameIndex(tokens, close) {
189601
- if (tokens[close + 1]?.text !== "(" && tokens[close + 1]?.text !== ".")
189602
- return -1;
189857
+ if (!["(", ".", "{"].includes(tokens[close + 1]?.text ?? "")) return -1;
189603
189858
  let depth = 0;
189604
189859
  for (let cursor = close; cursor > 0; cursor--) {
189605
189860
  const token = tokens[cursor];
@@ -189607,7 +189862,7 @@ function genericCallNameIndex(tokens, close) {
189607
189862
  if (token.text === ">") depth++;
189608
189863
  else if (token.text === "<") {
189609
189864
  if (--depth === 0) {
189610
- const valid = tokens[close + 1]?.text === "." ? new Parser(tokens.slice(cursor - 1, close + 1)).typeEnd() === close - cursor + 2 : callOpenParenIndex(tokens, cursor - 1) === close + 1;
189865
+ const valid = tokens[close + 1]?.text !== "(" ? new Parser(tokens.slice(cursor - 1, close + 1)).typeEnd() === close - cursor + 2 : callOpenParenIndex(tokens, cursor - 1) === close + 1;
189611
189866
  return valid ? cursor - 1 : -1;
189612
189867
  }
189613
189868
  } else if (!isCallTypeArgumentToken(token)) return -1;
@@ -189633,13 +189888,6 @@ function wordRangeAt(text, offset) {
189633
189888
  function isTypePosition(tokens) {
189634
189889
  const tail = tokens[tokens.length - 1];
189635
189890
  if (!tail) return false;
189636
- if (tail.kind === "operator" && tail.text === "<") {
189637
- const previous = tokens[tokens.length - 2];
189638
- return previous?.text === "Dictionary" || previous?.text === "Set";
189639
- }
189640
- if (tail.kind === "punctuation" && tail.text === ",") {
189641
- return tokens.some((token) => token.text === "Dictionary");
189642
- }
189643
189891
  if (tail.kind === "keyword" && tail.text === "is") return true;
189644
189892
  if (tail.text === "not" && tokens.at(-2)?.text === "is") return true;
189645
189893
  return false;
@@ -189758,11 +190006,10 @@ function isTypeAnnotationReference(snapshot, reference2) {
189758
190006
  function isConstructorTypeReference(snapshot, reference2) {
189759
190007
  return scriptFeatureIndex(snapshot).calls.get(reference2.start)?.kind === "constructor";
189760
190008
  }
189761
- var SCRIPT_FEATURE_INDEX, assumedLambdaInputs, LIST_OPENERS, LIST_CLOSERS, TUPLE_LABEL_DECLARATIONS, NAMED_ARGUMENT_LABELS, NO_EXPECTED_VALUE, CONSTRUCTIONS, FLOW_PROBES, OVERLOADED_FUNCTION_NAMES, GENERIC_CALL_NAMES, LOCAL_SCOPE_INDEX, NAMED_ITEM_INDEX, COLLECTION_FUNCTION_DOCUMENTATION, LOCAL_SYMBOL_CACHE, CALL_COMMIT_CHARACTERS, GENERIC_CALL_COMMIT_CHARACTERS, SETTER_VALUE_ID_SUFFIX, LAMBDA_BODY_INDEX;
190009
+ var SCRIPT_FEATURE_INDEX, assumedLambdaInputs, LIST_OPENERS, LIST_CLOSERS, TUPLE_LABEL_DECLARATIONS, NAMED_ARGUMENT_LABELS, NO_EXPECTED_VALUE, CONSTRUCTIONS, ANNOTATION_TYPE_NAMES, FLOW_PROBES, OVERLOADED_FUNCTION_NAMES, GENERIC_CALL_NAMES, LOCAL_SCOPE_INDEX, NAMED_ITEM_INDEX, COLLECTION_FUNCTION_DOCUMENTATION, LOCAL_SYMBOL_CACHE, CALL_COMMIT_CHARACTERS, GENERIC_CALL_COMMIT_CHARACTERS, SETTER_VALUE_ID_SUFFIX, LAMBDA_BODY_INDEX;
189762
190010
  var init_analyzer = __esm({
189763
190011
  "../packages/neoscript-language/src/analyzer.ts"() {
189764
190012
  "use strict";
189765
- init_argument_name_completions();
189766
190013
  init_extension_members();
189767
190014
  init_random_contract();
189768
190015
  init_error_contract();
@@ -189790,6 +190037,9 @@ var init_analyzer = __esm({
189790
190037
  NAMED_ARGUMENT_LABELS = /* @__PURE__ */ new WeakMap();
189791
190038
  NO_EXPECTED_VALUE = { type: null };
189792
190039
  CONSTRUCTIONS = /* @__PURE__ */ new WeakMap();
190040
+ ANNOTATION_TYPE_NAMES = new Set(
190041
+ NEOSCRIPT_BUILTIN_ANNOTATION_TYPES
190042
+ );
189793
190043
  FLOW_PROBES = /* @__PURE__ */ new WeakMap();
189794
190044
  OVERLOADED_FUNCTION_NAMES = /* @__PURE__ */ new WeakMap();
189795
190045
  GENERIC_CALL_NAMES = /* @__PURE__ */ new WeakMap();
@@ -189853,6 +190103,43 @@ var init_parity_contract = __esm({
189853
190103
  }
189854
190104
  });
189855
190105
 
190106
+ // ../packages/neoscript-language/src/argument-name-completions.ts
190107
+ function argumentNameCompletions(fields, tokens, start, prefixEnd, position) {
190108
+ const edit = argumentNameCompletionEdit(tokens, start, prefixEnd, position);
190109
+ if (!edit) return [];
190110
+ const { range: range2, hasColon } = edit;
190111
+ const items = [];
190112
+ for (const field of fields) {
190113
+ const insertText = hasColon ? field.name : `${field.name}: `;
190114
+ items.push({
190115
+ label: field.name,
190116
+ kind: "property",
190117
+ detail: field.defaultText === void 0 ? field.type : `[${field.type} = ${field.defaultText}]`,
190118
+ insertText,
190119
+ textEdit: { range: range2, newText: insertText }
190120
+ });
190121
+ }
190122
+ return items;
190123
+ }
190124
+ function argumentNameCompletionEdit(tokens, start, prefixEnd, position) {
190125
+ const first = tokens[start];
190126
+ if (prefixEnd > start + 1) return null;
190127
+ if (prefixEnd > start && (!first || !isCallArgumentLabelToken(first)))
190128
+ return null;
190129
+ const editingName = first !== void 0 && isCallArgumentLabelToken(first) && positionCompare(first.range.start, position) <= 0 && positionCompare(position, first.range.end) <= 0;
190130
+ if (first && isCallArgumentLabelToken(first) && !editingName) return null;
190131
+ const hasColon = editingName && tokens[start + 1]?.text === ":";
190132
+ const range2 = editingName ? first.range : { start: position, end: position };
190133
+ return { range: range2, hasColon };
190134
+ }
190135
+ var init_argument_name_completions = __esm({
190136
+ "../packages/neoscript-language/src/argument-name-completions.ts"() {
190137
+ "use strict";
190138
+ init_executable_parser();
190139
+ init_project_source_tokens();
190140
+ }
190141
+ });
190142
+
189856
190143
  // ../packages/neoscript-language/src/project-listener-annotations.ts
189857
190144
  function createContext2(analysis, source) {
189858
190145
  const project = cachedProjectIndex(analysis.project);
@@ -189948,6 +190235,20 @@ function sourceTypeAst(type2) {
189948
190235
  column: type2.range.start.character + 1
189949
190236
  }
189950
190237
  };
190238
+ if (type2.tupleElements)
190239
+ return {
190240
+ ...common,
190241
+ kind: "tuple",
190242
+ elements: type2.tupleElements.map((element) => {
190243
+ const nested = sourceTypeAst(element.type);
190244
+ return {
190245
+ type: nested,
190246
+ pos: nested.pos,
190247
+ ...element.name ? { name: element.name } : {},
190248
+ ...element.nameRange ? { nameRange: element.nameRange } : {}
190249
+ };
190250
+ })
190251
+ };
189951
190252
  const args = type2.typeArguments;
189952
190253
  if ((type2.name === "List" || type2.name === "Set") && args[0])
189953
190254
  return {
@@ -190828,6 +191129,63 @@ function projectDiagnostics(analysis, uri) {
190828
191129
  }));
190829
191130
  }
190830
191131
  function projectCompletions(analysis, document, position) {
191132
+ const result = projectCompletionsAt(analysis, document, position);
191133
+ const referenceNames = projectReferenceArgumentCompletions(
191134
+ analysis,
191135
+ document,
191136
+ position
191137
+ );
191138
+ return referenceNames.length ? { ...result, items: [...referenceNames, ...result.items] } : result;
191139
+ }
191140
+ function projectReferenceArgumentCompletions(analysis, document, position) {
191141
+ if (projectTokenAt(document, position)?.kind === "comment") return [];
191142
+ const documentTokens = projectSignificantTokens(analysis, document);
191143
+ const tokens = tokensBeforePosition(documentTokens, position);
191144
+ const openIndex = activeCallOpenIndex(tokens, position);
191145
+ if (openIndex < 0) return [];
191146
+ const calleeIndex = projectCallCalleeIndex(tokens, openIndex);
191147
+ if (tokens[calleeIndex]?.text !== "Reference" || tokens[calleeIndex + 1]?.text !== "<")
191148
+ return [];
191149
+ if ([".", "?.", "new"].includes(tokens[calleeIndex - 1]?.text ?? ""))
191150
+ return [];
191151
+ const active = activeCallArgument(tokens, openIndex, position);
191152
+ if (active.label !== null) return [];
191153
+ if (tokens.length > active.start + 1) return [];
191154
+ const args = projectCallArguments(documentTokens, openIndex);
191155
+ let field;
191156
+ if (active.index === 0) field = { name: "id", type: "string" };
191157
+ else if (active.index === 1 && args[0]?.name === "id") {
191158
+ const source = analysis.documents.get(document.uri);
191159
+ if (source?.listenerStatements?.some(
191160
+ (statement) => rangeContains(statement.range, position)
191161
+ ))
191162
+ return [];
191163
+ const before = tokens[calleeIndex - 1];
191164
+ if (before?.text === ")" && !initializerRootAt(analysis, document, position) && !projectBodySnapshotAt(analysis, document, position)) {
191165
+ const annotationOpen = activeCallOpenIndex(
191166
+ tokens.slice(0, calleeIndex - 1),
191167
+ before.range.start
191168
+ );
191169
+ if (tokens[annotationOpen - 1]?.text === "listeners" && tokens[annotationOpen - 2]?.text === "@")
191170
+ return [];
191171
+ }
191172
+ const target = tokens[calleeIndex + 2]?.text;
191173
+ if (target === "NeoImage" || target === "NeoAudioClip") return [];
191174
+ field = { name: "withProvenance", type: "bool", defaultText: "false" };
191175
+ } else return [];
191176
+ if (args.some(
191177
+ (argument2) => argument2.index !== active.index && argument2.name === field.name
191178
+ ))
191179
+ return [];
191180
+ return argumentNameCompletions(
191181
+ [field],
191182
+ documentTokens,
191183
+ active.start,
191184
+ tokens.length,
191185
+ position
191186
+ );
191187
+ }
191188
+ function projectCompletionsAt(analysis, document, position) {
190831
191189
  if (projectTokenAt(document, position)?.kind === "comment") {
190832
191190
  return { isIncomplete: false, items: [] };
190833
191191
  }
@@ -190902,6 +191260,29 @@ function projectCompletions(analysis, document, position) {
190902
191260
  position,
190903
191261
  annotationSite
190904
191262
  );
191263
+ const lambda = expression && completeLambdaBody(expression.snapshot, position);
191264
+ if (lambda && expression) {
191265
+ const members3 = projectInitializerMemberCompletions(
191266
+ analysis,
191267
+ document,
191268
+ position,
191269
+ expression.snapshot
191270
+ );
191271
+ if (members3) return { ...lambda, items: members3 };
191272
+ const names2 = projectConstructorArgumentCompletions(
191273
+ analysis,
191274
+ document,
191275
+ position,
191276
+ expression.snapshot
191277
+ );
191278
+ const items = names2?.length ? [...names2, ...lambda.items] : lambda.items;
191279
+ return {
191280
+ ...lambda,
191281
+ items: variantScopeInBody ? [...items, variantScopeInBody] : items
191282
+ };
191283
+ }
191284
+ const typeArgument = expression && completeTypeArgument(expression.snapshot, position);
191285
+ if (typeArgument) return typeArgument;
190905
191286
  const argument2 = expression && completeFunctionArgument(expression.snapshot, position);
190906
191287
  if (argument2) return argument2;
190907
191288
  const builtinMembers = projectBuiltinStaticMemberCompletions(
@@ -191430,7 +191811,7 @@ function projectExpressionMemberCompletions(analysis, document, position, annota
191430
191811
  const dot = before.at(-1);
191431
191812
  if (dot?.text !== "." && dot?.text !== "?.") return null;
191432
191813
  const receiver = before.at(-2);
191433
- if (!receiver || !(receiver.kind === "identifier" || receiver.kind === "type" || [")", "]", ">", "!", "this", "base", "root"].includes(receiver.text)))
191814
+ if (!receiver || !(receiver.kind === "identifier" || receiver.kind === "type" || [")", "]", "}", ">", "!", "this", "base", "root"].includes(receiver.text)))
191434
191815
  return null;
191435
191816
  const expression = projectExpressionSnapshotAt(
191436
191817
  analysis,
@@ -191460,6 +191841,11 @@ function projectExpressionSnapshotAt(analysis, document, position, annotationSit
191460
191841
  const { thisClass: _thisClass, ...staticContext } = language.context;
191461
191842
  context = { ...staticContext, staticMember: true };
191462
191843
  }
191844
+ if (root && !argument2) {
191845
+ const expected = constructionSiteAt(analysis, document, root.range.start);
191846
+ if (expected?.expectedTypeRef)
191847
+ context = { ...context, returnType: expected.expectedTypeRef };
191848
+ }
191463
191849
  const key = range2 ?? context;
191464
191850
  let documents = PROJECT_EXPRESSION_SNAPSHOT_CACHE.get(analysis);
191465
191851
  if (!documents) {
@@ -191863,6 +192249,7 @@ function projectConstructorArgumentCompletions(analysis, document, position, bod
191863
192249
  if (!typeName) return null;
191864
192250
  const active = activeCallArgument(tokens, openIndex, position);
191865
192251
  if (active.label !== null) return null;
192252
+ if (tokens.length > active.start + 1) return null;
191866
192253
  const args = projectCallArguments(documentTokens, openIndex);
191867
192254
  const builtin = lookupVariantFolderArgumentFields(typeName) ?? graphConstructorNamedArguments(typeName);
191868
192255
  const fields = builtin ? unusedConstructorArguments(builtin, args, active.index) : declaredConstructorNamedArguments(analysis, typeName, args, active.index);
@@ -191946,18 +192333,16 @@ function parameterArgumentField(parameter4) {
191946
192333
  ...parameter4.defaultValue === void 0 ? {} : { defaultText: parameter4.defaultValue.text }
191947
192334
  };
191948
192335
  }
191949
- function projectInitializerMemberCompletions(analysis, document, position) {
191950
- const site = constructionSiteAt(analysis, document, position);
191951
- if (!site?.atInitializerKey) return null;
191952
- const typeName = site.initializerTypeName;
191953
- if (typeName === null) return null;
192336
+ function projectInitializerMemberCompletions(analysis, document, position, body) {
192337
+ const site = body ? null : constructionSiteAt(analysis, document, position);
192338
+ const context = body ? initializerKeyContextAt(body, position) : null;
192339
+ const typeName = body ? context?.typeName : site?.initializerTypeName;
192340
+ if (typeName == null) return null;
192341
+ if (!body && !site?.atInitializerKey) return null;
192342
+ const keys = context?.keys ?? site?.initializerKeys ?? [];
191954
192343
  const index = projectConstructionIndex(analysis);
191955
- const unsettled = unsettledRequiredMembers(
191956
- index,
191957
- typeName,
191958
- site.initializerKeys
191959
- );
191960
- const taken = new Set(site.initializerKeys.map((key) => key.toLowerCase()));
192344
+ const unsettled = unsettledRequiredMembers(index, typeName, keys);
192345
+ const taken = new Set(keys.map((key) => key.toLowerCase()));
191961
192346
  for (const member of unsettled) taken.add(member.name.toLowerCase());
191962
192347
  const items = unsettled.map((member) => ({
191963
192348
  label: member.name,
@@ -193635,6 +194020,7 @@ function indexConstructionSites(analysis, document, root) {
193635
194020
  end++;
193636
194021
  const tokens = allTokens.slice(start, end).filter((token) => token.kind !== "comment" && token.kind !== "eof");
193637
194022
  let delimiterEnds;
194023
+ const genericCallOpens = constructionGenericCallOpens(tokens);
193638
194024
  const language = listenerSourceContext(analysis, document, root.range.start);
193639
194025
  const sourceType = (type2) => resolveSourceType(type2, language.context, language.project);
193640
194026
  const fieldType = (owner, name) => {
@@ -193687,7 +194073,11 @@ function indexConstructionSites(analysis, document, root) {
193687
194073
  case "object":
193688
194074
  case "list":
193689
194075
  case "dictionary":
194076
+ case "tuple":
194077
+ case "group":
193690
194078
  return frame.slotId;
194079
+ case "switch":
194080
+ return frame.inResult ? frame.slotId : null;
193691
194081
  case "call":
193692
194082
  case "opaque":
193693
194083
  return null;
@@ -193699,7 +194089,12 @@ function indexConstructionSites(analysis, document, root) {
193699
194089
  switch (frame.kind) {
193700
194090
  case "object":
193701
194091
  case "dictionary":
194092
+ case "group":
193702
194093
  return frame.slotTypeRef;
194094
+ case "tuple":
194095
+ return frame.typeRef.elements[frame.elementIndex]?.type ?? null;
194096
+ case "switch":
194097
+ return frame.inResult ? frame.resultTypeRef : null;
193703
194098
  case "list":
193704
194099
  return frame.elementTypeRef;
193705
194100
  case "opaque":
@@ -193737,7 +194132,12 @@ function indexConstructionSites(analysis, document, root) {
193737
194132
  switch (frame.kind) {
193738
194133
  case "object":
193739
194134
  case "dictionary":
194135
+ case "group":
193740
194136
  return frame.slotType;
194137
+ case "tuple":
194138
+ return frame.type?.tupleElements?.[frame.elementIndex]?.type ?? null;
194139
+ case "switch":
194140
+ return frame.inResult ? frame.resultType : null;
193741
194141
  case "list":
193742
194142
  return frame.elementType;
193743
194143
  case "call":
@@ -193834,7 +194234,7 @@ function indexConstructionSites(analysis, document, root) {
193834
194234
  sawNew = true;
193835
194235
  newStart = index;
193836
194236
  pendingNewTypeRef = expectedTypeRef();
193837
- pendingNewTypeName = expectedType()?.name ?? null;
194237
+ pendingNewTypeName = pendingNewTypeRef?.kind === "named" ? language.project.typeById.get(pendingNewTypeRef.typeId)?.name ?? null : expectedType()?.name ?? null;
193838
194238
  closedConstructorTypeName = null;
193839
194239
  continue;
193840
194240
  }
@@ -193872,8 +194272,24 @@ function indexConstructionSites(analysis, document, root) {
193872
194272
  }
193873
194273
  continue;
193874
194274
  }
194275
+ if (!sawNew) {
194276
+ const call = genericCallOpens.get(index) ?? -1;
194277
+ if (call >= 0) {
194278
+ index = call - 1;
194279
+ closedConstructorTypeName = null;
194280
+ continue;
194281
+ }
194282
+ }
193875
194283
  if (token.text === "{") {
193876
- if (sawNew || closedConstructorTypeName !== null) {
194284
+ if (tokens[index - 1]?.text === "switch") {
194285
+ stack.push({
194286
+ kind: "switch",
194287
+ resultType: expectedType(),
194288
+ resultTypeRef: expectedTypeRef(),
194289
+ slotId: expectedSlotId(),
194290
+ inResult: false
194291
+ });
194292
+ } else if (sawNew || closedConstructorTypeName !== null) {
193877
194293
  const frame2 = {
193878
194294
  kind: "object",
193879
194295
  typeName: pendingNewTypeName ?? closedConstructorTypeName,
@@ -193934,7 +194350,33 @@ function indexConstructionSites(analysis, document, root) {
193934
194350
  sawNew = false;
193935
194351
  pendingNewTypeName = null;
193936
194352
  } else {
193937
- stack.push({ kind: "opaque" });
194353
+ const ends = delimiterEnds ??= projectDelimiterEnds(tokens);
194354
+ const expected = expectedTypeRef();
194355
+ const kind = constructionParenthesesKind(
194356
+ tokens,
194357
+ index,
194358
+ ends,
194359
+ genericCallOpens,
194360
+ expected?.kind === "tuple"
194361
+ );
194362
+ if (kind === "tuple" && expected?.kind === "tuple") {
194363
+ stack.push({
194364
+ kind: "tuple",
194365
+ type: expectedType(),
194366
+ typeRef: expected,
194367
+ slotId: expectedSlotId(),
194368
+ elementIndex: 0
194369
+ });
194370
+ } else if (kind === "group") {
194371
+ stack.push({
194372
+ kind: "group",
194373
+ slotType: expectedType(),
194374
+ slotTypeRef: expected,
194375
+ slotId: expectedSlotId()
194376
+ });
194377
+ } else {
194378
+ stack.push({ kind: "opaque" });
194379
+ }
193938
194380
  }
193939
194381
  closedConstructorTypeName = null;
193940
194382
  continue;
@@ -193987,6 +194429,11 @@ function indexConstructionSites(analysis, document, root) {
193987
194429
  frame.slotType = null;
193988
194430
  frame.slotTypeRef = null;
193989
194431
  }
194432
+ } else if (frame.kind === "tuple") {
194433
+ if (token.text === ",") frame.elementIndex++;
194434
+ } else if (frame.kind === "switch") {
194435
+ if (token.text === "=>") frame.inResult = true;
194436
+ else if (token.text === ",") frame.inResult = false;
193990
194437
  } else if (frame.kind === "call") {
193991
194438
  if (token.text === ",") {
193992
194439
  frame.argumentIndex++;
@@ -194005,6 +194452,43 @@ function indexConstructionSites(analysis, document, root) {
194005
194452
  sites.push({ position: previousPosition, site: snapshot() });
194006
194453
  return sites;
194007
194454
  }
194455
+ function constructionParenthesesKind(tokens, open2, ends, genericCallOpens, tupleExpected) {
194456
+ const previous = tokens[open2 - 1];
194457
+ const close = ends.get(open2);
194458
+ if (previous?.kind === "identifier" || previous?.kind === "type" || [")", "]", ">", "!"].includes(previous?.text ?? "") || close !== void 0 && tokens[close + 1]?.text === "=>")
194459
+ return null;
194460
+ for (let index = open2 + 1; index < (close ?? tokens.length); index++) {
194461
+ const token = tokens[index];
194462
+ if (token.text === ",") return "tuple";
194463
+ if (["(", "[", "{"].includes(token.text)) {
194464
+ const end = ends.get(index);
194465
+ if (end === void 0) return tupleExpected ? "tuple" : "group";
194466
+ index = end;
194467
+ } else if (token.text === "new" && tokens[index + 1]?.text !== "(") {
194468
+ const end = new Parser(tokens, index + 1).typeEnd();
194469
+ if (end > index + 1) index = end - 1;
194470
+ } else {
194471
+ const call = genericCallOpens.get(index) ?? -1;
194472
+ if (call >= 0) index = call - 1;
194473
+ }
194474
+ }
194475
+ return close === void 0 && tupleExpected ? "tuple" : "group";
194476
+ }
194477
+ function constructionGenericCallOpens(tokens) {
194478
+ const opens = [];
194479
+ const calls = /* @__PURE__ */ new Map();
194480
+ for (let index = 0; index < tokens.length; index++) {
194481
+ if (tokens[index].text === "<") opens.push(index);
194482
+ else if (tokens[index].text === ">") {
194483
+ const open2 = opens.pop();
194484
+ if (open2 === void 0 || open2 === 0 || tokens[index + 1]?.text !== "(")
194485
+ continue;
194486
+ const end = new Parser(tokens, open2 - 1).typeEnd();
194487
+ if (end === index + 1) calls.set(open2 - 1, end);
194488
+ }
194489
+ }
194490
+ return calls;
194491
+ }
194008
194492
  function collectionElementType2(type2) {
194009
194493
  if (!type2) return null;
194010
194494
  if (type2.name === "List" || type2.name === "Set") {
@@ -218474,10 +218958,21 @@ async function runExport(workspace, options, session) {
218474
218958
  console.log(
218475
218959
  result.localChanges === null ? " Clean: the export holds the pulled head." : ` Local: the export includes ${result.localChanges} local change(s). Player builds fail and saves stay local until \`neo push\` or a clean \`neo export\`.`
218476
218960
  );
218961
+ let csharp14Members = 0;
218477
218962
  for (const diagnostic of result.diagnostics) {
218478
218963
  if (diagnostic.severity === "error") continue;
218964
+ if (diagnostic.code === "extension-wrapper-target") {
218965
+ csharp14Members++;
218966
+ continue;
218967
+ }
218479
218968
  warn(formatDiagnostic(diagnostic));
218480
218969
  }
218970
+ if (csharp14Members > 0) {
218971
+ const members2 = csharp14Members === 1 ? "member that requires" : "members that require";
218972
+ warn(
218973
+ `Skipping codegen for ${csharp14Members} ${members2} C# 14. NeoScript execution is unaffected.`
218974
+ );
218975
+ }
218481
218976
  if (result.schemaSkew !== null) {
218482
218977
  warn(
218483
218978
  `Unity's project.json was written at schema ${result.schemaSkew}; this export writes schema ${PROJECT_UNITY_EXPORT_SCHEMA_VERSION}. Update the Neo Compose SDK in Unity to a version that reads schema ${PROJECT_UNITY_EXPORT_SCHEMA_VERSION}.`
@@ -238168,7 +238663,7 @@ var releaseWorkspaceLock = () => void 0;
238168
238663
  async function main() {
238169
238664
  const args = parseArgs(process.argv.slice(2));
238170
238665
  if (args.command === "--version") {
238171
- console.log("0.89.1");
238666
+ console.log("0.89.3");
238172
238667
  return;
238173
238668
  }
238174
238669
  if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {