@voidaliot/swaml-cli 0.15.0 → 0.17.0

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/bin/diagram.mjs CHANGED
File without changes
package/bin/validate.mjs CHANGED
File without changes
package/dist/cli.mjs CHANGED
@@ -152480,7 +152480,7 @@ var require_react_dom_server_legacy_node_development = __commonJS({
152480
152480
  h1 = 3266489909 * (h1 & 65535) + ((3266489909 * (h1 >>> 16) & 65535) << 16) & 4294967295;
152481
152481
  return (h1 ^ h1 >>> 16) >>> 0;
152482
152482
  }
152483
- function typeName(value2) {
152483
+ function typeName2(value2) {
152484
152484
  return "function" === typeof Symbol && Symbol.toStringTag && value2[Symbol.toStringTag] || value2.constructor.name || "Object";
152485
152485
  }
152486
152486
  function willCoercionThrow(value2) {
@@ -152498,7 +152498,7 @@ var require_react_dom_server_legacy_node_development = __commonJS({
152498
152498
  return console.error(
152499
152499
  "The provided `%s` attribute is an unsupported type %s. This value must be coerced to a string before using it here.",
152500
152500
  attributeName,
152501
- typeName(value2)
152501
+ typeName2(value2)
152502
152502
  ), testStringCoercion(value2);
152503
152503
  }
152504
152504
  function checkCSSPropertyStringCoercion(value2, propName) {
@@ -152506,14 +152506,14 @@ var require_react_dom_server_legacy_node_development = __commonJS({
152506
152506
  return console.error(
152507
152507
  "The provided `%s` CSS property is an unsupported type %s. This value must be coerced to a string before using it here.",
152508
152508
  propName,
152509
- typeName(value2)
152509
+ typeName2(value2)
152510
152510
  ), testStringCoercion(value2);
152511
152511
  }
152512
152512
  function checkHtmlStringCoercion(value2) {
152513
152513
  if (willCoercionThrow(value2))
152514
152514
  return console.error(
152515
152515
  "The provided HTML markup uses a value of unsupported type %s. This value must be coerced to a string before using it here.",
152516
- typeName(value2)
152516
+ typeName2(value2)
152517
152517
  ), testStringCoercion(value2);
152518
152518
  }
152519
152519
  function isAttributeNameSafe(attributeName) {
@@ -154854,7 +154854,7 @@ var require_react_dom_server_legacy_node_development = __commonJS({
154854
154854
  willCoercionThrow(value2) && (console.error(
154855
154855
  "The provided `%s` option is an unsupported type %s. This value must be coerced to a string before using it here.",
154856
154856
  name2,
154857
- typeName(value2)
154857
+ typeName2(value2)
154858
154858
  ), testStringCoercion(value2));
154859
154859
  return ("" + value2).replace(
154860
154860
  regexForLinkHeaderQuotedParamValueContext,
@@ -160025,7 +160025,7 @@ var require_react_dom_server_node_development = __commonJS({
160025
160025
  function byteLengthOfChunk(chunk) {
160026
160026
  return "string" === typeof chunk ? Buffer.byteLength(chunk, "utf8") : chunk.byteLength;
160027
160027
  }
160028
- function typeName(value2) {
160028
+ function typeName2(value2) {
160029
160029
  return "function" === typeof Symbol && Symbol.toStringTag && value2[Symbol.toStringTag] || value2.constructor.name || "Object";
160030
160030
  }
160031
160031
  function willCoercionThrow(value2) {
@@ -160043,7 +160043,7 @@ var require_react_dom_server_node_development = __commonJS({
160043
160043
  return console.error(
160044
160044
  "The provided `%s` attribute is an unsupported type %s. This value must be coerced to a string before using it here.",
160045
160045
  attributeName,
160046
- typeName(value2)
160046
+ typeName2(value2)
160047
160047
  ), testStringCoercion(value2);
160048
160048
  }
160049
160049
  function checkCSSPropertyStringCoercion(value2, propName) {
@@ -160051,14 +160051,14 @@ var require_react_dom_server_node_development = __commonJS({
160051
160051
  return console.error(
160052
160052
  "The provided `%s` CSS property is an unsupported type %s. This value must be coerced to a string before using it here.",
160053
160053
  propName,
160054
- typeName(value2)
160054
+ typeName2(value2)
160055
160055
  ), testStringCoercion(value2);
160056
160056
  }
160057
160057
  function checkHtmlStringCoercion(value2) {
160058
160058
  if (willCoercionThrow(value2))
160059
160059
  return console.error(
160060
160060
  "The provided HTML markup uses a value of unsupported type %s. This value must be coerced to a string before using it here.",
160061
- typeName(value2)
160061
+ typeName2(value2)
160062
160062
  ), testStringCoercion(value2);
160063
160063
  }
160064
160064
  function isAttributeNameSafe(attributeName) {
@@ -162556,7 +162556,7 @@ var require_react_dom_server_node_development = __commonJS({
162556
162556
  willCoercionThrow(value2) && (console.error(
162557
162557
  "The provided `%s` option is an unsupported type %s. This value must be coerced to a string before using it here.",
162558
162558
  name2,
162559
- typeName(value2)
162559
+ typeName2(value2)
162560
162560
  ), testStringCoercion(value2));
162561
162561
  return ("" + value2).replace(
162562
162562
  regexForLinkHeaderQuotedParamValueContext,
@@ -169329,12 +169329,26 @@ function depthInside(outer, all2) {
169329
169329
  }
169330
169330
 
169331
169331
  // packages/diagram-protocol/out/overlay.js
169332
- var without = (meta) => {
169333
- if (!meta || !("overlay" in meta))
169334
- return meta;
169335
- const { overlay: _overlay, ...rest } = meta;
169336
- return rest;
169337
- };
169332
+ function withoutDecoration(value2, kind2) {
169333
+ if (!value2 || kind2 === void 0)
169334
+ return void 0;
169335
+ const previous3 = value2.previous && withoutDecoration(value2.previous, kind2);
169336
+ if (value2.kind === kind2)
169337
+ return previous3;
169338
+ if (previous3 === value2.previous)
169339
+ return value2;
169340
+ const { previous: _previous, ...rest } = value2;
169341
+ return previous3 ? { ...rest, previous: previous3 } : rest;
169342
+ }
169343
+ function clearDecoration(item, kind2) {
169344
+ if (!("overlay" in item))
169345
+ return item;
169346
+ const overlay = withoutDecoration(item.overlay, kind2);
169347
+ if (overlay === item.overlay)
169348
+ return item;
169349
+ const { overlay: _overlay, ...rest } = item;
169350
+ return overlay ? { ...rest, overlay } : rest;
169351
+ }
169338
169352
  function overlayDecoration(item) {
169339
169353
  const value2 = item?.overlay ?? item?.meta?.overlay;
169340
169354
  return value2 && typeof value2 === "object" ? value2 : void 0;
@@ -169344,20 +169358,12 @@ function diagramOverlays(model) {
169344
169358
  }
169345
169359
  function clearDiagramOverlay(model, kind2) {
169346
169360
  const kept = diagramOverlays(model).filter((item) => kind2 !== void 0 && item.kind !== kind2);
169347
- const owned = (meta) => !kind2 || meta?.overlay?.kind === kind2;
169348
- const clean2 = (item) => owned(item.meta) && item.meta && "overlay" in item.meta ? { ...item, meta: without(item.meta) } : item;
169349
- const markers = (meta) => Array.isArray(meta?.markers) ? { ...meta, markers: meta.markers.map((marker) => {
169350
- if (!("overlay" in marker) || kind2 && marker.overlay.kind !== kind2)
169351
- return marker;
169352
- const { overlay: _overlay, ...rest } = marker;
169353
- return rest;
169354
- }) } : meta;
169355
- const fragments = Array.isArray(model.meta?.fragments) ? model.meta.fragments.map((fragment2) => {
169356
- if (!("overlay" in fragment2) || kind2 && fragment2.overlay.kind !== kind2)
169357
- return fragment2;
169358
- const { overlay: _overlay, ...rest } = fragment2;
169359
- return rest;
169360
- }) : model.meta?.fragments;
169361
+ const clean2 = (item) => {
169362
+ const meta = item.meta && clearDecoration(item.meta, kind2);
169363
+ return meta === item.meta ? item : { ...item, meta };
169364
+ };
169365
+ const markers = (meta) => Array.isArray(meta?.markers) ? { ...meta, markers: meta.markers.map((marker) => clearDecoration(marker, kind2)) } : meta;
169366
+ const fragments = Array.isArray(model.meta?.fragments) ? model.meta.fragments.map((fragment2) => clearDecoration(fragment2, kind2)) : model.meta?.fragments;
169361
169367
  return {
169362
169368
  ...model,
169363
169369
  nodes: model.nodes.map((node2) => {
@@ -169373,18 +169379,18 @@ function applyDiagramOverlay(model, overlay) {
169373
169379
  const base2 = clearDiagramOverlay(model, overlay.kind);
169374
169380
  const decorations = overlay.stale ? {} : overlay.elements, markers = overlay.stale ? {} : overlay.markers ?? {};
169375
169381
  let decorated = 0;
169376
- const tag = (value2) => {
169382
+ const tag = (value2, previous3) => {
169377
169383
  decorated++;
169378
- return { ...value2, kind: overlay.kind };
169384
+ return { ...value2, kind: overlay.kind, ...previous3 ? { previous: previous3 } : {} };
169379
169385
  };
169380
- const decorate = (item) => decorations[item.id] ? { ...item, meta: { ...item.meta, overlay: tag(decorations[item.id]) } } : item;
169386
+ const decorate = (item) => decorations[item.id] ? { ...item, meta: { ...item.meta, overlay: tag(decorations[item.id], item.meta?.overlay) } } : item;
169381
169387
  const nodes2 = base2.nodes.map((node2) => {
169382
169388
  const next = decorate(node2);
169383
169389
  if (!Array.isArray(next.meta?.markers))
169384
169390
  return next;
169385
- return { ...next, meta: { ...next.meta, markers: next.meta.markers.map((marker) => typeof marker.statement === "string" && markers[marker.statement] ? { ...marker, overlay: tag(markers[marker.statement]) } : marker) } };
169391
+ return { ...next, meta: { ...next.meta, markers: next.meta.markers.map((marker) => typeof marker.statement === "string" && markers[marker.statement] ? { ...marker, overlay: tag(markers[marker.statement], marker.overlay) } : marker) } };
169386
169392
  });
169387
- const fragments = Array.isArray(base2.meta?.fragments) ? base2.meta.fragments.map((fragment2) => typeof fragment2.id === "string" && decorations[fragment2.id] ? { ...fragment2, overlay: tag(decorations[fragment2.id]) } : fragment2) : base2.meta?.fragments;
169393
+ const fragments = Array.isArray(base2.meta?.fragments) ? base2.meta.fragments.map((fragment2) => typeof fragment2.id === "string" && decorations[fragment2.id] ? { ...fragment2, overlay: tag(decorations[fragment2.id], fragment2.overlay) } : fragment2) : base2.meta?.fragments;
169388
169394
  const edges = base2.edges.map(decorate), frames = base2.frames?.map(decorate);
169389
169395
  const { elements: _elements, markers: _markers, ...summary } = overlay;
169390
169396
  return {
@@ -169645,6 +169651,21 @@ init_semantic();
169645
169651
  init_lib2();
169646
169652
  init_ast2();
169647
169653
  init_semantic();
169654
+
169655
+ // packages/language-server/src/diagram-names.ts
169656
+ init_names();
169657
+ function diagramElementName(path7, sourceSpelling = false) {
169658
+ return (sourceSpelling ? parsePathInput(path7) : path7).replace(/^.*(?:::|\.)/u, "");
169659
+ }
169660
+ function usageName(definition3) {
169661
+ const words = definition3.split(/[^A-Za-z0-9_]+/u).filter(Boolean);
169662
+ if (!words.length || /[^A-Za-z0-9_ ]/u.test(definition3)) return definition3[0].toLowerCase() + definition3.slice(1);
169663
+ const lower2 = (word) => /^[A-Z0-9]+$/u.test(word) ? word.toLowerCase() : word[0].toLowerCase() + word.slice(1);
169664
+ const value2 = lower2(words[0]) + words.slice(1).map((word) => word[0].toUpperCase() + word.slice(1)).join("");
169665
+ return /^[_A-Za-z]/u.test(value2) ? value2 : "_" + value2;
169666
+ }
169667
+
169668
+ // packages/language-server/src/behavior-projection.ts
169648
169669
  var text = (node2) => node2?.$cstNode?.text.replace(/\s+/gu, " ").trim() ?? "";
169649
169670
  var args = (values) => values.map(text).join(", ");
169650
169671
  var Builder = class {
@@ -169685,7 +169706,7 @@ var Builder = class {
169685
169706
  }
169686
169707
  place(pkg, path7, structure2) {
169687
169708
  const id2 = diagramId(pkg.name + "::" + path7);
169688
- this.lifeline({ id: id2, name: path7, role: "occurrence", path: path7, type: definitionName(structure2), source: source(structure2) });
169709
+ this.lifeline({ id: id2, name: diagramElementName(path7), role: "occurrence", path: path7, type: definitionName(structure2), source: source(structure2) });
169689
169710
  return { pkg, path: path7, structure: structure2, routes: this.routesOf(pkg), lifeline: id2 };
169690
169711
  }
169691
169712
  message(item) {
@@ -170207,7 +170228,7 @@ function executable(root6, ctx, options2) {
170207
170228
  const id3 = diagramId(pkg.name + "::" + occurrence.path);
170208
170229
  if (participants.some((item) => item.id === id3)) continue;
170209
170230
  const type = isComponentUsage(occurrence.structure) ? occurrence.structure.definition?.ref?.name : void 0;
170210
- participants.push(node2({ id: id3, name: occurrence.path, role: "occurrence", path: occurrence.path, type, source: source(occurrence.structure) }, false));
170231
+ participants.push(node2({ id: id3, name: diagramElementName(occurrence.path), role: "occurrence", path: occurrence.path, type, source: source(occurrence.structure) }, false));
170211
170232
  }
170212
170233
  const occurrencePath = isScenario(root6) ? void 0 : options2.path?.includes("::") ? options2.path.slice(options2.path.indexOf("::") + 2, options2.path.lastIndexOf(".")) : projection2.lifelines[0]?.path ?? projection2.lifelines[0]?.name;
170213
170234
  return { id: id2, name: root6.name, kind: projection2.root.kind, subjectId: subject ? diagramId(identity2(subject)) : void 0, ...occurrencePath ? { occurrencePath } : {}, source: source(root6), projection: projection2, participants };
@@ -170314,14 +170335,14 @@ function siteAt(document4, position3, sites) {
170314
170335
  }
170315
170336
 
170316
170337
  // packages/language-server/src/run-evidence.ts
170317
- init_lib2();
170318
170338
  init_ast2();
170319
170339
  init_semantic();
170320
170340
  var store = /* @__PURE__ */ new Map();
170321
- var canonical = (revisions2) => Object.fromEntries(Object.entries(revisions2).map(([uri, value2]) => [URI2.parse(uri).toString(), value2]));
170341
+ var sourceKeys = (revisions2) => Object.fromEntries(Object.entries(revisions2).map(([uri, value2]) => [sourceUriKey(uri), value2]));
170342
+ var currentEvidence = (evidence2, revisions2) => runEvidenceCurrent({ sourceRevisions: sourceKeys(evidence2.sourceRevisions) }, revisions2);
170322
170343
  function storedRunEvidence(revisions2) {
170323
- const current = canonical(revisions2);
170324
- return [...store.values()].reverse().map((item) => runEvidenceCurrent(item, current) ? item : { ...item, stale: true });
170344
+ const current = sourceKeys(revisions2);
170345
+ return [...store.values()].reverse().filter((item) => Object.hasOwn(current, sourceUriKey(item.caseUri))).map((item) => currentEvidence(item, current) ? item : { ...item, stale: true });
170325
170346
  }
170326
170347
 
170327
170348
  // packages/language-server/src/inlay-hints.ts
@@ -170741,15 +170762,6 @@ function memberUsersStubs(models, owner2, member, initial) {
170741
170762
  return users.map(({ structure: structure2, port }) => memberStubs(structure2, port.name, member, member.direction === "provides" !== port.reversed, (type) => initial(structure2, type)));
170742
170763
  }
170743
170764
 
170744
- // packages/language-server/src/diagram-names.ts
170745
- function usageName(definition3) {
170746
- const words = definition3.split(/[^A-Za-z0-9_]+/u).filter(Boolean);
170747
- if (!words.length || /[^A-Za-z0-9_ ]/u.test(definition3)) return definition3[0].toLowerCase() + definition3.slice(1);
170748
- const lower2 = (word) => /^[A-Z0-9]+$/u.test(word) ? word.toLowerCase() : word[0].toLowerCase() + word.slice(1);
170749
- const value2 = lower2(words[0]) + words.slice(1).map((word) => word[0].toUpperCase() + word.slice(1)).join("");
170750
- return /^[_A-Za-z]/u.test(value2) ? value2 : "_" + value2;
170751
- }
170752
-
170753
170765
  // packages/language-server/src/diagram-port-connections.ts
170754
170766
  init_lib2();
170755
170767
  init_ast2();
@@ -171091,24 +171103,33 @@ var fresh2 = (base2, used) => {
171091
171103
  };
171092
171104
  var forwards = (structure2, port) => members(structure2).filter(isConnect).some((link4) => link4.source === port && link4.target.includes(".") || link4.target === port && link4.source.includes("."));
171093
171105
  var memberNames = (structure2) => new Set(members(structure2).map((item) => item.name).filter(Boolean));
171094
- function lifeline(models, home, value2, what) {
171106
+ function lifeline(models, home, value2, what, scenario) {
171095
171107
  const typed2 = value2.trim();
171096
- if (typed2 === "\xABtest\xBB" || typed2.endsWith("::$test")) return { kind: "test" };
171097
- if (typed2.endsWith("::$script")) throw Error("A use case without actors has no lifeline to act from. Associate an actor with it first.");
171098
171108
  const gate2 = /^(.*)::\$port:(.+)$/u.exec(typed2), id2 = gate2 ? gate2[1] : typed2;
171109
+ const ids = [.../* @__PURE__ */ new Set([id2, parsePathInput(id2)])];
171099
171110
  const find3 = (pkg, path7) => connectionRoutes(pkg).occurrences.find((item) => item.path === path7);
171100
- const packages = [home, ...models.flatMap((model) => model.packages).filter((item) => local3(item) && item !== home)];
171101
- for (const pkg of packages) {
171102
- const prefix = diagramId(pkg.name) + "::";
171103
- if (!id2.startsWith(prefix)) continue;
171104
- const found2 = find3(pkg, id2.slice(prefix.length).split("::").join("."));
171111
+ const prefix = diagramId(home.name) + "::";
171112
+ let found = ids.filter((candidate) => candidate.startsWith(prefix) || !candidate.includes("::")).map((candidate) => find3(home, (candidate.startsWith(prefix) ? candidate.slice(prefix.length) : candidate).split("::").join("."))).find(Boolean);
171113
+ if (found) return { kind: "occurrence", pkg: home, path: found.path, structure: found.structure, ...gate2 ? { port: gate2[2] } : {} };
171114
+ const scenarioId = scenario && diagramId(identity2(scenario));
171115
+ if (scenario && (typed2 === "\xABtest\xBB" || ids.includes(scenarioId + "::$test"))) {
171116
+ if (scenario.kind !== "test") throw Error("Only a test calls its subject directly; a use case acts through the ports of its actors.");
171117
+ return { kind: "test" };
171118
+ }
171119
+ if (scenario?.kind === "useCase" && ids.includes(scenarioId + "::$script")) throw Error("A use case without actors has no lifeline to act from. Associate an actor with it first.");
171120
+ const packages = models.flatMap((model) => model.packages).filter((item) => local3(item) && item !== home);
171121
+ for (const candidate of ids) for (const pkg of packages) {
171122
+ const prefix2 = diagramId(pkg.name) + "::";
171123
+ if (!candidate.startsWith(prefix2)) continue;
171124
+ const found2 = find3(pkg, candidate.slice(prefix2.length).split("::").join("."));
171105
171125
  if (found2) return { kind: "occurrence", pkg, path: found2.path, structure: found2.structure, ...gate2 ? { port: gate2[2] } : {} };
171106
171126
  }
171107
- const found = find3(home, parsePathInput(id2).split("::").join("."));
171108
- if (found) return { kind: "occurrence", pkg: home, path: found.path, structure: found.structure };
171127
+ found = ids.map((candidate) => find3(home, candidate.split("::").join("."))).find(Boolean);
171128
+ if (found) return { kind: "occurrence", pkg: home, path: found.path, structure: found.structure, ...gate2 ? { port: gate2[2] } : {} };
171109
171129
  throw Error(`${typed2} is not an occurrence of ${home.name}. Choose one of its lifelines for where the message ${what}.`);
171110
171130
  }
171111
171131
  function connected(from, to) {
171132
+ if (to) samePackage(from, to);
171112
171133
  const routes = connectionRoutes(from.pkg), out = [];
171113
171134
  for (const link4 of routes.links) for (const [mine, other] of [[0, 1], [1, 0]]) {
171114
171135
  const end = link4.ends[mine], peer = link4.ends[other], cut = end.lastIndexOf("."), peerCut = peer.lastIndexOf(".");
@@ -171120,6 +171141,9 @@ function connected(from, to) {
171120
171141
  }
171121
171142
  return out;
171122
171143
  }
171144
+ function samePackage(from, to) {
171145
+ if (from.pkg !== to.pkg) throw Error("Messages cannot connect occurrences from different packages. Choose lifelines of the same package.");
171146
+ }
171123
171147
  function addMessage(plan, request) {
171124
171148
  const { models } = plan, kind2 = request.kind;
171125
171149
  if (!["send", "publish", "call"].includes(kind2)) throw Error("Choose send, publish or call for the message.");
@@ -171194,6 +171218,7 @@ function useMember(w2, port, initiator, emitter) {
171194
171218
  return shape;
171195
171219
  }
171196
171220
  function newRoute(w2, initiator, receiver, portName, emitter) {
171221
+ samePackage(initiator, receiver);
171197
171222
  const first2 = declaring(initiator.structure), second = declaring(receiver.structure);
171198
171223
  if (first2 === second) throw Error(`${initiator.path} and ${receiver.path} share one declaration. Connect them in Interconnect View first.`);
171199
171224
  for (const structure2 of [first2, second]) if (!local3(structure2)) throw Error("Standard-library declarations are read-only.");
@@ -171239,8 +171264,10 @@ function scriptMessage(w2, scenario, pkg) {
171239
171264
  const subject = caseSubject(scenario), { request, kind: kind2, name: name2, segments } = w2;
171240
171265
  const typedFrom = request.from?.trim() || (segments.length === 3 ? segments[0] : "");
171241
171266
  if (!typedFrom) throw Error("Choose the lifeline the message starts on, or write actor.port.member.");
171242
- const from = lifeline(w2.plan.models, pkg, typedFrom, "starts");
171243
- let to = request.to?.trim() ? lifeline(w2.plan.models, pkg, request.to, "ends") : void 0;
171267
+ const from = lifeline(w2.plan.models, pkg, typedFrom, "starts", scenario);
171268
+ let to = request.to?.trim() ? lifeline(w2.plan.models, pkg, request.to, "ends", scenario) : void 0;
171269
+ if (from.kind === "occurrence" && from.pkg !== pkg || to?.kind === "occurrence" && to.pkg !== pkg)
171270
+ throw Error(`A case uses only occurrences of its own package. Choose lifelines from ${pkg.name}.`);
171244
171271
  if (from.kind === "test") {
171245
171272
  if (scenario.kind !== "test") throw Error("Only a test calls its subject directly; a use case acts through the ports of its actors.");
171246
171273
  if (kind2 !== "call") throw Error("A test calls operations of its subject. To send or publish, start the message on an actor.");
@@ -171258,7 +171285,7 @@ function scriptMessage(w2, scenario, pkg) {
171258
171285
  const args2 = request.value?.trim() || parameters2.map((type) => w2.initial(scenario, type)).join(", ");
171259
171286
  return callStatement(formatPath(to.path) + "." + formatName(name2) + "(" + args2 + ")", name2, result, scenario);
171260
171287
  }
171261
- const isActor = (item) => item?.kind === "occurrence" && !item.path.includes(".") && item.structure !== subject && !active(item.structure);
171288
+ const isActor = (item) => item?.kind === "occurrence" && item.pkg === pkg && !item.path.includes(".") && item.structure !== subject && !active(item.structure);
171262
171289
  const outgoing = isActor(from) || !isActor(to);
171263
171290
  const actor = outgoing ? from : to;
171264
171291
  if (!isActor(actor)) {
@@ -171310,7 +171337,9 @@ function operationMessage(w2, executable2, pkg) {
171310
171337
  return found && { kind: "occurrence", pkg, path: found.path, structure: found.structure };
171311
171338
  })();
171312
171339
  let to = request.to?.trim() ? lifeline(w2.plan.models, pkg, request.to, "ends") : void 0;
171313
- if (from?.kind === "occurrence" && to?.kind === "occurrence" && to.path === from.path || !from && !to) {
171340
+ if (from?.kind === "occurrence" && !runs(from)) throw Error(`${executable2.name} does not run on ${from.path}. Start the message on its activation.`);
171341
+ if (from?.kind === "occurrence" && to?.kind === "occurrence") samePackage(from, to);
171342
+ if (from?.kind === "occurrence" && to?.kind === "occurrence" && to.pkg === from.pkg && to.path === from.path || !from && !to) {
171314
171343
  if (kind2 !== "call") throw Error("A component does not send to itself. Call one of its operations, or draw the message to another lifeline.");
171315
171344
  const op = members(structure2).filter(isExecutable).find((item) => item.name === name2), sig = op && signatureOf(op);
171316
171345
  if (op === executable2) throw Error(`${name2} would call itself. Choose another operation.`);
@@ -171324,7 +171353,6 @@ function operationMessage(w2, executable2, pkg) {
171324
171353
  return callStatement(formatName(name2) + "(" + args3 + ")", name2, result, executable2);
171325
171354
  }
171326
171355
  if (from?.kind !== "occurrence") throw Error("Start the message on the lifeline of a component occurrence.");
171327
- if (!runs(from)) throw Error(`${executable2.name} does not run on ${from.path}. Start the message on its activation.`);
171328
171356
  const portName = segments.length === 2 ? segments[0] : void 0;
171329
171357
  if (!to) {
171330
171358
  const peer = connected(from).find((item) => !portName || item.port.name === portName)?.peer;
@@ -174210,12 +174238,12 @@ async function effectiveConfiguration(services, key, uri) {
174210
174238
  init_lib2();
174211
174239
  init_formatter2();
174212
174240
  function configuredFormat(document4, services, settings, editor) {
174213
- const canonical5 = formatDocument(document4), lexer = services.parser.Lexer;
174241
+ const canonical4 = formatDocument(document4), lexer = services.parser.Lexer;
174214
174242
  const tokenize3 = (text8) => {
174215
174243
  const result = lexer.tokenize(text8);
174216
174244
  return [...result.tokens, ...result.hidden].filter((token) => token.tokenType.name !== "WS").sort((left, right) => left.startOffset - right.startOffset);
174217
174245
  };
174218
- const originalText = document4.textDocument.getText(), original2 = tokenize3(originalText), tokens = tokenize3(canonical5);
174246
+ const originalText = document4.textDocument.getText(), original2 = tokenize3(originalText), tokens = tokenize3(canonical4);
174219
174247
  if (original2.length !== tokens.length || tokens.some((token, index3) => token.image !== original2[index3].image)) throw Error("Formatting would change a source token.");
174220
174248
  const size = Number.isInteger(settings.indentSize) && settings.indentSize > 0 ? Math.min(16, settings.indentSize) : Math.max(1, Math.min(16, editor.tabSize || 2));
174221
174249
  const tabs = settings.indentStyle === "tabs" || settings.indentStyle !== "spaces" && !editor.insertSpaces;
@@ -174230,14 +174258,14 @@ function configuredFormat(document4, services, settings, editor) {
174230
174258
  }
174231
174259
  let output = "", previousEnd = 0, originalEnd = 0, column2 = 0, continuationIndent = "";
174232
174260
  tokens.forEach((token, index3) => {
174233
- let gap = canonical5.slice(previousEnd, token.startOffset);
174261
+ let gap = canonical4.slice(previousEnd, token.startOffset);
174234
174262
  const originalGap = originalText.slice(originalEnd, original2[index3].startOffset);
174235
- const lineStart = canonical5.lastIndexOf("\n", token.startOffset - 1) + 1;
174236
- const canonicalIndent = /^ */u.exec(canonical5.slice(lineStart))[0].length / 2;
174263
+ const lineStart = canonical4.lastIndexOf("\n", token.startOffset - 1) + 1;
174264
+ const canonicalIndent = /^ */u.exec(canonical4.slice(lineStart))[0].length / 2;
174237
174265
  const indentation = unit2.repeat(canonicalIndent);
174238
174266
  let chunkEnd = token.endOffset + 1;
174239
174267
  for (let next = index3 + 1; next < tokens.length && tokens[next].startOffset === chunkEnd; next++) chunkEnd = tokens[next].endOffset + 1;
174240
- const chunkWidth = canonical5.slice(token.startOffset, chunkEnd).length;
174268
+ const chunkWidth = canonical4.slice(token.startOffset, chunkEnd).length;
174241
174269
  if (gap.includes("\n")) {
174242
174270
  gap = "\n".repeat(separated.has(original2[index3].startOffset) ? blankLines + 1 : 1) + indentation;
174243
174271
  continuationIndent = indentation + unit2;
@@ -174404,9 +174432,9 @@ function validationModels(documents) {
174404
174432
  return [...new Set(documents.flatMap((d2) => isModel(d2.parseResult.value) ? workspaceModels.get(d2.parseResult.value) ?? [d2.parseResult.value] : []))];
174405
174433
  }
174406
174434
  function proposedErrors(before, candidates) {
174407
- const canonical5 = (value2) => Array.isArray(value2) ? value2.map(canonical5) : value2 && typeof value2 === "object" ? Object.fromEntries(Object.entries(value2).sort(([a3], [b10]) => a3.localeCompare(b10)).map(([key2, value3]) => [key2, canonical5(value3)])) : value2;
174435
+ const canonical4 = (value2) => Array.isArray(value2) ? value2.map(canonical4) : value2 && typeof value2 === "object" ? Object.fromEntries(Object.entries(value2).sort(([a3], [b10]) => a3.localeCompare(b10)).map(([key2, value3]) => [key2, canonical4(value3)])) : value2;
174408
174436
  const errors = (document4) => (document4.diagnostics ?? []).filter((d2) => d2.severity === 1);
174409
- const key = (diagnostics) => JSON.stringify(diagnostics.map((d2) => JSON.stringify(canonical5(d2))).sort());
174437
+ const key = (diagnostics) => JSON.stringify(diagnostics.map((d2) => JSON.stringify(canonical4(d2))).sort());
174410
174438
  return candidates.flatMap((document4) => {
174411
174439
  const uri = document4.uri.toString(), previous3 = before.find((source3) => source3.uri === uri), diagnostics = errors(document4);
174412
174440
  if (previous3 && previous3.text === document4.textDocument.getText()) {
@@ -174578,11 +174606,11 @@ function providerModule() {
174578
174606
  // packages/language-server/src/timing-evidence.ts
174579
174607
  init_lib2();
174580
174608
  init_edition();
174581
- var canonical2 = (uri) => URI2.parse(uri).toString();
174582
- var revisions = (values) => Object.fromEntries(Object.entries(values).map(([uri, value2]) => [canonical2(uri), value2]));
174609
+ var canonical = (uri) => URI2.parse(uri).toString();
174610
+ var revisions = (values) => Object.fromEntries(Object.entries(values).map(([uri, value2]) => [canonical(uri), value2]));
174583
174611
  var evidence = /* @__PURE__ */ new Map();
174584
174612
  function getTimingEvidence(uri, sourceRevisions) {
174585
- const run = evidence.get(canonical2(uri));
174613
+ const run = evidence.get(canonical(uri));
174586
174614
  sourceRevisions = revisions(sourceRevisions);
174587
174615
  if (!run) return void 0;
174588
174616
  const keys3 = Object.keys(run.sourceRevisions).sort(), current = Object.keys(sourceRevisions).sort();
@@ -174657,6 +174685,7 @@ init_semantic();
174657
174685
  // packages/language-server/src/test-inspection.ts
174658
174686
  init_ast2();
174659
174687
  init_semantic();
174688
+ init_names();
174660
174689
 
174661
174690
  // packages/language-server/src/run-cases.ts
174662
174691
  init_ast2();
@@ -175073,15 +175102,15 @@ init_names();
175073
175102
  var cell = (text8) => ({ text: text8 ?? "" });
175074
175103
  var column = (label2, value2) => ({ label: label2, cell: (entry) => cell(value2(entry)) });
175075
175104
  var original = (label2, index3) => ({ label: label2, cell: (entry) => entry.row.cells[index3] });
175076
- var elementName = (path7) => path7.replace(/^.*(?:::|\.)/, "");
175105
+ var elementName = diagramElementName;
175077
175106
  var shortType = (type) => elementName(typeKey(type));
175078
175107
  var display = (text8, fullText) => ({ text: text8 ?? "", ...fullText && fullText !== text8 ? { fullText } : {} });
175079
175108
  var named = (label2, value2) => ({ label: label2, cell: (entry) => {
175080
175109
  const paths = value2(entry);
175081
- return display(paths.map(elementName).join("\n"), paths.join("\n"));
175110
+ return display(paths.map((path7) => elementName(path7, true)).join("\n"), paths.join("\n"));
175082
175111
  } });
175083
175112
  var typed = (label2, value2) => ({ label: label2, cell: (entry) => display(value2(entry, shortType), value2(entry, typeKey)) });
175084
- var canonical3 = (path7) => formatPath(parsePathInput(path7));
175113
+ var canonical2 = formatPath;
175085
175114
  var attributes = (entry) => isRequirement(entry.ast) ? entry.ast.attributes : isComponentDef(entry.ast) || isComponentUsage(entry.ast) ? members(entry.ast).filter(isAttribute) : [];
175086
175115
  function valueText(value2, type) {
175087
175116
  if (isLiteral(value2)) {
@@ -175089,7 +175118,7 @@ function valueText(value2, type) {
175089
175118
  if (value2.boolean !== void 0) return value2.boolean;
175090
175119
  if (value2.number !== void 0) return String(value2.number);
175091
175120
  }
175092
- if (!type?.size && isEnumType(type?.type?.ref) && isReferenceExpression(value2)) return parsePathInput(value2.path).split(".").at(-1);
175121
+ if (!type?.size && isEnumType(type?.type?.ref) && isReferenceExpression(value2)) return elementName(value2.path);
175093
175122
  return value2.$cstNode?.text ?? "";
175094
175123
  }
175095
175124
  function attributeCell(entry, name2, source3) {
@@ -175130,7 +175159,7 @@ function gridCategoryTables(entries2, models, source3) {
175130
175159
  const start3 = [original("Name", 0), original("Kind", 1)], end = [original("Documentation", 3), sourceFile];
175131
175160
  const type = { label: "Type", cell: (entry) => {
175132
175161
  const declared = entry.row.cells[2];
175133
- return entry.node.shape === "annotation" ? declared : { ...declared, ...display(elementName(declared.text ?? ""), declared.text) };
175162
+ return entry.node.shape === "annotation" ? declared : { ...declared, ...display(entry.node.typeDisplayName ?? elementName(declared.text ?? "", true), declared.text) };
175134
175163
  } };
175135
175164
  const tables = [];
175136
175165
  const add = (id2, category, label2, rows, columns) => {
@@ -175143,7 +175172,7 @@ function gridCategoryTables(entries2, models, source3) {
175143
175172
  rows: rows.map((entry) => ({ ...entry.row, cells: columns.map((column2) => column2.cell(entry)) }))
175144
175173
  });
175145
175174
  };
175146
- const pillName = (path7) => ({ text: elementName(path7), fullText: path7 });
175175
+ const pillName = (path7) => ({ text: elementName(path7, true), fullText: path7 });
175147
175176
  const satisfies = { label: "Satisfies", cell: (entry) => ({
175148
175177
  tooltip: "Authored satisfy links identify satisfying designs. These links record intent, not proof or a passed run.",
175149
175178
  pills: claims.filter((item) => item.claim.requirement.ref === entry.ast).map((item) => ({
@@ -175227,7 +175256,7 @@ function gridCategoryTables(entries2, models, source3) {
175227
175256
  case "interface":
175228
175257
  columns = [
175229
175258
  ...start3,
175230
- column("Endpoints", (entry) => isConnect(entry.ast) ? canonical3(entry.ast.source) + " \u2194 " + canonical3(entry.ast.target) : ""),
175259
+ column("Endpoints", (entry) => isConnect(entry.ast) ? canonical2(entry.ast.source) + " \u2194 " + canonical2(entry.ast.target) : ""),
175231
175260
  named("Policy", (entry) => isConnect(entry.ast) && entry.ast.policy?.ref ? [formatPath(identity2(entry.ast.policy.ref))] : []),
175232
175261
  column("Settings", (entry) => isQosPolicy(entry.ast) ? entry.ast.settings.map((setting) => formatName(setting.name) + " = " + (setting.duration ?? setting.value)?.$cstNode?.text).join("\n") : ""),
175233
175262
  named("Root", (entry) => isDeployment(entry.ast) && entry.ast.root.ref ? [formatPath(identity2(entry.ast.root.ref))] : []),
@@ -175240,7 +175269,7 @@ function gridCategoryTables(entries2, models, source3) {
175240
175269
  columns = [
175241
175270
  ...start3,
175242
175271
  type,
175243
- named("Subjects", (entry) => isView(entry.ast) ? entry.ast.subject ? [canonical3(entry.ast.subject)] : entry.ast.selections.map((selection2) => canonical3(selection2.subject)) : []),
175272
+ named("Subjects", (entry) => isView(entry.ast) ? entry.ast.subject ? [canonical2(entry.ast.subject)] : entry.ast.selections.map((selection2) => canonical2(selection2.subject)) : []),
175244
175273
  column("Selections", (entry) => isView(entry.ast) ? entry.ast.selections.map((selection2) => selection2.$cstNode.text).join("\n") : ""),
175245
175274
  ...end
175246
175275
  ];
@@ -175248,7 +175277,7 @@ function gridCategoryTables(entries2, models, source3) {
175248
175277
  case "package":
175249
175278
  columns = [
175250
175279
  ...start3,
175251
- column("Imports", (entry) => isPackage(entry.ast) ? entry.ast.imports.map((item) => canonical3(item.namespace)).join("\n") : ""),
175280
+ column("Imports", (entry) => isPackage(entry.ast) ? entry.ast.imports.map((item) => canonical2(item.namespace)).join("\n") : ""),
175252
175281
  ...end
175253
175282
  ];
175254
175283
  break;
@@ -175353,6 +175382,7 @@ function convert(n2) {
175353
175382
  return {
175354
175383
  id: id2,
175355
175384
  name: n2.name,
175385
+ ...n2.kind === "package" && n2.name.includes("::") ? { nameDisplayName: diagramElementName(n2.name) } : {},
175356
175386
  keyword: ["component", "port"].includes(n2.kind) && isDef ? n2.kind + " def" : n2.kind === "useCase" ? "use case" : n2.kind,
175357
175387
  isDef,
175358
175388
  shape: n2.kind === "operation" ? "action" : n2.kind === "state" ? "state" : n2.kind === "package" ? "package" : ["useCase", "test"].includes(n2.kind) ? "usecase" : "box",
@@ -175369,7 +175399,19 @@ function requirementDocumentation(node2) {
175369
175399
  return [...new Set([documentationText2(node2), ...node2.attributes.filter((attribute) => ["description", "text"].includes(attribute.name) && isLiteral(attribute.value) && typeof attribute.value.text === "string").map((attribute) => attribute.value.text), ...sourceComments(node2).map((comment) => comment.text)].filter((text8) => !!text8))];
175370
175400
  }
175371
175401
  function requirementAttributes(node2) {
175372
- return isRequirement(node2) ? node2.attributes.filter((attribute) => !["description", "text"].includes(attribute.name)).map((attribute) => ({ name: attribute.name, type: typeKey(attribute.type), value: attribute.value.$cstNode.text })) : [];
175402
+ return isRequirement(node2) ? node2.attributes.filter((attribute) => !["description", "text"].includes(attribute.name)).map((attribute) => ({ name: attribute.name, type: typeKey(attribute.type), ...typeKey(attribute.type) !== typeCaption(attribute.type) ? { typeDisplayName: typeCaption(attribute.type) } : {}, value: attribute.value.$cstNode.text })) : [];
175403
+ }
175404
+ var typeName = (type) => type?.primitive ?? (type?.type?.ref ? type.type.ref.name : "?");
175405
+ var typeCaption = (type) => type ? typeName(type) + (type.size !== void 0 ? "[" + type.size + "]" : "") : "void";
175406
+ function nodeTypeCaption(node2) {
175407
+ if (isAttribute(node2) || isLocalVariable(node2) || isField(node2)) return typeCaption(node2.type);
175408
+ if (isPortUsage(node2)) return node2.definition?.ref?.name ?? (node2.definition ? diagramElementName(node2.definition.$refText) : "inline");
175409
+ if (isComponentUsage(node2)) return node2.definition?.ref?.name;
175410
+ if (isExecutable(node2)) {
175411
+ const sig = signature(node2);
175412
+ return "(" + (sig?.parameters.map((parameter) => (parameter.direction ?? "in") + " " + parameter.name + ": " + typeCaption(parameter.type)).join(", ") ?? "") + ") returns " + typeCaption(sig?.result);
175413
+ }
175414
+ return void 0;
175373
175415
  }
175374
175416
  function withCommentCards(model, ctx) {
175375
175417
  if (model.kind !== "gv" && model.kind !== "cv") return model;
@@ -175522,7 +175564,7 @@ function packageLinkRows(ctx, entries2) {
175522
175564
  for (const claim of pkg.satisfactions) {
175523
175565
  const requirement = claim.requirement.ref;
175524
175566
  const design = diagramId(pkg.name + "::" + claim.design);
175525
- rows.push(row(claim, "satisfy", design, requirement ? diagramId(identity2(requirement)) : claim.requirement.$refText, parsePathInput(claim.design), requirement?.name ?? claim.requirement.$refText));
175567
+ rows.push(row(claim, "satisfy", design, requirement ? diagramId(identity2(requirement)) : claim.requirement.$refText, diagramElementName(claim.design), requirement?.name ?? claim.requirement.$refText));
175526
175568
  }
175527
175569
  for (const link4 of pkg.verifications) {
175528
175570
  const test = link4.test.ref, requirement = link4.requirement.ref;
@@ -175605,6 +175647,7 @@ async function buildCurrentDiagram(services, params) {
175605
175647
  if (!ast) continue;
175606
175648
  const node2 = model.nodes.find((n2) => n2.id === diagramId(entry.id));
175607
175649
  if (node2) {
175650
+ node2.typeDisplayName = nodeTypeCaption(ast);
175608
175651
  node2.meta = { ...node2.meta, gvDocumentation: documentationText2({ documentation: ast.documentation }), ...isRequirement(ast) ? { swamlRequirementDocumentation: requirementDocumentation(ast) } : {}, declarationId: diagramId(identity2(ast)), expandedFromDefinition: diagramId(identity2(ast)) !== node2.id, localDeclaration: diagramId(identity2(ast)) === node2.id };
175609
175652
  for (const port of node2.ports ?? []) {
175610
175653
  const candidate = ctx.candidates.find((c3) => diagramId(c3.path) === port.id), declaration = candidate?.node ?? (port.meta?.structuralPort ? portAtOccurrence(ctx.candidates, port.id)?.port : void 0);
@@ -175629,14 +175672,14 @@ async function buildCurrentDiagram(services, params) {
175629
175672
  model.nodes.push({ id: id2, name: s2.$cstNode.text, keyword: "schedule", shape: "action", isDef: false, parent: diagramId(entry.id), source: source(s2), meta: { nonExecutableGrouping: true, gvExplicit: true, gvOwnerId: diagramId(entry.id), gvInScope: true, gvUsage: false } });
175630
175673
  model.edges.push({ id: id2 + "->target", from: id2, to: diagramId(entry.id + "." + s2.operation), kind: "dependency", label: s2.kind === "after" ? "successful completion" : "activation", source: source(s2) });
175631
175674
  });
175632
- if (node2 && entry.ports?.length) node2.compartments = [{ title: "Ports", items: entry.ports.flatMap((p2) => p2.members.map((m2) => ({ text: m2.direction + " " + m2.kind + " " + p2.name + "." + m2.name + (m2.kind === "attribute" ? ": " + m2.type : "(" + m2.parameters.map((v2) => v2.direction + " " + v2.name + ": " + v2.type).join(", ") + ")" + (m2.kind === "operation" ? " returns " + m2.type : "")), source: node2.ports?.find((x2) => x2.id === node2.id + "::" + p2.name + "::" + m2.name)?.source ?? node2.source }))) }, ...node2.compartments ?? []];
175675
+ if (node2 && entry.ports?.length) node2.compartments = [{ title: "Ports", items: entry.ports.flatMap((p2) => p2.members.map((m2) => ({ text: m2.direction + " " + m2.kind + " " + p2.name + "." + m2.name + (m2.kind === "attribute" ? ": " + diagramElementName(m2.type) : "(" + m2.parameters.map((v2) => v2.direction + " " + v2.name + ": " + diagramElementName(v2.type)).join(", ") + ")" + (m2.kind === "operation" ? " returns " + diagramElementName(m2.type) : "")), source: node2.ports?.find((x2) => x2.id === node2.id + "::" + p2.name + "::" + m2.name)?.source ?? node2.source }))) }, ...node2.compartments ?? []];
175633
175676
  if (node2 && isPortUsage(ast)) {
175634
175677
  node2.type = ast.definition?.$refText ?? "inline";
175635
175678
  node2.meta = { ...node2.meta, optional: ast.optional, reversed: ast.reversed };
175636
175679
  }
175637
175680
  if (node2 && isState(ast)) {
175638
175681
  if (ast.final) node2.shape = "final";
175639
- node2.meta = { ...node2.meta, stateOwnerId: node2.parent };
175682
+ node2.meta = { ...node2.meta, stateOwnerId: node2.parent, statement: statementIdentity(ast) };
175640
175683
  }
175641
175684
  if (isExecutable(ast)) for (const state2 of body(ast)?.states ?? []) state2.transitions.forEach((transition2, index3) => {
175642
175685
  const from = diagramId(entry.id + "." + state2.name), to = diagramId(entry.id + "." + transition2.target);
@@ -175652,7 +175695,7 @@ async function buildCurrentDiagram(services, params) {
175652
175695
  label: triggerGuard + (transition2.effect.statements.length ? " / " + effectText : ""),
175653
175696
  source: source(transition2),
175654
175697
  effect: transition2.effect.statements.length ? { id: effectId, role: "effect", declarationId: diagramId(identity2(ast)) + "::" + state2.name + "::$transition:" + index3 + "::$effect", ownerId: from, summary: effectText, text: effectText, source: source(transition2), bodySource: source(transition2.effect), provenance: diagramId(identity2(ast)) === diagramId(entry.id) ? "local" : "inherited", status: "available" } : void 0,
175655
- meta: { semanticKind: "transition", sourceOrder: index3, guardText: guard2 ?? "", transitionTriggerGuard: triggerGuard, effectText }
175698
+ meta: { semanticKind: "transition", sourceOrder: index3, guardText: guard2 ?? "", transitionTriggerGuard: triggerGuard, effectText, statement: statementIdentity(transition2) }
175656
175699
  });
175657
175700
  });
175658
175701
  if ((isExecutable(ast) || isScenario(ast) && ast.statements.length) && kind2 === "fv") addOperationFlow(model, entry, ast);
@@ -175747,7 +175790,7 @@ async function buildCurrentDiagram(services, params) {
175747
175790
  let current = op;
175748
175791
  while (current && (current.id !== anchor || flowFrame(current))) {
175749
175792
  if (frames.has(current.id)) break;
175750
- frames.set(current.id, { id: current.id, label: current.name, keyword: current.keyword, parent: current.parent, source: current.source, type: current.type, ports: current.keyword === "operation" ? current.ports : void 0, meta: { ...current.meta, swamlScope: true, contextOnly: !flowFrame(current) } });
175793
+ frames.set(current.id, { id: current.id, label: current.name, keyword: current.keyword, parent: current.parent, source: current.source, type: current.type, typeDisplayName: current.typeDisplayName, ports: current.keyword === "operation" ? current.ports : void 0, meta: { ...current.meta, swamlScope: true, contextOnly: !flowFrame(current) } });
175751
175794
  current = current.parent ? scopedNodes.get(current.parent) : void 0;
175752
175795
  }
175753
175796
  }
@@ -175771,7 +175814,7 @@ async function buildCurrentDiagram(services, params) {
175771
175814
  const typeField = ast && gridTypeField(ast);
175772
175815
  const documentationEditable = writable2 && !!(authoredDocumentation !== void 0 || ast && gridDocumentationInsertion(ast));
175773
175816
  const row = { id: n2.id, name: n2.name, keyword: n2.keyword, source: rowSource, cells: [
175774
- { text: n2.name, ...writable2 ? { edit: { kind: "name", value: n2.name } } : {} },
175817
+ { text: n2.nameDisplayName ?? n2.name, ...n2.nameDisplayName && n2.nameDisplayName !== n2.name ? { fullText: n2.name } : {}, ...writable2 ? { edit: { kind: "name", value: n2.name } } : {} },
175775
175818
  { text: n2.keyword },
175776
175819
  { text: n2.type ?? typeField?.value ?? "", ...writable2 && typeField ? { edit: { kind: "type", value: typeField.value } } : {} },
175777
175820
  { text: documentation.join("\n\n"), documentation, ...documentationEditable ? { edit: { kind: "doc", value: authoredDocumentation ?? "" } } : {} },
@@ -175788,7 +175831,7 @@ async function buildCurrentDiagram(services, params) {
175788
175831
  const candidateEvidence = getTimingEvidence(params.uri, revisions2), runPrefixes = (result) => result.target.kind === "package" ? ctx.models.flatMap((m2) => m2.packages).filter((p2) => p2.name === result.target.identity).flatMap((p2) => p2.elements.filter(isComponentUsage).map((root6) => p2.name + "::" + root6.name + ".")) : [result.target.identity + "."];
175789
175832
  const evidence2 = candidateEvidence && contracts.some((c2) => runPrefixes(candidateEvidence.result).some((prefix) => c2.functionPath.startsWith(prefix))) ? candidateEvidence : void 0;
175790
175833
  const runPackage = evidence2 && (evidence2.result.target.kind === "package" ? evidence2.result.target.identity : evidence2.result.target.identity.slice(0, evidence2.result.target.identity.lastIndexOf("::")));
175791
- const canonical5 = (path7) => path7.includes("::") ? path7 : runPackage + "::" + path7;
175834
+ const canonical4 = (path7) => path7.includes("::") ? path7 : runPackage + "::" + path7;
175792
175835
  const selectedSubjects = new Set(contracts.map((c2) => c2.functionPath));
175793
175836
  const endNs = evidence2 ? evidence2.result.status === "horizon" ? evidence2.result.options.untilNs : evidence2.result.timeNs : 0;
175794
175837
  const timing = evidence2 && projectOperationTiming(evidence2.result), requestActivations = /* @__PURE__ */ new Map();
@@ -175798,7 +175841,7 @@ async function buildCurrentDiagram(services, params) {
175798
175841
  const markers = timing.markers.filter((m2) => (m2.activation ?? (m2.kind === "timeout" && typeof m2.correlation === "string" ? requestActivations.get(m2.correlation) : void 0)) === id2);
175799
175842
  return {
175800
175843
  id: id2,
175801
- functionPath: canonical5(values[0].subject),
175844
+ functionPath: canonical4(values[0].subject),
175802
175845
  outcome: timing.markers.find((m2) => m2.activation === id2)?.kind ?? "open",
175803
175846
  intervals: values.map((i2) => ({ state: i2.phase, start: { timeNs: i2.startNs }, end: { timeNs: i2.endNs ?? endNs }, open: i2.endNs === void 0 })),
175804
175847
  markers: markers.map((m2) => ({ kind: m2.kind, point: { timeNs: m2.timeNs, ordinal: m2.ordinal }, correlation: typeof m2.correlation === "string" ? m2.correlation : void 0, detail: m2.subject }))
@@ -176514,13 +176557,13 @@ ${JSON.stringify(source3.range)}` : void 0;
176514
176557
  allocation: "allocations"
176515
176558
  };
176516
176559
  for (const child of children2) {
176517
- const canonical5 = canonicalById.get(child.id) ?? canonicalBySource.get(sourceKey5(child.source) ?? "");
176560
+ const canonical4 = canonicalById.get(child.id) ?? canonicalBySource.get(sourceKey5(child.source) ?? "");
176518
176561
  const kind2 = child.keyword.replace(/^ref\s+/, "").replace(/\s+def$/, "");
176519
176562
  const wiringFeature = !child.isDef && /^(?:connection|interface|connector)$/.test(kind2);
176520
- const title = wiringFeature && node2.shape !== "package" ? "features" : node2.shape === "package" ? "members" : canonical5?.compartment.title ?? (child.isDef ? "definitions" : titles[kind2] ?? "members");
176563
+ const title = wiringFeature && node2.shape !== "package" ? "features" : node2.shape === "package" ? "members" : canonical4?.compartment.title ?? (child.isDef ? "definitions" : titles[kind2] ?? "members");
176521
176564
  const definition3 = index3.byId.get(index3.definition.get(child.id) ?? "");
176522
176565
  const type = child.type ?? definition3?.name;
176523
- const text8 = node2.shape === "package" || child.isDef ? `\xAB${child.keyword}\xBB ${child.name}` : canonical5?.item.text ?? (kind2 === "doc" ? child.type ?? child.name : `${child.name}${type ? ` : ${type}` : ""}${child.multiplicity ? ` ${child.multiplicity}` : ""}${child.value !== void 0 ? ` = ${child.value}` : ""}`);
176566
+ const text8 = node2.shape === "package" || child.isDef ? `\xAB${child.keyword}\xBB ${child.name}` : canonical4?.item.text ?? (kind2 === "doc" ? child.type ?? child.name : `${child.name}${type ? ` : ${type}` : ""}${child.multiplicity ? ` ${child.multiplicity}` : ""}${child.value !== void 0 ? ` = ${child.value}` : ""}`);
176524
176567
  const group = groups.get(title) ?? { title, items: [], expandable: false, expanded: false };
176525
176568
  group.items.push({ text: text8, source: child.source, membership: child.membership, node: child });
176526
176569
  groups.set(title, group);
@@ -177377,10 +177420,10 @@ function projectGvStructureRelationships(input) {
177377
177420
  ...record2.body.nodes.map((node2) => node2.id)
177378
177421
  ]));
177379
177422
  for (const node2 of model.nodes) if (node2.meta?.gvRelationshipId || node2.meta?.gvRelationshipBodyOf) omitted.add(node2.id);
177380
- const sourceKeys = new Set(records.map((record2) => sourceKey4(record2.declaration)).filter(Boolean));
177423
+ const sourceKeys2 = new Set(records.map((record2) => sourceKey4(record2.declaration)).filter(Boolean));
177381
177424
  const primaryIds = new Set(records.flatMap((record2) => record2.edges.map((edge) => edge.id)));
177382
177425
  const nodes2 = model.nodes.filter((node2) => !omitted.has(node2.id));
177383
- const edges = model.edges.filter((edge) => edge.meta?.connectionDefinitionGraphical !== true && !primaryIds.has(edge.id) && !omitted.has(edge.from) && !omitted.has(edge.to) && !(sourceKeys.has(sourceKey4(edge)) && !["composition", "owningMembership", "definedBy", "reference"].includes(edge.kind)));
177426
+ const edges = model.edges.filter((edge) => edge.meta?.connectionDefinitionGraphical !== true && !primaryIds.has(edge.id) && !omitted.has(edge.from) && !omitted.has(edge.to) && !(sourceKeys2.has(sourceKey4(edge)) && !["composition", "owningMembership", "definedBy", "reference"].includes(edge.kind)));
177384
177427
  for (const record2 of records) {
177385
177428
  if (!canDisclose(record2) || !gvElementIsExpanded(record2.declaration, expanded2)) continue;
177386
177429
  let displayOwner = record2.ownerId;
@@ -178260,13 +178303,14 @@ function annotationLines(text8, width) {
178260
178303
  }
178261
178304
  function requirementContent(node2) {
178262
178305
  const documentation = Array.isArray(node2.meta?.swamlRequirementDocumentation) ? node2.meta.swamlRequirementDocumentation.filter((text8) => typeof text8 === "string") : [];
178263
- const attributes2 = Array.isArray(node2.meta?.swamlRequirementAttributes) ? node2.meta.swamlRequirementAttributes.filter((attribute) => !!attribute && typeof attribute.name === "string" && typeof attribute.type === "string" && typeof attribute.value === "string") : [];
178306
+ const attributes2 = Array.isArray(node2.meta?.swamlRequirementAttributes) ? node2.meta.swamlRequirementAttributes.filter((attribute) => !!attribute && typeof attribute.name === "string" && typeof attribute.type === "string" && typeof attribute.value === "string" && (attribute.typeDisplayName === void 0 || typeof attribute.typeDisplayName === "string")) : [];
178264
178307
  return { documentation, attributes: attributes2 };
178265
178308
  }
178266
178309
  function requirementFallback(node2, width, maximumLines = Number.POSITIVE_INFINITY) {
178267
178310
  const content3 = requirementContent(node2), documentation = content3.documentation.join("\n\n");
178268
- const attributes2 = content3.attributes.map((attribute) => `${attribute.name}: ${attribute.type} = ${attribute.value}`).join("\n");
178269
- const text8 = [documentation, attributes2].filter(Boolean).join("\n\n");
178311
+ const attributes2 = content3.attributes.map((attribute) => `${attribute.name}: ${attribute.typeDisplayName ?? attribute.type} = ${attribute.value}`).join("\n");
178312
+ const canonicalAttributes = content3.attributes.map((attribute) => `${attribute.name}: ${attribute.type} = ${attribute.value}`).join("\n");
178313
+ const text8 = [documentation, canonicalAttributes].filter(Boolean).join("\n\n");
178270
178314
  const units = Math.max(1, Math.floor(width / 6.2));
178271
178315
  const attributeLines = attributes2 ? attributes2.split(/\r?\n/u).flatMap((line2) => {
178272
178316
  const wrapped = [];
@@ -190343,7 +190387,7 @@ var xy = (p2) => `${fmt(p2.x)},${fmt(p2.y)}`;
190343
190387
  function cleanPolyline(points) {
190344
190388
  return clean(points);
190345
190389
  }
190346
- function canonical4(points) {
190390
+ function canonical3(points) {
190347
190391
  return clean(points.map(rounded));
190348
190392
  }
190349
190393
  function clean(points) {
@@ -190647,7 +190691,7 @@ var OrthogonalRouteIndex = class _OrthogonalRouteIndex {
190647
190691
  }
190648
190692
  /** Add one settled route. Input is compared on the rounded grid, never mutated. */
190649
190693
  add(points, tags) {
190650
- const route = canonical4([...points]);
190694
+ const route = canonical3([...points]);
190651
190695
  const horizontals = [];
190652
190696
  const verticals = [];
190653
190697
  for (let i2 = 1; i2 < route.length; i2 += 1) {
@@ -190680,7 +190724,7 @@ var OrthogonalRouteIndex = class _OrthogonalRouteIndex {
190680
190724
  /** Count strict perpendicular intersections. Endpoint contacts and parallel
190681
190725
  * overlaps are joins/continuations, not route crossings. */
190682
190726
  crossingCount(points) {
190683
- const route = canonical4([...points]);
190727
+ const route = canonical3([...points]);
190684
190728
  let count = 0;
190685
190729
  for (let i2 = 1; i2 < route.length; i2 += 1) {
190686
190730
  const a3 = route[i2 - 1], b10 = route[i2];
@@ -190710,7 +190754,7 @@ var OrthogonalRouteIndex = class _OrthogonalRouteIndex {
190710
190754
  * geometry is indexed once by {@link add}, so a shared structural bus has
190711
190755
  * one occupancy cost rather than one per semantic member. */
190712
190756
  overlapCount(points) {
190713
- const route = canonical4([...points]);
190757
+ const route = canonical3([...points]);
190714
190758
  let count = 0;
190715
190759
  for (let i2 = 1; i2 < route.length; i2 += 1) {
190716
190760
  const a3 = route[i2 - 1], b10 = route[i2];
@@ -197403,10 +197447,10 @@ function registerEdgeSideHandles(nodes2, edges) {
197403
197447
  const node2 = byId.get(id2);
197404
197448
  const parsed = parseSideAnchorHandleId(handle2);
197405
197449
  if (!node2 || !parsed) continue;
197406
- const canonical5 = sideAnchorHandleId(parsed.side, parsed.offset);
197407
- if (canonical5 !== handle2) {
197408
- if (end === "source") edge.sourceHandle = canonical5;
197409
- else edge.targetHandle = canonical5;
197450
+ const canonical4 = sideAnchorHandleId(parsed.side, parsed.offset);
197451
+ if (canonical4 !== handle2) {
197452
+ if (end === "source") edge.sourceHandle = canonical4;
197453
+ else edge.targetHandle = canonical4;
197410
197454
  if (edge.data?.settledGeometry) edge.data = { ...edge.data, settledGeometry: void 0 };
197411
197455
  }
197412
197456
  const current = node2.data.edgeSideAnchors?.[parsed.side] ?? [];
@@ -202805,6 +202849,9 @@ var import_react5 = __toESM(require_react());
202805
202849
 
202806
202850
  // packages/extension/src/swaml-name.ts
202807
202851
  init_names();
202852
+ function swamlPathName(value2) {
202853
+ return value2.split(/::|\./u).at(-1) ?? value2;
202854
+ }
202808
202855
 
202809
202856
  // packages/extension/src/webview/diagram/toolbox.ts
202810
202857
  var ELEMENT_LABELS = { useCase: "use case" };
@@ -205323,6 +205370,18 @@ var TIME_ORIGIN = 240;
205323
205370
  var TIME_WIDTH = 900;
205324
205371
  var TIME_ROW_HEIGHT = 72;
205325
205372
  var TIME_CHART_WIDTH = TIME_ORIGIN + TIME_WIDTH + 24;
205373
+ function sameSource2(left, right) {
205374
+ return !!left && !!right && left.uri === right.uri && left.revision === right.revision && left.range.start.line === right.range.start.line && left.range.start.character === right.range.start.character && left.range.end.line === right.range.end.line && left.range.end.character === right.range.end.character;
205375
+ }
205376
+ function timingExecutable(model, id2) {
205377
+ const matches = id2 ? model.nodes.filter((item) => item.id === id2) : [];
205378
+ return matches.length && matches.every((item) => item === matches[0] || sameSource2(item.source, matches[0].source)) ? matches[0] : void 0;
205379
+ }
205380
+ function timeContextTarget(model, node2) {
205381
+ const executable2 = timingExecutable(model, node2.data.modelId)?.source, shown2 = node2.data.source;
205382
+ const before = (left, right) => left.line < right.line || left.line === right.line && left.character <= right.character;
205383
+ return node2.data.kind !== "axis" && node2.data.modelId && executable2 && shown2 && executable2.uri === shown2.uri && executable2.revision === shown2.revision && before(executable2.range.start, shown2.range.start) && before(shown2.range.end, executable2.range.end) ? node2.data.modelId : void 0;
205384
+ }
205326
205385
  function timeScale(horizonNs) {
205327
205386
  const target2 = Math.max(1, horizonNs) / 8, magnitude = 10 ** Math.floor(Math.log10(target2));
205328
205387
  const stepNs = Math.max(1, ([1, 2, 5, 10].find((n2) => n2 * magnitude >= target2) ?? 10) * magnitude);
@@ -205358,9 +205417,8 @@ function timeNodes(model) {
205358
205417
  if (!timing) return [];
205359
205418
  const trace = timing.trace, scale = trace ? timeScale(trace.endNs) : void 0, nodes2 = [];
205360
205419
  const participantLines = (path7) => {
205361
- const name2 = path7.replace((trace?.target ?? model.root.qname) + ".", "").replace(/^[^:]+::/, "");
205362
- const split = name2.lastIndexOf(".");
205363
- return split < 0 ? textLines(name2 + "()", 25) : [...textLines(name2.slice(0, split), 25), ...textLines(name2.slice(split + 1) + "()", 25)];
205420
+ const split = path7.lastIndexOf(".");
205421
+ return split < 0 ? textLines(swamlPathName(path7) + "()", 25) : [...textLines(swamlPathName(path7.slice(0, split)), 25), ...textLines(swamlPathName(path7.slice(split + 1)) + "()", 25)];
205364
205422
  };
205365
205423
  const add = (id2, x2, y3, width, height, data) => {
205366
205424
  nodes2.push({
@@ -205381,8 +205439,8 @@ function timeNodes(model) {
205381
205439
  const paths = [.../* @__PURE__ */ new Set([...timing.contracts.map((c2) => c2.functionPath), ...trace?.activations.map((a3) => a3.functionPath) ?? []])];
205382
205440
  for (const path7 of paths) {
205383
205441
  const contractIndex = timing.contracts.findIndex((c2) => c2.functionPath === path7), contract = timing.contracts[contractIndex];
205384
- const executable2 = contract?.modelId ? model.nodes.find((n2) => n2.id === contract.modelId) : model.nodes[contractIndex];
205385
- const source3 = executable2?.source, modelId = contract?.modelId ?? executable2?.id ?? "";
205442
+ const executable2 = timingExecutable(model, contract?.modelId ?? model.nodes[contractIndex]?.id);
205443
+ const source3 = executable2?.source, modelId = executable2?.id ?? "";
205386
205444
  const declared = contract?.declared ?? (contract?.wcetNs !== void 0 || contract?.deadlineNs !== void 0);
205387
205445
  const detail = contract ? [
205388
205446
  declared ? "Declared contract" : "No timing contract declared",
@@ -205515,7 +205573,8 @@ var TimeView = (0, import_react10.forwardRef)(function TimeView2({
205515
205573
  onShowGridChange,
205516
205574
  onViewportChange,
205517
205575
  onSelect,
205518
- onReveal
205576
+ onReveal,
205577
+ onContextNode
205519
205578
  }, ref) {
205520
205579
  const [layoutRevision, setLayoutRevision] = (0, import_react10.useState)(0);
205521
205580
  const nodes2 = (0, import_react10.useMemo)(() => timeNodes(model).map((node2) => ({
@@ -205645,6 +205704,13 @@ var TimeView = (0, import_react10.forwardRef)(function TimeView2({
205645
205704
  },
205646
205705
  onPaneClick: () => onSelect(void 0),
205647
205706
  onNodeClick: (_event, node2) => onSelect(node2.data.modelId || void 0),
205707
+ onNodeContextMenu: onContextNode ? (event, node2) => {
205708
+ const id2 = timeContextTarget(model, node2);
205709
+ if (!id2) return;
205710
+ event.preventDefault();
205711
+ event.stopPropagation();
205712
+ onContextNode(id2, event.clientX, event.clientY);
205713
+ } : void 0,
205648
205714
  onNodeDoubleClick: (_event, node2) => onReveal(node2.data.source, node2.data.modelId, true),
205649
205715
  children: [
205650
205716
  showGrid && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(DiagramGrid, {}),
@@ -221138,6 +221204,11 @@ function OverlayNodeBadge({ item, w: w2 }) {
221138
221204
 
221139
221205
  // packages/extension/src/webview/diagram/flow/nodes.tsx
221140
221206
  var import_jsx_runtime19 = __toESM(require_jsx_runtime());
221207
+ function elementTitle(element3) {
221208
+ const type = element3.type ?? (typeof element3.meta?.gvDefinitionId === "string" ? element3.meta.gvDefinitionId : void 0);
221209
+ return [element3.id, type, ...element3.actions?.map((action) => `${action.role}: ${action.status}, ${action.provenance}
221210
+ ${action.summary}`) ?? []].filter(Boolean).join("\n");
221211
+ }
221141
221212
  var SIDES = [...PORT_DOCK_SIDES];
221142
221213
  var POS = {
221143
221214
  top: Position3.Top,
@@ -221633,7 +221704,7 @@ function BoxBody({ node: node2, w: w2, h: h2, showMult, quietTitle = false }) {
221633
221704
  ] }) }),
221634
221705
  /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("tbody", { children: requirementAttributes2.map((attribute) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("tr", { children: [
221635
221706
  /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("td", { children: attribute.name }),
221636
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("code", { children: attribute.type }) }),
221707
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("td", { title: attribute.typeDisplayName !== void 0 ? attribute.type : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("code", { children: attribute.typeDisplayName ?? attribute.type }) }),
221637
221708
  /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("code", { children: attribute.value }) })
221638
221709
  ] }, attribute.name)) })
221639
221710
  ] }) })
@@ -222598,8 +222669,7 @@ function NodeBody({ node: semanticNode, data, selectedPortId, hoveredPortId, mov
222598
222669
  const clip = !fittedGvBox && !connectionBar && (!CLIP_EXEMPT.has(node2.shape) || data.kind === "gv" && node2.shape === "actor");
222599
222670
  const elementColorClass = diagramElementColorClass(diagramElementColorTypeForNode(node2.shape, node2.keyword));
222600
222671
  return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("svg", { className: `rf-node-svg ${elementColorClass}${overlayClassName(node2)}`, width: w2, height: h2, style: { overflow: "visible" }, children: [
222601
- node2.actions?.length ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("title", { children: node2.actions.map((action) => `${action.role}: ${action.status}, ${action.provenance}
222602
- ${action.summary}`).join("\n\n") }) : null,
222672
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("title", { children: elementTitle(semanticNode) }),
222603
222673
  /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(NodeSurface, { node: node2, w: w2, h: h2 }),
222604
222674
  clip ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
222605
222675
  "svg",
@@ -222720,7 +222790,7 @@ function SwamlNode({ id: id2, data, draggable, selected: selected2, width, heigh
222720
222790
  {
222721
222791
  ref: containerRef,
222722
222792
  className: `rf-node${isLifeline ? " rf-lifeline" : ""}${selected2 ? " selected" : ""}${nodeSideStartable ? " rf-node-graph" : ""}${dropClass}${draggable === false ? "" : " rf-node-movable"}`,
222723
- title: typeof node2.meta?.statementHelp === "string" ? node2.name + "\n\n" + node2.meta.statementHelp : void 0,
222793
+ title: typeof node2.meta?.statementHelp === "string" ? node2.name + "\n\n" + node2.meta.statementHelp : elementTitle(node2),
222724
222794
  style: {
222725
222795
  width: w2,
222726
222796
  height: h2,
@@ -222828,7 +222898,7 @@ function SwamlNode({ id: id2, data, draggable, selected: selected2, width, heigh
222828
222898
  "div",
222829
222899
  {
222830
222900
  className: "dseq-lifeline-header-hit",
222831
- title: node2.name,
222901
+ title: elementTitle(node2),
222832
222902
  style: { left: 0, top: 0, width: w2, height: SEQ_LIFELINE_HEAD_HEIGHT }
222833
222903
  }
222834
222904
  ),
@@ -222862,7 +222932,7 @@ function SwamlNode({ id: id2, data, draggable, selected: selected2, width, heigh
222862
222932
  "div",
222863
222933
  {
222864
222934
  className: "rf-node-header",
222865
- title: node2.name,
222935
+ title: elementTitle(node2),
222866
222936
  style: {
222867
222937
  left: 0,
222868
222938
  top: 0,
@@ -223307,8 +223377,7 @@ function FrameNode({ id: id2, data, selected: selected2, width, height, position
223307
223377
  }
223308
223378
  ) : null,
223309
223379
  /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("svg", { className: `rf-node-svg ${elementColorClass}`, width: w2, height: h2, style: { overflow: "visible" }, children: [
223310
- frame2.actions?.length ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("title", { children: frame2.actions.map((action) => `${action.role}: ${action.status}, ${action.provenance}
223311
- ${action.summary}`).join("\n\n") }) : null,
223380
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("title", { children: elementTitle(frame2) }),
223312
223381
  /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("rect", { className: "dframe-hover-band", x: 0, y: 0, width: w2, height: h2, rx: 12, fill: "none", stroke: "transparent" }),
223313
223382
  /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("g", { className: `dshape-surface${frameRectangleSurface(frame2, data.kind, w2, h2) ? " dshape-rectangle" : ""}`, children: isPackage2 && data.kind === "gv" ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("path", { className: `dframe-rect package${isLibraryPackage ? " library" : ""}${data.isContainer ? " container" : ""}`, d: packageFramePath(w2, h2) }) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("rect", { className: `dframe-rect${frame2.meta?.gvReferenceFeature === true ? " dreference-feature" : ""}${data.isContainer ? " container" : ""}${frameSemanticClass ? ` ${frameSemanticClass}` : ""}${frame2.meta?.boundaryBox === true ? " boundary" : ""}${frame2.meta?.parallel === true ? " parallel" : ""}${frame2.meta?.loop === true ? " loop" : ""}${isStructuredControl ? " structured-control" : ""}${isStructuredControl && !isNamedStructuredAction ? " structured-anonymous" : ""}${frame2.meta?.performerLane === true ? " performer" : ""}${frame2.meta?.performerConflict === true ? " performer-conflict" : ""}${frame2.meta?.exhibitBoundary === true ? " exhibitor" : ""}${frame2.meta?.connectionFrame === true ? " dconnection-open" : ""}`, x: 0, y: 0, width: w2, height: h2, rx: frame2.isDef === true ? 0 : 12 }) }),
223314
223383
  /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("svg", { width: w2, height: h2, overflow: clipFrameContent ? "hidden" : "visible", children: [
@@ -223488,7 +223557,7 @@ ${action.summary}`).join("\n\n") }) : null,
223488
223557
  width: frame2.meta?.gvCanExpand === true ? Math.max(0, w2 - 28) : "100%",
223489
223558
  height: isStructuredControl && !isNamedStructuredAction ? frameHeaderHeight : titleHeaderHeight
223490
223559
  },
223491
- title: isStructuredControl && !isNamedStructuredAction && structuredCondition ? `Double-click to edit the condition; drag to move \xAB${structuredKeyword}\xBB` : diagramDisplayNames(frame2).name || `\xAB${structuredKeyword}\xBB${structuredCondition ? ` ${structuredCondition}` : ""}`,
223560
+ title: isStructuredControl && !isNamedStructuredAction && structuredCondition ? `Double-click to edit the condition; drag to move \xAB${structuredKeyword}\xBB` : elementTitle(frame2),
223492
223561
  onDoubleClick: isStructuredControl && !isNamedStructuredAction && structuredCondition ? (e2) => {
223493
223562
  e2.preventDefault();
223494
223563
  e2.stopPropagation();
@@ -224746,6 +224815,9 @@ function configuredDiagnostics(diagnostics, settings) {
224746
224815
  return [{ ...diagnostic, severity }];
224747
224816
  });
224748
224817
  }
224818
+ function diagnosticsFailPolicy(loaded, strict = false) {
224819
+ return loaded.diagnostics.some((item) => item.severity === 1 || (strict || loaded.settings.get(item.uri)?.["swaml.lint.profile"] === "strict") && item.severity === 2) || configuredDiagnostics(loaded.diagnostics, loaded.settings).some((item) => item.severity === 1);
224820
+ }
224749
224821
  function parseArguments(args2, flags) {
224750
224822
  const values = {}, switches = /* @__PURE__ */ new Set(), inputs = [];
224751
224823
  for (let index3 = 0; index3 < args2.length; index3++) {
@@ -224768,7 +224840,7 @@ function parseArguments(args2, flags) {
224768
224840
  // packages/cli/package.json
224769
224841
  var package_default = {
224770
224842
  name: "swaml-diagram",
224771
- version: "0.15.0",
224843
+ version: "0.17.0",
224772
224844
  private: true,
224773
224845
  type: "module",
224774
224846
  scripts: {
@@ -224806,7 +224878,7 @@ async function validateMain(args2) {
224806
224878
  for (const item of diagnostics) console.log(`${item.file}:${item.line}:${item.column}: ${item.severity === 1 ? "error" : item.severity === 2 ? "warning" : "info"} ${item.code ?? ""}: ${item.message}`);
224807
224879
  if (!diagnostics.length) console.log(loaded.diagnostics.some((item) => item.severity === 1) ? `swa.ml source is invalid; ${loaded.diagnostics.length} diagnostic(s) hidden by display settings. Use --no-config to inspect them.` : `Validated ${documents.length} swa.ml file(s), swa.ml 2.1 (implementation 3.0.0).`);
224808
224880
  }
224809
- return loaded.diagnostics.some((item) => item.severity === 1 || (switches.has("strict") || loaded.settings.get(item.uri)?.["swaml.lint.profile"] === "strict") && item.severity === 2) || diagnostics.some((item) => item.severity === 1) ? 1 : 0;
224881
+ return diagnosticsFailPolicy(loaded, switches.has("strict")) ? 1 : 0;
224810
224882
  }
224811
224883
 
224812
224884
  // packages/cli/src/main.ts
@@ -224835,7 +224907,7 @@ async function diagramMain(args2) {
224835
224907
  const sidecar = switches.has("no-config") ? void 0 : readSideCar(root6, file);
224836
224908
  const settings = switches.has("no-config") ? diagramSettingsFor(void 0) : diagramSettingsFor(readProjectConfig(root6), readWorkspaceSettings(root6));
224837
224909
  const loaded = await loadWorkspace([file, ...values.workspace ? [values.workspace] : []], { languageVersion: values["language-version"], noConfig: switches.has("no-config") });
224838
- if (loaded.diagnostics.some((item) => item.severity === 1 || switches.has("strict") && item.severity === 2)) {
224910
+ if (diagnosticsFailPolicy(loaded, switches.has("strict"))) {
224839
224911
  for (const item of loaded.diagnostics) console.error(`${item.file}:${item.line}:${item.column}: ${item.code ?? ""} ${item.message}`);
224840
224912
  return 1;
224841
224913
  }
package/dist/validate.mjs CHANGED
@@ -43725,7 +43725,7 @@ var init_swaml_module = __esm({
43725
43725
  // packages/cli/package.json
43726
43726
  var package_default = {
43727
43727
  name: "swaml-diagram",
43728
- version: "0.15.0",
43728
+ version: "0.17.0",
43729
43729
  private: true,
43730
43730
  type: "module",
43731
43731
  scripts: {
@@ -44494,6 +44494,16 @@ init_semantic();
44494
44494
  init_ast2();
44495
44495
  init_semantic();
44496
44496
 
44497
+ // packages/language-server/src/diagram-names.ts
44498
+ init_names();
44499
+ function usageName(definition) {
44500
+ const words = definition.split(/[^A-Za-z0-9_]+/u).filter(Boolean);
44501
+ if (!words.length || /[^A-Za-z0-9_ ]/u.test(definition)) return definition[0].toLowerCase() + definition.slice(1);
44502
+ const lower = (word) => /^[A-Z0-9]+$/u.test(word) ? word.toLowerCase() : word[0].toLowerCase() + word.slice(1);
44503
+ const value = lower(words[0]) + words.slice(1).map((word) => word[0].toUpperCase() + word.slice(1)).join("");
44504
+ return /^[_A-Za-z]/u.test(value) ? value : "_" + value;
44505
+ }
44506
+
44497
44507
  // packages/language-server/src/diagrams.ts
44498
44508
  init_names();
44499
44509
 
@@ -45490,15 +45500,6 @@ function resolveSelection(services, uri, selection) {
45490
45500
  // packages/language-server/src/diagram-edits.ts
45491
45501
  init_presentation();
45492
45502
 
45493
- // packages/language-server/src/diagram-names.ts
45494
- function usageName(definition) {
45495
- const words = definition.split(/[^A-Za-z0-9_]+/u).filter(Boolean);
45496
- if (!words.length || /[^A-Za-z0-9_ ]/u.test(definition)) return definition[0].toLowerCase() + definition.slice(1);
45497
- const lower = (word) => /^[A-Z0-9]+$/u.test(word) ? word.toLowerCase() : word[0].toLowerCase() + word.slice(1);
45498
- const value = lower(words[0]) + words.slice(1).map((word) => word[0].toUpperCase() + word.slice(1)).join("");
45499
- return /^[_A-Za-z]/u.test(value) ? value : "_" + value;
45500
- }
45501
-
45502
45503
  // packages/language-server/src/statement-edits.ts
45503
45504
  init_lib2();
45504
45505
  init_ast2();
@@ -45723,24 +45724,33 @@ var fresh2 = (base, used) => {
45723
45724
  };
45724
45725
  var forwards = (structure2, port) => members(structure2).filter(isConnect).some((link) => link.source === port && link.target.includes(".") || link.target === port && link.source.includes("."));
45725
45726
  var memberNames = (structure2) => new Set(members(structure2).map((item) => item.name).filter(Boolean));
45726
- function lifeline(models, home, value, what) {
45727
+ function lifeline(models, home, value, what, scenario) {
45727
45728
  const typed = value.trim();
45728
- if (typed === "\xABtest\xBB" || typed.endsWith("::$test")) return { kind: "test" };
45729
- if (typed.endsWith("::$script")) throw Error("A use case without actors has no lifeline to act from. Associate an actor with it first.");
45730
45729
  const gate = /^(.*)::\$port:(.+)$/u.exec(typed), id = gate ? gate[1] : typed;
45730
+ const ids = [.../* @__PURE__ */ new Set([id, parsePathInput(id)])];
45731
45731
  const find = (pkg, path4) => connectionRoutes(pkg).occurrences.find((item) => item.path === path4);
45732
- const packages = [home, ...models.flatMap((model) => model.packages).filter((item) => local(item) && item !== home)];
45733
- for (const pkg of packages) {
45734
- const prefix = diagramId(pkg.name) + "::";
45735
- if (!id.startsWith(prefix)) continue;
45736
- const found2 = find(pkg, id.slice(prefix.length).split("::").join("."));
45732
+ const prefix = diagramId(home.name) + "::";
45733
+ let found = ids.filter((candidate) => candidate.startsWith(prefix) || !candidate.includes("::")).map((candidate) => find(home, (candidate.startsWith(prefix) ? candidate.slice(prefix.length) : candidate).split("::").join("."))).find(Boolean);
45734
+ if (found) return { kind: "occurrence", pkg: home, path: found.path, structure: found.structure, ...gate ? { port: gate[2] } : {} };
45735
+ const scenarioId = scenario && diagramId(identity2(scenario));
45736
+ if (scenario && (typed === "\xABtest\xBB" || ids.includes(scenarioId + "::$test"))) {
45737
+ if (scenario.kind !== "test") throw Error("Only a test calls its subject directly; a use case acts through the ports of its actors.");
45738
+ return { kind: "test" };
45739
+ }
45740
+ if (scenario?.kind === "useCase" && ids.includes(scenarioId + "::$script")) throw Error("A use case without actors has no lifeline to act from. Associate an actor with it first.");
45741
+ const packages = models.flatMap((model) => model.packages).filter((item) => local(item) && item !== home);
45742
+ for (const candidate of ids) for (const pkg of packages) {
45743
+ const prefix2 = diagramId(pkg.name) + "::";
45744
+ if (!candidate.startsWith(prefix2)) continue;
45745
+ const found2 = find(pkg, candidate.slice(prefix2.length).split("::").join("."));
45737
45746
  if (found2) return { kind: "occurrence", pkg, path: found2.path, structure: found2.structure, ...gate ? { port: gate[2] } : {} };
45738
45747
  }
45739
- const found = find(home, parsePathInput(id).split("::").join("."));
45740
- if (found) return { kind: "occurrence", pkg: home, path: found.path, structure: found.structure };
45748
+ found = ids.map((candidate) => find(home, candidate.split("::").join("."))).find(Boolean);
45749
+ if (found) return { kind: "occurrence", pkg: home, path: found.path, structure: found.structure, ...gate ? { port: gate[2] } : {} };
45741
45750
  throw Error(`${typed} is not an occurrence of ${home.name}. Choose one of its lifelines for where the message ${what}.`);
45742
45751
  }
45743
45752
  function connected(from, to) {
45753
+ if (to) samePackage(from, to);
45744
45754
  const routes = connectionRoutes(from.pkg), out = [];
45745
45755
  for (const link of routes.links) for (const [mine, other] of [[0, 1], [1, 0]]) {
45746
45756
  const end = link.ends[mine], peer = link.ends[other], cut = end.lastIndexOf("."), peerCut = peer.lastIndexOf(".");
@@ -45752,6 +45762,9 @@ function connected(from, to) {
45752
45762
  }
45753
45763
  return out;
45754
45764
  }
45765
+ function samePackage(from, to) {
45766
+ if (from.pkg !== to.pkg) throw Error("Messages cannot connect occurrences from different packages. Choose lifelines of the same package.");
45767
+ }
45755
45768
  function addMessage(plan, request) {
45756
45769
  const { models } = plan, kind2 = request.kind;
45757
45770
  if (!["send", "publish", "call"].includes(kind2)) throw Error("Choose send, publish or call for the message.");
@@ -45826,6 +45839,7 @@ function useMember(w2, port, initiator, emitter) {
45826
45839
  return shape;
45827
45840
  }
45828
45841
  function newRoute(w2, initiator, receiver, portName, emitter) {
45842
+ samePackage(initiator, receiver);
45829
45843
  const first2 = declaring(initiator.structure), second = declaring(receiver.structure);
45830
45844
  if (first2 === second) throw Error(`${initiator.path} and ${receiver.path} share one declaration. Connect them in Interconnect View first.`);
45831
45845
  for (const structure2 of [first2, second]) if (!local(structure2)) throw Error("Standard-library declarations are read-only.");
@@ -45871,8 +45885,10 @@ function scriptMessage(w2, scenario, pkg) {
45871
45885
  const subject = caseSubject(scenario), { request, kind: kind2, name, segments } = w2;
45872
45886
  const typedFrom = request.from?.trim() || (segments.length === 3 ? segments[0] : "");
45873
45887
  if (!typedFrom) throw Error("Choose the lifeline the message starts on, or write actor.port.member.");
45874
- const from = lifeline(w2.plan.models, pkg, typedFrom, "starts");
45875
- let to = request.to?.trim() ? lifeline(w2.plan.models, pkg, request.to, "ends") : void 0;
45888
+ const from = lifeline(w2.plan.models, pkg, typedFrom, "starts", scenario);
45889
+ let to = request.to?.trim() ? lifeline(w2.plan.models, pkg, request.to, "ends", scenario) : void 0;
45890
+ if (from.kind === "occurrence" && from.pkg !== pkg || to?.kind === "occurrence" && to.pkg !== pkg)
45891
+ throw Error(`A case uses only occurrences of its own package. Choose lifelines from ${pkg.name}.`);
45876
45892
  if (from.kind === "test") {
45877
45893
  if (scenario.kind !== "test") throw Error("Only a test calls its subject directly; a use case acts through the ports of its actors.");
45878
45894
  if (kind2 !== "call") throw Error("A test calls operations of its subject. To send or publish, start the message on an actor.");
@@ -45890,7 +45906,7 @@ function scriptMessage(w2, scenario, pkg) {
45890
45906
  const args = request.value?.trim() || parameters2.map((type) => w2.initial(scenario, type)).join(", ");
45891
45907
  return callStatement(formatPath(to.path) + "." + formatName(name) + "(" + args + ")", name, result, scenario);
45892
45908
  }
45893
- const isActor = (item) => item?.kind === "occurrence" && !item.path.includes(".") && item.structure !== subject && !active(item.structure);
45909
+ const isActor = (item) => item?.kind === "occurrence" && item.pkg === pkg && !item.path.includes(".") && item.structure !== subject && !active(item.structure);
45894
45910
  const outgoing = isActor(from) || !isActor(to);
45895
45911
  const actor = outgoing ? from : to;
45896
45912
  if (!isActor(actor)) {
@@ -45942,7 +45958,9 @@ function operationMessage(w2, executable, pkg) {
45942
45958
  return found && { kind: "occurrence", pkg, path: found.path, structure: found.structure };
45943
45959
  })();
45944
45960
  let to = request.to?.trim() ? lifeline(w2.plan.models, pkg, request.to, "ends") : void 0;
45945
- if (from?.kind === "occurrence" && to?.kind === "occurrence" && to.path === from.path || !from && !to) {
45961
+ if (from?.kind === "occurrence" && !runs(from)) throw Error(`${executable.name} does not run on ${from.path}. Start the message on its activation.`);
45962
+ if (from?.kind === "occurrence" && to?.kind === "occurrence") samePackage(from, to);
45963
+ if (from?.kind === "occurrence" && to?.kind === "occurrence" && to.pkg === from.pkg && to.path === from.path || !from && !to) {
45946
45964
  if (kind2 !== "call") throw Error("A component does not send to itself. Call one of its operations, or draw the message to another lifeline.");
45947
45965
  const op = members(structure2).filter(isExecutable).find((item) => item.name === name), sig = op && signatureOf(op);
45948
45966
  if (op === executable) throw Error(`${name} would call itself. Choose another operation.`);
@@ -45956,7 +45974,6 @@ function operationMessage(w2, executable, pkg) {
45956
45974
  return callStatement(formatName(name) + "(" + args2 + ")", name, result, executable);
45957
45975
  }
45958
45976
  if (from?.kind !== "occurrence") throw Error("Start the message on the lifeline of a component occurrence.");
45959
- if (!runs(from)) throw Error(`${executable.name} does not run on ${from.path}. Start the message on its activation.`);
45960
45977
  const portName = segments.length === 2 ? segments[0] : void 0;
45961
45978
  if (!to) {
45962
45979
  const peer = connected(from).find((item) => !portName || item.port.name === portName)?.peer;
@@ -48663,6 +48680,7 @@ init_semantic();
48663
48680
  // packages/language-server/src/test-inspection.ts
48664
48681
  init_ast2();
48665
48682
  init_semantic();
48683
+ init_names();
48666
48684
 
48667
48685
  // packages/language-server/src/run-cases.ts
48668
48686
  init_ast2();
@@ -49013,6 +49031,9 @@ function configuredDiagnostics(diagnostics, settings) {
49013
49031
  return [{ ...diagnostic, severity }];
49014
49032
  });
49015
49033
  }
49034
+ function diagnosticsFailPolicy(loaded, strict = false) {
49035
+ return loaded.diagnostics.some((item) => item.severity === 1 || (strict || loaded.settings.get(item.uri)?.["swaml.lint.profile"] === "strict") && item.severity === 2) || configuredDiagnostics(loaded.diagnostics, loaded.settings).some((item) => item.severity === 1);
49036
+ }
49016
49037
  function parseArguments(args, flags) {
49017
49038
  const values = {}, switches = /* @__PURE__ */ new Set(), inputs = [];
49018
49039
  for (let index = 0; index < args.length; index++) {
@@ -49058,7 +49079,7 @@ async function validateMain(args) {
49058
49079
  for (const item of diagnostics) console.log(`${item.file}:${item.line}:${item.column}: ${item.severity === 1 ? "error" : item.severity === 2 ? "warning" : "info"} ${item.code ?? ""}: ${item.message}`);
49059
49080
  if (!diagnostics.length) console.log(loaded.diagnostics.some((item) => item.severity === 1) ? `swa.ml source is invalid; ${loaded.diagnostics.length} diagnostic(s) hidden by display settings. Use --no-config to inspect them.` : `Validated ${documents.length} swa.ml file(s), swa.ml 2.1 (implementation 3.0.0).`);
49060
49081
  }
49061
- return loaded.diagnostics.some((item) => item.severity === 1 || (switches.has("strict") || loaded.settings.get(item.uri)?.["swaml.lint.profile"] === "strict") && item.severity === 2) || diagnostics.some((item) => item.severity === 1) ? 1 : 0;
49082
+ return diagnosticsFailPolicy(loaded, switches.has("strict")) ? 1 : 0;
49062
49083
  }
49063
49084
 
49064
49085
  // packages/cli/src/validate-main.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voidaliot/swaml-cli",
3
- "version": "0.15.0",
3
+ "version": "0.17.0",
4
4
  "description": "swa.ml model validation and SVG/CSV diagram export",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE",