@neocompose/cli 0.76.3 → 0.77.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4587,7 +4587,10 @@ function isMemberEnum(value) {
4587
4587
  if (!isWithId(value)) return false;
4588
4588
  return isWithId(value);
4589
4589
  }
4590
- function isMemberLookupBase(value) {
4590
+ function isLookupSelection(selection) {
4591
+ return selection === void 0 || selection === 0 /* Single */ || selection === 1 /* Multi */;
4592
+ }
4593
+ function isMemberCollectionLookupBase(value) {
4591
4594
  const v = asMemberBaseForKind(value, 9 /* Lookup */);
4592
4595
  if (v === null) return false;
4593
4596
  if (typeof v.collectionMemberId !== "string") return false;
@@ -4598,7 +4601,22 @@ function isMemberLookupBase(value) {
4598
4601
  if (v.declaredTypeInfo !== void 0 && v.declaredTypeInfo !== null && !isNSTypeInfo(v.declaredTypeInfo)) {
4599
4602
  return false;
4600
4603
  }
4601
- return v.selection === void 0 || v.selection === 0 /* Single */ || v.selection === 1 /* Multi */;
4604
+ return isLookupSelection(v.selection);
4605
+ }
4606
+ function isMemberTypeLookupBase(value) {
4607
+ const v = asMemberBaseForKind(value, 9 /* Lookup */);
4608
+ if (v === null) return false;
4609
+ if (v.collectionMemberId !== void 0) return false;
4610
+ if (v.collectionValueId !== void 0) return false;
4611
+ if (!isLookupTargetTypeInfo(v.declaredTypeInfo)) return false;
4612
+ return isLookupSelection(v.selection);
4613
+ }
4614
+ function isLookupTargetTypeInfo(value) {
4615
+ if (!isNSTypeInfo(value)) return false;
4616
+ return value.type === 7 /* Class */ || value.type === 21 /* Generic */;
4617
+ }
4618
+ function isMemberLookupBase(value) {
4619
+ return isMemberCollectionLookupBase(value) || isMemberTypeLookupBase(value);
4602
4620
  }
4603
4621
  function isMemberLookup(value) {
4604
4622
  if (!isMemberLookupBase(value)) return false;
@@ -18677,7 +18695,11 @@ function evalInstructions(instructions, scope, ctx, options) {
18677
18695
  }
18678
18696
  let targetTypeInfo = ins.target.typeInfo;
18679
18697
  if (lookupAssignment && targetTypeInfo.type !== 9 /* Lookup */ && targetTypeInfo.type !== 18 /* DialogueLookup */) {
18680
- targetTypeInfo = {
18698
+ targetTypeInfo = member.collectionMemberId === void 0 ? {
18699
+ type: 9 /* Lookup */,
18700
+ required: targetTypeInfo.required,
18701
+ entryTypeInfo: targetTypeInfo
18702
+ } : {
18681
18703
  type: 9 /* Lookup */,
18682
18704
  required: targetTypeInfo.required,
18683
18705
  entryTypeInfo: targetTypeInfo,
@@ -21362,6 +21384,13 @@ function runtimeTypeInfoForMember(rawMember, env, ctx, seen) {
21362
21384
  };
21363
21385
  }
21364
21386
  if (isMemberLookup(member)) {
21387
+ if (member.collectionMemberId === void 0) {
21388
+ const entryTypeInfo2 = {
21389
+ ...substituteRuntimeTypeInfo(member.declaredTypeInfo, env, ctx),
21390
+ required: isMultiSelectionMember(member) ? true : false
21391
+ };
21392
+ return isMultiSelectionMember(member) ? { type: 9 /* Lookup */, required, entryTypeInfo: entryTypeInfo2 } : entryTypeInfo2;
21393
+ }
21365
21394
  const collection = evalMemberById(ctx.vm, member.collectionMemberId);
21366
21395
  if (collection === null) {
21367
21396
  throw new NSGetterRuntimeError(
@@ -28225,17 +28254,21 @@ function projectListenerEndpoint(args) {
28225
28254
 
28226
28255
  // ../packages/models/src/members/lookup-declared-type.ts
28227
28256
  function lookupDeclaredTypeInfo(member, collectionTypeInfo) {
28228
- if (collectionTypeInfo === null) return null;
28229
- if (collectionTypeInfo.type !== 6 /* List */ && collectionTypeInfo.type !== 5 /* Dictionary */) {
28230
- return null;
28231
- }
28232
- const entryTypeInfo = member.declaredTypeInfo ?? collectionTypeInfo.entryTypeInfo;
28257
+ const entryTypeInfo = lookupEntryTypeInfo(member, collectionTypeInfo);
28258
+ if (entryTypeInfo === null) return null;
28233
28259
  if (isMultiSelectionMember(member) !== true) {
28234
28260
  return {
28235
28261
  ...entryTypeInfo,
28236
28262
  required: isRequiredMember(member)
28237
28263
  };
28238
28264
  }
28265
+ if (member.collectionMemberId === void 0) {
28266
+ return {
28267
+ type: 9 /* Lookup */,
28268
+ required: isRequiredMember(member),
28269
+ entryTypeInfo
28270
+ };
28271
+ }
28239
28272
  return {
28240
28273
  type: 9 /* Lookup */,
28241
28274
  required: isRequiredMember(member),
@@ -28244,6 +28277,15 @@ function lookupDeclaredTypeInfo(member, collectionTypeInfo) {
28244
28277
  collectionValueId: member.collectionValueId ?? null
28245
28278
  };
28246
28279
  }
28280
+ function lookupEntryTypeInfo(member, collectionTypeInfo) {
28281
+ if (member.collectionMemberId === void 0) return member.declaredTypeInfo;
28282
+ const collection = collectionTypeInfo(member.collectionMemberId);
28283
+ if (collection === null) return null;
28284
+ if (collection.type !== 6 /* List */ && collection.type !== 5 /* Dictionary */) {
28285
+ return null;
28286
+ }
28287
+ return member.declaredTypeInfo ?? collection.entryTypeInfo;
28288
+ }
28247
28289
 
28248
28290
  // ../packages/neoscript-runtime/src/values/member-declared-type-info.ts
28249
28291
  function resolveMemberDeclaredTypeInfo(member, members, ownerClass = null) {
@@ -28351,19 +28393,18 @@ function resolveMemberDeclaredTypeInfoInternal(member, members, seen, ownerClass
28351
28393
  };
28352
28394
  }
28353
28395
  if (isMemberLookupBase(resolved)) {
28354
- const collection = members.find(
28355
- (candidate) => candidate.id === resolved.collectionMemberId
28356
- );
28357
- if (collection === void 0) return null;
28358
- return lookupDeclaredTypeInfo(
28359
- resolved,
28360
- resolveMemberDeclaredTypeInfoInternal(
28396
+ return lookupDeclaredTypeInfo(resolved, (collectionMemberId) => {
28397
+ const collection = members.find(
28398
+ (candidate) => candidate.id === collectionMemberId
28399
+ );
28400
+ if (collection === void 0) return null;
28401
+ return resolveMemberDeclaredTypeInfoInternal(
28361
28402
  collection,
28362
28403
  members,
28363
28404
  nextSeen,
28364
28405
  ownerClass
28365
- )
28366
- );
28406
+ );
28407
+ });
28367
28408
  }
28368
28409
  if (resolved.kind === 9 /* Lookup */) return null;
28369
28410
  if (!memberKindSupportsStorage(resolved.kind)) return null;
@@ -36073,7 +36114,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
36073
36114
  local,
36074
36115
  localType,
36075
36116
  "local" /* Local */,
36076
- initial.writability ?? "local" /* Local */,
36117
+ localOwnership(initial),
36077
36118
  this.localWriteTargetRoot(initial, scope)
36078
36119
  )
36079
36120
  );
@@ -39326,6 +39367,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
39326
39367
  } : {}
39327
39368
  };
39328
39369
  }
39370
+ const writability = member.writability ? toWritability(member.writability, this.writesUserData) : void 0;
39329
39371
  return {
39330
39372
  pointer: {
39331
39373
  type: "staticMember" /* StaticMember */,
@@ -39333,8 +39375,10 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
39333
39375
  },
39334
39376
  type: member.type,
39335
39377
  symbol: member,
39336
- ...member.writability ? {
39337
- writability: toWritability(member.writability, this.writesUserData)
39378
+ ...writability ? { writability } : {},
39379
+ ...member.lookup ? {
39380
+ entryWritability: this.lookupEntryWritability(member, writability),
39381
+ entryUserData: this.lookupEntryUserData(member)
39338
39382
  } : {}
39339
39383
  };
39340
39384
  }
@@ -39634,7 +39678,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
39634
39678
  const readonlySlot = member.readonlyDeclaration === true;
39635
39679
  const storageWritability = this.memberWritability(member, receiver);
39636
39680
  const writability = readonlySlot ? "readOnly" /* ReadOnly */ : storageWritability;
39637
- const entryWritability = member.lookup ? this.lookupEntryWritability(member, receiver) : readonlySlot ? storageWritability : void 0;
39681
+ const entryWritability = member.lookup ? this.lookupEntryWritability(member, receiver.writability) : readonlySlot ? storageWritability : void 0;
39638
39682
  const userData = this.memberUserData(member, receiver);
39639
39683
  const entryUserData = member.lookup ? this.lookupEntryUserData(member) : readonlySlot && userData;
39640
39684
  const lookupWire = member.lookup?.multiselect === true && memberType2.kind === "set" ? {
@@ -39644,7 +39688,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
39644
39688
  { ...memberType2.elementType, nullable: false },
39645
39689
  this.project
39646
39690
  ),
39647
- collectionMemberId: member.lookup.collectionMemberId,
39691
+ ...member.lookup.collectionMemberId !== void 0 ? { collectionMemberId: member.lookup.collectionMemberId } : {},
39648
39692
  ...member.lookup.collectionValueId !== void 0 ? { collectionValueId: member.lookup.collectionValueId } : {}
39649
39693
  } : void 0;
39650
39694
  return {
@@ -39768,16 +39812,18 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
39768
39812
  }
39769
39813
  lookupEntryUserData(member) {
39770
39814
  if (!member.lookup) return false;
39771
- const collectionWritability = member.lookup.collectionWritability ?? this.project.symbolById.get(member.lookup.collectionMemberId)?.writability;
39815
+ const collectionMemberId = member.lookup.collectionMemberId;
39816
+ if (collectionMemberId === void 0) return false;
39817
+ const collectionWritability = member.lookup.collectionWritability ?? this.project.symbolById.get(collectionMemberId)?.writability;
39772
39818
  return collectionWritability === "user";
39773
39819
  }
39774
- lookupEntryWritability(member, receiver) {
39820
+ lookupEntryWritability(member, receiverWritability) {
39775
39821
  if (!member.lookup) return "readOnly" /* ReadOnly */;
39776
- const target = this.project.symbolById.get(
39777
- member.lookup.collectionMemberId
39778
- );
39822
+ const collectionMemberId = member.lookup.collectionMemberId;
39823
+ if (collectionMemberId === void 0) return "runtime" /* Runtime */;
39824
+ const target = this.project.symbolById.get(collectionMemberId);
39779
39825
  const targetWritability = member.lookup.collectionWritability ? toWritability(member.lookup.collectionWritability, this.writesUserData) : target?.writability ? toWritability(target.writability, this.writesUserData) : target?.writable ? "runtime" /* Runtime */ : "readOnly" /* ReadOnly */;
39780
- if (receiver.writability === "immutable" /* Immutable */) {
39826
+ if (receiverWritability === "immutable" /* Immutable */) {
39781
39827
  if (targetWritability === "save" /* Save */) {
39782
39828
  return "immutableToSaveLookup" /* ImmutableToSaveLookup */;
39783
39829
  }
@@ -43974,6 +44020,12 @@ function bindConstructorArgumentNames(className, declared, argumentNames, pos) {
43974
44020
  return parameter3.name;
43975
44021
  });
43976
44022
  }
44023
+ function localOwnership(initial) {
44024
+ if (initial.entryWritability !== void 0 && (initial.type.kind === "named" || initial.type.kind === "typeParameter")) {
44025
+ return initial.entryWritability;
44026
+ }
44027
+ return initial.writability ?? "local" /* Local */;
44028
+ }
43977
44029
  function scopeVariable(name, value, sourceType, writability, ownership, writeRoot, readonlyBinding) {
43978
44030
  return {
43979
44031
  name,
@@ -46055,12 +46107,10 @@ function memberSymbol(member, schemaKey, environment, field) {
46055
46107
  environment
46056
46108
  );
46057
46109
  }
46058
- const lookupCollectionMemberId = kind === "lookup" ? string(member.collectionMemberId, `${field}.collectionMemberId`) : null;
46059
- const lookupCollectionWritability = lookupCollectionMemberId === null ? void 0 : environment.effectiveWritabilityByMemberId.get(
46060
- lookupCollectionMemberId
46061
- );
46110
+ const lookupCollection = kind === "lookup" ? lookupCollectionMemberId(member, field) : null;
46111
+ const lookupCollectionWritability = lookupCollection === null ? void 0 : environment.effectiveWritabilityByMemberId.get(lookupCollection);
46062
46112
  const lookup = kind === "lookup" ? {
46063
- collectionMemberId: lookupCollectionMemberId,
46113
+ ...lookupCollection === null ? {} : { collectionMemberId: lookupCollection },
46064
46114
  ...member.collectionValueId === null || typeof member.collectionValueId === "string" ? { collectionValueId: member.collectionValueId } : {},
46065
46115
  multiselect: boolean(member.multiselect, `${field}.multiselect`),
46066
46116
  ...lookupCollectionWritability === void 0 ? {} : { collectionWritability: lookupCollectionWritability }
@@ -46074,6 +46124,10 @@ function memberSymbol(member, schemaKey, environment, field) {
46074
46124
  ...lookup ? { lookup } : {}
46075
46125
  };
46076
46126
  }
46127
+ function lookupCollectionMemberId(member, field) {
46128
+ if (member.collectionMemberId === null) return null;
46129
+ return string(member.collectionMemberId, `${field}.collectionMemberId`);
46130
+ }
46077
46131
  function interfaceType(value, environment, field) {
46078
46132
  const id = string(value.id, `${field}.id`);
46079
46133
  return {
@@ -46542,9 +46596,8 @@ function memberType(member, environment, visiting, field) {
46542
46596
  };
46543
46597
  }
46544
46598
  if (kind === "lookup") {
46545
- const collection = environment.members.get(
46546
- string(member.collectionMemberId, `${field}.collectionMemberId`)
46547
- );
46599
+ const collectionMemberId = lookupCollectionMemberId(member, field);
46600
+ const collection = collectionMemberId === null ? void 0 : environment.members.get(collectionMemberId);
46548
46601
  const collectionType = collection ? memberType(collection, environment, next, `${field}.collection`) : unknownType();
46549
46602
  const declared = optionalRecord(member.declaredType);
46550
46603
  const declaredType = declared ? manifestType(declared, environment, `${field}.declaredType`) : null;
@@ -48159,6 +48212,13 @@ function memberToSymbol(record4, schemaKey, containingClass, ownerClassId, index
48159
48212
  };
48160
48213
  }
48161
48214
  if (isMemberLookupBase(resolved)) {
48215
+ if (resolved.collectionMemberId === void 0) {
48216
+ return {
48217
+ ...common,
48218
+ kind: "property",
48219
+ lookup: { multiselect: isMultiSelectionMember(resolved) }
48220
+ };
48221
+ }
48162
48222
  const collectionWritability = uniqueEffectiveWritability(
48163
48223
  resolved.collectionMemberId,
48164
48224
  context
@@ -48520,12 +48580,12 @@ function memberRuntimeType(record4, context, seen = /* @__PURE__ */ new Set(), g
48520
48580
  if (!isMemberLookupBase(member)) return UNKNOWN_TYPE;
48521
48581
  const declared = member.declaredTypeInfo ? toLanguageType(member.declaredTypeInfo, context, genericEnvironment) : null;
48522
48582
  const narrowed = declared && !isUnknownType3(declared) ? declared : null;
48523
- const entry = narrowed ?? lookupCollectionEntryType(
48583
+ const entry = narrowed ?? (member.collectionMemberId === void 0 ? null : lookupCollectionEntryType(
48524
48584
  member.collectionMemberId,
48525
48585
  context,
48526
48586
  nextSeen,
48527
48587
  genericEnvironment
48528
- );
48588
+ ));
48529
48589
  if (!entry) return UNKNOWN_TYPE;
48530
48590
  return isMultiSelectionMember(member) ? {
48531
48591
  kind: "set",
@@ -54156,12 +54216,23 @@ var schemaMemberSchema = variant("kind", [
54156
54216
  enumId: nonEmptyString,
54157
54217
  multiselect: boolean2()
54158
54218
  }),
54159
- memberSchema("lookup", {
54160
- collectionMemberId: nonEmptyString,
54161
- collectionValueId: nullableId,
54162
- multiselect: boolean2(),
54163
- declaredType: nullable(schemaTypeSchema)
54164
- }),
54219
+ pipe(
54220
+ memberSchema("lookup", {
54221
+ /** `null` on an unbound `Reference<T>` (P107), typed by `declaredType`. */
54222
+ collectionMemberId: nullable(nonEmptyString),
54223
+ collectionValueId: nullableId,
54224
+ multiselect: boolean2(),
54225
+ declaredType: nullable(schemaTypeSchema)
54226
+ }),
54227
+ check(
54228
+ (member) => member.collectionMemberId !== null || member.collectionValueId === null,
54229
+ "A lookup collection value requires a collection member."
54230
+ ),
54231
+ check(
54232
+ (member) => member.collectionMemberId !== null || member.declaredType?.kind === "class" || member.declaredType?.kind === "generic",
54233
+ "A lookup without a collection needs a class or generic declared type."
54234
+ )
54235
+ ),
54165
54236
  memberSchema("dialogueLookup", {
54166
54237
  dialogueGroupId: nullableId,
54167
54238
  multiselect: boolean2()
@@ -54559,10 +54630,8 @@ function memberFromDocument(record4, members, owners, classNames, context) {
54559
54630
  return {
54560
54631
  ...common,
54561
54632
  kind: "lookup",
54562
- collectionMemberId: requiredStringValue(
54563
- field("collectionMemberId", void 0),
54564
- record4,
54565
- "collectionMemberId"
54633
+ collectionMemberId: optionalStringOrNull(
54634
+ field("collectionMemberId", null)
54566
54635
  ),
54567
54636
  collectionValueId: optionalStringOrNull(field("collectionValueId", null)),
54568
54637
  multiselect: ordinalValue(
@@ -54880,7 +54949,9 @@ function memberToDocumentFields(member, baseData) {
54880
54949
  }
54881
54950
  }
54882
54951
  if (member.kind === "lookup") {
54883
- fields.collectionMemberId = member.collectionMemberId;
54952
+ if (member.collectionMemberId !== null) {
54953
+ fields.collectionMemberId = member.collectionMemberId;
54954
+ }
54884
54955
  if (member.collectionValueId !== null) {
54885
54956
  fields.collectionValueId = member.collectionValueId;
54886
54957
  }
@@ -56869,7 +56940,7 @@ var INITIALIZER_KEY_PLACEHOLDER = new RegExp(
56869
56940
 
56870
56941
  // ../packages/manifest/schema-contract/registry.mjs
56871
56942
  var PROJECT_SCHEMA_CONTRACT = Object.freeze({
56872
- cliVersion: "0.76.3",
56943
+ cliVersion: "0.77.0",
56873
56944
  projectFileUploadBatchSize: 32,
56874
56945
  documentRecords: {
56875
56946
  member: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neocompose/cli",
3
- "version": "0.76.3",
3
+ "version": "0.77.0",
4
4
  "description": "Neo Compose native project-source CLI with bidirectional sync.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -9,7 +9,7 @@ description: >-
9
9
  `@neocompose/cli` or `node cli/bin/neo.mjs` in the neo-compose repository.
10
10
  ---
11
11
 
12
- <!-- reviewed-through-cli: 0.76.3 -->
12
+ <!-- reviewed-through-cli: 0.77.0 -->
13
13
 
14
14
  # Neo Compose CLI
15
15
 
@@ -129,7 +129,7 @@ wrappers.
129
129
  The marker near the top of `SKILL.md` must exactly match the package version:
130
130
 
131
131
  ```html
132
- <!-- reviewed-through-cli: 0.76.3 -->
132
+ <!-- reviewed-through-cli: 0.77.0 -->
133
133
  ```
134
134
 
135
135
  The quoted version above is checked too, so this instruction cannot go stale
@@ -86,11 +86,11 @@ that does not authorize copying the annotation onto authored records.
86
86
 
87
87
  Use context-aware typed annotations:
88
88
 
89
- - `@settings(...)` for format/search/selection/editor constraints.
89
+ - `@settings(...)` for format/search/collection/editor constraints.
90
90
  - `@storage(allowed: ...)` on classes and storage keys on members.
91
91
  - `@visibility(.Hidden)` only on a class; absence means visible.
92
92
  - Stateful settings use contextual enum cases, such as
93
- `@settings(format: .Plain)` and `@settings(selection: .Multi)`.
93
+ `@settings(format: .Plain)` and `@settings(kind: .Unordered)`.
94
94
  - `@settings(...)` before a `List` element or `Dictionary` value type
95
95
  configures the collection's entries: `List<@settings(format: .Plain) string>`,
96
96
  `Dictionary<string, @settings(min: 0) int>`. Only the member that declares
@@ -231,14 +231,31 @@ the instance's recorded constructor or variant. They track later source-default
231
231
  edits until that field is explicitly overridden; resetting an override makes it
232
232
  virtual again.
233
233
 
234
- A lookup member's arity is its declared type. `public Config Config` selects one
235
- entry and its declared type is the entry type; `public Set<Config> Configs`
236
- selects several. An initializer body for a single-select lookup returns one
237
- entry, never a set.
234
+ Declare a lookup member as `Reference<T>`. `public Reference<Config> Config`
235
+ selects one row and reads as `Config`. `public Set<Reference<Config>> Configs`
236
+ selects several and reads as `Set<Config>`. An initializer body for a single
237
+ reference returns one row, never a set. `T` with `@settings(collection:)` is an
238
+ error; the language server's quick fix respells it.
238
239
 
239
- The CLI also accepts `List<T>` with `selection: .Multi` on a member. Emitted
240
- source uses `Set<T>`; constructor and function parameters must use `Set<T>`
241
- to carry selection semantics.
240
+ `@settings(collection: Owner.Member)` binds the reference to one collection.
241
+ Without it the reference is unbound: it selects any stored row of `T` or a
242
+ subclass, anywhere in the project. The selected row's store decides writes. A
243
+ write through it to a Save row lands, and to an asset row it errors. Its
244
+ generated C# property is the read-only interface; call `TryWritable` to write.
245
+
246
+ An unbound default can name its row by a unique index:
247
+
248
+ ```neo
249
+ public Reference<Item> StarterSeed = root.Assets.Items.Index.Slug["seed.carrot"]!;
250
+ ```
251
+
252
+ The receiver is a `root` path to a List, `.Index.<Name>` is a unique index on
253
+ it, and the key is a string literal. Any other shape stays initializer code.
254
+
255
+ A `Reference<T>` member satisfies an interface `T Foo { get; }` or
256
+ `{ get; set; }` and an abstract `T Foo { get; }`.
257
+
258
+ Constructor and function parameters use `Set<T>` for several selections.
242
259
 
243
260
  Declare a multicast event as `NeoAction<…>`. Its value is an ordered listener
244
261
  set, so give it a bracketed list of method groups — never a lambda, and never
@@ -569,7 +569,7 @@ locally, like push. If another commit lands while it runs, the run is refused:
569
569
  run it again. `neo loc` writes work the same way: a write refused because
570
570
  another commit landed is run again.
571
571
 
572
- VS Code rename follows override families and class constructors, resolves contextual enum options such as `.Success`, renames a constructor parameter's named arguments (`new Item(count: 1)`) in bodies, initializers, specs, and base clauses, and keeps local-variable renames scoped to their declaration. Assigned IDs are not required for these refactorings. Inferred locals initialized with conditional expressions retain their common branch type for member completion, navigation, and rename. Typed delegate calls retain their return type too. Lambda returns use the delegate signature for target-typed constructors and enum argument suggestions. Member completion also follows optional access and null-forgiving receivers, including dictionary lookups.
572
+ VS Code rename follows override families and class constructors, resolves contextual enum options such as `.Success`, renames a constructor parameter's named arguments (`new Item(count: 1)`) in bodies, initializers, specs, and base clauses, and keeps local-variable renames scoped to their declaration. Assigned IDs are not required for these refactorings. Inferred locals initialized with conditional expressions retain their common branch type for member completion, navigation, and rename. Direct parenthesized expressions and chained delegate factory calls retain their result type too. `List.Repeat` results infer their element type from the value, explicit call-site type arguments, and expected list type, including for inferred locals and direct indexed access. Lambda returns use the delegate signature for target-typed constructors and enum argument suggestions. Member completion also follows optional access and null-forgiving receivers, including dictionary lookups.
573
573
 
574
574
  ## Member change listeners
575
575