@neocompose/cli 0.71.0 → 0.71.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.
@@ -33573,6 +33573,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
33573
33573
  tryMutationContexts = [];
33574
33574
  functionControlBoundaries = [];
33575
33575
  debugSource;
33576
+ inferredExpressionReturnType;
33576
33577
  initialScope() {
33577
33578
  const scope = new Scope(null, this.options.onFlowScope !== void 0);
33578
33579
  scope.define(
@@ -33777,6 +33778,23 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
33777
33778
  this.context.kind === "action" || this.context.kind === "setter" || this.context.kind === "constructor" || isVoid(this.context.returnType),
33778
33779
  describeUnitKind(this.context.kind)
33779
33780
  );
33781
+ if (this.options.inferExpressionReturnType) {
33782
+ if (this.context.kind !== "getter")
33783
+ throw new CompileError(
33784
+ "Expression inference requires a getter.",
33785
+ body.pos
33786
+ );
33787
+ if (statements.length !== 1)
33788
+ throw new CompileError(
33789
+ "Expression inference requires one return expression.",
33790
+ body.pos
33791
+ );
33792
+ if (statements[0]?.kind !== "return" || statements[0].expr === null)
33793
+ throw new CompileError(
33794
+ "Expression inference requires a returned value.",
33795
+ body.pos
33796
+ );
33797
+ }
33780
33798
  const instructions = this.resolveStatements(statements, scope);
33781
33799
  if ((this.context.kind === "function" || this.context.kind === "getter" || this.context.kind === "condition" || this.context.kind === "initializer") && !isVoid(this.context.returnType) && !instructionsTerminate(instructions)) {
33782
33800
  throw new CompileError(
@@ -33793,7 +33811,10 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
33793
33811
  source: this.debugSource,
33794
33812
  parameters,
33795
33813
  instructions,
33796
- typeInfo: toWireType(returnType, this.project)
33814
+ typeInfo: toWireType(
33815
+ this.inferredExpressionReturnType ?? returnType,
33816
+ this.project
33817
+ )
33797
33818
  };
33798
33819
  } finally {
33799
33820
  this.expectedReturnStack.pop();
@@ -34595,10 +34616,11 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
34595
34616
  }
34596
34617
  const inference = this.lambdaReturnInference.at(-1);
34597
34618
  const inferring = inference?.depth === this.lambdaDepth;
34619
+ const inferExpression = this.options.inferExpressionReturnType && this.lambdaDepth === 0;
34598
34620
  const value = this.resolveExpression(
34599
34621
  statement.expr,
34600
34622
  scope,
34601
- inferring ? void 0 : expected
34623
+ inferring || inferExpression ? void 0 : expected
34602
34624
  );
34603
34625
  if (inferring) {
34604
34626
  inference.returns.push({
@@ -34618,12 +34640,21 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
34618
34640
  statement.pos
34619
34641
  );
34620
34642
  }
34621
- this.requireAssignable(
34622
- value.type,
34623
- expected,
34624
- statement.expr.pos,
34625
- "return"
34626
- );
34643
+ if (inferExpression) {
34644
+ if (isVoid(value.type))
34645
+ throw new CompileError(
34646
+ "A text expression must return a value, not void.",
34647
+ statement.expr.pos
34648
+ );
34649
+ this.inferredExpressionReturnType = value.type;
34650
+ } else {
34651
+ this.requireAssignable(
34652
+ value.type,
34653
+ expected,
34654
+ statement.expr.pos,
34655
+ "return"
34656
+ );
34657
+ }
34627
34658
  return {
34628
34659
  type: "return" /* Return */,
34629
34660
  pointer: value.pointer
@@ -42677,7 +42708,8 @@ function compileNeoScriptStrict(document2, context, options = {}) {
42677
42708
  {
42678
42709
  source: options.source,
42679
42710
  onFlowScope: options.onFlowScope,
42680
- sourceUri: document2.uri
42711
+ sourceUri: document2.uri,
42712
+ inferExpressionReturnType: options.inferExpressionReturnType
42681
42713
  }
42682
42714
  ).compile(ast);
42683
42715
  const ir = attachDependencyManifest(
@@ -46261,6 +46293,20 @@ function compileNSGetter(code, ctx) {
46261
46293
  ctx.source
46262
46294
  );
46263
46295
  }
46296
+ function compileNSInferredExpressionGetter(code, ctx) {
46297
+ const compiled = compileStrict(
46298
+ code,
46299
+ createContext(ctx, {
46300
+ scriptKind: "getter",
46301
+ dialogueContext: ctx.dialogueContext
46302
+ }),
46303
+ ctx.source,
46304
+ true
46305
+ );
46306
+ if (!isNSGetter(compiled))
46307
+ throw new Error("Expression compiler did not produce a getter.");
46308
+ return compiled;
46309
+ }
46264
46310
  function compileNSVoidBody(code, ctx) {
46265
46311
  const context = createContext(ctx, {
46266
46312
  scriptKind: "action",
@@ -46359,9 +46405,10 @@ function withInitializerSourcePosition(error) {
46359
46405
  error.unit
46360
46406
  );
46361
46407
  }
46362
- function compileStrict(code, context, sourceInfo) {
46408
+ function compileStrict(code, context, sourceInfo, inferExpressionReturnType = false) {
46363
46409
  const source = sourceInfo?.code === code ? sourceInfo.source : void 0;
46364
46410
  const cacheKey = JSON.stringify({
46411
+ inferExpressionReturnType,
46365
46412
  code,
46366
46413
  source,
46367
46414
  projectIdentity: compilationProjectIdentity(context.project),
@@ -46394,7 +46441,11 @@ function compileStrict(code, context, sourceInfo) {
46394
46441
  text: code
46395
46442
  },
46396
46443
  context,
46397
- { projectIndex: compilationProjectIndex(context.project), source }
46444
+ {
46445
+ projectIndex: compilationProjectIndex(context.project),
46446
+ source,
46447
+ inferExpressionReturnType
46448
+ }
46398
46449
  );
46399
46450
  if (result.diagnostics.length) {
46400
46451
  const error = result.diagnostics[0];
@@ -46513,6 +46564,7 @@ __export(compiler_adapter_exports, {
46513
46564
  compileNSConstructor: () => compileNSConstructor,
46514
46565
  compileNSFunction: () => compileNSFunction,
46515
46566
  compileNSGetter: () => compileNSGetter,
46567
+ compileNSInferredExpressionGetter: () => compileNSInferredExpressionGetter,
46516
46568
  compileNSInitializer: () => compileNSInitializer,
46517
46569
  compileNSSetter: () => compileNSSetter,
46518
46570
  compileNSVoidBody: () => compileNSVoidBody,
@@ -52912,61 +52964,6 @@ function invalidDocument(record4, path, message) {
52912
52964
  );
52913
52965
  }
52914
52966
 
52915
- // src/project-source/structured-leaf-source.ts
52916
- var STRUCTURED_LEAF_SOURCE_FORMS = {
52917
- sprite: { kind: 11 /* Sprite */, typeName: "SpriteInfo" },
52918
- vector2: { kind: 14 /* Vector2 */, typeName: "Vector2" },
52919
- vector2Int: { kind: 15 /* Vector2Int */, typeName: "Vector2Int" },
52920
- vector3: { kind: 16 /* Vector3 */, typeName: "Vector3" },
52921
- vector3Int: { kind: 17 /* Vector3Int */, typeName: "Vector3Int" },
52922
- color: { kind: 19 /* Color */, typeName: "Color" }
52923
- };
52924
- var STRUCTURED_LEAF_SOURCE_ENTRIES = Object.entries(STRUCTURED_LEAF_SOURCE_FORMS);
52925
-
52926
- // src/project-source/member-kind-type-names.ts
52927
- var MEMBER_KIND_SOURCE_TYPE_NAMES = {
52928
- null: "null",
52929
- bool: "bool",
52930
- int: "int",
52931
- string: "string",
52932
- float: "float",
52933
- decimal: "decimal",
52934
- sprite: "SpriteInfo",
52935
- audio: "AudioClipInfo",
52936
- vector2: "Vector2",
52937
- vector2Int: "Vector2Int",
52938
- vector3: "Vector3",
52939
- vector3Int: "Vector3Int",
52940
- color: "Color"
52941
- };
52942
- var MEMBER_KIND_NUMBERS = {
52943
- null: 0 /* Null */,
52944
- bool: 1 /* Bool */,
52945
- int: 2 /* Int */,
52946
- string: 3 /* String */,
52947
- float: 4 /* Float */,
52948
- decimal: 20 /* Decimal */,
52949
- sprite: 11 /* Sprite */,
52950
- audio: 12 /* Audio */,
52951
- vector2: 14 /* Vector2 */,
52952
- vector2Int: 15 /* Vector2Int */,
52953
- vector3: 16 /* Vector3 */,
52954
- vector3Int: 17 /* Vector3Int */,
52955
- color: 19 /* Color */
52956
- };
52957
- var SOURCE_TYPE_NAME_BY_MEMBER_KIND_NUMBER = new Map(
52958
- Object.entries(MEMBER_KIND_NUMBERS).map(([slug, kind]) => [
52959
- kind,
52960
- MEMBER_KIND_SOURCE_TYPE_NAMES[slug]
52961
- ])
52962
- );
52963
-
52964
- // src/project-source/value-sources.ts
52965
- var INITIALIZER_KEY_PLACEHOLDER = new RegExp(
52966
- `${PENDING_ID_PREFIX}reference-key:init:\\d+`,
52967
- "g"
52968
- );
52969
-
52970
52967
  // src/project-manifest/record-adapters/enum.ts
52971
52968
  var ENUM_SCHEMA_RECORD_ADAPTER = {
52972
52969
  recordKind: "enum",
@@ -54021,6 +54018,61 @@ var SCHEMA_RECORD_ADAPTERS = [
54021
54018
  SCHEMA_RECORD_ADAPTER_REGISTRY["internal-record-relation"]
54022
54019
  ];
54023
54020
 
54021
+ // src/project-source/structured-leaf-source.ts
54022
+ var STRUCTURED_LEAF_SOURCE_FORMS = {
54023
+ sprite: { kind: 11 /* Sprite */, typeName: "SpriteInfo" },
54024
+ vector2: { kind: 14 /* Vector2 */, typeName: "Vector2" },
54025
+ vector2Int: { kind: 15 /* Vector2Int */, typeName: "Vector2Int" },
54026
+ vector3: { kind: 16 /* Vector3 */, typeName: "Vector3" },
54027
+ vector3Int: { kind: 17 /* Vector3Int */, typeName: "Vector3Int" },
54028
+ color: { kind: 19 /* Color */, typeName: "Color" }
54029
+ };
54030
+ var STRUCTURED_LEAF_SOURCE_ENTRIES = Object.entries(STRUCTURED_LEAF_SOURCE_FORMS);
54031
+
54032
+ // src/project-source/member-kind-type-names.ts
54033
+ var MEMBER_KIND_SOURCE_TYPE_NAMES = {
54034
+ null: "null",
54035
+ bool: "bool",
54036
+ int: "int",
54037
+ string: "string",
54038
+ float: "float",
54039
+ decimal: "decimal",
54040
+ sprite: "SpriteInfo",
54041
+ audio: "AudioClipInfo",
54042
+ vector2: "Vector2",
54043
+ vector2Int: "Vector2Int",
54044
+ vector3: "Vector3",
54045
+ vector3Int: "Vector3Int",
54046
+ color: "Color"
54047
+ };
54048
+ var MEMBER_KIND_NUMBERS = {
54049
+ null: 0 /* Null */,
54050
+ bool: 1 /* Bool */,
54051
+ int: 2 /* Int */,
54052
+ string: 3 /* String */,
54053
+ float: 4 /* Float */,
54054
+ decimal: 20 /* Decimal */,
54055
+ sprite: 11 /* Sprite */,
54056
+ audio: 12 /* Audio */,
54057
+ vector2: 14 /* Vector2 */,
54058
+ vector2Int: 15 /* Vector2Int */,
54059
+ vector3: 16 /* Vector3 */,
54060
+ vector3Int: 17 /* Vector3Int */,
54061
+ color: 19 /* Color */
54062
+ };
54063
+ var SOURCE_TYPE_NAME_BY_MEMBER_KIND_NUMBER = new Map(
54064
+ Object.entries(MEMBER_KIND_NUMBERS).map(([slug, kind]) => [
54065
+ kind,
54066
+ MEMBER_KIND_SOURCE_TYPE_NAMES[slug]
54067
+ ])
54068
+ );
54069
+
54070
+ // src/project-source/value-sources.ts
54071
+ var INITIALIZER_KEY_PLACEHOLDER = new RegExp(
54072
+ `${PENDING_ID_PREFIX}reference-key:init:\\d+`,
54073
+ "g"
54074
+ );
54075
+
54024
54076
  // ../packages/neoscript-language/src/project-schema-contract.generated.ts
54025
54077
  var PROJECT_FILE_UPLOAD_BATCH_SIZE = 32;
54026
54078
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neocompose/cli",
3
- "version": "0.71.0",
3
+ "version": "0.71.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.71.0 -->
12
+ <!-- reviewed-through-cli: 0.71.2 -->
13
13
 
14
14
  # Neo Compose CLI
15
15
 
@@ -71,7 +71,7 @@ live in `packages/manifest`. Contract generation and its registry live in
71
71
 
72
72
  The CLI uses plain document snapshots and shared runtime functions. Keep Retree and web view models out of its imports. The headless architecture check follows CLI imports, and `cli/build.mjs` rejects UI modules and packages in the actual bundle metadata.
73
73
 
74
- Keep parsing, strict resolution, formatting, diagnostics, symbols, and
74
+ Keep parsing, strict resolution, formatting, diagnostics with authored file and expression ranges, symbols, and
75
75
  NeoScript compilation in the browser-safe `@neocompose/neoscript-language`
76
76
  service. Monaco, VS Code, CLI, trusted server, and corpus tooling must consume
77
77
  that shared implementation. Do not add language intelligence to one adapter.
@@ -95,7 +95,10 @@ bases. A modified CLI can therefore write bad rows to a project its user may
95
95
  already write; keep preparation in shared `src/database` code rather than
96
96
  forking it in the CLI. The server still verifies a push's uploaded
97
97
  project-file bytes, and web editor commits use the shared client preparation protocol.
98
- Unrelated source files are not uploaded or recompiled on every push. A CLI lowering mismatch on a normal push is exposed by the next
98
+ Unrelated source files are not uploaded or recompiled on every push.
99
+ Optional source maps missing from valid stored bodies do not request a backfill.
100
+ Existing map changes still refresh locations on push; authored edits, dependency
101
+ changes, and explicit forced recompilation retain their normal compile scope. A CLI lowering mismatch on a normal push is exposed by the next
99
102
  canonical pull; `neo push --dry-run` remains the complete source-to-record
100
103
  rehearsal.
101
104
 
@@ -115,7 +118,7 @@ wrappers.
115
118
  The marker near the top of `SKILL.md` must exactly match the package version:
116
119
 
117
120
  ```html
118
- <!-- reviewed-through-cli: 0.71.0 -->
121
+ <!-- reviewed-through-cli: 0.71.2 -->
119
122
  ```
120
123
 
121
124
  The quoted version above is checked too, so this instruction cannot go stale
@@ -301,7 +301,9 @@ changed, skips codegen when only values changed since the last export into
301
301
  that Unity project, and writes `Library/NeoCompose/export.json` last for
302
302
  Unity to ingest.
303
303
 
304
- - A clean working copy exports the last pull. Local edits, `Files/` bytes
304
+ - A clean working copy exports the pulled head. Diagnostic location differences
305
+ alone, including line shifts after push inserts ids, do not make it local.
306
+ Local edits, `Files/` bytes
305
307
  included, make the export local: `project.json` gets
306
308
  `metadata.localExport`, Unity fails player builds and keeps saves under
307
309
  `NeoCompose/LocalExport`, and a push or a clean export ends it.