@voidaliot/swaml-cli 0.16.0 → 0.17.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/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,
@@ -169651,6 +169651,21 @@ init_semantic();
169651
169651
  init_lib2();
169652
169652
  init_ast2();
169653
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
169654
169669
  var text = (node2) => node2?.$cstNode?.text.replace(/\s+/gu, " ").trim() ?? "";
169655
169670
  var args = (values) => values.map(text).join(", ");
169656
169671
  var Builder = class {
@@ -169691,7 +169706,7 @@ var Builder = class {
169691
169706
  }
169692
169707
  place(pkg, path7, structure2) {
169693
169708
  const id2 = diagramId(pkg.name + "::" + path7);
169694
- 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) });
169695
169710
  return { pkg, path: path7, structure: structure2, routes: this.routesOf(pkg), lifeline: id2 };
169696
169711
  }
169697
169712
  message(item) {
@@ -170213,7 +170228,7 @@ function executable(root6, ctx, options2) {
170213
170228
  const id3 = diagramId(pkg.name + "::" + occurrence.path);
170214
170229
  if (participants.some((item) => item.id === id3)) continue;
170215
170230
  const type = isComponentUsage(occurrence.structure) ? occurrence.structure.definition?.ref?.name : void 0;
170216
- 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));
170217
170232
  }
170218
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;
170219
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 };
@@ -170747,15 +170762,6 @@ function memberUsersStubs(models, owner2, member, initial) {
170747
170762
  return users.map(({ structure: structure2, port }) => memberStubs(structure2, port.name, member, member.direction === "provides" !== port.reversed, (type) => initial(structure2, type)));
170748
170763
  }
170749
170764
 
170750
- // packages/language-server/src/diagram-names.ts
170751
- function usageName(definition3) {
170752
- const words = definition3.split(/[^A-Za-z0-9_]+/u).filter(Boolean);
170753
- if (!words.length || /[^A-Za-z0-9_ ]/u.test(definition3)) return definition3[0].toLowerCase() + definition3.slice(1);
170754
- const lower2 = (word) => /^[A-Z0-9]+$/u.test(word) ? word.toLowerCase() : word[0].toLowerCase() + word.slice(1);
170755
- const value2 = lower2(words[0]) + words.slice(1).map((word) => word[0].toUpperCase() + word.slice(1)).join("");
170756
- return /^[_A-Za-z]/u.test(value2) ? value2 : "_" + value2;
170757
- }
170758
-
170759
170765
  // packages/language-server/src/diagram-port-connections.ts
170760
170766
  init_lib2();
170761
170767
  init_ast2();
@@ -171097,24 +171103,33 @@ var fresh2 = (base2, used) => {
171097
171103
  };
171098
171104
  var forwards = (structure2, port) => members(structure2).filter(isConnect).some((link4) => link4.source === port && link4.target.includes(".") || link4.target === port && link4.source.includes("."));
171099
171105
  var memberNames = (structure2) => new Set(members(structure2).map((item) => item.name).filter(Boolean));
171100
- function lifeline(models, home, value2, what) {
171106
+ function lifeline(models, home, value2, what, scenario) {
171101
171107
  const typed2 = value2.trim();
171102
- if (typed2 === "\xABtest\xBB" || typed2.endsWith("::$test")) return { kind: "test" };
171103
- if (typed2.endsWith("::$script")) throw Error("A use case without actors has no lifeline to act from. Associate an actor with it first.");
171104
171108
  const gate2 = /^(.*)::\$port:(.+)$/u.exec(typed2), id2 = gate2 ? gate2[1] : typed2;
171109
+ const ids = [.../* @__PURE__ */ new Set([id2, parsePathInput(id2)])];
171105
171110
  const find3 = (pkg, path7) => connectionRoutes(pkg).occurrences.find((item) => item.path === path7);
171106
- const packages = [home, ...models.flatMap((model) => model.packages).filter((item) => local3(item) && item !== home)];
171107
- for (const pkg of packages) {
171108
- const prefix = diagramId(pkg.name) + "::";
171109
- if (!id2.startsWith(prefix)) continue;
171110
- 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("."));
171111
171125
  if (found2) return { kind: "occurrence", pkg, path: found2.path, structure: found2.structure, ...gate2 ? { port: gate2[2] } : {} };
171112
171126
  }
171113
- const found = find3(home, parsePathInput(id2).split("::").join("."));
171114
- 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] } : {} };
171115
171129
  throw Error(`${typed2} is not an occurrence of ${home.name}. Choose one of its lifelines for where the message ${what}.`);
