@neocompose/cli 0.36.0 → 0.36.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.36.2] - 2026-08-19
4
+
5
+ ### Fixed
6
+
7
+ - Report invalid ordinary member initializers at their authored file and token
8
+ in the CLI and editor. C# numeric suffixes such as `0f` now explain that the
9
+ suffix should be removed instead of surfacing as `<project>:1:1` with an EOF
10
+ parser error.
11
+ - Accept `null` as the literal default of a nullable `NeoDelegate`, preventing
12
+ valid pending delegate members from failing prospective project,
13
+ initializer-materialization, and animation validation.
14
+
15
+ ## [0.36.1] - 2026-08-19
16
+
17
+ ### Fixed
18
+
19
+ - Preserve authored function parameter defaults in live project-source symbols,
20
+ so calls may omit a defaulted trailing argument and hover/signature help show
21
+ the declared `= value`.
22
+ - Store direct field and property reads, including static getters such as
23
+ `FeatureFlags.StartInventorySize`, as executable member initializers instead
24
+ of rejecting them as unresolved persisted literals.
25
+
3
26
  ## [0.36.0] - 2026-08-19
4
27
 
5
28
  ### Added
package/dist/neo.mjs CHANGED
@@ -22973,7 +22973,15 @@ function validateDeclaration(uri, declaration, documentKind, environment, diagno
22973
22973
  scope.set(member.name, semanticType(member.type));
22974
22974
  }
22975
22975
  for (const member of declaration.members) {
22976
- validateMember(uri, member, documentKind, scope, environment, diagnostics);
22976
+ validateMember(
22977
+ uri,
22978
+ member,
22979
+ declaration.name,
22980
+ documentKind,
22981
+ scope,
22982
+ environment,
22983
+ diagnostics
22984
+ );
22977
22985
  }
22978
22986
  if (declaration.kind === "class") {
22979
22987
  validateRetiredParameterReads(uri, declaration, scope, diagnostics);
@@ -23243,7 +23251,7 @@ function slotPosition(start, pos) {
23243
23251
  }
23244
23252
  return { line: start.line + pos.line - 1, character: pos.column - 1 };
23245
23253
  }
