@neocompose/cli 0.72.1 → 0.72.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 +6 -0
- package/dist/neo.mjs +213 -59
- package/dist/test-worker.mjs +31 -7
- package/package.json +1 -1
- package/skills/neocompose-cli/SKILL.md +1 -1
- package/skills/neocompose-cli/references/cli-development.md +1 -1
- package/skills/neocompose-cli/references/declarations-and-construction.md +7 -1
- package/skills/neocompose-cli/references/neoscript.md +4 -0
- package/skills/neocompose-cli/references/values-identities-and-references.md +3 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.72.2] - 2026-10-08
|
|
4
|
+
|
|
5
|
+
- Resolve void statement calls through generic class and interface constraints, preserving generic arguments and receiver nullability checks.
|
|
6
|
+
- Infer contextual enum literals in positional and named constructor arguments, including generic parameters and overloads with defaults.
|
|
7
|
+
- Reject unrelated explicit class constructions in typed initializers, with source diagnostics that agree between the editor and CLI. Preserve concrete and generic types when a local target-typed construction is stored through a base-class member.
|
|
8
|
+
|
|
3
9
|
## [0.72.1] - 2026-10-07
|
|
4
10
|
|
|
5
11
|
- Speed up `neo export` and `neo dev`: reuse verified unchanged exports, cache unchanged parsing and preparation work, share dialogue compiler symbols, and index Unity generation. Regenerate C# only when its schema inputs change; continue validating edited content and repairing changed output files.
|
package/dist/neo.mjs
CHANGED
|
@@ -20567,11 +20567,12 @@ var init_local_values = __esm({
|
|
|
20567
20567
|
init_formatter();
|
|
20568
20568
|
init_workspace_source_path();
|
|
20569
20569
|
init_executable_parser();
|
|
20570
|
+
init_source_text();
|
|
20570
20571
|
init_language_spec();
|
|
20571
20572
|
init_lower_support();
|
|
20572
20573
|
LocalValueBindingsV4 = class {
|
|
20573
20574
|
definitions = /* @__PURE__ */ new Map();
|
|
20574
|
-
|
|
20575
|
+
initializers = /* @__PURE__ */ new Map();
|
|
20575
20576
|
owners = /* @__PURE__ */ new Map();
|
|
20576
20577
|
/** Static members whose initializer is a bare local name, by that name. */
|
|
20577
20578
|
ownerMembers = /* @__PURE__ */ new Map();
|
|
@@ -20608,7 +20609,7 @@ var init_local_values = __esm({
|
|
|
20608
20609
|
owners.set(valueId, source.label);
|
|
20609
20610
|
this.owners.set(global.name, owners);
|
|
20610
20611
|
}
|
|
20611
|
-
text =
|
|
20612
|
+
text = step.text;
|
|
20612
20613
|
expression = step.expression;
|
|
20613
20614
|
source = {
|
|
20614
20615
|
...source,
|
|
@@ -20627,7 +20628,28 @@ var init_local_values = __esm({
|
|
|
20627
20628
|
let last = null;
|
|
20628
20629
|
for (const step of this.chain(name)) last = step;
|
|
20629
20630
|
if (last === null) return null;
|
|
20630
|
-
return { expression: last.expression, text: last.
|
|
20631
|
+
return { expression: last.expression, text: last.text };
|
|
20632
|
+
}
|
|
20633
|
+
initializer(global) {
|
|
20634
|
+
const cached = this.initializers.get(global.name);
|
|
20635
|
+
if (cached) return cached;
|
|
20636
|
+
let text = global.initializer;
|
|
20637
|
+
let expression = parseExpression(text);
|
|
20638
|
+
let construction = expression;
|
|
20639
|
+
while (construction.kind === "annotated")
|
|
20640
|
+
construction = construction.expression;
|
|
20641
|
+
if (construction.kind === "new" && construction.className === null) {
|
|
20642
|
+
const offset = new SourceText(text).offsetAt({
|
|
20643
|
+
line: construction.pos.line - 1,
|
|
20644
|
+
character: construction.pos.column - 1
|
|
20645
|
+
}) + 3;
|
|
20646
|
+
const type = typeText({ ...global.type, nullable: false });
|
|
20647
|
+
text = `${text.slice(0, offset)} ${type}${text.slice(offset)}`;
|
|
20648
|
+
expression = parseExpression(text);
|
|
20649
|
+
}
|
|
20650
|
+
const prepared = { global, expression, text };
|
|
20651
|
+
this.initializers.set(global.name, prepared);
|
|
20652
|
+
return prepared;
|
|
20631
20653
|
}
|
|
20632
20654
|
/** Each local an alias chain starting at `name` passes through, in order. */
|
|
20633
20655
|
*chain(name) {
|
|
@@ -20637,9 +20659,9 @@ var init_local_values = __esm({
|
|
|
20637
20659
|
if (visited.has(global.name))
|
|
20638
20660
|
throw new Error(`Local initializer cycle reaches ${global.name}.`);
|
|
20639
20661
|
visited.add(global.name);
|
|
20640
|
-
const
|
|
20641
|
-
|
|
20642
|
-
yield
|
|
20662
|
+
const prepared = this.initializer(global);
|
|
20663
|
+
const { expression } = prepared;
|
|
20664
|
+
yield prepared;
|
|
20643
20665
|
global = expression.kind === "ident" ? this.definitions.get(expression.name) : void 0;
|
|
20644
20666
|
}
|
|
20645
20667
|
}
|
|
@@ -20685,7 +20707,7 @@ var init_local_values = __esm({
|
|
|
20685
20707
|
const placements = [];
|
|
20686
20708
|
for (const [name, definition2] of this.definitions) {
|
|
20687
20709
|
const valueIds = this.owners.get(name)?.keys().toArray() ?? [];
|
|
20688
|
-
const expression = this.
|
|
20710
|
+
const expression = this.initializers.get(name)?.expression ?? parseExpression(definition2.initializer);
|
|
20689
20711
|
placements.push({
|
|
20690
20712
|
name,
|
|
20691
20713
|
type: typeText(definition2.type),
|
|
@@ -28282,6 +28304,20 @@ var init_collection_query = __esm({
|
|
|
28282
28304
|
function neoScriptArgumentNameSetKey(names) {
|
|
28283
28305
|
return [...names].map((name) => name.toLowerCase()).sort().join(",");
|
|
28284
28306
|
}
|
|
28307
|
+
function neoScriptParameterByName(parameters, name) {
|
|
28308
|
+
let indexes3 = parameterNameIndexes.get(parameters);
|
|
28309
|
+
if (!indexes3) {
|
|
28310
|
+
const built = /* @__PURE__ */ new Map();
|
|
28311
|
+
for (let index2 = 0; index2 < parameters.length; index2++) {
|
|
28312
|
+
const key = parameters[index2].name.toLowerCase();
|
|
28313
|
+
if (!built.has(key)) built.set(key, index2);
|
|
28314
|
+
}
|
|
28315
|
+
indexes3 = built;
|
|
28316
|
+
parameterNameIndexes.set(parameters, indexes3);
|
|
28317
|
+
}
|
|
28318
|
+
const index = indexes3.get(name.toLowerCase());
|
|
28319
|
+
return index === void 0 ? void 0 : parameters[index];
|
|
28320
|
+
}
|
|
28285
28321
|
function neoScriptCallMatchesParameters(suppliedNames, parameters) {
|
|
28286
28322
|
const supplied = new Set(suppliedNames.map((name) => name.toLowerCase()));
|
|
28287
28323
|
const declared = new Set(
|
|
@@ -28542,10 +28578,12 @@ function describeParameter(parameter4) {
|
|
|
28542
28578
|
const defaulted = parameter4.defaultValue === void 0 ? "" : ` = ${parameter4.defaultValue.displayText}`;
|
|
28543
28579
|
return `${parameter4.name}${nullability}${defaulted}`;
|
|
28544
28580
|
}
|
|
28581
|
+
var parameterNameIndexes;
|
|
28545
28582
|
var init_declared_constructors = __esm({
|
|
28546
28583
|
"../packages/neoscript-language/src/declared-constructors.ts"() {
|
|
28547
28584
|
"use strict";
|
|
28548
28585
|
init_project2();
|
|
28586
|
+
parameterNameIndexes = /* @__PURE__ */ new WeakMap();
|
|
28549
28587
|
}
|
|
28550
28588
|
});
|
|
28551
28589
|
|
|
@@ -35304,6 +35342,7 @@ var init_strict_resolver = __esm({
|
|
|
35304
35342
|
(candidate) => (candidate.kind === "function" || candidate.kind === "method") && candidate.name === callee.name
|
|
35305
35343
|
);
|
|
35306
35344
|
if (member) {
|
|
35345
|
+
this.validateFunctionReceiver(receiver, callee.name, optional2, pos);
|
|
35307
35346
|
if (type !== void 0) this.assertMemberAccessible(type, member, pos);
|
|
35308
35347
|
if (member.static === true) {
|
|
35309
35348
|
throw new CompileError(
|
|
@@ -36452,12 +36491,10 @@ var init_strict_resolver = __esm({
|
|
|
36452
36491
|
callableSignatureForReceiver(symbol, receiver) {
|
|
36453
36492
|
let parameters = symbol.parameters ?? [];
|
|
36454
36493
|
let returnType = symbol.returnType ?? symbol.type;
|
|
36455
|
-
if (this.context.projectSourceKind !== "spec" && !(receiver?.kind === "instance" && receiver.dispatch === "base")) {
|
|
36456
|
-
return { parameters, returnType };
|
|
36457
|
-
}
|
|
36458
36494
|
if (receiver?.kind !== "instance") return { parameters, returnType };
|
|
36459
36495
|
const receiverType = receiver.expression.type;
|
|
36460
36496
|
if (receiverType.kind !== "named") return { parameters, returnType };
|
|
36497
|
+
if (!receiverType.typeArguments?.length) return { parameters, returnType };
|
|
36461
36498
|
const declaring = this.project.typeById.get(receiverType.typeId);
|
|
36462
36499
|
if (declaring === void 0) return { parameters, returnType };
|
|
36463
36500
|
parameters = parameters.map((parameter4) => ({
|
|
@@ -37361,6 +37398,21 @@ var init_strict_resolver = __esm({
|
|
|
37361
37398
|
callSiteId: this.nextCallSite(expression.pos)
|
|
37362
37399
|
};
|
|
37363
37400
|
}
|
|
37401
|
+
validateFunctionReceiver(receiver, name, optional2, pos) {
|
|
37402
|
+
if (optional2 && !isNullable(receiver.type)) {
|
|
37403
|
+
throw new CompileError(
|
|
37404
|
+
`\`?.\` requires an optional receiver; got ${this.describe(receiver.type)}`,
|
|
37405
|
+
pos
|
|
37406
|
+
);
|
|
37407
|
+
}
|
|
37408
|
+
const receiverType = receiver.optionalChainType ?? receiver.type;
|
|
37409
|
+
if (!optional2 && isNullable(receiverType)) {
|
|
37410
|
+
throw new CompileError(
|
|
37411
|
+
`Function '${name}' is called on ${this.describe(receiverType)}, which may be null. Use optional chaining, force-unwrapping, or a null check before calling it.`,
|
|
37412
|
+
pos
|
|
37413
|
+
);
|
|
37414
|
+
}
|
|
37415
|
+
}
|
|
37364
37416
|
resolveFunctionStatement(expression, scope) {
|
|
37365
37417
|
if (expression.kind !== "call") return null;
|
|
37366
37418
|
const receiverValue = this.callReceiver(expression.callee, scope);
|
|
@@ -37524,12 +37576,19 @@ var init_strict_resolver = __esm({
|
|
|
37524
37576
|
}
|
|
37525
37577
|
}
|
|
37526
37578
|
const receiver = receiverValue();
|
|
37527
|
-
|
|
37528
|
-
|
|
37579
|
+
const memberReceiverType = neoScriptMemberLookupType(receiver.type);
|
|
37580
|
+
if (memberReceiverType.kind !== "named") return null;
|
|
37581
|
+
const type = this.project.typeById.get(memberReceiverType.typeId);
|
|
37529
37582
|
const symbol = type?.members.find(
|
|
37530
37583
|
(candidate) => (candidate.kind === "function" || candidate.kind === "method") && candidate.name === memberName
|
|
37531
37584
|
);
|
|
37532
37585
|
if (!symbol) return null;
|
|
37586
|
+
this.validateFunctionReceiver(
|
|
37587
|
+
receiver,
|
|
37588
|
+
memberName,
|
|
37589
|
+
expression.callee.optional === true,
|
|
37590
|
+
expression.pos
|
|
37591
|
+
);
|
|
37533
37592
|
if (type !== void 0) {
|
|
37534
37593
|
this.assertMemberAccessible(type, symbol, expression.pos);
|
|
37535
37594
|
}
|
|
@@ -37542,7 +37601,10 @@ var init_strict_resolver = __esm({
|
|
|
37542
37601
|
this.validateCallableInContext(symbol, expression.pos);
|
|
37543
37602
|
const resolved = this.resolveCallableArguments(
|
|
37544
37603
|
symbol,
|
|
37545
|
-
{
|
|
37604
|
+
{
|
|
37605
|
+
kind: "instance",
|
|
37606
|
+
expression: memberReceiverType === receiver.type ? receiver : { ...receiver, type: memberReceiverType }
|
|
37607
|
+
},
|
|
37546
37608
|
expression.args,
|
|
37547
37609
|
scope,
|
|
37548
37610
|
expression.pos
|
|
@@ -42576,6 +42638,7 @@ function createEnvironment(documents, project) {
|
|
|
42576
42638
|
project,
|
|
42577
42639
|
projectIndex: createProjectIndex(project),
|
|
42578
42640
|
listenerResolvers: /* @__PURE__ */ new Map(),
|
|
42641
|
+
assignability: /* @__PURE__ */ new Map(),
|
|
42579
42642
|
enums,
|
|
42580
42643
|
types,
|
|
42581
42644
|
globals,
|
|
@@ -43854,13 +43917,19 @@ function validateExpression(expression, expected, scope, environment, uri, range
|
|
|
43854
43917
|
);
|
|
43855
43918
|
return;
|
|
43856
43919
|
}
|
|
43857
|
-
if (expected && expression.kind !== "contextualEnum" && !isReferenceCall(expression)) {
|
|
43920
|
+
if (expected && expression.kind !== "contextualEnum" && expression.kind !== "annotated" && !isReferenceCall(expression)) {
|
|
43858
43921
|
const actual = inferExpressionType(expression, scope, environment);
|
|
43859
|
-
|
|
43922
|
+
const explicitConstruction = expression.kind === "new" && expression.className !== null && expected.name !== "Partial";
|
|
43923
|
+
const assignable = actual === void 0 || (explicitConstruction ? constructionTypesAssignable(actual, expected, scope, environment) : semanticTypesAssignable(actual, expected));
|
|
43924
|
+
if (actual && !assignable) {
|
|
43860
43925
|
pushDiagnostic(
|
|
43861
43926
|
diagnostics,
|
|
43862
43927
|
uri,
|
|
43863
|
-
anchor ? anchorSpan(
|
|
43928
|
+
anchor ? anchorSpan(
|
|
43929
|
+
anchor,
|
|
43930
|
+
expression.pos,
|
|
43931
|
+
expression.kind === "new" ? 3 : 1
|
|
43932
|
+
) : range2,
|
|
43864
43933
|
"project-expression-type-mismatch",
|
|
43865
43934
|
`Expected ${describeType(expected)} but received ${describeType(actual)}.`
|
|
43866
43935
|
);
|
|
@@ -44134,23 +44203,26 @@ function validateExpression(expression, expected, scope, environment, uri, range
|
|
|
44134
44203
|
}))
|
|
44135
44204
|
);
|
|
44136
44205
|
}
|
|
44137
|
-
const
|
|
44138
|
-
|
|
44139
|
-
|
|
44140
|
-
|
|
44206
|
+
const parameters = declaration.headerParameters ?? matchingDeclaredConstructor(declaration, siteArgumentNames)?.parameters;
|
|
44207
|
+
const fields = [];
|
|
44208
|
+
const fieldsByName = /* @__PURE__ */ new Map();
|
|
44209
|
+
if (declaration.headerParameters === void 0 && declaration.constructors.length === 0) {
|
|
44210
|
+
for (const member of declaration.members) {
|
|
44211
|
+
if (member.kind !== "field" || member.modifiers.includes("static"))
|
|
44212
|
+
continue;
|
|
44213
|
+
fields.push(member);
|
|
44214
|
+
fieldsByName.set(member.name, member);
|
|
44215
|
+
}
|
|
44216
|
+
}
|
|
44141
44217
|
expression.args.forEach((argument2, index) => {
|
|
44142
44218
|
const authoredName = expression.argumentNames?.[index];
|
|
44143
44219
|
const named = declaration.name === NEO_LOOKUP_VARIANT_FOLDER_TYPE_NAME ? authoredName ?? NEO_LOOKUP_VARIANT_FOLDER_CONSTRUCTOR_ARGUMENTS[index]?.name : authoredName;
|
|
44144
44220
|
if (declaration.name === NEO_LOOKUP_VARIANT_FOLDER_TYPE_NAME && named === "collection") {
|
|
44145
44221
|
return;
|
|
44146
44222
|
}
|
|
44147
|
-
const parameter4 = named ? (
|
|
44148
|
-
(candidate) => candidate.name === named
|
|
44149
|
-
) ?? overload?.parameters.find((candidate) => candidate.name === named) : void 0;
|
|
44223
|
+
const parameter4 = named && parameters ? neoScriptParameterByName(parameters, named) : parameters?.[index];
|
|
44150
44224
|
const variantMember = named === void 0 || named === null ? void 0 : variantSite === null ? void 0 : NEO_VARIANT_MEMBER_ARGUMENTS.get(named);
|
|
44151
|
-
const field = named ?
|
|
44152
|
-
(candidate) => candidate.name === (variantMember ?? named)
|
|
44153
|
-
) : fields[index];
|
|
44225
|
+
const field = named ? fieldsByName.get(variantMember ?? named) : fields[index];
|
|
44154
44226
|
const expectedType = parameter4?.type ?? field?.type;
|
|
44155
44227
|
const expectedSemanticType = declaration.name === NEO_LOOKUP_VARIANT_FOLDER_TYPE_NAME && named === "collectionValue" ? { name: "string" } : expectedType ? substituteSemanticType(semanticType(expectedType), siteBindings) : void 0;
|
|
44156
44228
|
validateExpression(
|
|
@@ -44450,6 +44522,41 @@ function commonSemanticAssignableType(left, right) {
|
|
|
44450
44522
|
if (semanticTypesAssignable(right, left)) return left;
|
|
44451
44523
|
return void 0;
|
|
44452
44524
|
}
|
|
44525
|
+
function constructionTypesAssignable(actual, expected, scope, environment) {
|
|
44526
|
+
if (actual.name === expected.name && !actual.arguments?.length && !expected.arguments?.length)
|
|
44527
|
+
return true;
|
|
44528
|
+
const owner = scope.get("this")?.name ?? "";
|
|
44529
|
+
const key = `${owner}:${describeType(actual)}>${describeType(expected)}`;
|
|
44530
|
+
const cached = environment.assignability.get(key);
|
|
44531
|
+
if (cached !== void 0) return cached;
|
|
44532
|
+
const declaration = environment.projectIndex.typeByName.get(owner);
|
|
44533
|
+
const context = {
|
|
44534
|
+
project: environment.project,
|
|
44535
|
+
kind: "initializerExpression",
|
|
44536
|
+
...declaration ? { declaringType: { kind: "named", typeId: declaration.id } } : {}
|
|
44537
|
+
};
|
|
44538
|
+
const pos = { line: 1, column: 1 };
|
|
44539
|
+
let assignable = true;
|
|
44540
|
+
try {
|
|
44541
|
+
assignable = isNeoScriptTypeAssignable(
|
|
44542
|
+
resolveNeoScriptType(
|
|
44543
|
+
semanticAst(actual, pos),
|
|
44544
|
+
context,
|
|
44545
|
+
environment.projectIndex
|
|
44546
|
+
),
|
|
44547
|
+
resolveNeoScriptType(
|
|
44548
|
+
semanticAst(expected, pos),
|
|
44549
|
+
context,
|
|
44550
|
+
environment.projectIndex
|
|
44551
|
+
),
|
|
44552
|
+
environment.projectIndex
|
|
44553
|
+
);
|
|
44554
|
+
} catch (error) {
|
|
44555
|
+
if (!(error instanceof CompileError)) throw error;
|
|
44556
|
+
}
|
|
44557
|
+
environment.assignability.set(key, assignable);
|
|
44558
|
+
return assignable;
|
|
44559
|
+
}
|
|
44453
44560
|
function semanticNumericRank(name) {
|
|
44454
44561
|
if (name === "int") return 0;
|
|
44455
44562
|
if (name === "float") return 1;
|
|
@@ -44599,7 +44706,10 @@ function inferExpressionType(expression, scope, environment) {
|
|
|
44599
44706
|
if (expression.kind === "litString" || expression.kind === "litInterp" || expression.kind === "litTripleString")
|
|
44600
44707
|
return primitiveType("string");
|
|
44601
44708
|
if (expression.kind === "new")
|
|
44602
|
-
return expression.className ? {
|
|
44709
|
+
return expression.className ? {
|
|
44710
|
+
name: expression.className,
|
|
44711
|
+
...expression.typeArguments ? { arguments: expression.typeArguments.map(semanticAstType) } : {}
|
|
44712
|
+
} : void 0;
|
|
44603
44713
|
if (expression.kind === "force") {
|
|
44604
44714
|
const operand = inferExpressionType(expression.operand, scope, environment);
|
|
44605
44715
|
return operand ? { ...operand, nullable: false } : void 0;
|
|
@@ -44874,14 +44984,19 @@ function classExtends(actual, expected, environment, visited) {
|
|
|
44874
44984
|
);
|
|
44875
44985
|
}
|
|
44876
44986
|
function matchingDeclaredConstructor(declaration, argumentNames) {
|
|
44877
|
-
|
|
44878
|
-
|
|
44879
|
-
);
|
|
44880
|
-
const
|
|
44881
|
-
const
|
|
44882
|
-
|
|
44987
|
+
if (declaration.constructors.length === 1)
|
|
44988
|
+
return declaration.constructors[0] ?? null;
|
|
44989
|
+
if (argumentNames.some((name) => name === null)) return null;
|
|
44990
|
+
const names = argumentNames.filter((name) => name !== null);
|
|
44991
|
+
const resolution = resolveNeoScriptNamedOverload(
|
|
44992
|
+
declaration.constructors,
|
|
44993
|
+
names,
|
|
44994
|
+
(constructor2) => constructor2.parameters.map((parameter4) => ({
|
|
44995
|
+
name: parameter4.name,
|
|
44996
|
+
defaulted: parameter4.defaultValue !== void 0
|
|
44997
|
+
}))
|
|
44883
44998
|
);
|
|
44884
|
-
return
|
|
44999
|
+
return resolution.kind === "resolved" ? resolution.overload : null;
|
|
44885
45000
|
}
|
|
44886
45001
|
function semanticType(type) {
|
|
44887
45002
|
return {
|
|
@@ -45230,6 +45345,7 @@ var init_project_source_semantics = __esm({
|
|
|
45230
45345
|
init_strict_compile_error();
|
|
45231
45346
|
init_executable_parser();
|
|
45232
45347
|
init_project_source_construction_diagnostics();
|
|
45348
|
+
init_declared_constructors();
|
|
45233
45349
|
init_project_source_variants();
|
|
45234
45350
|
init_language_spec();
|
|
45235
45351
|
init_project_source_settlement();
|
|
@@ -50866,7 +50982,7 @@ var init_registry = __esm({
|
|
|
50866
50982
|
"../packages/manifest/schema-contract/registry.mjs"() {
|
|
50867
50983
|
"use strict";
|
|
50868
50984
|
PROJECT_SCHEMA_CONTRACT = Object.freeze({
|
|
50869
|
-
cliVersion: "0.72.
|
|
50985
|
+
cliVersion: "0.72.2",
|
|
50870
50986
|
projectFileUploadBatchSize: 32,
|
|
50871
50987
|
documentRecords: {
|
|
50872
50988
|
member: {
|
|
@@ -110681,7 +110797,8 @@ function* prepareServerOwnedSchemaCommitPasses(args) {
|
|
|
110681
110797
|
continue;
|
|
110682
110798
|
const key = `${change.recordKind}:${change.recordId}`;
|
|
110683
110799
|
const base = baseScriptRecords.get(key);
|
|
110684
|
-
if (base &&
|
|
110800
|
+
if (base && // Rollout-tolerated bodies still need recompilation before reuse.
|
|
110801
|
+
firstRejectedNeoScriptCompiledBody(base, null) === null && !hasPendingNeoScriptDerivation(change.recordKind, base) && canonicallyEqual2(
|
|
110685
110802
|
authoredScriptRecord(change.recordKind, base),
|
|
110686
110803
|
authoredScriptRecord(change.recordKind, change.nextData)
|
|
110687
110804
|
))
|
|
@@ -110733,12 +110850,14 @@ function* prepareServerOwnedSchemaCommitPasses(args) {
|
|
|
110733
110850
|
if (kind === "member")
|
|
110734
110851
|
remappedMembers.set(record7.id, {
|
|
110735
110852
|
...moved,
|
|
110736
|
-
|
|
110853
|
+
createdAt: record7.createdAt,
|
|
110854
|
+
updatedAt: record7.updatedAt
|
|
110737
110855
|
});
|
|
110738
110856
|
else
|
|
110739
110857
|
remappedConstructors.set(record7.id, {
|
|
110740
110858
|
...moved,
|
|
110741
|
-
|
|
110859
|
+
createdAt: record7.createdAt,
|
|
110860
|
+
updatedAt: record7.updatedAt
|
|
110742
110861
|
});
|
|
110743
110862
|
}
|
|
110744
110863
|
}
|
|
@@ -114517,6 +114636,7 @@ var init_project_version_schema_commit = __esm({
|
|
|
114517
114636
|
"../src/database/project-version-schema-commit.ts"() {
|
|
114518
114637
|
"use strict";
|
|
114519
114638
|
init_dialogue_logic_compile_pure();
|
|
114639
|
+
init_neoscript_compiler_revision();
|
|
114520
114640
|
init_neoscript_source_catalog();
|
|
114521
114641
|
init_prepared_collection_bindings();
|
|
114522
114642
|
init_stored_closure_captures();
|
|
@@ -148410,6 +148530,14 @@ function projectCompletions(analysis, document, position) {
|
|
|
148410
148530
|
}))
|
|
148411
148531
|
};
|
|
148412
148532
|
}
|
|
148533
|
+
const contextualEnum = projectContextualEnumCompletions(
|
|
148534
|
+
analysis,
|
|
148535
|
+
document,
|
|
148536
|
+
position
|
|
148537
|
+
);
|
|
148538
|
+
if (contextualEnum) {
|
|
148539
|
+
return { isIncomplete: false, items: contextualEnum };
|
|
148540
|
+
}
|
|
148413
148541
|
const constructorFields = projectConstructorArgumentCompletions(
|
|
148414
148542
|
analysis,
|
|
148415
148543
|
document,
|
|
@@ -148436,14 +148564,6 @@ function projectCompletions(analysis, document, position) {
|
|
|
148436
148564
|
if (initializerMembers) {
|
|
148437
148565
|
return { isIncomplete: false, items: initializerMembers };
|
|
148438
148566
|
}
|
|
148439
|
-
const contextualEnum = projectContextualEnumCompletions(
|
|
148440
|
-
analysis,
|
|
148441
|
-
document,
|
|
148442
|
-
position
|
|
148443
|
-
);
|
|
148444
|
-
if (contextualEnum) {
|
|
148445
|
-
return { isIncomplete: false, items: contextualEnum };
|
|
148446
|
-
}
|
|
148447
148567
|
return projectFallbackCompletions(analysis, document, position);
|
|
148448
148568
|
}
|
|
148449
148569
|
function projectListenerContext(analysis, document, position) {
|
|
@@ -149775,11 +149895,19 @@ function projectCallArguments(tokens, openIndex, delimiterEnds) {
|
|
|
149775
149895
|
result.push({
|
|
149776
149896
|
start: token.range.start,
|
|
149777
149897
|
named: token.kind === "identifier" && tokens[index + 1]?.text === ":",
|
|
149898
|
+
name: token.kind === "identifier" && tokens[index + 1]?.text === ":" ? token.text : null,
|
|
149778
149899
|
...token.kind === "identifier" && (tokens[index + 1]?.text === "," || tokens[index + 1]?.text === ")") ? { identifier: token.text } : {}
|
|
149779
149900
|
});
|
|
149780
149901
|
atArgumentStart = false;
|
|
149781
149902
|
}
|
|
149782
|
-
if (token.text === "
|
|
149903
|
+
if (token.text === "new" && tokens[index + 2]?.text === "<") {
|
|
149904
|
+
let depth = 0;
|
|
149905
|
+
index += 2;
|
|
149906
|
+
for (; index < tokens.length; index++) {
|
|
149907
|
+
if (tokens[index].text === "<") depth++;
|
|
149908
|
+
else if (tokens[index].text === ">" && --depth === 0) break;
|
|
149909
|
+
}
|
|
149910
|
+
} else if (token.text === "(" || token.text === "[" || token.text === "{") {
|
|
149783
149911
|
index = delimiterEnds.get(index) ?? tokens.length;
|
|
149784
149912
|
}
|
|
149785
149913
|
}
|
|
@@ -150387,6 +150515,7 @@ function indexConstructionSites(analysis, document, root) {
|
|
|
150387
150515
|
while (end < allTokens.length && positionCompare(allTokens[end].range.start, root.range.end) <= 0)
|
|
150388
150516
|
end++;
|
|
150389
150517
|
const tokens = allTokens.slice(start, end).filter((token) => token.kind !== "comment" && token.kind !== "eof");
|
|
150518
|
+
let delimiterEnds;
|
|
150390
150519
|
const language = listenerSourceContext(analysis, document, root.range.start);
|
|
150391
150520
|
const resolveSourceType = (type) => {
|
|
150392
150521
|
if (!type) return null;
|
|
@@ -150427,15 +150556,17 @@ function indexConstructionSites(analysis, document, root) {
|
|
|
150427
150556
|
const declaration = language.project.typeById.get(frame.typeRef.typeId);
|
|
150428
150557
|
if (!declaration) return null;
|
|
150429
150558
|
const constructors = declaration.declaredConstructors;
|
|
150430
|
-
const parameters = constructors?.length
|
|
150431
|
-
const parameter4 = frame.argumentName ? parameters?.
|
|
150432
|
-
|
|
150433
|
-
|
|
150434
|
-
|
|
150435
|
-
|
|
150436
|
-
|
|
150437
|
-
|
|
150438
|
-
|
|
150559
|
+
const parameters = constructors?.length ? constructors[frame.constructorIndex]?.parameters : declaration.constructorSignature?.parameters;
|
|
150560
|
+
const parameter4 = frame.argumentName ? parameters && neoScriptParameterByName(parameters, frame.argumentName) : parameters?.[frame.argumentIndex];
|
|
150561
|
+
if (parameter4) {
|
|
150562
|
+
frame.expectedTypeRef = substituteTypeParameters(
|
|
150563
|
+
"type" in parameter4 ? parameter4.type : parameter4.valueType,
|
|
150564
|
+
frame.typeRef,
|
|
150565
|
+
declaration
|
|
150566
|
+
);
|
|
150567
|
+
} else if (!constructors?.length) {
|
|
150568
|
+
frame.expectedTypeRef = fieldType(frame.typeRef, frame.argumentName);
|
|
150569
|
+
}
|
|
150439
150570
|
return frame.expectedTypeRef;
|
|
150440
150571
|
}
|
|
150441
150572
|
}
|
|
@@ -150458,14 +150589,16 @@ function indexConstructionSites(analysis, document, root) {
|
|
|
150458
150589
|
const objects = [];
|
|
150459
150590
|
const snapshot = () => {
|
|
150460
150591
|
const expected = expectedType();
|
|
150592
|
+
const resolvedExpected = expectedTypeRef();
|
|
150593
|
+
const expectedTypeName = resolvedExpected?.kind === "named" ? language.project.typeById.get(resolvedExpected.typeId)?.name ?? expected?.name : expected?.name;
|
|
150461
150594
|
const innermost = stack.at(-1);
|
|
150462
150595
|
const directly = innermost?.kind === "object" ? innermost : null;
|
|
150463
150596
|
const keys = directly?.keys ?? [];
|
|
150464
150597
|
const keyCount = keys.length;
|
|
150465
150598
|
return {
|
|
150466
150599
|
expectedType: expected,
|
|
150467
|
-
expectedTypeRef:
|
|
150468
|
-
expectedTypeName:
|
|
150600
|
+
expectedTypeRef: resolvedExpected,
|
|
150601
|
+
expectedTypeName: expectedTypeName ?? null,
|
|
150469
150602
|
enclosingTypeName: objects.at(-1)?.typeName ?? null,
|
|
150470
150603
|
initializerTypeName: directly?.typeName ?? null,
|
|
150471
150604
|
get initializerKeys() {
|
|
@@ -150581,8 +150714,20 @@ function indexConstructionSites(analysis, document, root) {
|
|
|
150581
150714
|
}
|
|
150582
150715
|
if (token.text === "(") {
|
|
150583
150716
|
if (sawNew) {
|
|
150717
|
+
const declaration = pendingNewTypeName ? findTypeDeclaration(analysis, pendingNewTypeName) : null;
|
|
150718
|
+
let constructorIndex = 0;
|
|
150719
|
+
if (declaration?.kind === "class" && declaration.constructors.length > 1) {
|
|
150720
|
+
const names = projectCallArguments(
|
|
150721
|
+
tokens,
|
|
150722
|
+
index,
|
|
150723
|
+
delimiterEnds ??= projectDelimiterEnds(tokens)
|
|
150724
|
+
).map((argument2) => argument2.name);
|
|
150725
|
+
const constructor2 = matchingDeclaredConstructor(declaration, names);
|
|
150726
|
+
constructorIndex = constructor2 ? declaration.constructors.indexOf(constructor2) : -1;
|
|
150727
|
+
}
|
|
150584
150728
|
stack.push({
|
|
150585
150729
|
kind: "call",
|
|
150730
|
+
constructorIndex,
|
|
150586
150731
|
typeName: pendingNewTypeName,
|
|
150587
150732
|
typeRef: pendingNewTypeRef,
|
|
150588
150733
|
argumentIndex: 0,
|
|
@@ -150669,6 +150814,14 @@ function constructorArgumentType(analysis, frame) {
|
|
|
150669
150814
|
if (!declaration || declaration.kind === "global" || declaration.kind === "enum") {
|
|
150670
150815
|
return null;
|
|
150671
150816
|
}
|
|
150817
|
+
if (declaration.kind === "class") {
|
|
150818
|
+
const parameters = declaration.headerParameters ?? declaration.constructors[frame.constructorIndex]?.parameters;
|
|
150819
|
+
if (parameters) {
|
|
150820
|
+
const parameter4 = frame.argumentName === null ? parameters[frame.argumentIndex] : neoScriptParameterByName(parameters, frame.argumentName);
|
|
150821
|
+
return parameter4?.type ?? null;
|
|
150822
|
+
}
|
|
150823
|
+
if (declaration.constructors.length > 0) return null;
|
|
150824
|
+
}
|
|
150672
150825
|
const fields = declarationFields(declaration);
|
|
150673
150826
|
if (frame.argumentName !== null) {
|
|
150674
150827
|
return fields.assignableByName.get(frame.argumentName)?.type ?? null;
|
|
@@ -150925,6 +151078,7 @@ var init_project_source_language_features = __esm({
|
|
|
150925
151078
|
init_project_listener_annotations();
|
|
150926
151079
|
init_strict_resolver();
|
|
150927
151080
|
init_type_substitution();
|
|
151081
|
+
init_declared_constructors();
|
|
150928
151082
|
init_executable_parser();
|
|
150929
151083
|
init_strict_compile_error();
|
|
150930
151084
|
init_analyzer();
|
|
@@ -190289,7 +190443,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
|
|
|
190289
190443
|
async function main() {
|
|
190290
190444
|
const args = parseArgs(process.argv.slice(2));
|
|
190291
190445
|
if (args.command === "--version") {
|
|
190292
|
-
console.log("0.72.
|
|
190446
|
+
console.log("0.72.2");
|
|
190293
190447
|
return;
|
|
190294
190448
|
}
|
|
190295
190449
|
if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {
|
package/dist/test-worker.mjs
CHANGED
|
@@ -38520,6 +38520,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
38520
38520
|
(candidate) => (candidate.kind === "function" || candidate.kind === "method") && candidate.name === callee.name
|
|
38521
38521
|
);
|
|
38522
38522
|
if (member) {
|
|
38523
|
+
this.validateFunctionReceiver(receiver, callee.name, optional2, pos);
|
|
38523
38524
|
if (type !== void 0) this.assertMemberAccessible(type, member, pos);
|
|
38524
38525
|
if (member.static === true) {
|
|
38525
38526
|
throw new CompileError(
|
|
@@ -39668,12 +39669,10 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
39668
39669
|
callableSignatureForReceiver(symbol, receiver) {
|
|
39669
39670
|
let parameters = symbol.parameters ?? [];
|
|
39670
39671
|
let returnType = symbol.returnType ?? symbol.type;
|
|
39671
|
-
if (this.context.projectSourceKind !== "spec" && !(receiver?.kind === "instance" && receiver.dispatch === "base")) {
|
|
39672
|
-
return { parameters, returnType };
|
|
39673
|
-
}
|
|
39674
39672
|
if (receiver?.kind !== "instance") return { parameters, returnType };
|
|
39675
39673
|
const receiverType = receiver.expression.type;
|
|
39676
39674
|
if (receiverType.kind !== "named") return { parameters, returnType };
|
|
39675
|
+
if (!receiverType.typeArguments?.length) return { parameters, returnType };
|
|
39677
39676
|
const declaring = this.project.typeById.get(receiverType.typeId);
|
|
39678
39677
|
if (declaring === void 0) return { parameters, returnType };
|
|
39679
39678
|
parameters = parameters.map((parameter3) => ({
|
|
@@ -40577,6 +40576,21 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
40577
40576
|
callSiteId: this.nextCallSite(expression.pos)
|
|
40578
40577
|
};
|
|
40579
40578
|
}
|
|
40579
|
+
validateFunctionReceiver(receiver, name, optional2, pos) {
|
|
40580
|
+
if (optional2 && !isNullable(receiver.type)) {
|
|
40581
|
+
throw new CompileError(
|
|
40582
|
+
`\`?.\` requires an optional receiver; got ${this.describe(receiver.type)}`,
|
|
40583
|
+
pos
|
|
40584
|
+
);
|
|
40585
|
+
}
|
|
40586
|
+
const receiverType = receiver.optionalChainType ?? receiver.type;
|
|
40587
|
+
if (!optional2 && isNullable(receiverType)) {
|
|
40588
|
+
throw new CompileError(
|
|
40589
|
+
`Function '${name}' is called on ${this.describe(receiverType)}, which may be null. Use optional chaining, force-unwrapping, or a null check before calling it.`,
|
|
40590
|
+
pos
|
|
40591
|
+
);
|
|
40592
|
+
}
|
|
40593
|
+
}
|
|
40580
40594
|
resolveFunctionStatement(expression, scope) {
|
|
40581
40595
|
if (expression.kind !== "call") return null;
|
|
40582
40596
|
const receiverValue = this.callReceiver(expression.callee, scope);
|
|
@@ -40740,12 +40754,19 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
40740
40754
|
}
|
|
40741
40755
|
}
|
|
40742
40756
|
const receiver = receiverValue();
|
|
40743
|
-
|
|
40744
|
-
|
|
40757
|
+
const memberReceiverType = neoScriptMemberLookupType(receiver.type);
|
|
40758
|
+
if (memberReceiverType.kind !== "named") return null;
|
|
40759
|
+
const type = this.project.typeById.get(memberReceiverType.typeId);
|
|
40745
40760
|
const symbol = type?.members.find(
|
|
40746
40761
|
(candidate) => (candidate.kind === "function" || candidate.kind === "method") && candidate.name === memberName
|
|
40747
40762
|
);
|
|
40748
40763
|
if (!symbol) return null;
|
|
40764
|
+
this.validateFunctionReceiver(
|
|
40765
|
+
receiver,
|
|
40766
|
+
memberName,
|
|
40767
|
+
expression.callee.optional === true,
|
|
40768
|
+
expression.pos
|
|
40769
|
+
);
|
|
40749
40770
|
if (type !== void 0) {
|
|
40750
40771
|
this.assertMemberAccessible(type, symbol, expression.pos);
|
|
40751
40772
|
}
|
|
@@ -40758,7 +40779,10 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
40758
40779
|
this.validateCallableInContext(symbol, expression.pos);
|
|
40759
40780
|
const resolved = this.resolveCallableArguments(
|
|
40760
40781
|
symbol,
|
|
40761
|
-
{
|
|
40782
|
+
{
|
|
40783
|
+
kind: "instance",
|
|
40784
|
+
expression: memberReceiverType === receiver.type ? receiver : { ...receiver, type: memberReceiverType }
|
|
40785
|
+
},
|
|
40762
40786
|
expression.args,
|
|
40763
40787
|
scope,
|
|
40764
40788
|
expression.pos
|
|
@@ -54634,7 +54658,7 @@ var SPECIALIZED_RELATION_KINDS = /* @__PURE__ */ new Set([
|
|
|
54634
54658
|
|
|
54635
54659
|
// ../packages/manifest/schema-contract/registry.mjs
|
|
54636
54660
|
var PROJECT_SCHEMA_CONTRACT = Object.freeze({
|
|
54637
|
-
cliVersion: "0.72.
|
|
54661
|
+
cliVersion: "0.72.2",
|
|
54638
54662
|
projectFileUploadBatchSize: 32,
|
|
54639
54663
|
documentRecords: {
|
|
54640
54664
|
member: {
|
package/package.json
CHANGED
|
@@ -118,7 +118,7 @@ wrappers.
|
|
|
118
118
|
The marker near the top of `SKILL.md` must exactly match the package version:
|
|
119
119
|
|
|
120
120
|
```html
|
|
121
|
-
<!-- reviewed-through-cli: 0.72.
|
|
121
|
+
<!-- reviewed-through-cli: 0.72.2 -->
|
|
122
122
|
```
|
|
123
123
|
|
|
124
124
|
The quoted version above is checked too, so this instruction cannot go stale
|
|
@@ -176,7 +176,13 @@ indexes only on the original List member. Overrides inherit its indexes, and
|
|
|
176
176
|
List getter.
|
|
177
177
|
|
|
178
178
|
Use `.EnumCase` only when context fixes one enum type; otherwise write
|
|
179
|
-
`EnumType.Case`.
|
|
179
|
+
`EnumType.Case`. Constructor parameters supply this context for positional
|
|
180
|
+
and named arguments, including substituted generic parameter types. Defaults
|
|
181
|
+
and settings must be statically analyzable.
|
|
182
|
+
|
|
183
|
+
An explicit construction must be assignable to its receiving type. For example,
|
|
184
|
+
`List<Base>` accepts `new Derived()` when `Derived` inherits `Base`, but rejects
|
|
185
|
+
an unrelated class at `new`. Generic arguments must also be compatible.
|
|
180
186
|
|
|
181
187
|
## Member and relation rules
|
|
182
188
|
|
|
@@ -99,6 +99,10 @@ this.Items.Insert(0, item);
|
|
|
99
99
|
this.Items.Remove(item);
|
|
100
100
|
```
|
|
101
101
|
|
|
102
|
+
A generic receiver may call methods from its class or interface constraint,
|
|
103
|
+
including void calls used as statements. Generic arguments substitute through
|
|
104
|
+
the constraint; nullable receivers still require narrowing or null handling.
|
|
105
|
+
|
|
102
106
|
Prefer `--json` for automation.
|
|
103
107
|
|
|
104
108
|
`neo script check --all` reconstructs the prospective project entirely from
|
|
@@ -84,6 +84,9 @@ This names the initializer row. It does not create a stored global. The inline
|
|
|
84
84
|
`Quest HardAsStone = @id("...") new Quest();` spelling is also accepted, and
|
|
85
85
|
formatting moves its ID above the declaration. Do not put an ID in both places.
|
|
86
86
|
|
|
87
|
+
A local initializer such as `Delivery DeliveryRow = new()` retains `Delivery`
|
|
88
|
+
when consumed by a base-class member. Aliases retain that same concrete type.
|
|
89
|
+
|
|
87
90
|
Nested class/list rows remain independently addressable and keep inline IDs:
|
|
88
91
|
|
|
89
92
|
```neo
|