@neocompose/cli 0.31.3 → 0.31.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.31.5] - 2026-08-15
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- Resolve callable members through generic class and interface constraints, so
|
|
8
|
+
an open generic value can call guaranteed APIs such as `Class.Clone()`.
|
|
9
|
+
|
|
10
|
+
## [0.31.4] - 2026-08-14
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Preserve generic class constraints while compiling project-source bodies, so
|
|
15
|
+
an open generic member such as `TStackData extends InventoryStackData` can
|
|
16
|
+
be assigned to its declared base type in an `init` block.
|
|
17
|
+
|
|
3
18
|
## [0.31.3] - 2026-08-14
|
|
4
19
|
|
|
5
20
|
### Added
|
package/dist/neo.mjs
CHANGED
|
@@ -1832,6 +1832,21 @@ var init_generated_csharp_identifiers = __esm({
|
|
|
1832
1832
|
});
|
|
1833
1833
|
|
|
1834
1834
|
// ../packages/neoscript-language/src/project.ts
|
|
1835
|
+
function neoScriptMemberLookupType(type) {
|
|
1836
|
+
if (type.kind !== "typeParameter") return type;
|
|
1837
|
+
const visited = /* @__PURE__ */ new Set();
|
|
1838
|
+
let current = type;
|
|
1839
|
+
let nullable = type.nullable === true;
|
|
1840
|
+
while (current.kind === "typeParameter") {
|
|
1841
|
+
if (visited.has(current.id) || current.constraint === void 0) {
|
|
1842
|
+
return type;
|
|
1843
|
+
}
|
|
1844
|
+
visited.add(current.id);
|
|
1845
|
+
nullable ||= current.constraint.nullable === true;
|
|
1846
|
+
current = current.constraint;
|
|
1847
|
+
}
|
|
1848
|
+
return nullable && current.nullable !== true ? { ...current, nullable: true } : current;
|
|
1849
|
+
}
|
|
1835
1850
|
function neoScriptParameterIsOmittable(parameter4) {
|
|
1836
1851
|
return parameter4.defaultValue !== void 0;
|
|
1837
1852
|
}
|
|
@@ -3160,7 +3175,8 @@ function completionItemsForResolution(snapshot, resolved, word) {
|
|
|
3160
3175
|
(member) => member.static === true && isMemberCompletionAccessible(snapshot, staticType, member)
|
|
3161
3176
|
).map((member) => symbolCompletion(member, word, snapshot));
|
|
3162
3177
|
}
|
|
3163
|
-
const
|
|
3178
|
+
const memberType2 = neoScriptMemberLookupType(resolved.type);
|
|
3179
|
+
const owner = memberType2.kind === "named" ? snapshot.project.typeById.get(memberType2.typeId) : void 0;
|
|
3164
3180
|
return membersForType(snapshot, resolved.type).filter(
|
|
3165
3181
|
(symbol) => owner === void 0 || isMemberCompletionAccessible(snapshot, owner, symbol)
|
|
3166
3182
|
).map((symbol) => symbolCompletion(symbol, word, snapshot));
|
|
@@ -3174,6 +3190,17 @@ function isMemberCompletionAccessible(snapshot, owner, symbol) {
|
|
|
3174
3190
|
}) === null;
|
|
3175
3191
|
}
|
|
3176
3192
|
function membersForType(snapshot, type) {
|
|
3193
|
+
const memberType2 = neoScriptMemberLookupType(type);
|
|
3194
|
+
if (memberType2 !== type) {
|
|
3195
|
+
const members = [...membersForType(snapshot, memberType2)];
|
|
3196
|
+
if (type.kind !== "typeParameter" || type.nullable === true) return members;
|
|
3197
|
+
const named = memberType2.kind === "named" ? snapshot.project.typeById.get(memberType2.typeId) : void 0;
|
|
3198
|
+
if (named?.kind !== "class") return members;
|
|
3199
|
+
const cloneId = `builtin:${named.id}:Clone`;
|
|
3200
|
+
return members.map(
|
|
3201
|
+
(member) => member.id === cloneId ? cloneSymbol(named, type) : member
|
|
3202
|
+
);
|
|
3203
|
+
}
|
|
3177
3204
|
if (type.kind === "named") {
|
|
3178
3205
|
const named = snapshot.project.typeById.get(type.typeId);
|
|
3179
3206
|
if (!named) return [];
|
|
@@ -3950,13 +3977,13 @@ function stringContainsSymbol() {
|
|
|
3950
3977
|
"Returns true when the string contains the substring."
|
|
3951
3978
|
);
|
|
3952
3979
|
}
|
|
3953
|
-
function cloneSymbol(type) {
|
|
3980
|
+
function cloneSymbol(type, returnType = { kind: "named", typeId: type.id }) {
|
|
3954
3981
|
return {
|
|
3955
3982
|
id: `builtin:${type.id}:Clone`,
|
|
3956
3983
|
name: "Clone",
|
|
3957
3984
|
kind: "method",
|
|
3958
|
-
type:
|
|
3959
|
-
returnType
|
|
3985
|
+
type: returnType,
|
|
3986
|
+
returnType,
|
|
3960
3987
|
parameters: [],
|
|
3961
3988
|
documentation: `Deep-copy this ${type.name} into a new parentless writable value.`
|
|
3962
3989
|
};
|
|
@@ -11871,11 +11898,12 @@ var init_strict_resolver = __esm({
|
|
|
11871
11898
|
pos
|
|
11872
11899
|
);
|
|
11873
11900
|
}
|
|
11874
|
-
|
|
11875
|
-
|
|
11901
|
+
const memberReceiverType = neoScriptMemberLookupType(receiver.type);
|
|
11902
|
+
if (memberReceiverType.kind === "named") {
|
|
11903
|
+
const type = this.project.typeById.get(memberReceiverType.typeId);
|
|
11876
11904
|
if (!type) {
|
|
11877
11905
|
throw new CompileError(
|
|
11878
|
-
`Type ${
|
|
11906
|
+
`Type ${memberReceiverType.typeId} was not found in the project.`,
|
|
11879
11907
|
pos
|
|
11880
11908
|
);
|
|
11881
11909
|
}
|
|
@@ -11909,7 +11937,7 @@ var init_strict_resolver = __esm({
|
|
|
11909
11937
|
}
|
|
11910
11938
|
const memberType2 = substituteTypeParameters(
|
|
11911
11939
|
member.type,
|
|
11912
|
-
|
|
11940
|
+
memberReceiverType,
|
|
11913
11941
|
type
|
|
11914
11942
|
);
|
|
11915
11943
|
if (member.computed === true) {
|
|
@@ -12350,8 +12378,9 @@ var init_strict_resolver = __esm({
|
|
|
12350
12378
|
pos
|
|
12351
12379
|
);
|
|
12352
12380
|
}
|
|
12353
|
-
|
|
12354
|
-
|
|
12381
|
+
const memberReceiverType = neoScriptMemberLookupType(receiver.type);
|
|
12382
|
+
if (memberReceiverType.kind === "named") {
|
|
12383
|
+
const type = this.project.typeById.get(memberReceiverType.typeId);
|
|
12355
12384
|
const member = type?.members.find(
|
|
12356
12385
|
(candidate) => (candidate.kind === "function" || candidate.kind === "method") && candidate.name === callee.name
|
|
12357
12386
|
);
|
|
@@ -12365,7 +12394,10 @@ var init_strict_resolver = __esm({
|
|
|
12365
12394
|
}
|
|
12366
12395
|
return this.resolveSymbolCall(
|
|
12367
12396
|
member,
|
|
12368
|
-
{
|
|
12397
|
+
{
|
|
12398
|
+
kind: "instance",
|
|
12399
|
+
expression: memberReceiverType === receiver.type ? receiver : { ...receiver, type: memberReceiverType }
|
|
12400
|
+
},
|
|
12369
12401
|
argumentsList2,
|
|
12370
12402
|
scope,
|
|
12371
12403
|
pos,
|
|
@@ -12385,7 +12417,7 @@ var init_strict_resolver = __esm({
|
|
|
12385
12417
|
pos
|
|
12386
12418
|
);
|
|
12387
12419
|
}
|
|
12388
|
-
const schemaClass2 = toWireType(
|
|
12420
|
+
const schemaClass2 = toWireType(memberReceiverType, this.project);
|
|
12389
12421
|
return {
|
|
12390
12422
|
pointer: {
|
|
12391
12423
|
type: "function" /* Function */,
|
|
@@ -14815,7 +14847,7 @@ function applyDelimiterToken(stack, token, lambdaBraceOffsets) {
|
|
|
14815
14847
|
if (token.text === "{" && lambdaBraceOffsets.has(token.start)) {
|
|
14816
14848
|
for (let index = stack.length - 1; index >= 0; index--) {
|
|
14817
14849
|
const candidate = stack[index];
|
|
14818
|
-
if (candidate?.text === "(" && candidate.contributes) {
|
|
14850
|
+
if (candidate?.text === "(" && candidate.contributes && candidate.openingLine === token.range.start.line) {
|
|
14819
14851
|
restores = candidate;
|
|
14820
14852
|
break;
|
|
14821
14853
|
}
|
|
@@ -14824,6 +14856,7 @@ function applyDelimiterToken(stack, token, lambdaBraceOffsets) {
|
|
|
14824
14856
|
}
|
|
14825
14857
|
stack.push({
|
|
14826
14858
|
text: token.text,
|
|
14859
|
+
openingLine: token.range.start.line,
|
|
14827
14860
|
contributes: true,
|
|
14828
14861
|
...restores ? { restores } : {}
|
|
14829
14862
|
});
|
|
@@ -14847,6 +14880,7 @@ function delimiterDepth(stack) {
|
|
|
14847
14880
|
function cloneDelimiterStack(stack) {
|
|
14848
14881
|
const clones = stack.map((frame) => ({
|
|
14849
14882
|
text: frame.text,
|
|
14883
|
+
openingLine: frame.openingLine,
|
|
14850
14884
|
contributes: frame.contributes
|
|
14851
14885
|
}));
|
|
14852
14886
|
for (let index = 0; index < stack.length; index++) {
|
|
@@ -23605,7 +23639,11 @@ function compileProjectSourceBodies(documents) {
|
|
|
23605
23639
|
if (declaration.kind !== "class") continue;
|
|
23606
23640
|
const owner = graph.declarationsByName.get(declaration.name);
|
|
23607
23641
|
if (!owner) continue;
|
|
23608
|
-
const declaringType = declarationTypeRef(
|
|
23642
|
+
const declaringType = declarationTypeRef(
|
|
23643
|
+
owner,
|
|
23644
|
+
declaration,
|
|
23645
|
+
graph.typeIdsByName
|
|
23646
|
+
);
|
|
23609
23647
|
diagnostics.push(
|
|
23610
23648
|
...declaredConstructorOverloadDiagnostics(
|
|
23611
23649
|
uri,
|
|
@@ -23921,16 +23959,22 @@ function buildProjectGraph(documents) {
|
|
|
23921
23959
|
const target = declarationsByName.get(base.name);
|
|
23922
23960
|
return target?.declaration.kind === "interface" ? [target.id] : [];
|
|
23923
23961
|
}) : [];
|
|
23924
|
-
const typeParameters = classDeclaration ? classDeclaration.genericParameters.map((parameter4) =>
|
|
23925
|
-
|
|
23926
|
-
parameter4
|
|
23927
|
-
|
|
23928
|
-
|
|
23929
|
-
|
|
23930
|
-
|
|
23931
|
-
|
|
23932
|
-
|
|
23933
|
-
|
|
23962
|
+
const typeParameters = classDeclaration ? classDeclaration.genericParameters.map((parameter4) => {
|
|
23963
|
+
const type = sourceTypeParameterRef(
|
|
23964
|
+
parameter4,
|
|
23965
|
+
info,
|
|
23966
|
+
typeIds,
|
|
23967
|
+
/* @__PURE__ */ new Set(),
|
|
23968
|
+
false
|
|
23969
|
+
);
|
|
23970
|
+
return {
|
|
23971
|
+
id: type.id,
|
|
23972
|
+
name: parameter4.name,
|
|
23973
|
+
type,
|
|
23974
|
+
location: location(info.uri, parameter4.range),
|
|
23975
|
+
selectionLocation: location(info.uri, parameter4.nameRange)
|
|
23976
|
+
};
|
|
23977
|
+
}) : [];
|
|
23934
23978
|
return {
|
|
23935
23979
|
id: info.id,
|
|
23936
23980
|
name: info.declaration.name,
|
|
@@ -24268,50 +24312,49 @@ function projectRootType(documents, declarations) {
|
|
|
24268
24312
|
}
|
|
24269
24313
|
return { id: "builtin:Root", name: "Root", kind: "synthetic", members };
|
|
24270
24314
|
}
|
|
24271
|
-
function sourceTypeRef(type, owner, typeIds) {
|
|
24315
|
+
function sourceTypeRef(type, owner, typeIds, resolvingTypeParameters = /* @__PURE__ */ new Set()) {
|
|
24272
24316
|
const nullable = type.nullable || void 0;
|
|
24317
|
+
const resolveNested = (nested) => sourceTypeRef(nested, owner, typeIds, resolvingTypeParameters);
|
|
24273
24318
|
if (type.name === "List") {
|
|
24274
24319
|
return {
|
|
24275
24320
|
kind: "list",
|
|
24276
|
-
elementType: type.typeArguments[0] ?
|
|
24321
|
+
elementType: type.typeArguments[0] ? resolveNested(type.typeArguments[0]) : { kind: "primitive", name: "unknown" },
|
|
24277
24322
|
...nullable ? { nullable } : {}
|
|
24278
24323
|
};
|
|
24279
24324
|
}
|
|
24280
24325
|
if (type.name === "Set") {
|
|
24281
24326
|
return {
|
|
24282
24327
|
kind: "set",
|
|
24283
|
-
elementType: type.typeArguments[0] ?
|
|
24328
|
+
elementType: type.typeArguments[0] ? resolveNested(type.typeArguments[0]) : { kind: "primitive", name: "unknown" },
|
|
24284
24329
|
...nullable ? { nullable } : {}
|
|
24285
24330
|
};
|
|
24286
24331
|
}
|
|
24287
24332
|
if (type.name === "Dictionary") {
|
|
24288
24333
|
return {
|
|
24289
24334
|
kind: "dictionary",
|
|
24290
|
-
keyType: type.typeArguments[0] ?
|
|
24291
|
-
valueType: type.typeArguments[1] ?
|
|
24335
|
+
keyType: type.typeArguments[0] ? resolveNested(type.typeArguments[0]) : { kind: "primitive", name: "unknown" },
|
|
24336
|
+
valueType: type.typeArguments[1] ? resolveNested(type.typeArguments[1]) : { kind: "primitive", name: "unknown" },
|
|
24292
24337
|
...nullable ? { nullable } : {}
|
|
24293
24338
|
};
|
|
24294
24339
|
}
|
|
24295
24340
|
if (type.name === "NeoDelegate") {
|
|
24296
|
-
const returnType = type.typeArguments[0] ?
|
|
24341
|
+
const returnType = type.typeArguments[0] ? resolveNested(type.typeArguments[0]) : { kind: "primitive", name: "unknown" };
|
|
24297
24342
|
return {
|
|
24298
24343
|
kind: "delegate",
|
|
24299
24344
|
returnType,
|
|
24300
|
-
parameterTypes: type.typeArguments.slice(1).map(
|
|
24345
|
+
parameterTypes: type.typeArguments.slice(1).map(resolveNested),
|
|
24301
24346
|
...nullable ? { nullable } : {}
|
|
24302
24347
|
};
|
|
24303
24348
|
}
|
|
24304
24349
|
if (type.name === "NeoAction") {
|
|
24305
24350
|
return {
|
|
24306
24351
|
kind: "action",
|
|
24307
|
-
parameterTypes: type.typeArguments.map(
|
|
24308
|
-
(argument2) => sourceTypeRef(argument2, owner, typeIds)
|
|
24309
|
-
)
|
|
24352
|
+
parameterTypes: type.typeArguments.map(resolveNested)
|
|
24310
24353
|
};
|
|
24311
24354
|
}
|
|
24312
24355
|
if (type.name === "Reference" && type.typeArguments[0]) {
|
|
24313
24356
|
return {
|
|
24314
|
-
...
|
|
24357
|
+
...resolveNested(type.typeArguments[0]),
|
|
24315
24358
|
...nullable ? { nullable } : {}
|
|
24316
24359
|
};
|
|
24317
24360
|
}
|
|
@@ -24320,16 +24363,13 @@ function sourceTypeRef(type, owner, typeIds) {
|
|
|
24320
24363
|
(candidate) => candidate.name === type.name
|
|
24321
24364
|
);
|
|
24322
24365
|
if (parameter4) {
|
|
24323
|
-
return
|
|
24324
|
-
|
|
24325
|
-
|
|
24326
|
-
|
|
24327
|
-
|
|
24328
|
-
|
|
24329
|
-
|
|
24330
|
-
ownerClassId: owner.id,
|
|
24331
|
-
...nullable ? { nullable } : {}
|
|
24332
|
-
};
|
|
24366
|
+
return sourceTypeParameterRef(
|
|
24367
|
+
parameter4,
|
|
24368
|
+
owner,
|
|
24369
|
+
typeIds,
|
|
24370
|
+
resolvingTypeParameters,
|
|
24371
|
+
nullable === true
|
|
24372
|
+
);
|
|
24333
24373
|
}
|
|
24334
24374
|
}
|
|
24335
24375
|
const primitive3 = primitiveTypeName(type.name);
|
|
@@ -24345,27 +24385,37 @@ function sourceTypeRef(type, owner, typeIds) {
|
|
|
24345
24385
|
kind: "named",
|
|
24346
24386
|
typeId: targetId ?? `builtin:${type.name}`,
|
|
24347
24387
|
...type.typeArguments.length ? {
|
|
24348
|
-
typeArguments: type.typeArguments.map(
|
|
24349
|
-
(argument2) => sourceTypeRef(argument2, owner, typeIds)
|
|
24350
|
-
)
|
|
24388
|
+
typeArguments: type.typeArguments.map(resolveNested)
|
|
24351
24389
|
} : {},
|
|
24352
24390
|
...nullable ? { nullable } : {}
|
|
24353
24391
|
};
|
|
24354
24392
|
}
|
|
24355
|
-
function
|
|
24393
|
+
function sourceTypeParameterRef(parameter4, owner, typeIds, resolvingTypeParameters, nullable) {
|
|
24394
|
+
const id2 = sourceIdentity(
|
|
24395
|
+
parameter4.annotations,
|
|
24396
|
+
`generic:${owner.id}:${parameter4.name}`
|
|
24397
|
+
);
|
|
24398
|
+
const next = new Set(resolvingTypeParameters);
|
|
24399
|
+
next.add(id2);
|
|
24400
|
+
const constraintSource = parameter4.constraint;
|
|
24401
|
+
const constraint = constraintSource !== void 0 && !resolvingTypeParameters.has(id2) ? sourceTypeRef(constraintSource, owner, typeIds, next) : void 0;
|
|
24402
|
+
return {
|
|
24403
|
+
kind: "typeParameter",
|
|
24404
|
+
id: id2,
|
|
24405
|
+
name: parameter4.name,
|
|
24406
|
+
ownerClassId: owner.id,
|
|
24407
|
+
...constraint === void 0 ? {} : { constraint },
|
|
24408
|
+
...nullable ? { nullable: true } : {}
|
|
24409
|
+
};
|
|
24410
|
+
}
|
|
24411
|
+
function declarationTypeRef(info, declaration, typeIds) {
|
|
24356
24412
|
return {
|
|
24357
24413
|
kind: "named",
|
|
24358
24414
|
typeId: info.id,
|
|
24359
24415
|
...declaration.genericParameters.length ? {
|
|
24360
|
-
typeArguments: declaration.genericParameters.map(
|
|
24361
|
-
|
|
24362
|
-
|
|
24363
|
-
parameter4.annotations,
|
|
24364
|
-
`generic:${info.id}:${parameter4.name}`
|
|
24365
|
-
),
|
|
24366
|
-
name: parameter4.name,
|
|
24367
|
-
ownerClassId: info.id
|
|
24368
|
-
}))
|
|
24416
|
+
typeArguments: declaration.genericParameters.map(
|
|
24417
|
+
(parameter4) => sourceTypeParameterRef(parameter4, info, typeIds, /* @__PURE__ */ new Set(), false)
|
|
24418
|
+
)
|
|
24369
24419
|
} : {}
|
|
24370
24420
|
};
|
|
24371
24421
|
}
|
|
@@ -110633,7 +110683,7 @@ var init_registry2 = __esm({
|
|
|
110633
110683
|
PROJECT_SCHEMA_CONTRACT = Object.freeze({
|
|
110634
110684
|
formatVersion: 3,
|
|
110635
110685
|
contractVersion: "3.12",
|
|
110636
|
-
cliVersion: "0.31.
|
|
110686
|
+
cliVersion: "0.31.5",
|
|
110637
110687
|
projectFileUploadBatchSize: 32,
|
|
110638
110688
|
documentRecords: {
|
|
110639
110689
|
member: {
|
|
@@ -117228,7 +117278,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
|
|
|
117228
117278
|
async function main() {
|
|
117229
117279
|
const args = parseArgs(process.argv.slice(2));
|
|
117230
117280
|
if (args.command === "--version") {
|
|
117231
|
-
console.log("0.31.
|
|
117281
|
+
console.log("0.31.5");
|
|
117232
117282
|
return;
|
|
117233
117283
|
}
|
|
117234
117284
|
if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {
|
package/package.json
CHANGED
|
@@ -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.31.
|
|
86
|
+
<!-- reviewed-through-cli: 0.31.5 -->
|
|
87
87
|
```
|
|
88
88
|
|
|
89
89
|
The quoted version above is checked too, so this instruction cannot go stale
|