@neocompose/cli 0.82.3 → 0.82.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.82.5
4
+
5
+ ### Patch Changes
6
+
7
+ - 7d9a013: Preserve generic arguments in Unity animation clip target types and reference lookup factories. Generate clip getters with the declared target type so clips targeting a base class compile correctly. Report incompatible owner/target generic bindings during export instead of emitting C# that cannot compile. Run `neo export` after updating to regenerate the corrected C#.
8
+
9
+ ## 0.82.4
10
+
11
+ ### Patch Changes
12
+
13
+ - 8ce5b54: Accept Reference<T> constructor and method parameters during record validation, including enum and scalar slots. Invalid callable parameters now report the parameter name and validation cause.
14
+
3
15
  ## 0.82.3
4
16
 
5
17
  ### Patch Changes
@@ -15508,7 +15508,7 @@ var init_registry = __esm({
15508
15508
  "../packages/manifest/schema-contract/registry.mjs"() {
15509
15509
  "use strict";
15510
15510
  PROJECT_SCHEMA_CONTRACT = Object.freeze({
15511
- cliVersion: "0.82.3",
15511
+ cliVersion: "0.82.5",
15512
15512
  projectFileUploadBatchSize: 32,
15513
15513
  documentRecords: {
15514
15514
  member: {
@@ -24459,7 +24459,7 @@ function csharpPropertyValueType(ctx, member, saved = false, env, genericBinding
24459
24459
  }
24460
24460
  return csharpValueType(ctx, member, saved, env, genericBindingSaved);
24461
24461
  }
24462
- function animationClipTargetType(ctx, member, env) {
24462
+ function animationClipTargetType(ctx, member, env, ownerClassId) {
24463
24463
  const clipClass = resolveInheritanceChain(member.classId, ctx.classes).find(
24464
24464
  (candidate) => candidate.system?.worldKind === NeoWorldSystemClassKind.AnimationClip
24465
24465
  );
@@ -24540,7 +24540,47 @@ function animationClipTargetType(ctx, member, env) {
24540
24540
  });
24541
24541
  return null;
24542
24542
  }
24543
- return targetType;
24543
+ const suffix = constructedTypeArgumentsSuffix(ctx, bindingMember, true, env);
24544
+ if (suffix === null) return null;
24545
+ const constructedTarget = `${targetType}${suffix}`;
24546
+ if (ownerClassId !== void 0) {
24547
+ const ownerName = ctx.typeNames.get(ownerClassId) ?? ownerClassId;
24548
+ if (!resolveInheritanceChain(ownerClassId, ctx.classes).some(
24549
+ (ancestor) => ancestor.id === bindingMember.classId
24550
+ )) {
24551
+ ctx.diagnostics.push({
24552
+ severity: "error",
24553
+ message: `Animation clip "${member.name}" targets ${constructedTarget}, which is not its owner ${ownerName} or a base of it.`,
24554
+ path: memberPath3
24555
+ });
24556
+ return null;
24557
+ }
24558
+ const ownerArguments = [];
24559
+ for (const { param } of resolveGenericScopeForEmission(
24560
+ ctx,
24561
+ bindingMember.classId
24562
+ )) {
24563
+ const argument2 = csharpGenericParamType(
24564
+ ctx,
24565
+ param.id,
24566
+ true,
24567
+ env,
24568
+ memberPath3
24569
+ );
24570
+ if (argument2 === null) return null;
24571
+ ownerArguments.push(argument2);
24572
+ }
24573
+ const ownerTarget = `${targetType}${ownerArguments.length === 0 ? "" : `<${ownerArguments.join(", ")}>`}`;
24574
+ if (ownerTarget !== constructedTarget) {
24575
+ ctx.diagnostics.push({
24576
+ severity: "error",
24577
+ message: `Animation clip "${member.name}" targets ${constructedTarget}, but owner ${ownerName} has target type ${ownerTarget}. A clip must target its owner or a constructed base of it.`,
24578
+ path: memberPath3
24579
+ });
24580
+ return null;
24581
+ }
24582
+ }
24583
+ return constructedTarget;
24544
24584
  }
24545
24585
  function csharpTypeInfoValueType(ctx, typeInfo, saved, genericEnv, genericBindingSaved = saved) {
24546
24586
  const optional2 = !typeInfo.required;
@@ -128632,6 +128672,8 @@ function typeInfoInterfaceIds(value) {
128632
128672
  }
128633
128673
  if ("entryTypeInfo" in value)
128634
128674
  ids.push(...typeInfoInterfaceIds(value.entryTypeInfo));
128675
+ if ("targetTypeInfo" in value)
128676
+ ids.push(...typeInfoInterfaceIds(value.targetTypeInfo));
128635
128677
  if (isRecord8(value.typeArguments)) {
128636
128678
  for (const argument2 of Object.values(value.typeArguments)) {
128637
128679
  ids.push(...typeInfoInterfaceIds(argument2));
@@ -128711,6 +128753,15 @@ function isOpaqueNSTypeInfo(value, ancestors = /* @__PURE__ */ new Set()) {
128711
128753
  if (value.type === 22) {
128712
128754
  return typeof value.interfaceId === "string" && value.interfaceId.length > 0;
128713
128755
  }
128756
+ if (value.type === 29 /* Reference */) {
128757
+ if (ancestors.has(value)) return false;
128758
+ ancestors.add(value);
128759
+ try {
128760
+ return isOpaqueNSTypeInfo(value.targetTypeInfo, ancestors);
128761
+ } finally {
128762
+ ancestors.delete(value);
128763
+ }
128764
+ }
128714
128765
  if (value.type === 25) {
128715
128766
  if (!Array.isArray(value.argumentTypes) || ancestors.has(value)) {
128716
128767
  return false;
@@ -128750,6 +128801,9 @@ function isOpaqueNSTypeInfo(value, ancestors = /* @__PURE__ */ new Set()) {
128750
128801
  }
128751
128802
  function opaqueTypeInfoContainsUnknown(value) {
128752
128803
  if (value.type === "Unknown") return true;
128804
+ if (value.type === 29 /* Reference */) {
128805
+ return isRecord8(value.targetTypeInfo) && opaqueTypeInfoContainsUnknown(value.targetTypeInfo);
128806
+ }
128753
128807
  if (value.type === 5 /* Dictionary */ || value.type === 6 /* List */ || value.type === 28 /* Set */ || value.type === 9 /* Lookup */) {
128754
128808
  return isRecord8(value.entryTypeInfo) && opaqueTypeInfoContainsUnknown(value.entryTypeInfo);
128755
128809
  }
@@ -128838,6 +128892,7 @@ function opaqueFunctionGenericReference(value, matches) {
128838
128892
  }
128839
128893
  const children = [
128840
128894
  value.entryTypeInfo,
128895
+ value.targetTypeInfo,
128841
128896
  value.returnTypeInfo,
128842
128897
  ...Array.isArray(value.argumentTypes) ? value.argumentTypes : [],
128843
128898
  ...isRecord8(value.typeArguments) ? Object.values(value.typeArguments) : []
@@ -128855,7 +128910,38 @@ function isOpaqueNSFunctionReturnTypeInfo(value) {
128855
128910
  return isOpaqueNSTypeInfo(value);
128856
128911
  }
128857
128912
  function isOpaqueCallableArgumentTypeInfo(value) {
128858
- return isOpaqueNSTypeInfo(value) && isOpaqueCallableArgumentIdentifier(value.name) && !opaqueTypeInfoContainsUnknown(value) && hasValidOpaqueParameterDefault(value);
128913
+ return opaqueCallableArgumentError(value) === null;
128914
+ }
128915
+ function opaqueCallableArgumentError(value) {
128916
+ if (!isRecord8(value)) return "must be an argument type object.";
128917
+ const { type, required: required2 } = value;
128918
+ if (!isOpaqueNSTypeInfo(value)) {
128919
+ if (type === 29 /* Reference */) {
128920
+ if (typeof required2 !== "boolean") {
128921
+ return "Reference required must be a boolean.";
128922
+ }
128923
+ return "Reference targetTypeInfo is invalid.";
128924
+ }
128925
+ return "type information is invalid.";
128926
+ }
128927
+ if (!isOpaqueCallableArgumentIdentifier(value.name)) {
128928
+ return "name is invalid or reserved.";
128929
+ }
128930
+ if (opaqueTypeInfoContainsUnknown(value)) {
128931
+ return "type contains Unknown.";
128932
+ }
128933
+ if (!hasValidOpaqueParameterDefault(value)) {
128934
+ return "defaultValue is invalid for its type.";
128935
+ }
128936
+ return null;
128937
+ }
128938
+ function assertOpaqueCallableArgumentsValid(arguments_, owner) {
128939
+ for (const [index, argument2] of arguments_.entries()) {
128940
+ const error = opaqueCallableArgumentError(argument2);
128941
+ if (error === null) continue;
128942
+ const label = isRecord8(argument2) && typeof argument2.name === "string" ? `"${argument2.name}"` : `at index ${index}`;
128943
+ throw new Error(`${owner} parameter ${label} ${error}`);
128944
+ }
128859
128945
  }
128860
128946
  function hasValidOpaqueParameterDefault(value) {
128861
128947
  const wrapper = value.defaultValue;
@@ -128914,7 +129000,7 @@ function assertOpaqueParameterDefaultsValid(member) {
128914
129000
  for (const argument2 of argumentTypes) {
128915
129001
  if (!isRecord8(argument2) || !hasValidOpaqueParameterDefault(argument2)) {
128916
129002
  throw new Error(
128917
- `Function "${member.name}" (${member.id}) declares a parameter default value that does not match the parameter's type.`
129003
+ `Function "${member.name}" (${member.id}) parameter "${isRecord8(argument2) ? String(argument2.name) : "<invalid>"}" defaultValue is invalid for its type.`
128918
129004
  );
128919
129005
  }
128920
129006
  parameters.push(argument2);
@@ -129756,6 +129842,15 @@ function assertProjectInterfaceDocumentValid(view, options = {}) {
129756
129842
  )
129757
129843
  };
129758
129844
  }
129845
+ if (typeInfo.type === 29 /* Reference */) {
129846
+ return {
129847
+ ...typeInfo,
129848
+ targetTypeInfo: substituteTypeInfoForClass(
129849
+ typeInfo.targetTypeInfo,
129850
+ schemaClass2
129851
+ )
129852
+ };
129853
+ }
129759
129854
  if (typeInfo.type === 25 && Array.isArray(typeInfo.argumentTypes)) {
129760
129855
  return {
129761
129856
  ...typeInfo,
@@ -130224,11 +130319,10 @@ function assertOpaqueConstructorValid(declaredConstructor) {
130224
130319
  );
130225
130320
  }
130226
130321
  const argumentTypes = declaredConstructor.argumentTypes;
130227
- if (!argumentTypes.every(isOpaqueCallableArgumentTypeInfo)) {
130228
- throw new Error(
130229
- `Constructor "${declaredConstructor.id}" argumentTypes are invalid.`
130230
- );
130231
- }
130322
+ assertOpaqueCallableArgumentsValid(
130323
+ argumentTypes,
130324
+ `Constructor "${declaredConstructor.id}"`
130325
+ );
130232
130326
  const names = /* @__PURE__ */ new Set();
130233
130327
  for (const argument2 of argumentTypes) {
130234
130328
  const name = argument2.name;
@@ -130529,9 +130623,10 @@ function assertOpaqueNSFunctionValid(member, membersById, typeInfoInDeclaringCla
130529
130623
  if (!Array.isArray(member.argumentTypes)) {
130530
130624
  throw new Error(`NSFunction "${member.id}" argumentTypes are invalid.`);
130531
130625
  }
130532
- if (!member.argumentTypes.every(isOpaqueCallableArgumentTypeInfo)) {
130533
- throw new Error(`NSFunction "${member.id}" has an invalid argument type.`);
130534
- }
130626
+ assertOpaqueCallableArgumentsValid(
130627
+ member.argumentTypes,
130628
+ `NSFunction "${member.id}"`
130629
+ );
130535
130630
  const argumentNames = /* @__PURE__ */ new Set();
130536
130631
  for (const argument2 of member.argumentTypes) {
130537
130632
  const name = argument2.name;
@@ -181269,7 +181364,12 @@ function generateMember(ctx, schemaKey, memberId, saved, modifier, emitBody, own
181269
181364
  );
181270
181365
  }
181271
181366
  if (isMemberClassBase(member) && (ctx.worldKinds.get(member.classId) ?? null) === NeoWorldSystemClassKind.AnimationClip) {
181272
- const targetType = animationClipTargetType(ctx, member, genericEnv);
181367
+ const targetType = animationClipTargetType(
181368
+ ctx,
181369
+ member,
181370
+ genericEnv,
181371
+ ownerClassId
181372
+ );
181273
181373
  if (targetType === null) {
181274
181374
  return [`// Skipped invalid animation clip member: ${memberName}`];
181275
181375
  }
@@ -181288,7 +181388,7 @@ function generateMember(ctx, schemaKey, memberId, saved, modifier, emitBody, own
181288
181388
  "get",
181289
181389
  "{",
181290
181390
  ...indent([
181291
- `return client.GetOrCreateAnimationClip(this, "${escapeCSharpString(schemaKey)}");`
181391
+ `return client.GetOrCreateAnimationClip<${targetType}>(this, "${escapeCSharpString(schemaKey)}");`
181292
181392
  ]),
181293
181393
  "}"
181294
181394
  ]),
@@ -183325,7 +183425,7 @@ function lookupSelectionFactory(ctx, member, selection2, saved, writeGuardMember
183325
183425
  const targetClass = lookupTargetClassProjection(ctx, member, genericEnv);
183326
183426
  if (targetClass === null) return null;
183327
183427
  const typeName = ctx.typeNames.get(targetClass.classId) ?? "NeoNode";
183328
- const savedTypeRef = qualifyGeneratedType(ctx, savedTypeName(typeName));
183428
+ const savedTypeRef = `${qualifyGeneratedType(ctx, savedTypeName(typeName))}${targetClass.constructedSuffix}`;
183329
183429
  const writable = `writable${selection2[0].toUpperCase()}${selection2.slice(1)}`;
183330
183430
  if (lookupHasRuntimeOwnership(member) && schemaClassHasWritableFamily(ctx, targetClass.classId))
183331
183431
  return `${selection2} is NeoMemberClassWritable ${writable} ? ${savedTypeRef}.CreateWritable(client, ${writable}) : ${savedTypeRef}.Create(client, (NeoMemberClass)${selection2})`;
@@ -187038,7 +187138,7 @@ var UNITY_CODEGEN_REVISION;
187038
187138
  var init_unity_codegen_revision = __esm({
187039
187139
  "../src/models/exports/unity-codegen-revision.ts"() {
187040
187140
  "use strict";
187041
- UNITY_CODEGEN_REVISION = "4eae63e39962f0ceb684c43fe8932b031b420c82ad6319670c46608bd9cd1470";
187141
+ UNITY_CODEGEN_REVISION = "2734215e6a19e5f077e5f76093f84e82b0ee6fe9e3bc92a4f44c43c2448c63ba";
187042
187142
  }
187043
187143
  });
187044
187144
 
@@ -208017,7 +208117,7 @@ var releaseWorkspaceLock = () => void 0;
208017
208117
  async function main() {
208018
208118
  const args = parseArgs(process.argv.slice(2));
208019
208119
  if (args.command === "--version") {
208020
- console.log("0.82.3");
208120
+ console.log("0.82.5");
208021
208121
  return;
208022
208122
  }
208023
208123
  if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {
@@ -60511,7 +60511,7 @@ function csharpPropertyValueType(ctx, member, saved = false, env, genericBinding
60511
60511
  }
60512
60512
  return csharpValueType(ctx, member, saved, env, genericBindingSaved);
60513
60513
  }
60514
- function animationClipTargetType(ctx, member, env) {
60514
+ function animationClipTargetType(ctx, member, env, ownerClassId) {
60515
60515
  const clipClass = resolveInheritanceChain(member.classId, ctx.classes).find(
60516
60516
  (candidate) => candidate.system?.worldKind === NeoWorldSystemClassKind.AnimationClip
60517
60517
  );
@@ -60592,7 +60592,47 @@ function animationClipTargetType(ctx, member, env) {
60592
60592
  });
60593
60593
  return null;
60594
60594
  }
60595
- return targetType;
60595
+ const suffix = constructedTypeArgumentsSuffix(ctx, bindingMember, true, env);
60596
+ if (suffix === null) return null;
60597
+ const constructedTarget = `${targetType}${suffix}`;
60598
+ if (ownerClassId !== void 0) {
60599
+ const ownerName = ctx.typeNames.get(ownerClassId) ?? ownerClassId;
60600
+ if (!resolveInheritanceChain(ownerClassId, ctx.classes).some(
60601
+ (ancestor) => ancestor.id === bindingMember.classId
60602
+ )) {
60603
+ ctx.diagnostics.push({
60604
+ severity: "error",
60605
+ message: `Animation clip "${member.name}" targets ${constructedTarget}, which is not its owner ${ownerName} or a base of it.`,
60606
+ path: memberPath
60607
+ });
60608
+ return null;
60609
+ }
60610
+ const ownerArguments = [];
60611
+ for (const { param } of resolveGenericScopeForEmission(
60612
+ ctx,
60613
+ bindingMember.classId
60614
+ )) {
60615
+ const argument2 = csharpGenericParamType(
60616
+ ctx,
60617
+ param.id,
60618
+ true,
60619
+ env,
60620
+ memberPath
60621
+ );
60622
+ if (argument2 === null) return null;
60623
+ ownerArguments.push(argument2);
60624
+ }
60625
+ const ownerTarget = `${targetType}${ownerArguments.length === 0 ? "" : `<${ownerArguments.join(", ")}>`}`;
60626
+ if (ownerTarget !== constructedTarget) {
60627
+ ctx.diagnostics.push({
60628
+ severity: "error",
60629
+ message: `Animation clip "${member.name}" targets ${constructedTarget}, but owner ${ownerName} has target type ${ownerTarget}. A clip must target its owner or a constructed base of it.`,
60630
+ path: memberPath
60631
+ });
60632
+ return null;
60633
+ }
60634
+ }
60635
+ return constructedTarget;
60596
60636
  }
60597
60637
  function csharpTypeInfoValueType(ctx, typeInfo, saved, genericEnv, genericBindingSaved = saved) {
60598
60638
  const optional2 = !typeInfo.required;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neocompose/cli",
3
- "version": "0.82.3",
3
+ "version": "0.82.5",
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.82.3 -->
12
+ <!-- reviewed-through-cli: 0.82.5 -->
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.82.3 -->
132
+ <!-- reviewed-through-cli: 0.82.5 -->
133
133
  ```
134
134
 
135
135
  The quoted version above is checked too, so this instruction cannot go stale
@@ -331,6 +331,10 @@ to earlier content reuses that result after verifying output bytes; changed or
331
331
  missing outputs are regenerated. Edited content is validated
332
332
  even when C# generation is skipped. After a CLI code-generation fix, run
333
333
  `neo export` again; generator revision changes invalidate cached C# output.
334
+ Generated animation clip targets and reference lookup factories retain constructed
335
+ generic arguments, including supported forwarded bindings. Clip getters use the
336
+ declared target type when the owner is a derived class. Export reports an error
337
+ when a clip target does not match the owner or one of its constructed base types.
334
338
  New instances that reuse existing member-localized text retain its shared ID
335
339
  and translations in the export.
336
340
 
@@ -256,11 +256,11 @@ code types; see the NeoScript reference for handle and slot references.
256
256
  `public Reference<Config> Config` selects one row and reads as `Config`.
257
257
  `public Set<Reference<Config>> Configs` selects several and reads as
258
258
  `Set<Config>`. `public Reference<int> TrackedStat` names another member's int.
259
- `Reference<T>` also works as a collection element, a dictionary value, and an
260
- unbound generic argument such as `Box<Reference<int>>`. An initializer body for
261
- a single reference returns one row, never a set. `T` with
262
- `@settings(collection:)` is an error; the language server's quick fix respells
263
- it.
259
+ `Reference<T>` also works as a constructor or method parameter, a collection
260
+ element, a dictionary value, and an unbound generic argument such as
261
+ `Box<Reference<int>>`. An initializer body for a single reference returns one
262
+ row, never a set. `T` with `@settings(collection:)` is an error; the language
263
+ server's quick fix respells it.
264
264
 
265
265
  `@settings(collection: Owner.Member)` binds a class reference to one
266
266
  collection. Without it the reference is unbound: it selects any stored row of