@cratis/screenplay-language 4.55.0 → 4.55.1
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/dist/bundles/{chunk-GJX4NJYC.js → chunk-LXM5L4YK.js} +825 -768
- package/dist/bundles/chunk-LXM5L4YK.js.map +7 -0
- package/dist/bundles/index.js +5 -47
- package/dist/bundles/index.js.map +3 -3
- package/dist/bundles/sub-languages/projection/index.js +1 -1
- package/dist/symbols.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/bundles/chunk-GJX4NJYC.js.map +0 -7
|
@@ -261,531 +261,50 @@ function nearestEnclosingLine(lines, fences, lineIndex, indent) {
|
|
|
261
261
|
return void 0;
|
|
262
262
|
}
|
|
263
263
|
|
|
264
|
-
//
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
var authorizationContinuation = /^(?:(?:or|and)\s+)?[A-Za-z_(][\p{L}\p{Mn}\p{Nd}\p{Pc}\s()]*$/u;
|
|
285
|
-
var eventReserved = clauseKeywords.filter((keyword) => !["id", "description", "documentation"].includes(keyword));
|
|
286
|
-
var queryParameterPattern = /^\s*(?:by|filter)\s+([a-z_]\w*)\s+([\w.]+(?:\[\])?(?:\?|\s+optional)?)(?:\s+from\s+.+)?\s*$/;
|
|
287
|
-
function propertyTypeReference(property) {
|
|
288
|
-
return property.typeReference ?? typeReferenceSymbol(property.type);
|
|
289
|
-
}
|
|
290
|
-
function propertiesIn(lines, body, reserved3) {
|
|
291
|
-
return body.map((index) => ({ index, match: lines[index].match(propertyPattern) })).filter((entry) => entry.match !== null).filter(({ match }) => match[1].startsWith("@") || match[1] === "as" || !reserved3.includes(match[1])).map(({ index, match }) => ({
|
|
292
|
-
name: match[1].replace(/^@/, ""),
|
|
293
|
-
type: match[2],
|
|
294
|
-
typeReference: typeReferenceSymbol(match[2]),
|
|
295
|
-
isIdentifier: match[3] !== void 0,
|
|
296
|
-
line: index
|
|
297
|
-
}));
|
|
298
|
-
}
|
|
299
|
-
function collectBody(lines, fences, start, indent) {
|
|
300
|
-
const body = [];
|
|
301
|
-
for (let index = start + 1; index < lines.length; index++) {
|
|
302
|
-
if (fences[index]) {
|
|
303
|
-
continue;
|
|
264
|
+
// file-references.ts
|
|
265
|
+
var fileReferenceKeyword = "file";
|
|
266
|
+
var typeReferencePattern = /^[A-Za-z_]\w*(?:\[\])?(?:\?|\s+optional)?$/;
|
|
267
|
+
var absolutePathPattern = /^(?:[/\\]|[A-Za-z]:[/\\]|~[/\\])/;
|
|
268
|
+
function isAbsoluteFileReferencePath(path) {
|
|
269
|
+
return absolutePathPattern.test(path);
|
|
270
|
+
}
|
|
271
|
+
function withoutComment2(text) {
|
|
272
|
+
let inString = false;
|
|
273
|
+
let inTemplate = false;
|
|
274
|
+
for (let index = 0; index < text.length; index++) {
|
|
275
|
+
const current = text[index];
|
|
276
|
+
if (current === "\\" && inString && index + 1 < text.length) {
|
|
277
|
+
index++;
|
|
278
|
+
} else if (current === '"' && !inTemplate) {
|
|
279
|
+
inString = !inString;
|
|
280
|
+
} else if (current === "`" && !inString) {
|
|
281
|
+
inTemplate = !inTemplate;
|
|
282
|
+
} else if (!inString && !inTemplate && current === "/" && text[index + 1] === "/") {
|
|
283
|
+
return text.slice(0, index);
|
|
304
284
|
}
|
|
305
|
-
const line = lines[index];
|
|
306
|
-
if (line.trim().length === 0) continue;
|
|
307
|
-
if (indentOf(line) <= indent) break;
|
|
308
|
-
body.push(index);
|
|
309
285
|
}
|
|
310
|
-
return
|
|
311
|
-
}
|
|
312
|
-
function directBody(lines, fences, start, indent) {
|
|
313
|
-
const body = collectBody(lines, fences, start, indent).filter((index) => !fences[index] && !/^\s*(?:\/\/|#)/.test(lines[index]));
|
|
314
|
-
if (!/^\s*command\b/.test(lines[start])) return body;
|
|
315
|
-
let blockIndent;
|
|
316
|
-
let authorization = false;
|
|
317
|
-
return body.filter((index) => {
|
|
318
|
-
const childIndent = indentOf(lines[index]);
|
|
319
|
-
const text = lines[index].trim();
|
|
320
|
-
if (blockIndent !== void 0 && childIndent > blockIndent && (!authorization || authorizationContinuation.test(text))) return false;
|
|
321
|
-
const property = text !== "validate csharp" && propertiesIn(lines, [index], commandReserved).length > 0;
|
|
322
|
-
const leaf = property || /^description(?:\s|$)/.test(text);
|
|
323
|
-
blockIndent = leaf ? void 0 : childIndent;
|
|
324
|
-
authorization = /^authorize(?:\s|$)/.test(text);
|
|
325
|
-
return true;
|
|
326
|
-
});
|
|
286
|
+
return text;
|
|
327
287
|
}
|
|
328
|
-
function
|
|
329
|
-
const
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
lines = eventAnalysisSource(lines);
|
|
288
|
+
function fileReferenceOn(line, lineIndex) {
|
|
289
|
+
const indent = indentOf(line);
|
|
290
|
+
const content = withoutComment2(line.slice(indent)).trimEnd();
|
|
291
|
+
if (firstWord(content) !== fileReferenceKeyword) return void 0;
|
|
292
|
+
const afterKeyword = content.slice(fileReferenceKeyword.length);
|
|
293
|
+
const path = afterKeyword.trim();
|
|
294
|
+
if (path.length === 0 || typeReferencePattern.test(path)) return void 0;
|
|
295
|
+
const separatorLength = afterKeyword.length - afterKeyword.trimStart().length;
|
|
296
|
+
const startColumn = indent + fileReferenceKeyword.length + separatorLength + 1;
|
|
297
|
+
return { path, line: lineIndex, startColumn, endColumn: startColumn + path.length };
|
|
298
|
+
}
|
|
299
|
+
function fileReferences(lines) {
|
|
341
300
|
const fences = fenceMap(lines);
|
|
342
|
-
const
|
|
343
|
-
const eventFences = fences;
|
|
344
|
-
const eventPropertyLines = lines.map((line) => line.replace(/\s*=(?!=|>).*/, ""));
|
|
301
|
+
const references = [];
|
|
345
302
|
for (let index = 0; index < lines.length; index++) {
|
|
346
303
|
if (fences[index]) continue;
|
|
347
|
-
const
|
|
348
|
-
|
|
349
|
-
const indent = indentOf(line);
|
|
350
|
-
const importMatch = eventLines[index].trim().match(/^import\s+([\w.]+)\s*$/);
|
|
351
|
-
if (importMatch && indent === 0) {
|
|
352
|
-
const qualifiedName = importMatch[1];
|
|
353
|
-
const shortName = qualifiedName.split(".").pop() ?? qualifiedName;
|
|
354
|
-
symbols.imports.push({ qualifiedName, shortName, line: index });
|
|
355
|
-
continue;
|
|
356
|
-
}
|
|
357
|
-
const conceptMatch = trimmed.match(conceptPattern);
|
|
358
|
-
if (conceptMatch) {
|
|
359
|
-
const body = collectBody(lines, fences, index, indent).map((i) => lines[i].trim());
|
|
360
|
-
const attributeReasons = {};
|
|
361
|
-
for (const line2 of body) {
|
|
362
|
-
const reason = line2.match(attributeReasonPattern);
|
|
363
|
-
if (reason && attributeReasons[reason[1]] === void 0) {
|
|
364
|
-
attributeReasons[reason[1]] = reason[2];
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
const enumValues = conceptMatch[2] === "Enum" ? body.filter((line2) => !attributeReasonPattern.test(line2)) : [];
|
|
368
|
-
symbols.concepts.push({
|
|
369
|
-
name: conceptMatch[1],
|
|
370
|
-
primitive: conceptMatch[2],
|
|
371
|
-
attributes: conceptMatch[3].trim().split(/\s+/).filter(Boolean),
|
|
372
|
-
attributeReasons,
|
|
373
|
-
enumValues,
|
|
374
|
-
line: index
|
|
375
|
-
});
|
|
376
|
-
continue;
|
|
377
|
-
}
|
|
378
|
-
const typeMatch = trimmed.match(/^type\s+(\w+)\s*$/);
|
|
379
|
-
if (typeMatch) {
|
|
380
|
-
symbols.types.push({
|
|
381
|
-
name: typeMatch[1],
|
|
382
|
-
properties: propertiesIn(lines, collectBody(lines, fences, index, indent), clauseKeywords),
|
|
383
|
-
line: index
|
|
384
|
-
});
|
|
385
|
-
continue;
|
|
386
|
-
}
|
|
387
|
-
const policyMatch = trimmed.match(/^policy\s+(\w+)\s*$/);
|
|
388
|
-
if (policyMatch) {
|
|
389
|
-
const requires = collectBody(lines, fences, index, indent).filter((i) => !fences[i]).map((i) => lines[i].trim());
|
|
390
|
-
symbols.policies.push({ name: policyMatch[1], requires, line: index });
|
|
391
|
-
continue;
|
|
392
|
-
}
|
|
393
|
-
const eventMatch = eventLines[index].trim().match(/^(?:produces\s+)?event\s+(\w+)(?:\s+generation\s+(\d+))?\s*$/);
|
|
394
|
-
if (eventMatch) {
|
|
395
|
-
symbols.events.push({
|
|
396
|
-
name: eventMatch[1],
|
|
397
|
-
...eventMatch[2] ? { generation: Number(eventMatch[2]) } : {},
|
|
398
|
-
inline: trimmed.startsWith("produces "),
|
|
399
|
-
properties: propertiesIn(
|
|
400
|
-
trimmed.startsWith("produces ") ? eventPropertyLines : eventLines,
|
|
401
|
-
directBody(eventLines, eventFences, index, indent),
|
|
402
|
-
eventReserved
|
|
403
|
-
),
|
|
404
|
-
line: index
|
|
405
|
-
});
|
|
406
|
-
continue;
|
|
407
|
-
}
|
|
408
|
-
const commandMatch = eventLines[index].trim().match(/^command\s+(\w+)\s*$/);
|
|
409
|
-
if (commandMatch) {
|
|
410
|
-
const body = directBody(lines, fences, index, indent);
|
|
411
|
-
const productionHeaders = body.filter((line2) => /^\s*produces\b/.test(lines[line2]));
|
|
412
|
-
symbols.commands.push({
|
|
413
|
-
name: commandMatch[1],
|
|
414
|
-
properties: propertiesIn(lines, body.filter((line2) => lines[line2].trim() !== "validate csharp"), commandReserved),
|
|
415
|
-
productionHeaders,
|
|
416
|
-
produces: productionHeaders.flatMap((line2) => {
|
|
417
|
-
const header10 = eventLines[line2].trim();
|
|
418
|
-
const inline = /^produces\s+event\b/.test(header10);
|
|
419
|
-
const conditional2 = /^produces\s+when\b/.test(header10);
|
|
420
|
-
const eventLine = conditional2 ? directBody(eventLines, eventFences, line2, indentOf(eventLines[line2]))[0] : line2;
|
|
421
|
-
if (eventLine === void 0) return [];
|
|
422
|
-
const name = conditional2 ? eventLines[eventLine].trim() : header10.match(inline ? /^produces\s+event\s+([A-Za-z_]\w*)(?:\s+generation\s+\d+)?\s*$/ : /^produces\s+([A-Z]\w*)\s*$/)?.[1];
|
|
423
|
-
if (name === void 0 || !/^[A-Za-z_]\w*$/.test(name)) return [];
|
|
424
|
-
const children = directBody(eventLines, eventFences, eventLine, indentOf(eventLines[eventLine]));
|
|
425
|
-
const targets = children.map((index2) => eventLines[index2].trim().match(/^for(?:\s+(.*))?$/)).filter((match) => match !== null);
|
|
426
|
-
const target = targets.length === 0 ? void 0 : targets.length === 1 ? targets[0][1] ?? "" : "";
|
|
427
|
-
const mappings = children.flatMap((index2) => {
|
|
428
|
-
const match = eventLines[index2].trim().match(inline ? /^(@?[a-z_]\w*)\s+[\w.]+(?:\[\])?(?:\?|\s+optional)?\s*=(?!=|>)\s*(.+)$/ : /^(@?[\w.]+)\s*=(?!=|>)\s*(.+)$/);
|
|
429
|
-
return match === null ? [] : [{ name: match[1].replace(/^@/, ""), source: match[2], line: index2 }];
|
|
430
|
-
});
|
|
431
|
-
return [{ name, inline, conditional: conditional2, line: line2, target, mappings }];
|
|
432
|
-
}),
|
|
433
|
-
reads: body.filter((line2) => !fences[line2]).map((line2) => ({ line: line2, match: lines[line2].match(readPattern) })).filter((entry) => entry.match !== null).map(({ line: line2, match }) => ({
|
|
434
|
-
view: match[1],
|
|
435
|
-
...match[2] ? { alias: match[2] } : {},
|
|
436
|
-
...match[3] ? { by: match[3] } : {},
|
|
437
|
-
line: line2
|
|
438
|
-
})),
|
|
439
|
-
line: index
|
|
440
|
-
});
|
|
441
|
-
continue;
|
|
442
|
-
}
|
|
443
|
-
const queryMatch = trimmed.match(/^query\s+(\w+)\s*=>\s*(?:observable\s+)?([\w.]+(?:\[\])?(?:\?|\s+optional)?)\s*$/);
|
|
444
|
-
if (queryMatch) {
|
|
445
|
-
const parameters = collectBody(lines, fences, index, indent).map((i) => ({ index: i, match: lines[i].match(queryParameterPattern) })).filter(
|
|
446
|
-
(entry) => entry.match !== null
|
|
447
|
-
).map(({ index: line2, match }) => ({
|
|
448
|
-
name: match[1],
|
|
449
|
-
type: match[2],
|
|
450
|
-
typeReference: typeReferenceSymbol(match[2]),
|
|
451
|
-
isIdentifier: false,
|
|
452
|
-
line: line2
|
|
453
|
-
}));
|
|
454
|
-
symbols.queries.push({
|
|
455
|
-
name: queryMatch[1],
|
|
456
|
-
returnType: queryMatch[2],
|
|
457
|
-
returnTypeReference: typeReferenceSymbol(queryMatch[2]),
|
|
458
|
-
parameters,
|
|
459
|
-
line: index
|
|
460
|
-
});
|
|
461
|
-
continue;
|
|
462
|
-
}
|
|
463
|
-
const screenMatch = trimmed.match(/^screen\s+(\w+)\s*$/);
|
|
464
|
-
if (screenMatch) {
|
|
465
|
-
symbols.screens.push({ name: screenMatch[1], line: index });
|
|
466
|
-
continue;
|
|
467
|
-
}
|
|
468
|
-
const triggerMatch = trimmed.match(/^trigger\s+(\w+)\s*$/);
|
|
469
|
-
if (triggerMatch && indent === 0) {
|
|
470
|
-
symbols.triggers.push({ name: triggerMatch[1], line: index });
|
|
471
|
-
}
|
|
304
|
+
const reference = fileReferenceOn(lines[index], index);
|
|
305
|
+
if (reference) references.push(reference);
|
|
472
306
|
}
|
|
473
|
-
return
|
|
474
|
-
}
|
|
475
|
-
function mergeSymbols(...documents) {
|
|
476
|
-
return {
|
|
477
|
-
imports: documents.flatMap((document) => document.imports),
|
|
478
|
-
concepts: documents.flatMap((document) => document.concepts),
|
|
479
|
-
types: documents.flatMap((document) => document.types),
|
|
480
|
-
policies: documents.flatMap((document) => document.policies),
|
|
481
|
-
events: documents.flatMap((document) => document.events),
|
|
482
|
-
commands: documents.flatMap((document) => document.commands),
|
|
483
|
-
queries: documents.flatMap((document) => document.queries),
|
|
484
|
-
screens: documents.flatMap((document) => document.screens),
|
|
485
|
-
triggers: documents.flatMap((document) => document.triggers)
|
|
486
|
-
};
|
|
487
|
-
}
|
|
488
|
-
function knownEventNames(symbols) {
|
|
489
|
-
return [
|
|
490
|
-
...symbols.events.map((event) => event.name),
|
|
491
|
-
...symbols.imports.map((imported) => imported.shortName)
|
|
492
|
-
];
|
|
493
|
-
}
|
|
494
|
-
var builtInTriggerNames = ["Startup", "Shutdown"];
|
|
495
|
-
function knownTriggerNames(symbols) {
|
|
496
|
-
return [
|
|
497
|
-
...knownEventNames(symbols),
|
|
498
|
-
...symbols.triggers.map((trigger) => trigger.name),
|
|
499
|
-
...builtInTriggerNames
|
|
500
|
-
];
|
|
501
|
-
}
|
|
502
|
-
function knownTypeNames(symbols, primitives) {
|
|
503
|
-
return [
|
|
504
|
-
...primitives,
|
|
505
|
-
...symbols.concepts.map((concept) => concept.name),
|
|
506
|
-
...symbols.types.map((type) => type.name),
|
|
507
|
-
...symbols.imports.map((imported) => imported.shortName)
|
|
508
|
-
];
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
// event-context-catalog.ts
|
|
512
|
-
var eventContextRootType = "EventContext";
|
|
513
|
-
var eventContextTypes = {
|
|
514
|
-
"EventContext": [
|
|
515
|
-
{ name: "eventType", type: "EventType", kind: "composite", description: "The type of the event - its identifier, generation and whether it is a tombstone." },
|
|
516
|
-
{ name: "eventSourceType", type: "EventSourceType", kind: "value", description: "The type of the event source the event was appended to." },
|
|
517
|
-
{ name: "eventSourceId", type: "EventSourceId", kind: "value", description: "The identifier of the event source the event was appended to - the value $eventSourceId resolves." },
|
|
518
|
-
{ name: "eventStreamType", type: "EventStreamType", kind: "value", description: "The type of the event stream the event belongs to." },
|
|
519
|
-
{ name: "eventStreamId", type: "EventStreamId", kind: "value", description: "The identifier of the event stream the event belongs to." },
|
|
520
|
-
{ name: "sequenceNumber", type: "EventSequenceNumber", kind: "value", description: "The position of the event in its event sequence." },
|
|
521
|
-
{ name: "occurred", type: "DateTimeOffset", kind: "value", description: "When the event occurred - the time it was appended unless one was given." },
|
|
522
|
-
{ name: "eventStore", type: "EventStoreName", kind: "value", description: "The name of the event store the event belongs to." },
|
|
523
|
-
{ name: "namespace", type: "EventStoreNamespaceName", kind: "value", description: "The namespace within the event store the event belongs to." },
|
|
524
|
-
{ name: "correlationId", type: "CorrelationId", kind: "value", description: "The correlation identifier the event was appended with." },
|
|
525
|
-
{ name: "causation", type: "IEnumerable<Causation>", kind: "collection", description: "The chain of causes that led to the event - a collection, not addressable below." },
|
|
526
|
-
{ name: "causedBy", type: "Identity", kind: "composite", description: "The identity that caused the event." },
|
|
527
|
-
{ name: "tags", type: "IEnumerable<Tag>", kind: "collection", description: "The tags the event was appended with - a collection, not addressable below." },
|
|
528
|
-
{ name: "hash", type: "EventHash", kind: "value", description: "The hash of the event content." },
|
|
529
|
-
{ name: "observationState", type: "EventObservationState", kind: "value", description: "Whether the observer sees the event for the first time or again on replay - differs between live processing and replay." },
|
|
530
|
-
{ name: "subject", type: "Subject", kind: "value", description: "The compliance subject the event is about - the event source identifier unless one was given." },
|
|
531
|
-
{ name: "subjectIsEventSourceId", type: "bool", kind: "value", description: "Whether the subject is the event source identifier." }
|
|
532
|
-
],
|
|
533
|
-
"EventType": [
|
|
534
|
-
{ name: "id", type: "EventTypeId", kind: "value", description: "The identifier of the event type." },
|
|
535
|
-
{ name: "generation", type: "EventTypeGeneration", kind: "value", description: "The generation of the event type." },
|
|
536
|
-
{ name: "tombstone", type: "bool", kind: "value", description: "Whether the event is a tombstone event." }
|
|
537
|
-
],
|
|
538
|
-
"EventSourceType": [
|
|
539
|
-
{ name: "value", type: "string", kind: "value", description: "The underlying string value." }
|
|
540
|
-
],
|
|
541
|
-
"EventSourceId": [
|
|
542
|
-
{ name: "value", type: "string", kind: "value", description: "The underlying string value." }
|
|
543
|
-
],
|
|
544
|
-
"EventStreamType": [
|
|
545
|
-
{ name: "value", type: "string", kind: "value", description: "The underlying string value." }
|
|
546
|
-
],
|
|
547
|
-
"EventStreamId": [
|
|
548
|
-
{ name: "value", type: "string", kind: "value", description: "The underlying string value." }
|
|
549
|
-
],
|
|
550
|
-
"EventSequenceNumber": [
|
|
551
|
-
{ name: "value", type: "ulong", kind: "value", description: "The underlying ulong value." }
|
|
552
|
-
],
|
|
553
|
-
"DateTimeOffset": [
|
|
554
|
-
{ name: "Week", type: "int", kind: "function", description: "The ISO 8601 week of the year the value falls in." }
|
|
555
|
-
],
|
|
556
|
-
"EventStoreName": [
|
|
557
|
-
{ name: "value", type: "string", kind: "value", description: "The underlying string value." }
|
|
558
|
-
],
|
|
559
|
-
"EventStoreNamespaceName": [
|
|
560
|
-
{ name: "value", type: "string", kind: "value", description: "The underlying string value." }
|
|
561
|
-
],
|
|
562
|
-
"CorrelationId": [
|
|
563
|
-
{ name: "value", type: "Guid", kind: "value", description: "The underlying Guid value." }
|
|
564
|
-
],
|
|
565
|
-
"Identity": [
|
|
566
|
-
{ name: "subject", type: "string", kind: "value", description: "The subject identifier of the identity." },
|
|
567
|
-
{ name: "name", type: "string", kind: "value", description: "The display name of the identity." },
|
|
568
|
-
{ name: "userName", type: "string", kind: "value", description: "The user name of the identity." },
|
|
569
|
-
{ name: "onBehalfOf", type: "Identity", kind: "composite", description: "The identity this identity acted on behalf of, if any - an identity with the same members." }
|
|
570
|
-
],
|
|
571
|
-
"EventHash": [
|
|
572
|
-
{ name: "value", type: "string", kind: "value", description: "The underlying string value." }
|
|
573
|
-
],
|
|
574
|
-
"Subject": [
|
|
575
|
-
{ name: "value", type: "string", kind: "value", description: "The underlying string value." }
|
|
576
|
-
],
|
|
577
|
-
"EventTypeId": [
|
|
578
|
-
{ name: "value", type: "string", kind: "value", description: "The underlying string value." }
|
|
579
|
-
],
|
|
580
|
-
"EventTypeGeneration": [
|
|
581
|
-
{ name: "value", type: "uint", kind: "value", description: "The underlying uint value." }
|
|
582
|
-
]
|
|
583
|
-
};
|
|
584
|
-
var eventContextPaths = [
|
|
585
|
-
{ path: "eventType", name: "eventType", type: "EventType", kind: "composite", description: "The type of the event - its identifier, generation and whether it is a tombstone." },
|
|
586
|
-
{ path: "eventType.id", name: "id", type: "EventTypeId", kind: "value", description: "The identifier of the event type." },
|
|
587
|
-
{ path: "eventType.id.value", name: "value", type: "string", kind: "value", description: "The underlying string value." },
|
|
588
|
-
{ path: "eventType.generation", name: "generation", type: "EventTypeGeneration", kind: "value", description: "The generation of the event type." },
|
|
589
|
-
{ path: "eventType.generation.value", name: "value", type: "uint", kind: "value", description: "The underlying uint value." },
|
|
590
|
-
{ path: "eventType.tombstone", name: "tombstone", type: "bool", kind: "value", description: "Whether the event is a tombstone event." },
|
|
591
|
-
{ path: "eventSourceType", name: "eventSourceType", type: "EventSourceType", kind: "value", description: "The type of the event source the event was appended to." },
|
|
592
|
-
{ path: "eventSourceType.value", name: "value", type: "string", kind: "value", description: "The underlying string value." },
|
|
593
|
-
{ path: "eventSourceId", name: "eventSourceId", type: "EventSourceId", kind: "value", description: "The identifier of the event source the event was appended to - the value $eventSourceId resolves." },
|
|
594
|
-
{ path: "eventSourceId.value", name: "value", type: "string", kind: "value", description: "The underlying string value." },
|
|
595
|
-
{ path: "eventStreamType", name: "eventStreamType", type: "EventStreamType", kind: "value", description: "The type of the event stream the event belongs to." },
|
|
596
|
-
{ path: "eventStreamType.value", name: "value", type: "string", kind: "value", description: "The underlying string value." },
|
|
597
|
-
{ path: "eventStreamId", name: "eventStreamId", type: "EventStreamId", kind: "value", description: "The identifier of the event stream the event belongs to." },
|
|
598
|
-
{ path: "eventStreamId.value", name: "value", type: "string", kind: "value", description: "The underlying string value." },
|
|
599
|
-
{ path: "sequenceNumber", name: "sequenceNumber", type: "EventSequenceNumber", kind: "value", description: "The position of the event in its event sequence." },
|
|
600
|
-
{ path: "sequenceNumber.value", name: "value", type: "ulong", kind: "value", description: "The underlying ulong value." },
|
|
601
|
-
{ path: "occurred", name: "occurred", type: "DateTimeOffset", kind: "value", description: "When the event occurred - the time it was appended unless one was given." },
|
|
602
|
-
{ path: "occurred.Week", name: "Week", type: "int", kind: "function", description: "The ISO 8601 week of the year the value falls in." },
|
|
603
|
-
{ path: "eventStore", name: "eventStore", type: "EventStoreName", kind: "value", description: "The name of the event store the event belongs to." },
|
|
604
|
-
{ path: "eventStore.value", name: "value", type: "string", kind: "value", description: "The underlying string value." },
|
|
605
|
-
{ path: "namespace", name: "namespace", type: "EventStoreNamespaceName", kind: "value", description: "The namespace within the event store the event belongs to." },
|
|
606
|
-
{ path: "namespace.value", name: "value", type: "string", kind: "value", description: "The underlying string value." },
|
|
607
|
-
{ path: "correlationId", name: "correlationId", type: "CorrelationId", kind: "value", description: "The correlation identifier the event was appended with." },
|
|
608
|
-
{ path: "correlationId.value", name: "value", type: "Guid", kind: "value", description: "The underlying Guid value." },
|
|
609
|
-
{ path: "causation", name: "causation", type: "IEnumerable<Causation>", kind: "collection", description: "The chain of causes that led to the event - a collection, not addressable below." },
|
|
610
|
-
{ path: "causedBy", name: "causedBy", type: "Identity", kind: "composite", description: "The identity that caused the event." },
|
|
611
|
-
{ path: "causedBy.subject", name: "subject", type: "string", kind: "value", description: "The subject identifier of the identity." },
|
|
612
|
-
{ path: "causedBy.name", name: "name", type: "string", kind: "value", description: "The display name of the identity." },
|
|
613
|
-
{ path: "causedBy.userName", name: "userName", type: "string", kind: "value", description: "The user name of the identity." },
|
|
614
|
-
{ path: "causedBy.onBehalfOf", name: "onBehalfOf", type: "Identity", kind: "composite", description: "The identity this identity acted on behalf of, if any - an identity with the same members." },
|
|
615
|
-
{ path: "tags", name: "tags", type: "IEnumerable<Tag>", kind: "collection", description: "The tags the event was appended with - a collection, not addressable below." },
|
|
616
|
-
{ path: "hash", name: "hash", type: "EventHash", kind: "value", description: "The hash of the event content." },
|
|
617
|
-
{ path: "hash.value", name: "value", type: "string", kind: "value", description: "The underlying string value." },
|
|
618
|
-
{ path: "observationState", name: "observationState", type: "EventObservationState", kind: "value", description: "Whether the observer sees the event for the first time or again on replay - differs between live processing and replay." },
|
|
619
|
-
{ path: "subject", name: "subject", type: "Subject", kind: "value", description: "The compliance subject the event is about - the event source identifier unless one was given." },
|
|
620
|
-
{ path: "subject.value", name: "value", type: "string", kind: "value", description: "The underlying string value." },
|
|
621
|
-
{ path: "subjectIsEventSourceId", name: "subjectIsEventSourceId", type: "bool", kind: "value", description: "Whether the subject is the event source identifier." }
|
|
622
|
-
];
|
|
623
|
-
|
|
624
|
-
// event-context.ts
|
|
625
|
-
function namesEventContextMember(member, segment) {
|
|
626
|
-
if (member.kind === "function") {
|
|
627
|
-
return segment === member.name || segment === `${member.name}()`;
|
|
628
|
-
}
|
|
629
|
-
const declared = member.name[0].toUpperCase() + member.name.slice(1);
|
|
630
|
-
return segment === declared || segment.length > 0 && segment[0].toUpperCase() + segment.slice(1) === declared;
|
|
631
|
-
}
|
|
632
|
-
var eventContextMembers = eventContextTypes[eventContextRootType];
|
|
633
|
-
function eventContextMembersAfter(segments) {
|
|
634
|
-
let members = eventContextMembers;
|
|
635
|
-
for (const segment of segments) {
|
|
636
|
-
const member = members.find((candidate) => namesEventContextMember(candidate, segment));
|
|
637
|
-
if (!member || member.kind === "collection" || member.kind === "function") {
|
|
638
|
-
return void 0;
|
|
639
|
-
}
|
|
640
|
-
members = eventContextTypes[member.type] ?? [];
|
|
641
|
-
}
|
|
642
|
-
return members;
|
|
643
|
-
}
|
|
644
|
-
function eventContextMemberAt(segments) {
|
|
645
|
-
if (segments.length === 0) {
|
|
646
|
-
return void 0;
|
|
647
|
-
}
|
|
648
|
-
const members = eventContextMembersAfter(segments.slice(0, -1));
|
|
649
|
-
return members?.find((member) => namesEventContextMember(member, segments[segments.length - 1]));
|
|
650
|
-
}
|
|
651
|
-
function resolveEventContextPath(path) {
|
|
652
|
-
let current;
|
|
653
|
-
let expected = eventContextMembers;
|
|
654
|
-
for (const segment of path.split(".")) {
|
|
655
|
-
if (segment.length === 0) {
|
|
656
|
-
return { status: "missing", member: current, expected };
|
|
657
|
-
}
|
|
658
|
-
if (current?.kind === "collection") {
|
|
659
|
-
return { status: "belowCollection", member: current, segment, expected: [] };
|
|
660
|
-
}
|
|
661
|
-
const next = expected.find((member) => namesEventContextMember(member, segment));
|
|
662
|
-
if (!next) {
|
|
663
|
-
return { status: current ? "unknownSubPath" : "unknownMember", member: current, segment, expected };
|
|
664
|
-
}
|
|
665
|
-
current = next;
|
|
666
|
-
expected = next.kind === "function" ? [] : eventContextTypes[next.type] ?? [];
|
|
667
|
-
}
|
|
668
|
-
return { status: "known", member: current, expected: [] };
|
|
669
|
-
}
|
|
670
|
-
function describeEventContext() {
|
|
671
|
-
return [
|
|
672
|
-
"**$eventContext**",
|
|
673
|
-
"",
|
|
674
|
-
"Metadata about the event being projected. Paths are checked against the event-context catalog; `causation` and `tags` are collections and cannot be addressed below.",
|
|
675
|
-
"",
|
|
676
|
-
"**Members:**",
|
|
677
|
-
...eventContextMembers.map((member) => `- \`${member.name}\` (${member.type}) - ${member.description}`)
|
|
678
|
-
].join("\n");
|
|
679
|
-
}
|
|
680
|
-
function describeEventContextMember(path, member) {
|
|
681
|
-
const below = member.kind === "collection" || member.kind === "function" ? [] : eventContextTypes[member.type] ?? [];
|
|
682
|
-
const lines = [`**$eventContext.${path}**: \`${member.type}\``, "", member.description];
|
|
683
|
-
if (below.length > 0) {
|
|
684
|
-
lines.push("", `**Members:** ${below.map((child) => `\`${child.name}\``).join(", ")}`);
|
|
685
|
-
}
|
|
686
|
-
return lines.join("\n");
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
// production-destinations.ts
|
|
690
|
-
function productionDestinations(command) {
|
|
691
|
-
const identifiers = command.properties.filter((property) => property.isIdentifier && !propertyTypeReference(property).isOptional && !propertyTypeReference(property).isCollection);
|
|
692
|
-
const identifier = identifiers.length === 1 ? identifiers[0].name : void 0;
|
|
693
|
-
const productions = command.produces ?? [];
|
|
694
|
-
const mixed = productions.some((production) => production.target !== void 0 && production.target !== identifier) || productions.some((production) => production.inline && production.target === void 0) && productions.some((production) => !production.inline && production.target === void 0);
|
|
695
|
-
return { identifier, mixed };
|
|
696
|
-
}
|
|
697
|
-
function destinationHints(lines) {
|
|
698
|
-
const source = eventAnalysisSource(lines);
|
|
699
|
-
return scanDocument(source).commands.flatMap((command) => {
|
|
700
|
-
const { identifier, mixed } = productionDestinations(command);
|
|
701
|
-
if (mixed || command.productionHeaders?.length !== command.produces?.length) return [];
|
|
702
|
-
const hasPromotedDestination = command.produces?.some((sibling) => sibling.target !== void 0 || sibling.inline);
|
|
703
|
-
return (command.produces ?? []).flatMap((production) => {
|
|
704
|
-
if (production.target !== void 0 || production.inline && (identifier === void 0 || /\bgeneration\b/.test(source[production.line]))) return [];
|
|
705
|
-
if (!production.inline && hasPromotedDestination) return [];
|
|
706
|
-
return [{ line: production.line, column: source[production.line].length + 1, label: production.inline ? `for ${identifier}` : "for <new event source>" }];
|
|
707
|
-
});
|
|
708
|
-
});
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
// diagnostic-codes.ts
|
|
712
|
-
var diagnosticCodes = {
|
|
713
|
-
eventSourceIdInPayload: "PLAY0469",
|
|
714
|
-
explicitProducesTargetsRequired: "PLAY0470",
|
|
715
|
-
redundantEventId: "PLAY0471",
|
|
716
|
-
invalidEventId: "PLAY0472",
|
|
717
|
-
inlineEventCollision: "PLAY0473",
|
|
718
|
-
inlineEventOutsideCommand: "PLAY0474",
|
|
719
|
-
inlineEventGeneration: "PLAY0475",
|
|
720
|
-
reservedProductionMetadata: "PLAY0476",
|
|
721
|
-
invalidEventDocumentation: "PLAY0477",
|
|
722
|
-
tabIndentation: "PLAY0006",
|
|
723
|
-
unknownPrimitiveType: "PLAY0008",
|
|
724
|
-
unknownSliceType: "PLAY0028",
|
|
725
|
-
duplicateCommandIdentifier: "PLAY0036",
|
|
726
|
-
unknownContextPath: "PLAY0153",
|
|
727
|
-
unknownContextCausedByProperty: "PLAY0154",
|
|
728
|
-
unknownContextIdentityProperty: "PLAY0155",
|
|
729
|
-
unclosedCodeBlock: "PLAY0164",
|
|
730
|
-
unknownType: "PLAY0165",
|
|
731
|
-
unknownEvent: "PLAY0166",
|
|
732
|
-
unknownPolicy: "PLAY0167",
|
|
733
|
-
duplicateDeclaration: "PLAY0168",
|
|
734
|
-
unknownEventContextMember: "PLAY0295",
|
|
735
|
-
unknownEventContextPath: "PLAY0296",
|
|
736
|
-
eventContextPathBelowCollection: "PLAY0297",
|
|
737
|
-
missingEventContextPath: "PLAY0298",
|
|
738
|
-
unresolvedDynamicKeySource: "PLAY0299",
|
|
739
|
-
invalidFileImport: "PLAY0454",
|
|
740
|
-
omittedProductionDestination: "PLAY0478",
|
|
741
|
-
legacyOptionalSuffix: "PLAY0479",
|
|
742
|
-
invalidOptionalModifierOrder: "PLAY0480",
|
|
743
|
-
optionalReadsNotSupported: "PLAY0481"
|
|
744
|
-
};
|
|
745
|
-
|
|
746
|
-
// file-imports.ts
|
|
747
|
-
var fileImportPattern = /^import(\s+)"([^"\\]+)"\s*(?:\/\/.*)?$/;
|
|
748
|
-
var quotedImportPattern = /^import\s+"/;
|
|
749
|
-
function isFileImportLine(line) {
|
|
750
|
-
return quotedImportPattern.test(line.trim());
|
|
751
|
-
}
|
|
752
|
-
function fileImportOn(line, lineIndex) {
|
|
753
|
-
const indent = indentOf(line);
|
|
754
|
-
const match = line.slice(indent).match(fileImportPattern);
|
|
755
|
-
if (!match) return void 0;
|
|
756
|
-
const startColumn = indent + "import".length + match[1].length + 2;
|
|
757
|
-
return { pattern: match[2], line: lineIndex, startColumn, endColumn: startColumn + match[2].length };
|
|
758
|
-
}
|
|
759
|
-
function fileImports(lines) {
|
|
760
|
-
const fences = fenceMap(lines);
|
|
761
|
-
const found = [];
|
|
762
|
-
for (let index = 0; index < lines.length; index++) {
|
|
763
|
-
if (fences[index]) continue;
|
|
764
|
-
const fileImport = fileImportOn(lines[index], index);
|
|
765
|
-
if (fileImport) found.push(fileImport);
|
|
766
|
-
}
|
|
767
|
-
return found;
|
|
768
|
-
}
|
|
769
|
-
var folderOf = (path) => path.split("/").slice(0, -1);
|
|
770
|
-
function relativeTo(from, path) {
|
|
771
|
-
const segments = path.split("/");
|
|
772
|
-
let common = 0;
|
|
773
|
-
while (common < from.length && common < segments.length - 1 && from[common] === segments[common]) common++;
|
|
774
|
-
return [...from.slice(common).map(() => ".."), ...segments.slice(common)].join("/");
|
|
775
|
-
}
|
|
776
|
-
function importablePaths(documentPath, files) {
|
|
777
|
-
const from = folderOf(documentPath);
|
|
778
|
-
const paths = /* @__PURE__ */ new Set();
|
|
779
|
-
for (const file of files.filter((candidate) => candidate !== documentPath && candidate.toLowerCase().endsWith(".play"))) {
|
|
780
|
-
const relative = relativeTo(from, file);
|
|
781
|
-
const folders = folderOf(relative);
|
|
782
|
-
paths.add(relative);
|
|
783
|
-
paths.add([...folders, "*.play"].join("/"));
|
|
784
|
-
for (let depth = 0; depth <= folders.length; depth++) {
|
|
785
|
-
paths.add([...folders.slice(0, depth), "**", "*.play"].join("/"));
|
|
786
|
-
}
|
|
787
|
-
}
|
|
788
|
-
return [...paths].sort();
|
|
307
|
+
return references;
|
|
789
308
|
}
|
|
790
309
|
|
|
791
310
|
// ../../Compiler/dist/Diagnostics/DiagnosticCodes.js
|
|
@@ -1221,11 +740,11 @@ function keep(context, line, existing, owner, description) {
|
|
|
1221
740
|
}
|
|
1222
741
|
|
|
1223
742
|
// ../../Compiler/dist/Parsing/FileImportParser.js
|
|
1224
|
-
var
|
|
743
|
+
var fileImportPattern = pattern('^import\\s+"([^"\\\\]+)"$');
|
|
1225
744
|
var quotedPattern = pattern('^import\\s+"');
|
|
1226
745
|
var isFileImport = (content) => quotedPattern.test(content);
|
|
1227
746
|
function tryParseFileImport(line) {
|
|
1228
|
-
const match =
|
|
747
|
+
const match = fileImportPattern.exec(line.content);
|
|
1229
748
|
return match === null ? void 0 : { kind: "FileImportSyntax", pattern: match[1], location: locationOf(line) };
|
|
1230
749
|
}
|
|
1231
750
|
function parseFileImport(context, line, imports) {
|
|
@@ -1560,6 +1079,9 @@ function parseLiteral(text, location) {
|
|
|
1560
1079
|
return void 0;
|
|
1561
1080
|
}
|
|
1562
1081
|
|
|
1082
|
+
// ../../Compiler/dist/Text/ReservedWords.js
|
|
1083
|
+
var eventBodyReservedWords = ["tag"];
|
|
1084
|
+
|
|
1563
1085
|
// ../../Compiler/dist/Parsing/EventMetadataParser.js
|
|
1564
1086
|
var idPattern = pattern(`^id\\s+"(${stringBodyPattern})"$`);
|
|
1565
1087
|
var EventMetadataParser = class {
|
|
@@ -1608,16 +1130,16 @@ var EventMetadataParser = class {
|
|
|
1608
1130
|
};
|
|
1609
1131
|
|
|
1610
1132
|
// ../../Compiler/dist/Parsing/FileReferences.js
|
|
1611
|
-
var
|
|
1133
|
+
var typeReferencePattern2 = pattern("^[A-Za-z_]\\w*(?:\\[\\])?(?:\\?|\\s+optional)?$");
|
|
1612
1134
|
var pathOf = (line) => firstWord2(line.content) === "file" ? line.content.substring("file".length).trim() : "";
|
|
1613
1135
|
var isFileDirective = (line) => pathOf(line).length > 0;
|
|
1614
|
-
var isFileDirectiveAmongProperties = (line) => isFileDirective(line) && !
|
|
1136
|
+
var isFileDirectiveAmongProperties = (line) => isFileDirective(line) && !typeReferencePattern2.test(pathOf(line));
|
|
1615
1137
|
|
|
1616
1138
|
// ../../Compiler/dist/Parsing/PropertyLineParser.js
|
|
1617
|
-
var
|
|
1139
|
+
var propertyPattern = pattern("^(@?[a-z_]\\w*)\\s+([\\w.]+(?:\\[\\])?(?:\\?|\\s+optional)?)(?:\\s+(identifier))?$");
|
|
1618
1140
|
var reversedModifiers = pattern("^@?[a-z_]\\w*\\s+[\\w.]+(?:\\[\\])?\\s+identifier\\s+optional(?:\\s*=.*)?$");
|
|
1619
1141
|
function tryParseProperty(line) {
|
|
1620
|
-
const match =
|
|
1142
|
+
const match = propertyPattern.exec(line.content);
|
|
1621
1143
|
if (match === null) {
|
|
1622
1144
|
return void 0;
|
|
1623
1145
|
}
|
|
@@ -1733,7 +1255,7 @@ function parseEvent(context, header10) {
|
|
|
1733
1255
|
if (isFileDirectiveAmongProperties(line)) {
|
|
1734
1256
|
continue;
|
|
1735
1257
|
}
|
|
1736
|
-
if (firstWord2(line.content)
|
|
1258
|
+
if (eventBodyReservedWords.includes(firstWord2(line.content))) {
|
|
1737
1259
|
const tag = parseTag(context, line);
|
|
1738
1260
|
if (tag !== void 0) {
|
|
1739
1261
|
tags.push(tag);
|
|
@@ -3638,9 +3160,9 @@ var ParserContext = class {
|
|
|
3638
3160
|
// ../../Compiler/dist/Parsing/ScreenplayParser.js
|
|
3639
3161
|
var domainPattern = pattern("^domain\\s+([A-Za-z_]\\w*(?:\\.[A-Za-z_]\\w*)*)$");
|
|
3640
3162
|
var importPattern = pattern("^import\\s+([\\w.]+)$");
|
|
3641
|
-
var
|
|
3163
|
+
var conceptPattern = pattern("^concept\\s+(\\w+)\\s*:\\s*(\\w+)((?:\\s+@\\w+)*)$");
|
|
3642
3164
|
var enumValuePattern = pattern("^@?[a-z_]\\w*$");
|
|
3643
|
-
var
|
|
3165
|
+
var attributeReasonPattern = pattern(`^([a-z_]\\w*)\\s+reason\\s+"(${stringBodyPattern})"$`);
|
|
3644
3166
|
var personaPattern = pattern("^persona\\s+([A-Za-z_]\\w*)$");
|
|
3645
3167
|
var personaPolicyPattern = pattern("^policy\\s+([A-Za-z_]\\w*)$");
|
|
3646
3168
|
var tabIndentPattern = /^[ ]*\t/;
|
|
@@ -3789,7 +3311,7 @@ function warnOnTabIndentation(context, lines) {
|
|
|
3789
3311
|
}
|
|
3790
3312
|
}
|
|
3791
3313
|
function parseConcept(context, line) {
|
|
3792
|
-
const match =
|
|
3314
|
+
const match = conceptPattern.exec(line.content);
|
|
3793
3315
|
if (match === null) {
|
|
3794
3316
|
context.error(DiagnosticCodes.InvalidConceptDeclaration, `Invalid concept declaration '${line.content}' - expected 'concept <Name> : <Type>'`, locationOf(line));
|
|
3795
3317
|
context.skipBlock(line.indent);
|
|
@@ -3808,7 +3330,7 @@ function parseConcept(context, line) {
|
|
|
3808
3330
|
const values = [];
|
|
3809
3331
|
for (let child = context.peekChild(line.indent); child !== void 0; child = context.peekChild(line.indent)) {
|
|
3810
3332
|
context.reader.takeSignificant();
|
|
3811
|
-
const reason =
|
|
3333
|
+
const reason = attributeReasonPattern.exec(child.content);
|
|
3812
3334
|
if (isFileDirective(child)) {
|
|
3813
3335
|
continue;
|
|
3814
3336
|
} else if (firstWord2(child.content) === "validate") {
|
|
@@ -4094,258 +3616,789 @@ var ScreenplaySyntaxWalker = class {
|
|
|
4094
3616
|
visitTriggerSource(syntax) {
|
|
4095
3617
|
this.visitNode(syntax);
|
|
4096
3618
|
}
|
|
4097
|
-
visitScreen(syntax) {
|
|
4098
|
-
this.visitNode(syntax);
|
|
4099
|
-
syntax.directives.forEach((node) => this.visitScreenDirective(node));
|
|
3619
|
+
visitScreen(syntax) {
|
|
3620
|
+
this.visitNode(syntax);
|
|
3621
|
+
syntax.directives.forEach((node) => this.visitScreenDirective(node));
|
|
3622
|
+
}
|
|
3623
|
+
visitScreenDirective(syntax) {
|
|
3624
|
+
this.visitNode(syntax);
|
|
3625
|
+
switch (syntax.kind) {
|
|
3626
|
+
case "ScreenDataSyntax":
|
|
3627
|
+
this.visitTypeRef(syntax.type);
|
|
3628
|
+
break;
|
|
3629
|
+
case "ScreenActionSyntax":
|
|
3630
|
+
if (syntax.navigate !== null)
|
|
3631
|
+
this.visitScreenDirective(syntax.navigate);
|
|
3632
|
+
break;
|
|
3633
|
+
case "ScreenTemplateReferenceSyntax":
|
|
3634
|
+
syntax.slots.forEach((slot2) => {
|
|
3635
|
+
this.visitNode(slot2);
|
|
3636
|
+
slot2.directives.forEach((node) => this.visitScreenDirective(node));
|
|
3637
|
+
});
|
|
3638
|
+
break;
|
|
3639
|
+
case "ScreenSectionSyntax":
|
|
3640
|
+
syntax.directives.forEach((node) => this.visitScreenDirective(node));
|
|
3641
|
+
break;
|
|
3642
|
+
case "ScreenTableSyntax":
|
|
3643
|
+
syntax.columns.forEach((node) => this.visitNode(node));
|
|
3644
|
+
if (syntax.rowClick !== null)
|
|
3645
|
+
this.visitScreenDirective(syntax.rowClick);
|
|
3646
|
+
break;
|
|
3647
|
+
case "ScreenSummarySyntax":
|
|
3648
|
+
syntax.fields.forEach((node) => this.visitNode(node));
|
|
3649
|
+
break;
|
|
3650
|
+
case "ScreenCodeSyntax":
|
|
3651
|
+
this.visitNode(syntax.code);
|
|
3652
|
+
break;
|
|
3653
|
+
}
|
|
3654
|
+
}
|
|
3655
|
+
visitSpecification(syntax) {
|
|
3656
|
+
this.visitNode(syntax);
|
|
3657
|
+
if (syntax.givenClock !== null)
|
|
3658
|
+
this.visitSpecificationClock(syntax.givenClock);
|
|
3659
|
+
syntax.given.forEach((node) => this.visitSpecificationEvent(node));
|
|
3660
|
+
syntax.givenReadModels.forEach((node) => this.visitSpecificationReadModel(node));
|
|
3661
|
+
if (syntax.when !== null)
|
|
3662
|
+
this.visitSpecificationCommand(syntax.when);
|
|
3663
|
+
syntax.givenCaptures.forEach((node) => this.visitSpecificationCapture(node));
|
|
3664
|
+
if (syntax.whenAppended !== null)
|
|
3665
|
+
this.visitSpecificationEvent(syntax.whenAppended);
|
|
3666
|
+
if (syntax.whenClock !== null)
|
|
3667
|
+
this.visitSpecificationClock(syntax.whenClock);
|
|
3668
|
+
if (syntax.whenTrigger !== null)
|
|
3669
|
+
this.visitSpecificationTrigger(syntax.whenTrigger);
|
|
3670
|
+
if (syntax.whenCapture !== null)
|
|
3671
|
+
this.visitSpecificationCapture(syntax.whenCapture);
|
|
3672
|
+
if (syntax.whenQuery !== null)
|
|
3673
|
+
this.visitSpecificationWhenQuery(syntax.whenQuery);
|
|
3674
|
+
syntax.thenEvents.forEach((node) => this.visitSpecificationEvent(node));
|
|
3675
|
+
syntax.thenReadModels.forEach((node) => this.visitSpecificationReadModel(node));
|
|
3676
|
+
syntax.thenResults.forEach((node) => this.visitSpecificationQueryResult(node));
|
|
3677
|
+
if (syntax.thenNoResult !== null)
|
|
3678
|
+
this.visitNode(syntax.thenNoResult);
|
|
3679
|
+
syntax.thenErrors.forEach((node) => this.visitNode(node));
|
|
3680
|
+
}
|
|
3681
|
+
visitSpecificationClock(syntax) {
|
|
3682
|
+
this.visitNode(syntax);
|
|
3683
|
+
}
|
|
3684
|
+
visitSpecificationTrigger(syntax) {
|
|
3685
|
+
this.visitNode(syntax);
|
|
3686
|
+
syntax.values.forEach((node) => this.visitPropertyMapping(node));
|
|
3687
|
+
}
|
|
3688
|
+
visitSpecificationCapture(syntax) {
|
|
3689
|
+
this.visitNode(syntax);
|
|
3690
|
+
syntax.record.forEach((node) => this.visitPropertyMapping(node));
|
|
3691
|
+
}
|
|
3692
|
+
visitSpecificationWhenQuery(syntax) {
|
|
3693
|
+
this.visitNode(syntax);
|
|
3694
|
+
syntax.arguments.forEach((node) => this.visitPropertyMapping(node));
|
|
3695
|
+
}
|
|
3696
|
+
visitSpecificationQueryResult(syntax) {
|
|
3697
|
+
this.visitNode(syntax);
|
|
3698
|
+
syntax.properties.forEach((node) => this.visitPropertyMapping(node));
|
|
3699
|
+
}
|
|
3700
|
+
visitSpecificationEvent(syntax) {
|
|
3701
|
+
this.visitNode(syntax);
|
|
3702
|
+
syntax.values.forEach((node) => this.visitPropertyMapping(node));
|
|
3703
|
+
if (syntax.for !== null)
|
|
3704
|
+
this.visitExpression(syntax.for);
|
|
3705
|
+
}
|
|
3706
|
+
visitSpecificationCommand(syntax) {
|
|
3707
|
+
this.visitNode(syntax);
|
|
3708
|
+
syntax.values.forEach((node) => this.visitPropertyMapping(node));
|
|
3709
|
+
if (syntax.for !== null)
|
|
3710
|
+
this.visitExpression(syntax.for);
|
|
3711
|
+
}
|
|
3712
|
+
visitSpecificationReadModel(syntax) {
|
|
3713
|
+
this.visitNode(syntax);
|
|
3714
|
+
syntax.properties.forEach((node) => this.visitPropertyMapping(node));
|
|
3715
|
+
}
|
|
3716
|
+
visitPropertyMapping(syntax) {
|
|
3717
|
+
this.visitNode(syntax);
|
|
3718
|
+
this.visitExpression(syntax.source);
|
|
3719
|
+
}
|
|
3720
|
+
visitProperty(syntax) {
|
|
3721
|
+
this.visitNode(syntax);
|
|
3722
|
+
this.visitTypeRef(syntax.type);
|
|
3723
|
+
}
|
|
3724
|
+
visitTypeRef(syntax) {
|
|
3725
|
+
this.visitNode(syntax);
|
|
3726
|
+
}
|
|
3727
|
+
visitExpression(syntax) {
|
|
3728
|
+
this.visitNode(syntax);
|
|
3729
|
+
if (syntax.kind === "ListExpressionSyntax") {
|
|
3730
|
+
syntax.items.forEach((item) => this.visitExpression(item));
|
|
3731
|
+
} else if (syntax.kind === "ObjectExpressionSyntax") {
|
|
3732
|
+
syntax.members.forEach((member) => this.visitObjectMember(member));
|
|
3733
|
+
}
|
|
3734
|
+
}
|
|
3735
|
+
visitObjectMember(syntax) {
|
|
3736
|
+
this.visitNode(syntax);
|
|
3737
|
+
this.visitExpression(syntax.value);
|
|
3738
|
+
}
|
|
3739
|
+
};
|
|
3740
|
+
|
|
3741
|
+
// ../../Compiler/dist/Authoring/QuickFixes.js
|
|
3742
|
+
function isQuickFixDiagnostic(code) {
|
|
3743
|
+
return code === DiagnosticCodes.LegacyOptionalSuffix || code === DiagnosticCodes.RedundantEventId;
|
|
3744
|
+
}
|
|
3745
|
+
function legacyOptionalTypeLength(line, diagnostic) {
|
|
3746
|
+
if (diagnostic.code !== DiagnosticCodes.LegacyOptionalSuffix)
|
|
3747
|
+
return 0;
|
|
3748
|
+
return /^[\p{L}\p{Mn}\p{Nd}\p{Pc}.]+(?:\[\])?\?/u.exec(line.slice(diagnostic.location.column - 1))?.[0].length ?? 0;
|
|
3749
|
+
}
|
|
3750
|
+
function prepareQuickFixes(source, options = {}) {
|
|
3751
|
+
const original = parseForAuthoring(source, void 0, options.placement);
|
|
3752
|
+
if (!original.success)
|
|
3753
|
+
return () => [];
|
|
3754
|
+
const lines = splitLines(source);
|
|
3755
|
+
const eventsByLine = /* @__PURE__ */ new Map();
|
|
3756
|
+
const walker = new class extends ScreenplaySyntaxWalker {
|
|
3757
|
+
visitEvent(event2) {
|
|
3758
|
+
eventsByLine.set(event2.location.line, event2);
|
|
3759
|
+
}
|
|
3760
|
+
}();
|
|
3761
|
+
walker.visitApplication(original.value);
|
|
3762
|
+
const counts = /* @__PURE__ */ new Map();
|
|
3763
|
+
const byLine = /* @__PURE__ */ new Map();
|
|
3764
|
+
const events = /* @__PURE__ */ new Map();
|
|
3765
|
+
let event;
|
|
3766
|
+
for (const line of lines) {
|
|
3767
|
+
event = eventsByLine.get(line.number) ?? event;
|
|
3768
|
+
if (event !== void 0)
|
|
3769
|
+
events.set(line.number, event);
|
|
3770
|
+
}
|
|
3771
|
+
for (const diagnostic of original.diagnostics) {
|
|
3772
|
+
counts.set(diagnostic.code, (counts.get(diagnostic.code) ?? 0) + 1);
|
|
3773
|
+
const line = lines[diagnostic.location.line - 1];
|
|
3774
|
+
const length = legacyOptionalTypeLength(line.raw, diagnostic);
|
|
3775
|
+
if (length > 0) {
|
|
3776
|
+
byLine.set(line.number, { line: line.number, fix: { diagnosticCode: diagnostic.code, title: "Use 'optional' instead of '?'", scope: "occurrence", edits: [{ start: line.startOffset + diagnostic.location.column + length - 2, length: 1, text: " optional" }] } });
|
|
3777
|
+
} else if (diagnostic.code === DiagnosticCodes.RedundantEventId && commentStart(line.raw) < 0) {
|
|
3778
|
+
const declaration = events.get(line.number);
|
|
3779
|
+
if (declaration?.id !== declaration?.name || declaration === void 0)
|
|
3780
|
+
continue;
|
|
3781
|
+
byLine.set(line.number, {
|
|
3782
|
+
line: line.number,
|
|
3783
|
+
fix: { diagnosticCode: diagnostic.code, title: "Remove the redundant event id", scope: "occurrence", edits: [{ start: line.startOffset, length: (lines[line.number]?.startOffset ?? source.length) - line.startOffset, text: "" }] },
|
|
3784
|
+
change: { node: declaration, replacement: { ...declaration, id: null } }
|
|
3785
|
+
});
|
|
3786
|
+
}
|
|
3787
|
+
}
|
|
3788
|
+
const optional = [...byLine.values()].filter((candidate) => candidate.fix.diagnosticCode === DiagnosticCodes.LegacyOptionalSuffix);
|
|
3789
|
+
const syntax = verificationShape(original);
|
|
3790
|
+
const verified = /* @__PURE__ */ new Map();
|
|
3791
|
+
let rangeVerdicts;
|
|
3792
|
+
let documentChecked = false;
|
|
3793
|
+
let documentFix;
|
|
3794
|
+
const verify = (fix, change) => {
|
|
3795
|
+
const candidate = applyQuickFixEdits(source, fix.edits);
|
|
3796
|
+
if (candidate === void 0)
|
|
3797
|
+
return void 0;
|
|
3798
|
+
const parsed = parseForAuthoring(candidate, void 0, options.placement);
|
|
3799
|
+
if (!parsed.success || verificationShape(parsed) !== (change === void 0 ? syntax : verificationShape(original, [change])))
|
|
3800
|
+
return void 0;
|
|
3801
|
+
return parsed.diagnostics.filter((diagnostic) => diagnostic.code === fix.diagnosticCode).length === (counts.get(fix.diagnosticCode) ?? 0) - fix.edits.length ? fix : void 0;
|
|
3802
|
+
};
|
|
3803
|
+
return (line, diagnosticCode) => {
|
|
3804
|
+
const requests = typeof line === "number" || line === void 0 ? void 0 : line;
|
|
3805
|
+
const includeDocument = requests === void 0 ? diagnosticCode === void 0 || diagnosticCode === DiagnosticCodes.LegacyOptionalSuffix : requests.some((request) => request.diagnosticCode === DiagnosticCodes.LegacyOptionalSuffix);
|
|
3806
|
+
if (includeDocument && !documentChecked) {
|
|
3807
|
+
if (optional.length > 0)
|
|
3808
|
+
documentFix = verify({ diagnosticCode: DiagnosticCodes.LegacyOptionalSuffix, title: "Use 'optional' throughout this document", scope: "document", edits: optional.flatMap((candidate) => candidate.fix.edits) });
|
|
3809
|
+
documentChecked = true;
|
|
3810
|
+
}
|
|
3811
|
+
if (requests !== void 0) {
|
|
3812
|
+
if (rangeVerdicts === void 0) {
|
|
3813
|
+
rangeVerdicts = /* @__PURE__ */ new Map();
|
|
3814
|
+
const candidates = lines.flatMap((line2) => byLine.has(line2.number) ? [byLine.get(line2.number)] : []);
|
|
3815
|
+
const edits = candidates.flatMap((candidate) => candidate.fix.edits);
|
|
3816
|
+
const candidateSource = applyQuickFixEdits(source, edits);
|
|
3817
|
+
if (edits.length > 0 && candidateSource !== void 0) {
|
|
3818
|
+
const parsed = parseForAuthoring(candidateSource, void 0, options.placement);
|
|
3819
|
+
const changes = candidates.flatMap((candidate) => candidate.change === void 0 ? [] : [candidate.change]);
|
|
3820
|
+
if (parsed.success && verificationShape(parsed) === verificationShape(original, changes)) {
|
|
3821
|
+
const remaining = /* @__PURE__ */ new Map();
|
|
3822
|
+
const removed = /* @__PURE__ */ new Map();
|
|
3823
|
+
for (const diagnostic of parsed.diagnostics)
|
|
3824
|
+
remaining.set(diagnostic.code, (remaining.get(diagnostic.code) ?? 0) + 1);
|
|
3825
|
+
for (const candidate of candidates)
|
|
3826
|
+
removed.set(candidate.fix.diagnosticCode, (removed.get(candidate.fix.diagnosticCode) ?? 0) + candidate.fix.edits.length);
|
|
3827
|
+
if ([...removed].every(([code, count]) => (remaining.get(code) ?? 0) === (counts.get(code) ?? 0) - count)) {
|
|
3828
|
+
for (const candidate of candidates)
|
|
3829
|
+
rangeVerdicts.set(candidate.line, candidate.fix);
|
|
3830
|
+
}
|
|
3831
|
+
}
|
|
3832
|
+
}
|
|
3833
|
+
}
|
|
3834
|
+
const selected2 = /* @__PURE__ */ new Map();
|
|
3835
|
+
for (const request of requests) {
|
|
3836
|
+
const fix = rangeVerdicts.get(request.line);
|
|
3837
|
+
if (fix?.diagnosticCode === request.diagnosticCode)
|
|
3838
|
+
selected2.set(request.line, fix);
|
|
3839
|
+
}
|
|
3840
|
+
return [...selected2.values(), ...includeDocument && documentFix !== void 0 ? [documentFix] : []];
|
|
3841
|
+
}
|
|
3842
|
+
const occurrenceLine = typeof line === "number" ? line : void 0;
|
|
3843
|
+
const selected = occurrenceLine === void 0 ? void 0 : byLine.get(occurrenceLine);
|
|
3844
|
+
let occurrenceFix;
|
|
3845
|
+
if (selected !== void 0 && occurrenceLine !== void 0 && (diagnosticCode === void 0 || selected.fix.diagnosticCode === diagnosticCode)) {
|
|
3846
|
+
if (!verified.has(occurrenceLine)) {
|
|
3847
|
+
if (verified.size === 32)
|
|
3848
|
+
verified.delete(verified.keys().next().value);
|
|
3849
|
+
verified.set(occurrenceLine, verify(selected.fix, selected.change));
|
|
3850
|
+
}
|
|
3851
|
+
occurrenceFix = verified.get(occurrenceLine);
|
|
3852
|
+
}
|
|
3853
|
+
return [occurrenceFix, includeDocument ? documentFix : void 0].filter((fix) => fix !== void 0);
|
|
3854
|
+
};
|
|
3855
|
+
}
|
|
3856
|
+
function verificationShape(parsed, changes = []) {
|
|
3857
|
+
const replacements = new Map(changes.map((change) => [change.node, change.replacement]));
|
|
3858
|
+
return JSON.stringify([parsed.value, parsed.triggerData], (key, value) => key === "location" ? void 0 : replacements.get(value) ?? value);
|
|
3859
|
+
}
|
|
3860
|
+
function applyQuickFixEdits(source, edits) {
|
|
3861
|
+
const parts = [];
|
|
3862
|
+
let end = 0;
|
|
3863
|
+
for (const edit of edits) {
|
|
3864
|
+
if (edit.start < end || edit.start < 0 || edit.length < 0 || edit.start + edit.length > source.length)
|
|
3865
|
+
return void 0;
|
|
3866
|
+
parts.push(source.slice(end, edit.start), edit.text);
|
|
3867
|
+
end = edit.start + edit.length;
|
|
3868
|
+
}
|
|
3869
|
+
parts.push(source.slice(end));
|
|
3870
|
+
return parts.join("");
|
|
3871
|
+
}
|
|
3872
|
+
|
|
3873
|
+
// event-analysis-source.ts
|
|
3874
|
+
function eventAnalysisSource(lines) {
|
|
3875
|
+
let fenced = false;
|
|
3876
|
+
return lines.map((line) => {
|
|
3877
|
+
if (fenced) {
|
|
3878
|
+
if (line.trim() === "```") fenced = false;
|
|
3879
|
+
return line;
|
|
3880
|
+
}
|
|
3881
|
+
const text = withoutComment(line);
|
|
3882
|
+
if (/^\s*```(?:[a-z]+)?\s*$/.test(text)) fenced = true;
|
|
3883
|
+
return text.trimEnd();
|
|
3884
|
+
});
|
|
3885
|
+
}
|
|
3886
|
+
|
|
3887
|
+
// symbols.ts
|
|
3888
|
+
var conceptPattern2 = /^concept\s+(\w+)\s*:\s*(\w+)((?:\s+@\w+)*)\s*$/;
|
|
3889
|
+
var propertyPattern2 = /^\s*(@?[a-z_]\w*)\s+([\w.]+(?:\[\])?(?:\?|\s+optional)?)(\s+identifier)?\s*$/;
|
|
3890
|
+
var attributeReasonPattern2 = /^([a-z_]\w*)\s+reason\s+"((?:[^"\\]|\\.)*)"\s*$/;
|
|
3891
|
+
var readPattern = /^\s*reads\s+([A-Z]\w*)(?:\s+as\s+([a-z_]\w*))?(?:\s+by\s+([a-z_]\w*))?\s*$/;
|
|
3892
|
+
var commandReserved = ["authorize", "produces", "reads"];
|
|
3893
|
+
var authorizationContinuation = /^(?:(?:or|and)\s+)?[A-Za-z_(][\p{L}\p{Mn}\p{Nd}\p{Pc}\s()]*$/u;
|
|
3894
|
+
var eventReserved = eventBodyReservedWords;
|
|
3895
|
+
var inlineEventReserved = ["tag", "for", "generation", "origin", "namespace", "sequence", "correlation", "causation", "causedBy", "occurred"];
|
|
3896
|
+
var queryParameterPattern = /^\s*(?:by|filter)\s+([a-z_]\w*)\s+([\w.]+(?:\[\])?(?:\?|\s+optional)?)(?:\s+from\s+.+)?\s*$/;
|
|
3897
|
+
function propertyTypeReference(property) {
|
|
3898
|
+
return property.typeReference ?? typeReferenceSymbol(property.type);
|
|
3899
|
+
}
|
|
3900
|
+
function propertiesIn(lines, body, reserved3) {
|
|
3901
|
+
return body.map((index) => ({ index, match: lines[index].match(propertyPattern2) })).filter((entry) => entry.match !== null).filter(({ match }) => match[1].startsWith("@") || match[1] === "as" || !reserved3.includes(match[1])).map(({ index, match }) => ({
|
|
3902
|
+
name: match[1].replace(/^@/, ""),
|
|
3903
|
+
type: match[2],
|
|
3904
|
+
typeReference: typeReferenceSymbol(match[2]),
|
|
3905
|
+
isIdentifier: match[3] !== void 0,
|
|
3906
|
+
line: index
|
|
3907
|
+
}));
|
|
3908
|
+
}
|
|
3909
|
+
function collectBody(lines, fences, start, indent) {
|
|
3910
|
+
const body = [];
|
|
3911
|
+
for (let index = start + 1; index < lines.length; index++) {
|
|
3912
|
+
if (fences[index]) {
|
|
3913
|
+
continue;
|
|
3914
|
+
}
|
|
3915
|
+
const line = lines[index];
|
|
3916
|
+
if (line.trim().length === 0) continue;
|
|
3917
|
+
if (indentOf(line) <= indent) break;
|
|
3918
|
+
body.push(index);
|
|
4100
3919
|
}
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
3920
|
+
return body;
|
|
3921
|
+
}
|
|
3922
|
+
function directBody(lines, fences, start, indent) {
|
|
3923
|
+
const body = collectBody(lines, fences, start, indent).filter((index) => !fences[index] && !/^\s*(?:\/\/|#)/.test(lines[index]));
|
|
3924
|
+
if (!/^\s*command\b/.test(lines[start])) return body;
|
|
3925
|
+
let blockIndent;
|
|
3926
|
+
let authorization = false;
|
|
3927
|
+
return body.filter((index) => {
|
|
3928
|
+
const childIndent = indentOf(lines[index]);
|
|
3929
|
+
const text = lines[index].trim();
|
|
3930
|
+
if (blockIndent !== void 0 && childIndent > blockIndent && (!authorization || authorizationContinuation.test(text))) return false;
|
|
3931
|
+
const property = text !== "validate csharp" && propertiesIn(lines, [index], commandReserved).length > 0;
|
|
3932
|
+
const leaf = property || /^description(?:\s|$)/.test(text);
|
|
3933
|
+
blockIndent = leaf ? void 0 : childIndent;
|
|
3934
|
+
authorization = /^authorize(?:\s|$)/.test(text);
|
|
3935
|
+
return true;
|
|
3936
|
+
});
|
|
3937
|
+
}
|
|
3938
|
+
function scanDocument(lines) {
|
|
3939
|
+
const symbols = {
|
|
3940
|
+
imports: [],
|
|
3941
|
+
concepts: [],
|
|
3942
|
+
types: [],
|
|
3943
|
+
policies: [],
|
|
3944
|
+
events: [],
|
|
3945
|
+
commands: [],
|
|
3946
|
+
queries: [],
|
|
3947
|
+
screens: [],
|
|
3948
|
+
triggers: []
|
|
3949
|
+
};
|
|
3950
|
+
lines = eventAnalysisSource(lines);
|
|
3951
|
+
const fences = fenceMap(lines);
|
|
3952
|
+
const eventLines = lines;
|
|
3953
|
+
const eventFences = fences;
|
|
3954
|
+
const eventPropertyLines = lines.map((line) => line.replace(/\s*=(?!=|>).*/, ""));
|
|
3955
|
+
for (let index = 0; index < lines.length; index++) {
|
|
3956
|
+
if (fences[index]) continue;
|
|
3957
|
+
const line = lines[index];
|
|
3958
|
+
const trimmed = line.trim();
|
|
3959
|
+
const indent = indentOf(line);
|
|
3960
|
+
const importMatch = eventLines[index].trim().match(/^import\s+([\w.]+)\s*$/);
|
|
3961
|
+
if (importMatch && indent === 0) {
|
|
3962
|
+
const qualifiedName = importMatch[1];
|
|
3963
|
+
const shortName = qualifiedName.split(".").pop() ?? qualifiedName;
|
|
3964
|
+
symbols.imports.push({ qualifiedName, shortName, line: index });
|
|
3965
|
+
continue;
|
|
3966
|
+
}
|
|
3967
|
+
const conceptMatch = trimmed.match(conceptPattern2);
|
|
3968
|
+
if (conceptMatch) {
|
|
3969
|
+
const body = collectBody(lines, fences, index, indent).map((i) => lines[i].trim());
|
|
3970
|
+
const attributeReasons = {};
|
|
3971
|
+
for (const line2 of body) {
|
|
3972
|
+
const reason = line2.match(attributeReasonPattern2);
|
|
3973
|
+
if (reason && attributeReasons[reason[1]] === void 0) {
|
|
3974
|
+
attributeReasons[reason[1]] = reason[2];
|
|
3975
|
+
}
|
|
3976
|
+
}
|
|
3977
|
+
const enumValues = conceptMatch[2] === "Enum" ? body.filter((line2) => !attributeReasonPattern2.test(line2)) : [];
|
|
3978
|
+
symbols.concepts.push({
|
|
3979
|
+
name: conceptMatch[1],
|
|
3980
|
+
primitive: conceptMatch[2],
|
|
3981
|
+
attributes: conceptMatch[3].trim().split(/\s+/).filter(Boolean),
|
|
3982
|
+
attributeReasons,
|
|
3983
|
+
enumValues,
|
|
3984
|
+
line: index
|
|
3985
|
+
});
|
|
3986
|
+
continue;
|
|
3987
|
+
}
|
|
3988
|
+
const typeMatch = trimmed.match(/^type\s+(\w+)\s*$/);
|
|
3989
|
+
if (typeMatch) {
|
|
3990
|
+
symbols.types.push({
|
|
3991
|
+
name: typeMatch[1],
|
|
3992
|
+
properties: propertiesIn(lines, collectBody(lines, fences, index, indent), clauseKeywords),
|
|
3993
|
+
line: index
|
|
3994
|
+
});
|
|
3995
|
+
continue;
|
|
3996
|
+
}
|
|
3997
|
+
const policyMatch = trimmed.match(/^policy\s+(\w+)\s*$/);
|
|
3998
|
+
if (policyMatch) {
|
|
3999
|
+
const requires = collectBody(lines, fences, index, indent).filter((i) => !fences[i]).map((i) => lines[i].trim());
|
|
4000
|
+
symbols.policies.push({ name: policyMatch[1], requires, line: index });
|
|
4001
|
+
continue;
|
|
4002
|
+
}
|
|
4003
|
+
const eventMatch = eventLines[index].trim().match(/^(?:produces\s+)?event\s+(\w+)(?:\s+generation\s+(\d+))?\s*$/);
|
|
4004
|
+
if (eventMatch) {
|
|
4005
|
+
const inline = trimmed.startsWith("produces ");
|
|
4006
|
+
const body = directBody(eventLines, eventFences, index, indent);
|
|
4007
|
+
const propertyBody = inline ? body : body.filter((line2) => fileReferenceOn(eventLines[line2], line2) === void 0);
|
|
4008
|
+
symbols.events.push({
|
|
4009
|
+
name: eventMatch[1],
|
|
4010
|
+
...eventMatch[2] ? { generation: Number(eventMatch[2]) } : {},
|
|
4011
|
+
inline,
|
|
4012
|
+
properties: propertiesIn(
|
|
4013
|
+
inline ? eventPropertyLines : eventLines,
|
|
4014
|
+
propertyBody,
|
|
4015
|
+
inline ? inlineEventReserved : eventReserved
|
|
4016
|
+
),
|
|
4017
|
+
line: index
|
|
4018
|
+
});
|
|
4019
|
+
continue;
|
|
4020
|
+
}
|
|
4021
|
+
const commandMatch = eventLines[index].trim().match(/^command\s+(\w+)\s*$/);
|
|
4022
|
+
if (commandMatch) {
|
|
4023
|
+
const body = directBody(lines, fences, index, indent);
|
|
4024
|
+
const productionHeaders = body.filter((line2) => /^\s*produces\b/.test(lines[line2]));
|
|
4025
|
+
symbols.commands.push({
|
|
4026
|
+
name: commandMatch[1],
|
|
4027
|
+
properties: propertiesIn(lines, body.filter((line2) => lines[line2].trim() !== "validate csharp"), commandReserved),
|
|
4028
|
+
productionHeaders,
|
|
4029
|
+
produces: productionHeaders.flatMap((line2) => {
|
|
4030
|
+
const header10 = eventLines[line2].trim();
|
|
4031
|
+
const inline = /^produces\s+event\b/.test(header10);
|
|
4032
|
+
const conditional2 = /^produces\s+when\b/.test(header10);
|
|
4033
|
+
const eventLine = conditional2 ? directBody(eventLines, eventFences, line2, indentOf(eventLines[line2]))[0] : line2;
|
|
4034
|
+
if (eventLine === void 0) return [];
|
|
4035
|
+
const name = conditional2 ? eventLines[eventLine].trim() : header10.match(inline ? /^produces\s+event\s+([A-Za-z_]\w*)(?:\s+generation\s+\d+)?\s*$/ : /^produces\s+([A-Z]\w*)\s*$/)?.[1];
|
|
4036
|
+
if (name === void 0 || !/^[A-Za-z_]\w*$/.test(name)) return [];
|
|
4037
|
+
const children = directBody(eventLines, eventFences, eventLine, indentOf(eventLines[eventLine]));
|
|
4038
|
+
const targets = children.map((index2) => eventLines[index2].trim().match(/^for(?:\s+(.*))?$/)).filter((match) => match !== null);
|
|
4039
|
+
const target = targets.length === 0 ? void 0 : targets.length === 1 ? targets[0][1] ?? "" : "";
|
|
4040
|
+
const mappings = children.flatMap((index2) => {
|
|
4041
|
+
const match = eventLines[index2].trim().match(inline ? /^(@?[a-z_]\w*)\s+[\w.]+(?:\[\])?(?:\?|\s+optional)?\s*=(?!=|>)\s*(.+)$/ : /^(@?[\w.]+)\s*=(?!=|>)\s*(.+)$/);
|
|
4042
|
+
return match === null ? [] : [{ name: match[1].replace(/^@/, ""), source: match[2], line: index2 }];
|
|
4043
|
+
});
|
|
4044
|
+
return [{ name, inline, conditional: conditional2, line: line2, target, mappings }];
|
|
4045
|
+
}),
|
|
4046
|
+
reads: body.filter((line2) => !fences[line2]).map((line2) => ({ line: line2, match: lines[line2].match(readPattern) })).filter((entry) => entry.match !== null).map(({ line: line2, match }) => ({
|
|
4047
|
+
view: match[1],
|
|
4048
|
+
...match[2] ? { alias: match[2] } : {},
|
|
4049
|
+
...match[3] ? { by: match[3] } : {},
|
|
4050
|
+
line: line2
|
|
4051
|
+
})),
|
|
4052
|
+
line: index
|
|
4053
|
+
});
|
|
4054
|
+
continue;
|
|
4055
|
+
}
|
|
4056
|
+
const queryMatch = trimmed.match(/^query\s+(\w+)\s*=>\s*(?:observable\s+)?([\w.]+(?:\[\])?(?:\?|\s+optional)?)\s*$/);
|
|
4057
|
+
if (queryMatch) {
|
|
4058
|
+
const parameters = collectBody(lines, fences, index, indent).map((i) => ({ index: i, match: lines[i].match(queryParameterPattern) })).filter(
|
|
4059
|
+
(entry) => entry.match !== null
|
|
4060
|
+
).map(({ index: line2, match }) => ({
|
|
4061
|
+
name: match[1],
|
|
4062
|
+
type: match[2],
|
|
4063
|
+
typeReference: typeReferenceSymbol(match[2]),
|
|
4064
|
+
isIdentifier: false,
|
|
4065
|
+
line: line2
|
|
4066
|
+
}));
|
|
4067
|
+
symbols.queries.push({
|
|
4068
|
+
name: queryMatch[1],
|
|
4069
|
+
returnType: queryMatch[2],
|
|
4070
|
+
returnTypeReference: typeReferenceSymbol(queryMatch[2]),
|
|
4071
|
+
parameters,
|
|
4072
|
+
line: index
|
|
4073
|
+
});
|
|
4074
|
+
continue;
|
|
4075
|
+
}
|
|
4076
|
+
const screenMatch = trimmed.match(/^screen\s+(\w+)\s*$/);
|
|
4077
|
+
if (screenMatch) {
|
|
4078
|
+
symbols.screens.push({ name: screenMatch[1], line: index });
|
|
4079
|
+
continue;
|
|
4080
|
+
}
|
|
4081
|
+
const triggerMatch = trimmed.match(/^trigger\s+(\w+)\s*$/);
|
|
4082
|
+
if (triggerMatch && indent === 0) {
|
|
4083
|
+
symbols.triggers.push({ name: triggerMatch[1], line: index });
|
|
4131
4084
|
}
|
|
4132
4085
|
}
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4086
|
+
return symbols;
|
|
4087
|
+
}
|
|
4088
|
+
function mergeSymbols(...documents) {
|
|
4089
|
+
return {
|
|
4090
|
+
imports: documents.flatMap((document) => document.imports),
|
|
4091
|
+
concepts: documents.flatMap((document) => document.concepts),
|
|
4092
|
+
types: documents.flatMap((document) => document.types),
|
|
4093
|
+
policies: documents.flatMap((document) => document.policies),
|
|
4094
|
+
events: documents.flatMap((document) => document.events),
|
|
4095
|
+
commands: documents.flatMap((document) => document.commands),
|
|
4096
|
+
queries: documents.flatMap((document) => document.queries),
|
|
4097
|
+
screens: documents.flatMap((document) => document.screens),
|
|
4098
|
+
triggers: documents.flatMap((document) => document.triggers)
|
|
4099
|
+
};
|
|
4100
|
+
}
|
|
4101
|
+
function knownEventNames(symbols) {
|
|
4102
|
+
return [
|
|
4103
|
+
...symbols.events.map((event) => event.name),
|
|
4104
|
+
...symbols.imports.map((imported) => imported.shortName)
|
|
4105
|
+
];
|
|
4106
|
+
}
|
|
4107
|
+
var builtInTriggerNames = ["Startup", "Shutdown"];
|
|
4108
|
+
function knownTriggerNames(symbols) {
|
|
4109
|
+
return [
|
|
4110
|
+
...knownEventNames(symbols),
|
|
4111
|
+
...symbols.triggers.map((trigger) => trigger.name),
|
|
4112
|
+
...builtInTriggerNames
|
|
4113
|
+
];
|
|
4114
|
+
}
|
|
4115
|
+
function knownTypeNames(symbols, primitives) {
|
|
4116
|
+
return [
|
|
4117
|
+
...primitives,
|
|
4118
|
+
...symbols.concepts.map((concept) => concept.name),
|
|
4119
|
+
...symbols.types.map((type) => type.name),
|
|
4120
|
+
...symbols.imports.map((imported) => imported.shortName)
|
|
4121
|
+
];
|
|
4122
|
+
}
|
|
4123
|
+
|
|
4124
|
+
// event-context-catalog.ts
|
|
4125
|
+
var eventContextRootType = "EventContext";
|
|
4126
|
+
var eventContextTypes = {
|
|
4127
|
+
"EventContext": [
|
|
4128
|
+
{ name: "eventType", type: "EventType", kind: "composite", description: "The type of the event - its identifier, generation and whether it is a tombstone." },
|
|
4129
|
+
{ name: "eventSourceType", type: "EventSourceType", kind: "value", description: "The type of the event source the event was appended to." },
|
|
4130
|
+
{ name: "eventSourceId", type: "EventSourceId", kind: "value", description: "The identifier of the event source the event was appended to - the value $eventSourceId resolves." },
|
|
4131
|
+
{ name: "eventStreamType", type: "EventStreamType", kind: "value", description: "The type of the event stream the event belongs to." },
|
|
4132
|
+
{ name: "eventStreamId", type: "EventStreamId", kind: "value", description: "The identifier of the event stream the event belongs to." },
|
|
4133
|
+
{ name: "sequenceNumber", type: "EventSequenceNumber", kind: "value", description: "The position of the event in its event sequence." },
|
|
4134
|
+
{ name: "occurred", type: "DateTimeOffset", kind: "value", description: "When the event occurred - the time it was appended unless one was given." },
|
|
4135
|
+
{ name: "eventStore", type: "EventStoreName", kind: "value", description: "The name of the event store the event belongs to." },
|
|
4136
|
+
{ name: "namespace", type: "EventStoreNamespaceName", kind: "value", description: "The namespace within the event store the event belongs to." },
|
|
4137
|
+
{ name: "correlationId", type: "CorrelationId", kind: "value", description: "The correlation identifier the event was appended with." },
|
|
4138
|
+
{ name: "causation", type: "IEnumerable<Causation>", kind: "collection", description: "The chain of causes that led to the event - a collection, not addressable below." },
|
|
4139
|
+
{ name: "causedBy", type: "Identity", kind: "composite", description: "The identity that caused the event." },
|
|
4140
|
+
{ name: "tags", type: "IEnumerable<Tag>", kind: "collection", description: "The tags the event was appended with - a collection, not addressable below." },
|
|
4141
|
+
{ name: "hash", type: "EventHash", kind: "value", description: "The hash of the event content." },
|
|
4142
|
+
{ name: "observationState", type: "EventObservationState", kind: "value", description: "Whether the observer sees the event for the first time or again on replay - differs between live processing and replay." },
|
|
4143
|
+
{ name: "subject", type: "Subject", kind: "value", description: "The compliance subject the event is about - the event source identifier unless one was given." },
|
|
4144
|
+
{ name: "subjectIsEventSourceId", type: "bool", kind: "value", description: "Whether the subject is the event source identifier." }
|
|
4145
|
+
],
|
|
4146
|
+
"EventType": [
|
|
4147
|
+
{ name: "id", type: "EventTypeId", kind: "value", description: "The identifier of the event type." },
|
|
4148
|
+
{ name: "generation", type: "EventTypeGeneration", kind: "value", description: "The generation of the event type." },
|
|
4149
|
+
{ name: "tombstone", type: "bool", kind: "value", description: "Whether the event is a tombstone event." }
|
|
4150
|
+
],
|
|
4151
|
+
"EventSourceType": [
|
|
4152
|
+
{ name: "value", type: "string", kind: "value", description: "The underlying string value." }
|
|
4153
|
+
],
|
|
4154
|
+
"EventSourceId": [
|
|
4155
|
+
{ name: "value", type: "string", kind: "value", description: "The underlying string value." }
|
|
4156
|
+
],
|
|
4157
|
+
"EventStreamType": [
|
|
4158
|
+
{ name: "value", type: "string", kind: "value", description: "The underlying string value." }
|
|
4159
|
+
],
|
|
4160
|
+
"EventStreamId": [
|
|
4161
|
+
{ name: "value", type: "string", kind: "value", description: "The underlying string value." }
|
|
4162
|
+
],
|
|
4163
|
+
"EventSequenceNumber": [
|
|
4164
|
+
{ name: "value", type: "ulong", kind: "value", description: "The underlying ulong value." }
|
|
4165
|
+
],
|
|
4166
|
+
"DateTimeOffset": [
|
|
4167
|
+
{ name: "Week", type: "int", kind: "function", description: "The ISO 8601 week of the year the value falls in." }
|
|
4168
|
+
],
|
|
4169
|
+
"EventStoreName": [
|
|
4170
|
+
{ name: "value", type: "string", kind: "value", description: "The underlying string value." }
|
|
4171
|
+
],
|
|
4172
|
+
"EventStoreNamespaceName": [
|
|
4173
|
+
{ name: "value", type: "string", kind: "value", description: "The underlying string value." }
|
|
4174
|
+
],
|
|
4175
|
+
"CorrelationId": [
|
|
4176
|
+
{ name: "value", type: "Guid", kind: "value", description: "The underlying Guid value." }
|
|
4177
|
+
],
|
|
4178
|
+
"Identity": [
|
|
4179
|
+
{ name: "subject", type: "string", kind: "value", description: "The subject identifier of the identity." },
|
|
4180
|
+
{ name: "name", type: "string", kind: "value", description: "The display name of the identity." },
|
|
4181
|
+
{ name: "userName", type: "string", kind: "value", description: "The user name of the identity." },
|
|
4182
|
+
{ name: "onBehalfOf", type: "Identity", kind: "composite", description: "The identity this identity acted on behalf of, if any - an identity with the same members." }
|
|
4183
|
+
],
|
|
4184
|
+
"EventHash": [
|
|
4185
|
+
{ name: "value", type: "string", kind: "value", description: "The underlying string value." }
|
|
4186
|
+
],
|
|
4187
|
+
"Subject": [
|
|
4188
|
+
{ name: "value", type: "string", kind: "value", description: "The underlying string value." }
|
|
4189
|
+
],
|
|
4190
|
+
"EventTypeId": [
|
|
4191
|
+
{ name: "value", type: "string", kind: "value", description: "The underlying string value." }
|
|
4192
|
+
],
|
|
4193
|
+
"EventTypeGeneration": [
|
|
4194
|
+
{ name: "value", type: "uint", kind: "value", description: "The underlying uint value." }
|
|
4195
|
+
]
|
|
4196
|
+
};
|
|
4197
|
+
var eventContextPaths = [
|
|
4198
|
+
{ path: "eventType", name: "eventType", type: "EventType", kind: "composite", description: "The type of the event - its identifier, generation and whether it is a tombstone." },
|
|
4199
|
+
{ path: "eventType.id", name: "id", type: "EventTypeId", kind: "value", description: "The identifier of the event type." },
|
|
4200
|
+
{ path: "eventType.id.value", name: "value", type: "string", kind: "value", description: "The underlying string value." },
|
|
4201
|
+
{ path: "eventType.generation", name: "generation", type: "EventTypeGeneration", kind: "value", description: "The generation of the event type." },
|
|
4202
|
+
{ path: "eventType.generation.value", name: "value", type: "uint", kind: "value", description: "The underlying uint value." },
|
|
4203
|
+
{ path: "eventType.tombstone", name: "tombstone", type: "bool", kind: "value", description: "Whether the event is a tombstone event." },
|
|
4204
|
+
{ path: "eventSourceType", name: "eventSourceType", type: "EventSourceType", kind: "value", description: "The type of the event source the event was appended to." },
|
|
4205
|
+
{ path: "eventSourceType.value", name: "value", type: "string", kind: "value", description: "The underlying string value." },
|
|
4206
|
+
{ path: "eventSourceId", name: "eventSourceId", type: "EventSourceId", kind: "value", description: "The identifier of the event source the event was appended to - the value $eventSourceId resolves." },
|
|
4207
|
+
{ path: "eventSourceId.value", name: "value", type: "string", kind: "value", description: "The underlying string value." },
|
|
4208
|
+
{ path: "eventStreamType", name: "eventStreamType", type: "EventStreamType", kind: "value", description: "The type of the event stream the event belongs to." },
|
|
4209
|
+
{ path: "eventStreamType.value", name: "value", type: "string", kind: "value", description: "The underlying string value." },
|
|
4210
|
+
{ path: "eventStreamId", name: "eventStreamId", type: "EventStreamId", kind: "value", description: "The identifier of the event stream the event belongs to." },
|
|
4211
|
+
{ path: "eventStreamId.value", name: "value", type: "string", kind: "value", description: "The underlying string value." },
|
|
4212
|
+
{ path: "sequenceNumber", name: "sequenceNumber", type: "EventSequenceNumber", kind: "value", description: "The position of the event in its event sequence." },
|
|
4213
|
+
{ path: "sequenceNumber.value", name: "value", type: "ulong", kind: "value", description: "The underlying ulong value." },
|
|
4214
|
+
{ path: "occurred", name: "occurred", type: "DateTimeOffset", kind: "value", description: "When the event occurred - the time it was appended unless one was given." },
|
|
4215
|
+
{ path: "occurred.Week", name: "Week", type: "int", kind: "function", description: "The ISO 8601 week of the year the value falls in." },
|
|
4216
|
+
{ path: "eventStore", name: "eventStore", type: "EventStoreName", kind: "value", description: "The name of the event store the event belongs to." },
|
|
4217
|
+
{ path: "eventStore.value", name: "value", type: "string", kind: "value", description: "The underlying string value." },
|
|
4218
|
+
{ path: "namespace", name: "namespace", type: "EventStoreNamespaceName", kind: "value", description: "The namespace within the event store the event belongs to." },
|
|
4219
|
+
{ path: "namespace.value", name: "value", type: "string", kind: "value", description: "The underlying string value." },
|
|
4220
|
+
{ path: "correlationId", name: "correlationId", type: "CorrelationId", kind: "value", description: "The correlation identifier the event was appended with." },
|
|
4221
|
+
{ path: "correlationId.value", name: "value", type: "Guid", kind: "value", description: "The underlying Guid value." },
|
|
4222
|
+
{ path: "causation", name: "causation", type: "IEnumerable<Causation>", kind: "collection", description: "The chain of causes that led to the event - a collection, not addressable below." },
|
|
4223
|
+
{ path: "causedBy", name: "causedBy", type: "Identity", kind: "composite", description: "The identity that caused the event." },
|
|
4224
|
+
{ path: "causedBy.subject", name: "subject", type: "string", kind: "value", description: "The subject identifier of the identity." },
|
|
4225
|
+
{ path: "causedBy.name", name: "name", type: "string", kind: "value", description: "The display name of the identity." },
|
|
4226
|
+
{ path: "causedBy.userName", name: "userName", type: "string", kind: "value", description: "The user name of the identity." },
|
|
4227
|
+
{ path: "causedBy.onBehalfOf", name: "onBehalfOf", type: "Identity", kind: "composite", description: "The identity this identity acted on behalf of, if any - an identity with the same members." },
|
|
4228
|
+
{ path: "tags", name: "tags", type: "IEnumerable<Tag>", kind: "collection", description: "The tags the event was appended with - a collection, not addressable below." },
|
|
4229
|
+
{ path: "hash", name: "hash", type: "EventHash", kind: "value", description: "The hash of the event content." },
|
|
4230
|
+
{ path: "hash.value", name: "value", type: "string", kind: "value", description: "The underlying string value." },
|
|
4231
|
+
{ path: "observationState", name: "observationState", type: "EventObservationState", kind: "value", description: "Whether the observer sees the event for the first time or again on replay - differs between live processing and replay." },
|
|
4232
|
+
{ path: "subject", name: "subject", type: "Subject", kind: "value", description: "The compliance subject the event is about - the event source identifier unless one was given." },
|
|
4233
|
+
{ path: "subject.value", name: "value", type: "string", kind: "value", description: "The underlying string value." },
|
|
4234
|
+
{ path: "subjectIsEventSourceId", name: "subjectIsEventSourceId", type: "bool", kind: "value", description: "Whether the subject is the event source identifier." }
|
|
4235
|
+
];
|
|
4236
|
+
|
|
4237
|
+
// event-context.ts
|
|
4238
|
+
function namesEventContextMember(member, segment) {
|
|
4239
|
+
if (member.kind === "function") {
|
|
4240
|
+
return segment === member.name || segment === `${member.name}()`;
|
|
4197
4241
|
}
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4242
|
+
const declared = member.name[0].toUpperCase() + member.name.slice(1);
|
|
4243
|
+
return segment === declared || segment.length > 0 && segment[0].toUpperCase() + segment.slice(1) === declared;
|
|
4244
|
+
}
|
|
4245
|
+
var eventContextMembers = eventContextTypes[eventContextRootType];
|
|
4246
|
+
function eventContextMembersAfter(segments) {
|
|
4247
|
+
let members = eventContextMembers;
|
|
4248
|
+
for (const segment of segments) {
|
|
4249
|
+
const member = members.find((candidate) => namesEventContextMember(candidate, segment));
|
|
4250
|
+
if (!member || member.kind === "collection" || member.kind === "function") {
|
|
4251
|
+
return void 0;
|
|
4252
|
+
}
|
|
4253
|
+
members = eventContextTypes[member.type] ?? [];
|
|
4201
4254
|
}
|
|
4202
|
-
|
|
4203
|
-
|
|
4255
|
+
return members;
|
|
4256
|
+
}
|
|
4257
|
+
function eventContextMemberAt(segments) {
|
|
4258
|
+
if (segments.length === 0) {
|
|
4259
|
+
return void 0;
|
|
4204
4260
|
}
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4261
|
+
const members = eventContextMembersAfter(segments.slice(0, -1));
|
|
4262
|
+
return members?.find((member) => namesEventContextMember(member, segments[segments.length - 1]));
|
|
4263
|
+
}
|
|
4264
|
+
function resolveEventContextPath(path) {
|
|
4265
|
+
let current;
|
|
4266
|
+
let expected = eventContextMembers;
|
|
4267
|
+
for (const segment of path.split(".")) {
|
|
4268
|
+
if (segment.length === 0) {
|
|
4269
|
+
return { status: "missing", member: current, expected };
|
|
4270
|
+
}
|
|
4271
|
+
if (current?.kind === "collection") {
|
|
4272
|
+
return { status: "belowCollection", member: current, segment, expected: [] };
|
|
4273
|
+
}
|
|
4274
|
+
const next = expected.find((member) => namesEventContextMember(member, segment));
|
|
4275
|
+
if (!next) {
|
|
4276
|
+
return { status: current ? "unknownSubPath" : "unknownMember", member: current, segment, expected };
|
|
4211
4277
|
}
|
|
4278
|
+
current = next;
|
|
4279
|
+
expected = next.kind === "function" ? [] : eventContextTypes[next.type] ?? [];
|
|
4212
4280
|
}
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4281
|
+
return { status: "known", member: current, expected: [] };
|
|
4282
|
+
}
|
|
4283
|
+
function describeEventContext() {
|
|
4284
|
+
return [
|
|
4285
|
+
"**$eventContext**",
|
|
4286
|
+
"",
|
|
4287
|
+
"Metadata about the event being projected. Paths are checked against the event-context catalog; `causation` and `tags` are collections and cannot be addressed below.",
|
|
4288
|
+
"",
|
|
4289
|
+
"**Members:**",
|
|
4290
|
+
...eventContextMembers.map((member) => `- \`${member.name}\` (${member.type}) - ${member.description}`)
|
|
4291
|
+
].join("\n");
|
|
4292
|
+
}
|
|
4293
|
+
function describeEventContextMember(path, member) {
|
|
4294
|
+
const below = member.kind === "collection" || member.kind === "function" ? [] : eventContextTypes[member.type] ?? [];
|
|
4295
|
+
const lines = [`**$eventContext.${path}**: \`${member.type}\``, "", member.description];
|
|
4296
|
+
if (below.length > 0) {
|
|
4297
|
+
lines.push("", `**Members:** ${below.map((child) => `\`${child.name}\``).join(", ")}`);
|
|
4216
4298
|
}
|
|
4299
|
+
return lines.join("\n");
|
|
4300
|
+
}
|
|
4301
|
+
|
|
4302
|
+
// production-destinations.ts
|
|
4303
|
+
function productionDestinations(command) {
|
|
4304
|
+
const identifiers = command.properties.filter((property) => property.isIdentifier && !propertyTypeReference(property).isOptional && !propertyTypeReference(property).isCollection);
|
|
4305
|
+
const identifier = identifiers.length === 1 ? identifiers[0].name : void 0;
|
|
4306
|
+
const productions = command.produces ?? [];
|
|
4307
|
+
const mixed = productions.some((production) => production.target !== void 0 && production.target !== identifier) || productions.some((production) => production.inline && production.target === void 0) && productions.some((production) => !production.inline && production.target === void 0);
|
|
4308
|
+
return { identifier, mixed };
|
|
4309
|
+
}
|
|
4310
|
+
function destinationHints(lines) {
|
|
4311
|
+
const source = eventAnalysisSource(lines);
|
|
4312
|
+
return scanDocument(source).commands.flatMap((command) => {
|
|
4313
|
+
const { identifier, mixed } = productionDestinations(command);
|
|
4314
|
+
if (mixed || command.productionHeaders?.length !== command.produces?.length) return [];
|
|
4315
|
+
const hasPromotedDestination = command.produces?.some((sibling) => sibling.target !== void 0 || sibling.inline);
|
|
4316
|
+
return (command.produces ?? []).flatMap((production) => {
|
|
4317
|
+
if (production.target !== void 0 || production.inline && (identifier === void 0 || /\bgeneration\b/.test(source[production.line]))) return [];
|
|
4318
|
+
if (!production.inline && hasPromotedDestination) return [];
|
|
4319
|
+
return [{ line: production.line, column: source[production.line].length + 1, label: production.inline ? `for ${identifier}` : "for <new event source>" }];
|
|
4320
|
+
});
|
|
4321
|
+
});
|
|
4322
|
+
}
|
|
4323
|
+
|
|
4324
|
+
// diagnostic-codes.ts
|
|
4325
|
+
var diagnosticCodes = {
|
|
4326
|
+
eventSourceIdInPayload: "PLAY0469",
|
|
4327
|
+
explicitProducesTargetsRequired: "PLAY0470",
|
|
4328
|
+
redundantEventId: "PLAY0471",
|
|
4329
|
+
invalidEventId: "PLAY0472",
|
|
4330
|
+
inlineEventCollision: "PLAY0473",
|
|
4331
|
+
inlineEventOutsideCommand: "PLAY0474",
|
|
4332
|
+
inlineEventGeneration: "PLAY0475",
|
|
4333
|
+
reservedProductionMetadata: "PLAY0476",
|
|
4334
|
+
invalidEventDocumentation: "PLAY0477",
|
|
4335
|
+
tabIndentation: "PLAY0006",
|
|
4336
|
+
unknownPrimitiveType: "PLAY0008",
|
|
4337
|
+
unknownSliceType: "PLAY0028",
|
|
4338
|
+
duplicateCommandIdentifier: "PLAY0036",
|
|
4339
|
+
unknownContextPath: "PLAY0153",
|
|
4340
|
+
unknownContextCausedByProperty: "PLAY0154",
|
|
4341
|
+
unknownContextIdentityProperty: "PLAY0155",
|
|
4342
|
+
unclosedCodeBlock: "PLAY0164",
|
|
4343
|
+
unknownType: "PLAY0165",
|
|
4344
|
+
unknownEvent: "PLAY0166",
|
|
4345
|
+
unknownPolicy: "PLAY0167",
|
|
4346
|
+
duplicateDeclaration: "PLAY0168",
|
|
4347
|
+
unknownEventContextMember: "PLAY0295",
|
|
4348
|
+
unknownEventContextPath: "PLAY0296",
|
|
4349
|
+
eventContextPathBelowCollection: "PLAY0297",
|
|
4350
|
+
missingEventContextPath: "PLAY0298",
|
|
4351
|
+
unresolvedDynamicKeySource: "PLAY0299",
|
|
4352
|
+
invalidFileImport: "PLAY0454",
|
|
4353
|
+
omittedProductionDestination: "PLAY0478",
|
|
4354
|
+
legacyOptionalSuffix: "PLAY0479",
|
|
4355
|
+
invalidOptionalModifierOrder: "PLAY0480",
|
|
4356
|
+
optionalReadsNotSupported: "PLAY0481"
|
|
4217
4357
|
};
|
|
4218
4358
|
|
|
4219
|
-
//
|
|
4220
|
-
|
|
4221
|
-
|
|
4359
|
+
// file-imports.ts
|
|
4360
|
+
var fileImportPattern2 = /^import(\s+)"([^"\\]+)"\s*(?:\/\/.*)?$/;
|
|
4361
|
+
var quotedImportPattern = /^import\s+"/;
|
|
4362
|
+
function isFileImportLine(line) {
|
|
4363
|
+
return quotedImportPattern.test(line.trim());
|
|
4222
4364
|
}
|
|
4223
|
-
function
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4365
|
+
function fileImportOn(line, lineIndex) {
|
|
4366
|
+
const indent = indentOf(line);
|
|
4367
|
+
const match = line.slice(indent).match(fileImportPattern2);
|
|
4368
|
+
if (!match) return void 0;
|
|
4369
|
+
const startColumn = indent + "import".length + match[1].length + 2;
|
|
4370
|
+
return { pattern: match[2], line: lineIndex, startColumn, endColumn: startColumn + match[2].length };
|
|
4227
4371
|
}
|
|
4228
|
-
function
|
|
4229
|
-
const
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
visitEvent(event2) {
|
|
4236
|
-
eventsByLine.set(event2.location.line, event2);
|
|
4237
|
-
}
|
|
4238
|
-
}();
|
|
4239
|
-
walker.visitApplication(original.value);
|
|
4240
|
-
const counts = /* @__PURE__ */ new Map();
|
|
4241
|
-
const byLine = /* @__PURE__ */ new Map();
|
|
4242
|
-
const events = /* @__PURE__ */ new Map();
|
|
4243
|
-
let event;
|
|
4244
|
-
for (const line of lines) {
|
|
4245
|
-
event = eventsByLine.get(line.number) ?? event;
|
|
4246
|
-
if (event !== void 0)
|
|
4247
|
-
events.set(line.number, event);
|
|
4248
|
-
}
|
|
4249
|
-
for (const diagnostic of original.diagnostics) {
|
|
4250
|
-
counts.set(diagnostic.code, (counts.get(diagnostic.code) ?? 0) + 1);
|
|
4251
|
-
const line = lines[diagnostic.location.line - 1];
|
|
4252
|
-
const length = legacyOptionalTypeLength(line.raw, diagnostic);
|
|
4253
|
-
if (length > 0) {
|
|
4254
|
-
byLine.set(line.number, { line: line.number, fix: { diagnosticCode: diagnostic.code, title: "Use 'optional' instead of '?'", scope: "occurrence", edits: [{ start: line.startOffset + diagnostic.location.column + length - 2, length: 1, text: " optional" }] } });
|
|
4255
|
-
} else if (diagnostic.code === DiagnosticCodes.RedundantEventId && commentStart(line.raw) < 0) {
|
|
4256
|
-
const declaration = events.get(line.number);
|
|
4257
|
-
if (declaration?.id !== declaration?.name || declaration === void 0)
|
|
4258
|
-
continue;
|
|
4259
|
-
byLine.set(line.number, {
|
|
4260
|
-
line: line.number,
|
|
4261
|
-
fix: { diagnosticCode: diagnostic.code, title: "Remove the redundant event id", scope: "occurrence", edits: [{ start: line.startOffset, length: (lines[line.number]?.startOffset ?? source.length) - line.startOffset, text: "" }] },
|
|
4262
|
-
change: { node: declaration, replacement: { ...declaration, id: null } }
|
|
4263
|
-
});
|
|
4264
|
-
}
|
|
4372
|
+
function fileImports(lines) {
|
|
4373
|
+
const fences = fenceMap(lines);
|
|
4374
|
+
const found = [];
|
|
4375
|
+
for (let index = 0; index < lines.length; index++) {
|
|
4376
|
+
if (fences[index]) continue;
|
|
4377
|
+
const fileImport = fileImportOn(lines[index], index);
|
|
4378
|
+
if (fileImport) found.push(fileImport);
|
|
4265
4379
|
}
|
|
4266
|
-
|
|
4267
|
-
const syntax = verificationShape(original);
|
|
4268
|
-
const verified = /* @__PURE__ */ new Map();
|
|
4269
|
-
let rangeVerdicts;
|
|
4270
|
-
let documentChecked = false;
|
|
4271
|
-
let documentFix;
|
|
4272
|
-
const verify = (fix, change) => {
|
|
4273
|
-
const candidate = applyQuickFixEdits(source, fix.edits);
|
|
4274
|
-
if (candidate === void 0)
|
|
4275
|
-
return void 0;
|
|
4276
|
-
const parsed = parseForAuthoring(candidate, void 0, options.placement);
|
|
4277
|
-
if (!parsed.success || verificationShape(parsed) !== (change === void 0 ? syntax : verificationShape(original, [change])))
|
|
4278
|
-
return void 0;
|
|
4279
|
-
return parsed.diagnostics.filter((diagnostic) => diagnostic.code === fix.diagnosticCode).length === (counts.get(fix.diagnosticCode) ?? 0) - fix.edits.length ? fix : void 0;
|
|
4280
|
-
};
|
|
4281
|
-
return (line, diagnosticCode) => {
|
|
4282
|
-
const requests = typeof line === "number" || line === void 0 ? void 0 : line;
|
|
4283
|
-
const includeDocument = requests === void 0 ? diagnosticCode === void 0 || diagnosticCode === DiagnosticCodes.LegacyOptionalSuffix : requests.some((request) => request.diagnosticCode === DiagnosticCodes.LegacyOptionalSuffix);
|
|
4284
|
-
if (includeDocument && !documentChecked) {
|
|
4285
|
-
if (optional.length > 0)
|
|
4286
|
-
documentFix = verify({ diagnosticCode: DiagnosticCodes.LegacyOptionalSuffix, title: "Use 'optional' throughout this document", scope: "document", edits: optional.flatMap((candidate) => candidate.fix.edits) });
|
|
4287
|
-
documentChecked = true;
|
|
4288
|
-
}
|
|
4289
|
-
if (requests !== void 0) {
|
|
4290
|
-
if (rangeVerdicts === void 0) {
|
|
4291
|
-
rangeVerdicts = /* @__PURE__ */ new Map();
|
|
4292
|
-
const candidates = lines.flatMap((line2) => byLine.has(line2.number) ? [byLine.get(line2.number)] : []);
|
|
4293
|
-
const edits = candidates.flatMap((candidate) => candidate.fix.edits);
|
|
4294
|
-
const candidateSource = applyQuickFixEdits(source, edits);
|
|
4295
|
-
if (edits.length > 0 && candidateSource !== void 0) {
|
|
4296
|
-
const parsed = parseForAuthoring(candidateSource, void 0, options.placement);
|
|
4297
|
-
const changes = candidates.flatMap((candidate) => candidate.change === void 0 ? [] : [candidate.change]);
|
|
4298
|
-
if (parsed.success && verificationShape(parsed) === verificationShape(original, changes)) {
|
|
4299
|
-
const remaining = /* @__PURE__ */ new Map();
|
|
4300
|
-
const removed = /* @__PURE__ */ new Map();
|
|
4301
|
-
for (const diagnostic of parsed.diagnostics)
|
|
4302
|
-
remaining.set(diagnostic.code, (remaining.get(diagnostic.code) ?? 0) + 1);
|
|
4303
|
-
for (const candidate of candidates)
|
|
4304
|
-
removed.set(candidate.fix.diagnosticCode, (removed.get(candidate.fix.diagnosticCode) ?? 0) + candidate.fix.edits.length);
|
|
4305
|
-
if ([...removed].every(([code, count]) => (remaining.get(code) ?? 0) === (counts.get(code) ?? 0) - count)) {
|
|
4306
|
-
for (const candidate of candidates)
|
|
4307
|
-
rangeVerdicts.set(candidate.line, candidate.fix);
|
|
4308
|
-
}
|
|
4309
|
-
}
|
|
4310
|
-
}
|
|
4311
|
-
}
|
|
4312
|
-
const selected2 = /* @__PURE__ */ new Map();
|
|
4313
|
-
for (const request of requests) {
|
|
4314
|
-
const fix = rangeVerdicts.get(request.line);
|
|
4315
|
-
if (fix?.diagnosticCode === request.diagnosticCode)
|
|
4316
|
-
selected2.set(request.line, fix);
|
|
4317
|
-
}
|
|
4318
|
-
return [...selected2.values(), ...includeDocument && documentFix !== void 0 ? [documentFix] : []];
|
|
4319
|
-
}
|
|
4320
|
-
const occurrenceLine = typeof line === "number" ? line : void 0;
|
|
4321
|
-
const selected = occurrenceLine === void 0 ? void 0 : byLine.get(occurrenceLine);
|
|
4322
|
-
let occurrenceFix;
|
|
4323
|
-
if (selected !== void 0 && occurrenceLine !== void 0 && (diagnosticCode === void 0 || selected.fix.diagnosticCode === diagnosticCode)) {
|
|
4324
|
-
if (!verified.has(occurrenceLine)) {
|
|
4325
|
-
if (verified.size === 32)
|
|
4326
|
-
verified.delete(verified.keys().next().value);
|
|
4327
|
-
verified.set(occurrenceLine, verify(selected.fix, selected.change));
|
|
4328
|
-
}
|
|
4329
|
-
occurrenceFix = verified.get(occurrenceLine);
|
|
4330
|
-
}
|
|
4331
|
-
return [occurrenceFix, includeDocument ? documentFix : void 0].filter((fix) => fix !== void 0);
|
|
4332
|
-
};
|
|
4380
|
+
return found;
|
|
4333
4381
|
}
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4382
|
+
var folderOf = (path) => path.split("/").slice(0, -1);
|
|
4383
|
+
function relativeTo(from, path) {
|
|
4384
|
+
const segments = path.split("/");
|
|
4385
|
+
let common = 0;
|
|
4386
|
+
while (common < from.length && common < segments.length - 1 && from[common] === segments[common]) common++;
|
|
4387
|
+
return [...from.slice(common).map(() => ".."), ...segments.slice(common)].join("/");
|
|
4337
4388
|
}
|
|
4338
|
-
function
|
|
4339
|
-
const
|
|
4340
|
-
|
|
4341
|
-
for (const
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4389
|
+
function importablePaths(documentPath, files) {
|
|
4390
|
+
const from = folderOf(documentPath);
|
|
4391
|
+
const paths = /* @__PURE__ */ new Set();
|
|
4392
|
+
for (const file of files.filter((candidate) => candidate !== documentPath && candidate.toLowerCase().endsWith(".play"))) {
|
|
4393
|
+
const relative = relativeTo(from, file);
|
|
4394
|
+
const folders = folderOf(relative);
|
|
4395
|
+
paths.add(relative);
|
|
4396
|
+
paths.add([...folders, "*.play"].join("/"));
|
|
4397
|
+
for (let depth = 0; depth <= folders.length; depth++) {
|
|
4398
|
+
paths.add([...folders.slice(0, depth), "**", "*.play"].join("/"));
|
|
4399
|
+
}
|
|
4346
4400
|
}
|
|
4347
|
-
|
|
4348
|
-
return parts.join("");
|
|
4401
|
+
return [...paths].sort();
|
|
4349
4402
|
}
|
|
4350
4403
|
|
|
4351
4404
|
// inline-event-validation.ts
|
|
@@ -4799,12 +4852,19 @@ export {
|
|
|
4799
4852
|
languageConfiguration,
|
|
4800
4853
|
typeReferenceSymbol,
|
|
4801
4854
|
typeReferenceText,
|
|
4855
|
+
DiagnosticCodes,
|
|
4856
|
+
isQuickFixDiagnostic,
|
|
4857
|
+
prepareQuickFixes,
|
|
4802
4858
|
indentOf,
|
|
4803
4859
|
firstWord,
|
|
4804
4860
|
fenceMap,
|
|
4805
4861
|
enclosingChain,
|
|
4806
4862
|
nearestEnclosingLine,
|
|
4807
4863
|
eventAnalysisSource,
|
|
4864
|
+
fileReferenceKeyword,
|
|
4865
|
+
isAbsoluteFileReferencePath,
|
|
4866
|
+
fileReferenceOn,
|
|
4867
|
+
fileReferences,
|
|
4808
4868
|
propertyTypeReference,
|
|
4809
4869
|
directBody,
|
|
4810
4870
|
scanDocument,
|
|
@@ -4822,9 +4882,6 @@ export {
|
|
|
4822
4882
|
describeEventContextMember,
|
|
4823
4883
|
productionDestinations,
|
|
4824
4884
|
destinationHints,
|
|
4825
|
-
DiagnosticCodes,
|
|
4826
|
-
isQuickFixDiagnostic,
|
|
4827
|
-
prepareQuickFixes,
|
|
4828
4885
|
diagnosticCodes,
|
|
4829
4886
|
isFileImportLine,
|
|
4830
4887
|
fileImportOn,
|
|
@@ -4833,4 +4890,4 @@ export {
|
|
|
4833
4890
|
validateLines,
|
|
4834
4891
|
validateEventContextPaths
|
|
4835
4892
|
};
|
|
4836
|
-
//# sourceMappingURL=chunk-
|
|
4893
|
+
//# sourceMappingURL=chunk-LXM5L4YK.js.map
|