171116
171130
  }
171117
171131
  function connected(from, to) {
171132
+ if (to) samePackage(from, to);
171118
171133
  const routes = connectionRoutes(from.pkg), out = [];
171119
171134
  for (const link4 of routes.links) for (const [mine, other] of [[0, 1], [1, 0]]) {
171120
171135
  const end = link4.ends[mine], peer = link4.ends[other], cut = end.lastIndexOf("."), peerCut = peer.lastIndexOf(".");
@@ -171126,6 +171141,9 @@ function connected(from, to) {
171126
171141
  }
171127
171142
  return out;
171128
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
+ }
171129
171147
  function addMessage(plan, request) {
171130
171148
  const { models } = plan, kind2 = request.kind;
171131
171149
  if (!["send", "publish", "call"].includes(kind2)) throw Error("Choose send, publish or call for the message.");
@@ -171200,6 +171218,7 @@ function useMember(w2, port, initiator, emitter) {
171200
171218
  return shape;
171201
171219
  }
171202
171220
  function newRoute(w2, initiator, receiver, portName, emitter) {
171221
+ samePackage(initiator, receiver);
171203
171222
  const first2 = declaring(initiator.structure), second = declaring(receiver.structure);
171204
171223
  if (first2 === second) throw Error(`${initiator.path} and ${receiver.path} share one declaration. Connect them in Interconnect View first.`);
171205
171224
  for (const structure2 of [first2, second]) if (!local3(structure2)) throw Error("Standard-library declarations are read-only.");
@@ -171245,8 +171264,10 @@ function scriptMessage(w2, scenario, pkg) {
171245
171264
  const subject = caseSubject(scenario), { request, kind: kind2, name: name2, segments } = w2;
171246
171265
  const typedFrom = request.from?.trim() || (segments.length === 3 ? segments[0] : "");
171247
171266
  if (!typedFrom) throw Error("Choose the lifeline the message starts on, or write actor.port.member.");
171248
- const from = lifeline(w2.plan.models, pkg, typedFrom, "starts");
171249
- 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}.`);
171250
171271
  if (from.kind === "test") {
171251
171272
  if (scenario.kind !== "test") throw Error("Only a test calls its subject directly; a use case acts through the ports of its actors.");
171252
171273
  if (kind2 !== "call") throw Error("A test calls operations of its subject. To send or publish, start the message on an actor.");
@@ -171264,7 +171285,7 @@ function scriptMessage(w2, scenario, pkg) {
171264
171285
  const args2 = request.value?.trim() || parameters2.map((type) => w2.initial(scenario, type)).join(", ");
171265
171286
  return callStatement(formatPath(to.path) + "." + formatName(name2) + "(" + args2 + ")", name2, result, scenario);
171266
171287
  }
171267
- 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);
171268
171289
  const outgoing = isActor(from) || !isActor(to);
171269
171290
  const actor = outgoing ? from : to;
171270
171291
  if (!isActor(actor)) {
@@ -171316,7 +171337,9 @@ function operationMessage(w2, executable2, pkg) {
171316
171337
  return found && { kind: "occurrence", pkg, path: found.path, structure: found.structure };
171317
171338
  })();
171318
171339
  let to = request.to?.trim() ? lifeline(w2.plan.models, pkg, request.to, "ends") : void 0;
171319
- 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) {
171320
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.");
171321
171344
  const op = members(structure2).filter(isExecutable).find((item) => item.name === name2), sig = op && signatureOf(op);
171322
171345
  if (op === executable2) throw Error(`${name2} would call itself. Choose another operation.`);
@@ -171330,7 +171353,6 @@ function operationMessage(w2, executable2, pkg) {
171330
171353
  return callStatement(formatName(name2) + "(" + args3 + ")", name2, result, executable2);
171331
171354
  }
171332
171355
  if (from?.kind !== "occurrence") throw Error("Start the message on the lifeline of a component occurrence.");
171333
- if (!runs(from)) throw Error(`${executable2.name} does not run on ${from.path}. Start the message on its activation.`);
171334
171356
  const portName = segments.length === 2 ? segments[0] : void 0;
171335
171357
  if (!to) {
171336
171358
  const peer = connected(from).find((item) => !portName || item.port.name === portName)?.peer;
@@ -175080,15 +175102,15 @@ init_names();
175080
175102
  var cell = (text8) => ({ text: text8 ?? "" });
175081
175103
  var column = (label2, value2) => ({ label: label2, cell: (entry) => cell(value2(entry)) });
175082
175104
  var original = (label2, index3) => ({ label: label2, cell: (entry) => entry.row.cells[index3] });
175083
- var elementName = (path7) => path7.replace(/^.*(?:::|\.)/, "");
175105
+ var elementName = diagramElementName;
175084
175106
  var shortType = (type) => elementName(typeKey(type));
175085
175107
  var display = (text8, fullText) => ({ text: text8 ?? "", ...fullText && fullText !== text8 ? { fullText } : {} });
175086
175108
  var named = (label2, value2) => ({ label: label2, cell: (entry) => {
175087
175109
  const paths = value2(entry);
175088
- return display(paths.map(elementName).join("\n"), paths.join("\n"));
175110
+ return display(paths.map((path7) => elementName(path7, true)).join("\n"), paths.join("\n"));
175089
175111
  } });
175090
175112
  var typed = (label2, value2) => ({ label: label2, cell: (entry) => display(value2(entry, shortType), value2(entry, typeKey)) });
175091
- var canonical2 = (path7) => formatPath(parsePathInput(path7));
175113
+ var canonical2 = formatPath;
175092
175114
  var attributes = (entry) => isRequirement(entry.ast) ? entry.ast.attributes : isComponentDef(entry.ast) || isComponentUsage(entry.ast) ? members(entry.ast).filter(isAttribute) : [];
175093
175115
  function valueText(value2, type) {
175094
175116
  if (isLiteral(value2)) {
@@ -175096,7 +175118,7 @@ function valueText(value2, type) {
175096
175118
  if (value2.boolean !== void 0) return value2.boolean;
175097
175119
  if (value2.number !== void 0) return String(value2.number);
175098
175120
  }
175099
- 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);
175100
175122
  return value2.$cstNode?.text ?? "";
175101
175123
  }
175102
175124
  function attributeCell(entry, name2, source3) {
@@ -175137,7 +175159,7 @@ function gridCategoryTables(entries2, models, source3) {
175137
175159
  const start3 = [original("Name", 0), original("Kind", 1)], end = [original("Documentation", 3), sourceFile];
175138
175160
  const type = { label: "Type", cell: (entry) => {
175139
175161
  const declared = entry.row.cells[2];
175140
- 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) };
175141
175163
  } };
175142
175164
  const tables = [];
175143
175165
  const add = (id2, category, label2, rows, columns) => {
@@ -175150,7 +175172,7 @@ function gridCategoryTables(entries2, models, source3) {
175150
175172
  rows: rows.map((entry) => ({ ...entry.row, cells: columns.map((column2) => column2.cell(entry)) }))
175151
175173
  });
175152
175174
  };
175153
- const pillName = (path7) => ({ text: elementName(path7), fullText: path7 });
175175
+ const pillName = (path7) => ({ text: elementName(path7, true), fullText: path7 });
175154
175176
  const satisfies = { label: "Satisfies", cell: (entry) => ({
175155
175177
  tooltip: "Authored satisfy links identify satisfying designs. These links record intent, not proof or a passed run.",
175156
175178
  pills: claims.filter((item) => item.claim.requirement.ref === entry.ast).map((item) => ({
@@ -175360,6 +175382,7 @@ function convert(n2) {
175360
175382
  return {
175361
175383
  id: id2,
175362
175384
  name: n2.name,
175385
+ ...n2.kind === "package" && n2.name.includes("::") ? { nameDisplayName: diagramElementName(n2.name) } : {},
175363
175386
  keyword: ["component", "port"].includes(n2.kind) && isDef ? n2.kind + " def" : n2.kind === "useCase" ? "use case" : n2.kind,
175364
175387
  isDef,
175365
175388
  shape: n2.kind === "operation" ? "action" : n2.kind === "state" ? "state" : n2.kind === "package" ? "package" : ["useCase", "test"].includes(n2.kind) ? "usecase" : "box",
@@ -175376,7 +175399,19 @@ function requirementDocumentation(node2) {
175376
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))];
175377
175400
  }
175378
175401
  function requirementAttributes(node2) {
175379
- 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;
175380
175415
  }
175381
175416
  function withCommentCards(model, ctx) {
175382
175417
  if (model.kind !== "gv" && model.kind !== "cv") return model;
@@ -175529,7 +175564,7 @@ function packageLinkRows(ctx, entries2) {
175529
175564
  for (const claim of pkg.satisfactions) {
175530
175565
  const requirement = claim.requirement.ref;
175531
175566
  const design = diagramId(pkg.name + "::" + claim.design);
175532
- 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));
175533
175568
  }
175534
175569
  for (const link4 of pkg.verifications) {
175535
175570
  const test = link4.test.ref, requirement = link4.requirement.ref;
@@ -175612,6 +175647,7 @@ async function buildCurrentDiagram(services, params) {
175612
175647
  if (!ast) continue;
175613
175648
  const node2 = model.nodes.find((n2) => n2.id === diagramId(entry.id));
175614
175649
  if (node2) {
175650
+ node2.typeDisplayName = nodeTypeCaption(ast);
175615
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 };
175616
175652
  for (const port of node2.ports ?? []) {
175617
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);
@@ -175636,7 +175672,7 @@ async function buildCurrentDiagram(services, params) {
175636
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 } });
175637
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) });
175638
175674
  });
175639
- 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 (kind2 !== "iv" && 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 ?? []];
175640
175676
  if (node2 && isPortUsage(ast)) {
175641
175677
  node2.type = ast.definition?.$refText ?? "inline";
175642
175678
  node2.meta = { ...node2.meta, optional: ast.optional, reversed: ast.reversed };
@@ -175754,7 +175790,7 @@ async function buildCurrentDiagram(services, params) {
175754
175790
  let current = op;
175755
175791
  while (current && (current.id !== anchor || flowFrame(current))) {
175756
175792
  if (frames.has(current.id)) break;
175757
- 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) } });
175758
175794
  current = current.parent ? scopedNodes.get(current.parent) : void 0;
175759
175795
  }
175760
175796
  }
@@ -175778,7 +175814,7 @@ async function buildCurrentDiagram(services, params) {
175778
175814
  const typeField = ast && gridTypeField(ast);
175779
175815
  const documentationEditable = writable2 && !!(authoredDocumentation !== void 0 || ast && gridDocumentationInsertion(ast));
175780
175816
  const row = { id: n2.id, name: n2.name, keyword: n2.keyword, source: rowSource, cells: [
175781
- { 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 } } : {} },
175782
175818
  { text: n2.keyword },
175783
175819
  { text: n2.type ?? typeField?.value ?? "", ...writable2 && typeField ? { edit: { kind: "type", value: typeField.value } } : {} },
175784
175820
  { text: documentation.join("\n\n"), documentation, ...documentationEditable ? { edit: { kind: "doc", value: authoredDocumentation ?? "" } } : {} },
@@ -178267,13 +178303,14 @@ function annotationLines(text8, width) {
178267
178303
  }
178268
178304
  function requirementContent(node2) {
178269
178305
  const documentation = Array.isArray(node2.meta?.swamlRequirementDocumentation) ? node2.meta.swamlRequirementDocumentation.filter((text8) => typeof text8 === "string") : [];
178270
- 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")) : [];
178271
178307
  return { documentation, attributes: attributes2 };
178272
178308
  }
178273
178309
  function requirementFallback(node2, width, maximumLines = Number.POSITIVE_INFINITY) {
178274
178310
  const content3 = requirementContent(node2), documentation = content3.documentation.join("\n\n");
178275
- const attributes2 = content3.attributes.map((attribute) => `${attribute.name}: ${attribute.type} = ${attribute.value}`).join("\n");
178276
- 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");
178277
178314
  const units = Math.max(1, Math.floor(width / 6.2));
178278
178315
  const attributeLines = attributes2 ? attributes2.split(/\r?\n/u).flatMap((line2) => {
178279
178316
  const wrapped = [];
@@ -202812,6 +202849,9 @@ var import_react5 = __toESM(require_react());
202812
202849
 
202813
202850
  // packages/extension/src/swaml-name.ts
202814
202851
  init_names();
202852
+ function swamlPathName(value2) {
202853
+ return value2.split(/::|\./u).at(-1) ?? value2;
202854
+ }
202815
202855
 
202816
202856
  // packages/extension/src/webview/diagram/toolbox.ts
202817
202857
  var ELEMENT_LABELS = { useCase: "use case" };
@@ -205330,6 +205370,18 @@ var TIME_ORIGIN = 240;
205330
205370
  var TIME_WIDTH = 900;
205331
205371
  var TIME_ROW_HEIGHT = 72;
205332
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
+ }
205333
205385
  function timeScale(horizonNs) {
205334
205386
  const target2 = Math.max(1, horizonNs) / 8, magnitude = 10 ** Math.floor(Math.log10(target2));
205335
205387
  const stepNs = Math.max(1, ([1, 2, 5, 10].find((n2) => n2 * magnitude >= target2) ?? 10) * magnitude);
@@ -205365,9 +205417,8 @@ function timeNodes(model) {
205365
205417
  if (!timing) return [];
205366
205418
  const trace = timing.trace, scale = trace ? timeScale(trace.endNs) : void 0, nodes2 = [];
205367
205419
  const participantLines = (path7) => {
205368
- const name2 = path7.replace((trace?.target ?? model.root.qname) + ".", "").replace(/^[^:]+::/, "");
205369
- const split = name2.lastIndexOf(".");
205370
- 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)];
205371
205422
  };
205372
205423
  const add = (id2, x2, y3, width, height, data) => {
205373
205424
  nodes2.push({
@@ -205388,8 +205439,8 @@ function timeNodes(model) {
205388
205439
  const paths = [.../* @__PURE__ */ new Set([...timing.contracts.map((c2) => c2.functionPath), ...trace?.activations.map((a3) => a3.functionPath) ?? []])];
205389
205440
  for (const path7 of paths) {
205390
205441
  const contractIndex = timing.contracts.findIndex((c2) => c2.functionPath === path7), contract = timing.contracts[contractIndex];
205391
- const executable2 = contract?.modelId ? model.nodes.find((n2) => n2.id === contract.modelId) : model.nodes[contractIndex];
205392
- 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 ?? "";
205393
205444
  const declared = contract?.declared ?? (contract?.wcetNs !== void 0 || contract?.deadlineNs !== void 0);
205394
205445
  const detail = contract ? [
205395
205446
  declared ? "Declared contract" : "No timing contract declared",
@@ -205522,7 +205573,8 @@ var TimeView = (0, import_react10.forwardRef)(function TimeView2({
205522
205573
  onShowGridChange,
205523
205574
  onViewportChange,
205524
205575
  onSelect,
205525
- onReveal
205576
+ onReveal,
205577
+ onContextNode
205526
205578
  }, ref) {
205527
205579
  const [layoutRevision, setLayoutRevision] = (0, import_react10.useState)(0);
205528
205580
  const nodes2 = (0, import_react10.useMemo)(() => timeNodes(model).map((node2) => ({
@@ -205652,6 +205704,13 @@ var TimeView = (0, import_react10.forwardRef)(function TimeView2({
205652
205704
  },
205653
205705
  onPaneClick: () => onSelect(void 0),
205654
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,
205655
205714
  onNodeDoubleClick: (_event, node2) => onReveal(node2.data.source, node2.data.modelId, true),
205656
205715
  children: [
205657
205716
  showGrid && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(DiagramGrid, {}),
@@ -221145,6 +221204,11 @@ function OverlayNodeBadge({ item, w: w2 }) {
221145
221204
 
221146
221205
  // packages/extension/src/webview/diagram/flow/nodes.tsx
221147
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
+ }
221148
221212
  var SIDES = [...PORT_DOCK_SIDES];
221149
221213
  var POS = {
221150
221214
  top: Position3.Top,
@@ -221640,7 +221704,7 @@ function BoxBody({ node: node2, w: w2, h: h2, showMult, quietTitle = false }) {
221640
221704
  ] }) }),
221641
221705
  /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("tbody", { children: requirementAttributes2.map((attribute) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("tr", { children: [
221642
221706
  /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("td", { children: attribute.name }),
221643
- /* @__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 }) }),
221644
221708
  /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("code", { children: attribute.value }) })
221645
221709
  ] }, attribute.name)) })
221646
221710
  ] }) })
@@ -222605,8 +222669,7 @@ function NodeBody({ node: semanticNode, data, selectedPortId, hoveredPortId, mov
222605
222669
  const clip = !fittedGvBox && !connectionBar && (!CLIP_EXEMPT.has(node2.shape) || data.kind === "gv" && node2.shape === "actor");
222606
222670
  const elementColorClass = diagramElementColorClass(diagramElementColorTypeForNode(node2.shape, node2.keyword));
222607
222671
  return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("svg", { className: `rf-node-svg ${elementColorClass}${overlayClassName(node2)}`, width: w2, height: h2, style: { overflow: "visible" }, children: [
222608
- node2.actions?.length ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("title", { children: node2.actions.map((action) => `${action.role}: ${action.status}, ${action.provenance}
222609
- ${action.summary}`).join("\n\n") }) : null,
222672
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("title", { children: elementTitle(semanticNode) }),
222610
222673
  /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(NodeSurface, { node: node2, w: w2, h: h2 }),
222611
222674
  clip ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
222612
222675
  "svg",
@@ -222727,7 +222790,7 @@ function SwamlNode({ id: id2, data, draggable, selected: selected2, width, heigh
222727
222790
  {
222728
222791
  ref: containerRef,
222729
222792
  className: `rf-node${isLifeline ? " rf-lifeline" : ""}${selected2 ? " selected" : ""}${nodeSideStartable ? " rf-node-graph" : ""}${dropClass}${draggable === false ? "" : " rf-node-movable"}`,
222730
- 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),
222731
222794
  style: {
222732
222795
  width: w2,
222733
222796
  height: h2,
@@ -222835,7 +222898,7 @@ function SwamlNode({ id: id2, data, draggable, selected: selected2, width, heigh
222835
222898
  "div",
222836
222899
  {
222837
222900
  className: "dseq-lifeline-header-hit",
222838
- title: node2.name,
222901
+ title: elementTitle(node2),
222839
222902
  style: { left: 0, top: 0, width: w2, height: SEQ_LIFELINE_HEAD_HEIGHT }
222840
222903
  }
222841
222904
  ),
@@ -222869,7 +222932,7 @@ function SwamlNode({ id: id2, data, draggable, selected: selected2, width, heigh
222869
222932
  "div",
222870
222933
  {
222871
222934
  className: "rf-node-header",
222872
- title: node2.name,
222935
+ title: elementTitle(node2),
222873
222936
  style: {
222874
222937
  left: 0,
222875
222938
  top: 0,
@@ -223314,8 +223377,7 @@ function FrameNode({ id: id2, data, selected: selected2, width, height, position
223314
223377
  }
223315
223378
  ) : null,
223316
223379
  /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("svg", { className: `rf-node-svg ${elementColorClass}`, width: w2, height: h2, style: { overflow: "visible" }, children: [
223317
- frame2.actions?.length ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("title", { children: frame2.actions.map((action) => `${action.role}: ${action.status}, ${action.provenance}
223318
- ${action.summary}`).join("\n\n") }) : null,
223380
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("title", { children: elementTitle(frame2) }),
223319
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" }),
223320
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 }) }),
223321
223383
  /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("svg", { width: w2, height: h2, overflow: clipFrameContent ? "hidden" : "visible", children: [
@@ -223495,7 +223557,7 @@ ${action.summary}`).join("\n\n") }) : null,
223495
223557
  width: frame2.meta?.gvCanExpand === true ? Math.max(0, w2 - 28) : "100%",
223496
223558
  height: isStructuredControl && !isNamedStructuredAction ? frameHeaderHeight : titleHeaderHeight
223497
223559
  },
223498
- 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),
223499
223561
  onDoubleClick: isStructuredControl && !isNamedStructuredAction && structuredCondition ? (e2) => {
223500
223562
  e2.preventDefault();
223501
223563
  e2.stopPropagation();
@@ -224778,7 +224840,7 @@ function parseArguments(args2, flags) {
224778
224840
  // packages/cli/package.json
224779
224841
  var package_default = {
224780
224842
  name: "swaml-diagram",
224781
- version: "0.16.0",
224843
+ version: "0.17.1",
224782
224844
  private: true,
224783
224845
  type: "module",
224784
224846
  scripts: {
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.16.0",
43728
+ version: "0.17.1",
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voidaliot/swaml-cli",
3
- "version": "0.16.0",
3
+ "version": "0.17.1",
4
4
  "description": "swa.ml model validation and SVG/CSV diagram export",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE",