@neocompose/cli 0.62.0 → 0.62.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 +12 -0
- package/README.md +17 -3
- package/dist/neo.mjs +718 -160
- package/dist/test-worker.mjs +48502 -0
- 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/commands-and-sync.md +14 -0
- package/skills/neocompose-cli/references/declarations-and-construction.md +5 -0
- package/skills/neocompose-cli/references/values-identities-and-references.md +3 -1
package/dist/neo.mjs
CHANGED
|
@@ -19576,6 +19576,56 @@ var init_project_source_registry = __esm({
|
|
|
19576
19576
|
}
|
|
19577
19577
|
});
|
|
19578
19578
|
|
|
19579
|
+
// ../packages/neoscript-language/src/reference-argument.ts
|
|
19580
|
+
function parseReferenceArgument(raw) {
|
|
19581
|
+
let expression;
|
|
19582
|
+
try {
|
|
19583
|
+
expression = typeof raw === "string" ? parseExpression(raw) : raw;
|
|
19584
|
+
} catch {
|
|
19585
|
+
return null;
|
|
19586
|
+
}
|
|
19587
|
+
if (expression.kind === "litNull") return { kind: "none" };
|
|
19588
|
+
if (expression.kind === "call") {
|
|
19589
|
+
if (expression.callee.kind !== "ident" || expression.callee.name !== "Reference")
|
|
19590
|
+
return null;
|
|
19591
|
+
const idIndex = expression.argumentNames?.indexOf("id") ?? -1;
|
|
19592
|
+
const index = idIndex < 0 ? 0 : idIndex;
|
|
19593
|
+
if (expression.args.length < 1 || expression.args.length > 2) return null;
|
|
19594
|
+
for (let i2 = 0; i2 < expression.args.length; i2++) {
|
|
19595
|
+
const name = expression.argumentNames?.[i2];
|
|
19596
|
+
if (i2 === index) {
|
|
19597
|
+
if (name != null && name !== "id") return null;
|
|
19598
|
+
} else if (name !== "withProvenance" || expression.args[i2]?.kind !== "litBool")
|
|
19599
|
+
return null;
|
|
19600
|
+
}
|
|
19601
|
+
expression = expression.args[index];
|
|
19602
|
+
if (expression.kind === "litString") {
|
|
19603
|
+
return expression.value.length === 0 ? null : { kind: "id", value: expression.value };
|
|
19604
|
+
}
|
|
19605
|
+
}
|
|
19606
|
+
const segments = [];
|
|
19607
|
+
while (expression.kind === "member") {
|
|
19608
|
+
segments.push(expression.name);
|
|
19609
|
+
expression = expression.receiver;
|
|
19610
|
+
}
|
|
19611
|
+
if (expression.kind !== "ident" || expression.name !== "root" || segments.length === 0)
|
|
19612
|
+
return null;
|
|
19613
|
+
return { kind: "rootPath", value: ["root", ...segments.reverse()].join(".") };
|
|
19614
|
+
}
|
|
19615
|
+
function referenceArgumentRequirement(name) {
|
|
19616
|
+
if (name === "collectionValue")
|
|
19617
|
+
return '@settings collectionValue requires Reference("id") or a root path such as root.Assets.Collection.';
|
|
19618
|
+
if (name === "template")
|
|
19619
|
+
return '@settings template requires Reference("id") or a template symbol.';
|
|
19620
|
+
return `@settings ${name} requires Reference("id").`;
|
|
19621
|
+
}
|
|
19622
|
+
var init_reference_argument = __esm({
|
|
19623
|
+
"../packages/neoscript-language/src/reference-argument.ts"() {
|
|
19624
|
+
"use strict";
|
|
19625
|
+
init_executable_parser();
|
|
19626
|
+
}
|
|
19627
|
+
});
|
|
19628
|
+
|
|
19579
19629
|
// ../packages/neoscript-language/src/project-schema-contract.generated.ts
|
|
19580
19630
|
var PROJECT_FILE_UPLOAD_BATCH_SIZE, NEO_PROJECT_SOURCE_RECORD_CONTRACT;
|
|
19581
19631
|
var init_project_schema_contract_generated = __esm({
|
|
@@ -24151,6 +24201,22 @@ function validateAnnotations(uri, annotations, context, environment, diagnostics
|
|
|
24151
24201
|
if (field.name === "member" && (annotation2.name === "index" || annotation2.name === "column")) {
|
|
24152
24202
|
continue;
|
|
24153
24203
|
}
|
|
24204
|
+
if (annotation2.name === "settings" && (field.name === "collectionValue" || field.name === "group" || field.name === "template")) {
|
|
24205
|
+
const reference2 = parseReferenceArgument(argument2.text);
|
|
24206
|
+
if (reference2?.kind === "none" || reference2?.kind === "id" || reference2?.kind === "rootPath" && field.name === "collectionValue")
|
|
24207
|
+
continue;
|
|
24208
|
+
const templateSymbol = field.name === "template" && /^[A-Za-z_][A-Za-z0-9_]*$/.test(argument2.text.trim());
|
|
24209
|
+
if (!templateSymbol) {
|
|
24210
|
+
pushDiagnostic(
|
|
24211
|
+
diagnostics,
|
|
24212
|
+
uri,
|
|
24213
|
+
argument2.range,
|
|
24214
|
+
"invalid-reference-argument",
|
|
24215
|
+
referenceArgumentRequirement(field.name)
|
|
24216
|
+
);
|
|
24217
|
+
continue;
|
|
24218
|
+
}
|
|
24219
|
+
}
|
|
24154
24220
|
validateExpressionText(
|
|
24155
24221
|
uri,
|
|
24156
24222
|
argument2.text,
|
|
@@ -25967,6 +26033,7 @@ var NEO_VARIANT_FOLDER_SETTING, primitiveType, LIST_COLUMN_INHERITANCE_KEY, SEMA
|
|
|
25967
26033
|
var init_project_source_semantics = __esm({
|
|
25968
26034
|
"../packages/neoscript-language/src/project-source-semantics.ts"() {
|
|
25969
26035
|
"use strict";
|
|
26036
|
+
init_reference_argument();
|
|
25970
26037
|
init_project_source_ast();
|
|
25971
26038
|
init_project_local_values();
|
|
25972
26039
|
init_language_spec();
|
|
@@ -35618,8 +35685,8 @@ var init_spelling_diagnostics = __esm({
|
|
|
35618
35685
|
});
|
|
35619
35686
|
|
|
35620
35687
|
// ../packages/neoscript-language/src/service.ts
|
|
35621
|
-
function createNeoScriptLanguageService() {
|
|
35622
|
-
return new LanguageService();
|
|
35688
|
+
function createNeoScriptLanguageService(options = {}) {
|
|
35689
|
+
return new LanguageService(options);
|
|
35623
35690
|
}
|
|
35624
35691
|
function isProjectDocument(document, context) {
|
|
35625
35692
|
return context?.projectSourceKind !== "spec" && (document.languageId === "neo" || document.languageId === "neoflow");
|
|
@@ -35730,6 +35797,11 @@ var init_service = __esm({
|
|
|
35730
35797
|
init_syntax();
|
|
35731
35798
|
init_test_prelude();
|
|
35732
35799
|
LanguageService = class {
|
|
35800
|
+
constructor(options) {
|
|
35801
|
+
this.options = options;
|
|
35802
|
+
}
|
|
35803
|
+
options;
|
|
35804
|
+
cachedSourceValidation;
|
|
35733
35805
|
documents = /* @__PURE__ */ new Map();
|
|
35734
35806
|
specSnapshots = /* @__PURE__ */ new Set();
|
|
35735
35807
|
projectGeneration = 0;
|
|
@@ -35845,10 +35917,18 @@ var init_service = __esm({
|
|
|
35845
35917
|
if (signal?.aborted) return [];
|
|
35846
35918
|
const generation = ++state.validationGeneration;
|
|
35847
35919
|
if (isProjectDocument(state.document, state.context)) {
|
|
35848
|
-
const
|
|
35849
|
-
|
|
35850
|
-
|
|
35851
|
-
);
|
|
35920
|
+
const projectGeneration = this.projectGeneration;
|
|
35921
|
+
const project = this.projectAnalysis();
|
|
35922
|
+
const extended = await this.validateProjectSources();
|
|
35923
|
+
if (projectGeneration !== this.projectGeneration) return [];
|
|
35924
|
+
const diagnostics = this.enhanceDiagnostics(state, [
|
|
35925
|
+
...projectDiagnostics(project, uri),
|
|
35926
|
+
...extended.filter(
|
|
35927
|
+
(diagnostic) => diagnostic.uri === uri && !project.diagnostics.some(
|
|
35928
|
+
(existing) => existing.uri === uri && existing.code === diagnostic.code && existing.message === diagnostic.message && existing.range.start.line === diagnostic.range.start.line && existing.range.start.character === diagnostic.range.start.character
|
|
35929
|
+
)
|
|
35930
|
+
)
|
|
35931
|
+
]);
|
|
35852
35932
|
if (signal?.aborted) return [];
|
|
35853
35933
|
const current2 = this.documents.get(uri);
|
|
35854
35934
|
if (!current2 || current2.validationGeneration !== generation) return [];
|
|
@@ -36051,6 +36131,31 @@ var init_service = __esm({
|
|
|
36051
36131
|
)
|
|
36052
36132
|
);
|
|
36053
36133
|
}
|
|
36134
|
+
validateProjectSources() {
|
|
36135
|
+
const validate3 = this.options.validateProjectSources;
|
|
36136
|
+
if (validate3 === void 0) return Promise.resolve([]);
|
|
36137
|
+
if (this.cachedSourceValidation?.generation === this.projectGeneration)
|
|
36138
|
+
return this.cachedSourceValidation.result;
|
|
36139
|
+
const inputs = [...this.documents.values()].flatMap(
|
|
36140
|
+
({ document, context }) => isProjectDocument(document, context) ? [
|
|
36141
|
+
{
|
|
36142
|
+
uri: document.uri,
|
|
36143
|
+
text: document.text,
|
|
36144
|
+
kind: document.languageId === "neoflow" ? "flow" : context.kind === "migration" ? "migration" : "definition"
|
|
36145
|
+
}
|
|
36146
|
+
] : []
|
|
36147
|
+
);
|
|
36148
|
+
const result = validate3(inputs).catch((error) => {
|
|
36149
|
+
if (this.cachedSourceValidation?.result === result)
|
|
36150
|
+
this.cachedSourceValidation = void 0;
|
|
36151
|
+
throw error;
|
|
36152
|
+
});
|
|
36153
|
+
this.cachedSourceValidation = {
|
|
36154
|
+
generation: this.projectGeneration,
|
|
36155
|
+
result
|
|
36156
|
+
};
|
|
36157
|
+
return result;
|
|
36158
|
+
}
|
|
36054
36159
|
projectAnalysis() {
|
|
36055
36160
|
if (this.cachedProjectAnalysis?.generation === this.projectGeneration) {
|
|
36056
36161
|
return this.cachedProjectAnalysis.analysis;
|
|
@@ -36437,6 +36542,7 @@ var init_src = __esm({
|
|
|
36437
36542
|
init_project_local_value_refactorings();
|
|
36438
36543
|
init_cell_pattern();
|
|
36439
36544
|
init_tile_conversion();
|
|
36545
|
+
init_reference_argument();
|
|
36440
36546
|
}
|
|
36441
36547
|
});
|
|
36442
36548
|
|
|
@@ -38016,6 +38122,7 @@ var init_args = __esm({
|
|
|
38016
38122
|
"generate-ids",
|
|
38017
38123
|
"help",
|
|
38018
38124
|
"passWithNoTests",
|
|
38125
|
+
"runInBand",
|
|
38019
38126
|
"no-verify",
|
|
38020
38127
|
"fix",
|
|
38021
38128
|
"yes"
|
|
@@ -38067,9 +38174,11 @@ var init_args = __esm({
|
|
|
38067
38174
|
"outputFile",
|
|
38068
38175
|
"output-file",
|
|
38069
38176
|
"testNamePattern",
|
|
38177
|
+
"maxWorkers",
|
|
38070
38178
|
"test-timeout",
|
|
38071
38179
|
"testTimeout",
|
|
38072
38180
|
"passWithNoTests",
|
|
38181
|
+
"runInBand",
|
|
38073
38182
|
"no-verify"
|
|
38074
38183
|
]);
|
|
38075
38184
|
TEST_ONLY_FLAGS = /* @__PURE__ */ new Set([
|
|
@@ -38077,9 +38186,11 @@ var init_args = __esm({
|
|
|
38077
38186
|
"outputFile",
|
|
38078
38187
|
"output-file",
|
|
38079
38188
|
"testNamePattern",
|
|
38189
|
+
"maxWorkers",
|
|
38080
38190
|
"test-timeout",
|
|
38081
38191
|
"testTimeout",
|
|
38082
|
-
"passWithNoTests"
|
|
38192
|
+
"passWithNoTests",
|
|
38193
|
+
"runInBand"
|
|
38083
38194
|
]);
|
|
38084
38195
|
}
|
|
38085
38196
|
});
|
|
@@ -38569,8 +38680,9 @@ var init_source_diagnostics = __esm({
|
|
|
38569
38680
|
"neoflow-incomplete-draft"
|
|
38570
38681
|
]);
|
|
38571
38682
|
SchemaSourceError = class extends Error {
|
|
38572
|
-
constructor(
|
|
38573
|
-
super(`${file}:${line}:${column} \u2014 ${
|
|
38683
|
+
constructor(detail, file, line, column, code, severity = "error") {
|
|
38684
|
+
super(`${file}:${line}:${column} \u2014 ${detail}`);
|
|
38685
|
+
this.detail = detail;
|
|
38574
38686
|
this.file = file;
|
|
38575
38687
|
this.line = line;
|
|
38576
38688
|
this.column = column;
|
|
@@ -38578,6 +38690,7 @@ var init_source_diagnostics = __esm({
|
|
|
38578
38690
|
this.severity = severity;
|
|
38579
38691
|
this.name = "SchemaSourceError";
|
|
38580
38692
|
}
|
|
38693
|
+
detail;
|
|
38581
38694
|
file;
|
|
38582
38695
|
line;
|
|
38583
38696
|
column;
|
|
@@ -62319,13 +62432,23 @@ function lowerClass(context, declaration) {
|
|
|
62319
62432
|
...placement
|
|
62320
62433
|
});
|
|
62321
62434
|
} catch (error) {
|
|
62322
|
-
|
|
62323
|
-
throw new SchemaSourceError(
|
|
62435
|
+
const positioned = error instanceof SchemaSourceError ? error : new SchemaSourceError(
|
|
62324
62436
|
error instanceof Error ? error.message : String(error),
|
|
62325
62437
|
memberDeclaration.source.uri,
|
|
62326
62438
|
memberDeclaration.source.range.start.line + 1,
|
|
62327
62439
|
memberDeclaration.source.range.start.character + 1
|
|
62328
62440
|
);
|
|
62441
|
+
if (context.onDeclarationError === void 0) throw positioned;
|
|
62442
|
+
context.onDeclarationError(positioned, memberDeclaration);
|
|
62443
|
+
const previous = context.baseMembers.get(memberId);
|
|
62444
|
+
if (previous !== void 0)
|
|
62445
|
+
context.loweredMembers.set(memberId, previous);
|
|
62446
|
+
else {
|
|
62447
|
+
delete schema[memberDeclaration.name];
|
|
62448
|
+
schemaKeyOrder.pop();
|
|
62449
|
+
placements.pop();
|
|
62450
|
+
}
|
|
62451
|
+
continue;
|
|
62329
62452
|
}
|
|
62330
62453
|
const existing = context.loweredMembers.get(memberId);
|
|
62331
62454
|
if (existing && !sameSharedMember(existing, lowered)) {
|
|
@@ -62697,7 +62820,8 @@ function lowerFieldMember(context, ownerClass, declaration, id2, commonInput, ba
|
|
|
62697
62820
|
base,
|
|
62698
62821
|
id2,
|
|
62699
62822
|
storesSelectionArray,
|
|
62700
|
-
`${ownerClass.name}.${declaration.name}
|
|
62823
|
+
`${ownerClass.name}.${declaration.name}`,
|
|
62824
|
+
!declaration.modifiers.includes("static") && contextualEnumArgument(settings, "kind") === "Unordered"
|
|
62701
62825
|
)
|
|
62702
62826
|
};
|
|
62703
62827
|
const name = fieldType.name;
|
|
@@ -63558,12 +63682,12 @@ function lowerType(context, type, ownerClass) {
|
|
|
63558
63682
|
if (type.name === "object") return { kind: "unknown", nullable: nullable2 };
|
|
63559
63683
|
throw new Error(`Unknown Neo type ${JSON.stringify(type.name)}.`);
|
|
63560
63684
|
}
|
|
63561
|
-
function lowerDefault(context, initializer, type, ownerClass, base, memberId, storesSelectionArray, path) {
|
|
63685
|
+
function lowerDefault(context, initializer, type, ownerClass, base, memberId, storesSelectionArray, path, unorderedList = false) {
|
|
63562
63686
|
if (initializer === null) {
|
|
63563
63687
|
return base?.defaultValue && "serverValueId" in base.defaultValue ? base.defaultValue : null;
|
|
63564
63688
|
}
|
|
63565
63689
|
const expression = parseExpression(initializer);
|
|
63566
|
-
if (positionRequiresEvaluation(context, expression, type, ownerClass)) {
|
|
63690
|
+
if (unorderedList && expression.kind === "litList" && expression.elements.length > 0 || positionRequiresEvaluation(context, expression, type, ownerClass)) {
|
|
63567
63691
|
return {
|
|
63568
63692
|
init: {
|
|
63569
63693
|
code: context.settleInitializerReferences(
|
|
@@ -64715,7 +64839,15 @@ function storageChainStep(context, memberId) {
|
|
|
64715
64839
|
}
|
|
64716
64840
|
function referenceIdArgument(value, name) {
|
|
64717
64841
|
const raw = argument(value, name);
|
|
64718
|
-
|
|
64842
|
+
if (raw === null) return null;
|
|
64843
|
+
const parsed = parseReferenceArgument(raw);
|
|
64844
|
+
if (parsed?.kind === "none") return null;
|
|
64845
|
+
if (parsed?.kind === "id") return parsed.value;
|
|
64846
|
+
if (parsed?.kind === "rootPath" && name === "collectionValue")
|
|
64847
|
+
return `${PENDING_ID_PREFIX}root-path:${parsed.value}`;
|
|
64848
|
+
if (name === "template" && parseAnnotationExpression(raw).kind === "ident")
|
|
64849
|
+
return null;
|
|
64850
|
+
throw new Error(referenceArgumentRequirement(name));
|
|
64719
64851
|
}
|
|
64720
64852
|
function templateSymbolArgument(context, settings, ownerClass, declaration) {
|
|
64721
64853
|
const raw = argument(settings, "template");
|
|
@@ -64731,32 +64863,9 @@ function templateSymbolArgument(context, settings, ownerClass, declaration) {
|
|
|
64731
64863
|
return templateId;
|
|
64732
64864
|
}
|
|
64733
64865
|
function referenceId(raw) {
|
|
64734
|
-
|
|
64735
|
-
|
|
64736
|
-
|
|
64737
|
-
if (expression.callee.kind !== "ident" || expression.callee.name !== "Reference") {
|
|
64738
|
-
return null;
|
|
64739
|
-
}
|
|
64740
|
-
const index = expression.argumentNames?.findIndex((entry) => entry === "id") ?? -1;
|
|
64741
|
-
const value = expression.args[index >= 0 ? index : 0];
|
|
64742
|
-
if (value?.kind === "litString") return value.value;
|
|
64743
|
-
const path = value === void 0 ? null : rootValuePath(value);
|
|
64744
|
-
return path === null ? null : `${PENDING_ID_PREFIX}root-path:${path}`;
|
|
64745
|
-
} catch {
|
|
64746
|
-
return null;
|
|
64747
|
-
}
|
|
64748
|
-
}
|
|
64749
|
-
function rootValuePath(expression) {
|
|
64750
|
-
const segments = [];
|
|
64751
|
-
let cursor = expression;
|
|
64752
|
-
while (cursor.kind === "member") {
|
|
64753
|
-
segments.unshift(cursor.name);
|
|
64754
|
-
cursor = cursor.receiver;
|
|
64755
|
-
}
|
|
64756
|
-
if (cursor.kind !== "ident") return null;
|
|
64757
|
-
if (cursor.name !== "root") return null;
|
|
64758
|
-
if (segments.length === 0) return null;
|
|
64759
|
-
return ["root", ...segments].join(".");
|
|
64866
|
+
const parsed = parseReferenceArgument(raw);
|
|
64867
|
+
if (parsed === null || parsed.kind === "none") return null;
|
|
64868
|
+
return parsed.kind === "id" ? parsed.value : `${PENDING_ID_PREFIX}root-path:${parsed.value}`;
|
|
64760
64869
|
}
|
|
64761
64870
|
function isImpliedSchemaKeyOrder(order) {
|
|
64762
64871
|
return order.every((key, index) => index === 0 || order[index - 1] <= key);
|
|
@@ -112398,16 +112507,8 @@ function validateDocumentInheritanceFlags(ctx) {
|
|
|
112398
112507
|
const valueBearing = memberKindSupportsStorage(member.kind);
|
|
112399
112508
|
const valueId = getField(member, "valueId");
|
|
112400
112509
|
if (valueBearing) {
|
|
112401
|
-
if (
|
|
112402
|
-
errors.push(
|
|
112403
|
-
message: `Static member "${member.name}" (${member.id}) stores live content through valueId and cannot retain a schema defaultValue seed.`
|
|
112404
|
-
});
|
|
112405
|
-
}
|
|
112406
|
-
if (isRequiredMember2(member) && (typeof valueId !== "string" || valueId.length === 0)) {
|
|
112407
|
-
errors.push({
|
|
112408
|
-
message: `Required static member "${member.name}" (${member.id}) must have an authored value binding.`
|
|
112409
|
-
});
|
|
112410
|
-
}
|
|
112510
|
+
if (ctx.phase !== "schema")
|
|
112511
|
+
errors.push(...validateStaticMemberValueBinding(member));
|
|
112411
112512
|
} else if (member.storage != null || valueId != null || member.defaultValue != null) {
|
|
112412
112513
|
errors.push({
|
|
112413
112514
|
message: `Value-less static member "${member.name}" (${member.id}) cannot declare storage, valueId, or default content.`
|
|
@@ -112555,6 +112656,7 @@ function validateDocumentInheritanceFlags(ctx) {
|
|
|
112555
112656
|
inheritedMetadata.declarationClassId
|
|
112556
112657
|
);
|
|
112557
112658
|
errors.push({
|
|
112659
|
+
memberId,
|
|
112558
112660
|
message: `Schema member "${schemaKey}" on class "${schemaClass2.name}" (${schemaClass2.id}) does not match the inherited generated signature from member "${generatedAncestorMember.name}" (${generatedAncestorMember.id}). ${schemaClass2.name}.${schemaKey} generates "${ctx.signatureProjector.format(localSignature)}" but ${declaringClass?.name ?? inheritedMetadata.memberId}.${schemaKey} declares "${ctx.signatureProjector.format(ancestorSignature)}". Abstract implementations and re-abstractions must preserve the generated member contract or have a supported codegen bridge.`
|
|
112559
112661
|
});
|
|
112560
112662
|
}
|
|
@@ -112633,6 +112735,23 @@ function nearestAncestorDeclaration2(schemaClass2, schemaKey, classesById) {
|
|
|
112633
112735
|
}
|
|
112634
112736
|
return null;
|
|
112635
112737
|
}
|
|
112738
|
+
function validateStaticMemberValueBinding(member) {
|
|
112739
|
+
if (!isStaticMember(member) || !memberKindSupportsStorage(member.kind))
|
|
112740
|
+
return [];
|
|
112741
|
+
const errors = [];
|
|
112742
|
+
if (member.defaultValue != null)
|
|
112743
|
+
errors.push({
|
|
112744
|
+
memberId: member.id,
|
|
112745
|
+
message: `Static member "${member.name}" (${member.id}) stores live content through valueId and cannot retain a schema defaultValue seed.`
|
|
112746
|
+
});
|
|
112747
|
+
const valueId = getField(member, "valueId");
|
|
112748
|
+
if (isRequiredMember2(member) && (typeof valueId !== "string" || valueId.length === 0))
|
|
112749
|
+
errors.push({
|
|
112750
|
+
memberId: member.id,
|
|
112751
|
+
message: `Required static member "${member.name}" (${member.id}) must have an authored value binding.`
|
|
112752
|
+
});
|
|
112753
|
+
return errors;
|
|
112754
|
+
}
|
|
112636
112755
|
var init_inheritance_flags_validation = __esm({
|
|
112637
112756
|
"../src/models/classes/inheritance-flags-validation.ts"() {
|
|
112638
112757
|
"use strict";
|
|
@@ -114889,7 +115008,7 @@ function changesRequireInheritanceFlagsValidation(changes) {
|
|
|
114889
115008
|
(change) => change.recordKind === "member" || change.recordKind === "class" || change.recordKind === "enum" || change.recordKind === "interface" || change.recordKind === "project"
|
|
114890
115009
|
);
|
|
114891
115010
|
}
|
|
114892
|
-
function
|
|
115011
|
+
function collectProjectDocumentInheritanceFlagsErrors(document, phase = "complete") {
|
|
114893
115012
|
let generatedSignatures = null;
|
|
114894
115013
|
const getGeneratedSignatures = () => {
|
|
114895
115014
|
if (generatedSignatures !== null) return generatedSignatures;
|
|
@@ -114915,6 +115034,7 @@ function assertProjectDocumentInheritanceFlagsValid(document) {
|
|
|
114915
115034
|
return generatedSignatures;
|
|
114916
115035
|
};
|
|
114917
115036
|
const errors = validateDocumentInheritanceFlags({
|
|
115037
|
+
phase,
|
|
114918
115038
|
members: document.members,
|
|
114919
115039
|
classes: document.classes,
|
|
114920
115040
|
rootMemberIds: new Set(
|
|
@@ -114939,9 +115059,11 @@ function assertProjectDocumentInheritanceFlagsValid(document) {
|
|
|
114939
115059
|
hasImplementationBridge: (classId, schemaKey) => getGeneratedSignatures().hasImplementationBridge(classId, schemaKey)
|
|
114940
115060
|
}
|
|
114941
115061
|
});
|
|
114942
|
-
|
|
114943
|
-
|
|
114944
|
-
|
|
115062
|
+
return errors;
|
|
115063
|
+
}
|
|
115064
|
+
function assertProjectDocumentInheritanceFlagsValid(document) {
|
|
115065
|
+
const errors = collectProjectDocumentInheritanceFlagsErrors(document);
|
|
115066
|
+
if (errors.length > 0) throw new Error(errors[0].message);
|
|
114945
115067
|
}
|
|
114946
115068
|
var init_project_document_inheritance_validation = __esm({
|
|
114947
115069
|
"../src/database/project-document-inheritance-validation.ts"() {
|
|
@@ -117435,6 +117557,103 @@ var init_client_commit_preparation = __esm({
|
|
|
117435
117557
|
}
|
|
117436
117558
|
});
|
|
117437
117559
|
|
|
117560
|
+
// src/project-source/schema-source-validation.ts
|
|
117561
|
+
function sourceDiagnosticMapper(analysis) {
|
|
117562
|
+
const locations = /* @__PURE__ */ new Map();
|
|
117563
|
+
for (const declaration of analysis.schema.classes) {
|
|
117564
|
+
locations.set(
|
|
117565
|
+
materializedId(declaration, "class", declaration.name),
|
|
117566
|
+
declaration.source
|
|
117567
|
+
);
|
|
117568
|
+
for (const member of declaration.members) {
|
|
117569
|
+
locations.set(
|
|
117570
|
+
materializedId(member, "member", `${declaration.name}.${member.name}`),
|
|
117571
|
+
member.source
|
|
117572
|
+
);
|
|
117573
|
+
}
|
|
117574
|
+
}
|
|
117575
|
+
return (error, fallback = "<project>", recordId) => {
|
|
117576
|
+
const message = error instanceof SchemaSourceError ? error.detail : error instanceof Error ? error.message : String(error);
|
|
117577
|
+
if (error instanceof SchemaSourceError && !error.file.startsWith("<"))
|
|
117578
|
+
return error;
|
|
117579
|
+
let location3 = recordId === void 0 ? void 0 : locations.get(recordId);
|
|
117580
|
+
if (location3 === void 0) {
|
|
117581
|
+
for (const match of message.matchAll(
|
|
117582
|
+
/(__pending__:[^:\s]+:[^:\s]+:\d+:\d+:[^\s"()]*)|\(([^()]+)\)|"([^"\n]+)"/g
|
|
117583
|
+
)) {
|
|
117584
|
+
const id2 = match[1] ?? match[2] ?? match[3];
|
|
117585
|
+
location3 = locations.get(id2);
|
|
117586
|
+
if (location3 !== void 0) break;
|
|
117587
|
+
const pending = /^__pending__:[^:]+:([^:]+):(\d+):(\d+):/.exec(id2);
|
|
117588
|
+
if (pending !== null) {
|
|
117589
|
+
const start = {
|
|
117590
|
+
line: Number(pending[2]),
|
|
117591
|
+
character: Number(pending[3])
|
|
117592
|
+
};
|
|
117593
|
+
location3 = {
|
|
117594
|
+
uri: decodeURIComponent(pending[1]),
|
|
117595
|
+
range: { start, end: start }
|
|
117596
|
+
};
|
|
117597
|
+
break;
|
|
117598
|
+
}
|
|
117599
|
+
}
|
|
117600
|
+
}
|
|
117601
|
+
if (location3 === void 0 && error instanceof SchemaSourceError)
|
|
117602
|
+
return error;
|
|
117603
|
+
return new SchemaSourceError(
|
|
117604
|
+
message,
|
|
117605
|
+
location3?.uri ?? fallback,
|
|
117606
|
+
(location3?.range.start.line ?? 0) + 1,
|
|
117607
|
+
(location3?.range.start.character ?? 0) + 1,
|
|
117608
|
+
error instanceof SchemaSourceError ? error.code : "schema-validation"
|
|
117609
|
+
);
|
|
117610
|
+
};
|
|
117611
|
+
}
|
|
117612
|
+
function collectSourceSchemaErrors(document) {
|
|
117613
|
+
const rootMemberIds2 = new Set(
|
|
117614
|
+
PROJECT_ROOTS.map((root) => document.project[root.projectField])
|
|
117615
|
+
);
|
|
117616
|
+
const errors = [];
|
|
117617
|
+
for (const validate3 of [
|
|
117618
|
+
() => validateDocumentAccessModifiers({ ...document, rootMemberIds: rootMemberIds2 }),
|
|
117619
|
+
() => collectProjectDocumentInheritanceFlagsErrors(document, "schema")
|
|
117620
|
+
]) {
|
|
117621
|
+
try {
|
|
117622
|
+
errors.push(...validate3());
|
|
117623
|
+
} catch (error) {
|
|
117624
|
+
errors.push({
|
|
117625
|
+
message: error instanceof Error ? error.message : String(error)
|
|
117626
|
+
});
|
|
117627
|
+
}
|
|
117628
|
+
}
|
|
117629
|
+
for (const member of document.members) {
|
|
117630
|
+
if (member.kind !== 6 /* List */) continue;
|
|
117631
|
+
errors.push(...validateListIndexDefinitions(document, member));
|
|
117632
|
+
}
|
|
117633
|
+
return errors;
|
|
117634
|
+
}
|
|
117635
|
+
function uniqueSourceErrors(errors) {
|
|
117636
|
+
const seen = /* @__PURE__ */ new Set();
|
|
117637
|
+
return errors.filter((error) => {
|
|
117638
|
+
const key = `${error.file}:${error.line}:${error.column}:${error.detail}`;
|
|
117639
|
+
if (seen.has(key)) return false;
|
|
117640
|
+
seen.add(key);
|
|
117641
|
+
return true;
|
|
117642
|
+
});
|
|
117643
|
+
}
|
|
117644
|
+
var init_schema_source_validation = __esm({
|
|
117645
|
+
"src/project-source/schema-source-validation.ts"() {
|
|
117646
|
+
"use strict";
|
|
117647
|
+
init_project_document_inheritance_validation();
|
|
117648
|
+
init_member_access_modifier_validation();
|
|
117649
|
+
init_list_indexes();
|
|
117650
|
+
init_member_kinds();
|
|
117651
|
+
init_project2();
|
|
117652
|
+
init_source_diagnostics();
|
|
117653
|
+
init_lower_support();
|
|
117654
|
+
}
|
|
117655
|
+
});
|
|
117656
|
+
|
|
117438
117657
|
// src/project-sync/value-record-comparison.ts
|
|
117439
117658
|
function valueRecordComparisonBody(value) {
|
|
117440
117659
|
if (!isObjectRecord2(value)) return value;
|
|
@@ -117495,7 +117714,13 @@ function lowerConfiguration(base, analysis) {
|
|
|
117495
117714
|
(global) => global.type.name === "Localization"
|
|
117496
117715
|
);
|
|
117497
117716
|
if (!localizationGlobal) {
|
|
117498
|
-
throw new
|
|
117717
|
+
throw new SchemaSourceError(
|
|
117718
|
+
"Format-4 source requires one Localization global.",
|
|
117719
|
+
base.localization.source.span.path,
|
|
117720
|
+
1,
|
|
117721
|
+
1,
|
|
117722
|
+
"missing-localization-global"
|
|
117723
|
+
);
|
|
117499
117724
|
}
|
|
117500
117725
|
return {
|
|
117501
117726
|
textureTemplates,
|
|
@@ -118426,6 +118651,7 @@ var wireEnumOptions, TEXTURE_TYPE_WIRE_OPTIONS, ALPHA_SOURCE_WIRE_OPTIONS, NON_P
|
|
|
118426
118651
|
var init_lower_configuration = __esm({
|
|
118427
118652
|
"src/project-source/lower-configuration.ts"() {
|
|
118428
118653
|
"use strict";
|
|
118654
|
+
init_source_diagnostics();
|
|
118429
118655
|
init_src();
|
|
118430
118656
|
init_lower_support();
|
|
118431
118657
|
wireEnumOptions = () => (options) => options;
|
|
@@ -119140,6 +119366,7 @@ function lowerProjectSchemaV4(base, analysis, options = {}) {
|
|
|
119140
119366
|
)
|
|
119141
119367
|
);
|
|
119142
119368
|
const context = {
|
|
119369
|
+
onDeclarationError: options.onDeclarationError,
|
|
119143
119370
|
base,
|
|
119144
119371
|
baseClasses: new Map(base.classes.map((entry) => [entry.id, entry])),
|
|
119145
119372
|
baseConstructors: new Map(
|
|
@@ -119198,17 +119425,29 @@ function lowerProjectSchemaV4(base, analysis, options = {}) {
|
|
|
119198
119425
|
analysis.compiledBodies.filter((body) => body.unit === "function").map((body) => [`${body.ownerName}.${body.memberName}`, body.ir])
|
|
119199
119426
|
)
|
|
119200
119427
|
};
|
|
119201
|
-
const classes = analysis.schema.classes.
|
|
119202
|
-
|
|
119203
|
-
|
|
119204
|
-
|
|
119205
|
-
|
|
119206
|
-
|
|
119207
|
-
|
|
119208
|
-
|
|
119209
|
-
|
|
119210
|
-
|
|
119211
|
-
|
|
119428
|
+
const classes = analysis.schema.classes.flatMap((declaration) => {
|
|
119429
|
+
try {
|
|
119430
|
+
return [lowerClass(context, declaration)];
|
|
119431
|
+
} catch (error) {
|
|
119432
|
+
if (options.onDeclarationError === void 0) throw error;
|
|
119433
|
+
options.onDeclarationError(error, declaration);
|
|
119434
|
+
return [];
|
|
119435
|
+
}
|
|
119436
|
+
});
|
|
119437
|
+
const constructors = analysis.schema.classes.flatMap((declaration) => {
|
|
119438
|
+
try {
|
|
119439
|
+
return lowerClassConstructors(
|
|
119440
|
+
context,
|
|
119441
|
+
declaration,
|
|
119442
|
+
materializedId(declaration, "class", declaration.name),
|
|
119443
|
+
(type, ownerClass) => lowerType(context, type, ownerClass)
|
|
119444
|
+
);
|
|
119445
|
+
} catch (error) {
|
|
119446
|
+
if (options.onDeclarationError === void 0) throw error;
|
|
119447
|
+
options.onDeclarationError(error, declaration);
|
|
119448
|
+
return [];
|
|
119449
|
+
}
|
|
119450
|
+
});
|
|
119212
119451
|
normalizeLookupDeclaredTypes(context);
|
|
119213
119452
|
for (const [memberId, placements] of context.placements) {
|
|
119214
119453
|
const member = context.loweredMembers.get(memberId);
|
|
@@ -123643,6 +123882,9 @@ function computeWorkspaceStatus(workspace, options) {
|
|
|
123643
123882
|
staticMemberOwnershipRecoveries.filter((recovery) => recovery.action === "delete").map((recovery) => recordStateKey("member", recovery.memberId))
|
|
123644
123883
|
);
|
|
123645
123884
|
let manifest;
|
|
123885
|
+
let rootEnvelopeValid = false;
|
|
123886
|
+
let invalidSchema = false;
|
|
123887
|
+
let schemaValidationDocument;
|
|
123646
123888
|
let authoredValueSeeds = /* @__PURE__ */ new Map();
|
|
123647
123889
|
let staticMemberValueIds = /* @__PURE__ */ new Map();
|
|
123648
123890
|
let memberDefaults = {
|
|
@@ -123676,36 +123918,33 @@ function computeWorkspaceStatus(workspace, options) {
|
|
|
123676
123918
|
}
|
|
123677
123919
|
const analysis = options.readProjectAnalysisCache?.(workspace.root, compilationSources) ?? compileNeoProjectSources(compilationSources);
|
|
123678
123920
|
projectAnalysisV4 = analysis;
|
|
123679
|
-
for (const
|
|
123921
|
+
for (const diagnostic2 of analysis.diagnostics) {
|
|
123680
123922
|
const positioned = new SchemaSourceError(
|
|
123681
|
-
`${
|
|
123682
|
-
|
|
123683
|
-
|
|
123684
|
-
|
|
123685
|
-
|
|
123686
|
-
|
|
123923
|
+
`${diagnostic2.code ?? "analysis"}: ${diagnostic2.message}`,
|
|
123924
|
+
diagnostic2.uri,
|
|
123925
|
+
diagnostic2.range.start.line + 1,
|
|
123926
|
+
diagnostic2.range.start.character + 1,
|
|
123927
|
+
diagnostic2.code,
|
|
123928
|
+
diagnostic2.severity
|
|
123687
123929
|
);
|
|
123688
123930
|
if (positioned.severity === "error") parseErrors.push(positioned);
|
|
123689
123931
|
else parseWarnings.push(positioned);
|
|
123690
123932
|
}
|
|
123691
|
-
|
|
123692
|
-
|
|
123693
|
-
|
|
123694
|
-
|
|
123695
|
-
|
|
123696
|
-
|
|
123697
|
-
reconstructed: /* @__PURE__ */ new Map(),
|
|
123698
|
-
authoredValueSeeds,
|
|
123699
|
-
binaryChanges: [],
|
|
123700
|
-
binaryFiles: []
|
|
123701
|
-
};
|
|
123702
|
-
}
|
|
123933
|
+
const rootDeclaration = analysis.configuration.globals.find(
|
|
123934
|
+
(global) => global.type.name === "Root"
|
|
123935
|
+
);
|
|
123936
|
+
const rootHasCompilerError = rootDeclaration !== void 0 && analysis.diagnostics.some(
|
|
123937
|
+
(error) => error.severity === "error" && error.uri === rootDeclaration.source.uri && sourceRangeContains(rootDeclaration.source.range, error.range.start)
|
|
123938
|
+
);
|
|
123703
123939
|
try {
|
|
123704
|
-
|
|
123705
|
-
|
|
123706
|
-
|
|
123707
|
-
|
|
123708
|
-
|
|
123940
|
+
if (!rootHasCompilerError) {
|
|
123941
|
+
validateProjectRootEnvelopeV4(
|
|
123942
|
+
loweringRecords,
|
|
123943
|
+
analysis,
|
|
123944
|
+
valueLowerRegistry.parsedInitializers
|
|
123945
|
+
);
|
|
123946
|
+
rootEnvelopeValid = true;
|
|
123947
|
+
}
|
|
123709
123948
|
} catch (error) {
|
|
123710
123949
|
const root = analysis.configuration.globals.find(
|
|
123711
123950
|
(global) => global.type.name === "Root"
|
|
@@ -123718,18 +123957,48 @@ function computeWorkspaceStatus(workspace, options) {
|
|
|
123718
123957
|
(root?.source.range.start.character ?? 0) + 1
|
|
123719
123958
|
)
|
|
123720
123959
|
);
|
|
123721
|
-
return {
|
|
123722
|
-
changes: [],
|
|
123723
|
-
conflictedFiles,
|
|
123724
|
-
parseErrors,
|
|
123725
|
-
parseWarnings,
|
|
123726
|
-
reconstructed: /* @__PURE__ */ new Map(),
|
|
123727
|
-
authoredValueSeeds,
|
|
123728
|
-
binaryChanges: [],
|
|
123729
|
-
binaryFiles: []
|
|
123730
|
-
};
|
|
123731
123960
|
}
|
|
123732
|
-
|
|
123961
|
+
const diagnostic = sourceDiagnosticMapper(analysis);
|
|
123962
|
+
const errorsByUri = /* @__PURE__ */ new Map();
|
|
123963
|
+
for (const error of analysis.diagnostics) {
|
|
123964
|
+
if (error.severity !== "error") continue;
|
|
123965
|
+
const errors = errorsByUri.get(error.uri) ?? [];
|
|
123966
|
+
errors.push(error);
|
|
123967
|
+
errorsByUri.set(error.uri, errors);
|
|
123968
|
+
}
|
|
123969
|
+
const validAnalysis = {
|
|
123970
|
+
...analysis,
|
|
123971
|
+
configuration: {
|
|
123972
|
+
globals: analysis.configuration.globals.filter(
|
|
123973
|
+
(global) => global.type.name !== "Root" || rootEnvelopeValid && !rootHasCompilerError
|
|
123974
|
+
)
|
|
123975
|
+
},
|
|
123976
|
+
schema: {
|
|
123977
|
+
...analysis.schema,
|
|
123978
|
+
classes: analysis.schema.classes.map((declaration) => ({
|
|
123979
|
+
...declaration,
|
|
123980
|
+
members: declaration.members.filter(
|
|
123981
|
+
(member) => !(errorsByUri.get(member.source.uri) ?? []).some(
|
|
123982
|
+
(error) => sourceRangeContains(member.source.range, error.range.start)
|
|
123983
|
+
)
|
|
123984
|
+
)
|
|
123985
|
+
}))
|
|
123986
|
+
}
|
|
123987
|
+
};
|
|
123988
|
+
const failedDeclarations = /* @__PURE__ */ new Set();
|
|
123989
|
+
manifest = lowerProjectSchemaV4(baseManifest, validAnalysis, {
|
|
123990
|
+
onDeclarationError: (error, declaration) => {
|
|
123991
|
+
failedDeclarations.add(declaration);
|
|
123992
|
+
parseErrors.push(
|
|
123993
|
+
error instanceof SchemaSourceError ? error : new SchemaSourceError(
|
|
123994
|
+
error instanceof Error ? error.message : String(error),
|
|
123995
|
+
declaration.source.uri,
|
|
123996
|
+
declaration.source.range.start.line + 1,
|
|
123997
|
+
declaration.source.range.start.character + 1,
|
|
123998
|
+
"schema-lowering"
|
|
123999
|
+
)
|
|
124000
|
+
);
|
|
124001
|
+
},
|
|
123733
124002
|
staticValueIdsBySymbol: staticValueIdsBySymbol(loweringRecords),
|
|
123734
124003
|
projectFileIdsBySymbol: projectFileIdsBySymbol(loweringRecords, analysis),
|
|
123735
124004
|
rowBackedDefaultMemberIds: rowBackedDefaultMemberIdsV4(loweringRecords),
|
|
@@ -123737,9 +124006,61 @@ function computeWorkspaceStatus(workspace, options) {
|
|
|
123737
124006
|
Object.values(loweringRecords)
|
|
123738
124007
|
)
|
|
123739
124008
|
});
|
|
124009
|
+
try {
|
|
124010
|
+
const schemaRecords = /* @__PURE__ */ new Map();
|
|
124011
|
+
for (const [key, record6] of Object.entries(loweringRecords)) {
|
|
124012
|
+
if (record6.recordKind !== "project") continue;
|
|
124013
|
+
schemaRecords.set(key, { ...record6, deleted: false });
|
|
124014
|
+
}
|
|
124015
|
+
for (const record6 of projectSchemaManifestToDocuments(
|
|
124016
|
+
manifest,
|
|
124017
|
+
manifestToDocumentContext(baseDocuments)
|
|
124018
|
+
)) {
|
|
124019
|
+
schemaRecords.set(recordStateKey(record6.recordKind, record6.recordId), {
|
|
124020
|
+
...record6,
|
|
124021
|
+
contentHash: "",
|
|
124022
|
+
deleted: false
|
|
124023
|
+
});
|
|
124024
|
+
}
|
|
124025
|
+
if ([...schemaRecords.values()].some(
|
|
124026
|
+
(record6) => record6.recordKind === "project"
|
|
124027
|
+
)) {
|
|
124028
|
+
const document = readPulledProjectDocumentV4(schemaRecords);
|
|
124029
|
+
schemaValidationDocument = document;
|
|
124030
|
+
for (const error of collectSourceSchemaErrors(document)) {
|
|
124031
|
+
parseErrors.push(
|
|
124032
|
+
diagnostic(new Error(error.message), "<project>", error.memberId)
|
|
124033
|
+
);
|
|
124034
|
+
}
|
|
124035
|
+
}
|
|
124036
|
+
} catch (error) {
|
|
124037
|
+
parseErrors.push(diagnostic(error));
|
|
124038
|
+
}
|
|
124039
|
+
invalidSchema = parseErrors.some(isBlockingSchemaSourceError);
|
|
124040
|
+
const loweredMemberIds = new Set(
|
|
124041
|
+
manifest.members.map((member) => member.id)
|
|
124042
|
+
);
|
|
124043
|
+
projectAnalysisV4 = {
|
|
124044
|
+
...validAnalysis,
|
|
124045
|
+
schema: {
|
|
124046
|
+
...validAnalysis.schema,
|
|
124047
|
+
classes: validAnalysis.schema.classes.map((declaration) => ({
|
|
124048
|
+
...declaration,
|
|
124049
|
+
members: declaration.members.filter(
|
|
124050
|
+
(member) => !failedDeclarations.has(member) && loweredMemberIds.has(
|
|
124051
|
+
materializedId(
|
|
124052
|
+
member,
|
|
124053
|
+
"member",
|
|
124054
|
+
`${declaration.name}.${member.name}`
|
|
124055
|
+
)
|
|
124056
|
+
)
|
|
124057
|
+
)
|
|
124058
|
+
}))
|
|
124059
|
+
}
|
|
124060
|
+
};
|
|
123740
124061
|
memberDefaults = lowerMemberDefaultSourcesV4(
|
|
123741
124062
|
loweringRecords,
|
|
123742
|
-
|
|
124063
|
+
projectAnalysisV4,
|
|
123743
124064
|
manifest,
|
|
123744
124065
|
{ registry: valueLowerRegistry }
|
|
123745
124066
|
);
|
|
@@ -123759,9 +124080,17 @@ function computeWorkspaceStatus(workspace, options) {
|
|
|
123759
124080
|
);
|
|
123760
124081
|
reportPhase("analysis-schema-defaults", "Reading stored values\u2026");
|
|
123761
124082
|
} catch (error) {
|
|
124083
|
+
const missingLocalization = error instanceof SchemaSourceError && error.code === "missing-localization-global";
|
|
124084
|
+
const positioned = missingLocalization ? new SchemaSourceError(
|
|
124085
|
+
error.detail,
|
|
124086
|
+
loweringRecords[`localization-config:${baseManifest?.localization.id}`]?.file ?? "Localization.neo",
|
|
124087
|
+
1,
|
|
124088
|
+
1,
|
|
124089
|
+
error.code
|
|
124090
|
+
) : error;
|
|
123762
124091
|
parseErrors.push(
|
|
123763
|
-
|
|
123764
|
-
|
|
124092
|
+
positioned instanceof SchemaSourceError ? positioned : new SchemaSourceError(
|
|
124093
|
+
positioned instanceof Error ? positioned.message : String(positioned),
|
|
123765
124094
|
"<project>",
|
|
123766
124095
|
1,
|
|
123767
124096
|
1
|
|
@@ -123823,12 +124152,25 @@ function computeWorkspaceStatus(workspace, options) {
|
|
|
123823
124152
|
...memberDefaults.seeds
|
|
123824
124153
|
]);
|
|
123825
124154
|
staticMemberValueIds = staticValues.memberValueIds;
|
|
123826
|
-
|
|
123827
|
-
|
|
123828
|
-
|
|
123829
|
-
|
|
123830
|
-
|
|
123831
|
-
|
|
124155
|
+
if (schemaValidationDocument !== void 0) {
|
|
124156
|
+
const diagnostic = sourceDiagnosticMapper(projectAnalysisV4);
|
|
124157
|
+
for (const member of schemaValidationDocument.members) {
|
|
124158
|
+
const valueId = staticMemberValueIds.get(member.id);
|
|
124159
|
+
const finalized = valueId === void 0 ? member : { ...member, valueId, defaultValue: void 0 };
|
|
124160
|
+
for (const error of validateStaticMemberValueBinding(finalized)) {
|
|
124161
|
+
parseErrors.push(
|
|
124162
|
+
diagnostic(new Error(error.message), "<project>", member.id)
|
|
124163
|
+
);
|
|
124164
|
+
}
|
|
124165
|
+
}
|
|
124166
|
+
}
|
|
124167
|
+
const rootValues = rootEnvelopeValid ? lowerProjectRootSourceV4(loweringRecords, projectAnalysisV4, manifest, {
|
|
124168
|
+
registry: valueLowerRegistry
|
|
124169
|
+
}) : {
|
|
124170
|
+
records: [],
|
|
124171
|
+
memberValueIds: /* @__PURE__ */ new Map(),
|
|
124172
|
+
seeds: /* @__PURE__ */ new Map()
|
|
124173
|
+
};
|
|
123832
124174
|
reportPhase("documents-static-root", "Reading variants and dialogues\u2026");
|
|
123833
124175
|
authoredValueSeeds = new Map([...authoredValueSeeds, ...rootValues.seeds]);
|
|
123834
124176
|
const rootPathResolutionState = overlayProspectiveSourceRecords(
|
|
@@ -124453,6 +124795,14 @@ function computeWorkspaceStatus(workspace, options) {
|
|
|
124453
124795
|
}
|
|
124454
124796
|
reportPhase("initializer-materialization");
|
|
124455
124797
|
}
|
|
124798
|
+
const mapDiagnostic = projectAnalysisV4 === null ? null : sourceDiagnosticMapper(projectAnalysisV4);
|
|
124799
|
+
const positionedErrors = mapDiagnostic === null ? parseErrors : parseErrors.map((error) => mapDiagnostic(error, error.file));
|
|
124800
|
+
if (invalidSchema)
|
|
124801
|
+
return refusedStatus(
|
|
124802
|
+
conflictedFiles,
|
|
124803
|
+
uniqueSourceErrors(positionedErrors),
|
|
124804
|
+
parseWarnings
|
|
124805
|
+
);
|
|
124456
124806
|
return {
|
|
124457
124807
|
...projectAnalysisV4 === null ? {} : {
|
|
124458
124808
|
sourceSnapshot: {
|
|
@@ -124463,7 +124813,7 @@ function computeWorkspaceStatus(workspace, options) {
|
|
|
124463
124813
|
localValues: valueLowerRegistry.localValues?.placements(),
|
|
124464
124814
|
changes,
|
|
124465
124815
|
conflictedFiles,
|
|
124466
|
-
parseErrors,
|
|
124816
|
+
parseErrors: uniqueSourceErrors(positionedErrors),
|
|
124467
124817
|
parseWarnings,
|
|
124468
124818
|
reconstructed: reconstructed3,
|
|
124469
124819
|
authoredValueSeeds,
|
|
@@ -125440,10 +125790,16 @@ function refusedStatus(conflictedFiles, parseErrors, parseWarnings) {
|
|
|
125440
125790
|
binaryFiles: []
|
|
125441
125791
|
};
|
|
125442
125792
|
}
|
|
125793
|
+
function sourceRangeContains(range2, position) {
|
|
125794
|
+
return (position.line > range2.start.line || position.line === range2.start.line && position.character >= range2.start.character) && (position.line < range2.end.line || position.line === range2.end.line && position.character < range2.end.character);
|
|
125795
|
+
}
|
|
125443
125796
|
var ANIMATION_DOCUMENT_RECORD_KINDS, ANIMATION_REPLAY_RECORD_KINDS, PROSPECTIVE_ANIMATION_RECORD_KINDS;
|
|
125444
125797
|
var init_workspace_status_core = __esm({
|
|
125445
125798
|
"src/project-source/workspace-status-core.ts"() {
|
|
125446
125799
|
"use strict";
|
|
125800
|
+
init_lower_support();
|
|
125801
|
+
init_inheritance_flags_validation();
|
|
125802
|
+
init_schema_source_validation();
|
|
125447
125803
|
init_members();
|
|
125448
125804
|
init_collection_binding_materialization();
|
|
125449
125805
|
init_localizable_member_value_writes();
|
|
@@ -125566,9 +125922,9 @@ function verifyProjectSourceCommitAgainstStateV4(args) {
|
|
|
125566
125922
|
});
|
|
125567
125923
|
const blockingErrors = status.parseErrors.filter(isBlockingSchemaSourceError);
|
|
125568
125924
|
if (status.conflictedFiles.length > 0 || blockingErrors.length > 0) {
|
|
125569
|
-
const first = blockingErrors[0];
|
|
125570
125925
|
throw new ProjectSourceCommitVerificationError(
|
|
125571
|
-
|
|
125926
|
+
blockingErrors.length > 0 ? `Trusted source lowering failed:
|
|
125927
|
+
${blockingErrors.map((error) => error.message).join("\n")}` : `Trusted source lowering found conflict markers in ${status.conflictedFiles.join(", ")}.`
|
|
125572
125928
|
);
|
|
125573
125929
|
}
|
|
125574
125930
|
auditAuthoredSeedRowIdentities(
|
|
@@ -125601,8 +125957,10 @@ function verifyProjectSourceCommitAgainstStateV4(args) {
|
|
|
125601
125957
|
);
|
|
125602
125958
|
for (const pendingId2 of assignments.keys()) {
|
|
125603
125959
|
if (!usedAssignments.has(pendingId2)) {
|
|
125960
|
+
const message = `Pending id assignment ${pendingId2} is not present in the verified source manifest.`;
|
|
125961
|
+
const analysis = status.sourceSnapshot?.analysis;
|
|
125604
125962
|
throw new ProjectSourceCommitVerificationError(
|
|
125605
|
-
|
|
125963
|
+
analysis === void 0 ? message : sourceDiagnosticMapper(analysis)(new Error(message)).message
|
|
125606
125964
|
);
|
|
125607
125965
|
}
|
|
125608
125966
|
}
|
|
@@ -126096,6 +126454,7 @@ var ProjectSourceCommitVerificationError, ABSENT_DIFFERENCE_VALUE;
|
|
|
126096
126454
|
var init_trusted_commit_verification = __esm({
|
|
126097
126455
|
"src/project-source/trusted-commit-verification.ts"() {
|
|
126098
126456
|
"use strict";
|
|
126457
|
+
init_schema_source_validation();
|
|
126099
126458
|
init_projectRecordBuckets();
|
|
126100
126459
|
init_workspace_status_core();
|
|
126101
126460
|
init_supplemental_records();
|
|
@@ -128480,6 +128839,8 @@ function defaultRequiresOwnedRows(context, member, sourceExpression, source) {
|
|
|
128480
128839
|
}
|
|
128481
128840
|
function memberInitializerRequiresEvaluation(context, member, expression, source) {
|
|
128482
128841
|
if (member.kind === "class" && member.partial === true) return false;
|
|
128842
|
+
if (source.purpose === "memberDefault" && member.id === source.memberId && member.kind === "list" && member.listKind === "unordered" && expression.kind === "litList" && expression.elements.length > 0)
|
|
128843
|
+
return true;
|
|
128483
128844
|
const requiresEvaluation = isSchemaMemberValueRead(context, expression, source) || initializerRequiresEvaluation(
|
|
128484
128845
|
context.declaredConstructors,
|
|
128485
128846
|
expression,
|
|
@@ -144934,6 +145295,113 @@ var init_project_integrity = __esm({
|
|
|
144934
145295
|
}
|
|
144935
145296
|
});
|
|
144936
145297
|
|
|
145298
|
+
// src/test-worker-pool.ts
|
|
145299
|
+
import { Worker as Worker5 } from "node:worker_threads";
|
|
145300
|
+
var TestWorkerPool;
|
|
145301
|
+
var init_test_worker_pool = __esm({
|
|
145302
|
+
"src/test-worker-pool.ts"() {
|
|
145303
|
+
"use strict";
|
|
145304
|
+
TestWorkerPool = class {
|
|
145305
|
+
constructor(workerUrl) {
|
|
145306
|
+
this.workerUrl = workerUrl;
|
|
145307
|
+
}
|
|
145308
|
+
workerUrl;
|
|
145309
|
+
interrupted = false;
|
|
145310
|
+
workers = [];
|
|
145311
|
+
failures = /* @__PURE__ */ new Map();
|
|
145312
|
+
pending = /* @__PURE__ */ new Map();
|
|
145313
|
+
async start(document, count) {
|
|
145314
|
+
await Promise.all(
|
|
145315
|
+
Array.from({ length: count }, async () => {
|
|
145316
|
+
const worker = new Worker5(this.workerUrl);
|
|
145317
|
+
this.workers.push(worker);
|
|
145318
|
+
worker.on(
|
|
145319
|
+
"error",
|
|
145320
|
+
(error) => this.fail(
|
|
145321
|
+
worker,
|
|
145322
|
+
error instanceof Error ? error : new Error(String(error))
|
|
145323
|
+
)
|
|
145324
|
+
);
|
|
145325
|
+
worker.on(
|
|
145326
|
+
"exit",
|
|
145327
|
+
(code) => this.fail(
|
|
145328
|
+
worker,
|
|
145329
|
+
new Error(
|
|
145330
|
+
`Test worker exited before completing its file (code ${code}).`
|
|
145331
|
+
)
|
|
145332
|
+
)
|
|
145333
|
+
);
|
|
145334
|
+
const response = await this.request(worker, { kind: "init", document });
|
|
145335
|
+
if (response.kind !== "ready")
|
|
145336
|
+
throw new Error("Test worker did not initialize its project.");
|
|
145337
|
+
})
|
|
145338
|
+
);
|
|
145339
|
+
}
|
|
145340
|
+
fail(worker, error) {
|
|
145341
|
+
this.failures.set(worker, error);
|
|
145342
|
+
this.pending.get(worker)?.(error);
|
|
145343
|
+
}
|
|
145344
|
+
request(worker, request) {
|
|
145345
|
+
const failure = this.failures.get(worker);
|
|
145346
|
+
if (failure !== void 0) return Promise.reject(failure);
|
|
145347
|
+
return new Promise((resolve5, reject) => {
|
|
145348
|
+
const cleanup = () => {
|
|
145349
|
+
worker.off("message", onMessage);
|
|
145350
|
+
this.pending.delete(worker);
|
|
145351
|
+
};
|
|
145352
|
+
const onMessage = (response) => {
|
|
145353
|
+
cleanup();
|
|
145354
|
+
if (response.kind === "error") reject(new Error(response.message));
|
|
145355
|
+
else resolve5(response);
|
|
145356
|
+
};
|
|
145357
|
+
const onError = (error) => {
|
|
145358
|
+
cleanup();
|
|
145359
|
+
reject(error);
|
|
145360
|
+
};
|
|
145361
|
+
this.pending.set(worker, onError);
|
|
145362
|
+
worker.once("message", onMessage);
|
|
145363
|
+
try {
|
|
145364
|
+
worker.postMessage(request);
|
|
145365
|
+
} catch (error) {
|
|
145366
|
+
onError(error instanceof Error ? error : new Error(String(error)));
|
|
145367
|
+
}
|
|
145368
|
+
});
|
|
145369
|
+
}
|
|
145370
|
+
async run(jobs, timeoutMs, onResult) {
|
|
145371
|
+
let next = 0;
|
|
145372
|
+
await Promise.all(
|
|
145373
|
+
this.workers.map(async (worker) => {
|
|
145374
|
+
while (!this.interrupted && next < jobs.length) {
|
|
145375
|
+
const job = jobs[next++];
|
|
145376
|
+
const response = await this.request(worker, {
|
|
145377
|
+
kind: "run",
|
|
145378
|
+
...job,
|
|
145379
|
+
timeoutMs
|
|
145380
|
+
});
|
|
145381
|
+
if (response.kind !== "result")
|
|
145382
|
+
throw new Error("Test worker returned no file result.");
|
|
145383
|
+
onResult(job.spec, response.result);
|
|
145384
|
+
}
|
|
145385
|
+
})
|
|
145386
|
+
);
|
|
145387
|
+
}
|
|
145388
|
+
interrupt() {
|
|
145389
|
+
this.interrupted = true;
|
|
145390
|
+
for (const worker of this.workers) {
|
|
145391
|
+
worker.postMessage({ kind: "interrupt" });
|
|
145392
|
+
}
|
|
145393
|
+
}
|
|
145394
|
+
async stop() {
|
|
145395
|
+
for (const reject of this.pending.values())
|
|
145396
|
+
reject(new Error("Test worker stopped."));
|
|
145397
|
+
await Promise.all(this.workers.map((worker) => worker.terminate()));
|
|
145398
|
+
this.workers.length = 0;
|
|
145399
|
+
this.failures.clear();
|
|
145400
|
+
}
|
|
145401
|
+
};
|
|
145402
|
+
}
|
|
145403
|
+
});
|
|
145404
|
+
|
|
144937
145405
|
// src/neoscript-language-adapter.ts
|
|
144938
145406
|
function createCliNeoScriptContext(options) {
|
|
144939
145407
|
const members = [...options.documents.members];
|
|
@@ -144943,12 +145411,7 @@ function createCliNeoScriptContext(options) {
|
|
|
144943
145411
|
members,
|
|
144944
145412
|
classes: [...options.documents.classes],
|
|
144945
145413
|
enums: [...options.documents.enums],
|
|
144946
|
-
interfaces: [...options.documents.interfaces]
|
|
144947
|
-
databaseVM: {
|
|
144948
|
-
memberById: (id2) => members.find(
|
|
144949
|
-
(member) => member.id === id2
|
|
144950
|
-
) ?? null
|
|
144951
|
-
}
|
|
145414
|
+
interfaces: [...options.documents.interfaces]
|
|
144952
145415
|
};
|
|
144953
145416
|
const compilerContext = createNeoScriptDocumentContext({
|
|
144954
145417
|
vm,
|
|
@@ -144990,7 +145453,7 @@ async function validateCliNeoScript(uri, source, context) {
|
|
|
144990
145453
|
service.closeDocument(uri);
|
|
144991
145454
|
}
|
|
144992
145455
|
}
|
|
144993
|
-
function compileCliNeoScript(uri, source, context) {
|
|
145456
|
+
function compileCliNeoScript(uri, source, context, projectIndex) {
|
|
144994
145457
|
const result = compileNeoScriptStrict(
|
|
144995
145458
|
{
|
|
144996
145459
|
uri,
|
|
@@ -144998,7 +145461,8 @@ function compileCliNeoScript(uri, source, context) {
|
|
|
144998
145461
|
version: 1,
|
|
144999
145462
|
text: source
|
|
145000
145463
|
},
|
|
145001
|
-
context
|
|
145464
|
+
context,
|
|
145465
|
+
{ projectIndex }
|
|
145002
145466
|
);
|
|
145003
145467
|
const error = result.diagnostics.find(
|
|
145004
145468
|
(diagnostic) => diagnostic.severity === "error"
|
|
@@ -146998,7 +147462,7 @@ var init_registry2 = __esm({
|
|
|
146998
147462
|
"../packages/manifest/schema-contract/registry.mjs"() {
|
|
146999
147463
|
"use strict";
|
|
147000
147464
|
PROJECT_SCHEMA_CONTRACT = Object.freeze({
|
|
147001
|
-
cliVersion: "0.62.
|
|
147465
|
+
cliVersion: "0.62.2",
|
|
147002
147466
|
projectFileUploadBatchSize: 32,
|
|
147003
147467
|
documentRecords: {
|
|
147004
147468
|
member: {
|
|
@@ -148417,8 +148881,10 @@ var init_registry2 = __esm({
|
|
|
148417
148881
|
// src/commands/test.ts
|
|
148418
148882
|
var test_exports = {};
|
|
148419
148883
|
__export(test_exports, {
|
|
148884
|
+
executeTestFile: () => executeTestFile,
|
|
148420
148885
|
inspectNeoTestCompilation: () => inspectNeoTestCompilation,
|
|
148421
148886
|
maintainNeoTestBuildCache: () => maintainNeoTestBuildCache,
|
|
148887
|
+
prepareTestEvaluator: () => prepareTestEvaluator,
|
|
148422
148888
|
runTest: () => runTest
|
|
148423
148889
|
});
|
|
148424
148890
|
import { createHash as createHash10, randomUUID as randomUUID6 } from "node:crypto";
|
|
@@ -148442,6 +148908,7 @@ import {
|
|
|
148442
148908
|
resolve as resolve4,
|
|
148443
148909
|
sep as sep8
|
|
148444
148910
|
} from "node:path";
|
|
148911
|
+
import { availableParallelism } from "node:os";
|
|
148445
148912
|
import { isDeepStrictEqual } from "node:util";
|
|
148446
148913
|
function isRecord11(value) {
|
|
148447
148914
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -148763,8 +149230,28 @@ function cacheTestCandidate(workspace, inputFingerprint, candidate) {
|
|
|
148763
149230
|
);
|
|
148764
149231
|
return { ...candidate, documentSha256 };
|
|
148765
149232
|
}
|
|
148766
|
-
function
|
|
148767
|
-
const
|
|
149233
|
+
function createSpecCompiler(document) {
|
|
149234
|
+
const context = withNeoTestPrelude({
|
|
149235
|
+
...createCliNeoScriptContext({
|
|
149236
|
+
documents: readDocumentArrays(document),
|
|
149237
|
+
kind: "function",
|
|
149238
|
+
thisClass: null
|
|
149239
|
+
}),
|
|
149240
|
+
kind: "function",
|
|
149241
|
+
projectSourceKind: "spec",
|
|
149242
|
+
returnType: { kind: "primitive", name: "void" }
|
|
149243
|
+
});
|
|
149244
|
+
const projectIndex = createProjectIndex(context.project);
|
|
149245
|
+
return (uri, source) => compileCliNeoScript(uri, source, context, projectIndex);
|
|
149246
|
+
}
|
|
149247
|
+
function lazySpecCompiler(document) {
|
|
149248
|
+
let compiler;
|
|
149249
|
+
return (uri, source) => {
|
|
149250
|
+
compiler ??= createSpecCompiler(document);
|
|
149251
|
+
return compiler(uri, source);
|
|
149252
|
+
};
|
|
149253
|
+
}
|
|
149254
|
+
function compileSpec(workspace, compile, absolutePath, projectCompilationHash2) {
|
|
148768
149255
|
const path = relative8(workspace.root, absolutePath).split(sep8).join("/");
|
|
148769
149256
|
const source = readFileSync19(absolutePath, "utf8");
|
|
148770
149257
|
const sourceHash = createHash10("sha256").update(source).digest("hex");
|
|
@@ -148787,21 +149274,10 @@ function compileSpec(workspace, document, absolutePath, projectCompilationHash2)
|
|
|
148787
149274
|
}
|
|
148788
149275
|
} catch {
|
|
148789
149276
|
}
|
|
148790
|
-
const baseContext2 = createCliNeoScriptContext({
|
|
148791
|
-
documents: scriptDocument,
|
|
148792
|
-
kind: "function",
|
|
148793
|
-
thisClass: null
|
|
148794
|
-
});
|
|
148795
|
-
const context = withNeoTestPrelude({
|
|
148796
|
-
...baseContext2,
|
|
148797
|
-
kind: "function",
|
|
148798
|
-
projectSourceKind: "spec",
|
|
148799
|
-
returnType: { kind: "primitive", name: "void" }
|
|
148800
|
-
});
|
|
148801
149277
|
const compiled = {
|
|
148802
149278
|
path,
|
|
148803
149279
|
source,
|
|
148804
|
-
action:
|
|
149280
|
+
action: compile(`file://${absolutePath}`, source)
|
|
148805
149281
|
};
|
|
148806
149282
|
atomicWrite(
|
|
148807
149283
|
artifactPath,
|
|
@@ -149481,6 +149957,18 @@ function failureFor(error, file, position, member = null) {
|
|
|
149481
149957
|
function suiteHasSelectedTests(suite, selected) {
|
|
149482
149958
|
return suite.tests.some((test) => selected.has(test.id)) || suite.suites.some((child) => suiteHasSelectedTests(child, selected));
|
|
149483
149959
|
}
|
|
149960
|
+
function prepareTestEvaluator(document) {
|
|
149961
|
+
sharedEvaluatorBase(document);
|
|
149962
|
+
}
|
|
149963
|
+
async function executeTestFile(spec, document, selected, timeoutMs, interrupted = () => false) {
|
|
149964
|
+
return executeRegisteredSpec(
|
|
149965
|
+
registerSpec(spec, document),
|
|
149966
|
+
document,
|
|
149967
|
+
selected,
|
|
149968
|
+
timeoutMs,
|
|
149969
|
+
interrupted
|
|
149970
|
+
);
|
|
149971
|
+
}
|
|
149484
149972
|
async function executeRegisteredSpec(registered, document, selected, timeoutMs, interrupted) {
|
|
149485
149973
|
const results = [];
|
|
149486
149974
|
const fileFailures = [];
|
|
@@ -149679,8 +150167,11 @@ async function runTest(workspace, options, dependencies = {}) {
|
|
|
149679
150167
|
let testDurationMs = 0;
|
|
149680
150168
|
let exitCode = 0;
|
|
149681
150169
|
let interrupted = false;
|
|
150170
|
+
let workerPool;
|
|
150171
|
+
let parallelExecution = false;
|
|
149682
150172
|
const handleSigint = () => {
|
|
149683
150173
|
interrupted = true;
|
|
150174
|
+
workerPool?.interrupt();
|
|
149684
150175
|
};
|
|
149685
150176
|
const assertNotInterrupted = () => {
|
|
149686
150177
|
if (interrupted) {
|
|
@@ -149695,6 +150186,7 @@ async function runTest(workspace, options, dependencies = {}) {
|
|
|
149695
150186
|
select: 0,
|
|
149696
150187
|
compile: 0,
|
|
149697
150188
|
register: 0,
|
|
150189
|
+
workers: 0,
|
|
149698
150190
|
execute: 0,
|
|
149699
150191
|
finalize: 0
|
|
149700
150192
|
};
|
|
@@ -149725,6 +150217,9 @@ async function runTest(workspace, options, dependencies = {}) {
|
|
|
149725
150217
|
}
|
|
149726
150218
|
if (candidate === null) {
|
|
149727
150219
|
const prepared = dependencies.prepareLocalCandidate === void 0 ? await prepareLocalCandidateV4(workspace, {
|
|
150220
|
+
// Tests need the compiled, validated candidate. Serializing it
|
|
150221
|
+
// back to source and re-lowering is a push dry-run check.
|
|
150222
|
+
fullValidation: false,
|
|
149728
150223
|
onPhase: (label) => {
|
|
149729
150224
|
dependencies.progress?.update(label);
|
|
149730
150225
|
}
|
|
@@ -149776,8 +150271,9 @@ async function runTest(workspace, options, dependencies = {}) {
|
|
|
149776
150271
|
);
|
|
149777
150272
|
}
|
|
149778
150273
|
enterPhase("compile", "Compiling test files\u2026");
|
|
150274
|
+
const compile = lazySpecCompiler(rawDocument);
|
|
149779
150275
|
specs = selectedPaths.map(
|
|
149780
|
-
(path) => compileSpec(workspace,
|
|
150276
|
+
(path) => compileSpec(workspace, compile, path, compilationHash)
|
|
149781
150277
|
);
|
|
149782
150278
|
let pattern = null;
|
|
149783
150279
|
if (options.testNamePattern !== null) {
|
|
@@ -149806,21 +150302,54 @@ async function runTest(workspace, options, dependencies = {}) {
|
|
|
149806
150302
|
);
|
|
149807
150303
|
}
|
|
149808
150304
|
const selectedIds = new Set(selectedTests.map((test) => test.id));
|
|
149809
|
-
enterPhase("execute", "Running tests\u2026");
|
|
149810
150305
|
const timeoutMs = options.timeoutMs ?? workspace.config.test?.timeoutMs ?? 5e3;
|
|
149811
|
-
|
|
149812
|
-
|
|
149813
|
-
|
|
149814
|
-
|
|
149815
|
-
|
|
149816
|
-
|
|
149817
|
-
|
|
149818
|
-
|
|
150306
|
+
const maxWorkers = options.maxWorkers ?? workspace.config.test?.maxWorkers ?? Math.min(4, availableParallelism());
|
|
150307
|
+
if (!Number.isSafeInteger(maxWorkers) || maxWorkers <= 0) {
|
|
150308
|
+
throw new NeoTestUsageError("--maxWorkers must be a positive integer.");
|
|
150309
|
+
}
|
|
150310
|
+
const jobs = registered.filter(
|
|
150311
|
+
(entry) => (selectedTestCountByFile.get(entry.spec.path) ?? 0) > 0
|
|
150312
|
+
);
|
|
150313
|
+
const workerCount = options.runInBand === true ? 1 : Math.min(maxWorkers, jobs.length);
|
|
150314
|
+
const recordResult = (spec, executed) => {
|
|
149819
150315
|
results.push(...executed.tests);
|
|
149820
150316
|
testDurationMs += executed.testDurationMs;
|
|
149821
|
-
fileFailuresByPath.set(
|
|
150317
|
+
fileFailuresByPath.set(spec.path, executed.failures);
|
|
150318
|
+
};
|
|
150319
|
+
if (workerCount > 1) {
|
|
150320
|
+
enterPhase("workers", "Starting test workers\u2026");
|
|
150321
|
+
workerPool = new TestWorkerPool(
|
|
150322
|
+
new URL("./test-worker.mjs", import.meta.url)
|
|
150323
|
+
);
|
|
150324
|
+
await workerPool.start(rawDocument, workerCount);
|
|
149822
150325
|
assertNotInterrupted();
|
|
150326
|
+
parallelExecution = true;
|
|
150327
|
+
enterPhase("execute", "Running tests\u2026");
|
|
150328
|
+
await workerPool.run(
|
|
150329
|
+
jobs.map((entry) => ({
|
|
150330
|
+
spec: entry.spec,
|
|
150331
|
+
selectedIds: entry.tests.filter((test) => selectedIds.has(test.id)).map((test) => test.id)
|
|
150332
|
+
})),
|
|
150333
|
+
timeoutMs,
|
|
150334
|
+
recordResult
|
|
150335
|
+
);
|
|
150336
|
+
} else {
|
|
150337
|
+
enterPhase("execute", "Running tests\u2026");
|
|
150338
|
+
for (const entry of jobs) {
|
|
150339
|
+
recordResult(
|
|
150340
|
+
entry.spec,
|
|
150341
|
+
await executeRegisteredSpec(
|
|
150342
|
+
entry,
|
|
150343
|
+
rawDocument,
|
|
150344
|
+
selectedIds,
|
|
150345
|
+
timeoutMs,
|
|
150346
|
+
() => interrupted
|
|
150347
|
+
)
|
|
150348
|
+
);
|
|
150349
|
+
assertNotInterrupted();
|
|
150350
|
+
}
|
|
149823
150351
|
}
|
|
150352
|
+
assertNotInterrupted();
|
|
149824
150353
|
if (results.some((result) => result.status === "failed") || [...fileFailuresByPath.values()].some((failures) => failures.length > 0)) {
|
|
149825
150354
|
exitCode = 1;
|
|
149826
150355
|
}
|
|
@@ -149828,7 +150357,7 @@ async function runTest(workspace, options, dependencies = {}) {
|
|
|
149828
150357
|
const buildManifest = {
|
|
149829
150358
|
version: 1,
|
|
149830
150359
|
cliVersion: PROJECT_SCHEMA_CONTRACT.cliVersion,
|
|
149831
|
-
runnerRevision:
|
|
150360
|
+
runnerRevision: 4,
|
|
149832
150361
|
compilerRevision: NEOSCRIPT_COMPILER_REVISION,
|
|
149833
150362
|
evaluatorRevision: 4,
|
|
149834
150363
|
projectFingerprint,
|
|
@@ -149848,12 +150377,12 @@ async function runTest(workspace, options, dependencies = {}) {
|
|
|
149848
150377
|
`
|
|
149849
150378
|
);
|
|
149850
150379
|
} catch (error) {
|
|
149851
|
-
const diagnosticCode = error instanceof NeoTestInterruptedError ? "NEO_TEST_INTERRUPTED" : error instanceof NeoTestPreparedCandidateError ? "NEO_TEST_PREPARED_CANDIDATE" : error instanceof NeoTestUsageError ? "NEO_TEST_USAGE" : error instanceof NeoTestNoTestsError ? "NEO_TEST_NO_TESTS" : error instanceof NeoTestRegistrationError ? "NEO_TEST_REGISTRATION" : phase === "prepare" ? "NEO_TEST_PREPARATION" : phase === "compile" ? "NEO_TEST_COMPILE" : "NEO_TEST_RUNNER";
|
|
149852
|
-
exitCode = error instanceof NeoTestInterruptedError ? 130 : error instanceof NeoTestUsageError || error instanceof NeoTestReportWriteError || error instanceof NeoTestPreparedCandidateError || diagnosticCode === "NEO_TEST_RUNNER" ? 2 : 1;
|
|
150380
|
+
const diagnosticCode = interrupted || error instanceof NeoTestInterruptedError ? "NEO_TEST_INTERRUPTED" : error instanceof NeoTestPreparedCandidateError ? "NEO_TEST_PREPARED_CANDIDATE" : error instanceof NeoTestUsageError ? "NEO_TEST_USAGE" : error instanceof NeoTestNoTestsError ? "NEO_TEST_NO_TESTS" : error instanceof NeoTestRegistrationError ? "NEO_TEST_REGISTRATION" : phase === "prepare" ? "NEO_TEST_PREPARATION" : phase === "compile" ? "NEO_TEST_COMPILE" : "NEO_TEST_RUNNER";
|
|
150381
|
+
exitCode = interrupted || error instanceof NeoTestInterruptedError ? 130 : error instanceof NeoTestUsageError || error instanceof NeoTestReportWriteError || error instanceof NeoTestPreparedCandidateError || diagnosticCode === "NEO_TEST_RUNNER" ? 2 : 1;
|
|
149853
150382
|
diagnostics.push({
|
|
149854
150383
|
severity: "error",
|
|
149855
150384
|
code: diagnosticCode,
|
|
149856
|
-
message: errorMessage2(error),
|
|
150385
|
+
message: interrupted ? "Neo test was interrupted by SIGINT; partial results were written." : errorMessage2(error),
|
|
149857
150386
|
file: null,
|
|
149858
150387
|
line: null,
|
|
149859
150388
|
column: null,
|
|
@@ -149861,6 +150390,7 @@ async function runTest(workspace, options, dependencies = {}) {
|
|
|
149861
150390
|
});
|
|
149862
150391
|
}
|
|
149863
150392
|
finishPhase();
|
|
150393
|
+
await workerPool?.stop();
|
|
149864
150394
|
dependencies.progress?.stop();
|
|
149865
150395
|
process.off("SIGINT", handleSigint);
|
|
149866
150396
|
const failed = results.filter((result) => result.status === "failed").length;
|
|
@@ -149870,21 +150400,33 @@ async function runTest(workspace, options, dependencies = {}) {
|
|
|
149870
150400
|
);
|
|
149871
150401
|
const skipped = Math.max(0, selectedTestTotal - results.length);
|
|
149872
150402
|
const durationMs = performance.now() - performanceStarted;
|
|
149873
|
-
const startupDurationMs = Math.max(0, durationMs - testDurationMs);
|
|
150403
|
+
const startupDurationMs = parallelExecution ? Math.max(0, durationMs - phaseDurations.execute) : Math.max(0, durationMs - testDurationMs);
|
|
149874
150404
|
const perTestStartupDurationMs = results.reduce(
|
|
149875
150405
|
(sum, result) => sum + result.startupDurationMs,
|
|
149876
150406
|
0
|
|
149877
150407
|
);
|
|
149878
150408
|
const sharedStartupDurationMs = Math.max(
|
|
149879
150409
|
0,
|
|
149880
|
-
startupDurationMs - perTestStartupDurationMs
|
|
150410
|
+
startupDurationMs - (parallelExecution ? 0 : perTestStartupDurationMs)
|
|
149881
150411
|
);
|
|
150412
|
+
const testsByFile = /* @__PURE__ */ new Map();
|
|
150413
|
+
for (const result of results) {
|
|
150414
|
+
const tests = testsByFile.get(result.file) ?? [];
|
|
150415
|
+
tests.push(result);
|
|
150416
|
+
testsByFile.set(result.file, tests);
|
|
150417
|
+
}
|
|
149882
150418
|
const testFiles = specs.map((spec) => {
|
|
149883
|
-
const tests =
|
|
150419
|
+
const tests = testsByFile.get(spec.path) ?? [];
|
|
149884
150420
|
const failures = fileFailuresByPath.get(spec.path) ?? [];
|
|
150421
|
+
let status = "passed";
|
|
150422
|
+
if (tests.some((test) => test.status === "failed") || failures.length > 0) {
|
|
150423
|
+
status = "failed";
|
|
150424
|
+
} else if (tests.length < (selectedTestCountByFile.get(spec.path) ?? 0) && exitCode !== 0) {
|
|
150425
|
+
status = interrupted ? "interrupted" : "failed";
|
|
150426
|
+
}
|
|
149885
150427
|
return {
|
|
149886
150428
|
path: spec.path,
|
|
149887
|
-
status
|
|
150429
|
+
status,
|
|
149888
150430
|
tests,
|
|
149889
150431
|
failures
|
|
149890
150432
|
};
|
|
@@ -149920,6 +150462,7 @@ async function runTest(workspace, options, dependencies = {}) {
|
|
|
149920
150462
|
selectMs: phaseDurations.select,
|
|
149921
150463
|
compileMs: phaseDurations.compile,
|
|
149922
150464
|
registerMs: phaseDurations.register,
|
|
150465
|
+
workerStartupMs: phaseDurations.workers,
|
|
149923
150466
|
executeMs: phaseDurations.execute,
|
|
149924
150467
|
finalizeMs: phaseDurations.finalize
|
|
149925
150468
|
},
|
|
@@ -150001,8 +150544,9 @@ async function runTest(workspace, options, dependencies = {}) {
|
|
|
150001
150544
|
console.log(
|
|
150002
150545
|
` ${color.bold(pad("Tests", 11))} ${formatStatusCounts(report.summary.passed, report.summary.failed, report.summary.tests, report.summary.skipped)}`
|
|
150003
150546
|
);
|
|
150547
|
+
const timingDetail = parallelExecution ? `test work ${formatTestDuration(report.summary.testDurationMs)}, execution ${formatTestDuration(report.timings.executeMs)}, startup ${formatTestDuration(report.summary.startupDurationMs)}` : `test ${formatTestDuration(report.summary.testDurationMs)}, startup ${formatTestDuration(report.summary.startupDurationMs)}`;
|
|
150004
150548
|
console.log(
|
|
150005
|
-
` ${color.bold(pad("Duration", 11))} ${color.bold(`total ${formatTestDuration(report.summary.durationMs)}`)} ${color.dim(`(
|
|
150549
|
+
` ${color.bold(pad("Duration", 11))} ${color.bold(`total ${formatTestDuration(report.summary.durationMs)}`)} ${color.dim(`(${timingDetail})`)}`
|
|
150006
150550
|
);
|
|
150007
150551
|
}
|
|
150008
150552
|
if (!report.success) process.exitCode = exitCode;
|
|
@@ -150032,9 +150576,10 @@ async function inspectNeoTestCompilation(workspace, dependencies = {}) {
|
|
|
150032
150576
|
document
|
|
150033
150577
|
);
|
|
150034
150578
|
const errors = [];
|
|
150579
|
+
const compile = lazySpecCompiler(document);
|
|
150035
150580
|
for (const path of selectedPaths) {
|
|
150036
150581
|
try {
|
|
150037
|
-
compileSpec(workspace,
|
|
150582
|
+
compileSpec(workspace, compile, path, compilationHash);
|
|
150038
150583
|
} catch (error) {
|
|
150039
150584
|
errors.push({
|
|
150040
150585
|
file: relative8(workspace.root, path).split(sep8).join("/"),
|
|
@@ -150053,6 +150598,7 @@ var TEST_BUILD_CACHE_LIMIT_BYTES, ABANDONED_TEMP_MAX_AGE_MS, TEST_CANDIDATE_CACH
|
|
|
150053
150598
|
var init_test = __esm({
|
|
150054
150599
|
"src/commands/test.ts"() {
|
|
150055
150600
|
"use strict";
|
|
150601
|
+
init_test_worker_pool();
|
|
150056
150602
|
init_src();
|
|
150057
150603
|
init_members();
|
|
150058
150604
|
init_neoscript2();
|
|
@@ -155591,6 +156137,11 @@ ${h("Usage")}
|
|
|
155591
156137
|
neo test ${d("[file-or-directory ...]")}
|
|
155592
156138
|
neo test -t ${d('"name pattern"')}
|
|
155593
156139
|
neo test ${d("--reporter=json --outputFile=output.json")}
|
|
156140
|
+
neo test ${d("--maxWorkers=4")}
|
|
156141
|
+
neo test ${d("--runInBand")}
|
|
156142
|
+
|
|
156143
|
+
Files run in parallel, using up to four available CPU workers by default.
|
|
156144
|
+
--maxWorkers overrides neo.json test.maxWorkers; --runInBand runs serially.
|
|
155594
156145
|
|
|
155595
156146
|
Tests execute against the locally compiled candidate graph, including changes
|
|
155596
156147
|
that have not been pushed. Test files are never included in a push.
|
|
@@ -155678,7 +156229,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
|
|
|
155678
156229
|
async function main() {
|
|
155679
156230
|
const args = parseArgs(process.argv.slice(2));
|
|
155680
156231
|
if (args.command === "--version") {
|
|
155681
|
-
console.log("0.62.
|
|
156232
|
+
console.log("0.62.2");
|
|
155682
156233
|
return;
|
|
155683
156234
|
}
|
|
155684
156235
|
if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {
|
|
@@ -156004,6 +156555,11 @@ async function main() {
|
|
|
156004
156555
|
"--testTimeout must be a positive number of milliseconds."
|
|
156005
156556
|
);
|
|
156006
156557
|
}
|
|
156558
|
+
const maxWorkersValue = stringFlag(args, "maxWorkers");
|
|
156559
|
+
const maxWorkers = maxWorkersValue === null ? void 0 : Number(maxWorkersValue);
|
|
156560
|
+
if (maxWorkers !== void 0 && (!Number.isSafeInteger(maxWorkers) || maxWorkers <= 0)) {
|
|
156561
|
+
throw new NeoCliUsageError("--maxWorkers must be a positive integer.");
|
|
156562
|
+
}
|
|
156007
156563
|
const progress = reporterValue === "default" && process.stdout.isTTY === true ? spinner("Reading local workspace\u2026") : null;
|
|
156008
156564
|
try {
|
|
156009
156565
|
const workspace = loadWorkspaceForCommand(args);
|
|
@@ -156016,6 +156572,8 @@ async function main() {
|
|
|
156016
156572
|
reporter: reporterValue,
|
|
156017
156573
|
outputFile: stringFlag(args, "outputFile") ?? stringFlag(args, "output-file"),
|
|
156018
156574
|
passWithNoTests: boolFlag(args, "passWithNoTests"),
|
|
156575
|
+
runInBand: boolFlag(args, "runInBand"),
|
|
156576
|
+
...maxWorkers === void 0 ? {} : { maxWorkers },
|
|
156019
156577
|
...timeoutMs === void 0 ? {} : { timeoutMs }
|
|
156020
156578
|
},
|
|
156021
156579
|
progress === null ? {} : { progress }
|