23246
- function validateMember(uri, member, documentKind, ownerScope, environment, diagnostics) {
23254
+ function validateMember(uri, member, ownerName, documentKind, ownerScope, environment, diagnostics) {
23247
23255
  const memberType2 = semanticType(member.type);
23248
23256
  validateAnnotations(
23249
23257
  uri,
@@ -23285,7 +23293,11 @@ function validateMember(uri, member, documentKind, ownerScope, environment, diag
23285
23293
  environment,
23286
23294
  member.initializer.range,
23287
23295
  diagnostics,
23288
- anchorOf(member.initializer)
23296
+ anchorOf(member.initializer),
23297
+ {
23298
+ code: "invalid-project-member-initializer",
23299
+ label: `Member '${ownerName}.${member.name}' initializer`
23300
+ }
23289
23301
  );
23290
23302
  }
23291
23303
  if (documentKind === "flow" && member.flowInitializer?.body?.kind === "block") {
@@ -23789,7 +23801,7 @@ function settingsClassFields(name) {
23789
23801
  function anchorOf(source) {
23790
23802
  return { text: source.text, start: source.range.start };
23791
23803
  }
23792
- function validateExpressionText(uri, text, expected, scope, environment, range2, diagnostics, anchor) {
23804
+ function validateExpressionText(uri, text, expected, scope, environment, range2, diagnostics, anchor, syntaxDiagnostic) {
23793
23805
  try {
23794
23806
  validateExpression(
23795
23807
  parseExpression(text),
@@ -23803,8 +23815,38 @@ function validateExpressionText(uri, text, expected, scope, environment, range2,
23803
23815
  );
23804
23816
  } catch (error) {
23805
23817
  if (!(error instanceof CompileError)) throw error;
23818
+ if (syntaxDiagnostic !== void 0) {
23819
+ const errorRange = anchor === void 0 ? range2 : anchorSpan(
23820
+ anchor,
23821
+ { line: error.line, column: error.column },
23822
+ anchorOffset(anchor, error) < text.length ? 1 : 0
23823
+ );
23824
+ pushDiagnostic(
23825
+ diagnostics,
23826
+ uri,
23827
+ errorRange,
23828
+ syntaxDiagnostic.code,
23829
+ memberInitializerSyntaxMessage(syntaxDiagnostic.label, text, error)
23830
+ );
23831
+ return;
23832
+ }
23806
23833
  }
23807
23834
  }
23835
+ function memberInitializerSyntaxMessage(label, text, error) {
23836
+ const anchor = {
23837
+ text,
23838
+ start: { line: 0, character: 0 }
23839
+ };
23840
+ const offset = anchorOffset(anchor, error);
23841
+ const suffix = text[offset];
23842
+ const previous = text[offset - 1];
23843
+ const next = text[offset + 1];
23844
+ if (suffix !== void 0 && previous !== void 0 && /[fFdDmM]/u.test(suffix) && /[0-9]/u.test(previous) && (next === void 0 || !/[A-Za-z0-9_]/u.test(next))) {
23845
+ return `${label} uses unsupported C# numeric suffix '${suffix}'. NeoScript numeric literals do not use suffixes; remove '${suffix}'.`;
23846
+ }
23847
+ const detail = error.message.replace(/^\d+:\d+:\s*/u, "");
23848
+ return `${label} could not be parsed: ${detail}`;
23849
+ }
23808
23850
  function validateFunctionBody(uri, text, returnType, scope, environment, range2, diagnostics) {
23809
23851
  try {
23810
23852
  const source = stripOuterBraces2(text);
@@ -25290,13 +25332,14 @@ function compileProjectSourceBodies(documents) {
25290
25332
  implicitMemberAccess: true,
25291
25333
  staticMember: false,
25292
25334
  kind: "constructor",
25293
- parameters: constructor2.parameters.map((parameter4, index) => ({
25294
- id: `${declaredConstructorId(owner, declaration, constructor2)}:argument:${index}`,
25295
- name: parameter4.name,
25296
- type: sourceTypeRef(parameter4.type, owner, graph.typeIdsByName),
25297
- location: location(uri, parameter4.range),
25298
- selectionLocation: location(uri, parameter4.nameRange)
25299
- })),
25335
+ parameters: constructor2.parameters.map(
25336
+ (parameter4, index) => sourceParameter(
25337
+ parameter4,
25338
+ owner,
25339
+ graph.typeIdsByName,
25340
+ `${declaredConstructorId(owner, declaration, constructor2)}:argument:${index}`
25341
+ )
25342
+ ),
25300
25343
  functionName: constructor2.name
25301
25344
  },
25302
25345
  projectIndex,
@@ -25325,13 +25368,12 @@ function compileProjectSourceBodies(documents) {
25325
25368
  staticMember: false,
25326
25369
  kind: "constructor",
25327
25370
  parameters: (declaration.headerParameters ?? []).map(
25328
- (parameter4, index) => ({
25329
- id: `${initId}:argument:${index}`,
25330
- name: parameter4.name,
25331
- type: sourceTypeRef(parameter4.type, owner, graph.typeIdsByName),
25332
- location: location(uri, parameter4.range),
25333
- selectionLocation: location(uri, parameter4.nameRange)
25334
- })
25371
+ (parameter4, index) => sourceParameter(
25372
+ parameter4,
25373
+ owner,
25374
+ graph.typeIdsByName,
25375
+ `${initId}:argument:${index}`
25376
+ )
25335
25377
  ),
25336
25378
  functionName: "init"
25337
25379
  },
@@ -25368,13 +25410,14 @@ function compileProjectSourceBodies(documents) {
25368
25410
  context: {
25369
25411
  ...baseContext2,
25370
25412
  kind: "function",
25371
- parameters: member.parameters.map((parameter4, index) => ({
25372
- id: `${info.symbol.id}:argument:${index}`,
25373
- name: parameter4.name,
25374
- type: sourceTypeRef(parameter4.type, owner, graph.typeIdsByName),
25375
- location: location(uri, parameter4.range),
25376
- selectionLocation: location(uri, parameter4.nameRange)
25377
- })),
25413
+ parameters: member.parameters.map(
25414
+ (parameter4, index) => sourceParameter(
25415
+ parameter4,
25416
+ owner,
25417
+ graph.typeIdsByName,
25418
+ `${info.symbol.id}:argument:${index}`
25419
+ )
25420
+ ),
25378
25421
  deferred: member.modifiers.includes("async"),
25379
25422
  functionName: member.name
25380
25423
  },
@@ -25741,13 +25784,9 @@ function sourceMemberSymbol(member, owner, typeIds, source) {
25741
25784
  ...common,
25742
25785
  kind: "function",
25743
25786
  returnType: type,
25744
- parameters: member.parameters.map((parameter4, index) => ({
25745
- id: `${id2}:argument:${index}`,
25746
- name: parameter4.name,
25747
- type: sourceTypeRef(parameter4.type, owner, typeIds),
25748
- location: location(owner.uri, parameter4.range),
25749
- selectionLocation: location(owner.uri, parameter4.nameRange)
25750
- })),
25787
+ parameters: member.parameters.map(
25788
+ (parameter4, index) => sourceParameter(parameter4, owner, typeIds, `${id2}:argument:${index}`)
25789
+ ),
25751
25790
  deferred: member.modifiers.includes("async"),
25752
25791
  ...member.modifiers.includes("native") ? { native: true } : {}
25753
25792
  };
@@ -25819,8 +25858,7 @@ function requiredConstructorSymbol(owner, declaration, typeIds) {
25819
25858
  return {
25820
25859
  id: requiredConstructorBodyId(owner),
25821
25860
  parameters: headerParameters.map((parameter4) => ({
25822
- name: parameter4.name,
25823
- type: sourceTypeRef(parameter4.type, owner, typeIds),
25861
+ ...sourceParameter(parameter4, owner, typeIds),
25824
25862
  required: !parameter4.type.nullable
25825
25863
  })),
25826
25864
  required: true,
@@ -25831,14 +25869,23 @@ function declaredConstructorSymbol(owner, declaration, constructor2, typeIds) {
25831
25869
  return {
25832
25870
  id: declaredConstructorId(owner, declaration, constructor2),
25833
25871
  parameters: constructor2.parameters.map((parameter4) => ({
25834
- name: parameter4.name,
25835
- type: sourceTypeRef(parameter4.type, owner, typeIds),
25872
+ ...sourceParameter(parameter4, owner, typeIds),
25836
25873
  required: !parameter4.type.nullable
25837
25874
  })),
25838
25875
  ...constructor2.docsText ? { documentation: constructor2.docsText } : {},
25839
25876
  location: location(owner.uri, constructor2.range)
25840
25877
  };
25841
25878
  }
25879
+ function sourceParameter(parameter4, owner, typeIds, id2) {
25880
+ return {
25881
+ ...id2 === void 0 ? {} : { id: id2 },
25882
+ name: parameter4.name,
25883
+ type: sourceTypeRef(parameter4.type, owner, typeIds),
25884
+ ...parameter4.defaultValue === void 0 ? {} : { defaultValue: { displayText: parameter4.defaultValue.text } },
25885
+ location: location(owner.uri, parameter4.range),
25886
+ selectionLocation: location(owner.uri, parameter4.nameRange)
25887
+ };
25888
+ }
25842
25889
  function substituteInheritedSourceMember(member, baseInfo, resolvedBaseType) {
25843
25890
  if (baseInfo.declaration.kind !== "class" || resolvedBaseType.kind !== "named") {
25844
25891
  return {
@@ -44533,6 +44580,7 @@ function isMemberDelegateBase(value) {
44533
44580
  if (defaultValue === void 0 || defaultValue === null) return true;
44534
44581
  if (!isMemberValueBase(defaultValue)) return false;
44535
44582
  if (isInitValueContent(defaultValue)) return true;
44583
+ if (defaultValue.value === null) return v.required === false;
44536
44584
  return isNSDelegateValue(defaultValue.value);
44537
44585
  }
44538
44586
  function nsActionListenerIdentity(listener) {
@@ -59730,6 +59778,7 @@ function lowerExpressionValue(context, expression, declaredExpected, ownerClass,
59730
59778
  function positionRequiresEvaluation(context, expression, expected, ownerClass) {
59731
59779
  if (isStoredDelegateLiteral(expected, expression)) return false;
59732
59780
  if (isStoredActionLiteral(expected, expression)) return false;
59781
+ if (isSourceMemberValueRead(context, expression, ownerClass)) return true;
59733
59782
  return initializerRequiresEvaluation(
59734
59783
  context.declaredConstructors,
59735
59784
  expression,
@@ -59740,6 +59789,36 @@ function positionRequiresEvaluation(context, expression, expected, ownerClass) {
59740
59789
  )
59741
59790
  );
59742
59791
  }
59792
+ function isSourceMemberValueRead(context, expression, ownerClass) {
59793
+ let current = expression;
59794
+ while (current.kind === "annotated") current = current.expression;
59795
+ const path = expressionMemberPath(current);
59796
+ if (path === null) return false;
59797
+ const parts = path.split(".");
59798
+ let classId;
59799
+ let memberName;
59800
+ let requiresStatic = false;
59801
+ if (parts.length === 1 || parts.length === 2 && parts[0] === "this") {
59802
+ classId = materializedId(ownerClass, "class", ownerClass.name);
59803
+ memberName = parts.at(-1);
59804
+ } else if (parts.length === 2) {
59805
+ classId = context.classIdsByName.get(parts[0]);
59806
+ memberName = parts[1];
59807
+ requiresStatic = true;
59808
+ } else {
59809
+ const receiverPath = parts.slice(0, -1).join(".");
59810
+ classId = context.rootValueTargetsByPath.get(receiverPath)?.classId;
59811
+ memberName = parts.at(-1);
59812
+ }
59813
+ if (classId === void 0 || memberName === void 0) return false;
59814
+ const memberId = effectiveMemberIdByName(context, classId, memberName);
59815
+ if (memberId === null) return false;
59816
+ const source = context.sourceMembersById.get(memberId)?.member;
59817
+ if (source?.kind === "function") return false;
59818
+ const schema = context.loweredMembers.get(memberId) ?? context.baseMembers.get(memberId);
59819
+ const isStatic = source?.modifiers.includes("static") ?? schema?.isStatic ?? false;
59820
+ return !requiresStatic || isStatic;
59821
+ }
59743
59822
  function isStoredDelegateLiteral(type, expression) {
59744
59823
  if (type.name !== "NeoDelegate") return false;
59745
59824
  let current = expression;
@@ -113795,7 +113874,7 @@ var init_registry2 = __esm({
113795
113874
  PROJECT_SCHEMA_CONTRACT = Object.freeze({
113796
113875
  formatVersion: 3,
113797
113876
  contractVersion: "3.14",
113798
- cliVersion: "0.36.0",
113877
+ cliVersion: "0.36.2",
113799
113878
  projectFileUploadBatchSize: 32,
113800
113879
  documentRecords: {
113801
113880
  member: {
@@ -120397,7 +120476,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
120397
120476
  async function main() {
120398
120477
  const args = parseArgs(process.argv.slice(2));
120399
120478
  if (args.command === "--version") {
120400
- console.log("0.36.0");
120479
+ console.log("0.36.2");
120401
120480
  return;
120402
120481
  }
120403
120482
  if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neocompose/cli",
3
- "version": "0.36.0",
3
+ "version": "0.36.2",
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.36.0 -->
12
+ <!-- reviewed-through-cli: 0.36.2 -->
13
13
 
14
14
  # Neo Compose CLI
15
15
 
@@ -83,7 +83,7 @@ wrappers.
83
83
  The marker near the top of `SKILL.md` must exactly match the package version:
84
84
 
85
85
  ```html
86
- <!-- reviewed-through-cli: 0.36.0 -->
86
+ <!-- reviewed-through-cli: 0.36.2 -->
87
87
  ```
88
88
 
89
89
  The quoted version above is checked too, so this instruction cannot go stale
@@ -154,6 +154,16 @@ components must be numeric literals. When a computed list or dictionary entry
154
154
  carries an authored `@id`, parenthesize the expression — `@id("row")
155
155
  (A.B / A.C)` — so the annotation names the row rather than its left operand.
156
156
 
157
+ Numeric literals do not use C# suffixes: write `0` or `0.5`, not `0f` or
158
+ `0.5f`. The declared/contextual type determines whether a literal is stored as
159
+ an int, float, or decimal.
160
+
161
+ A direct field or property read is computed too, whether it is local,
162
+ qualified static, or reached through a stable root path. For example,
163
+ `protected int Slots = FeatureFlags.StartInventorySize;` evaluates the current
164
+ static field or getter whenever a new instance is constructed; it is not baked
165
+ into a persisted literal during push.
166
+
157
167
  Declare overloadable constructors as members when each constructor body owns
158
168
  its parameter scope:
159
169