@neocompose/cli 0.32.2 → 0.32.4

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,25 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.32.4] - 2026-08-18
4
+
5
+ ### Fixed
6
+
7
+ - Validate identifiers in their actual namespace so qualified member labels,
8
+ enum options, registry entries, and schema keys may reuse unrelated builtin
9
+ type or module names such as `Set`, `Dictionary`, `List`, and `Math`, while
10
+ preserving real keyword, binding, global namespace, and codegen conflicts.
11
+ - Share those contextual rules across project compilation, schema validation,
12
+ rename analysis, CLI emission, generated file registries, and server-side
13
+ validation so `neo test`, `neo script check --all`, dry runs, and pushes agree.
14
+
15
+ ## [0.32.3] - 2026-08-18
16
+
17
+ ### Fixed
18
+
19
+ - Accept exact-case builtin type tokens such as `Set` and `Dictionary` in
20
+ contextual project identifier slots, including member access and parameter
21
+ references, while continuing to reserve actual NeoScript keywords.
22
+
3
23
  ## [0.32.2] - 2026-08-18
4
24
 
5
25
  ### Fixed
package/dist/neo.mjs CHANGED
@@ -2833,12 +2833,6 @@ function referenceAtPosition(snapshot, position) {
2833
2833
  snapshot.source.offsetAt(position)
2834
2834
  );
2835
2835
  }
2836
- function isValidNeoIdentifier(name) {
2837
- return IDENTIFIER_PATTERN.test(name) && !RESERVED_NAMES.has(name);
2838
- }
2839
- function isValidRenameIdentifier(name) {
2840
- return isValidNeoIdentifier(name);
2841
- }
2842
2836
  function contextualCompletionItems(snapshot, offset, word) {
2843
2837
  const items = [];
2844
2838
  const expectedType = expectedTypeAt(snapshot, word.start);
@@ -4609,20 +4603,11 @@ function isConstructorTypeReference(snapshot, reference2) {
4609
4603
  (call) => call.kind === "constructor" && call.nameRange.start.line === reference2.range.start.line && call.nameRange.start.character === reference2.range.start.character
4610
4604
  );
4611
4605
  }
4612
- var IDENTIFIER_PATTERN, RESERVED_NAMES;
4613
4606
  var init_analyzer = __esm({
4614
4607
  "../packages/neoscript-language/src/analyzer.ts"() {
4615
4608
  "use strict";
4616
4609
  init_language_spec();
4617
4610
  init_project();
4618
- IDENTIFIER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
4619
- RESERVED_NAMES = /* @__PURE__ */ new Set([
4620
- ...NEOSCRIPT_KEYWORDS,
4621
- ...NEOSCRIPT_PRIMITIVE_TYPES,
4622
- ...NEOSCRIPT_BUILTIN_NAMESPACES,
4623
- "Dictionary",
4624
- "Set"
4625
- ]);
4626
4611
  }
4627
4612
  });
4628
4613
 
@@ -5919,6 +5904,52 @@ var init_strict_compile_error = __esm({
5919
5904
  }
5920
5905
  });
5921
5906
 
5907
+ // ../packages/neoscript-language/src/project-source-identifiers.ts
5908
+ function isValidNeoProjectIdentifier(name) {
5909
+ return PROJECT_IDENTIFIER_PATTERN.test(name) && !PROJECT_RESERVED_NAMES.has(name);
5910
+ }
5911
+ function isValidNeoProjectMemberIdentifier(name) {
5912
+ return PROJECT_IDENTIFIER_PATTERN.test(name) && !PROJECT_MEMBER_RESERVED_NAMES.has(name);
5913
+ }
5914
+ function isValidNeoProjectBindingIdentifier(name) {
5915
+ return PROJECT_IDENTIFIER_PATTERN.test(name) && !PROJECT_BINDING_RESERVED_NAMES.has(name);
5916
+ }
5917
+ function isValidNeoScriptBindingIdentifier(name) {
5918
+ return PROJECT_IDENTIFIER_PATTERN.test(name) && !INLINE_BINDING_RESERVED_NAMES.has(name);
5919
+ }
5920
+ function isNeoProjectReservedName(name) {
5921
+ return PROJECT_RESERVED_NAMES.has(name);
5922
+ }
5923
+ function isNeoProjectMemberReservedName(name) {
5924
+ return PROJECT_MEMBER_RESERVED_NAMES.has(name);
5925
+ }
5926
+ var PROJECT_IDENTIFIER_PATTERN, PROJECT_RESERVED_NAMES, PROJECT_MEMBER_RESERVED_NAMES, PROJECT_BINDING_RESERVED_NAMES, INLINE_BINDING_RESERVED_NAMES;
5927
+ var init_project_source_identifiers = __esm({
5928
+ "../packages/neoscript-language/src/project-source-identifiers.ts"() {
5929
+ "use strict";
5930
+ init_language_spec();
5931
+ PROJECT_IDENTIFIER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
5932
+ PROJECT_RESERVED_NAMES = /* @__PURE__ */ new Set([
5933
+ ...NEOSCRIPT_KEYWORDS,
5934
+ ...NEOSCRIPT_BUILTIN_NAMESPACES
5935
+ ]);
5936
+ PROJECT_MEMBER_RESERVED_NAMES = new Set(NEOSCRIPT_KEYWORDS);
5937
+ PROJECT_BINDING_RESERVED_NAMES = /* @__PURE__ */ new Set([
5938
+ ...PROJECT_RESERVED_NAMES,
5939
+ "this",
5940
+ "root",
5941
+ "context"
5942
+ ]);
5943
+ INLINE_BINDING_RESERVED_NAMES = /* @__PURE__ */ new Set([
5944
+ ...PROJECT_BINDING_RESERVED_NAMES,
5945
+ ...NEOSCRIPT_PRIMITIVE_TYPES,
5946
+ "Dictionary",
5947
+ "List",
5948
+ "Set"
5949
+ ]);
5950
+ }
5951
+ });
5952
+
5922
5953
  // ../packages/neoscript-language/src/strict-lexer.ts
5923
5954
  function lex2(source) {
5924
5955
  const tokens = [];
@@ -6463,6 +6494,7 @@ var init_strict_parser = __esm({
6463
6494
  "use strict";
6464
6495
  init_strict_compile_error();
6465
6496
  init_language_spec();
6497
+ init_project_source_identifiers();
6466
6498
  init_strict_lexer();
6467
6499
  Parser = class _Parser {
6468
6500
  constructor(tokens) {
@@ -6501,7 +6533,7 @@ var init_strict_parser = __esm({
6501
6533
  }
6502
6534
  expectMemberName() {
6503
6535
  const token = this.peek();
6504
- if (token.kind === "ident" || token.kind === "keyword" && token.text === "native") {
6536
+ if (token.kind === "ident" || token.kind === "keyword" && (token.text === "native" || isValidNeoProjectMemberIdentifier(token.text))) {
6505
6537
  return this.next();
6506
6538
  }
6507
6539
  throw new CompileError(
@@ -7273,7 +7305,7 @@ var init_strict_parser = __esm({
7273
7305
  }
7274
7306
  while (true) {
7275
7307
  let name = null;
7276
- if ((this.peek().kind === "ident" || this.peek().kind === "keyword" && this.peek().text === "default") && this.peek(1).kind === "punct" && this.peek(1).text === ":") {
7308
+ if ((this.peek().kind === "ident" || this.peek().kind === "keyword" && (this.peek().text === "default" || isValidNeoProjectIdentifier(this.peek().text))) && this.peek(1).kind === "punct" && this.peek(1).text === ":") {
7277
7309
  name = this.next().text;
7278
7310
  this.next();
7279
7311
  }
@@ -7320,7 +7352,7 @@ var init_strict_parser = __esm({
7320
7352
  }
7321
7353
  if (t.kind === "punct" && t.text === ".") {
7322
7354
  this.next();
7323
- const option = this.expect("ident");
7355
+ const option = this.expectMemberName();
7324
7356
  return { kind: "contextualEnum", name: option.text, pos: t.pos };
7325
7357
  }
7326
7358
  if (t.kind === "ident" && t.text === NEOSCRIPT_CONSTRUCTOR_KEYWORD) {
@@ -7424,7 +7456,7 @@ var init_strict_parser = __esm({
7424
7456
  this.expect("punct", ")");
7425
7457
  return inner;
7426
7458
  }
7427
- if (t.kind === "ident") {
7459
+ if (t.kind === "ident" || t.kind === "keyword" && isValidNeoProjectIdentifier(t.text)) {
7428
7460
  this.next();
7429
7461
  return { kind: "ident", name: t.text, pos: t.pos };
7430
7462
  }
@@ -7440,7 +7472,7 @@ var init_strict_parser = __esm({
7440
7472
  this.expect("punct", "{");
7441
7473
  const entries = [];
7442
7474
  while (!(this.peek().kind === "punct" && this.peek().text === "}")) {
7443
- const name = this.expect("ident");
7475
+ const name = this.expectMemberName();
7444
7476
  this.expect("op", "=");
7445
7477
  entries.push({ name: name.text, value: this.parseExpr(), pos: name.pos });
7446
7478
  if (!this.eat("punct", ",")) break;
@@ -17940,12 +17972,15 @@ function projectTokenAt(document, position) {
17940
17972
  const containing = tokens.find(
17941
17973
  (token) => token.start <= offset && offset < token.end
17942
17974
  );
17943
- if (containing?.kind === "identifier") return containing;
17975
+ if (isProjectNameToken(containing)) return containing;
17944
17976
  const touching = tokens.find(
17945
- (token) => token.kind === "identifier" && token.end === offset
17977
+ (token) => isProjectNameToken(token) && token.end === offset
17946
17978
  );
17947
17979
  return touching ?? containing;
17948
17980
  }
17981
+ function isProjectNameToken(token) {
17982
+ return token !== void 0 && (token.kind === "identifier" || token.kind === "type" || token.kind === "keyword");
17983
+ }
17949
17984
  function projectTokens(document) {
17950
17985
  const cached = PROJECT_TOKEN_CACHE.get(document);
17951
17986
  if (cached) return cached;
@@ -18108,7 +18143,7 @@ function collectGlobalChildEntries(sourceText, declaration) {
18108
18143
  continue;
18109
18144
  }
18110
18145
  const name = tokens[index + 1];
18111
- if ((token.kind === "type" || token.kind === "identifier") && name?.kind === "identifier" && tokens[index + 2]?.text === "=" && tokens[index + 3]?.text !== "=" && // A pending annotation or statement boundary precedes a declaration;
18146
+ if ((token.kind === "type" || token.kind === "identifier") && isProjectNameToken(name) && isValidNeoProjectMemberIdentifier(name.text) && tokens[index + 2]?.text === "=" && tokens[index + 3]?.text !== "=" && // A pending annotation or statement boundary precedes a declaration;
18112
18147
  // `key: value` fields and expression member accesses never do.
18113
18148
  tokens[index - 1]?.text !== "." && tokens[index - 1]?.text !== ":") {
18114
18149
  entries.push({
@@ -18163,6 +18198,7 @@ var init_project_source_registry = __esm({
18163
18198
  "../packages/neoscript-language/src/project-source-registry.ts"() {
18164
18199
  "use strict";
18165
18200
  init_lexer();
18201
+ init_project_source_identifiers();
18166
18202
  init_project_source_tokens();
18167
18203
  }
18168
18204
  });
@@ -23848,7 +23884,7 @@ function memberKeyArgument(annotation2) {
23848
23884
  if (argument2 === void 0) return null;
23849
23885
  const text = argument2.text.trim();
23850
23886
  return {
23851
- key: IDENTIFIER_PATTERN2.test(text) ? text : null,
23887
+ key: IDENTIFIER_PATTERN.test(text) ? text : null,
23852
23888
  range: argument2.range
23853
23889
  };
23854
23890
  }
@@ -24037,7 +24073,7 @@ function classDerivesFromName(name, ancestorName, environment, seen = /* @__PURE
24037
24073
  return classDerivesFromName(base.name, ancestorName, environment, seen);
24038
24074
  });
24039
24075
  }
24040
- var NEO_VARIANT_FOLDER_SETTING, primitiveType, IDENTIFIER_PATTERN2, LIST_COLUMN_INHERITANCE_KEY;
24076
+ var NEO_VARIANT_FOLDER_SETTING, primitiveType, IDENTIFIER_PATTERN, LIST_COLUMN_INHERITANCE_KEY;
24041
24077
  var init_project_source_semantics = __esm({
24042
24078
  "../packages/neoscript-language/src/project-source-semantics.ts"() {
24043
24079
  "use strict";
@@ -24052,7 +24088,7 @@ var init_project_source_semantics = __esm({
24052
24088
  init_project_root();
24053
24089
  NEO_VARIANT_FOLDER_SETTING = "folder";
24054
24090
  primitiveType = (name) => ({ name });
24055
- IDENTIFIER_PATTERN2 = /^[A-Za-z_][A-Za-z0-9_]*$/;
24091
+ IDENTIFIER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
24056
24092
  LIST_COLUMN_INHERITANCE_KEY = "__other__";
24057
24093
  }
24058
24094
  });
@@ -25218,7 +25254,7 @@ function validatePersistedName(uri, name, range2, diagnostics, reservedAlreadyCh
25218
25254
  );
25219
25255
  return;
25220
25256
  }
25221
- if (!RESERVED_NAMES2.has(name) || reservedAlreadyChecked) return;
25257
+ if (!isNeoProjectReservedName(name) || reservedAlreadyChecked) return;
25222
25258
  diagnose(
25223
25259
  diagnostics,
25224
25260
  uri,
@@ -26489,12 +26525,13 @@ function diagnose(diagnostics, uri, range2, code, message, relatedInformation) {
26489
26525
  ...relatedInformation?.length ? { relatedInformation } : {}
26490
26526
  });
26491
26527
  }
26492
- var BUILTIN_ARITY, BUILTIN_TYPES, RESERVED_NAMES2;
26528
+ var BUILTIN_ARITY, BUILTIN_TYPES;
26493
26529
  var init_project_source_type_checker = __esm({
26494
26530
  "../packages/neoscript-language/src/project-source-type-checker.ts"() {
26495
26531
  "use strict";
26496
26532
  init_language_spec();
26497
26533
  init_project_source_ast();
26534
+ init_project_source_identifiers();
26498
26535
  BUILTIN_ARITY = /* @__PURE__ */ new Map([
26499
26536
  ["List", 1],
26500
26537
  ["Set", 1],
@@ -26522,10 +26559,6 @@ var init_project_source_type_checker = __esm({
26522
26559
  "NeoAudioClip",
26523
26560
  "ProjectRelation"
26524
26561
  ]);
26525
- RESERVED_NAMES2 = /* @__PURE__ */ new Set([
26526
- ...NEOSCRIPT_KEYWORDS,
26527
- ...NEOSCRIPT_BUILTIN_NAMESPACES
26528
- ]);
26529
26562
  }
26530
26563
  });
26531
26564
 
@@ -27029,14 +27062,16 @@ function collectFlowSymbols(uri, content, ownerName, scopeRange, symbols, diagno
27029
27062
  }
27030
27063
  }
27031
27064
  function collectSymbol(uri, kind, name, range2, annotations, ownerName, symbols, diagnostics, scopeRange, detail, callable2, documentation, staticMember) {
27032
- if (RESERVED_NAMES3.has(name)) {
27065
+ const memberLabel2 = kind === "member" || kind === "enumOption" || kind === "graphChild";
27066
+ const reserved = memberLabel2 ? isNeoProjectMemberReservedName(name) : isNeoProjectReservedName(name);
27067
+ if (reserved) {
27033
27068
  diagnostics.push({
27034
27069
  uri,
27035
27070
  range: range2,
27036
27071
  severity: "error",
27037
27072
  source: "neo-project",
27038
27073
  code: "reserved-project-name",
27039
- message: `'${name}' is a reserved Neo keyword and cannot be used as a persisted source name without the language's identifier escape syntax.`
27074
+ message: `'${name}' is reserved in this Neo declaration context and cannot be used as a persisted source name without the language's identifier escape syntax.`
27040
27075
  });
27041
27076
  }
27042
27077
  const id2 = sourceId(uri, annotations, diagnostics);
@@ -27412,12 +27447,13 @@ function emptyRange2() {
27412
27447
  end: { line: 0, character: 0 }
27413
27448
  };
27414
27449
  }
27415
- var BUILTIN_TYPE_NAMES, RESERVED_NAMES3, SYSTEM_RECORD_ID_PREFIX, RFC_4122_UUID, QUARANTINED_LEGACY_SYSTEM_ID_PREFIXES, QUARANTINED_LEGACY_SYSTEM_RECORD_IDS;
27450
+ var BUILTIN_TYPE_NAMES, SYSTEM_RECORD_ID_PREFIX, RFC_4122_UUID, QUARANTINED_LEGACY_SYSTEM_ID_PREFIXES, QUARANTINED_LEGACY_SYSTEM_RECORD_IDS;
27416
27451
  var init_project_source_analysis = __esm({
27417
27452
  "../packages/neoscript-language/src/project-source-analysis.ts"() {
27418
27453
  "use strict";
27419
27454
  init_language_spec();
27420
27455
  init_pending_id();
27456
+ init_project_source_identifiers();
27421
27457
  init_project_source_parser();
27422
27458
  init_project_source_registry();
27423
27459
  init_project_source_semantics();
@@ -27446,10 +27482,6 @@ var init_project_source_analysis = __esm({
27446
27482
  "NeoAudioClip",
27447
27483
  "ProjectRelation"
27448
27484
  ]);
27449
- RESERVED_NAMES3 = /* @__PURE__ */ new Set([
27450
- ...NEOSCRIPT_KEYWORDS,
27451
- ...NEOSCRIPT_BUILTIN_NAMESPACES
27452
- ]);
27453
27485
  SYSTEM_RECORD_ID_PREFIX = "system_";
27454
27486
  RFC_4122_UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/u;
27455
27487
  QUARANTINED_LEGACY_SYSTEM_ID_PREFIXES = [
@@ -28508,7 +28540,7 @@ function projectVariantScopeCompletion(analysis, document, position) {
28508
28540
  }
28509
28541
  function projectVariantPathSymbolAt(analysis, document, position) {
28510
28542
  const token = projectTokenAt(document, position);
28511
- if (!token || token.kind !== "identifier") return null;
28543
+ if (!isProjectNameToken(token)) return null;
28512
28544
  const tokens = projectTokens(document);
28513
28545
  const tokenIndex = tokens.findIndex(
28514
28546
  (candidate) => candidate.start === token.start && candidate.end === token.end
@@ -28519,7 +28551,7 @@ function projectVariantPathSymbolAt(analysis, document, position) {
28519
28551
  for (; ; ) {
28520
28552
  const dot = tokens[cursor];
28521
28553
  const owner = tokens[cursor - 1];
28522
- if (dot?.text !== "." || owner?.kind !== "identifier") break;
28554
+ if (dot?.text !== "." || !isProjectNameToken(owner)) break;
28523
28555
  segments.unshift(owner.text);
28524
28556
  cursor -= 2;
28525
28557
  }
@@ -29172,10 +29204,12 @@ function projectSemanticTokens(document, analysis) {
29172
29204
  return [];
29173
29205
  }
29174
29206
  const declaration = symbolsDeclaredAt(index, document.uri, token.range)[0];
29175
- const resolved = token.kind === "identifier" ? indexedProjectSymbolAt(analysis, document, token.range.start, index)?.symbol : void 0;
29207
+ const resolved = isProjectNameToken(token) ? indexedProjectSymbolAt(analysis, document, token.range.start, index)?.symbol : void 0;
29176
29208
  let type;
29177
29209
  if (declaration) {
29178
29210
  type = projectSemanticTokenType(declaration);
29211
+ } else if (resolved) {
29212
+ type = projectSemanticTokenType(resolved);
29179
29213
  } else if (token.kind === "keyword") type = "keyword";
29180
29214
  else if (token.kind === "type") type = "type";
29181
29215
  else if (token.kind === "string") type = "string";
@@ -29227,7 +29261,14 @@ function projectSymbolAt(analysis, document, position) {
29227
29261
  }
29228
29262
  function indexedProjectSymbolAt(analysis, document, position, index) {
29229
29263
  const token = projectTokenAt(document, position);
29230
- if (!token || token.kind !== "identifier") return null;
29264
+ if (!isProjectNameToken(token)) return null;
29265
+ const body = projectBodySnapshotAt(analysis, document, position);
29266
+ if (body) {
29267
+ const reference2 = referenceAtPosition(body, position);
29268
+ const symbolId = reference2 ? resolveReferenceSymbolId(body, reference2) : null;
29269
+ const symbol = symbolId ? analysis.symbols.find((candidate) => candidate.id === symbolId) : void 0;
29270
+ if (symbol) return { token, symbol };
29271
+ }
29231
29272
  const exact = symbolsDeclaredAt(index, document.uri, token.range);
29232
29273
  if (exact.length === 1) return { token, symbol: exact[0] };
29233
29274
  const candidates = index.byName.get(token.text) ?? [];
@@ -29284,7 +29325,7 @@ function indexedProjectSymbolAt(analysis, document, position, index) {
29284
29325
  dotOwner.range.start,
29285
29326
  index
29286
29327
  );
29287
- const ownerNames = resolvedOwner ? projectReceiverOwnerNames(analysis, resolvedOwner.symbol) : [dotOwner.text];
29328
+ const ownerNames = dotOwner.text === "this" && owner ? projectTypeAndBaseOwnerNames(analysis, owner) : resolvedOwner ? projectReceiverOwnerNames(analysis, resolvedOwner.symbol) : [dotOwner.text];
29288
29329
  const qualified = visibleCandidates.filter(
29289
29330
  (symbol) => symbol.ownerName !== void 0 && ownerNames.includes(symbol.ownerName) && (resolvedOwner === null || projectQualifiedSymbolMatchesReceiver(symbol, resolvedOwner.symbol))
29290
29331
  );
@@ -29319,27 +29360,33 @@ function projectQualifiedSymbolMatchesReceiver(symbol, receiver) {
29319
29360
  }
29320
29361
  function projectReceiverOwnerNames(analysis, receiver) {
29321
29362
  const result = [];
29322
- const visitedTypes = /* @__PURE__ */ new Set();
29323
- const appendTypeAndBases = (typeName2) => {
29324
- if (visitedTypes.has(typeName2)) return;
29325
- visitedTypes.add(typeName2);
29326
- if (!result.includes(typeName2)) result.push(typeName2);
29327
- const declaration = findTypeDeclaration(analysis, typeName2);
29363
+ if (receiver.kind === "global") {
29364
+ result.push(receiver.name);
29365
+ }
29366
+ const typeName = projectSymbolTypeName(receiver);
29367
+ if (typeName)
29368
+ result.push(...projectTypeAndBaseOwnerNames(analysis, typeName));
29369
+ return result;
29370
+ }
29371
+ function projectTypeAndBaseOwnerNames(analysis, typeName) {
29372
+ const result = [];
29373
+ const visited = /* @__PURE__ */ new Set();
29374
+ const append = (candidateName) => {
29375
+ if (visited.has(candidateName)) return;
29376
+ visited.add(candidateName);
29377
+ result.push(candidateName);
29378
+ const declaration = findTypeDeclaration(analysis, candidateName);
29328
29379
  if (declaration?.kind !== "class" && declaration?.kind !== "interface") {
29329
29380
  return;
29330
29381
  }
29331
29382
  for (const base of declaration.baseTypes) {
29332
29383
  const resolved = findTypeDeclaration(analysis, base.name);
29333
29384
  if (resolved?.kind === "class" || resolved?.kind === "interface") {
29334
- appendTypeAndBases(base.name);
29385
+ append(base.name);
29335
29386
  }
29336
29387
  }
29337
29388
  };
29338
- if (receiver.kind === "global") {
29339
- result.push(receiver.name);
29340
- }
29341
- const typeName = projectSymbolTypeName(receiver);
29342
- if (typeName) appendTypeAndBases(typeName);
29389
+ append(typeName);
29343
29390
  return result;
29344
29391
  }
29345
29392
  function contextualProjectEnumOptionSymbol(analysis, document, token, candidates, source) {
@@ -33084,6 +33131,8 @@ var init_service = __esm({
33084
33131
  init_analyzer();
33085
33132
  init_compiler();
33086
33133
  init_formatter();
33134
+ init_generated_csharp_identifiers();
33135
+ init_project_source_identifiers();
33087
33136
  init_project_source_analysis();
33088
33137
  init_project_source_construction_quick_fixes();
33089
33138
  init_project_source_language_features();
@@ -33305,9 +33354,25 @@ var init_service = __esm({
33305
33354
  return { range: reference2.range, placeholder: reference2.name };
33306
33355
  }
33307
33356
  rename(uri, position, newName) {
33308
- if (!isValidRenameIdentifier(newName)) {
33357
+ const state = this.requireState(uri);
33358
+ let validName;
33359
+ if (isProjectDocument(state.document, state.context)) {
33360
+ const resolved = projectSymbolAt(
33361
+ this.projectAnalysis(),
33362
+ state.document,
33363
+ position
33364
+ );
33365
+ if (!resolved) return null;
33366
+ const memberLabel2 = resolved.symbol.kind === "member" || resolved.symbol.kind === "enumOption" || resolved.symbol.kind === "graphChild";
33367
+ const binding = resolved.symbol.kind === "parameter" || resolved.symbol.kind === "genericParameter" || resolved.symbol.kind === "flowBinding";
33368
+ const validNeoName = memberLabel2 ? isValidNeoProjectMemberIdentifier(newName) : binding ? isValidNeoProjectBindingIdentifier(newName) : isValidNeoProjectIdentifier(newName);
33369
+ validName = validNeoName && isGeneratedCSharpIdentifier(newName) && !isGeneratedCSharpReservedKeyword(newName);
33370
+ } else {
33371
+ validName = isValidNeoScriptBindingIdentifier(newName);
33372
+ }
33373
+ if (!validName) {
33309
33374
  throw new Error(
33310
- `Cannot rename a NeoScript symbol to "${newName}": use a non-keyword identifier containing letters, digits, or underscores.`
33375
+ `Cannot rename a NeoScript symbol to "${newName}": use an identifier valid in this declaration context and generated C#.`
33311
33376
  );
33312
33377
  }
33313
33378
  const prepared = this.prepareRename(uri, position);
@@ -33407,7 +33472,7 @@ var init_service = __esm({
33407
33472
  }
33408
33473
  projectReferences(document, position, includeDeclaration) {
33409
33474
  const token = projectTokenAt(document, position);
33410
- if (!token || token.kind !== "identifier") return [];
33475
+ if (!isProjectNameToken(token)) return [];
33411
33476
  const analysis = this.projectAnalysis();
33412
33477
  const resolved = projectSymbolAt(analysis, document, position);
33413
33478
  if (!resolved) return [];
@@ -33416,7 +33481,7 @@ var init_service = __esm({
33416
33481
  for (const state of this.documents.values()) {
33417
33482
  if (!isProjectDocument(state.document, state.context)) continue;
33418
33483
  for (const candidate of projectTokens(state.document)) {
33419
- if (candidate.kind !== "identifier" || candidate.text !== token.text) {
33484
+ if (!isProjectNameToken(candidate) || candidate.text !== token.text) {
33420
33485
  continue;
33421
33486
  }
33422
33487
  const candidateSymbol = projectSymbolAt(
@@ -33719,6 +33784,7 @@ var init_src = __esm({
33719
33784
  init_project();
33720
33785
  init_project_source_ast();
33721
33786
  init_project_source_ignore();
33787
+ init_project_source_identifiers();
33722
33788
  init_project_source_analysis();
33723
33789
  init_project_source_accessors();
33724
33790
  init_project_source_construction_diagnostics();
@@ -41168,6 +41234,46 @@ var init_docs_text2 = __esm({
41168
41234
  }
41169
41235
  });
41170
41236
 
41237
+ // ../src/models/project-source-identifiers.ts
41238
+ function isValidGeneratedIdentifier(value) {
41239
+ return typeof value === "string" && isGeneratedCSharpIdentifier(value) && !isGeneratedCSharpReservedKeyword(value);
41240
+ }
41241
+ function isValidProjectSourceIdentifier(value) {
41242
+ return isValidGeneratedIdentifier(value) && isValidNeoProjectIdentifier(value);
41243
+ }
41244
+ function isValidProjectMemberIdentifier(value) {
41245
+ return isValidGeneratedIdentifier(value) && isValidNeoProjectMemberIdentifier(value);
41246
+ }
41247
+ function isValidProjectBindingIdentifier(value) {
41248
+ return isValidGeneratedIdentifier(value) && isValidNeoProjectBindingIdentifier(value);
41249
+ }
41250
+ var init_project_source_identifiers2 = __esm({
41251
+ "../src/models/project-source-identifiers.ts"() {
41252
+ "use strict";
41253
+ init_src();
41254
+ }
41255
+ });
41256
+
41257
+ // ../src/models/schema-identifiers.ts
41258
+ function isValidSchemaAuthoredIdentifier(value) {
41259
+ return isValidProjectSourceIdentifier(value);
41260
+ }
41261
+ function isValidSchemaMemberIdentifier(value) {
41262
+ return isValidProjectMemberIdentifier(value);
41263
+ }
41264
+ function isValidSchemaBindingIdentifier(value) {
41265
+ return isValidProjectBindingIdentifier(value);
41266
+ }
41267
+ function isValidSchemaNSFunctionBindingIdentifier(value) {
41268
+ return isValidSchemaBindingIdentifier(value) && value !== "value";
41269
+ }
41270
+ var init_schema_identifiers = __esm({
41271
+ "../src/models/schema-identifiers.ts"() {
41272
+ "use strict";
41273
+ init_project_source_identifiers2();
41274
+ }
41275
+ });
41276
+
41171
41277
  // ../src/models/neoscript/neoscript-types.ts
41172
41278
  var NS_TYPE_UNKNOWN, NS_TYPE_VOID, NSAssignmentOperator, NSWritability, NSCollectionMutation;
41173
41279
  var init_neoscript_types = __esm({
@@ -42739,12 +42845,20 @@ function isMemberAccessModifierKind(value) {
42739
42845
  if (value === "protected") return true;
42740
42846
  return value === "private";
42741
42847
  }
42742
- function isValidCallableIdentifier(value) {
42743
- if (typeof value !== "string") return false;
42744
- if (!FunctionMemberNamePattern.test(value)) return false;
42848
+ function isValidCallableMemberIdentifier(value) {
42849
+ if (!isValidSchemaMemberIdentifier(value)) return false;
42850
+ if (value.startsWith("__")) return false;
42851
+ return true;
42852
+ }
42853
+ function isValidCallableArgumentIdentifier(value) {
42854
+ if (!isValidSchemaBindingIdentifier(value)) return false;
42745
42855
  if (value.startsWith("__")) return false;
42746
42856
  return !FunctionArgumentReservedNames.has(value);
42747
42857
  }
42858
+ function isValidNSFunctionArgumentIdentifier(value) {
42859
+ if (!isValidSchemaNSFunctionBindingIdentifier(value)) return false;
42860
+ return !value.startsWith("__");
42861
+ }
42748
42862
  function isMemberListColumnSettings(value) {
42749
42863
  if (!value) return false;
42750
42864
  if (typeof value !== "object") return false;
@@ -43108,7 +43222,7 @@ function isMemberAudioBase(value) {
43108
43222
  function isMemberFunctionBase(value) {
43109
43223
  const v = asMemberBaseForKind(value, 13 /* Function */);
43110
43224
  if (v === null) return false;
43111
- if (!isValidCallableIdentifier(v.name)) return false;
43225
+ if (!isValidCallableMemberIdentifier(v.name)) return false;
43112
43226
  if (!isNSFunctionReturnTypeInfo(v.returnTypeInfo)) return false;
43113
43227
  if (!Array.isArray(v.argumentTypes)) return false;
43114
43228
  if (typeof v.deferred !== "boolean") return false;
@@ -43116,7 +43230,7 @@ function isMemberFunctionBase(value) {
43116
43230
  const argumentTypes = [];
43117
43231
  for (const arg of v.argumentTypes) {
43118
43232
  if (!isNSFunctionArgumentTypeInfo(arg)) return false;
43119
- if (!isValidCallableIdentifier(arg.name)) return false;
43233
+ if (!isValidCallableArgumentIdentifier(arg.name)) return false;
43120
43234
  if (arg.type === NS_TYPE_UNKNOWN) return false;
43121
43235
  if (names.has(arg.name)) return false;
43122
43236
  names.add(arg.name);
@@ -43162,7 +43276,7 @@ function isNSFunctionUIBody(value) {
43162
43276
  function isMemberNSFunctionBase(value) {
43163
43277
  const v = asMemberBaseForKind(value, 23 /* NSFunction */);
43164
43278
  if (v === null) return false;
43165
- if (!isValidCallableIdentifier(v.name)) return false;
43279
+ if (!isValidCallableMemberIdentifier(v.name)) return false;
43166
43280
  if (v.required !== false) return false;
43167
43281
  if (v.defaultValue !== void 0 && v.defaultValue !== null) return false;
43168
43282
  if (v.storage !== void 0 && v.storage !== null) return false;
@@ -43178,8 +43292,7 @@ function isMemberNSFunctionBase(value) {
43178
43292
  for (const argument2 of v.argumentTypes) {
43179
43293
  if (!isNSFunctionArgumentTypeInfo(argument2)) return false;
43180
43294
  if (argument2.type === NS_TYPE_UNKNOWN) return false;
43181
- if (!isValidCallableIdentifier(argument2.name)) return false;
43182
- if (NSFunctionArgumentReservedNames.has(argument2.name)) return false;
43295
+ if (!isValidNSFunctionArgumentIdentifier(argument2.name)) return false;
43183
43296
  if (names.has(argument2.name)) return false;
43184
43297
  names.add(argument2.name);
43185
43298
  argumentTypes.push(argument2);
@@ -43257,7 +43370,7 @@ function isMemberDelegateBase(value) {
43257
43370
  const names = /* @__PURE__ */ new Set();
43258
43371
  for (const argument2 of v.argumentTypes) {
43259
43372
  if (!isNSFunctionArgumentTypeInfo(argument2)) return false;
43260
- if (!isValidCallableIdentifier(argument2.name)) return false;
43373
+ if (!isValidCallableArgumentIdentifier(argument2.name)) return false;
43261
43374
  if (argument2.type === NS_TYPE_UNKNOWN) return false;
43262
43375
  if (names.has(argument2.name)) return false;
43263
43376
  names.add(argument2.name);
@@ -43296,7 +43409,7 @@ function isMemberActionBase(value) {
43296
43409
  const names = /* @__PURE__ */ new Set();
43297
43410
  for (const argument2 of v.argumentTypes) {
43298
43411
  if (!isNSFunctionArgumentTypeInfo(argument2)) return false;
43299
- if (!isValidCallableIdentifier(argument2.name)) return false;
43412
+ if (!isValidCallableArgumentIdentifier(argument2.name)) return false;
43300
43413
  if (argument2.type === NS_TYPE_UNKNOWN) return false;
43301
43414
  if (names.has(argument2.name)) return false;
43302
43415
  names.add(argument2.name);
@@ -43600,7 +43713,7 @@ function isMemberOverrideProps(value) {
43600
43713
  if (v.setter !== void 0 && !isNSVoidBody(v.setter)) return false;
43601
43714
  const isCallableOverride = v.kind === 13 /* Function */ || v.kind === 23 /* NSFunction */;
43602
43715
  if (isCallableOverride) {
43603
- if (!isValidCallableIdentifier(v.name)) return false;
43716
+ if (!isValidCallableMemberIdentifier(v.name)) return false;
43604
43717
  if (v.returnTypeInfo !== void 0) return false;
43605
43718
  if (v.argumentTypes !== void 0) return false;
43606
43719
  if (v.deferred !== void 0) return false;
@@ -43677,37 +43790,23 @@ function isAnyMember(value) {
43677
43790
  function isAnyMemberAuthoredOrCompiled(value) {
43678
43791
  return isAnyMember(value) || isUncompiledMemberNSFunctionOverride(value);
43679
43792
  }
43680
- var FunctionMemberNamePattern, FunctionArgumentReservedNames, NSFunctionArgumentReservedNames, DECIMAL_STRING_PATTERN, DECIMAL_MAX_SIGNIFICANT_DIGITS, DECIMAL_MAX_SCALE;
43793
+ var FunctionArgumentReservedNames, NSFunctionArgumentReservedNames, DECIMAL_STRING_PATTERN, DECIMAL_MAX_SIGNIFICANT_DIGITS, DECIMAL_MAX_SCALE;
43681
43794
  var init_member_kinds = __esm({
43682
43795
  "../src/models/members/member-kinds.ts"() {
43683
43796
  "use strict";
43684
43797
  init_core();
43685
43798
  init_docs_text2();
43799
+ init_schema_identifiers();
43686
43800
  init_neoscript();
43687
43801
  init_classes();
43688
43802
  init_member_kind_enum();
43689
43803
  init_member_storage();
43690
43804
  init_structured_leaf_fields();
43691
43805
  init_member_kind_enum();
43692
- FunctionMemberNamePattern = /^[A-Za-z_][A-Za-z0-9_]*$/;
43693
43806
  FunctionArgumentReservedNames = /* @__PURE__ */ new Set([
43694
43807
  "this",
43695
43808
  "root",
43696
- "context",
43697
- "true",
43698
- "false",
43699
- "null",
43700
- "void",
43701
- "if",
43702
- "else",
43703
- "return",
43704
- "throw",
43705
- "var",
43706
- "int",
43707
- "float",
43708
- "decimal",
43709
- "string",
43710
- "bool"
43809
+ "context"
43711
43810
  ]);
43712
43811
  NSFunctionArgumentReservedNames = /* @__PURE__ */ new Set([
43713
43812
  ...FunctionArgumentReservedNames,
@@ -47803,28 +47902,6 @@ var init_files = __esm({
47803
47902
  }
47804
47903
  });
47805
47904
 
47806
- // ../src/models/project-source-identifiers.ts
47807
- function isValidProjectSourceIdentifier(value) {
47808
- return typeof value === "string" && isValidNeoIdentifier(value) && isGeneratedCSharpIdentifier(value) && !isGeneratedCSharpReservedKeyword(value);
47809
- }
47810
- var init_project_source_identifiers = __esm({
47811
- "../src/models/project-source-identifiers.ts"() {
47812
- "use strict";
47813
- init_src();
47814
- }
47815
- });
47816
-
47817
- // ../src/models/schema-identifiers.ts
47818
- function isValidSchemaAuthoredIdentifier(value) {
47819
- return isValidProjectSourceIdentifier(value);
47820
- }
47821
- var init_schema_identifiers = __esm({
47822
- "../src/models/schema-identifiers.ts"() {
47823
- "use strict";
47824
- init_project_source_identifiers();
47825
- }
47826
- });
47827
-
47828
47905
  // ../src/models/enum/enum-types.ts
47829
47906
  function isValidEnumOptionId(id2) {
47830
47907
  if (typeof id2 !== "string" || id2.length === 0) return false;
@@ -47836,7 +47913,7 @@ function isProspectiveEnumOptionId(id2) {
47836
47913
  return isValidEnumOptionId(id2);
47837
47914
  }
47838
47915
  function isValidEnumOptionName(name) {
47839
- return isValidSchemaAuthoredIdentifier(name);
47916
+ return isValidSchemaMemberIdentifier(name);
47840
47917
  }
47841
47918
  function isEnumOptionWithIds(value, isOptionId) {
47842
47919
  const v = value;
@@ -50778,14 +50855,14 @@ function listAnnotations(member) {
50778
50855
  if (member.kind !== "list") return [];
50779
50856
  return [
50780
50857
  ...member.indexes.map((entry) => {
50781
- assertIdentifier(entry.schemaKey, "list index member");
50858
+ assertMemberIdentifier(entry.schemaKey, "list index member");
50782
50859
  return `@index(${[
50783
50860
  `member: ${entry.schemaKey}`,
50784
50861
  ...entry.unique ? ["unique: true"] : []
50785
50862
  ].join(", ")})`;
50786
50863
  }),
50787
50864
  ...member.columns.map((entry) => {
50788
- assertIdentifier(entry.memberKey, "list column member");
50865
+ assertMemberIdentifier(entry.memberKey, "list column member");
50789
50866
  return `@column(${[
50790
50867
  `member: ${entry.memberKey}`,
50791
50868
  ...entry.width === null ? [] : [`width: ${entry.width}`],
@@ -51220,7 +51297,7 @@ function renderNestedValue(context, member, value) {
51220
51297
  return renderDefaultValue(context, member, { value, classId: null });
51221
51298
  }
51222
51299
  function emitTextureTemplate(value) {
51223
- assertIdentifier(value.name, "texture template");
51300
+ assertProjectIdentifier(value.name, "texture template");
51224
51301
  const platformSettings = `new(
51225
51302
  ${namedArguments(
51226
51303
  [
@@ -51413,7 +51490,7 @@ function emitVector4(value) {
51413
51490
  return `new(x: ${value.x}, y: ${value.y}, z: ${value.z}, w: ${value.w})`;
51414
51491
  }
51415
51492
  function emitAudioTemplate(value) {
51416
- assertIdentifier(value.name, "audio template");
51493
+ assertProjectIdentifier(value.name, "audio template");
51417
51494
  const enumArguments = /* @__PURE__ */ new Set([
51418
51495
  "loadType",
51419
51496
  "compressionFormat",
@@ -51618,7 +51695,7 @@ function emitVariantFiles(context, variantInitializers) {
51618
51695
  function emitVariantFolder(context, className, folder) {
51619
51696
  for (const segment of folder.path.split("/")) {
51620
51697
  if (segment.length === 0) continue;
51621
- assertIdentifier(segment, "variant folder path segment");
51698
+ assertProjectIdentifier(segment, "variant folder path segment");
51622
51699
  }
51623
51700
  if (folder.binding === null) {
51624
51701
  return `${id(folder.id)}NeoVariantFolder<${className}> ${variantFolderSymbol(folder)} = new(${quote(folder.path)});`;
@@ -51638,7 +51715,7 @@ function emitVariantFolder(context, className, folder) {
51638
51715
  );`;
51639
51716
  }
51640
51717
  function emitVariant(context, className, variant, folder, variantInitializers) {
51641
- assertIdentifier(variant.name, "variant");
51718
+ assertProjectIdentifier(variant.name, "variant");
51642
51719
  const initializer = variantInitializers.get(variant.id);
51643
51720
  if (initializer === void 0) {
51644
51721
  throw new Error(
@@ -51693,13 +51770,20 @@ function assertUniqueEmittedPaths(files) {
51693
51770
  paths.set(key, file);
51694
51771
  }
51695
51772
  }
51696
- function assertIdentifier(value, kind) {
51697
- if (!isValidNeoIdentifier(value)) {
51773
+ function assertProjectIdentifier(value, kind) {
51774
+ if (!isValidNeoProjectIdentifier(value)) {
51698
51775
  throw new Error(
51699
51776
  `Persisted ${kind} name ${quote(value)} is not a valid Neo identifier; repair the server record before format-4 conversion.`
51700
51777
  );
51701
51778
  }
51702
51779
  }
51780
+ function assertMemberIdentifier(value, kind) {
51781
+ if (!isValidNeoProjectMemberIdentifier(value)) {
51782
+ throw new Error(
51783
+ `Persisted ${kind} name ${quote(value)} is not a valid Neo member identifier; repair the server record before format-4 conversion.`
51784
+ );
51785
+ }
51786
+ }
51703
51787
  function required(map, key, kind) {
51704
51788
  const value = map.get(key);
51705
51789
  if (!value) throw new Error(`Unknown ${kind} ${quote(key)}.`);
@@ -51813,7 +51897,7 @@ function assignDeterministicProjectFileSymbols(files, reservedSymbols = []) {
51813
51897
  const candidate = `${item.base}${collidesByStem ? item.extension : ""}`;
51814
51898
  let symbol = candidate;
51815
51899
  let suffix = 2;
51816
- while (used.has(symbol.toLowerCase()) || !isValidNeoIdentifier(symbol))
51900
+ while (used.has(symbol.toLowerCase()) || !isValidNeoProjectMemberIdentifier(symbol))
51817
51901
  symbol = `${candidate}_${suffix++}`;
51818
51902
  used.add(symbol.toLowerCase());
51819
51903
  result.set(item.stableId, symbol);
@@ -52434,7 +52518,7 @@ ${args.map(([name, value]) => ` ${name}: ${value},`).join("\n")}
52434
52518
  `;
52435
52519
  }
52436
52520
  function emitPriorityGroup(data, recordId, name) {
52437
- assertIdentifier2(name, "priority group");
52521
+ assertProjectIdentifier2(name, "priority group");
52438
52522
  const options = Array.isArray(data.options) ? data.options : [];
52439
52523
  const body = options.map((option, index) => {
52440
52524
  if (!isObjectRecord2(option) || typeof option.id !== "string" || typeof option.name !== "string") {
@@ -52442,7 +52526,7 @@ function emitPriorityGroup(data, recordId, name) {
52442
52526
  `Priority group ${recordId} option ${index} is malformed.`
52443
52527
  );
52444
52528
  }
52445
- assertIdentifier2(option.name, "priority option");
52529
+ assertMemberIdentifier2(option.name, "priority option");
52446
52530
  return ` @id(${quote2(option.id)})
52447
52531
  PriorityOption ${option.name} = new();`;
52448
52532
  });
@@ -52457,7 +52541,7 @@ ${body.join("\n\n")}
52457
52541
  `;
52458
52542
  }
52459
52543
  function emitDialogueGroup(data, recordId, name, priorityNames, dialogueNames, uiLogicResolver) {
52460
- assertIdentifier2(name, "dialogue group");
52544
+ assertProjectIdentifier2(name, "dialogue group");
52461
52545
  const kind = data.type === 1 ? "Lookup" : data.type === 2 ? "Folder" : "Standard";
52462
52546
  const args = [["kind", `.${kind}`]];
52463
52547
  const priority = reference(
@@ -52529,7 +52613,7 @@ function collectDialogueGroupFunctions(data, groupId, resolver) {
52529
52613
  let functionName = functionNameById.get(functionId);
52530
52614
  const code = typeof value.code === "string" ? value.code.trim() : value.type === 0 ? uiConditionSource(value.getter, resolver) : null;
52531
52615
  if (functionName === void 0) {
52532
- assertIdentifier2(requestedName, "dialogue group function");
52616
+ assertMemberIdentifier2(requestedName, "dialogue group function");
52533
52617
  functionName = uniqueIdentifier(requestedName, names);
52534
52618
  functions.set(functionId, { id: functionId, name: functionName, code });
52535
52619
  functionNameById.set(functionId, functionName);
@@ -53091,7 +53175,7 @@ function requiredName(data, record3) {
53091
53175
  if (typeof data.name !== "string") {
53092
53176
  throw new Error(`${record3.recordKind}:${record3.recordId} has no name.`);
53093
53177
  }
53094
- assertIdentifier2(data.name, record3.recordKind);
53178
+ assertProjectIdentifier2(data.name, record3.recordKind);
53095
53179
  return data.name;
53096
53180
  }
53097
53181
  function namesById(records2, kind) {
@@ -53183,7 +53267,7 @@ function normalizeSource(value) {
53183
53267
  return value.replace(/\s+/gu, " ").trim();
53184
53268
  }
53185
53269
  function isIdentifier(value) {
53186
- return /^[A-Za-z_][A-Za-z0-9_]*$/u.test(value);
53270
+ return isValidNeoProjectMemberIdentifier(value);
53187
53271
  }
53188
53272
  function reference(value, names, type) {
53189
53273
  if (value === void 0 || value === null) return null;
@@ -53234,13 +53318,20 @@ function enumCase2(value) {
53234
53318
  function lowerFirst2(value) {
53235
53319
  return `${value[0]?.toLowerCase() ?? ""}${value.slice(1)}`;
53236
53320
  }
53237
- function assertIdentifier2(value, kind) {
53238
- if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(value)) {
53321
+ function assertProjectIdentifier2(value, kind) {
53322
+ if (!isValidNeoProjectIdentifier(value)) {
53239
53323
  throw new Error(
53240
53324
  `${kind} name ${JSON.stringify(value)} is not a valid Neo identifier.`
53241
53325
  );
53242
53326
  }
53243
53327
  }
53328
+ function assertMemberIdentifier2(value, kind) {
53329
+ if (!isValidNeoProjectMemberIdentifier(value)) {
53330
+ throw new Error(
53331
+ `${kind} name ${JSON.stringify(value)} is not a valid Neo member identifier.`
53332
+ );
53333
+ }
53334
+ }
53244
53335
  function uniqueIdentifier(requested, used) {
53245
53336
  let candidate = requested;
53246
53337
  let suffix = 2;
@@ -53329,7 +53420,7 @@ function isDialogueSourceIdentifier(value) {
53329
53420
  var init_dialogue_source_identifiers = __esm({
53330
53421
  "../src/models/dialogue/dialogue-source-identifiers.ts"() {
53331
53422
  "use strict";
53332
- init_project_source_identifiers();
53423
+ init_project_source_identifiers2();
53333
53424
  }
53334
53425
  });
53335
53426
 
@@ -53951,6 +54042,7 @@ var init_interface_validation = __esm({
53951
54042
  "../src/models/interfaces/interface-validation.ts"() {
53952
54043
  "use strict";
53953
54044
  init_member_kinds();
54045
+ init_schema_identifiers();
53954
54046
  init_interface_conformance();
53955
54047
  init_interface_graph();
53956
54048
  }
@@ -72783,22 +72875,22 @@ var init_init_backed_value_materialization = __esm({
72783
72875
  function hasRejectedConstructorKey(value) {
72784
72876
  return REJECTED_CONSTRUCTOR_KEYS.some((key) => value[key] !== void 0);
72785
72877
  }
72786
- function isNamedBaseClauseEntry(value) {
72878
+ function isNamedBaseClauseEntry(value, nameIsValid) {
72787
72879
  if (typeof value !== "object" || value === null) return false;
72788
72880
  if (Array.isArray(value)) return false;
72789
72881
  const candidate = value;
72790
72882
  if (!Object.keys(candidate).every((key) => key === "name" || key === "code")) {
72791
72883
  return false;
72792
72884
  }
72793
- if (!isValidCallableIdentifier(candidate.name)) return false;
72885
+ if (!nameIsValid(candidate.name)) return false;
72794
72886
  if (typeof candidate.code !== "string") return false;
72795
72887
  return candidate.code.length > 0;
72796
72888
  }
72797
72889
  function isNeoConstructorBaseArgument(value) {
72798
- return isNamedBaseClauseEntry(value);
72890
+ return isNamedBaseClauseEntry(value, isValidCallableArgumentIdentifier);
72799
72891
  }
72800
72892
  function isNeoConstructorBaseInitializerField(value) {
72801
- return isNamedBaseClauseEntry(value);
72893
+ return isNamedBaseClauseEntry(value, isValidSchemaMemberIdentifier);
72802
72894
  }
72803
72895
  function isNeoClassConstructorBase(value) {
72804
72896
  if (typeof value !== "object" || value === null) return false;
@@ -72814,7 +72906,7 @@ function isNeoClassConstructorBase(value) {
72814
72906
  const argumentTypes = [];
72815
72907
  for (const argument2 of v.argumentTypes) {
72816
72908
  if (!isNSFunctionArgumentTypeInfo(argument2)) return false;
72817
- if (!isValidCallableIdentifier(argument2.name)) return false;
72909
+ if (!isValidCallableArgumentIdentifier(argument2.name)) return false;
72818
72910
  if (parameterNames.has(argument2.name)) return false;
72819
72911
  parameterNames.add(argument2.name);
72820
72912
  argumentTypes.push(argument2);
@@ -72913,6 +73005,7 @@ var init_constructors = __esm({
72913
73005
  init_core();
72914
73006
  init_docs_text2();
72915
73007
  init_member_kinds();
73008
+ init_schema_identifiers();
72916
73009
  init_neoscript();
72917
73010
  REJECTED_CONSTRUCTOR_KEYS = [
72918
73011
  "bodyMode",
@@ -83097,8 +83190,20 @@ function stableValue(value) {
83097
83190
  function stableTypeInfo(value) {
83098
83191
  return JSON.stringify(stableValue(value));
83099
83192
  }
83100
- function isOpaqueCallableIdentifier(value) {
83101
- return typeof value === "string" && OPAQUE_CALLABLE_IDENTIFIER_PATTERN.test(value) && !value.startsWith("__") && !OPAQUE_CALLABLE_RESERVED_NAMES.has(value);
83193
+ function isOpaqueGeneratedIdentifier(value, neoPredicate) {
83194
+ return typeof value === "string" && neoPredicate(value) && isGeneratedCSharpIdentifier(value) && !isGeneratedCSharpReservedKeyword(value);
83195
+ }
83196
+ function isOpaqueSchemaMemberIdentifier(value) {
83197
+ return isOpaqueGeneratedIdentifier(value, isValidNeoProjectMemberIdentifier);
83198
+ }
83199
+ function isOpaqueCallableMemberIdentifier(value) {
83200
+ return isOpaqueSchemaMemberIdentifier(value) && !value.startsWith("__");
83201
+ }
83202
+ function isOpaqueCallableArgumentIdentifier(value) {
83203
+ return isOpaqueGeneratedIdentifier(value, isValidNeoProjectBindingIdentifier) && !value.startsWith("__");
83204
+ }
83205
+ function isOpaqueNSFunctionArgumentIdentifier(value) {
83206
+ return isOpaqueCallableArgumentIdentifier(value) && value !== "value";
83102
83207
  }
83103
83208
  function isOpaqueNSTypeInfo(value, ancestors = /* @__PURE__ */ new Set()) {
83104
83209
  if (!isRecord7(value) || typeof value.required !== "boolean") return false;
@@ -83192,11 +83297,11 @@ function isOpaqueNSFunctionReturnTypeInfo(value) {
83192
83297
  return isOpaqueNSTypeInfo(value);
83193
83298
  }
83194
83299
  function isOpaqueNSFunctionArgumentTypeInfo(value) {
83195
- return isOpaqueNSTypeInfo(value) && isOpaqueCallableIdentifier(value.name) && !opaqueTypeInfoContainsUnknown(value) && hasValidOpaqueParameterDefault(value);
83300
+ return isOpaqueNSTypeInfo(value) && isOpaqueNSFunctionArgumentIdentifier(value.name) && !opaqueTypeInfoContainsUnknown(value) && hasValidOpaqueParameterDefault(value);
83196
83301
  }
83197
83302
  function isOpaqueConstructorArgumentTypeInfo(value) {
83198
83303
  if (!isRecord7(value)) return false;
83199
- return isOpaqueNSTypeInfo(value) && (value.name === "value" || isOpaqueCallableIdentifier(value.name)) && !opaqueTypeInfoContainsUnknown(value) && hasValidOpaqueParameterDefault(value);
83304
+ return isOpaqueNSTypeInfo(value) && isOpaqueCallableArgumentIdentifier(value.name) && !opaqueTypeInfoContainsUnknown(value) && hasValidOpaqueParameterDefault(value);
83200
83305
  }
83201
83306
  function hasValidOpaqueParameterDefault(value) {
83202
83307
  const wrapper = value.defaultValue;
@@ -84649,7 +84754,8 @@ function assertOpaqueBaseClauseListValid(declaredConstructor, spec) {
84649
84754
  `Constructor "${declaredConstructor.id}" has a ${spec.entryLabel} that is not an object.`
84650
84755
  );
84651
84756
  }
84652
- if (!isOpaqueCallableIdentifier(entry.name)) {
84757
+ const nameIsValid = spec.nameKind === "member" ? isOpaqueSchemaMemberIdentifier : isOpaqueCallableArgumentIdentifier;
84758
+ if (!nameIsValid(entry.name)) {
84653
84759
  throw new Error(
84654
84760
  `Constructor "${declaredConstructor.id}" has a ${spec.entryLabel} with an invalid name.`
84655
84761
  );
@@ -84950,7 +85056,7 @@ function assertOpaqueMemberDefaultValueValid(member) {
84950
85056
  }
84951
85057
  function assertOpaqueNSFunctionValid(member, membersById) {
84952
85058
  if (member.kind !== 23) return;
84953
- if (!isOpaqueCallableIdentifier(member.name)) {
85059
+ if (!isOpaqueCallableMemberIdentifier(member.name)) {
84954
85060
  throw new Error(`NSFunction "${member.id}" name is invalid.`);
84955
85061
  }
84956
85062
  if (member.storage !== void 0 && member.storage !== null) {
@@ -85086,34 +85192,14 @@ function assertOpaqueNSFunctionValid(member, membersById) {
85086
85192
  deferred: member.deferred
85087
85193
  });
85088
85194
  }
85089
- var NEO_OBJECT_WORLD_KIND, READ_ONLY_SYNTHETIC_VALUE_ID_PREFIX2, OPAQUE_CALLABLE_IDENTIFIER_PATTERN, OPAQUE_CALLABLE_RESERVED_NAMES, REJECTED_OPAQUE_CONSTRUCTOR_KEYS, OPAQUE_INITIALIZER_KEYS, OPAQUE_BASE_ARGUMENTS_SPEC, OPAQUE_BASE_INITIALIZER_FIELDS_SPEC;
85195
+ var NEO_OBJECT_WORLD_KIND, READ_ONLY_SYNTHETIC_VALUE_ID_PREFIX2, REJECTED_OPAQUE_CONSTRUCTOR_KEYS, OPAQUE_INITIALIZER_KEYS, OPAQUE_BASE_ARGUMENTS_SPEC, OPAQUE_BASE_INITIALIZER_FIELDS_SPEC;
85090
85196
  var init_projectInterfaceValidation = __esm({
85091
85197
  "../convex/projectInterfaceValidation.ts"() {
85092
85198
  "use strict";
85093
85199
  init_projectVariantValidation();
85200
+ init_src();
85094
85201
  NEO_OBJECT_WORLD_KIND = "object";
85095
85202
  READ_ONLY_SYNTHETIC_VALUE_ID_PREFIX2 = "__neo_readonly_default:";
85096
- OPAQUE_CALLABLE_IDENTIFIER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
85097
- OPAQUE_CALLABLE_RESERVED_NAMES = /* @__PURE__ */ new Set([
85098
- "this",
85099
- "root",
85100
- "context",
85101
- "value",
85102
- "true",
85103
- "false",
85104
- "null",
85105
- "void",
85106
- "if",
85107
- "else",
85108
- "return",
85109
- "throw",
85110
- "var",
85111
- "int",
85112
- "float",
85113
- "decimal",
85114
- "string",
85115
- "bool"
85116
- ]);
85117
85203
  REJECTED_OPAQUE_CONSTRUCTOR_KEYS = [
85118
85204
  "bodyMode",
85119
85205
  "uiAction",
@@ -85124,6 +85210,7 @@ var init_projectInterfaceValidation = __esm({
85124
85210
  OPAQUE_BASE_ARGUMENTS_SPEC = {
85125
85211
  authoredKey: "baseArguments",
85126
85212
  compiledKey: "compiledBaseArguments",
85213
+ nameKind: "parameter",
85127
85214
  entryLabel: "base argument",
85128
85215
  compiledLabel: "compiled base arguments",
85129
85216
  clauseLabel: "a base call"
@@ -85131,6 +85218,7 @@ var init_projectInterfaceValidation = __esm({
85131
85218
  OPAQUE_BASE_INITIALIZER_FIELDS_SPEC = {
85132
85219
  authoredKey: "baseInitializerFields",
85133
85220
  compiledKey: "compiledBaseInitializerFields",
85221
+ nameKind: "member",
85134
85222
  entryLabel: "base initializer field",
85135
85223
  compiledLabel: "compiled base initializer fields",
85136
85224
  clauseLabel: "a base initializer block"
@@ -85142,34 +85230,37 @@ var init_projectInterfaceValidation = __esm({
85142
85230
  function isRecord8(value) {
85143
85231
  return typeof value === "object" && value !== null && !Array.isArray(value);
85144
85232
  }
85145
- function assertIdentifier3(value, label) {
85146
- if (isValidSchemaAuthoredIdentifier(value)) return;
85233
+ function assertIdentifier(value, label, predicate) {
85234
+ if (predicate(value)) return;
85147
85235
  throw new Error(
85148
85236
  `${label} must be a valid Neo/codegen identifier; use letters, digits, and underscores, begin with a letter or underscore, and avoid reserved language keywords.`
85149
85237
  );
85150
85238
  }
85151
- function assertArgumentIdentifiers(value, ownerLabel) {
85239
+ function assertArgumentIdentifiers(value, ownerLabel, predicate) {
85152
85240
  if (!Array.isArray(value)) return;
85153
85241
  for (let index = 0; index < value.length; index += 1) {
85154
85242
  const argument2 = value[index];
85155
85243
  if (!isRecord8(argument2)) continue;
85156
- assertIdentifier3(
85244
+ assertIdentifier(
85157
85245
  argument2.name,
85158
- `${ownerLabel} parameter ${index + 1} name ${JSON.stringify(argument2.name)}`
85246
+ `${ownerLabel} parameter ${index + 1} name ${JSON.stringify(argument2.name)}`,
85247
+ predicate
85159
85248
  );
85160
85249
  }
85161
85250
  }
85162
85251
  function assertClassIdentifiers(recordId, value) {
85163
85252
  if (!isRecord8(value)) return;
85164
- assertIdentifier3(
85253
+ assertIdentifier(
85165
85254
  value.name,
85166
- `Class "${recordId}" name ${JSON.stringify(value.name)}`
85255
+ `Class "${recordId}" name ${JSON.stringify(value.name)}`,
85256
+ isValidSchemaAuthoredIdentifier
85167
85257
  );
85168
85258
  if (isRecord8(value.schema)) {
85169
85259
  for (const schemaKey of Object.keys(value.schema)) {
85170
- assertIdentifier3(
85260
+ assertIdentifier(
85171
85261
  schemaKey,
85172
- `Class "${recordId}" schema key ${JSON.stringify(schemaKey)}`
85262
+ `Class "${recordId}" schema key ${JSON.stringify(schemaKey)}`,
85263
+ isValidSchemaMemberIdentifier
85173
85264
  );
85174
85265
  }
85175
85266
  }
@@ -85177,17 +85268,19 @@ function assertClassIdentifiers(recordId, value) {
85177
85268
  for (let index = 0; index < value.genericParams.length; index += 1) {
85178
85269
  const parameter4 = value.genericParams[index];
85179
85270
  if (!isRecord8(parameter4)) continue;
85180
- assertIdentifier3(
85271
+ assertIdentifier(
85181
85272
  parameter4.name,
85182
- `Class "${recordId}" generic parameter ${index + 1} name ${JSON.stringify(parameter4.name)}`
85273
+ `Class "${recordId}" generic parameter ${index + 1} name ${JSON.stringify(parameter4.name)}`,
85274
+ isValidSchemaBindingIdentifier
85183
85275
  );
85184
85276
  }
85185
85277
  }
85186
85278
  function assertEnumIdentifiers(recordId, value) {
85187
85279
  if (!isRecord8(value)) return;
85188
- assertIdentifier3(
85280
+ assertIdentifier(
85189
85281
  value.name,
85190
- `Enum "${recordId}" name ${JSON.stringify(value.name)}`
85282
+ `Enum "${recordId}" name ${JSON.stringify(value.name)}`,
85283
+ isValidSchemaAuthoredIdentifier
85191
85284
  );
85192
85285
  if (!isRecord8(value.options)) return;
85193
85286
  const optionIdsByFoldedName = /* @__PURE__ */ new Map();
@@ -85203,9 +85296,10 @@ function assertEnumIdentifiers(recordId, value) {
85203
85296
  `Enum "${recordId}" option "${optionId}" must embed the same stable id.`
85204
85297
  );
85205
85298
  }
85206
- assertIdentifier3(
85299
+ assertIdentifier(
85207
85300
  option.name,
85208
- `Enum "${recordId}" option "${optionId}" name ${JSON.stringify(option.name)}`
85301
+ `Enum "${recordId}" option "${optionId}" name ${JSON.stringify(option.name)}`,
85302
+ isValidSchemaMemberIdentifier
85209
85303
  );
85210
85304
  const foldedName = option.name.toLowerCase();
85211
85305
  const collidingOptionId = optionIdsByFoldedName.get(foldedName);
@@ -85219,20 +85313,23 @@ function assertEnumIdentifiers(recordId, value) {
85219
85313
  }
85220
85314
  function assertInterfaceIdentifiers(recordId, value) {
85221
85315
  if (!isRecord8(value)) return;
85222
- assertIdentifier3(
85316
+ assertIdentifier(
85223
85317
  value.name,
85224
- `Interface "${recordId}" name ${JSON.stringify(value.name)}`
85318
+ `Interface "${recordId}" name ${JSON.stringify(value.name)}`,
85319
+ isValidSchemaAuthoredIdentifier
85225
85320
  );
85226
85321
  if (!isRecord8(value.members)) return;
85227
85322
  for (const [memberKey, member] of Object.entries(value.members)) {
85228
- assertIdentifier3(
85323
+ assertIdentifier(
85229
85324
  memberKey,
85230
- `Interface "${recordId}" member name ${JSON.stringify(memberKey)}`
85325
+ `Interface "${recordId}" member name ${JSON.stringify(memberKey)}`,
85326
+ isValidSchemaMemberIdentifier
85231
85327
  );
85232
85328
  if (!isRecord8(member) || member.kind !== "function") continue;
85233
85329
  assertArgumentIdentifiers(
85234
85330
  member.argumentTypes,
85235
- `Interface "${recordId}" function "${memberKey}"`
85331
+ `Interface "${recordId}" function "${memberKey}"`,
85332
+ isValidSchemaNSFunctionBindingIdentifier
85236
85333
  );
85237
85334
  }
85238
85335
  }
@@ -85244,15 +85341,17 @@ function isCallableOrPropertyMemberKind(value) {
85244
85341
  function assertMemberIdentifiers(recordId, value, directlyAuthoredMemberIds) {
85245
85342
  if (!isRecord8(value)) return;
85246
85343
  if (directlyAuthoredMemberIds.has(recordId) || isCallableOrPropertyMemberKind(value)) {
85247
- assertIdentifier3(
85344
+ assertIdentifier(
85248
85345
  value.name,
85249
- `Member "${recordId}" name ${JSON.stringify(value.name)}`
85346
+ `Member "${recordId}" name ${JSON.stringify(value.name)}`,
85347
+ isValidSchemaMemberIdentifier
85250
85348
  );
85251
85349
  }
85252
85350
  if (value.kind !== 13 && value.kind !== 23) return;
85253
85351
  assertArgumentIdentifiers(
85254
85352
  value.argumentTypes,
85255
- `Function member "${recordId}"`
85353
+ `Function member "${recordId}"`,
85354
+ value.kind === 23 ? isValidSchemaNSFunctionBindingIdentifier : isValidSchemaBindingIdentifier
85256
85355
  );
85257
85356
  }
85258
85357
  function assertSchemaIdentifierWriteChangesValid(changes, directlyAuthoredMemberIds) {
@@ -109307,7 +109406,7 @@ function isObjectRecord5(value) {
109307
109406
  var init_project_file_authoring_identifiers = __esm({
109308
109407
  "../src/models/project-file-authoring-identifiers.ts"() {
109309
109408
  "use strict";
109310
- init_project_source_identifiers();
109409
+ init_project_source_identifiers2();
109311
109410
  }
109312
109411
  });
109313
109412
 
@@ -112251,7 +112350,7 @@ var init_registry2 = __esm({
112251
112350
  PROJECT_SCHEMA_CONTRACT = Object.freeze({
112252
112351
  formatVersion: 3,
112253
112352
  contractVersion: "3.13",
112254
- cliVersion: "0.32.2",
112353
+ cliVersion: "0.32.4",
112255
112354
  projectFileUploadBatchSize: 32,
112256
112355
  documentRecords: {
112257
112356
  member: {
@@ -118846,7 +118945,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
118846
118945
  async function main() {
118847
118946
  const args = parseArgs(process.argv.slice(2));
118848
118947
  if (args.command === "--version") {
118849
- console.log("0.32.2");
118948
+ console.log("0.32.4");
118850
118949
  return;
118851
118950
  }
118852
118951
  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.32.2",
3
+ "version": "0.32.4",
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.32.2 -->
12
+ <!-- reviewed-through-cli: 0.32.4 -->
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.32.2 -->
86
+ <!-- reviewed-through-cli: 0.32.4 -->
87
87
  ```
88
88
 
89
89
  The quoted version above is checked too, so this instruction cannot go stale
@@ -21,6 +21,15 @@ migration, or `.neoflow` file. NeoFlow has its own single-dialogue exception.
21
21
  Persist the declared identifier as the schema name; there is no separate
22
22
  technical/display name. Keep existing IDs stable.
23
23
 
24
+ NeoScript keywords are case-sensitive. Qualified member labels, schema keys,
25
+ registry entries, and enum options occupy their owner's namespace, so they may
26
+ reuse unrelated builtin names such as `Set`, `Dictionary`, `List`, or `Math`.
27
+ Type-token spellings such as `Set` and `Dictionary` are also legal parameters.
28
+ Actual lowercase grammar keywords such as `class` and `return` remain
29
+ reserved. Top-level declarations and bindings retain their own reservations:
30
+ for example, neither may shadow the unqualified builtin `Math` namespace, and
31
+ implicit bindings such as `this`, `root`, and `context` cannot be parameters.
32
+
24
33
  ```neo
25
34
  @id("interface-named-id")
26
35
  interface INamed {
@@ -108,8 +108,10 @@ language's `float`-to-`int` conversions: they return `int` for `int` and
108
108
  at runtime. `Round` rounds midpoints to even, matching `decimal.Round(0)`.
109
109
  `Sign` always returns `int`; `Sqrt` takes `int` or `float` only.
110
110
 
111
- `Math` is a qualifier, never a type or a value, and the name is reserved: no
112
- Class, enum, member, parameter, or local may be named `Math`.
111
+ `Math` is an unqualified builtin qualifier, never a type or value, so no Class,
112
+ enum, parameter, or local may shadow it. Qualified members use their owner's
113
+ namespace and may be named `Math`; access one as `this.Math` or
114
+ `SomeValue.Math` without colliding with the builtin qualifier.
113
115
 
114
116
  ## Logical operators
115
117