@neocompose/cli 0.89.0 → 0.89.2

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.0",
19380
+ cliVersion: "0.89.2",
19381
19381
  projectFileUploadBatchSize: 32,
19382
19382
  documentRecords: {
19383
19383
  member: {
@@ -36679,8 +36679,12 @@ var init_function_type_inference = __esm({
36679
36679
  const value = actual.parameterTypes[index];
36680
36680
  if (value !== void 0) this.add(value, expected, "exact");
36681
36681
  });
36682
- } else if (pattern.kind === "reference" && actual.kind === "reference") {
36683
- this.add(actual.target, pattern.target, "exact");
36682
+ } else if (pattern.kind === "reference") {
36683
+ this.add(
36684
+ actual.kind === "reference" ? actual.target : actual,
36685
+ pattern.target,
36686
+ "exact"
36687
+ );
36684
36688
  }
36685
36689
  }
36686
36690
  fix(index) {
@@ -37834,6 +37838,17 @@ var init_read_class_member = __esm({
37834
37838
  });
37835
37839
 
37836
37840
  // ../packages/neoscript-language/src/declared-constructors.ts
37841
+ function neoScriptCommonParameterNames(signatures) {
37842
+ const names2 = [];
37843
+ for (const [signatureIndex, { parameters }] of signatures.entries()) {
37844
+ const length = Math.max(names2.length, parameters.length);
37845
+ for (let index = 0; index < length; index++) {
37846
+ const name = parameters[index]?.name;
37847
+ names2[index] = signatureIndex === 0 || names2[index] === name ? name ?? null : null;
37848
+ }
37849
+ }
37850
+ return names2;
37851
+ }
37837
37852
  function neoScriptArgumentNameSetKey(names2) {
37838
37853
  return [...names2].map((name) => name.toLowerCase()).sort().join(",");
37839
37854
  }
@@ -47001,11 +47016,14 @@ function resolveMemberForValueRow(row, ctx, visited) {
47001
47016
  ctx.__valueOverlay
47002
47017
  );
47003
47018
  if (parent === null) continue;
47004
- const parentMember = resolveMemberForValueRow(
47005
- parent,
47006
- ctx,
47007
- new Set(visited)
47008
- );
47019
+ let parentMember = resolveMemberForValueRow(parent, ctx, new Set(visited));
47020
+ if (parentMember?.kind === 21 /* Generic */) {
47021
+ parentMember = substituteMember(
47022
+ parentMember,
47023
+ runtimeParentGenericEnv(parent, ctx, /* @__PURE__ */ new Set()),
47024
+ ctx.vm.members
47025
+ );
47026
+ }
47009
47027
  if (parentMember !== null && isMemberTupleBase(parentMember)) {
47010
47028
  const memberId = parentMember.elementMemberIds[Number(link.key)];
47011
47029
  return memberId === void 0 ? null : evalMemberById(ctx.vm, memberId);
@@ -62517,18 +62535,19 @@ function buildNeoScriptEditorIndex(lexed, kind) {
62517
62535
  lexed,
62518
62536
  diagnostics
62519
62537
  );
62538
+ const regionCalls = indexCalls(executable, executablePairs, lexed);
62520
62539
  const regionLocals = applySwitchSectionScopes(
62521
62540
  indexLocals(
62522
62541
  executable,
62523
62542
  executablePairs,
62524
62543
  lexed,
62525
62544
  diagnostics,
62526
- lambdaBodies
62545
+ lambdaBodies,
62546
+ regionCalls
62527
62547
  ),
62528
62548
  regionSwitches,
62529
62549
  lexed
62530
62550
  );
62531
- const regionCalls = indexCalls(executable, executablePairs, lexed);
62532
62551
  const declarations = new Set(
62533
62552
  regionLocals.map(
62534
62553
  (local) => `${local.nameRange.start.line}:${local.nameRange.start.character}`
@@ -62981,9 +63000,10 @@ function duplicateUnitDiagnostic(label, units, diagnostics) {
62981
63000
  ]
62982
63001
  });
62983
63002
  }
62984
- function indexLocals(tokens, pairs, lexed, diagnostics, lambdaBodies) {
63003
+ function indexLocals(tokens, pairs, lexed, diagnostics, lambdaBodies, calls) {
62985
63004
  const locals = [];
62986
63005
  const braceScope = braceScopeIndex(tokens, lexed.end);
63006
+ const switchArrows = switchExpressionArrowIndexes(tokens, calls);
62987
63007
  for (let index = 0; index < tokens.length; index++) {
62988
63008
  const caught = tryParseCatchParameter(tokens, index, pairs, lexed);
62989
63009
  if (caught) {
@@ -63004,7 +63024,13 @@ function indexLocals(tokens, pairs, lexed, diagnostics, lambdaBodies) {
63004
63024
  index = loop.resumeTokenIndex;
63005
63025
  continue;
63006
63026
  }
63007
- const lambda = tryParseLambdaParameters(tokens, index, pairs, lexed);
63027
+ const lambda = tryParseLambdaParameters(
63028
+ tokens,
63029
+ index,
63030
+ pairs,
63031
+ lexed,
63032
+ switchArrows
63033
+ );
63008
63034
  if (lambda) {
63009
63035
  locals.push(...lambda.locals);
63010
63036
  lambdaBodies.push(lambda.body);
@@ -63165,7 +63191,35 @@ function statementEndTokenIndex(tokens, start) {
63165
63191
  }
63166
63192
  return tokens.length;
63167
63193
  }
63168
- function tryParseLambdaParameters(tokens, start, pairs, lexed) {
63194
+ function switchExpressionArrowIndexes(tokens, calls) {
63195
+ const enclosing = enclosingOpenerIndex(tokens);
63196
+ const inResult = /* @__PURE__ */ new Set();
63197
+ const arrows = /* @__PURE__ */ new Set();
63198
+ const genericEnds = /* @__PURE__ */ new Map();
63199
+ for (const call of calls) {
63200
+ const first = call.typeArgumentTokens?.[0];
63201
+ if (first) genericEnds.set(first.start, call.openParenOffset);
63202
+ }
63203
+ for (let index = 0; index < tokens.length; index++) {
63204
+ const token = tokens[index];
63205
+ const genericEnd = genericEnds.get(token.start);
63206
+ if (genericEnd !== void 0) {
63207
+ while (tokens[index + 1] && tokens[index + 1].start < genericEnd)
63208
+ index++;
63209
+ continue;
63210
+ }
63211
+ const opener = enclosing[index];
63212
+ if (tokens[opener]?.text !== "{" || tokens[opener - 1]?.text !== "switch")
63213
+ continue;
63214
+ if (token.text === ",") inResult.delete(opener);
63215
+ else if (token.text === "=>" && !inResult.has(opener)) {
63216
+ arrows.add(index);
63217
+ inResult.add(opener);
63218
+ }
63219
+ }
63220
+ return arrows;
63221
+ }
63222
+ function tryParseLambdaParameters(tokens, start, pairs, lexed, switchArrows) {
63169
63223
  const open2 = tokens[start];
63170
63224
  if (!open2) return null;
63171
63225
  if (open2.kind === "identifier") {
@@ -63173,6 +63227,7 @@ function tryParseLambdaParameters(tokens, start, pairs, lexed) {
63173
63227
  if (!arrow2 || arrow2.kind !== "operator" || arrow2.text !== "=>") {
63174
63228
  return null;
63175
63229
  }
63230
+ if (switchArrows.has(start + 1)) return null;
63176
63231
  const body2 = lambdaBodySpan(tokens, start + 1, pairs, lexed);
63177
63232
  return {
63178
63233
  locals: [
@@ -63197,6 +63252,7 @@ function tryParseLambdaParameters(tokens, start, pairs, lexed) {
63197
63252
  if (closeIndex === void 0) return null;
63198
63253
  const arrow = tokens[closeIndex + 1];
63199
63254
  if (!arrow || arrow.kind !== "operator" || arrow.text !== "=>") return null;
63255
+ if (switchArrows.has(closeIndex + 1)) return null;
63200
63256
  const body = lambdaBodySpan(tokens, closeIndex + 1, pairs, lexed);
63201
63257
  const locals = [];
63202
63258
  for (const [parameterIndex, [from, to]] of patternSegments(
@@ -63402,7 +63458,9 @@ function indexCalls(tokens, pairs, lexed) {
63402
63458
  const name = tokens[index];
63403
63459
  const openIndex = callOpenParenIndex(tokens, index);
63404
63460
  const open2 = tokens[openIndex];
63405
- if (!name || name.kind !== "identifier") continue;
63461
+ if (!name) continue;
63462
+ const expression = [")", "]", "!"].includes(name.text) && openIndex === index + 1;
63463
+ if (name.kind !== "identifier" && !expression) continue;
63406
63464
  if (!open2 || open2.kind !== "punctuation" || open2.text !== "(") continue;
63407
63465
  const previous = tokens[index - 1];
63408
63466
  const targetTyped = isContextualNew(name, previous, open2);
@@ -63431,14 +63489,19 @@ function indexCalls(tokens, pairs, lexed) {
63431
63489
  segmentStart = token.end;
63432
63490
  segmentStartIndex = cursor + 1;
63433
63491
  }
63492
+ if (tokens[cursor + 1]?.text === "<") {
63493
+ const genericOpen = callOpenParenIndex(tokens, cursor);
63494
+ if (genericOpen >= 0) cursor = genericOpen - 1;
63495
+ }
63434
63496
  }
63435
63497
  if (segmentStart < (close?.start ?? lexed.end)) {
63436
63498
  ranges.push(lexed.source.range(segmentStart, close?.start ?? lexed.end));
63437
63499
  names2.push(callArgumentLabel(tokens, segmentStartIndex, limit));
63438
63500
  }
63501
+ const namedKind = contextualKeyword ? "constructor" : "function";
63439
63502
  calls.push({
63440
- kind: contextualKeyword ? "constructor" : "function",
63441
- name: name.text,
63503
+ kind: expression ? "expression" : namedKind,
63504
+ name: expression ? "delegate" : name.text,
63442
63505
  nameRange: name.range,
63443
63506
  ...contextualKeyword ? { contextualKeywordRange: contextualKeyword.range } : {},
63444
63507
  ...targetTyped ? { targetTyped: true } : {},
@@ -67495,6 +67558,7 @@ function weighedLambda(probes, expected) {
67495
67558
  if (probe === void 0 || probe.type.kind !== "delegate") return void 0;
67496
67559
  if (probe.needsReturnContext !== true && sameCompilationType(probe.type.returnType, expected.returnType))
67497
67560
  return probe;
67561
+ if (expected.returnType.kind === "reference") return void 0;
67498
67562
  return probe.retype?.(expected.returnType);
67499
67563
  }
67500
67564
  function replaceReturns(instructions, replaced) {
@@ -67616,6 +67680,9 @@ function andList(texts) {
67616
67680
  if (texts.length <= 2) return texts.join(" and ");
67617
67681
  return `${texts.slice(0, -1).join(", ")}, and ${texts[texts.length - 1]}`;
67618
67682
  }
67683
+ function isContextualReferenceExpression(expression) {
67684
+ return expression.kind === "conditional" || expression.kind === "switchExpression" || expression.kind === "coalesce" || expression.kind === "annotated";
67685
+ }
67619
67686
  function isPureArgument(expression) {
67620
67687
  switch (expression.kind) {
67621
67688
  case "litInt":
@@ -68432,6 +68499,10 @@ var init_strict_resolver = __esm({
68432
68499
  if (expected === void 0) return;
68433
68500
  this.requireAssignable(resolved.type, expected, expression.pos, "value");
68434
68501
  }
68502
+ /** Type a source expression with the same call binding rules as executable code. */
68503
+ resolveExpressionType(expression) {
68504
+ return this.resolveExpression(expression, this.initialScope()).type;
68505
+ }
68435
68506
  persistedListenerCompletions(receiver, expected) {
68436
68507
  const scope = this.initialScope();
68437
68508
  let receiverType = this.context.thisClass;
@@ -70698,8 +70769,7 @@ var init_strict_resolver = __esm({
70698
70769
  );
70699
70770
  }
70700
70771
  }
70701
- resolveMemberRowOf(place, scope) {
70702
- const optional2 = place.optional === true;
70772
+ resolveMemberRowOf(place, scope, resolved) {
70703
70773
  if ((this.context.kind === "initializer" || this.context.kind === "initializerExpression") && this.delegateCaptureContexts.length === 0 && referencePlaceRoot(place) === "this") {
70704
70774
  const text = referencePlaceText(place) ?? "this";
70705
70775
  throw new CompileError(
@@ -70707,12 +70777,12 @@ var init_strict_resolver = __esm({
70707
70777
  place.pos
70708
70778
  );
70709
70779
  }
70710
- const slot = this.resolveMemberNatural(
70780
+ const slot = resolved ?? this.resolveMemberNatural(
70711
70781
  place.receiver,
70712
70782
  place.name,
70713
70783
  scope,
70714
70784
  place.pos,
70715
- optional2
70785
+ place.optional === true
70716
70786
  );
70717
70787
  const member = slot.symbol;
70718
70788
  if (member === void 0) {
@@ -70730,19 +70800,55 @@ var init_strict_resolver = __esm({
70730
70800
  place.pos
70731
70801
  );
70732
70802
  }
70733
- const read = slot.optionalChainType ?? slot.type;
70734
- const stored = member.lookup !== void 0 && member.lookup.multiselect !== true && read.kind !== "reference" ? {
70735
- kind: "reference",
70736
- target: { ...read, nullable: false },
70737
- ...isNullable(read) ? { nullable: true } : {}
70738
- } : read;
70739
- const type2 = this.referenceType(stored, optional2);
70803
+ const type2 = this.memberReferenceType(slot, place.optional === true);
70740
70804
  if (type2.kind !== "reference") return slot;
70741
70805
  return {
70742
70806
  pointer: { type: "rowOf" /* RowOf */, place: slot.pointer },
70743
70807
  type: type2
70744
70808
  };
70745
70809
  }
70810
+ memberReferenceType(slot, optional2) {
70811
+ const read = slot.storedType ?? slot.optionalChainType ?? slot.type;
70812
+ const stored = slot.symbol?.lookup !== void 0 && slot.symbol.lookup.multiselect !== true && read.kind !== "reference" ? {
70813
+ kind: "reference",
70814
+ target: { ...read, nullable: false },
70815
+ ...isNullable(read) ? { nullable: true } : {}
70816
+ } : read;
70817
+ return this.referenceType(
70818
+ stored,
70819
+ optional2 || slot.optionalChainType !== void 0
70820
+ );
70821
+ }
70822
+ /** Only stored member slots can acquire a reference from an expected type. */
70823
+ implicitReferenceType(expression, value) {
70824
+ if (expression.kind !== "member") return void 0;
70825
+ if (value.symbol === void 0 || value.symbol.computed === true)
70826
+ return void 0;
70827
+ return this.memberReferenceType(value, expression.optional === true);
70828
+ }
70829
+ referenceInferenceType(expression, value, pattern) {
70830
+ const read = this.readReferences(value, pattern).type;
70831
+ if (pattern.kind !== "reference" || read.kind === "reference") return read;
70832
+ return this.implicitReferenceType(expression, value) ?? read;
70833
+ }
70834
+ contextualReferenceType(expression, value, expected) {
70835
+ const read = this.readReferences(value, expected).type;
70836
+ if (expected.kind !== "reference" || isNeoScriptTypeAssignable(read, expected, this.project))
70837
+ return read;
70838
+ const reference2 = this.implicitReferenceType(expression, value);
70839
+ return reference2 !== void 0 && isNeoScriptTypeAssignable(reference2, expected, this.project) ? reference2 : read;
70840
+ }
70841
+ /** Use the same slot identity for explicit and expected-type references. */
70842
+ contextualReference(expression, value, scope, expected) {
70843
+ const read = this.readReferences(value, expected);
70844
+ if (expected?.kind !== "reference" || isNeoScriptTypeAssignable(read.type, expected, this.project))
70845
+ return read;
70846
+ const reference2 = this.implicitReferenceType(expression, value);
70847
+ if (expression.kind === "member" && reference2 !== void 0 && isNeoScriptTypeAssignable(reference2, expected, this.project)) {
70848
+ return this.resolveMemberRowOf(expression, scope, value);
70849
+ }
70850
+ return read;
70851
+ }
70746
70852
  /** Whether assigning `target` rebinds a reference to a handle. */
70747
70853
  holdsHandleReference(target) {
70748
70854
  if (target.type.kind === "reference") {
@@ -71351,13 +71457,15 @@ var init_strict_resolver = __esm({
71351
71457
  });
71352
71458
  }
71353
71459
  resolveExpression(expression, scope, expected, convertSequence = true) {
71354
- const value = this.readReferences(
71460
+ const value = this.contextualReference(
71461
+ expression,
71355
71462
  this.resolveReferenceExpression(
71356
71463
  expression,
71357
71464
  scope,
71358
71465
  expected,
71359
71466
  convertSequence
71360
71467
  ),
71468
+ scope,
71361
71469
  expected
71362
71470
  );
71363
71471
  return convertSequence ? this.convertSequence(value, expected) : value;
@@ -72879,7 +72987,8 @@ var init_strict_resolver = __esm({
72879
72987
  }
72880
72988
  entryType = common;
72881
72989
  }
72882
- if (expected?.kind === "set" && this.context.kind === "initializer") {
72990
+ const referenceSelection = expected?.kind === "set" && this.context.kind === "initializer" && (expected.elementType.kind === "reference" || hasReferenceEquality(expected.elementType, this.project));
72991
+ if (expected?.kind === "set" && this.context.kind === "initializer" && !referenceSelection) {
72883
72992
  const element = expected.elementType;
72884
72993
  const spelling = element.kind === "named" && this.project.typeById.get(element.typeId)?.kind === "enum" ? `.Option or ${this.describe({ ...element, nullable: false })}.Option values` : "literal values";
72885
72994
  throw new CompileError(
@@ -72897,7 +73006,7 @@ var init_strict_resolver = __esm({
72897
73006
  "NeoScript strict compiler produced a non-list wire type for a list literal."
72898
73007
  );
72899
73008
  }
72900
- return {
73009
+ const list = {
72901
73010
  pointer: {
72902
73011
  type: "listLiteral" /* ListLiteral */,
72903
73012
  typeInfo: wire,
@@ -72906,6 +73015,18 @@ var init_strict_resolver = __esm({
72906
73015
  type: type2,
72907
73016
  entries: resolved
72908
73017
  };
73018
+ return referenceSelection ? this.resolveCollectionQuery(
73019
+ list,
73020
+ {
73021
+ kind: "list",
73022
+ keyType: { kind: "primitive", name: "int" },
73023
+ valueType: entryType
73024
+ },
73025
+ "ToSet",
73026
+ [],
73027
+ scope,
73028
+ pos
73029
+ ) : list;
72909
73030
  }
72910
73031
  resolveDictionaryLiteral(entries, scope, expected, pos) {
72911
73032
  const expectedDictionary = expected?.kind === "dictionary" ? expected : void 0;
@@ -73616,7 +73737,12 @@ var init_strict_resolver = __esm({
73616
73737
  const rootEntry = scope.lookupFlowRoot(pathRoot(path));
73617
73738
  if (rootEntry) {
73618
73739
  const narrowed = scope.lookupNarrowedType(path, rootEntry);
73619
- if (narrowed) resolved = { ...resolved, type: narrowed };
73740
+ if (narrowed)
73741
+ resolved = {
73742
+ ...resolved,
73743
+ storedType: resolved.type,
73744
+ type: narrowed
73745
+ };
73620
73746
  }
73621
73747
  }
73622
73748
  }
@@ -76335,17 +76461,28 @@ var init_strict_resolver = __esm({
76335
76461
  args,
76336
76462
  scope
76337
76463
  );
76338
- return resolveNeoScriptDeclaredConstructorOverload(
76464
+ const resolve8 = (implicit) => resolveNeoScriptDeclaredConstructorOverload(
76339
76465
  declared,
76340
76466
  named.map((name, index) => {
76341
76467
  const inferred = inferredTypes?.[index];
76342
- if (!inferred) return { name };
76468
+ const argument2 = args[index];
76469
+ if (!inferred || !argument2) return { name };
76343
76470
  return {
76344
76471
  name,
76345
- matchesParameter: (parameter4) => isNeoScriptTypeAssignable(inferred, parameter4.type, this.project)
76472
+ matchesParameter: (parameter4) => implicit && parameter4.type.kind === "reference" && isContextualReferenceExpression(argument2) ? this.targetTypedArgumentFits(argument2, parameter4.type, scope) : isNeoScriptTypeAssignable(
76473
+ implicit ? this.contextualReferenceType(
76474
+ argument2,
76475
+ inferred,
76476
+ parameter4.type
76477
+ ) : inferred.type,
76478
+ parameter4.type,
76479
+ this.project
76480
+ )
76346
76481
  };
76347
76482
  })
76348
76483
  );
76484
+ const direct = resolve8(false);
76485
+ return direct.kind === "ambiguous" ? resolve8(true) : direct;
76349
76486
  }
76350
76487
  /**
76351
76488
  * Types for the §6.1.1 step-2 tie-break, computed only when several
@@ -76366,7 +76503,9 @@ var init_strict_resolver = __esm({
76366
76503
  const argument2 = args[index];
76367
76504
  if (!argument2) return null;
76368
76505
  try {
76369
- return this.resolveExpression(argument2, scope).type;
76506
+ if (isContextualReferenceExpression(argument2))
76507
+ this.typeOverloadEntries(argument2, scope);
76508
+ return this.resolveReferenceExpression(argument2, scope);
76370
76509
  } catch (error) {
76371
76510
  if (error instanceof CompileError) return null;
76372
76511
  throw error;
@@ -76736,7 +76875,8 @@ var init_strict_resolver = __esm({
76736
76875
  (argument2) => this.overloadArgumentKind(argument2, scope)
76737
76876
  );
76738
76877
  argumentsList2.forEach((argument2, index) => {
76739
- if (kinds[index] !== "typed") this.typeOverloadEntries(argument2, scope);
76878
+ if (kinds[index] !== "typed" || isContextualReferenceExpression(argument2))
76879
+ this.typeOverloadEntries(argument2, scope);
76740
76880
  });
76741
76881
  const typed = argumentsList2.map(
76742
76882
  (argument2, index) => kinds[index] === "targetTyped" ? void 0 : this.resolveReferenceExpression(argument2, scope)
@@ -76784,11 +76924,11 @@ var init_strict_resolver = __esm({
76784
76924
  const fits = argumentsList2.every((argument2, index) => {
76785
76925
  const parameter4 = requiredAt(parameters, index).type;
76786
76926
  const resolved = typed[index];
76787
- if (resolved === void 0 || argument2.kind === "tuple" || kinds[index] === "numeric" && parameter4.kind === "tuple") {
76927
+ if (resolved === void 0 || parameter4.kind === "reference" && isContextualReferenceExpression(argument2) || argument2.kind === "tuple" || kinds[index] === "numeric" && parameter4.kind === "tuple") {
76788
76928
  return this.targetTypedArgumentFits(argument2, parameter4, scope);
76789
76929
  }
76790
76930
  return this.typedArgumentFits(
76791
- this.readReferences(resolved, parameter4).type,
76931
+ this.contextualReferenceType(argument2, resolved, parameter4),
76792
76932
  requiredAt(kinds, index),
76793
76933
  parameter4
76794
76934
  );
@@ -76960,6 +77100,12 @@ var init_strict_resolver = __esm({
76960
77100
  }
76961
77101
  case "annotated":
76962
77102
  return this.entryFits(argument2.expression, parameter4, scope);
77103
+ case "coalesce":
77104
+ return this.entryFits(
77105
+ argument2.left,
77106
+ { ...parameter4, nullable: true },
77107
+ scope
77108
+ ) && this.entryFits(argument2.right, parameter4, scope);
76963
77109
  case "conditional": {
76964
77110
  const { trueScope, falseScope } = this.conditionalBranchScopes(
76965
77111
  argument2,
@@ -77039,12 +77185,12 @@ var init_strict_resolver = __esm({
77039
77185
  */
77040
77186
  entryFits(argument2, parameter4, scope) {
77041
77187
  const kind = this.overloadArgumentKind(argument2, scope);
77042
- if (kind === "targetTyped" || argument2.kind === "tuple" || kind === "numeric" && parameter4.kind === "tuple") {
77188
+ if (kind === "targetTyped" || parameter4.kind === "reference" && isContextualReferenceExpression(argument2) || argument2.kind === "tuple" || kind === "numeric" && parameter4.kind === "tuple") {
77043
77189
  return this.targetTypedArgumentFits(argument2, parameter4, scope);
77044
77190
  }
77045
- const resolved = isPureArgument(argument2) ? this.resolveExpression(argument2, scope) : this.overloadEntries.get(argument2) ?? this.resolveReferenceExpression(argument2, scope);
77191
+ const resolved = isPureArgument(argument2) ? this.resolveReferenceExpression(argument2, scope) : this.overloadEntries.get(argument2) ?? this.resolveReferenceExpression(argument2, scope);
77046
77192
  return this.typedArgumentFits(
77047
- this.readReferences(resolved, parameter4).type,
77193
+ this.contextualReferenceType(argument2, resolved, parameter4),
77048
77194
  kind,
77049
77195
  parameter4
77050
77196
  );
@@ -77087,6 +77233,10 @@ var init_strict_resolver = __esm({
77087
77233
  case "annotated":
77088
77234
  visit(argument2.expression, scope);
77089
77235
  return;
77236
+ case "coalesce":
77237
+ visit(argument2.left, scope);
77238
+ visit(argument2.right, scope);
77239
+ return;
77090
77240
  case "conditional": {
77091
77241
  visit(argument2.condition, scope);
77092
77242
  const { trueScope, falseScope } = this.conditionalBranchScopes(
@@ -77271,19 +77421,16 @@ var init_strict_resolver = __esm({
77271
77421
  pos,
77272
77422
  inferred?.typeArguments
77273
77423
  );
77274
- if (signature2.typeArguments.length > 0)
77275
- this.options.onCallResolved?.(pos, {
77276
- ...symbol,
77277
- type: signature2.returnType,
77278
- returnType: signature2.returnType,
77279
- parameters: signature2.parameters,
77280
- typeParameters: (symbol.typeParameters ?? []).map(
77281
- (parameter4, index) => ({
77282
- ...parameter4,
77283
- type: requiredAt(signature2.typeArguments, index)
77284
- })
77285
- )
77286
- });
77424
+ this.options.onCallResolved?.(pos, {
77425
+ ...symbol,
77426
+ type: signature2.returnType,
77427
+ returnType: signature2.returnType,
77428
+ parameters: signature2.parameters,
77429
+ typeParameters: (symbol.typeParameters ?? []).map((parameter4, index) => ({
77430
+ ...parameter4,
77431
+ type: requiredAt(signature2.typeArguments, index)
77432
+ }))
77433
+ });
77287
77434
  const wireTypeArguments = signature2.typeArguments.length ? {
77288
77435
  typeArguments: signature2.typeArguments.map(
77289
77436
  (argument2) => toWireType(argument2, this.project)
@@ -77458,7 +77605,12 @@ var init_strict_resolver = __esm({
77458
77605
  const prior = choice?.preResolved[index];
77459
77606
  const cached = inferred?.resolved.get(argument2);
77460
77607
  let resolved;
77461
- if (prior !== void 0) resolved = this.readReferences(prior, target);
77608
+ if (prior !== void 0 && !(target?.kind === "reference" && isContextualReferenceExpression(argument2) && !isNeoScriptTypeAssignable(
77609
+ this.readReferences(prior, target).type,
77610
+ target,
77611
+ this.project
77612
+ )))
77613
+ resolved = this.readReferences(prior, target);
77462
77614
  else if (cached && (sameCompilationType(cached.type, expected) || cached.pointer.type === "callFunction" /* CallFunction */)) {
77463
77615
  resolved = cached;
77464
77616
  } else {
@@ -77467,6 +77619,7 @@ var init_strict_resolver = __esm({
77467
77619
  const compile = () => this.resolveExpression(argument2, scope, target);
77468
77620
  resolved = weighed ?? (argument2.kind === "lambda" && lambdas ? this.inLambdaFrame(lambdas, argument2, compile) : compile());
77469
77621
  }
77622
+ resolved = this.contextualReference(argument2, resolved, scope, target);
77470
77623
  resolved = this.convertSequence(resolved, target);
77471
77624
  if (!isUnknown(expected)) {
77472
77625
  this.requireReferenceArgument(
@@ -77541,7 +77694,10 @@ var init_strict_resolver = __esm({
77541
77694
  if (!hasIndependentTypeEvidence(argument2)) return;
77542
77695
  const prior = weighed?.typed[index];
77543
77696
  if (prior !== void 0) {
77544
- inference.add(this.readReferences(prior, void 0).type, pattern);
77697
+ inference.add(
77698
+ this.referenceInferenceType(argument2, prior, pattern),
77699
+ pattern
77700
+ );
77545
77701
  return;
77546
77702
  }
77547
77703
  const group = pattern.kind === "delegate" ? this.inferredMethodGroupTarget(argument2, probe) : null;
@@ -77552,10 +77708,13 @@ var init_strict_resolver = __esm({
77552
77708
  pattern
77553
77709
  );
77554
77710
  } else {
77555
- const resolved = weighed?.contextless.get(argument2) ?? this.resolveExpression(argument2, probe);
77711
+ const resolved = weighed?.contextless.get(argument2) ?? this.resolveReferenceExpression(argument2, probe);
77556
77712
  weighed?.contextless.set(argument2, resolved);
77557
77713
  resolvedArguments.set(argument2, resolved);
77558
- inference.add(resolved.type, pattern);
77714
+ inference.add(
77715
+ this.referenceInferenceType(argument2, resolved, pattern),
77716
+ pattern
77717
+ );
77559
77718
  }
77560
77719
  });
77561
77720
  const error = inference.solve(callbacks, (callback, inputs) => {
@@ -80625,7 +80784,7 @@ var init_strict_resolver = __esm({
80625
80784
  }
80626
80785
  return canonicalPath(target) ?? "the slot";
80627
80786
  }
80628
- /** P112 §3.1. A value never converts to a reference, since it has no row. */
80787
+ /** A transient value has no stored slot to pass by reference. */
80629
80788
  requireReferenceArgument(source, target, parameter4, pos) {
80630
80789
  if (target.kind !== "reference") return;
80631
80790
  if (source.kind === "reference") return;
@@ -80634,7 +80793,7 @@ var init_strict_resolver = __esm({
80634
80793
  const value = this.describe(source);
80635
80794
  const article = /^[aeiou]/i.test(value) ? "an" : "a";
80636
80795
  throw new CompileError(
80637
- `Argument \`${parameter4}\` needs a ${this.describe(target)}, not ${article} ${value}. Wrap a member path in Reference() to pass a stored ${this.describe(read)}.`,
80796
+ `Argument \`${parameter4}\` needs a ${this.describe(target)}, not ${article} ${value}. Pass a stored ${this.describe(read)} member instead.`,
80638
80797
  pos
80639
80798
  );
80640
80799
  }
@@ -81988,7 +82147,8 @@ function neoSourceTypeText(type2) {
81988
82147
  }
81989
82148
  function referenceReadType(type2) {
81990
82149
  const target = type2.name === "Reference" ? type2.typeArguments[0] : void 0;
81991
- if (target !== void 0) return { ...target, nullable: type2.nullable };
82150
+ if (target !== void 0)
82151
+ return { ...target, nullable: type2.nullable || target.nullable };
81992
82152
  const element = type2.name === "Set" ? type2.typeArguments[0] : void 0;
81993
82153
  if (element?.name !== "Reference" || element.typeArguments.length === 0) {
81994
82154
  return type2;
@@ -83130,7 +83290,7 @@ var init_project_source_parser = __esm({
83130
83290
  ...value ? { value } : {},
83131
83291
  range: rangeFrom(optionStart, end)
83132
83292
  });
83133
- if (!this.eat(",") && !this.at("}")) {
83293
+ if (!this.eat(",") && !this.at("}") && !this.done()) {
83134
83294
  throw this.failure(
83135
83295
  "enum-option-separator",
83136
83296
  "Enum options must be separated by a comma.",
@@ -83138,7 +83298,7 @@ var init_project_source_parser = __esm({
83138
83298
  );
83139
83299
  }
83140
83300
  }
83141
- const close = this.expect("}");
83301
+ const close = this.expectClosingBrace();
83142
83302
  return {
83143
83303
  kind: "enum",
83144
83304
  annotations,
@@ -83344,7 +83504,12 @@ var init_project_source_parser = __esm({
83344
83504
  }
83345
83505
  if (this.cursor === start) this.cursor++;
83346
83506
  }
83347
- return { members: members2, constructors, initBlocks, close: this.expect("}") };
83507
+ return {
83508
+ members: members2,
83509
+ constructors,
83510
+ initBlocks,
83511
+ close: this.expectClosingBrace()
83512
+ };
83348
83513
  }
83349
83514
  parseMember(ownerName, ownerKind) {
83350
83515
  const start = this.peek();
@@ -83817,16 +83982,19 @@ var init_project_source_parser = __esm({
83817
83982
  if (token.text === "}") depth--;
83818
83983
  }
83819
83984
  if (depth !== 0) {
83820
- throw this.failure(
83821
- "unclosed-source-body",
83822
- "Unclosed source body; add `}`.",
83823
- open2
83985
+ this.report(
83986
+ this.failure(
83987
+ "unclosed-source-body",
83988
+ "Unclosed source body; add `}`.",
83989
+ open2
83990
+ )
83824
83991
  );
83825
83992
  }
83826
- const close = this.previous();
83993
+ const close = depth === 0 ? this.previous() : this.peek();
83827
83994
  return {
83828
83995
  text: this.source.text.slice(open2.start, close.end),
83829
- range: rangeFrom(open2, close)
83996
+ range: rangeFrom(open2, close),
83997
+ ...depth === 0 ? {} : { unclosed: true }
83830
83998
  };
83831
83999
  }
83832
84000
  /**
@@ -83838,21 +84006,24 @@ var init_project_source_parser = __esm({
83838
84006
  const arrow = this.expect("=>");
83839
84007
  const expression = this.captureUntilTopLevel(/* @__PURE__ */ new Set([";"]), true);
83840
84008
  if (expression.text.trim().length === 0) {
83841
- throw this.failure(
84009
+ const error = this.failure(
83842
84010
  "empty-expression-body",
83843
84011
  `An expression-bodied ${label} needs an expression after \`=>\`.`,
83844
84012
  this.peek()
83845
84013
  );
84014
+ if (!this.done()) throw error;
84015
+ this.report(error);
83846
84016
  }
83847
- const close = this.previous();
84017
+ const close = this.done() ? this.peek() : this.previous();
83848
84018
  if (!this.at(";")) {
83849
- throw this.failure(
84019
+ const error = this.failure(
83850
84020
  "unterminated-expression-body",
83851
84021
  `An expression-bodied ${label} must end with \`;\`.`,
83852
84022
  this.peek()
83853
84023
  );
83854
- }
83855
- this.next();
84024
+ if (!this.done()) throw error;
84025
+ this.report(error);
84026
+ } else this.next();
83856
84027
  return {
83857
84028
  text: this.source.text.slice(arrow.start, close.end),
83858
84029
  range: rangeFrom(arrow, close),
@@ -83888,7 +84059,7 @@ var init_project_source_parser = __esm({
83888
84059
  if (this.cursor === startCursor) {
83889
84060
  return { text: "", range: start.range };
83890
84061
  }
83891
- const end = this.previous();
84062
+ const end = this.done() ? this.peek() : this.previous();
83892
84063
  return {
83893
84064
  text: this.source.text.slice(start.start, end.end),
83894
84065
  range: rangeFrom(start, end)
@@ -83959,6 +84130,19 @@ var init_project_source_parser = __esm({
83959
84130
  message
83960
84131
  });
83961
84132
  }
84133
+ /** Keep declarations and their editor scope when only the closing brace is missing. */
84134
+ expectClosingBrace() {
84135
+ if (!this.done()) return this.expect("}");
84136
+ const end = this.peek();
84137
+ this.report(
84138
+ this.failure(
84139
+ "unexpected-source-token",
84140
+ `Expected \`}\`, but found ${describe2(end)}.`,
84141
+ end
84142
+ )
84143
+ );
84144
+ return end;
84145
+ }
83962
84146
  expect(text) {
83963
84147
  if (!this.at(text)) {
83964
84148
  throw this.failure(
@@ -95467,49 +95651,65 @@ function annotationContextForDeclaration(declaration) {
95467
95651
  return { kind: "schema" };
95468
95652
  }
95469
95653
  function contextualAnnotationFields(document, position) {
95470
- for (const declaration of document.declarations) {
95471
- const declarationAnnotation = declaration.annotations.find(
95472
- (annotation2) => inAnnotationArguments(annotation2, position)
95473
- );
95474
- if (declarationAnnotation) {
95475
- return fieldsForAnnotation(
95476
- declarationAnnotation.name,
95477
- annotationContextForDeclaration(declaration)
95478
- );
95654
+ return contextualAnnotationSite(document, position)?.fields ?? null;
95655
+ }
95656
+ function contextualAnnotationSite(document, position) {
95657
+ let sites = ANNOTATION_SITES.get(document);
95658
+ if (!sites) {
95659
+ sites = collectAnnotationSites(document);
95660
+ ANNOTATION_SITES.set(document, sites);
95661
+ }
95662
+ let low = 0;
95663
+ let high = sites.length;
95664
+ while (low < high) {
95665
+ const middle = low + high >>> 1;
95666
+ if (compare(sites[middle].annotation.range.end, position) < 0)
95667
+ low = middle + 1;
95668
+ else high = middle;
95669
+ }
95670
+ const site = sites[low];
95671
+ return site && inAnnotationArguments(site.annotation, position) ? site : null;
95672
+ }
95673
+ function collectAnnotationSites(document) {
95674
+ const sites = [];
95675
+ const add = (annotations, context, type2) => {
95676
+ for (const annotation2 of annotations) {
95677
+ const fields = fieldsForAnnotation(annotation2.name, context);
95678
+ if (fields) sites.push({ annotation: annotation2, fields, ...type2 ? { type: type2 } : {} });
95479
95679
  }
95680
+ };
95681
+ const addType = (type2) => {
95682
+ if (type2.annotations.length > 0)
95683
+ add(type2.annotations, { kind: "type", type: semanticType(type2) }, type2);
95684
+ for (const argument2 of type2.typeArguments) addType(argument2);
95685
+ };
95686
+ for (const declaration of document.declarations) {
95687
+ add(declaration.annotations, annotationContextForDeclaration(declaration));
95480
95688
  if (declaration.kind === "global") continue;
95481
95689
  if (declaration.kind === "enum") {
95482
- for (const option of declaration.options) {
95483
- const annotation2 = option.annotations.find(
95484
- (candidate) => inAnnotationArguments(candidate, position)
95485
- );
95486
- if (annotation2)
95487
- return fieldsForAnnotation(annotation2.name, { kind: "schema" });
95488
- }
95690
+ for (const option of declaration.options)
95691
+ add(option.annotations, { kind: "schema" });
95489
95692
  continue;
95490
95693
  }
95491
95694
  for (const member of declaration.members) {
95492
- const annotation2 = member.annotations.find(
95493
- (candidate) => inAnnotationArguments(candidate, position)
95494
- );
95495
- if (annotation2) {
95496
- return fieldsForAnnotation(annotation2.name, {
95497
- kind: "member",
95498
- ownerName: declaration.name,
95499
- type: semanticType(member.type),
95500
- memberKind: member.kind
95501
- });
95502
- }
95503
- const typeAnnotation = findTypeAnnotation(member.type, position);
95504
- if (typeAnnotation) {
95505
- return fieldsForAnnotation(typeAnnotation.annotation.name, {
95506
- kind: "type",
95507
- type: semanticType(typeAnnotation.type)
95508
- });
95509
- }
95695
+ if (member.annotations.length > 0)
95696
+ add(
95697
+ member.annotations,
95698
+ {
95699
+ kind: "member",
95700
+ ownerName: declaration.name,
95701
+ type: semanticType(member.type),
95702
+ memberKind: member.kind,
95703
+ reference: member.type.name === "Reference"
95704
+ },
95705
+ member.type
95706
+ );
95707
+ addType(member.type);
95510
95708
  }
95511
95709
  }
95512
- return null;
95710
+ return sites.sort(
95711
+ (left, right) => compare(left.annotation.range.start, right.annotation.range.start)
95712
+ );
95513
95713
  }
95514
95714
  function generatedContractEnumCases(type2) {
95515
95715
  const element = /^(?:IReadOnly)?List<(.+)>$/.exec(type2)?.[1];
@@ -95525,7 +95725,6 @@ function createEnvironment(documents, project) {
95525
95725
  const enums = /* @__PURE__ */ new Map();
95526
95726
  const types = /* @__PURE__ */ new Map();
95527
95727
  const globals = /* @__PURE__ */ new Map();
95528
- const mutableFunctions = /* @__PURE__ */ new Map();
95529
95728
  const referenceTargets = /* @__PURE__ */ new Map();
95530
95729
  for (const [name, options] of Object.entries(
95531
95730
  NEO_PROJECT_SOURCE_RECORD_CONTRACT.enums
@@ -95570,17 +95769,6 @@ function createEnvironment(documents, project) {
95570
95769
  }
95571
95770
  }
95572
95771
  }
95573
- for (const member of declaration.members) {
95574
- if (member.kind !== "function") continue;
95575
- const signatures = mutableFunctions.get(member.name) ?? [];
95576
- signatures.push({
95577
- parameters: member.parameters.map(
95578
- (parameter4) => semanticType(parameter4.type)
95579
- ),
95580
- returnType: semanticType(member.type)
95581
- });
95582
- mutableFunctions.set(member.name, signatures);
95583
- }
95584
95772
  }
95585
95773
  }
95586
95774
  return {
@@ -95593,7 +95781,8 @@ function createEnvironment(documents, project) {
95593
95781
  enums,
95594
95782
  types,
95595
95783
  globals,
95596
- functions: mutableFunctions,
95784
+ callBindings: /* @__PURE__ */ new WeakMap(),
95785
+ callScopes: /* @__PURE__ */ new WeakMap(),
95597
95786
  referenceTargets,
95598
95787
  variantScopes: buildNeoVariantScopeIndex(documents),
95599
95788
  construction: buildNeoConstructionIndex(documents)
@@ -95771,6 +95960,8 @@ function validateOwnedStaticDefault(uri, member, ownerName, scope, environment,
95771
95960
  const initializer = member.initializer;
95772
95961
  if (initializer === void 0) return;
95773
95962
  if (member.type.name === "Reference") return;
95963
+ if (member.type.name === "Set" && member.type.typeArguments[0]?.name === "Reference")
95964
+ return;
95774
95965
  let expression;
95775
95966
  try {
95776
95967
  expression = parseExpression(initializer.text);
@@ -96004,6 +96195,7 @@ function validateFlowContent(uri, content, parentScope, environment, diagnostics
96004
96195
  for (const binding of content.bindings) {
96005
96196
  const type2 = parseTypeText(binding.typeText);
96006
96197
  scope.set(binding.name, type2);
96198
+ environment.callScopes.delete(scope);
96007
96199
  validateAnnotations(
96008
96200
  uri,
96009
96201
  binding.annotations,
@@ -96758,7 +96950,10 @@ function validateStatements(statements, returnType, scope, environment, uri, ran
96758
96950
  diagnostics
96759
96951
  );
96760
96952
  const inferred = declared ?? inferExpressionType(statement.init, scope, environment);
96761
- if (inferred) scope.set(statement.name, inferred);
96953
+ if (inferred) {
96954
+ scope.set(statement.name, inferred);
96955
+ environment.callScopes.delete(scope);
96956
+ }
96762
96957
  } else if (statement.kind === "assign") {
96763
96958
  const target = inferExpressionType(statement.target, scope, environment);
96764
96959
  if (statement.value)
@@ -96889,6 +97084,21 @@ function knownGeneratorExpression(expression, scope, environment) {
96889
97084
  return candidates !== void 0 && candidates.length > 0 && candidates.every((member) => member.generator === true);
96890
97085
  }
96891
97086
  function validateExpression(expression, expected, scope, environment, uri, range2, diagnostics, anchor, storedValue = true) {
97087
+ if (anchor !== void 0 && expression.kind === "call") {
97088
+ const error = sourceCallBinding(expression, scope, environment)?.error;
97089
+ if (error?.message.includes(
97090
+ "Named arguments are not supported for this call."
97091
+ )) {
97092
+ pushDiagnostic(
97093
+ diagnostics,
97094
+ uri,
97095
+ anchorSpan(anchor, error, 1),
97096
+ "invalid-function-call",
97097
+ error.message.replace(/^\d+:\d+: /, "")
97098
+ );
97099
+ return;
97100
+ }
97101
+ }
96892
97102
  if (expression.kind === "new" && expression.typeArguments?.length) {
96893
97103
  const { context } = initializerResolver(
96894
97104
  environment,
@@ -97541,7 +97751,18 @@ function validateExpression(expression, expected, scope, environment, uri, range
97541
97751
  );
97542
97752
  return;
97543
97753
  }
97544
- const parameters = callParameters(expression.callee, scope, environment);
97754
+ const binding = sourceCallBinding(expression, scope, environment);
97755
+ if (binding?.error?.message.replace(/^\d+:\d+: /, "").startsWith("No overload of ")) {
97756
+ pushDiagnostic(
97757
+ diagnostics,
97758
+ uri,
97759
+ anchor ? anchorSpan(anchor, binding.error, 1) : range2,
97760
+ "invalid-function-call",
97761
+ binding.error.message.replace(/^\d+:\d+: /, "")
97762
+ );
97763
+ return;
97764
+ }
97765
+ const parameters = callParameters(expression, scope, environment);
97545
97766
  expression.args.forEach((argument2, index) => {
97546
97767
  const name = expression.argumentNames?.[index];
97547
97768
  const parameter4 = name === void 0 || name === null ? parameters?.[index] : parameters?.find((candidate) => candidate.name === name);
@@ -98000,6 +98221,16 @@ function semanticAst(type2, pos) {
98000
98221
  return { ...common, kind: "primitive", name: type2.name };
98001
98222
  }
98002
98223
  const args = type2.arguments ?? [];
98224
+ if (type2.name === "")
98225
+ return {
98226
+ ...common,
98227
+ kind: "tuple",
98228
+ elements: args.map((argument2, index) => ({
98229
+ pos,
98230
+ type: semanticAst(argument2, pos),
98231
+ ...type2.tupleNames?.[index] ? { name: type2.tupleNames[index] } : {}
98232
+ }))
98233
+ };
98003
98234
  if ((type2.name === "List" || type2.name === "Set") && args[0]) {
98004
98235
  return {
98005
98236
  ...common,
@@ -98385,34 +98616,192 @@ function inferExpressionType(expression, scope, environment) {
98385
98616
  const argument2 = expression.args[0];
98386
98617
  return argument2 === void 0 ? void 0 : inferExpressionType(argument2, scope, environment);
98387
98618
  }
98388
- return environment.functions.get(expression.callee.name)?.[0]?.returnType;
98619
+ }
98620
+ if (expression.kind === "call") {
98621
+ const binding = sourceCallBinding(expression, scope, environment);
98622
+ if (binding?.returnType) return binding.returnType;
98623
+ const member = sourceCallMember(expression.callee, scope, environment);
98624
+ if (member?.member.kind === "function") {
98625
+ const bindings = new Map(member.bindings);
98626
+ for (const [
98627
+ index,
98628
+ parameter4
98629
+ ] of member.member.genericParameters.entries()) {
98630
+ const argument2 = expression.typeArguments?.[index];
98631
+ if (!argument2) return void 0;
98632
+ bindings.set(parameter4.name, semanticAstType(argument2));
98633
+ }
98634
+ return substituteSemanticType(semanticType(member.member.type), bindings);
98635
+ }
98636
+ if (member === null) return void 0;
98637
+ const callee = inferExpressionType(expression.callee, scope, environment);
98638
+ return callee?.name === "NeoDelegate" ? callee.arguments?.[0] : void 0;
98389
98639
  }
98390
98640
  return void 0;
98391
98641
  }
98392
- function callParameters(callee, scope, environment) {
98393
- if (callee.kind === "ident") {
98394
- return environment.functions.get(callee.name)?.[0]?.parameters.map((type2) => ({ name: null, type: type2 }));
98642
+ function sourceCallBinding(expression, scope, environment) {
98643
+ const cached = environment.callBindings.get(expression);
98644
+ if (cached?.scope === scope) return cached.binding;
98645
+ let entry = environment.callScopes.get(scope);
98646
+ if (!entry) {
98647
+ const owner = environment.types.get(scope.get("this")?.name ?? "");
98648
+ const { context } = initializerResolver(
98649
+ environment,
98650
+ owner?.name ?? "",
98651
+ false
98652
+ );
98653
+ const names2 = new Set(scope.keys());
98654
+ names2.delete("this");
98655
+ names2.delete("root");
98656
+ for (const member of owner?.members ?? []) {
98657
+ if (member.kind === "function") names2.delete(member.name);
98658
+ }
98659
+ entry = { context, names: names2, types: /* @__PURE__ */ new Map() };
98660
+ environment.callScopes.set(scope, entry);
98661
+ }
98662
+ const parameters = [];
98663
+ const seen = /* @__PURE__ */ new Set();
98664
+ for (const { name } of collectIdentifierReads(expression, entry.names)) {
98665
+ if (seen.has(name)) continue;
98666
+ seen.add(name);
98667
+ if (!entry.types.has(name))
98668
+ entry.types.set(
98669
+ name,
98670
+ semanticTypeRef(scope.get(name), scope, environment)
98671
+ );
98672
+ const type2 = entry.types.get(name);
98673
+ if (type2) parameters.push({ name, type: type2 });
98674
+ }
98675
+ let symbol;
98676
+ const resolver = new StrictNeoScriptResolver(
98677
+ { ...entry.context, kind: "function", parameters },
98678
+ environment.projectIndex,
98679
+ void 0,
98680
+ {
98681
+ onCallResolved(pos, resolved) {
98682
+ if (pos === expression.pos) symbol = resolved;
98683
+ }
98684
+ }
98685
+ );
98686
+ let binding;
98687
+ try {
98688
+ const type2 = resolver.resolveExpressionType(expression);
98689
+ binding = {
98690
+ returnType: semanticResolvedType(type2, environment.projectIndex),
98691
+ ...symbol?.parameters ? {
98692
+ parameters: symbol.parameters.map((parameter4) => ({
98693
+ name: parameter4.name,
98694
+ type: semanticResolvedType(
98695
+ parameter4.type,
98696
+ environment.projectIndex
98697
+ )
98698
+ }))
98699
+ } : {}
98700
+ };
98701
+ } catch (error) {
98702
+ if (!(error instanceof CompileError)) throw error;
98703
+ binding = { error };
98395
98704
  }
98396
- if (callee.kind !== "member") return void 0;
98397
- const receiverType = inferExpressionType(callee.receiver, scope, environment);
98398
- const staticDeclaration = receiverType === void 0 && callee.receiver.kind === "ident" ? environment.types.get(callee.receiver.name) : void 0;
98399
- let owner = staticDeclaration ?? (receiverType && environment.types.get(receiverType.name));
98705
+ environment.callBindings.set(expression, { scope, binding });
98706
+ return binding;
98707
+ }
98708
+ function semanticResolvedType(type2, project, read = true) {
98709
+ const child2 = (type3) => semanticResolvedType(type3, project, false);
98710
+ if (read && type2.kind === "reference")
98711
+ return semanticResolvedType(
98712
+ {
98713
+ ...type2.target,
98714
+ nullable: type2.nullable === true || type2.target.nullable === true
98715
+ },
98716
+ project
98717
+ );
98718
+ if (read && type2.kind === "set" && type2.elementType.kind === "reference")
98719
+ return {
98720
+ name: "Set",
98721
+ nullable: type2.nullable === true,
98722
+ arguments: [semanticResolvedType(type2.elementType, project)]
98723
+ };
98724
+ const nullable2 = type2.nullable === true;
98725
+ switch (type2.kind) {
98726
+ case "primitive":
98727
+ return { name: type2.name, nullable: nullable2 };
98728
+ case "typeParameter":
98729
+ return { name: type2.name, nullable: nullable2 };
98730
+ case "named":
98731
+ return {
98732
+ name: project.typeById.get(type2.typeId)?.name ?? type2.typeId,
98733
+ nullable: nullable2,
98734
+ arguments: (type2.typeArguments ?? []).map(child2)
98735
+ };
98736
+ case "tuple":
98737
+ return {
98738
+ name: "",
98739
+ nullable: nullable2,
98740
+ arguments: type2.elements.map((element) => child2(element.type)),
98741
+ tupleNames: type2.elements.map((element) => element.name)
98742
+ };
98743
+ case "list":
98744
+ return { name: "List", nullable: nullable2, arguments: [child2(type2.elementType)] };
98745
+ case "set":
98746
+ return { name: "Set", nullable: nullable2, arguments: [child2(type2.elementType)] };
98747
+ case "dictionary":
98748
+ return {
98749
+ name: "Dictionary",
98750
+ nullable: nullable2,
98751
+ arguments: [child2(type2.keyType), child2(type2.valueType)]
98752
+ };
98753
+ case "reference":
98754
+ return { name: "Reference", nullable: nullable2, arguments: [child2(type2.target)] };
98755
+ case "delegate":
98756
+ return {
98757
+ name: "NeoDelegate",
98758
+ nullable: nullable2,
98759
+ arguments: [child2(type2.returnType), ...type2.parameterTypes.map(child2)]
98760
+ };
98761
+ case "action":
98762
+ return {
98763
+ name: "NeoAction",
98764
+ nullable: nullable2,
98765
+ arguments: type2.parameterTypes.map(child2)
98766
+ };
98767
+ }
98768
+ }
98769
+ function sourceCallMember(callee, scope, environment) {
98770
+ if (callee.kind !== "ident" && callee.kind !== "member") return void 0;
98771
+ const receiver = callee.kind === "ident" ? scope.get("this") : inferExpressionType(callee.receiver, scope, environment);
98772
+ const staticDeclaration = !receiver && callee.kind === "member" && callee.receiver.kind === "ident" ? environment.types.get(callee.receiver.name) : void 0;
98773
+ let owner = staticDeclaration ?? (receiver && environment.types.get(receiver.name));
98400
98774
  const visited = /* @__PURE__ */ new Set();
98401
98775
  let functionCount = 0;
98402
- while (owner !== void 0 && !visited.has(owner.name)) {
98776
+ while (owner && !visited.has(owner.name)) {
98403
98777
  visited.add(owner.name);
98404
- for (const member of owner.members) {
98405
- if (member.name === callee.name && member.kind === "function")
98778
+ for (const member2 of owner.members) {
98779
+ if (member2.name === callee.name && member2.kind === "function")
98406
98780
  functionCount++;
98407
98781
  }
98408
- if (functionCount > 1) return void 0;
98782
+ if (functionCount > 1) return null;
98409
98783
  const base = owner.baseTypes.find(
98410
98784
  (type2) => environment.types.has(type2.name)
98411
98785
  );
98412
98786
  owner = base && environment.types.get(base.name);
98413
98787
  }
98414
- const resolved = staticDeclaration === void 0 ? receiverType === void 0 ? void 0 : sourceClassMemberForType(receiverType, callee.name, environment) : sourceClassMemberByName(staticDeclaration, callee.name, environment);
98415
- if (resolved?.member.kind !== "function") return void 0;
98788
+ const member = receiver ? sourceClassMemberForType(receiver, callee.name, environment) : staticDeclaration && sourceClassMemberByName(staticDeclaration, callee.name, environment);
98789
+ return !staticDeclaration || member?.member.modifiers.includes("static") ? member : void 0;
98790
+ }
98791
+ function callParameters(expression, scope, environment) {
98792
+ const binding = sourceCallBinding(expression, scope, environment);
98793
+ if (binding?.parameters) return binding.parameters;
98794
+ const callee = expression.callee;
98795
+ if (callee.kind !== "member" && callee.kind !== "ident")
98796
+ return delegateCallParameters(
98797
+ inferExpressionType(callee, scope, environment)
98798
+ );
98799
+ const resolved = sourceCallMember(callee, scope, environment);
98800
+ if (resolved === null) return void 0;
98801
+ if (resolved?.member.kind !== "function")
98802
+ return delegateCallParameters(
98803
+ inferExpressionType(callee, scope, environment)
98804
+ );
98416
98805
  return resolved.member.parameters.map((parameter4) => ({
98417
98806
  name: parameter4.name,
98418
98807
  type: substituteSemanticType(
@@ -98421,6 +98810,9 @@ function callParameters(callee, scope, environment) {
98421
98810
  )
98422
98811
  }));
98423
98812
  }
98813
+ function delegateCallParameters(type2) {
98814
+ return type2?.name === "NeoDelegate" ? type2.arguments?.slice(1).map((type3) => ({ name: null, type: type3 })) : void 0;
98815
+ }
98424
98816
  function semanticMemberType(member, environment, bindings = /* @__PURE__ */ new Map()) {
98425
98817
  const type2 = substituteSemanticType(semanticType(member.type), bindings);
98426
98818
  if (type2.name !== "List") return type2;
@@ -98658,21 +99050,23 @@ function matchingDeclaredConstructor(declaration, argumentNames) {
98658
99050
  return neoScriptNamedCallSignature(declaration.constructors, argumentNames) ?? null;
98659
99051
  }
98660
99052
  function semanticType(type2) {
99053
+ const read = referenceReadType(type2);
99054
+ return read === type2 ? declaredSemanticType(type2) : semanticType(read);
99055
+ }
99056
+ function declaredSemanticType(type2) {
98661
99057
  if (type2.tupleElements)
98662
99058
  return {
98663
99059
  name: "",
98664
99060
  nullable: type2.nullable,
98665
99061
  arguments: type2.tupleElements.map(
98666
- (element) => semanticType(element.type)
99062
+ (element) => declaredSemanticType(element.type)
98667
99063
  ),
98668
99064
  tupleNames: type2.tupleElements.map((element) => element.name)
98669
99065
  };
98670
- const read = referenceReadType(type2);
98671
- if (read !== type2) return semanticType(read);
98672
99066
  return {
98673
99067
  name: type2.name,
98674
99068
  nullable: type2.nullable,
98675
- arguments: type2.typeArguments.map(semanticType)
99069
+ arguments: type2.typeArguments.map(declaredSemanticType)
98676
99070
  };
98677
99071
  }
98678
99072
  function semanticAstType(type2) {
@@ -98697,6 +99091,9 @@ function semanticAstType(type2) {
98697
99091
  arguments: type2.kind === "dict" ? [semanticAstType(type2.key), semanticAstType(type2.value)] : [semanticAstType(type2.element)]
98698
99092
  };
98699
99093
  }
99094
+ function formatAnnotationValueType(type2) {
99095
+ return describeType(contractType(type2));
99096
+ }
98700
99097
  function contractType(type2) {
98701
99098
  const nullable2 = type2.endsWith("?");
98702
99099
  const withoutNullable = type2.replace(/\?$/, "");
@@ -98799,7 +99196,7 @@ function validateListAnnotations(uri, member, ownerName, environment, diagnostic
98799
99196
  const domainError = indexKeyDomainError(
98800
99197
  field.member,
98801
99198
  substituteSemanticType(semanticType(field.member.type), field.bindings),
98802
- environment
99199
+ environment.enums
98803
99200
  );
98804
99201
  if (domainError !== null) {
98805
99202
  pushDiagnostic(
@@ -98838,16 +99235,16 @@ function sourceClassMemberForType(type2, name, environment) {
98838
99235
  }
98839
99236
  return sourceClassMemberByName(declaration, name, environment, bindings);
98840
99237
  }
98841
- function indexKeyDomainError(field, type2, environment) {
99238
+ function indexKeyDomainError(field, type2, enums) {
98842
99239
  if (field.kind !== "field") {
98843
99240
  return `'${field.name}' is a ${field.kind}, and index keys require a stored field`;
98844
99241
  }
98845
99242
  if (type2.name === "string") {
98846
99243
  return annotationEnumOption(field.annotations, "settings", "format") === "Plain" ? null : `'${field.name}' is localized, and String index keys must be plain`;
98847
99244
  }
98848
- if (environment.enums.has(type2.name)) return null;
99245
+ if (enums.has(type2.name)) return null;
98849
99246
  const entry = type2.arguments?.[0];
98850
- if (type2.name === "Set" && entry !== void 0 && environment.enums.has(entry.name)) {
99247
+ if (type2.name === "Set" && entry !== void 0 && enums.has(entry.name)) {
98851
99248
  return `'${field.name}' is a multi-select Enum, and index keys require a single-select Enum`;
98852
99249
  }
98853
99250
  return `'${field.name}' is a ${type2.name} field, and index keys require a plain String or a single-select Enum`;
@@ -98860,17 +99257,6 @@ function annotationEnumOption(annotations, name, field) {
98860
99257
  function isListContext(context) {
98861
99258
  return context.kind === "member" && (context.type.name === "List" || context.type.name === "Set");
98862
99259
  }
98863
- function findTypeAnnotation(type2, position) {
98864
- const own = type2.annotations.find(
98865
- (annotation2) => inAnnotationArguments(annotation2, position)
98866
- );
98867
- if (own) return { annotation: own, type: type2 };
98868
- for (const argument2 of type2.typeArguments) {
98869
- const nested = findTypeAnnotation(argument2, position);
98870
- if (nested) return nested;
98871
- }
98872
- return null;
98873
- }
98874
99260
  function describeAnnotationContext(context) {
98875
99261
  if (context.kind === "member" || context.kind === "type" || context.kind === "flowBinding" || context.kind === "flowMember")
98876
99262
  return `${context.type.name} ${context.kind}`;
@@ -98885,8 +99271,6 @@ function contains(range2, position) {
98885
99271
  }
98886
99272
  function inAnnotationArguments(annotation2, position) {
98887
99273
  if (!contains(annotation2.range, position)) return false;
98888
- const first = annotation2.arguments[0];
98889
- if (first) return compare(first.range.start, position) <= 0;
98890
99274
  return compare(annotation2.nameRange.end, position) < 0;
98891
99275
  }
98892
99276
  function compare(left, right) {
@@ -99006,7 +99390,7 @@ function classDerivesFromName(name, ancestorName, environment, seen = /* @__PURE
99006
99390
  return classDerivesFromName(base.name, ancestorName, environment, seen);
99007
99391
  });
99008
99392
  }
99009
- var NEO_VARIANT_FOLDER_SETTING, NEO_ANIMATION_CHILD_OVERRIDE_TYPE_NAME, primitiveType, LIST_COLUMN_INHERITANCE_KEY, documentContracts, previousSemanticContract, validDocuments, DECLARATION_BODY_GLOBAL_TYPES, SEMANTIC_PRIMITIVE_TYPE_NAMES, AST_PRIMITIVE_TYPE_NAMES;
99393
+ var NEO_VARIANT_FOLDER_SETTING, NEO_ANIMATION_CHILD_OVERRIDE_TYPE_NAME, primitiveType, LIST_COLUMN_INHERITANCE_KEY, documentContracts, previousSemanticContract, validDocuments, ANNOTATION_SITES, DECLARATION_BODY_GLOBAL_TYPES, SEMANTIC_PRIMITIVE_TYPE_NAMES, AST_PRIMITIVE_TYPE_NAMES;
99010
99394
  var init_project_source_semantics = __esm({
99011
99395
  "../packages/neoscript-language/src/project-source-semantics.ts"() {
99012
99396
  "use strict";
@@ -99036,6 +99420,7 @@ var init_project_source_semantics = __esm({
99036
99420
  LIST_COLUMN_INHERITANCE_KEY = "__other__";
99037
99421
  documentContracts = /* @__PURE__ */ new WeakMap();
99038
99422
  validDocuments = /* @__PURE__ */ new WeakMap();
99423
+ ANNOTATION_SITES = /* @__PURE__ */ new WeakMap();
99039
99424
  DECLARATION_BODY_GLOBAL_TYPES = /* @__PURE__ */ new Set([
99040
99425
  NEOSCRIPT_IMAGE_REGISTRY_TYPE,
99041
99426
  NEOSCRIPT_AUDIO_CLIP_REGISTRY_TYPE,
@@ -99129,6 +99514,16 @@ function projectSourceAccessors(input, containingRange) {
99129
99514
  openIndex = cursor;
99130
99515
  break;
99131
99516
  }
99517
+ if (!body) {
99518
+ const start = bodyStart + open2.end;
99519
+ const end = full.offsetAt(range2.end);
99520
+ body = {
99521
+ range: full.range(start, end),
99522
+ source: source.slice(start, end),
99523
+ form: "block"
99524
+ };
99525
+ openIndex = tokens.length - 1;
99526
+ }
99132
99527
  }
99133
99528
  accessors.push({
99134
99529
  keyword: token.text,
@@ -99155,6 +99550,7 @@ function expressionAccessor(source, full, tokens, bodyStart, firstIndex2) {
99155
99550
  const start = bodyStart + first.start;
99156
99551
  let end = bodyStart + (tokens.at(-1)?.start ?? 0);
99157
99552
  let depth = 0;
99553
+ let terminated = false;
99158
99554
  for (let cursor = firstIndex2; cursor < tokens.length; cursor++) {
99159
99555
  const token = tokens[cursor];
99160
99556
  if (token.kind !== "punctuation") continue;
@@ -99169,6 +99565,7 @@ function expressionAccessor(source, full, tokens, bodyStart, firstIndex2) {
99169
99565
  if (token.text === "}") {
99170
99566
  if (depth === 0) {
99171
99567
  end = bodyStart + token.start;
99568
+ terminated = true;
99172
99569
  break;
99173
99570
  }
99174
99571
  depth--;
@@ -99176,14 +99573,17 @@ function expressionAccessor(source, full, tokens, bodyStart, firstIndex2) {
99176
99573
  }
99177
99574
  if (depth === 0 && token.text === ";") {
99178
99575
  end = bodyStart + token.start;
99576
+ terminated = true;
99179
99577
  break;
99180
99578
  }
99181
99579
  }
99182
- const trimmed = source.slice(start, end).trimEnd();
99183
- if (trimmed.length === 0) return null;
99580
+ const authored = source.slice(start, end);
99581
+ const trimmed = authored.trimEnd();
99582
+ if (trimmed.length === 0 && terminated) return null;
99583
+ const body = terminated ? trimmed : authored;
99184
99584
  return {
99185
- range: full.range(start, start + trimmed.length),
99186
- source: trimmed,
99585
+ range: full.range(start, start + body.length),
99586
+ source: body,
99187
99587
  form: "expression"
99188
99588
  };
99189
99589
  }
@@ -99410,7 +99810,7 @@ function compileProjectSourceBodies(documents, options = {}) {
99410
99810
  `dialogue-group:${uri}:${declaration.name}:${member.name}`
99411
99811
  ),
99412
99812
  unit: "function",
99413
- range: expression?.range ?? innerBodyRange(document.syntax.source, member.body.range),
99813
+ range: expression?.range ?? innerBodyRange(document.syntax.source, member.body),
99414
99814
  ...expression ? { bodyMode: "expression" } : {},
99415
99815
  context: {
99416
99816
  project,
@@ -99474,10 +99874,7 @@ function compileProjectSourceBodies(documents, options = {}) {
99474
99874
  constructor2
99475
99875
  ),
99476
99876
  unit: "constructor",
99477
- range: innerBodyRange(
99478
- document.syntax.source,
99479
- constructor2.body.range
99480
- ),
99877
+ range: innerBodyRange(document.syntax.source, constructor2.body),
99481
99878
  context: {
99482
99879
  project,
99483
99880
  declaringType,
@@ -99513,7 +99910,7 @@ function compileProjectSourceBodies(documents, options = {}) {
99513
99910
  declarationRange: initBlock.keywordRange,
99514
99911
  memberId: initId,
99515
99912
  unit: "init",
99516
- range: innerBodyRange(document.syntax.source, initBlock.body.range),
99913
+ range: innerBodyRange(document.syntax.source, initBlock.body),
99517
99914
  context: {
99518
99915
  project,
99519
99916
  declaringType,
@@ -99572,7 +99969,7 @@ function compileProjectSourceBodies(documents, options = {}) {
99572
99969
  memberId: info.symbol.id,
99573
99970
  unit: "function",
99574
99971
  signature: sourceOverloadParameterIdentity(member),
99575
- range: expressionBody?.range ?? innerBodyRange(document.syntax.source, member.body.range),
99972
+ range: expressionBody?.range ?? innerBodyRange(document.syntax.source, member.body),
99576
99973
  ...expressionBody ? { bodyMode: "expression" } : {},
99577
99974
  context: {
99578
99975
  ...baseContext2,
@@ -100791,10 +101188,13 @@ function memberWritability(annotations) {
100791
101188
  if (/\.Session\b/.test(allowed ?? "")) return "session";
100792
101189
  return "runtime";
100793
101190
  }
100794
- function innerBodyRange(text, range2) {
100795
- const start = text.offsetAt(range2.start);
100796
- const end = text.offsetAt(range2.end);
100797
- return text.range(Math.min(end, start + 1), Math.max(start + 1, end - 1));
101191
+ function innerBodyRange(text, body) {
101192
+ const start = text.offsetAt(body.range.start);
101193
+ const end = text.offsetAt(body.range.end);
101194
+ return text.range(
101195
+ Math.min(end, start + 1),
101196
+ body.unclosed ? end : Math.max(start + 1, end - 1)
101197
+ );
100798
101198
  }
100799
101199
  function collectRegistryMembers(documents) {
100800
101200
  const byRegistryType = /* @__PURE__ */ new Map();
@@ -106881,8 +107281,10 @@ function parseIndexPathSpellingV4(expression) {
106881
107281
  key: indexed.index.value
106882
107282
  };
106883
107283
  }
106884
- function parseSlotPathSpellingV4(expression, isStaticSymbol) {
106885
- if (expression.kind !== "call") return null;
107284
+ function parseSlotPathSpellingV4(expression, isStaticSymbol, allowImplicit = false) {
107285
+ if (expression.kind !== "call") {
107286
+ return allowImplicit ? parseSlotPath(expression, isStaticSymbol) : null;
107287
+ }
106886
107288
  if (expression.callee.kind !== "ident") return null;
106887
107289
  if (expression.callee.name !== "Reference") return null;
106888
107290
  if ((expression.typeArguments?.length ?? 0) > 0) return null;
@@ -106891,8 +107293,11 @@ function parseSlotPathSpellingV4(expression, isStaticSymbol) {
106891
107293
  }
106892
107294
  const argument2 = expression.args[0];
106893
107295
  if (expression.args.length !== 1 || argument2 === void 0) return null;
107296
+ return parseSlotPath(argument2, isStaticSymbol);
107297
+ }
107298
+ function parseSlotPath(expression, isStaticSymbol) {
106894
107299
  const steps = [];
106895
- let current = argument2;
107300
+ let current = expression;
106896
107301
  for (; ; ) {
106897
107302
  const indexed = current.kind === "force" ? current.operand : current;
106898
107303
  if (indexed.kind === "index") {
@@ -106987,6 +107392,7 @@ function astTypeNameV4(type2) {
106987
107392
  if (type2.kind === "primitive" || type2.kind === "named") return type2.name;
106988
107393
  if (type2.kind === "list") return "List";
106989
107394
  if (type2.kind === "set") return "Set";
107395
+ if (type2.kind === "tuple") return "tuple";
106990
107396
  return "Dictionary";
106991
107397
  }
106992
107398
  function encodeMemberDefaultKeyReferenceV4(spelling) {
@@ -122193,90 +122599,60 @@ function constructorExpressionSlice(source) {
122193
122599
  return normalizeInitializerSource(source);
122194
122600
  }
122195
122601
  function topLevelEntrySlices(initializer, open2, close) {
122196
- const start = topLevelIndexOf(initializer, open2);
122197
- if (start < 0) return [];
122602
+ const tokens = lex(initializer).roots.filter(
122603
+ (token) => token.kind !== "comment"
122604
+ );
122605
+ const angles = [];
122606
+ const genericStarts = /* @__PURE__ */ new Set();
122607
+ for (let index = 0; index < tokens.length; index++) {
122608
+ const token = tokens[index];
122609
+ if (token.kind !== "operator") continue;
122610
+ if (token.text === "<") angles.push(index);
122611
+ else if (token.text === ">") {
122612
+ const start = angles.pop();
122613
+ const next = tokens[index + 1]?.text;
122614
+ if (start !== void 0 && (next === "(" || next === "{" || next === "."))
122615
+ genericStarts.add(start - 1);
122616
+ }
122617
+ }
122198
122618
  const slices = [];
122199
122619
  let depth = 0;
122200
122620
  let entryStart = -1;
122201
- let quote6 = null;
122202
- let escaped = false;
122203
- let index = start;
122204
- while (index < initializer.length) {
122205
- const character = initializer[index];
122206
- if (quote6 !== null) {
122207
- if (escaped) escaped = false;
122208
- else if (character === "\\") escaped = true;
122209
- else if (character === quote6) quote6 = null;
122210
- index += 1;
122211
- continue;
122212
- }
122213
- const afterComment = commentEndIndex(initializer, index);
122214
- if (afterComment !== null) {
122215
- index = afterComment;
122216
- continue;
122217
- }
122218
- if (character === '"' || character === "'") {
122219
- quote6 = character;
122220
- index += 1;
122221
- continue;
122621
+ for (let index = 0; index < tokens.length; index++) {
122622
+ const token = tokens[index];
122623
+ if (genericStarts.has(index)) {
122624
+ const end = new Parser(tokens, index).typeEnd();
122625
+ const next = tokens[end]?.text;
122626
+ if (end > index && (next === "(" || next === "{" || next === ".")) {
122627
+ index = end - 1;
122628
+ continue;
122629
+ }
122222
122630
  }
122631
+ if (token.kind !== "punctuation") continue;
122632
+ const character = token.text;
122633
+ if (depth === 0 && character !== open2) continue;
122223
122634
  if (character === "[" || character === "{" || character === "(") {
122224
- depth += 1;
122225
- if (depth === 1) entryStart = index + 1;
122226
- index += 1;
122227
- continue;
122228
- }
122229
- if (character === "]" || character === "}" || character === ")") {
122230
- depth -= 1;
122635
+ depth++;
122636
+ if (depth === 1) entryStart = token.end;
122637
+ } else if (character === "]" || character === "}" || character === ")") {
122638
+ depth--;
122231
122639
  if (depth === 0) {
122232
122640
  if (character !== close) return [];
122233
122641
  const text = normalizeInitializerSource(
122234
- initializer.slice(entryStart, index)
122642
+ initializer.slice(entryStart, token.start)
122235
122643
  );
122236
- if (text.length > 0 || slices.length > 0) slices.push(text);
122644
+ if (text.length > 0) slices.push(text);
122237
122645
  return slices.filter((entry) => entry.length > 0);
122238
122646
  }
122239
- index += 1;
122240
- continue;
122241
- }
122242
- if (character === "," && depth === 1) {
122647
+ } else if (character === "," && depth === 1) {
122243
122648
  slices.push(
122244
- normalizeInitializerSource(initializer.slice(entryStart, index))
122649
+ normalizeInitializerSource(initializer.slice(entryStart, token.start))
122245
122650
  );
122246
- entryStart = index + 1;
122651
+ entryStart = token.end;
122247
122652
  }
122248
- index += 1;
122249
122653
  }
122250
122654
  return [];
122251
122655
  }
122252
- function topLevelIndexOf(source, character) {
122253
- let quote6 = null;
122254
- let escaped = false;
122255
- let index = 0;
122256
- while (index < source.length) {
122257
- const current = source[index];
122258
- if (quote6 !== null) {
122259
- if (escaped) escaped = false;
122260
- else if (current === "\\") escaped = true;
122261
- else if (current === quote6) quote6 = null;
122262
- index += 1;
122263
- continue;
122264
- }
122265
- const afterComment = commentEndIndex(source, index);
122266
- if (afterComment !== null) {
122267
- index = afterComment;
122268
- continue;
122269
- }
122270
- if (current === '"' || current === "'") {
122271
- quote6 = current;
122272
- index += 1;
122273
- continue;
122274
- }
122275
- if (current === character) return index;
122276
- index += 1;
122277
- }
122278
- return -1;
122279
- }
122280
122656
  function matchesStoredInitializer(defaultValue, source) {
122281
122657
  if (!isObjectRecord(defaultValue) || !isObjectRecord(defaultValue.init))
122282
122658
  return false;
@@ -122290,6 +122666,7 @@ var normalizedInitializers, normalizedInitializerCharacters, MAX_NORMALIZED_INIT
122290
122666
  var init_init_source = __esm({
122291
122667
  "src/project-source/init-source.ts"() {
122292
122668
  "use strict";
122669
+ init_executable_parser();
122293
122670
  init_lexer();
122294
122671
  init_value_comparison();
122295
122672
  normalizedInitializers = /* @__PURE__ */ new Map();
@@ -123646,7 +124023,7 @@ function lowerFieldMember(context, ownerClass, declaration, id2, commonInput, ba
123646
124023
  storesSelectionArray,
123647
124024
  `${ownerClass.name}.${declaration.name}`,
123648
124025
  !declaration.modifiers.includes("static") && contextualEnumArgument(settings, "kind") === "Unordered",
123649
- reference2 !== null
124026
+ reference2 !== null ? fieldType : null
123650
124027
  )
123651
124028
  };
123652
124029
  if (fieldType.tupleElements) {
@@ -124882,10 +125259,36 @@ function deferredReferenceDefault(context, expression) {
124882
125259
  function deferredReferenceValue(context, expression) {
124883
125260
  const spelling = parseIndexPathSpellingV4(expression) ?? parseSlotPathSpellingV4(
124884
125261
  expression,
124885
- (symbol) => context.staticValueIdsBySymbol.has(symbol) || context.classIdsByName.has(symbol.slice(0, symbol.indexOf(".")))
125262
+ (symbol) => context.staticValueIdsBySymbol.has(symbol) || context.classIdsByName.has(symbol.slice(0, symbol.indexOf("."))),
125263
+ isStoredValuePath(context, expression)
124886
125264
  );
124887
125265
  return spelling === null ? null : encodeMemberDefaultKeyReferenceV4(spelling);
124888
125266
  }
125267
+ function isStoredValuePath(context, expression) {
125268
+ const path = expressionMemberPath(expression);
125269
+ if (path === null) return false;
125270
+ const separator = path.lastIndexOf(".");
125271
+ if (separator < 0) return false;
125272
+ const receiver = path.slice(0, separator);
125273
+ const classId = context.rootValueTargetsByPath.get(receiver)?.classId ?? context.classIdsByName.get(receiver);
125274
+ if (classId === void 0) return false;
125275
+ const memberId = effectiveMemberIdByName(
125276
+ context,
125277
+ classId,
125278
+ path.slice(separator + 1)
125279
+ );
125280
+ if (memberId === null) return false;
125281
+ if (!receiver.startsWith("root.") && !isStaticMember2(context, memberId))
125282
+ return false;
125283
+ const source = context.sourceMembersById.get(memberId);
125284
+ if (source !== void 0) {
125285
+ return source.member.kind === "field" && source.member.type.name !== "Reference" && !(source.member.type.name === "Set" && source.member.type.arguments[0]?.name === "Reference") && !source.ownerClass.genericParameters.some(
125286
+ (parameter4) => parameter4.name === source.member.type.name
125287
+ );
125288
+ }
125289
+ const member = context.loweredMembers.get(memberId) ?? context.baseMembers.get(memberId);
125290
+ return member !== void 0 && member.kind !== "lookup" && member.kind !== "generic" && member.kind !== "function" && member.kind !== "scriptFunction";
125291
+ }
124889
125292
  function slotReferenceType(readType) {
124890
125293
  if (readType.name === "Reference") return readType;
124891
125294
  const element = readType.name === "Set" ? readType.arguments[0] : void 0;
@@ -124898,7 +125301,7 @@ function spellsReference(expression) {
124898
125301
  }
124899
125302
  return expression.kind === "call" && expression.callee.kind === "ident" && expression.callee.name === "Reference";
124900
125303
  }
124901
- function lowerDefault(context, initializer, type2, ownerClass, base, memberId, storesSelectionArray, path, unorderedList = false, reference2 = false) {
125304
+ function lowerDefault(context, initializer, type2, ownerClass, base, memberId, storesSelectionArray, path, unorderedList = false, referenceType = null) {
124902
125305
  if (initializer === null) {
124903
125306
  return base?.defaultValue && "serverValueId" in base.defaultValue ? base.defaultValue : null;
124904
125307
  }
@@ -124920,9 +125323,14 @@ function lowerDefault(context, initializer, type2, ownerClass, base, memberId, s
124920
125323
  }
124921
125324
  if (base?.defaultValue != null && matchesStoredInitializer(base.defaultValue, initializer))
124922
125325
  return base.defaultValue;
124923
- const deferred = reference2 ? deferredReferenceDefault(context, expression) : null;
125326
+ const deferred = referenceType !== null && (referenceType.name !== "Set" || expression.kind === "litList") ? deferredReferenceDefault(context, expression) : null;
124924
125327
  if (deferred !== null) return { value: deferred, classId: null };
124925
- if (unorderedList && expression.kind === "litList" && expression.elements.length > 0 || constructsValue(expression) && slotForwardsTypeParameter(context, type2, ownerClass) || positionRequiresEvaluation(context, expression, type2, ownerClass)) {
125328
+ if (unorderedList && expression.kind === "litList" && expression.elements.length > 0 || constructsValue(expression) && slotForwardsTypeParameter(context, type2, ownerClass) || positionRequiresEvaluation(
125329
+ context,
125330
+ expression,
125331
+ referenceType ?? type2,
125332
+ ownerClass
125333
+ )) {
124926
125334
  return {
124927
125335
  init: {
124928
125336
  code: context.settleInitializerReferences(
@@ -124938,7 +125346,7 @@ function lowerDefault(context, initializer, type2, ownerClass, base, memberId, s
124938
125346
  if (context.rowBackedDefaultMemberIds.has(memberId) && base?.defaultValue && !("serverValueId" in base.defaultValue)) {
124939
125347
  return base.defaultValue;
124940
125348
  }
124941
- const slot = reference2 ? slotReferenceType(type2) : null;
125349
+ const slot = referenceType !== null ? slotReferenceType(type2) : null;
124942
125350
  if (slot !== null && !spellsReference(expression)) {
124943
125351
  throw new Error(
124944
125352
  `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.`
@@ -125479,6 +125887,12 @@ function positionRequiresEvaluation(context, expression, expected, ownerClass) {
125479
125887
  ownerClass.name
125480
125888
  )
125481
125889
  );
125890
+ const selectionEntry = expected.name === "Set" ? expected.arguments[0] : void 0;
125891
+ if (selectionEntry?.name === "Reference" && expression.kind === "litList") {
125892
+ return expression.elements.some(
125893
+ (element) => positionRequiresEvaluation(context, element, selectionEntry, ownerClass)
125894
+ );
125895
+ }
125482
125896
  if (isStoredDelegateLiteral(expected, expression))
125483
125897
  return requiresEvaluation();
125484
125898
  if (isStoredActionLiteral(expected, expression)) return false;
@@ -126131,7 +126545,7 @@ function lowerGenericArgument(context, ownerClass, type2, memberId, genericParam
126131
126545
  genericParamId
126132
126546
  };
126133
126547
  const base = context.baseMembers.get(memberId);
126134
- if (base && JSON.stringify(manifestTypeForMember(context, base)) === JSON.stringify(type2)) {
126548
+ if (base && base.kind !== "tuple" && JSON.stringify(manifestTypeForMember(context, base)) === JSON.stringify(type2)) {
126135
126549
  context.loweredMembers.set(memberId, { ...base, owner });
126136
126550
  if (base.kind === "list" || base.kind === "set" || base.kind === "dictionary") {
126137
126551
  lowerCollectionEntry(
@@ -127045,7 +127459,7 @@ function renderVariantSelectionV4(context, memberName, value) {
127045
127459
  );
127046
127460
  }
127047
127461
  const rootPath = context.collectionValuePaths.get(rowValueId);
127048
- const reference2 = rootPath === void 0 ? `Reference(id: ${quoteNeoString(rowValueId)})` : `Reference(${rootPath})`;
127462
+ const reference2 = rootPath === void 0 ? `Reference(id: ${quoteNeoString(rowValueId)})` : rootPath;
127049
127463
  return `${path}.Bind(${reference2})`;
127050
127464
  }
127051
127465
  var init_variant_selection_source = __esm({
@@ -127868,7 +128282,7 @@ function memberSettings(context, member) {
127868
128282
  member.collectionValueId
127869
128283
  );
127870
128284
  settings.push(
127871
- rootPath === void 0 ? `collectionValue: Reference(id: ${quote(member.collectionValueId)})` : `collectionValue: Reference(${rootPath})`
128285
+ rootPath === void 0 ? `collectionValue: Reference(id: ${quote(member.collectionValueId)})` : `collectionValue: ${rootPath}`
127872
128286
  );
127873
128287
  }
127874
128288
  } else if (member.kind === "dialogueLookup") {
@@ -129014,7 +129428,7 @@ function emitVariantFolder(context, className, folder) {
129014
129428
  const rootPath = context.collectionValuePaths.get(
129015
129429
  folder.binding.collectionValueId
129016
129430
  );
129017
- const collectionValue = rootPath === void 0 ? `Reference(id: ${quote(folder.binding.collectionValueId)})` : `Reference(${rootPath})`;
129431
+ const collectionValue = rootPath === void 0 ? `Reference(id: ${quote(folder.binding.collectionValueId)})` : rootPath;
129018
129432
  return `${id(folder.id)}${NEO_LOOKUP_VARIANT_FOLDER_TYPE_NAME}<${className}, ${valueType}> ${variantFolderSymbol(folder)} = new(
129019
129433
  path: ${quote(folder.path)},
129020
129434
  collection: ${qualifiedMember(context, folder.binding.collectionMemberId)},
@@ -130065,7 +130479,7 @@ function emitDialogueGroup(data, recordId, name, priorityNames, dialogueNames, u
130065
130479
  const path = collectionValuePaths.get(data.collectionValueId);
130066
130480
  args.push([
130067
130481
  "collectionValue",
130068
- path === void 0 ? `Reference(id: ${quote2(data.collectionValueId)})` : `Reference(${path})`
130482
+ path === void 0 ? `Reference(id: ${quote2(data.collectionValueId)})` : path
130069
130483
  ]);
130070
130484
  }
130071
130485
  const source = collectDialogueGroupFunctions(data, recordId, uiLogicResolver);
@@ -144396,14 +144810,14 @@ function* prepareServerOwnedSchemaCommitPasses(args) {
144396
144810
  const currentById = new Map(
144397
144811
  args.document.members.map((member) => [member.id, member])
144398
144812
  );
144399
- const sourceMembers = authoredPostDocument.members.map(
144813
+ const sourceMembers2 = authoredPostDocument.members.map(
144400
144814
  (member) => remappedMembers.get(member.id) ?? (recompileTargets.memberIds.has(member.id) || explicitlyChangedMemberIds.has(member.id) ? stripDerivedBodies(member) : member)
144401
144815
  );
144402
144816
  let currentSourceMembers;
144403
144817
  let postCompilationProject;
144404
144818
  let currentCompilationProject;
144405
144819
  const toleratedPreexistingFailures = /* @__PURE__ */ new Set();
144406
- for (const member of sourceMembers) {
144820
+ for (const member of sourceMembers2) {
144407
144821
  if (!hasAuthoredNeoScriptBody(member)) continue;
144408
144822
  if (!recompileTargets.memberIds.has(member.id) || remappedMembers.has(member.id)) {
144409
144823
  continue;
@@ -144412,11 +144826,11 @@ function* prepareServerOwnedSchemaCommitPasses(args) {
144412
144826
  compileOneAuthoredMember({
144413
144827
  scriptSources: scriptSources.get(`member:${member.id}`),
144414
144828
  document: authoredPostDocument,
144415
- members: sourceMembers,
144829
+ members: sourceMembers2,
144416
144830
  member,
144417
144831
  compilationProject: postCompilationProject ??= cachedServerCompilationProject({
144418
144832
  ...authoredPostDocument,
144419
- members: sourceMembers
144833
+ members: sourceMembers2
144420
144834
  })
144421
144835
  });
144422
144836
  } catch (postWriteError) {
@@ -144449,7 +144863,7 @@ function* prepareServerOwnedSchemaCommitPasses(args) {
144449
144863
  }
144450
144864
  }
144451
144865
  const compiledById = new Map(
144452
- sourceMembers.map((member) => [member.id, member])
144866
+ sourceMembers2.map((member) => [member.id, member])
144453
144867
  );
144454
144868
  const explicitMemberIds = /* @__PURE__ */ new Set();
144455
144869
  for (const change of authoredChanges) {
@@ -144470,7 +144884,7 @@ function* prepareServerOwnedSchemaCommitPasses(args) {
144470
144884
  return { ...change, nextData: compiled };
144471
144885
  });
144472
144886
  const hashByKey = indexLiveContentHashesByRecordKey(args.contentHashHeads);
144473
- for (const compiled of sourceMembers) {
144887
+ for (const compiled of sourceMembers2) {
144474
144888
  if (!recompileTargets.memberIds.has(compiled.id)) continue;
144475
144889
  if (explicitMemberIds.has(compiled.id)) continue;
144476
144890
  if (toleratedPreexistingFailures.has(compiled.id)) continue;
@@ -144503,7 +144917,7 @@ function* prepareServerOwnedSchemaCommitPasses(args) {
144503
144917
  targetIds: recompileTargets.constructorIds,
144504
144918
  contentHashHeads: args.contentHashHeads
144505
144919
  });
144506
- const constructionTypeMembers = [...sourceMembers];
144920
+ const constructionTypeMembers = [...sourceMembers2];
144507
144921
  const appendConstructionTypes = () => {
144508
144922
  const created = compiledConstructionTypeMembers(
144509
144923
  constructionTypeMembers,
@@ -159180,7 +159594,7 @@ function folderBinding(context, global) {
159180
159594
  }
159181
159595
  if (collectionValue === void 0) {
159182
159596
  throw new Error(
159183
- `Lookup variant folder ${global.name} requires collectionValue: Reference(...).`
159597
+ `Lookup variant folder ${global.name} requires collectionValue naming a collection row.`
159184
159598
  );
159185
159599
  }
159186
159600
  const collectionValueId = lowerReferenceValue(collectionValue);
@@ -159192,11 +159606,10 @@ function folderBinding(context, global) {
159192
159606
  return { collectionMemberId, collectionValueId };
159193
159607
  }
159194
159608
  function lowerReferenceValue(expression) {
159195
- if (expression.kind !== "call" || expression.callee.kind !== "ident" || expression.callee.name !== "Reference")
159196
- return null;
159197
- const idIndex = expression.argumentNames?.findIndex((name) => name === "id") ?? -1;
159198
- const target = expression.args[idIndex >= 0 ? idIndex : 0];
159199
- if (target?.kind === "litString") return target.value;
159609
+ const isReferenceCall2 = expression.kind === "call" && expression.callee.kind === "ident" && expression.callee.name === "Reference";
159610
+ const idIndex = isReferenceCall2 ? expression.argumentNames?.findIndex((name) => name === "id") ?? -1 : -1;
159611
+ const target = isReferenceCall2 ? expression.args[idIndex >= 0 ? idIndex : 0] : expression;
159612
+ if (isReferenceCall2 && target?.kind === "litString") return target.value;
159200
159613
  const path = target === void 0 ? null : dottedPath(target);
159201
159614
  if (path === null || !path.startsWith("root.")) return null;
159202
159615
  return referenceId2(`Reference(${path})`);
@@ -162017,9 +162430,20 @@ function defaultRequiresOwnedRows(context, member, sourceExpression, source) {
162017
162430
  }
162018
162431
  function memberInitializerRequiresEvaluation(context, member, expression, source) {
162019
162432
  if (member.kind === "class" && member.partial === true) return false;
162020
- if (member.kind === "lookup" && isDeferredPathReferenceValue(context, expression)) {
162433
+ if (member.kind === "lookup" && isDeferredPathReferenceValue(context, expression, member)) {
162021
162434
  return false;
162022
162435
  }
162436
+ if (member.kind === "lookup" && expression.kind === "litList") {
162437
+ const elementMember = { ...member, multiselect: false };
162438
+ return expression.elements.some(
162439
+ (element) => memberInitializerRequiresEvaluation(
162440
+ context,
162441
+ elementMember,
162442
+ element,
162443
+ source
162444
+ )
162445
+ );
162446
+ }
162023
162447
  const unorderedDefault = source.purpose === "memberDefault" && member.id === source.memberId && member.kind === "list" && member.listKind === "unordered" && expression.kind === "litList" && expression.elements.length > 0;
162024
162448
  const requiresEvaluation = unorderedDefault || source.purpose === "memberDefault" && member.id === source.memberId && constructsValue(expression) && slotForwardsTypeParameter2(context, member, source.ownerClassId) || context.localValues.readsInstance(expression) || isSchemaMemberValueRead(context, expression, source) || isUnresolvedLiteralName(context, member, expression) || initializerRequiresEvaluation(
162025
162449
  context.declaredConstructors,
@@ -162049,18 +162473,20 @@ function slotForwardsTypeParameter2(context, member, ownerClassId) {
162049
162473
  }
162050
162474
  return false;
162051
162475
  }
162052
- function deferredPathSpelling(context, expression) {
162476
+ function deferredPathSpelling(context, expression, expected) {
162053
162477
  return parseIndexPathSpellingV4(expression) ?? parseSlotPathSpellingV4(
162054
162478
  expression,
162055
- (symbol) => context.staticValueIdsBySymbol.has(symbol)
162479
+ (symbol) => context.staticValueIdsBySymbol.has(symbol),
162480
+ isStoredSlotPath(context, expression, expected)
162056
162481
  );
162057
162482
  }
162058
- function isDeferredPathReferenceValue(context, sourceExpression) {
162483
+ function isDeferredPathReferenceValue(context, sourceExpression, expected) {
162059
162484
  const expression = annotatedValue(sourceExpression).expression;
162485
+ if (expected.multiselect && expression.kind !== "litList") return false;
162060
162486
  const elements = expression.kind === "litList" ? expression.elements : [expression];
162061
162487
  let indexPaths = 0;
162062
162488
  for (const element of elements) {
162063
- if (deferredPathSpelling(context, element) !== null) {
162489
+ if (deferredPathSpelling(context, element, expected) !== null) {
162064
162490
  indexPaths += 1;
162065
162491
  continue;
162066
162492
  }
@@ -162070,6 +162496,35 @@ function isDeferredPathReferenceValue(context, sourceExpression) {
162070
162496
  }
162071
162497
  return indexPaths > 0;
162072
162498
  }
162499
+ function isStoredSlotPath(context, expression, expected) {
162500
+ const path = memberPath2(expression);
162501
+ if (path === null) return false;
162502
+ const separator = path.lastIndexOf(".");
162503
+ if (separator < 0) return false;
162504
+ const receiver = path.slice(0, separator);
162505
+ const staticClass = context.classesByName.get(receiver);
162506
+ const classId = context.rootValueTargetsByPath.get(receiver)?.classId ?? staticClass?.id;
162507
+ if (classId === void 0) return false;
162508
+ const memberId = classSchemaMemberId(
162509
+ context,
162510
+ classId,
162511
+ path.slice(separator + 1)
162512
+ );
162513
+ const member = memberId === null ? void 0 : context.members.get(memberId);
162514
+ if (member === void 0) return false;
162515
+ if (staticClass !== void 0 && member.modifier !== "static") return false;
162516
+ if (member.kind === "lookup") {
162517
+ if (member.declaredType === null) return false;
162518
+ if (member.multiselect) return false;
162519
+ const storedType = {
162520
+ kind: "reference",
162521
+ nullable: !member.required,
162522
+ target: member.declaredType
162523
+ };
162524
+ return canonicallyEqual(expected.declaredType, storedType);
162525
+ }
162526
+ return member.kind !== "generic" && member.kind !== "computed" && member.kind !== "function" && member.kind !== "scriptFunction";
162527
+ }
162073
162528
  function isSchemaMemberValueRead(context, expression, source) {
162074
162529
  const path = memberPath2(annotatedValue(expression).expression);
162075
162530
  if (path === null) return false;
@@ -165468,7 +165923,8 @@ function lowerRawMemberTypeName(context, memberId) {
165468
165923
  if (member.kind === 8 /* Enum */ && typeof member.enumId === "string") {
165469
165924
  return context.enumNames.get(member.enumId) ?? null;
165470
165925
  }
165471
- if (member.kind === 9 /* Lookup */) return "Reference";
165926
+ if (member.kind === 9 /* Lookup */)
165927
+ return member.selection === 1 /* Multi */ ? "Set" : "Reference";
165472
165928
  if (member.kind === 6 /* List */) return "List";
165473
165929
  if (member.kind === 28 /* Set */) return "Set";
165474
165930
  if (member.kind === 5 /* Dictionary */) return "Dictionary";
@@ -165484,7 +165940,7 @@ function lowerSchemaMemberTypeName(context, member) {
165484
165940
  case "enum":
165485
165941
  return context.enumNames.get(member.enumId) ?? null;
165486
165942
  case "lookup":
165487
- return "Reference";
165943
+ return member.multiselect ? "Set" : "Reference";
165488
165944
  case "list":
165489
165945
  return "List";
165490
165946
  case "set":
@@ -165903,13 +166359,17 @@ function lowerEnum2(context, member, expression) {
165903
166359
  });
165904
166360
  }
165905
166361
  function lowerReferences(context, member, expression, ownerValueId, source) {
166362
+ function refuse(message, at3 = expression) {
166363
+ context.loweringFailures.push({ message, site: referenceSite(source, at3) });
166364
+ throw new ReportedLoweringFailure(message);
166365
+ }
165906
166366
  const elements = member.multiselect ? expression.kind === "litList" ? expression.elements : null : [expression];
165907
166367
  if (elements === null) {
165908
- throw new Error(`Reference member ${member.name} requires [...].`);
166368
+ refuse(`Reference member ${member.name} requires [...].`);
165909
166369
  }
165910
166370
  const ids = [];
165911
166371
  for (const [index, entry] of elements.entries()) {
165912
- const path = member.kind === "lookup" ? deferredPathSpelling(context, entry) : null;
166372
+ const path = member.kind === "lookup" ? deferredPathSpelling(context, entry, member) : null;
165913
166373
  if (path !== null) {
165914
166374
  ids.push(`${PENDING_ID_PREFIX}reference-index:${source.label}:${index}`);
165915
166375
  context.referenceObligations.push({
@@ -165923,7 +166383,7 @@ function lowerReferences(context, member, expression, ownerValueId, source) {
165923
166383
  }
165924
166384
  const target = referenceTargetSpelling(context, entry);
165925
166385
  if (target === null) {
165926
- throw new Error(`Reference member ${member.name} has an invalid target.`);
166386
+ refuse(`Reference member ${member.name} has an invalid target.`, entry);
165927
166387
  }
165928
166388
  if (target.spelling === "key" || target.spelling === "local") {
165929
166389
  ids.push(`${PENDING_ID_PREFIX}reference-key:${source.label}:${index}`);
@@ -165946,9 +166406,7 @@ function lowerReferences(context, member, expression, ownerValueId, source) {
165946
166406
  ids.push(target.spelling === "id" ? target.id : target.resolved.id);
165947
166407
  }
165948
166408
  if (new Set(ids).size !== ids.length) {
165949
- throw new Error(
165950
- `Reference member ${member.name} cannot contain duplicate targets.`
165951
- );
166409
+ refuse(`Reference member ${member.name} cannot contain duplicate targets.`);
165952
166410
  }
165953
166411
  return ids;
165954
166412
  }
@@ -168938,9 +169396,14 @@ function schemaTypeForBindingMember(context, memberId, environment, visited = /*
168938
169396
  if (member.declaredType !== null) {
168939
169397
  if (member.collectionMemberId === null && member.multiselect) {
168940
169398
  return {
168941
- kind: "lookup",
169399
+ kind: "set",
168942
169400
  nullable: nullable2,
168943
- entryType: referenceReadType2(context, member.declaredType)
169401
+ setMemberId: member.id,
169402
+ entryType: {
169403
+ kind: "reference",
169404
+ nullable: false,
169405
+ target: member.declaredType
169406
+ }
168944
169407
  };
168945
169408
  }
168946
169409
  return { kind: "reference", nullable: nullable2, target: member.declaredType };
@@ -170107,10 +170570,10 @@ function unboundReferenceTypeName(context, member, targetId) {
170107
170570
  if (manifestMember.collectionMemberId !== null) return null;
170108
170571
  const declared = manifestMember.declaredType;
170109
170572
  if (declared === null) return null;
170110
- if (declared.kind !== "class" && declared.kind !== "interface" && declared.kind !== "generic") {
170573
+ if (declared.kind !== "interface" && declared.kind !== "generic") {
170111
170574
  return storedTypeArgumentName(context, declared, /* @__PURE__ */ new Map());
170112
170575
  }
170113
- const classId = declared.kind === "class" ? declared.classId : context.values.get(targetId)?.classId;
170576
+ const classId = context.values.get(targetId)?.classId;
170114
170577
  if (typeof classId !== "string") return null;
170115
170578
  return context.manifestClasses.get(classId)?.name ?? null;
170116
170579
  }
@@ -185097,15 +185560,7 @@ function complete(snapshot, position) {
185097
185560
  const tokens = significantTokensBefore(snapshot.lexed.tokens, word.start);
185098
185561
  const tail = tokens[tokens.length - 1];
185099
185562
  let candidates;
185100
- const genericMember = tail?.text === "<" ? resolveChain(
185101
- snapshot,
185102
- expressionTokensBefore(tokens, tokens.length - 1),
185103
- offset
185104
- )?.symbol : void 0;
185105
- const genericMemberId = genericMember?.id;
185106
- const firstTypeParameter = genericMember?.typeParameters?.[0]?.type;
185107
- const functionConstraint = firstTypeParameter?.kind === "typeParameter" && firstTypeParameter.constraint?.kind === "named" ? firstTypeParameter.constraint.typeId : void 0;
185108
- const nativeGenericClassId = genericMemberId === NEO_TILE_CONVERT_MEMBER_ID ? NEO_TILE_CLASS_ID : functionConstraint;
185563
+ const genericTypes = typeArgumentCompletionItems(snapshot, tokens, word);
185109
185564
  const catchFilterCandidates = catchFilterCompletionItems(
185110
185565
  snapshot,
185111
185566
  word.start,
@@ -185122,7 +185577,9 @@ function complete(snapshot, position) {
185122
185577
  prefix,
185123
185578
  word
185124
185579
  );
185125
- if (catchFilterCandidates) {
185580
+ if (genericTypes) {
185581
+ candidates = genericTypes;
185582
+ } else if (catchFilterCandidates) {
185126
185583
  candidates = catchFilterCandidates;
185127
185584
  } else if (catchClauseCandidates) {
185128
185585
  candidates = catchClauseCandidates;
@@ -185149,14 +185606,6 @@ function complete(snapshot, position) {
185149
185606
  word,
185150
185607
  expectedValueAt(snapshot, word.start)
185151
185608
  );
185152
- } else if (nativeGenericClassId) {
185153
- candidates = [...snapshot.project.typeByName.values()].filter(
185154
- (type2) => type2.kind === "class" && (genericMemberId !== NEO_TILE_CONVERT_MEMBER_ID || !type2.abstract && !type2.typeParameters?.length) && isNeoScriptTypeAssignable(
185155
- { kind: "named", typeId: type2.id },
185156
- { kind: "named", typeId: nativeGenericClassId },
185157
- snapshot.project
185158
- )
185159
- ).map((type2) => typeCompletion(type2, word, snapshot));
185160
185609
  } else if (isTypePosition(tokens)) {
185161
185610
  candidates = typeCompletionItems(snapshot, word);
185162
185611
  } else if (isLambdaParameterPosition(tokens)) {
@@ -185169,6 +185618,98 @@ function complete(snapshot, position) {
185169
185618
  items: rankAndDeduplicate(candidates, prefix)
185170
185619
  };
185171
185620
  }
185621
+ function completeTypeArgument(snapshot, position) {
185622
+ const offset = snapshot.source.offsetAt(position);
185623
+ if (insidePlainString(snapshot.lexed.tokens, offset)) return null;
185624
+ const word = {
185625
+ start: wordRangeAt(snapshot.source.text, offset).start,
185626
+ end: offset
185627
+ };
185628
+ const tokens = significantTokensBefore(snapshot.lexed.tokens, word.start);
185629
+ const items = typeArgumentCompletionItems(snapshot, tokens, word);
185630
+ return items === null ? null : {
185631
+ isIncomplete: hasUnclosedConstruct(snapshot.lexed.tokens, offset),
185632
+ items: rankAndDeduplicate(
185633
+ items,
185634
+ snapshot.source.text.slice(word.start, offset)
185635
+ )
185636
+ };
185637
+ }
185638
+ function typeArgumentCompletionItems(snapshot, tokens, word) {
185639
+ let depth = 0;
185640
+ let argumentIndex = 0;
185641
+ let tupleDepth = 0;
185642
+ let inTuple = false;
185643
+ for (let index = tokens.length - 1; index >= 0; index--) {
185644
+ const token = tokens[index];
185645
+ if (token.text === ")") tupleDepth++;
185646
+ else if (token.text === "(") {
185647
+ if (!["<", ",", "("].includes(tokens[index - 1]?.text ?? "")) return null;
185648
+ if (tupleDepth > 0) tupleDepth--;
185649
+ else inTuple = true;
185650
+ } else if (/^>+$/.test(token.text)) depth += token.text.length;
185651
+ else if (token.text === "<") {
185652
+ if (depth > 0) {
185653
+ depth--;
185654
+ continue;
185655
+ }
185656
+ const name = tokens[index - 1]?.text;
185657
+ const resolution = resolveChain(
185658
+ snapshot,
185659
+ expressionTokensBefore(tokens, index),
185660
+ word.start
185661
+ );
185662
+ const member = resolution?.symbol;
185663
+ const declaration = (tokens[index - 2]?.text === "new" || resolution === null) && name ? snapshot.project.typeByName.get(name) : resolution?.staticType;
185664
+ const parameters = member?.typeParameters ?? declaration?.typeParameters;
185665
+ const builtin = name !== void 0 && member === void 0 && tokens[index - 2]?.text !== "." && [
185666
+ "List",
185667
+ "Set",
185668
+ "Dictionary",
185669
+ "Reference",
185670
+ "Partial",
185671
+ "FunctionRef",
185672
+ "NeoDelegate",
185673
+ "NeoAction"
185674
+ ].includes(name);
185675
+ const tileConversion = member?.id === NEO_TILE_CONVERT_MEMBER_ID && argumentIndex === 0;
185676
+ if (!parameters?.length && !builtin && !tileConversion) return null;
185677
+ const parameter4 = inTuple ? void 0 : parameters?.[argumentIndex]?.type;
185678
+ const constraint = parameter4?.kind === "typeParameter" ? parameter4.constraint : void 0;
185679
+ const constraintId = constraint?.kind === "named" ? constraint.typeId : void 0;
185680
+ const classId = tileConversion ? NEO_TILE_CLASS_ID : constraintId;
185681
+ if (!classId) return typeCompletionItems(snapshot, word);
185682
+ const candidates = [...snapshot.project.typeByName.values()].filter(
185683
+ (type2) => type2.kind === "class" && (!tileConversion || !type2.abstract && !type2.typeParameters?.length) && isNeoScriptTypeAssignable(
185684
+ { kind: "named", typeId: type2.id },
185685
+ { kind: "named", typeId: classId },
185686
+ snapshot.project
185687
+ )
185688
+ ).map((type2) => typeCompletion(type2, word, snapshot));
185689
+ if (!tileConversion)
185690
+ candidates.push(
185691
+ ...typeParameterCompletionItems(snapshot, word, constraint)
185692
+ );
185693
+ return candidates;
185694
+ } else if (!isCallTypeArgumentToken(token)) return null;
185695
+ else if (depth === 0 && tupleDepth === 0 && token.text === ",")
185696
+ argumentIndex++;
185697
+ }
185698
+ return null;
185699
+ }
185700
+ function completeLambdaBody(snapshot, position) {
185701
+ return lambdaBodyAt(snapshot, snapshot.source.offsetAt(position)) ? complete(snapshot, position) : null;
185702
+ }
185703
+ function completeFunctionArgument(snapshot, position) {
185704
+ const argument2 = callArgumentAt(snapshot, snapshot.source.offsetAt(position));
185705
+ if (!argument2 || argument2.call.kind === "constructor" || !callSymbol(snapshot, argument2.call))
185706
+ return null;
185707
+ const features = scriptFeatureIndex(snapshot);
185708
+ for (let opener = innermostOpener(features, snapshot.source.offsetAt(position)); opener >= 0 && features.tokens[opener].start > argument2.call.openParenOffset; opener = features.enclosingOpener[opener]) {
185709
+ if (features.tokens[opener].text === "{") return null;
185710
+ }
185711
+ return complete(snapshot, position);
185712
+ }
185172
185713
  function hover(snapshot, position) {
185173
185714
  const offset = snapshot.source.offsetAt(position);
185174
185715
  const reference2 = referenceAt(snapshot.parsed.references, offset);
@@ -185274,6 +185815,10 @@ function definition(snapshot, position) {
185274
185815
  ) === index
185275
185816
  );
185276
185817
  }
185818
+ function constructorTypeAt(snapshot, position) {
185819
+ const argument2 = callArgumentAt(snapshot, snapshot.source.offsetAt(position));
185820
+ return argument2?.call.kind === "constructor" ? constructionType(snapshot, argument2.call)?.declaration.name ?? null : null;
185821
+ }
185277
185822
  function signatureHelp(snapshot, position) {
185278
185823
  const argument2 = callArgumentAt(snapshot, snapshot.source.offsetAt(position));
185279
185824
  if (!argument2) return null;
@@ -185670,6 +186215,12 @@ function typeArgumentCount(tokens) {
185670
186215
  }
185671
186216
  return count;
185672
186217
  }
186218
+ function callParametersAt(snapshot, position) {
186219
+ const call = scriptFeatureIndex(snapshot).calls.get(
186220
+ snapshot.source.offsetAt(position)
186221
+ );
186222
+ return call?.kind === "function" ? callSymbol(snapshot, call)?.parameters ?? null : null;
186223
+ }
185673
186224
  function inlayHints(snapshot, range2) {
185674
186225
  const hints = [];
185675
186226
  for (const call of snapshot.parsed.calls) {
@@ -185689,11 +186240,9 @@ function inlayHints(snapshot, range2) {
185689
186240
  if (!argumentRange || !parameterName || call.argumentNames[index]) {
185690
186241
  continue;
185691
186242
  }
185692
- if (obviousParameterName(snapshot, argumentRange, parameterName)) {
185693
- continue;
185694
- }
185695
- const position = firstNonWhitespacePosition(snapshot, argumentRange);
185696
- if (comparePositions(position, argumentRange.end) >= 0) continue;
186243
+ const argument2 = argumentTokenBounds(snapshot, argumentRange);
186244
+ if (!argument2 || obviousParameterName(argument2, parameterName)) continue;
186245
+ const position = argument2.first.range.start;
185697
186246
  if (range2 && !positionInRange(position, range2)) continue;
185698
186247
  hints.push({
185699
186248
  position,
@@ -185718,11 +186267,8 @@ function inlayHints(snapshot, range2) {
185718
186267
  }
185719
186268
  return hints;
185720
186269
  }
185721
- function obviousParameterName(snapshot, argumentRange, parameterName) {
185722
- const start = snapshot.source.offsetAt(argumentRange.start);
185723
- const end = snapshot.source.offsetAt(argumentRange.end);
185724
- const argument2 = snapshot.source.text.slice(start, end).trim();
185725
- return /^[A-Za-z_][A-Za-z0-9_]*$/.test(argument2) && normalizeHintName(argument2) === normalizeHintName(parameterName);
186270
+ function obviousParameterName(argument2, parameterName) {
186271
+ return argument2.first === argument2.last && argument2.first.kind === "identifier" && normalizeHintName(argument2.first.text) === normalizeHintName(parameterName);
185726
186272
  }
185727
186273
  function normalizeHintName(name) {
185728
186274
  return name.replaceAll("_", "").toLocaleLowerCase();
@@ -185758,18 +186304,7 @@ function positionCompare2(left, right) {
185758
186304
  }
185759
186305
  function constructorParameterNames(type2) {
185760
186306
  const declared = type2?.declaredConstructors ?? [];
185761
- if (declared.length > 0) {
185762
- const arity = Math.max(
185763
- ...declared.map((constructor2) => constructor2.parameters.length)
185764
- );
185765
- return Array.from({ length: arity }, (_, index) => {
185766
- const names2 = new Set(
185767
- declared.map((constructor2) => constructor2.parameters[index]?.name)
185768
- );
185769
- const [name] = names2;
185770
- return names2.size === 1 && name ? name : null;
185771
- });
185772
- }
186307
+ if (declared.length > 0) return neoScriptCommonParameterNames(declared);
185773
186308
  return type2?.constructorSignature?.parameters.map((parameter4) => parameter4.name) ?? null;
185774
186309
  }
185775
186310
  function documentSymbols2(snapshot) {
@@ -186567,6 +187102,32 @@ function initializerConstruction(snapshot, brace, constructor2) {
186567
187102
  }
186568
187103
  return construction;
186569
187104
  }
187105
+ function initializerKeyContextAt(snapshot, position) {
187106
+ const features = scriptFeatureIndex(snapshot);
187107
+ const offset = snapshot.source.offsetAt(position);
187108
+ const brace = innermostOpener(features, offset);
187109
+ const constructor2 = features.objectInitializers.get(brace);
187110
+ if (constructor2 === void 0) return null;
187111
+ const keys = [];
187112
+ let atKey = true;
187113
+ for (let index = brace + 1; index < features.tokens.length; index++) {
187114
+ const token = features.tokens[index];
187115
+ if (token.start >= offset) break;
187116
+ if (features.enclosingOpener[index] !== brace) continue;
187117
+ const call = features.calls.get(token.start);
187118
+ if (call?.typeArgumentTokens?.length) {
187119
+ index = (features.tokenIndexes.get(call.openParenOffset) ?? index + 1) - 1;
187120
+ continue;
187121
+ }
187122
+ if (token.text === "=") {
187123
+ keys.push(features.tokens[index - 1].text);
187124
+ atKey = false;
187125
+ } else if (token.text === ",") atKey = true;
187126
+ }
187127
+ if (!atKey) return null;
187128
+ const construction = initializerConstruction(snapshot, brace, constructor2);
187129
+ return construction ? { typeName: construction.declaration.name, keys } : null;
187130
+ }
186570
187131
  function initializerExpectedType(snapshot, offset, bodyStart) {
186571
187132
  const features = scriptFeatureIndex(snapshot);
186572
187133
  const { tokens, enclosingOpener, callOpenings, objectInitializers } = features;
@@ -186731,6 +187292,22 @@ function innermostOpener(features, offset) {
186731
187292
  return token.kind === "punctuation" && (token.text === "(" || token.text === "[" || token.text === "{") ? last : enclosingOpener[last];
186732
187293
  }
186733
187294
  function callSymbol(snapshot, call) {
187295
+ if (call.kind === "expression") {
187296
+ const features = scriptFeatureIndex(snapshot);
187297
+ const open2 = features.tokenIndexes.get(call.openParenOffset);
187298
+ if (open2 === void 0) return void 0;
187299
+ const type2 = inferExpressionType2(
187300
+ expressionTokensBefore(features.tokens, open2),
187301
+ snapshot,
187302
+ call.openParenOffset
187303
+ );
187304
+ return type2.kind === "delegate" ? {
187305
+ id: `delegate:${call.openParenOffset}`,
187306
+ name: "delegate",
187307
+ kind: "local",
187308
+ type: type2
187309
+ } : void 0;
187310
+ }
186734
187311
  const reference2 = scriptFeatureIndex(snapshot).references.get(
186735
187312
  snapshot.source.offsetAt(call.nameRange.start)
186736
187313
  );
@@ -186964,6 +187541,27 @@ function matchingCloseBraceIndex(tokens, openIndex) {
186964
187541
  }
186965
187542
  return null;
186966
187543
  }
187544
+ function typeParameterCompletionItems(snapshot, word, constraint) {
187545
+ const items = [];
187546
+ for (const parameter4 of [
187547
+ ...contextualTypeParameters(snapshot),
187548
+ ...snapshot.context.typeParameters ?? []
187549
+ ]) {
187550
+ if (constraint && !isNeoScriptTypeAssignable(parameter4.type, constraint, snapshot.project))
187551
+ continue;
187552
+ items.push(
187553
+ completion(
187554
+ parameter4.name,
187555
+ "typeParameter",
187556
+ parameter4.name,
187557
+ "Type parameter",
187558
+ word,
187559
+ snapshot
187560
+ )
187561
+ );
187562
+ }
187563
+ return items;
187564
+ }
186967
187565
  function typeCompletionItems(snapshot, word) {
186968
187566
  const items = NEOSCRIPT_PRIMITIVE_TYPES.map(
186969
187567
  (name) => completion(name, "keyword", name, "Primitive type", word, snapshot)
@@ -186979,8 +187577,9 @@ function typeCompletionItems(snapshot, word) {
186979
187577
  "snippet"
186980
187578
  )
186981
187579
  );
187580
+ items.push(...typeParameterCompletionItems(snapshot, word));
186982
187581
  for (const type2 of snapshot.project.typeByName.values()) {
186983
- if (type2.id === NEOSCRIPT_MATH_TYPE_ID || type2.id === "builtin:Debug")
187582
+ if (type2.kind === "builtin" && !ANNOTATION_TYPE_NAMES.has(type2.name))
186984
187583
  continue;
186985
187584
  items.push(typeCompletion(type2, word, snapshot));
186986
187585
  }
@@ -187292,7 +187891,7 @@ function isKnownMemberReceiver(snapshot, receiver) {
187292
187891
  function specializeGenericCall(snapshot, resolved, typeArguments, openParenOffset) {
187293
187892
  if (resolved === null) return null;
187294
187893
  const inferred = openParenOffset === void 0 ? void 0 : flowProbe(snapshot).calls.get(openParenOffset);
187295
- if (inferred !== void 0 && inferred.id === resolved.symbol?.id)
187894
+ if (inferred !== void 0)
187296
187895
  return { type: inferred.returnType ?? inferred.type, symbol: inferred };
187297
187896
  const { symbol } = resolved;
187298
187897
  const parameters = symbol?.typeParameters;
@@ -187743,9 +188342,10 @@ function flowProbe(snapshot) {
187743
188342
  return result;
187744
188343
  const text = snapshot.source.text;
187745
188344
  const source = snapshot.source;
188345
+ const context = snapshot.expressionRange && snapshot.context.kind === "initializerExpression" ? { ...snapshot.context, kind: "function" } : snapshot.context;
187746
188346
  compileNeoScriptStrict(
187747
188347
  { uri: snapshot.uri, languageId: "neoscript", version: 1, text },
187748
- snapshot.context,
188348
+ context,
187749
188349
  {
187750
188350
  emit: false,
187751
188351
  projectIndex: snapshot.project,
@@ -188780,6 +189380,18 @@ function inferLambdaParameterType(local, snapshot) {
188780
189380
  if (declarationIndex < 0) return UNKNOWN_TYPE;
188781
189381
  const arrow = tokens[declarationIndex + 1];
188782
189382
  let opener = enclosingOpener[declarationIndex];
189383
+ let lambdaStart = arrow?.text === "=>" ? declarationIndex : opener;
189384
+ for (let depth = 0; depth < (local.tuplePath?.length ?? 0); depth++)
189385
+ lambdaStart = enclosingOpener[lambdaStart] ?? -1;
189386
+ if (lambdaStart >= 0) {
189387
+ const offset = tokens[lambdaStart].start;
189388
+ const argument2 = resolvedCallArgumentAt(snapshot, offset);
189389
+ const expected = isCollectionCallbackArgument(argument2) ? null : expectedTypeAt(snapshot, offset, void 0, argument2);
189390
+ if (expected?.kind === "delegate") {
189391
+ const parameter4 = expected.parameterTypes[local.lambdaParameterIndex ?? 0];
189392
+ if (parameter4) return tuplePathType(parameter4, local.tuplePath);
189393
+ }
189394
+ }
188783
189395
  if (!(arrow?.kind === "operator" && arrow.text === "=>")) {
188784
189396
  if (opener < 0 || tokens[opener]?.text !== "(") return UNKNOWN_TYPE;
188785
189397
  opener = enclosingOpener[opener];
@@ -189045,15 +189657,25 @@ function significantTokensBefore(tokens, offset, start = 0) {
189045
189657
  }
189046
189658
  function expressionTokensBefore(tokens, endExclusive) {
189047
189659
  let depth = 0;
189660
+ let groupEnd = -1;
189048
189661
  let start = endExclusive - 1;
189049
189662
  for (; start >= 0; start--) {
189050
189663
  const token = tokens[start];
189051
189664
  if (!token) continue;
189052
- if (token.kind === "punctuation" && [")", "]"].includes(token.text))
189665
+ if (token.kind === "punctuation" && [")", "]", "}"].includes(token.text)) {
189666
+ if (token.text === "}" && depth === 0 && start < endExclusive - 1 && ![".", "?.", "!"].includes(tokens[start + 1]?.text ?? ""))
189667
+ break;
189668
+ if (depth === 0) groupEnd = start;
189053
189669
  depth++;
189054
- if (token.kind === "punctuation" && ["(", "["].includes(token.text)) {
189670
+ }
189671
+ if (token.kind === "punctuation" && ["(", "[", "{"].includes(token.text)) {
189055
189672
  if (depth > 0) depth--;
189056
189673
  else break;
189674
+ if (depth === 0 && ["if", "while", "for", "foreach"].includes(
189675
+ tokens[start - 1]?.text ?? ""
189676
+ ))
189677
+ return tokens.slice(groupEnd + 1, endExclusive);
189678
+ continue;
189057
189679
  }
189058
189680
  if (depth === 0 && token.kind === "operator" && token.text === ">") {
189059
189681
  const name = genericCallNameIndex(tokens, start);
@@ -189070,8 +189692,7 @@ function expressionTokensBefore(tokens, endExclusive) {
189070
189692
  return tokens.slice(start + 1, endExclusive);
189071
189693
  }
189072
189694
  function genericCallNameIndex(tokens, close) {
189073
- if (tokens[close + 1]?.text !== "(" && tokens[close + 1]?.text !== ".")
189074
- return -1;
189695
+ if (!["(", ".", "{"].includes(tokens[close + 1]?.text ?? "")) return -1;
189075
189696
  let depth = 0;
189076
189697
  for (let cursor = close; cursor > 0; cursor--) {
189077
189698
  const token = tokens[cursor];
@@ -189079,7 +189700,7 @@ function genericCallNameIndex(tokens, close) {
189079
189700
  if (token.text === ">") depth++;
189080
189701
  else if (token.text === "<") {
189081
189702
  if (--depth === 0) {
189082
- const valid = tokens[close + 1]?.text === "." ? new Parser(tokens.slice(cursor - 1, close + 1)).typeEnd() === close - cursor + 2 : callOpenParenIndex(tokens, cursor - 1) === close + 1;
189703
+ const valid = tokens[close + 1]?.text !== "(" ? new Parser(tokens.slice(cursor - 1, close + 1)).typeEnd() === close - cursor + 2 : callOpenParenIndex(tokens, cursor - 1) === close + 1;
189083
189704
  return valid ? cursor - 1 : -1;
189084
189705
  }
189085
189706
  } else if (!isCallTypeArgumentToken(token)) return -1;
@@ -189105,13 +189726,6 @@ function wordRangeAt(text, offset) {
189105
189726
  function isTypePosition(tokens) {
189106
189727
  const tail = tokens[tokens.length - 1];
189107
189728
  if (!tail) return false;
189108
- if (tail.kind === "operator" && tail.text === "<") {
189109
- const previous = tokens[tokens.length - 2];
189110
- return previous?.text === "Dictionary" || previous?.text === "Set";
189111
- }
189112
- if (tail.kind === "punctuation" && tail.text === ",") {
189113
- return tokens.some((token) => token.text === "Dictionary");
189114
- }
189115
189729
  if (tail.kind === "keyword" && tail.text === "is") return true;
189116
189730
  if (tail.text === "not" && tokens.at(-2)?.text === "is") return true;
189117
189731
  return false;
@@ -189207,14 +189821,16 @@ function boundParameter(parameters, call, index) {
189207
189821
  index
189208
189822
  );
189209
189823
  }
189210
- function firstNonWhitespacePosition(snapshot, range2) {
189824
+ function argumentTokenBounds(snapshot, range2) {
189211
189825
  const start = snapshot.source.offsetAt(range2.start);
189212
189826
  const end = snapshot.source.offsetAt(range2.end);
189213
- let offset = start;
189214
- while (offset < end && /\s/.test(snapshot.source.text[offset] ?? "")) {
189215
- offset++;
189216
- }
189217
- return snapshot.source.positionAt(offset);
189827
+ const tokens = snapshot.lexed.tokens;
189828
+ let first = firstIndex(tokens, (token) => token.start >= start);
189829
+ let last = firstIndex(tokens, (token) => token.start >= end) - 1;
189830
+ while (first <= last && tokens[first].kind === "comment") first++;
189831
+ while (last >= first && tokens[last].kind === "comment") last--;
189832
+ if (first > last || tokens[first]?.kind === "eof") return null;
189833
+ return { first: tokens[first], last: tokens[last] };
189218
189834
  }
189219
189835
  function positionInRange(position, range2) {
189220
189836
  return comparePositions(position, range2.start) >= 0 && comparePositions(position, range2.end) <= 0;
@@ -189228,7 +189844,7 @@ function isTypeAnnotationReference(snapshot, reference2) {
189228
189844
  function isConstructorTypeReference(snapshot, reference2) {
189229
189845
  return scriptFeatureIndex(snapshot).calls.get(reference2.start)?.kind === "constructor";
189230
189846
  }
189231
- 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;
189847
+ 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;
189232
189848
  var init_analyzer = __esm({
189233
189849
  "../packages/neoscript-language/src/analyzer.ts"() {
189234
189850
  "use strict";
@@ -189259,6 +189875,9 @@ var init_analyzer = __esm({
189259
189875
  NAMED_ARGUMENT_LABELS = /* @__PURE__ */ new WeakMap();
189260
189876
  NO_EXPECTED_VALUE = { type: null };
189261
189877
  CONSTRUCTIONS = /* @__PURE__ */ new WeakMap();
189878
+ ANNOTATION_TYPE_NAMES = new Set(
189879
+ NEOSCRIPT_BUILTIN_ANNOTATION_TYPES
189880
+ );
189262
189881
  FLOW_PROBES = /* @__PURE__ */ new WeakMap();
189263
189882
  OVERLOADED_FUNCTION_NAMES = /* @__PURE__ */ new WeakMap();
189264
189883
  GENERIC_CALL_NAMES = /* @__PURE__ */ new WeakMap();
@@ -189322,6 +189941,43 @@ var init_parity_contract = __esm({
189322
189941
  }
189323
189942
  });
189324
189943
 
189944
+ // ../packages/neoscript-language/src/argument-name-completions.ts
189945
+ function argumentNameCompletions(fields, tokens, start, prefixEnd, position) {
189946
+ const edit = argumentNameCompletionEdit(tokens, start, prefixEnd, position);
189947
+ if (!edit) return [];
189948
+ const { range: range2, hasColon } = edit;
189949
+ const items = [];
189950
+ for (const field of fields) {
189951
+ const insertText = hasColon ? field.name : `${field.name}: `;
189952
+ items.push({
189953
+ label: field.name,
189954
+ kind: "property",
189955
+ detail: field.defaultText === void 0 ? field.type : `[${field.type} = ${field.defaultText}]`,
189956
+ insertText,
189957
+ textEdit: { range: range2, newText: insertText }
189958
+ });
189959
+ }
189960
+ return items;
189961
+ }
189962
+ function argumentNameCompletionEdit(tokens, start, prefixEnd, position) {
189963
+ const first = tokens[start];
189964
+ if (prefixEnd > start + 1) return null;
189965
+ if (prefixEnd > start && (!first || !isCallArgumentLabelToken(first)))
189966
+ return null;
189967
+ const editingName = first !== void 0 && isCallArgumentLabelToken(first) && positionCompare(first.range.start, position) <= 0 && positionCompare(position, first.range.end) <= 0;
189968
+ if (first && isCallArgumentLabelToken(first) && !editingName) return null;
189969
+ const hasColon = editingName && tokens[start + 1]?.text === ":";
189970
+ const range2 = editingName ? first.range : { start: position, end: position };
189971
+ return { range: range2, hasColon };
189972
+ }
189973
+ var init_argument_name_completions = __esm({
189974
+ "../packages/neoscript-language/src/argument-name-completions.ts"() {
189975
+ "use strict";
189976
+ init_executable_parser();
189977
+ init_project_source_tokens();
189978
+ }
189979
+ });
189980
+
189325
189981
  // ../packages/neoscript-language/src/project-listener-annotations.ts
189326
189982
  function createContext2(analysis, source) {
189327
189983
  const project = cachedProjectIndex(analysis.project);
@@ -189336,10 +189992,25 @@ function createContext2(analysis, source) {
189336
189992
  } : {}
189337
189993
  };
189338
189994
  const resolver = new StrictNeoScriptResolver(context, project);
189995
+ const parameterContexts = /* @__PURE__ */ new Map();
189339
189996
  const parameterResolvers = /* @__PURE__ */ new Map();
189997
+ function parameterContext(constructorIndex) {
189998
+ const key = constructorIndex ?? -1;
189999
+ const cached = parameterContexts.get(key);
190000
+ if (cached) return cached;
190001
+ const declared = constructorIndex === void 0 ? source?.headerParameters : source?.constructors[constructorIndex]?.parameters;
190002
+ const parameters = declared?.flatMap((parameter4) => {
190003
+ const type2 = resolveSourceType(parameter4.type, context, project);
190004
+ return type2 ? [{ name: parameter4.name, type: type2 }] : [];
190005
+ });
190006
+ const created = parameters?.length ? { ...context, parameters } : context;
190007
+ parameterContexts.set(key, created);
190008
+ return created;
190009
+ }
189340
190010
  return {
189341
190011
  context,
189342
190012
  project,
190013
+ parameterContext,
189343
190014
  provide: createListenerAnnotationProvider(project, context),
189344
190015
  resolver,
189345
190016
  /**
@@ -189352,14 +190023,8 @@ function createContext2(analysis, source) {
189352
190023
  const key = constructorIndex ?? -1;
189353
190024
  const cached = parameterResolvers.get(key);
189354
190025
  if (cached) return cached;
189355
- const declared = constructorIndex === void 0 ? source?.headerParameters : source?.constructors[constructorIndex]?.parameters;
189356
- const parameters = declared?.flatMap(
189357
- (parameter4) => {
189358
- const type2 = resolveSourceType(parameter4.type, context, project);
189359
- return type2 ? [{ name: parameter4.name, type: type2 }] : [];
189360
- }
189361
- );
189362
- const created = parameters?.length ? new StrictNeoScriptResolver({ ...context, parameters }, project) : resolver;
190026
+ const scoped = parameterContext(constructorIndex);
190027
+ const created = scoped !== context ? new StrictNeoScriptResolver(scoped, project) : resolver;
189363
190028
  parameterResolvers.set(key, created);
189364
190029
  return created;
189365
190030
  }
@@ -189367,9 +190032,17 @@ function createContext2(analysis, source) {
189367
190032
  }
189368
190033
  function listenerSourceContext(analysis, document, position) {
189369
190034
  const source = analysis.documents.get(document.uri);
189370
- const declaring = source?.declarations.find(
189371
- (declaration) => declaration.kind === "class" && rangeContains(declaration.range, position)
189372
- );
190035
+ const declarations = source?.declarations ?? [];
190036
+ let low = 0;
190037
+ let high = declarations.length;
190038
+ while (low < high) {
190039
+ const middle = low + high >>> 1;
190040
+ if (positionCompare(declarations[middle].range.end, position) < 0)
190041
+ low = middle + 1;
190042
+ else high = middle;
190043
+ }
190044
+ const candidate = declarations[low];
190045
+ const declaring = candidate?.kind === "class" && rangeContains(candidate.range, position) ? candidate : void 0;
189373
190046
  const name = declaring?.name;
189374
190047
  let contexts = CONTEXTS.get(analysis);
189375
190048
  if (!contexts) {
@@ -189400,6 +190073,20 @@ function sourceTypeAst(type2) {
189400
190073
  column: type2.range.start.character + 1
189401
190074
  }
189402
190075
  };
190076
+ if (type2.tupleElements)
190077
+ return {
190078
+ ...common,
190079
+ kind: "tuple",
190080
+ elements: type2.tupleElements.map((element) => {
190081
+ const nested = sourceTypeAst(element.type);
190082
+ return {
190083
+ type: nested,
190084
+ pos: nested.pos,
190085
+ ...element.name ? { name: element.name } : {},
190086
+ ...element.nameRange ? { nameRange: element.nameRange } : {}
190087
+ };
190088
+ })
190089
+ };
189403
190090
  const args = type2.typeArguments;
189404
190091
  if ((type2.name === "List" || type2.name === "Set") && args[0])
189405
190092
  return {
@@ -189600,6 +190287,224 @@ var init_project_listener_annotations = __esm({
189600
190287
  }
189601
190288
  });
189602
190289
 
190290
+ // ../packages/neoscript-language/src/project-annotation-path-completions.ts
190291
+ function annotationSchemaPathCompletions(analysis, document, position, site, field, tokens, next) {
190292
+ const kind = annotationSchemaPathKind(site.annotation.name, field);
190293
+ if (!kind) return null;
190294
+ const entryMember = kind === "member";
190295
+ const collection = kind === "collection";
190296
+ const atCursor = projectTokenAt(document, position);
190297
+ if (atCursor?.kind === "comment" || atCursor?.kind === "string") return [];
190298
+ if (next && positionCompare(position, next.range.start) < 0 && ![",", ")"].includes(next.text))
190299
+ return [];
190300
+ const { context, project } = listenerSourceContext(
190301
+ analysis,
190302
+ document,
190303
+ position
190304
+ );
190305
+ const targetType = annotationTargetType(site, context, project);
190306
+ let receiver;
190307
+ let word;
190308
+ if (entryMember) {
190309
+ if (tokens.length > 1) return [];
190310
+ receiver = targetType ? neoScriptMemberLookupType(targetType) : void 0;
190311
+ word = tokens[0];
190312
+ } else {
190313
+ if (tokens.length > 3) return [];
190314
+ if (tokens.length >= 2) {
190315
+ if (tokens[1]?.text !== ".") return [];
190316
+ const owner = project.typeByName.get(tokens[0].text);
190317
+ if (!owner || owner.kind !== "class") return [];
190318
+ receiver = { kind: "named", typeId: owner.id };
190319
+ word = tokens[2];
190320
+ } else {
190321
+ word = tokens[0];
190322
+ }
190323
+ }
190324
+ if (word && word.kind !== "identifier" && word.kind !== "type") return [];
190325
+ if (word && positionCompare(word.range.end, position) < 0) return [];
190326
+ const editingWord = word ?? (atCursor?.kind === "identifier" || atCursor?.kind === "type" ? atCursor : void 0);
190327
+ const range2 = editingWord?.range ?? { start: position, end: position };
190328
+ const sources2 = entryMember && site.annotation.name === "index" ? sourceMembers(analysis) : null;
190329
+ const enums = {
190330
+ has: (name) => project.typeByName.get(name)?.kind === "enum"
190331
+ };
190332
+ const isClass = (value) => {
190333
+ const bound = neoScriptMemberLookupType(value);
190334
+ return bound.kind === "named" && project.typeById.get(bound.typeId)?.kind === "class";
190335
+ };
190336
+ const eligible = (symbol, type2) => {
190337
+ if (symbol.static || symbol.kind !== "field" && symbol.kind !== "property")
190338
+ return false;
190339
+ if (entryMember && site.annotation.name === "index") {
190340
+ const source = symbol.selectionLocation;
190341
+ const member = source ? sources2?.get(locationKey2(source.uri, source.range.start)) : void 0;
190342
+ if (!member) return false;
190343
+ let name = type2.kind;
190344
+ if (type2.kind === "primitive") name = type2.name;
190345
+ else if (type2.kind === "named")
190346
+ name = project.typeById.get(type2.typeId)?.name ?? type2.typeId;
190347
+ return indexKeyDomainError(member, { name }, enums) === null;
190348
+ }
190349
+ if (!collection) return true;
190350
+ const entry = collectionElement(type2);
190351
+ if (!entry) return false;
190352
+ if (!targetType) return true;
190353
+ const classes = isClass(targetType) && isClass(entry);
190354
+ return isNeoScriptTypeAssignable(
190355
+ { ...classes ? targetType : entry, nullable: false },
190356
+ { ...classes ? entry : targetType, nullable: false },
190357
+ project
190358
+ );
190359
+ };
190360
+ const items = [];
190361
+ if (receiver?.kind === "named") {
190362
+ const owner = project.typeById.get(receiver.typeId);
190363
+ if (!owner) return [];
190364
+ for (const symbol of owner.members) {
190365
+ const type2 = substituteTypeParameters(
190366
+ symbol.type,
190367
+ receiver,
190368
+ owner,
190369
+ project
190370
+ );
190371
+ if (!eligible(symbol, type2)) continue;
190372
+ items.push({
190373
+ label: symbol.name,
190374
+ kind: "property",
190375
+ detail: formatType(type2, project),
190376
+ symbolId: symbol.id,
190377
+ insertText: symbol.name,
190378
+ textEdit: { range: range2, newText: symbol.name }
190379
+ });
190380
+ }
190381
+ } else if (!entryMember) {
190382
+ for (const owner of project.typeById.values()) {
190383
+ if (owner.kind !== "class" || !owner.location) continue;
190384
+ if (!owner.members.some((member) => eligible(member, member.type)))
190385
+ continue;
190386
+ items.push({
190387
+ label: owner.name,
190388
+ kind: "class",
190389
+ insertText: owner.name,
190390
+ textEdit: { range: range2, newText: owner.name }
190391
+ });
190392
+ }
190393
+ }
190394
+ if (entryMember && site.annotation.name === "column") {
190395
+ items.push({
190396
+ label: "__other__",
190397
+ kind: "property",
190398
+ detail: "Inherited columns",
190399
+ insertText: "__other__",
190400
+ textEdit: { range: range2, newText: "__other__" }
190401
+ });
190402
+ }
190403
+ return items;
190404
+ }
190405
+ function annotationSchemaPathKind(annotation2, field) {
190406
+ if (field === "member" && (annotation2 === "index" || annotation2 === "column"))
190407
+ return "member";
190408
+ if (annotation2 === "settings" && (field === "collection" || field === "target"))
190409
+ return field;
190410
+ return null;
190411
+ }
190412
+ function annotationTargetType(site, context, project) {
190413
+ const declared = site.type ? resolveSourceType(site.type, context, project) : null;
190414
+ const resolved = declared?.kind === "reference" ? declared.target : declared;
190415
+ return resolved ? collectionElement(resolved) ?? resolved : null;
190416
+ }
190417
+ function annotationSchemaPathTarget(analysis, document, token, site) {
190418
+ const argumentIndex = site.annotation.arguments.findIndex(
190419
+ (argument3) => rangeContains(argument3.range, token.range.start)
190420
+ );
190421
+ const argument2 = site.annotation.arguments[argumentIndex];
190422
+ if (!argument2) return void 0;
190423
+ const field = argument2.name ?? site.fields[argumentIndex]?.name;
190424
+ const kind = field && annotationSchemaPathKind(site.annotation.name, field);
190425
+ if (!kind) return void 0;
190426
+ const allTokens = projectTokens(document);
190427
+ const tokens = [];
190428
+ for (let index = projectTokenIndexAt(document, argument2.range.start); index < allTokens.length; index++) {
190429
+ const current = allTokens[index];
190430
+ if (positionCompare(current.range.start, argument2.range.end) >= 0) break;
190431
+ if (current.kind !== "comment") tokens.push(current);
190432
+ }
190433
+ if (tokens[1]?.text === ":") tokens.splice(0, 2);
190434
+ const { context, project } = listenerSourceContext(
190435
+ analysis,
190436
+ document,
190437
+ token.range.start
190438
+ );
190439
+ let receiver;
190440
+ if (kind === "member") {
190441
+ if (tokens.length !== 1 || tokens[0] !== token || site.annotation.name === "column" && token.text === "__other__")
190442
+ return null;
190443
+ receiver = annotationTargetType(site, context, project);
190444
+ } else {
190445
+ const owner2 = project.typeByName.get(tokens[0]?.text ?? "");
190446
+ if (!owner2 || owner2.kind !== "class") return null;
190447
+ if (tokens[0] === token) return owner2;
190448
+ if (tokens.length !== 3 || tokens[1]?.text !== "." || tokens[2] !== token)
190449
+ return null;
190450
+ receiver = { kind: "named", typeId: owner2.id };
190451
+ }
190452
+ if (!receiver) return null;
190453
+ const bound = neoScriptMemberLookupType(receiver);
190454
+ const owner = bound.kind === "named" ? project.typeById.get(bound.typeId) : void 0;
190455
+ return owner ? schemaMembers(owner).get(token.text) ?? null : null;
190456
+ }
190457
+ function schemaMembers(owner) {
190458
+ const cached = SCHEMA_MEMBERS.get(owner);
190459
+ if (cached) return cached;
190460
+ const members2 = /* @__PURE__ */ new Map();
190461
+ for (const member of owner.members) {
190462
+ if (member.static || member.kind !== "field" && member.kind !== "property")
190463
+ continue;
190464
+ if (!members2.has(member.name)) members2.set(member.name, member);
190465
+ }
190466
+ SCHEMA_MEMBERS.set(owner, members2);
190467
+ return members2;
190468
+ }
190469
+ function collectionElement(type2) {
190470
+ if (type2.kind === "list" || type2.kind === "set") return type2.elementType;
190471
+ if (type2.kind === "dictionary") return type2.valueType;
190472
+ return null;
190473
+ }
190474
+ function sourceMembers(analysis) {
190475
+ let members2 = SOURCE_MEMBERS.get(analysis);
190476
+ if (!members2) {
190477
+ const result = /* @__PURE__ */ new Map();
190478
+ for (const [uri, document] of analysis.documents) {
190479
+ for (const declaration of document.declarations) {
190480
+ if (declaration.kind === "global" || declaration.kind === "enum")
190481
+ continue;
190482
+ for (const member of declaration.members)
190483
+ result.set(locationKey2(uri, member.nameRange.start), member);
190484
+ }
190485
+ }
190486
+ members2 = result;
190487
+ SOURCE_MEMBERS.set(analysis, members2);
190488
+ }
190489
+ return members2;
190490
+ }
190491
+ function locationKey2(uri, position) {
190492
+ return `${uri}:${position.line}:${position.character}`;
190493
+ }
190494
+ var SCHEMA_MEMBERS, SOURCE_MEMBERS;
190495
+ var init_project_annotation_path_completions = __esm({
190496
+ "../packages/neoscript-language/src/project-annotation-path-completions.ts"() {
190497
+ "use strict";
190498
+ init_project_source_semantics();
190499
+ init_project_listener_annotations();
190500
+ init_project_source_tokens();
190501
+ init_project2();
190502
+ init_type_substitution();
190503
+ SCHEMA_MEMBERS = /* @__PURE__ */ new WeakMap();
190504
+ SOURCE_MEMBERS = /* @__PURE__ */ new WeakMap();
190505
+ }
190506
+ });
190507
+
189603
190508
  // ../packages/neoscript-language/src/project-source-lifecycle-editor.ts
189604
190509
  function projectLifecycleHooks(analysis) {
189605
190510
  let hooks = PROJECT_LIFECYCLE_HOOKS.get(analysis);
@@ -190062,6 +190967,66 @@ function projectDiagnostics(analysis, uri) {
190062
190967
  }));
190063
190968
  }
190064
190969
  function projectCompletions(analysis, document, position) {
190970
+ const result = projectCompletionsAt(analysis, document, position);
190971
+ const referenceNames = projectReferenceArgumentCompletions(
190972
+ analysis,
190973
+ document,
190974
+ position
190975
+ );
190976
+ return referenceNames.length ? { ...result, items: [...referenceNames, ...result.items] } : result;
190977
+ }
190978
+ function projectReferenceArgumentCompletions(analysis, document, position) {
190979
+ if (projectTokenAt(document, position)?.kind === "comment") return [];
190980
+ const documentTokens = projectSignificantTokens(analysis, document);
190981
+ const tokens = tokensBeforePosition(documentTokens, position);
190982
+ const openIndex = activeCallOpenIndex(tokens, position);
190983
+ if (openIndex < 0) return [];
190984
+ const calleeIndex = projectCallCalleeIndex(tokens, openIndex);
190985
+ if (tokens[calleeIndex]?.text !== "Reference" || tokens[calleeIndex + 1]?.text !== "<")
190986
+ return [];
190987
+ if ([".", "?.", "new"].includes(tokens[calleeIndex - 1]?.text ?? ""))
190988
+ return [];
190989
+ const active = activeCallArgument(tokens, openIndex, position);
190990
+ if (active.label !== null) return [];
190991
+ if (tokens.length > active.start + 1) return [];
190992
+ const args = projectCallArguments(documentTokens, openIndex);
190993
+ let field;
190994
+ if (active.index === 0) field = { name: "id", type: "string" };
190995
+ else if (active.index === 1 && args[0]?.name === "id") {
190996
+ const source = analysis.documents.get(document.uri);
190997
+ if (source?.listenerStatements?.some(
190998
+ (statement) => rangeContains(statement.range, position)
190999
+ ))
191000
+ return [];
191001
+ const before = tokens[calleeIndex - 1];
191002
+ if (before?.text === ")" && !initializerRootAt(analysis, document, position) && !projectBodySnapshotAt(analysis, document, position)) {
191003
+ const annotationOpen = activeCallOpenIndex(
191004
+ tokens.slice(0, calleeIndex - 1),
191005
+ before.range.start
191006
+ );
191007
+ if (tokens[annotationOpen - 1]?.text === "listeners" && tokens[annotationOpen - 2]?.text === "@")
191008
+ return [];
191009
+ }
191010
+ const target = tokens[calleeIndex + 2]?.text;
191011
+ if (target === "NeoImage" || target === "NeoAudioClip") return [];
191012
+ field = { name: "withProvenance", type: "bool", defaultText: "false" };
191013
+ } else return [];
191014
+ if (args.some(
191015
+ (argument2) => argument2.index !== active.index && argument2.name === field.name
191016
+ ))
191017
+ return [];
191018
+ return argumentNameCompletions(
191019
+ [field],
191020
+ documentTokens,
191021
+ active.start,
191022
+ tokens.length,
191023
+ position
191024
+ );
191025
+ }
191026
+ function projectCompletionsAt(analysis, document, position) {
191027
+ if (projectTokenAt(document, position)?.kind === "comment") {
191028
+ return { isIncomplete: false, items: [] };
191029
+ }
190065
191030
  const variantPathInBody = projectVariantPathCompletions(
190066
191031
  analysis,
190067
191032
  document,
@@ -190078,9 +191043,16 @@ function projectCompletions(analysis, document, position) {
190078
191043
  const body = projectBodySnapshotAt(analysis, document, position);
190079
191044
  if (body) {
190080
191045
  const script = complete(body, position);
190081
- return variantScopeInBody === null ? script : {
191046
+ const names2 = projectConstructorArgumentCompletions(
191047
+ analysis,
191048
+ document,
191049
+ position,
191050
+ body
191051
+ );
191052
+ const items = names2?.length ? [...names2, ...script.items] : script.items;
191053
+ return variantScopeInBody === null ? { ...script, items } : {
190082
191054
  ...script,
190083
- items: [...script.items, variantScopeInBody]
191055
+ items: [...items, variantScopeInBody]
190084
191056
  };
190085
191057
  }
190086
191058
  const groupMembers = dialogueGroupCompletions(analysis, document, position);
@@ -190109,6 +191081,48 @@ function projectCompletions(analysis, document, position) {
190109
191081
  const targets = listenerHandlerCompletions(listener, document);
190110
191082
  if (targets) return { isIncomplete: false, items: targets };
190111
191083
  }
191084
+ const source = analysis.documents.get(document.uri);
191085
+ const annotationSite = source ? contextualAnnotationSite(source, position) : null;
191086
+ if (annotationSite) {
191087
+ const schemaPath = projectAnnotationSchemaCompletions(
191088
+ analysis,
191089
+ document,
191090
+ position,
191091
+ annotationSite
191092
+ );
191093
+ if (schemaPath !== null) return { isIncomplete: false, items: schemaPath };
191094
+ }
191095
+ const expression = projectExpressionSnapshotAt(
191096
+ analysis,
191097
+ document,
191098
+ position,
191099
+ annotationSite
191100
+ );
191101
+ const lambda = expression && completeLambdaBody(expression.snapshot, position);
191102
+ if (lambda && expression) {
191103
+ const members3 = projectInitializerMemberCompletions(
191104
+ analysis,
191105
+ document,
191106
+ position,
191107
+ expression.snapshot
191108
+ );
191109
+ if (members3) return { ...lambda, items: members3 };
191110
+ const names2 = projectConstructorArgumentCompletions(
191111
+ analysis,
191112
+ document,
191113
+ position,
191114
+ expression.snapshot
191115
+ );
191116
+ const items = names2?.length ? [...names2, ...lambda.items] : lambda.items;
191117
+ return {
191118
+ ...lambda,
191119
+ items: variantScopeInBody ? [...items, variantScopeInBody] : items
191120
+ };
191121
+ }
191122
+ const typeArgument = expression && completeTypeArgument(expression.snapshot, position);
191123
+ if (typeArgument) return typeArgument;
191124
+ const argument2 = expression && completeFunctionArgument(expression.snapshot, position);
191125
+ if (argument2) return argument2;
190112
191126
  const builtinMembers = projectBuiltinStaticMemberCompletions(
190113
191127
  document,
190114
191128
  position
@@ -190119,6 +191133,18 @@ function projectCompletions(analysis, document, position) {
190119
191133
  items: builtinMembers.map(projectBuiltinCompletionItem)
190120
191134
  };
190121
191135
  }
191136
+ const expressionMembers = projectExpressionMemberCompletions(
191137
+ analysis,
191138
+ document,
191139
+ position,
191140
+ annotationSite
191141
+ );
191142
+ if (expressionMembers) {
191143
+ return variantScopeInBody === null ? expressionMembers : {
191144
+ ...expressionMembers,
191145
+ items: [...expressionMembers.items, variantScopeInBody]
191146
+ };
191147
+ }
190122
191148
  const members2 = projectMemberCompletions(analysis, document, position);
190123
191149
  const variantScope = variantScopeInBody;
190124
191150
  if (members2 || variantScope) {
@@ -190153,43 +191179,16 @@ function projectCompletions(analysis, document, position) {
190153
191179
  }))
190154
191180
  };
190155
191181
  }
190156
- const source = analysis.documents.get(document.uri);
190157
- const annotationFields = source ? contextualAnnotationFields(source, position) : null;
191182
+ const annotationFields = annotationSite?.fields;
190158
191183
  if (annotationFields) {
190159
- const activeOption = activeNamedArgument(document.text, position);
190160
- const activeField = activeOption ? annotationFields.find((field) => field.name === activeOption) : void 0;
190161
- const activeArgument = activeOption ?? activeAnnotationArgumentName(document.text, position);
190162
- if (activeArgument === NEO_VARIANT_FOLDER_SETTING && source) {
190163
- const folders = projectVariantFolderCompletions(
190164
- analysis,
190165
- source,
190166
- position
190167
- );
190168
- if (folders) return { isIncomplete: false, items: folders };
190169
- }
190170
- const enumCases = activeField ? generatedContractEnumCases(activeField.type) : null;
190171
- if (enumCases) {
190172
- return {
190173
- isIncomplete: false,
190174
- items: enumCases.map((name) => ({
190175
- label: `.${name}`,
190176
- kind: "enumMember",
190177
- ...activeField ? { detail: activeField.type } : {},
190178
- // The active-option matcher requires the contextual dot to have
190179
- // already been authored. VS Code replaces only the identifier word,
190180
- // so inserting another dot would produce `..Option`.
190181
- insertText: name
190182
- }))
190183
- };
190184
- }
190185
191184
  return {
190186
191185
  isIncomplete: false,
190187
- items: annotationFields.map((field) => ({
190188
- label: field.name,
190189
- kind: "property",
190190
- detail: field.type,
190191
- insertText: `${field.name}: `
190192
- }))
191186
+ items: projectAnnotationArgumentCompletions(
191187
+ analysis,
191188
+ document,
191189
+ position,
191190
+ annotationFields
191191
+ )
190193
191192
  };
190194
191193
  }
190195
191194
  const contextualEnum = projectContextualEnumCompletions(
@@ -190200,22 +191199,15 @@ function projectCompletions(analysis, document, position) {
190200
191199
  if (contextualEnum) {
190201
191200
  return { isIncomplete: false, items: contextualEnum };
190202
191201
  }
190203
- const constructorFields = projectConstructorArgumentCompletions(
191202
+ const constructorNames = projectConstructorArgumentCompletions(
190204
191203
  analysis,
190205
191204
  document,
190206
191205
  position
190207
191206
  );
190208
- if (constructorFields) {
191207
+ if (constructorNames) {
190209
191208
  return {
190210
191209
  isIncomplete: false,
190211
- items: constructorFields.map((field) => ({
190212
- label: field.name,
190213
- kind: "property",
190214
- // P65 §6. C#-style square brackets mark a defaulted parameter as
190215
- // omittable at the call site.
190216
- detail: field.defaultText === void 0 ? field.type : `[${field.type} = ${field.defaultText}]`,
190217
- insertText: `${field.name}: `
190218
- }))
191210
+ items: constructorNames
190219
191211
  };
190220
191212
  }
190221
191213
  const initializerMembers = projectInitializerMemberCompletions(
@@ -190278,7 +191270,12 @@ function projectAnnotationCompletions(analysis, document, position) {
190278
191270
  return ["id", "listeners"].map((name) => ({
190279
191271
  label: `@${name}`,
190280
191272
  kind: "snippet",
190281
- insertText: name
191273
+ insertText: name,
191274
+ filterText: name,
191275
+ textEdit: {
191276
+ range: source.range(word.start, word.end),
191277
+ newText: name
191278
+ }
190282
191279
  }));
190283
191280
  }
190284
191281
  const names2 = projectAnnotationNamesAt(analysis, document, position);
@@ -190286,6 +191283,7 @@ function projectAnnotationCompletions(analysis, document, position) {
190286
191283
  label: `@${name}`,
190287
191284
  kind: "snippet",
190288
191285
  insertText: name,
191286
+ filterText: name,
190289
191287
  textEdit: {
190290
191288
  range: source.range(word.start, word.end),
190291
191289
  newText: name
@@ -190347,7 +191345,8 @@ function projectDeclarationAnnotationNames(declaration) {
190347
191345
  function projectMemberAnnotationNames(member) {
190348
191346
  const names2 = ["id", "settings", "storage", "distribution"];
190349
191347
  if (member?.kind === "function") names2.push("effect");
190350
- if (member?.type.name === "List") names2.push("index", "column");
191348
+ if (member?.type.name === "List" || member?.type.name === "Set")
191349
+ names2.push("index", "column");
190351
191350
  return names2;
190352
191351
  }
190353
191352
  function projectContextualEnumCompletions(analysis, document, position) {
@@ -190639,6 +191638,90 @@ function projectBodyIndex(analysis, context) {
190639
191638
  }
190640
191639
  return index;
190641
191640
  }
191641
+ function projectExpressionMemberCompletions(analysis, document, position, annotationSite) {
191642
+ const source = projectSourceText(document);
191643
+ const offset = source.offsetAt(position);
191644
+ const word = projectWordRange(document.text, offset);
191645
+ const before = tokensBeforePosition(
191646
+ projectSignificantTokens(analysis, document),
191647
+ source.positionAt(word.start)
191648
+ );
191649
+ const dot = before.at(-1);
191650
+ if (dot?.text !== "." && dot?.text !== "?.") return null;
191651
+ const receiver = before.at(-2);
191652
+ if (!receiver || !(receiver.kind === "identifier" || receiver.kind === "type" || [")", "]", "}", ">", "!", "this", "base", "root"].includes(receiver.text)))
191653
+ return null;
191654
+ const expression = projectExpressionSnapshotAt(
191655
+ analysis,
191656
+ document,
191657
+ dot.range.start,
191658
+ annotationSite,
191659
+ true
191660
+ );
191661
+ if (!expression) return null;
191662
+ const result = complete(expression.snapshot, position);
191663
+ return expression.bounded || result.items.length > 0 ? result : null;
191664
+ }
191665
+ function projectExpressionSnapshotAt(analysis, document, position, annotationSite = null, recover = false) {
191666
+ const source = projectSourceText(document);
191667
+ const root = initializerRootAt(analysis, document, position);
191668
+ const argument2 = annotationSite?.annotation.arguments.find(
191669
+ (argument3) => rangeContains(argument3.range, position)
191670
+ );
191671
+ const range2 = argument2?.range ?? root?.range;
191672
+ if (!range2 && !recover) return null;
191673
+ const cached = range2 && PROJECT_EXPRESSION_SNAPSHOT_CACHE.get(analysis)?.get(document)?.get(range2);
191674
+ if (cached) return { snapshot: cached, bounded: true };
191675
+ const language = listenerSourceContext(analysis, document, position);
191676
+ const staticField = root?.slot.kind === "declared" && root.slot.field?.static;
191677
+ let context = argument2 ? language.context : language.parameterContext(root?.constructorIndex);
191678
+ if (staticField) {
191679
+ const { thisClass: _thisClass, ...staticContext } = language.context;
191680
+ context = { ...staticContext, staticMember: true };
191681
+ }
191682
+ if (root && !argument2) {
191683
+ const expected = constructionSiteAt(analysis, document, root.range.start);
191684
+ if (expected?.expectedTypeRef)
191685
+ context = { ...context, returnType: expected.expectedTypeRef };
191686
+ }
191687
+ const key = range2 ?? context;
191688
+ let documents = PROJECT_EXPRESSION_SNAPSHOT_CACHE.get(analysis);
191689
+ if (!documents) {
191690
+ documents = /* @__PURE__ */ new WeakMap();
191691
+ PROJECT_EXPRESSION_SNAPSHOT_CACHE.set(analysis, documents);
191692
+ }
191693
+ let snapshots = documents.get(document);
191694
+ if (!snapshots) {
191695
+ snapshots = /* @__PURE__ */ new WeakMap();
191696
+ documents.set(document, snapshots);
191697
+ }
191698
+ let snapshot = snapshots.get(key);
191699
+ if (!snapshot) {
191700
+ const initialStart = range2 ? source.offsetAt(range2.start) : 0;
191701
+ let start = initialStart;
191702
+ const end = range2 ? source.offsetAt(range2.end) : document.text.length;
191703
+ const lexed = analysis.documents.get(document.uri)?.syntax ?? lex(document.text);
191704
+ let sliced = sliceLexResult(lexed, start, end);
191705
+ const tokens = sliced.tokens.filter((token) => token.kind !== "comment");
191706
+ if (tokens[1]?.text === ":" || tokens[1]?.text === "=")
191707
+ start = tokens[1].end;
191708
+ else if (tokens[0]?.text === ":" || tokens[0]?.text === "=")
191709
+ start = tokens[0].end;
191710
+ if (start !== initialStart) sliced = sliceLexResult(lexed, start, end);
191711
+ const syntax = analyzeNeoScriptSyntax(document.text, context.kind, sliced);
191712
+ snapshot = {
191713
+ uri: document.uri,
191714
+ expressionRange: source.range(start, end),
191715
+ source: syntax.lexed.source,
191716
+ lexed: syntax.lexed,
191717
+ parsed: syntax.parsed,
191718
+ context,
191719
+ project: projectBodyIndex(analysis, context)
191720
+ };
191721
+ snapshots.set(key, snapshot);
191722
+ }
191723
+ return { snapshot, bounded: range2 !== void 0 };
191724
+ }
190642
191725
  function projectWordRange(text, offset) {
190643
191726
  let start = offset;
190644
191727
  while (start > 0 && /[A-Za-z0-9_]/.test(text[start - 1] ?? "")) start--;
@@ -190851,37 +191934,203 @@ function projectBuiltinSymbolSignature(symbol) {
190851
191934
  }
190852
191935
  return `${formatType(symbol.type)} ${symbol.name}`;
190853
191936
  }
190854
- function projectConstructorArgumentCompletions(analysis, document, position) {
191937
+ function projectAnnotationSchemaCompletions(analysis, document, position, site) {
191938
+ const documentTokens = projectSignificantTokens(analysis, document);
191939
+ const tokens = tokensBeforePosition(documentTokens, position);
191940
+ const openIndex = activeCallOpenIndex(tokens, position);
191941
+ if (openIndex < 0 || tokens[openIndex - 2]?.text !== "@") return null;
191942
+ const active = activeCallArgument(tokens, openIndex, position);
191943
+ if (active.label === null && callArgumentLabel(documentTokens, active.start, documentTokens.length) !== null)
191944
+ return null;
191945
+ const field = active.label === null ? site.fields[active.index] : site.fields.find((field2) => field2.name === active.label);
191946
+ if (!field) return null;
191947
+ const start = active.start + (active.label === null ? 0 : 2);
191948
+ if (active.label === null && start === tokens.length) return null;
191949
+ const items = annotationSchemaPathCompletions(
191950
+ analysis,
191951
+ document,
191952
+ position,
191953
+ site,
191954
+ field.name,
191955
+ documentTokens.slice(start, tokens.length),
191956
+ documentTokens[tokens.length]
191957
+ );
191958
+ if (items === null || active.label !== null) return items;
191959
+ return [
191960
+ ...items,
191961
+ ...projectAnnotationArgumentCompletions(
191962
+ analysis,
191963
+ document,
191964
+ position,
191965
+ site.fields
191966
+ )
191967
+ ];
191968
+ }
191969
+ function projectAnnotationArgumentCompletions(analysis, document, position, fields) {
191970
+ const documentTokens = projectSignificantTokens(analysis, document);
191971
+ const tokens = tokensBeforePosition(documentTokens, position);
191972
+ const openIndex = activeCallOpenIndex(tokens, position);
191973
+ if (openIndex < 0 || tokens[openIndex - 2]?.text !== "@") return [];
191974
+ const active = activeCallArgument(tokens, openIndex, position);
191975
+ let valueItems = [];
191976
+ const named = callArgumentLabel(
191977
+ documentTokens,
191978
+ active.start,
191979
+ documentTokens.length
191980
+ );
191981
+ if (active.label !== null || named === null) {
191982
+ const field = active.label === null ? fields[active.index] : fields.find((field2) => field2.name === active.label);
191983
+ const start = active.start + (active.label === null ? 0 : 2);
191984
+ if (field && (active.label !== null || start < tokens.length)) {
191985
+ const values = projectAnnotationValueCompletions(
191986
+ analysis,
191987
+ document,
191988
+ position,
191989
+ documentTokens,
191990
+ tokens,
191991
+ start,
191992
+ field
191993
+ );
191994
+ if (values !== null) {
191995
+ if (active.label !== null || tokens[start]?.text === ".") return values;
191996
+ valueItems = values;
191997
+ }
191998
+ }
191999
+ }
192000
+ if (active.label !== null) return valueItems;
192001
+ const first = documentTokens[active.start];
192002
+ if (tokens.length > active.start + 1) return valueItems;
192003
+ if (tokens.length > active.start && (!first || !isCallArgumentLabelToken(first)))
192004
+ return valueItems;
192005
+ const used = /* @__PURE__ */ new Set();
192006
+ const args = projectCallArguments(documentTokens, openIndex);
192007
+ for (let index = 0; index < args.length; index++) {
192008
+ const argument2 = args[index];
192009
+ if (first && positionCompare(argument2.start, first.range.start) === 0) {
192010
+ continue;
192011
+ }
192012
+ const name = argument2.name ?? fields[index]?.name;
192013
+ if (name !== void 0) used.add(name);
192014
+ }
192015
+ return [
192016
+ ...argumentNameCompletions(
192017
+ fields.filter((field) => !used.has(field.name)).map((field) => ({
192018
+ ...field,
192019
+ type: formatAnnotationValueType(field.type)
192020
+ })),
192021
+ documentTokens,
192022
+ active.start,
192023
+ tokens.length,
192024
+ position
192025
+ ),
192026
+ ...valueItems
192027
+ ];
192028
+ }
192029
+ function projectAnnotationValueCompletions(analysis, document, position, documentTokens, tokens, start, field) {
192030
+ const dot = tokens[start]?.text === ".";
192031
+ const wordIndex = start + (dot ? 1 : 0);
192032
+ if (tokens.length > wordIndex + 1) return [];
192033
+ const word = documentTokens[wordIndex];
192034
+ const isWord = word?.kind === "identifier" || word?.text === "true" || word?.text === "false";
192035
+ const editingWord = isWord && positionCompare(word.range.start, position) <= 0 && positionCompare(position, word.range.end) <= 0;
192036
+ if (tokens.length > wordIndex && !editingWord) return [];
192037
+ if (word && !editingWord && ![",", ")"].includes(word.text)) return [];
192038
+ const atCursor = projectTokenAt(document, position);
192039
+ if (atCursor?.kind === "comment" || atCursor?.kind === "string") return [];
192040
+ const range2 = editingWord ? word.range : { start: position, end: position };
192041
+ const enumCases = generatedContractEnumCases(field.type);
192042
+ if (enumCases) {
192043
+ return enumCases.map((name) => {
192044
+ const insertText = dot ? name : `.${name}`;
192045
+ return {
192046
+ label: `.${name}`,
192047
+ kind: "enumMember",
192048
+ detail: field.type,
192049
+ filterText: name,
192050
+ insertText,
192051
+ textEdit: { range: range2, newText: insertText }
192052
+ };
192053
+ });
192054
+ }
192055
+ if (dot) return [];
192056
+ if (field.type === "bool" || field.type === "bool?") {
192057
+ return ["true", "false"].map((name) => ({
192058
+ label: name,
192059
+ kind: "keyword",
192060
+ detail: field.type,
192061
+ insertText: name,
192062
+ textEdit: { range: range2, newText: name }
192063
+ }));
192064
+ }
192065
+ if (field.name === NEO_VARIANT_FOLDER_SETTING) {
192066
+ const source = analysis.documents.get(document.uri);
192067
+ const folders = source ? projectVariantFolderCompletions(analysis, source, position) : null;
192068
+ if (folders)
192069
+ return folders.map((item) => ({
192070
+ ...item,
192071
+ textEdit: { range: range2, newText: item.insertText ?? item.label }
192072
+ }));
192073
+ }
192074
+ return null;
192075
+ }
192076
+ function projectConstructorArgumentCompletions(analysis, document, position, body) {
190855
192077
  const documentTokens = projectSignificantTokens(analysis, document);
190856
192078
  const tokens = tokensBeforePosition(documentTokens, position);
190857
192079
  const openIndex = activeCallOpenIndex(tokens, position);
190858
192080
  if (openIndex < 0) return null;
190859
- const callee = tokens[openIndex - 1];
192081
+ const calleeIndex = projectCallCalleeIndex(tokens, openIndex);
192082
+ const callee = tokens[calleeIndex];
190860
192083
  if (!callee) return null;
190861
- const beforeCallee = tokens[openIndex - 2];
190862
- const typeName = callee.text === "Pause" ? "Pause" : beforeCallee?.text === "new" ? callee.text : callee.text === "new" ? contextualConstructorType(analysis, document, callee.range.start) : null;
192084
+ const beforeCallee = tokens[calleeIndex - 1];
192085
+ const constructorType = body ? constructorTypeAt(body, position) : projectConstructorTypeName(analysis, document, callee, beforeCallee);
192086
+ const typeName = callee.text === "Pause" ? "Pause" : constructorType;
190863
192087
  if (!typeName) return null;
190864
192088
  const active = activeCallArgument(tokens, openIndex, position);
190865
192089
  if (active.label !== null) return null;
190866
- const activeStart = documentTokens[active.start]?.range.start;
190867
- const used = /* @__PURE__ */ new Set();
190868
- for (const { name, start } of projectCallArguments(
192090
+ if (tokens.length > active.start + 1) return null;
192091
+ const args = projectCallArguments(documentTokens, openIndex);
192092
+ const builtin = lookupVariantFolderArgumentFields(typeName) ?? graphConstructorNamedArguments(typeName);
192093
+ const fields = builtin ? unusedConstructorArguments(builtin, args, active.index) : declaredConstructorNamedArguments(analysis, typeName, args, active.index);
192094
+ if (!fields) return null;
192095
+ return argumentNameCompletions(
192096
+ fields,
190869
192097
  documentTokens,
190870
- openIndex
190871
- )) {
190872
- if (name !== null && !(activeStart && positionCompare(start, activeStart) === 0)) {
190873
- used.add(name);
190874
- }
192098
+ active.start,
192099
+ tokens.length,
192100
+ position
192101
+ );
192102
+ }
192103
+ function projectCallCalleeIndex(tokens, openIndex) {
192104
+ if (!/^>+$/.test(tokens[openIndex - 1]?.text ?? "")) return openIndex - 1;
192105
+ let depth = 0;
192106
+ for (let index = openIndex - 1; index >= 0; index--) {
192107
+ const token = tokens[index];
192108
+ if (/^>+$/.test(token.text)) depth += token.text.length;
192109
+ else if (token.text === "<") {
192110
+ if (--depth === 0)
192111
+ return callOpenParenIndex(tokens, index - 1) === openIndex ? index - 1 : -1;
192112
+ } else if (!isCallTypeArgumentToken(token)) return -1;
190875
192113
  }
190876
- const fields = lookupVariantFolderArgumentFields(typeName) ?? graphConstructorNamedArguments(typeName) ?? declaredConstructorNamedArguments(analysis, typeName, used);
190877
- if (!fields) return null;
190878
- return fields.filter((field) => !used.has(field.name));
192114
+ return -1;
192115
+ }
192116
+ function unusedConstructorArguments(fields, args, activeIndex) {
192117
+ const used = /* @__PURE__ */ new Set();
192118
+ for (const argument2 of args) {
192119
+ if (argument2.index === activeIndex) continue;
192120
+ const parameter4 = neoScriptArgumentParameter(
192121
+ fields,
192122
+ argument2.name,
192123
+ argument2.index
192124
+ );
192125
+ if (parameter4) used.add(parameter4.name.toLowerCase());
192126
+ }
192127
+ return fields.filter((field) => !used.has(field.name.toLowerCase()));
190879
192128
  }
190880
192129
  function lookupVariantFolderArgumentFields(typeName) {
190881
192130
  if (typeName !== NEO_LOOKUP_VARIANT_FOLDER_TYPE_NAME) return null;
190882
192131
  return NEO_LOOKUP_VARIANT_FOLDER_CONSTRUCTOR_ARGUMENTS;
190883
192132
  }
190884
- function declaredConstructorNamedArguments(analysis, typeName, used) {
192133
+ function declaredConstructorNamedArguments(analysis, typeName, args, activeIndex) {
190885
192134
  const contract = classConstructionContract(
190886
192135
  projectConstructionIndex(analysis),
190887
192136
  typeName
@@ -190889,17 +192138,28 @@ function declaredConstructorNamedArguments(analysis, typeName, used) {
190889
192138
  if (!contract) return null;
190890
192139
  if (contract.kind === "implicit") return null;
190891
192140
  if (contract.kind === "required") {
190892
- return contract.parameters.map(parameterArgumentField);
192141
+ return unusedConstructorArguments(
192142
+ contract.parameters.map(parameterArgumentField),
192143
+ args,
192144
+ activeIndex
192145
+ );
190893
192146
  }
190894
- const reachable = neoScriptApplicableSignatures(contract.constructors, [
190895
- ...used
190896
- ]);
192147
+ const labels = projectCallArgumentLabels(args, activeIndex);
192148
+ labels[activeIndex] = null;
192149
+ const reachable = neoScriptApplicableSignatures(
192150
+ contract.constructors,
192151
+ labels
192152
+ );
190897
192153
  const selected = reachable.length > 0 ? reachable : contract.constructors;
190898
192154
  const fields = /* @__PURE__ */ new Map();
190899
192155
  for (const constructor2 of selected) {
190900
- for (const parameter4 of constructor2.parameters) {
190901
- if (fields.has(parameter4.name)) continue;
190902
- fields.set(parameter4.name, parameterArgumentField(parameter4));
192156
+ for (const field of unusedConstructorArguments(
192157
+ constructor2.parameters.map(parameterArgumentField),
192158
+ args,
192159
+ activeIndex
192160
+ )) {
192161
+ const key = field.name.toLowerCase();
192162
+ if (!fields.has(key)) fields.set(key, field);
190903
192163
  }
190904
192164
  }
190905
192165
  return [...fields.values()];
@@ -190911,18 +192171,16 @@ function parameterArgumentField(parameter4) {
190911
192171
  ...parameter4.defaultValue === void 0 ? {} : { defaultText: parameter4.defaultValue.text }
190912
192172
  };
190913
192173
  }
190914
- function projectInitializerMemberCompletions(analysis, document, position) {
190915
- const site = constructionSiteAt(analysis, document, position);
190916
- if (!site?.atInitializerKey) return null;
190917
- const typeName = site.initializerTypeName;
190918
- if (typeName === null) return null;
192174
+ function projectInitializerMemberCompletions(analysis, document, position, body) {
192175
+ const site = body ? null : constructionSiteAt(analysis, document, position);
192176
+ const context = body ? initializerKeyContextAt(body, position) : null;
192177
+ const typeName = body ? context?.typeName : site?.initializerTypeName;
192178
+ if (typeName == null) return null;
192179
+ if (!body && !site?.atInitializerKey) return null;
192180
+ const keys = context?.keys ?? site?.initializerKeys ?? [];
190919
192181
  const index = projectConstructionIndex(analysis);
190920
- const unsettled = unsettledRequiredMembers(
190921
- index,
190922
- typeName,
190923
- site.initializerKeys
190924
- );
190925
- const taken = new Set(site.initializerKeys.map((key) => key.toLowerCase()));
192182
+ const unsettled = unsettledRequiredMembers(index, typeName, keys);
192183
+ const taken = new Set(keys.map((key) => key.toLowerCase()));
190926
192184
  for (const member of unsettled) taken.add(member.name.toLowerCase());
190927
192185
  const items = unsettled.map((member) => ({
190928
192186
  label: member.name,
@@ -190972,10 +192230,6 @@ function constructibleMembers(analysis, typeName) {
190972
192230
  function sourceParameterSignatureText(parameter4) {
190973
192231
  return constructorParameterLabel(sourceParameterProjection(parameter4));
190974
192232
  }
190975
- function functionParameterLabel(parameter4) {
190976
- const suffix = parameter4.defaultValue === void 0 ? "" : ` = ${parameter4.defaultValue.text}`;
190977
- return `${parameter4.type.name} ${parameter4.name}${suffix}`;
190978
- }
190979
192233
  function projectConstructionIndex(analysis) {
190980
192234
  const cached = CONSTRUCTION_INDEX_CACHE.get(analysis);
190981
192235
  if (cached) return cached;
@@ -191188,22 +192442,6 @@ function graphConstructorNamedArguments(typeName) {
191188
192442
  return null;
191189
192443
  }
191190
192444
  }
191191
- function activeAnnotationArgumentName(text, position) {
191192
- const lines = text.split("\n");
191193
- const prefix = [
191194
- ...lines.slice(0, position.line),
191195
- (lines[position.line] ?? "").slice(0, position.character)
191196
- ].join("\n");
191197
- return /([A-Za-z_][A-Za-z0-9_]*)\s*:\s*[A-Za-z0-9_]*$/.exec(prefix)?.[1] ?? null;
191198
- }
191199
- function activeNamedArgument(text, position) {
191200
- const lines = text.split("\n");
191201
- const prefix = [
191202
- ...lines.slice(0, position.line),
191203
- (lines[position.line] ?? "").slice(0, position.character)
191204
- ].join("\n");
191205
- return /([A-Za-z_][A-Za-z0-9_]*)\s*:\s*\.[A-Za-z0-9_]*$/.exec(prefix)?.[1] ?? null;
191206
- }
191207
192445
  function referenceHoverText(analysis, symbol, reference2) {
191208
192446
  const storage = `\`${reference2.storage}\``;
191209
192447
  const member = symbol.ownerName === void 0 ? void 0 : cachedProjectIndex(analysis.project).typeByName.get(symbol.ownerName)?.members.find(({ name }) => name === symbol.name);
@@ -191250,7 +192488,20 @@ Requires a list of \`void(${type2})\` method targets. The member name is require
191250
192488
  }
191251
192489
  const body = projectBodySnapshotAt(analysis, document, position);
191252
192490
  if (body) return hover(body, position);
191253
- const builtin = projectBuiltinSymbolAt(document, position);
192491
+ const sourceDocument = analysis.documents.get(document.uri);
192492
+ const annotationSite = sourceDocument ? contextualAnnotationSite(sourceDocument, position) : null;
192493
+ const token = projectTokenAt(document, position);
192494
+ const parameter4 = annotationSite ? annotationParameterHover(document, position, annotationSite) : null;
192495
+ if (parameter4) return parameter4;
192496
+ const schemaPath = annotationSite && token ? annotationSchemaPathTarget(analysis, document, token, annotationSite) : void 0;
192497
+ const expression = schemaPath === void 0 ? projectExpressionSnapshotAt(
192498
+ analysis,
192499
+ document,
192500
+ position,
192501
+ annotationSite
192502
+ ) : null;
192503
+ const inferred = expression ? hover(expression.snapshot, position) : null;
192504
+ const builtin = inferred ? null : projectBuiltinSymbolAt(document, position);
191254
192505
  if (builtin) {
191255
192506
  if (builtin.symbol) {
191256
192507
  const documentation3 = builtin.symbol.documentation ? `
@@ -191276,7 +192527,7 @@ Schema id: \`${builtin.type.id}\``
191276
192527
  };
191277
192528
  }
191278
192529
  const resolved = projectSymbolAt(analysis, document, position);
191279
- if (!resolved) return null;
192530
+ if (!resolved) return inferred;
191280
192531
  const owner = resolved.symbol.ownerName ? ` on \`${resolved.symbol.ownerName}\`` : "";
191281
192532
  const documentation = resolved.symbol.documentation ? `
191282
192533
 
@@ -191291,11 +192542,57 @@ ${referenceHoverText(analysis, resolved.symbol, resolved.symbol.reference)}` : "
191291
192542
  const setStorage = setStorageHoverMarkdown(analysis, resolved.symbol);
191292
192543
  const contract = resolved.symbol.kind === "class" ? projectConstructionContractMarkdown(analysis, resolved.symbol.name) : "";
191293
192544
  const lifecycle = resolved.symbol.kind === "member" && resolved.symbol.callable === true && resolved.symbol.static !== true && analysis.documents.get(resolved.symbol.location.uri)?.kind !== "flow" ? lifecycleHoverMarkdown(analysis, resolved.symbol.name) : "";
192545
+ if (inferred) {
192546
+ return {
192547
+ ...inferred,
192548
+ markdown: `${inferred.markdown}${reference2}${setStorage}${lifecycle}${contract}`
192549
+ };
192550
+ }
191294
192551
  return {
191295
192552
  range: resolved.token.range,
191296
192553
  markdown: `**${resolved.symbol.kind}** \`${resolved.symbol.name}\`${detail}${owner}${reference2}${setStorage}${documentation}${lifecycle}${contract}${id2}`
191297
192554
  };
191298
192555
  }
192556
+ function annotationParameterHover(document, position, site) {
192557
+ const tokens = projectTokens(document);
192558
+ const index = projectTokenIndexAt(document, position);
192559
+ const token = tokens[index];
192560
+ if (!token || !isCallArgumentLabelToken(token)) return null;
192561
+ if (tokens[significantTokenIndex(tokens, index, 1)]?.text !== ":")
192562
+ return null;
192563
+ const previous = significantTokenIndex(tokens, index, -1);
192564
+ if (tokens[previous]?.text !== "(" && tokens[previous]?.text !== ",")
192565
+ return null;
192566
+ const open2 = enclosingOpeners(tokens)[index];
192567
+ const callee = tokens[significantTokenIndex(tokens, open2, -1)];
192568
+ if (!callee || positionCompare(callee.range.start, site.annotation.nameRange.start) !== 0)
192569
+ return null;
192570
+ const field = site.fields.find((field2) => field2.name === token.text);
192571
+ if (!field) return null;
192572
+ const path = annotationSchemaPathKind(site.annotation.name, field.name);
192573
+ let type2 = formatAnnotationValueType(field.type);
192574
+ let description = "";
192575
+ if (path === "member") {
192576
+ type2 = "entry member";
192577
+ description = "Names a member of the collection entry, such as `Slug`.";
192578
+ } else if (path) {
192579
+ type2 = path === "collection" ? "collection path" : "member path";
192580
+ description = "Names a schema member using `Class.Member`.";
192581
+ } else if (site.annotation.name === "settings" && field.name === "collectionValue") {
192582
+ type2 = "collection reference";
192583
+ description = "Selects a collection instance, such as `root.Assets.Items`. The `Reference(...)` wrapper is optional.";
192584
+ }
192585
+ const options = generatedContractEnumCases(field.type);
192586
+ const choices = options?.length ? `
192587
+
192588
+ Values: ${options.map((option) => `\`.${option}\``).join(", ")}.` : "";
192589
+ return {
192590
+ range: token.range,
192591
+ markdown: `\`@${site.annotation.name}(${field.name}: ${type2})\`${description ? `
192592
+
192593
+ ${description}` : ""}${choices}`
192594
+ };
192595
+ }
191299
192596
  function setStorageHoverMarkdown(analysis, symbol) {
191300
192597
  if (symbol.kind !== "member" || symbol.ownerName === void 0) return "";
191301
192598
  const owner = findTypeDeclaration(analysis, symbol.ownerName);
@@ -191467,7 +192764,8 @@ function projectSignatureHelp(analysis, document, position) {
191467
192764
  const openIndex = activeCallOpenIndex(tokens, position);
191468
192765
  if (openIndex < 0) return null;
191469
192766
  const open2 = tokens[openIndex];
191470
- const callee = tokens[openIndex - 1];
192767
+ const calleeIndex = projectCallCalleeIndex(tokens, openIndex);
192768
+ const callee = tokens[calleeIndex];
191471
192769
  if (!open2 || !callee) return null;
191472
192770
  const active = activeCallArgument(tokens, openIndex, position);
191473
192771
  const activeParameter = active.index;
@@ -191476,16 +192774,19 @@ function projectSignatureHelp(analysis, document, position) {
191476
192774
  active.start,
191477
192775
  documentTokens.length
191478
192776
  );
191479
- const beforeCallee = tokens[openIndex - 2];
192777
+ const beforeCallee = tokens[calleeIndex - 1];
191480
192778
  if (beforeCallee?.text === "@") {
191481
- const source = analysis.documents.get(document.uri);
191482
- const contextual = source ? contextualAnnotationFields(source, position) : null;
191483
- const parameters = contextual?.map((field) => `${field.type} ${field.name}`) ?? annotationSignatureParameters(callee.text);
192779
+ const source2 = analysis.documents.get(document.uri);
192780
+ const contextual = source2 ? contextualAnnotationFields(source2, position) : null;
192781
+ const parameters = contextual?.map((field) => ({
192782
+ name: field.name,
192783
+ label: `${formatAnnotationValueType(field.type)} ${field.name}`
192784
+ })) ?? annotationSignatureParameters(callee.text);
191484
192785
  if (!parameters) return null;
191485
192786
  return signatureResult(
191486
192787
  `@${callee.text}`,
191487
- parameters,
191488
- neoScriptClampActiveParameter(activeParameter, parameters.length)
192788
+ parameters.map((parameter4) => parameter4.label),
192789
+ neoScriptActiveParameter(parameters, label, activeParameter)
191489
192790
  );
191490
192791
  }
191491
192792
  if (callee.text === "Reference") {
@@ -191493,7 +192794,11 @@ function projectSignatureHelp(analysis, document, position) {
191493
192794
  return signatureResult(
191494
192795
  "Reference",
191495
192796
  parameters,
191496
- neoScriptClampActiveParameter(activeParameter, parameters.length)
192797
+ neoScriptActiveParameter(
192798
+ [{ name: "id" }, { name: "withProvenance" }],
192799
+ label,
192800
+ activeParameter
192801
+ )
191497
192802
  );
191498
192803
  }
191499
192804
  if (callee.text === "Pause") {
@@ -191513,8 +192818,9 @@ function projectSignatureHelp(analysis, document, position) {
191513
192818
  if (constructorType) {
191514
192819
  const overloads = declaredConstructorOverloads(analysis, constructorType);
191515
192820
  if (overloads) {
191516
- const labels = projectCallArguments(documentTokens, openIndex).map(
191517
- ({ name }) => name
192821
+ const labels = projectCallArgumentLabels(
192822
+ projectCallArguments(documentTokens, openIndex),
192823
+ activeParameter
191518
192824
  );
191519
192825
  return constructorOverloadSignatures(
191520
192826
  constructorType,
@@ -191531,25 +192837,15 @@ function projectSignatureHelp(analysis, document, position) {
191531
192837
  neoScriptActiveParameter(parameters, label, activeParameter)
191532
192838
  );
191533
192839
  }
191534
- const functions = projectFunctionsNamed(analysis, callee.text);
191535
- if (functions.length === 0) return null;
191536
- return {
191537
- signatures: functions.map(({ owner, member }) => {
191538
- const parameters = member.parameters.map(functionParameterLabel);
191539
- return {
191540
- label: `${member.type.name} ${owner}.${member.name}(${parameters.join(", ")})`,
191541
- parameters: member.parameters.map((parameter4) => ({
191542
- label: functionParameterLabel(parameter4)
191543
- }))
191544
- };
191545
- }),
191546
- activeSignature: 0,
191547
- activeParameter: neoScriptActiveParameter(
191548
- functions[0].member.parameters,
191549
- label,
191550
- activeParameter
191551
- )
191552
- };
192840
+ const source = analysis.documents.get(document.uri);
192841
+ const expression = projectExpressionSnapshotAt(
192842
+ analysis,
192843
+ document,
192844
+ callee.range.start,
192845
+ source ? contextualAnnotationSite(source, callee.range.start) : null,
192846
+ true
192847
+ );
192848
+ return expression ? signatureHelp(expression.snapshot, position) : null;
191553
192849
  }
191554
192850
  function declaredConstructorOverloads(analysis, typeName) {
191555
192851
  if (lookupVariantFolderArgumentFields(typeName) !== null) return null;
@@ -191581,25 +192877,21 @@ function projectInlayHints(analysis, document, range2) {
191581
192877
  );
191582
192878
  const delimiterEnds = projectDelimiterEnds(tokens);
191583
192879
  const hints = [];
191584
- for (let index = 0; index < tokens.length - 1; index++) {
191585
- const callee = tokens[index];
191586
- const open2 = tokens[index + 1];
192880
+ for (let index = 0; index < tokens.length; index++) {
192881
+ if (tokens[index]?.text !== "(") continue;
192882
+ const calleeIndex = projectCallCalleeIndex(tokens, index);
192883
+ const callee = tokens[calleeIndex];
191587
192884
  if (!callee || callee.kind !== "identifier" && callee.kind !== "type") {
191588
192885
  continue;
191589
192886
  }
191590
192887
  if (rangeItemAt(bodyContexts, callee.range.start)) {
191591
192888
  continue;
191592
192889
  }
191593
- if (!open2 || open2.text !== "(") continue;
191594
- const beforeCallee = tokens[index - 1];
192890
+ const beforeCallee = tokens[calleeIndex - 1];
191595
192891
  if (beforeCallee?.text === "@") continue;
191596
192892
  if (declarationNames.has(positionKey(callee.range.start))) continue;
191597
192893
  if (range2 && positionCompare(callee.range.start, range2.end) > 0) break;
191598
- const callArguments2 = projectCallArguments(
191599
- tokens,
191600
- index + 1,
191601
- delimiterEnds
191602
- );
192894
+ const callArguments2 = projectCallArguments(tokens, index, delimiterEnds);
191603
192895
  if (range2 && !callArguments2.some((argument2) => rangeContains(range2, argument2.start)))
191604
192896
  continue;
191605
192897
  const parameterNames = projectCallParameterNames(
@@ -191612,7 +192904,7 @@ function projectInlayHints(analysis, document, range2) {
191612
192904
  for (let argument2 = 0; argument2 < callArguments2.length; argument2++) {
191613
192905
  const argumentToken = callArguments2[argument2];
191614
192906
  if (!argumentToken || argumentToken.name !== null) continue;
191615
- const name = parameterNames[argument2];
192907
+ const name = parameterNames[argumentToken.index];
191616
192908
  if (!name) continue;
191617
192909
  if (argumentToken.identifier && normalizeProjectHintName(argumentToken.identifier) === normalizeProjectHintName(name)) {
191618
192910
  continue;
@@ -191656,22 +192948,34 @@ function projectCallParameterNames(analysis, document, callee, beforeCallee) {
191656
192948
  beforeCallee
191657
192949
  );
191658
192950
  if (constructorType) {
192951
+ const overloads = declaredConstructorOverloads(analysis, constructorType);
192952
+ if (overloads) return neoScriptCommonParameterNames(overloads);
191659
192953
  const parameters = projectConstructorParameters(analysis, constructorType);
191660
192954
  if (parameters.length === 0) return null;
191661
192955
  return parameters.map((parameter4) => parameter4.name);
191662
192956
  }
191663
- const functions = projectFunctionsNamed(analysis, callee.text);
191664
- if (functions.length === 0) return null;
191665
- const arity = Math.max(
191666
- ...functions.map(({ member }) => member.parameters.length)
192957
+ const source = analysis.documents.get(document.uri);
192958
+ const expression = projectExpressionSnapshotAt(
192959
+ analysis,
192960
+ document,
192961
+ callee.range.start,
192962
+ source ? contextualAnnotationSite(source, callee.range.start) : null,
192963
+ true
191667
192964
  );
191668
- return Array.from({ length: arity }, (_, parameterIndex) => {
191669
- const names2 = new Set(
191670
- functions.map(({ member }) => member.parameters[parameterIndex]?.name)
191671
- );
191672
- const [name] = names2;
191673
- return names2.size === 1 && name ? name : null;
191674
- });
192965
+ if (expression) {
192966
+ return callParametersAt(expression.snapshot, callee.range.start)?.map(
192967
+ (parameter4) => parameter4.name
192968
+ ) ?? null;
192969
+ }
192970
+ return null;
192971
+ }
192972
+ function projectCallArgumentLabels(args, activeIndex) {
192973
+ const labels = Array.from(
192974
+ { length: Math.max(activeIndex + 1, (args.at(-1)?.index ?? -1) + 1) },
192975
+ () => null
192976
+ );
192977
+ for (const argument2 of args) labels[argument2.index] = argument2.name;
192978
+ return labels;
191675
192979
  }
191676
192980
  function projectDelimiterEnds(tokens) {
191677
192981
  const ends = /* @__PURE__ */ new Map();
@@ -191689,6 +192993,7 @@ function projectDelimiterEnds(tokens) {
191689
192993
  function projectCallArguments(tokens, openIndex, delimiterEnds) {
191690
192994
  const result = [];
191691
192995
  let atArgumentStart = true;
192996
+ let argumentIndex = 0;
191692
192997
  let depth = 0;
191693
192998
  for (let index = openIndex + 1; index < tokens.length; index++) {
191694
192999
  const token = tokens[index];
@@ -191704,11 +193009,13 @@ function projectCallArguments(tokens, openIndex, delimiterEnds) {
191704
193009
  break;
191705
193010
  } else if (depth === 0 && text === ",") {
191706
193011
  atArgumentStart = true;
193012
+ argumentIndex++;
191707
193013
  continue;
191708
193014
  }
191709
193015
  if (atArgumentStart) {
191710
193016
  const name = callArgumentLabel(tokens, index, tokens.length);
191711
193017
  result.push({
193018
+ index: argumentIndex,
191712
193019
  start: token.range.start,
191713
193020
  name,
191714
193021
  ...token.kind === "identifier" && (tokens[index + 1]?.text === "," || tokens[index + 1]?.text === ")") ? { identifier: token.text } : {}
@@ -191717,13 +193024,9 @@ function projectCallArguments(tokens, openIndex, delimiterEnds) {
191717
193024
  }
191718
193025
  if (opens && delimiterEnds) {
191719
193026
  index = delimiterEnds.get(index) ?? tokens.length;
191720
- } else if (text === "new" && tokens[index + 2]?.text === "<") {
191721
- let angles = 0;
191722
- index += 2;
191723
- for (; index < tokens.length; index++) {
191724
- if (tokens[index].text === "<") angles++;
191725
- else if (tokens[index].text === ">" && --angles === 0) break;
191726
- }
193027
+ } else if (tokens[index + 1]?.text === "<") {
193028
+ const open2 = callOpenParenIndex(tokens, index);
193029
+ if (open2 >= 0) index = open2 - 1;
191727
193030
  }
191728
193031
  }
191729
193032
  return result;
@@ -191965,10 +193268,28 @@ function indexedProjectSymbolAt(analysis, document, position, index) {
191965
193268
  const tokenIndex = projectTokenIndexAt(document, position);
191966
193269
  const sourceTokens = projectTokens(document);
191967
193270
  const token = sourceTokens[tokenIndex];
193271
+ const previousIndex = significantTokenIndex(sourceTokens, tokenIndex, -1);
193272
+ const previous = sourceTokens[previousIndex];
191968
193273
  if (!isProjectNameToken(token)) return null;
191969
193274
  if (isAnnotationName(sourceTokens, tokenIndex)) return null;
191970
193275
  const body = projectBodySnapshotAt(analysis, document, position);
191971
- const tupleLabel = body ? tupleLabelSymbolAtPosition(body, position) : null;
193276
+ const sourceDocument = analysis.documents.get(document.uri);
193277
+ const annotationSite = !body && sourceDocument ? contextualAnnotationSite(sourceDocument, position) : null;
193278
+ if (annotationSite) {
193279
+ const target = annotationSchemaPathTarget(
193280
+ analysis,
193281
+ document,
193282
+ token,
193283
+ annotationSite
193284
+ );
193285
+ if (target !== void 0) {
193286
+ const location3 = target?.selectionLocation ?? target?.location;
193287
+ const symbol = location3 && symbolsDeclaredAt(index, location3.uri, location3.range)[0];
193288
+ return symbol ? { token, symbol } : null;
193289
+ }
193290
+ }
193291
+ const executable = body ?? projectExpressionSnapshotAt(analysis, document, position, annotationSite)?.snapshot;
193292
+ const tupleLabel = executable ? tupleLabelSymbolAtPosition(executable, position) : null;
191972
193293
  if (tupleLabel?.location)
191973
193294
  return {
191974
193295
  token,
@@ -191984,8 +193305,8 @@ function indexedProjectSymbolAt(analysis, document, position, index) {
191984
193305
  const symbol = location3 && symbolsDeclaredAt(index, location3.uri, location3.range)[0];
191985
193306
  return symbol ? { token, symbol } : null;
191986
193307
  }
191987
- if (body) {
191988
- const local = localSymbolAtPosition(body, position);
193308
+ if (executable) {
193309
+ const local = localSymbolAtPosition(executable, position);
191989
193310
  if (local?.location) {
191990
193311
  return {
191991
193312
  token,
@@ -191997,10 +193318,10 @@ function indexedProjectSymbolAt(analysis, document, position, index) {
191997
193318
  }
191998
193319
  };
191999
193320
  }
192000
- const reference2 = referenceAtPosition(body, position);
192001
- const symbolId = reference2 ? resolveReferenceSymbolId(body, reference2) : null;
192002
- const executable = symbolId ? body.project.symbolById.get(symbolId) : void 0;
192003
- const location3 = executable?.selectionLocation ?? executable?.location;
193321
+ const reference2 = referenceAtPosition(executable, position);
193322
+ const symbolId = reference2 ? resolveReferenceSymbolId(executable, reference2) : null;
193323
+ const target = symbolId ? executable.project.symbolById.get(symbolId) : void 0;
193324
+ const location3 = target?.selectionLocation ?? target?.location;
192004
193325
  const located = location3 ? symbolsDeclaredAt(index, location3.uri, location3.range)[0] : void 0;
192005
193326
  const symbol = located ?? (symbolId ? index.byId.get(symbolId) : void 0);
192006
193327
  if (symbol) return { token, symbol };
@@ -192021,7 +193342,7 @@ function indexedProjectSymbolAt(analysis, document, position, index) {
192021
193342
  const source = analysis.documents.get(document.uri);
192022
193343
  const typePosition = source && sourceTypeAt(source, token.range.start);
192023
193344
  const inScope = (symbol) => !symbol.scopeRange || symbol.location.uri === document.uri && rangeContains(symbol.scopeRange, token.range.start);
192024
- if (typePosition || sourceTokens[tokenIndex - 1]?.text === "new") {
193345
+ if (typePosition || previous?.text === "new") {
192025
193346
  const types = candidates.filter((symbol) => isProjectTypeSymbol(symbol) && inScope(symbol)).sort(compareScopeSize);
192026
193347
  const innermost = types[0];
192027
193348
  if (innermost?.scopeRange) return { token, symbol: innermost };
@@ -192052,13 +193373,13 @@ function indexedProjectSymbolAt(analysis, document, position, index) {
192052
193373
  if (constructed) return { token, symbol: constructed };
192053
193374
  }
192054
193375
  const owner = source ? declarationContaining(source, token.range.start)?.name : void 0;
192055
- if (owner && sourceTokens[tokenIndex - 1]?.text !== ".") {
193376
+ if (owner && previous?.text !== "." && previous?.text !== "?.") {
192056
193377
  const owned = visibleCandidates.filter(
192057
193378
  (symbol) => symbol.ownerName === owner
192058
193379
  );
192059
193380
  if (owned.length === 1) return { token, symbol: owned[0] };
192060
193381
  }
192061
- const dotOwner = sourceTokens[tokenIndex - 1]?.text === "." ? sourceTokens[tokenIndex - 2] : void 0;
193382
+ const dotOwner = previous?.text === "." || previous?.text === "?." ? sourceTokens[significantTokenIndex(sourceTokens, previousIndex, -1)] : void 0;
192062
193383
  if (dotOwner) {
192063
193384
  const resolvedOwner = indexedProjectSymbolAt(
192064
193385
  analysis,
@@ -192360,6 +193681,10 @@ function activeCallArgument(tokens, openIndex, position) {
192360
193681
  parameter4++;
192361
193682
  start = end + 1;
192362
193683
  }
193684
+ if (tokens[end + 1]?.text === "<") {
193685
+ const open2 = callOpenParenIndex(tokens, end);
193686
+ if (open2 >= 0) end = open2 - 1;
193687
+ }
192363
193688
  }
192364
193689
  return {
192365
193690
  index: parameter4,
@@ -192370,28 +193695,31 @@ function activeCallArgument(tokens, openIndex, position) {
192370
193695
  function annotationSignatureParameters(name) {
192371
193696
  switch (name) {
192372
193697
  case "id":
192373
- return ["string id"];
193698
+ return [{ name: "id", label: "string id" }];
192374
193699
  case "settings":
192375
- return ["named settings"];
193700
+ return [{ name: "", label: "named settings" }];
192376
193701
  case "storage":
192377
- return ["StorageKind allowed"];
193702
+ return [{ name: "allowed", label: "StorageKind allowed" }];
192378
193703
  case "distribution":
192379
- return ["NeoSubtreeDistribution kind"];
193704
+ return [{ name: "kind", label: "NeoSubtreeDistribution kind" }];
192380
193705
  case "effect":
192381
- return ["NeoEffectKind kind"];
193706
+ return [{ name: "kind", label: "NeoEffectKind kind" }];
192382
193707
  case "relations":
192383
- return ["relation descriptors"];
193708
+ return [{ name: "", label: "relation descriptors" }];
192384
193709
  case "incomplete":
192385
- return ["string reason"];
193710
+ return [{ name: "reason", label: "string reason" }];
192386
193711
  case "index":
192387
- return ["entry member", "ListIndexKind kind"];
193712
+ return [
193713
+ { name: "member", label: "entry member" },
193714
+ { name: "kind", label: "ListIndexKind kind" }
193715
+ ];
192388
193716
  case "column":
192389
193717
  return [
192390
- "entry member",
192391
- "int width",
192392
- "ColumnVisibilityKind visibility",
192393
- "ColumnPinKind pin",
192394
- "ColumnOverflowKind overflow"
193718
+ { name: "member", label: "entry member" },
193719
+ { name: "width", label: "int width" },
193720
+ { name: "visibility", label: "ColumnVisibilityKind visibility" },
193721
+ { name: "pin", label: "ColumnPinKind pin" },
193722
+ { name: "overflow", label: "ColumnOverflowKind overflow" }
192395
193723
  ];
192396
193724
  default:
192397
193725
  return null;
@@ -192460,7 +193788,11 @@ function initializerRoots(source) {
192460
193788
  slot: {
192461
193789
  kind: "declared",
192462
193790
  type: member.type,
192463
- field: { owner: declaration.name, name: member.name }
193791
+ field: {
193792
+ owner: declaration.name,
193793
+ name: member.name,
193794
+ static: member.modifiers.includes("static")
193795
+ }
192464
193796
  },
192465
193797
  range: member.initializer.range
192466
193798
  });
@@ -192526,6 +193858,7 @@ function indexConstructionSites(analysis, document, root) {
192526
193858
  end++;
192527
193859
  const tokens = allTokens.slice(start, end).filter((token) => token.kind !== "comment" && token.kind !== "eof");
192528
193860
  let delimiterEnds;
193861
+ const genericCallOpens = constructionGenericCallOpens(tokens);
192529
193862
  const language = listenerSourceContext(analysis, document, root.range.start);
192530
193863
  const sourceType = (type2) => resolveSourceType(type2, language.context, language.project);
192531
193864
  const fieldType = (owner, name) => {
@@ -192578,7 +193911,11 @@ function indexConstructionSites(analysis, document, root) {
192578
193911
  case "object":
192579
193912
  case "list":
192580
193913
  case "dictionary":
193914
+ case "tuple":
193915
+ case "group":
192581
193916
  return frame.slotId;
193917
+ case "switch":
193918
+ return frame.inResult ? frame.slotId : null;
192582
193919
  case "call":
192583
193920
  case "opaque":
192584
193921
  return null;
@@ -192590,7 +193927,12 @@ function indexConstructionSites(analysis, document, root) {
192590
193927
  switch (frame.kind) {
192591
193928
  case "object":
192592
193929
  case "dictionary":
193930
+ case "group":
192593
193931
  return frame.slotTypeRef;
193932
+ case "tuple":
193933
+ return frame.typeRef.elements[frame.elementIndex]?.type ?? null;
193934
+ case "switch":
193935
+ return frame.inResult ? frame.resultTypeRef : null;
192594
193936
  case "list":
192595
193937
  return frame.elementTypeRef;
192596
193938
  case "opaque":
@@ -192628,7 +193970,12 @@ function indexConstructionSites(analysis, document, root) {
192628
193970
  switch (frame.kind) {
192629
193971
  case "object":
192630
193972
  case "dictionary":
193973
+ case "group":
192631
193974
  return frame.slotType;
193975
+ case "tuple":
193976
+ return frame.type?.tupleElements?.[frame.elementIndex]?.type ?? null;
193977
+ case "switch":
193978
+ return frame.inResult ? frame.resultType : null;
192632
193979
  case "list":
192633
193980
  return frame.elementType;
192634
193981
  case "call":
@@ -192725,7 +194072,7 @@ function indexConstructionSites(analysis, document, root) {
192725
194072
  sawNew = true;
192726
194073
  newStart = index;
192727
194074
  pendingNewTypeRef = expectedTypeRef();
192728
- pendingNewTypeName = expectedType()?.name ?? null;
194075
+ pendingNewTypeName = pendingNewTypeRef?.kind === "named" ? language.project.typeById.get(pendingNewTypeRef.typeId)?.name ?? null : expectedType()?.name ?? null;
192729
194076
  closedConstructorTypeName = null;
192730
194077
  continue;
192731
194078
  }
@@ -192763,8 +194110,24 @@ function indexConstructionSites(analysis, document, root) {
192763
194110
  }
192764
194111
  continue;
192765
194112
  }
194113
+ if (!sawNew) {
194114
+ const call = genericCallOpens.get(index) ?? -1;
194115
+ if (call >= 0) {
194116
+ index = call - 1;
194117
+ closedConstructorTypeName = null;
194118
+ continue;
194119
+ }
194120
+ }
192766
194121
  if (token.text === "{") {
192767
- if (sawNew || closedConstructorTypeName !== null) {
194122
+ if (tokens[index - 1]?.text === "switch") {
194123
+ stack.push({
194124
+ kind: "switch",
194125
+ resultType: expectedType(),
194126
+ resultTypeRef: expectedTypeRef(),
194127
+ slotId: expectedSlotId(),
194128
+ inResult: false
194129
+ });
194130
+ } else if (sawNew || closedConstructorTypeName !== null) {
192768
194131
  const frame2 = {
192769
194132
  kind: "object",
192770
194133
  typeName: pendingNewTypeName ?? closedConstructorTypeName,
@@ -192825,7 +194188,33 @@ function indexConstructionSites(analysis, document, root) {
192825
194188
  sawNew = false;
192826
194189
  pendingNewTypeName = null;
192827
194190
  } else {
192828
- stack.push({ kind: "opaque" });
194191
+ const ends = delimiterEnds ??= projectDelimiterEnds(tokens);
194192
+ const expected = expectedTypeRef();
194193
+ const kind = constructionParenthesesKind(
194194
+ tokens,
194195
+ index,
194196
+ ends,
194197
+ genericCallOpens,
194198
+ expected?.kind === "tuple"
194199
+ );
194200
+ if (kind === "tuple" && expected?.kind === "tuple") {
194201
+ stack.push({
194202
+ kind: "tuple",
194203
+ type: expectedType(),
194204
+ typeRef: expected,
194205
+ slotId: expectedSlotId(),
194206
+ elementIndex: 0
194207
+ });
194208
+ } else if (kind === "group") {
194209
+ stack.push({
194210
+ kind: "group",
194211
+ slotType: expectedType(),
194212
+ slotTypeRef: expected,
194213
+ slotId: expectedSlotId()
194214
+ });
194215
+ } else {
194216
+ stack.push({ kind: "opaque" });
194217
+ }
192829
194218
  }
192830
194219
  closedConstructorTypeName = null;
192831
194220
  continue;
@@ -192878,6 +194267,11 @@ function indexConstructionSites(analysis, document, root) {
192878
194267
  frame.slotType = null;
192879
194268
  frame.slotTypeRef = null;
192880
194269
  }
194270
+ } else if (frame.kind === "tuple") {
194271
+ if (token.text === ",") frame.elementIndex++;
194272
+ } else if (frame.kind === "switch") {
194273
+ if (token.text === "=>") frame.inResult = true;
194274
+ else if (token.text === ",") frame.inResult = false;
192881
194275
  } else if (frame.kind === "call") {
192882
194276
  if (token.text === ",") {
192883
194277
  frame.argumentIndex++;
@@ -192896,6 +194290,43 @@ function indexConstructionSites(analysis, document, root) {
192896
194290
  sites.push({ position: previousPosition, site: snapshot() });
192897
194291
  return sites;
192898
194292
  }
194293
+ function constructionParenthesesKind(tokens, open2, ends, genericCallOpens, tupleExpected) {
194294
+ const previous = tokens[open2 - 1];
194295
+ const close = ends.get(open2);
194296
+ if (previous?.kind === "identifier" || previous?.kind === "type" || [")", "]", ">", "!"].includes(previous?.text ?? "") || close !== void 0 && tokens[close + 1]?.text === "=>")
194297
+ return null;
194298
+ for (let index = open2 + 1; index < (close ?? tokens.length); index++) {
194299
+ const token = tokens[index];
194300
+ if (token.text === ",") return "tuple";
194301
+ if (["(", "[", "{"].includes(token.text)) {
194302
+ const end = ends.get(index);
194303
+ if (end === void 0) return tupleExpected ? "tuple" : "group";
194304
+ index = end;
194305
+ } else if (token.text === "new" && tokens[index + 1]?.text !== "(") {
194306
+ const end = new Parser(tokens, index + 1).typeEnd();
194307
+ if (end > index + 1) index = end - 1;
194308
+ } else {
194309
+ const call = genericCallOpens.get(index) ?? -1;
194310
+ if (call >= 0) index = call - 1;
194311
+ }
194312
+ }
194313
+ return close === void 0 && tupleExpected ? "tuple" : "group";
194314
+ }
194315
+ function constructionGenericCallOpens(tokens) {
194316
+ const opens = [];
194317
+ const calls = /* @__PURE__ */ new Map();
194318
+ for (let index = 0; index < tokens.length; index++) {
194319
+ if (tokens[index].text === "<") opens.push(index);
194320
+ else if (tokens[index].text === ">") {
194321
+ const open2 = opens.pop();
194322
+ if (open2 === void 0 || open2 === 0 || tokens[index + 1]?.text !== "(")
194323
+ continue;
194324
+ const end = new Parser(tokens, open2 - 1).typeEnd();
194325
+ if (end === index + 1) calls.set(open2 - 1, end);
194326
+ }
194327
+ }
194328
+ return calls;
194329
+ }
192899
194330
  function collectionElementType2(type2) {
192900
194331
  if (!type2) return null;
192901
194332
  if (type2.name === "List" || type2.name === "Set") {
@@ -193106,27 +194537,6 @@ function graphConstructorParameters(typeName) {
193106
194537
  return [];
193107
194538
  }
193108
194539
  }
193109
- function projectFunctionsNamed(analysis, name) {
193110
- let byName = PROJECT_FUNCTIONS.get(analysis);
193111
- if (!byName) {
193112
- byName = /* @__PURE__ */ new Map();
193113
- for (const document of analysis.documents.values()) {
193114
- for (const declaration of document.declarations) {
193115
- if (declaration.kind === "global" || declaration.kind === "enum")
193116
- continue;
193117
- for (const member of declaration.members) {
193118
- if (member.kind !== "function") continue;
193119
- const entry = { owner: declaration.name, member };
193120
- const named = byName.get(member.name);
193121
- if (named) named.push(entry);
193122
- else byName.set(member.name, [entry]);
193123
- }
193124
- }
193125
- }
193126
- PROJECT_FUNCTIONS.set(analysis, byName);
193127
- }
193128
- return byName.get(name) ?? [];
193129
- }
193130
194540
  function dialoguePathTokens(tokens, end) {
193131
194541
  const path = [];
193132
194542
  for (let i2 = end; i2 >= 0 && isProjectNameToken(tokens[i2]); i2 -= 2) {
@@ -193177,10 +194587,12 @@ function dialogueGroupCompletions(analysis, document, position) {
193177
194587
  function isDialogueGroupArgument(tokens, pathStart) {
193178
194588
  return tokens[pathStart - 1]?.text === ":" && tokens[pathStart - 2]?.text === "group";
193179
194589
  }
193180
- var PROJECT_BODIES, PROJECT_BODY_INDEX_CACHE, PROJECT_BODY_SNAPSHOT_CACHE, SOURCE_TYPES, CONSTRUCTION_INDEX_CACHE, VARIANT_SCOPE_INDEX_CACHE, PROJECT_SYMBOL_INDEX_CACHE, ENCLOSING_OPENERS, significantTokens2, INITIALIZER_ROOTS, CONSTRUCTION_SITE_CACHE, DECLARATION_FIELDS, PROJECT_TYPE_DECLARATIONS, PROJECT_FUNCTIONS;
194590
+ var PROJECT_BODIES, PROJECT_EXPRESSION_SNAPSHOT_CACHE, PROJECT_BODY_INDEX_CACHE, PROJECT_BODY_SNAPSHOT_CACHE, SOURCE_TYPES, CONSTRUCTION_INDEX_CACHE, VARIANT_SCOPE_INDEX_CACHE, PROJECT_SYMBOL_INDEX_CACHE, ENCLOSING_OPENERS, significantTokens2, INITIALIZER_ROOTS, CONSTRUCTION_SITE_CACHE, DECLARATION_FIELDS, PROJECT_TYPE_DECLARATIONS;
193181
194591
  var init_project_source_language_features = __esm({
193182
194592
  "../packages/neoscript-language/src/project-source-language-features.ts"() {
193183
194593
  "use strict";
194594
+ init_argument_name_completions();
194595
+ init_project_annotation_path_completions();
193184
194596
  init_random_contract();
193185
194597
  init_analyzer();
193186
194598
  init_project_source_dialogue_groups();
@@ -193209,6 +194621,7 @@ var init_project_source_language_features = __esm({
193209
194621
  init_quick_fixes();
193210
194622
  init_syntax();
193211
194623
  PROJECT_BODIES = /* @__PURE__ */ new WeakMap();
194624
+ PROJECT_EXPRESSION_SNAPSHOT_CACHE = /* @__PURE__ */ new WeakMap();
193212
194625
  PROJECT_BODY_INDEX_CACHE = /* @__PURE__ */ new WeakMap();
193213
194626
  PROJECT_BODY_SNAPSHOT_CACHE = /* @__PURE__ */ new WeakMap();
193214
194627
  SOURCE_TYPES = /* @__PURE__ */ new WeakMap();
@@ -193221,7 +194634,6 @@ var init_project_source_language_features = __esm({
193221
194634
  CONSTRUCTION_SITE_CACHE = /* @__PURE__ */ new WeakMap();
193222
194635
  DECLARATION_FIELDS = /* @__PURE__ */ new WeakMap();
193223
194636
  PROJECT_TYPE_DECLARATIONS = /* @__PURE__ */ new WeakMap();
193224
- PROJECT_FUNCTIONS = /* @__PURE__ */ new WeakMap();
193225
194637
  }
193226
194638
  });
193227
194639
 
@@ -194341,7 +195753,7 @@ function sameLocationInList(target, locations) {
194341
195753
  (location3) => location3.uri === target.uri && location3.range.start.line === target.range.start.line && location3.range.start.character === target.range.start.character
194342
195754
  );
194343
195755
  }
194344
- function locationKey2(location3) {
195756
+ function locationKey3(location3) {
194345
195757
  const { start, end } = location3.range;
194346
195758
  return JSON.stringify([
194347
195759
  location3.uri,
@@ -194909,7 +196321,7 @@ var init_service = __esm({
194909
196321
  const declaration = resolved.symbol;
194910
196322
  const family = projectReferenceFamily(analysis, declaration, index);
194911
196323
  const familyLocations = new Set(
194912
- family.map((member) => locationKey2(member.location))
196324
+ family.map((member) => locationKey3(member.location))
194913
196325
  );
194914
196326
  const familyIds = new Set(
194915
196327
  family.flatMap((member) => member.id === null ? [] : [member.id])
@@ -194932,11 +196344,11 @@ var init_service = __esm({
194932
196344
  candidate.range.start,
194933
196345
  index
194934
196346
  )?.symbol;
194935
- if (!candidateSymbol || !familyLocations.has(locationKey2(candidateSymbol.location))) {
196347
+ if (!candidateSymbol || !familyLocations.has(locationKey3(candidateSymbol.location))) {
194936
196348
  continue;
194937
196349
  }
194938
196350
  const location3 = { uri: state.document.uri, range: candidate.range };
194939
- if (!includeDeclaration && familyLocations.has(locationKey2(location3))) {
196351
+ if (!includeDeclaration && familyLocations.has(locationKey3(location3))) {
194940
196352
  continue;
194941
196353
  }
194942
196354
  locations.push(location3);
@@ -194951,7 +196363,7 @@ var init_service = __esm({
194951
196363
  const symbolId = resolveReferenceSymbolId(snapshot, candidate);
194952
196364
  if (symbolId === null) continue;
194953
196365
  const matches = familyIds.has(symbolId) || definition(snapshot, candidate.range.start).some(
194954
- (location3) => familyLocations.has(locationKey2(location3))
196366
+ (location3) => familyLocations.has(locationKey3(location3))
194955
196367
  );
194956
196368
  if (!matches) continue;
194957
196369
  locations.push({ uri: state.document.uri, range: candidate.range });
@@ -194959,7 +196371,7 @@ var init_service = __esm({
194959
196371
  if (declaration.kind !== "parameter") continue;
194960
196372
  for (const label of namedArgumentLabels(snapshot)) {
194961
196373
  const parameter4 = label.parameter.selectionLocation;
194962
- if (parameter4 && familyLocations.has(locationKey2(parameter4)))
196374
+ if (parameter4 && familyLocations.has(locationKey3(parameter4)))
194963
196375
  locations.push({ uri: state.document.uri, range: label.range });
194964
196376
  }
194965
196377
  }
@@ -237078,7 +238490,7 @@ var releaseWorkspaceLock = () => void 0;
237078
238490
  async function main() {
237079
238491
  const args = parseArgs(process.argv.slice(2));
237080
238492
  if (args.command === "--version") {
237081
- console.log("0.89.0");
238493
+ console.log("0.89.2");
237082
238494
  return;
237083
238495
  }
237084
238496
  if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {