sysml-diagram 0.33.0 → 0.34.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/out/main.js CHANGED
@@ -175867,6 +175867,73 @@ function implicitSpecializationsFor(shared) {
175867
175867
  return created;
175868
175868
  }
175869
175869
 
175870
+ // ../language-server/out/src/services/modifier-order.js
175871
+ var MODIFIER_RANK = /* @__PURE__ */ new Map([
175872
+ ["public", 0],
175873
+ ["private", 0],
175874
+ ["protected", 0],
175875
+ ["in", 1],
175876
+ ["out", 1],
175877
+ ["inout", 1],
175878
+ ["derived", 2],
175879
+ ["abstract", 3],
175880
+ ["variation", 4],
175881
+ ["variant", 4],
175882
+ ["composite", 5],
175883
+ ["constant", 6],
175884
+ ["const", 6],
175885
+ ["ref", 7],
175886
+ ["var", 8],
175887
+ ["individual", 9],
175888
+ ["snapshot", 10],
175889
+ ["timeslice", 10]
175890
+ ]);
175891
+ var CANONICAL_MODIFIER_ORDER = "visibility, direction, derived, abstract, variation, composite, constant, ref, var, individual, then the portion kind";
175892
+ function isRankedRun(modifiers2) {
175893
+ return modifiers2.every((m) => MODIFIER_RANK.has(m));
175894
+ }
175895
+ function firstMisplacedModifier(modifiers2) {
175896
+ if (modifiers2.length < 2 || !isRankedRun(modifiers2))
175897
+ return void 0;
175898
+ for (let index2 = 1; index2 < modifiers2.length; index2++) {
175899
+ const rank = MODIFIER_RANK.get(modifiers2[index2]);
175900
+ for (let before = 0; before < index2; before++) {
175901
+ if (MODIFIER_RANK.get(modifiers2[before]) > rank)
175902
+ return { index: index2, before };
175903
+ }
175904
+ }
175905
+ return void 0;
175906
+ }
175907
+ var MODIFIER_PROPERTIES = ["modifiers", "postModifiers"];
175908
+ function modifierRunsOf(node) {
175909
+ const runs = [];
175910
+ if (!node.$cstNode)
175911
+ return runs;
175912
+ for (const property3 of MODIFIER_PROPERTIES) {
175913
+ const modifiers2 = node[property3];
175914
+ if (!Array.isArray(modifiers2) || modifiers2.length < 2)
175915
+ continue;
175916
+ if (!modifiers2.every((m) => typeof m === "string"))
175917
+ continue;
175918
+ if (!isRankedRun(modifiers2))
175919
+ continue;
175920
+ const nodes = grammar_utils_exports.findNodesForProperty(node.$cstNode, property3);
175921
+ if (nodes.length !== modifiers2.length)
175922
+ continue;
175923
+ if (nodes.some((cst, index2) => cst.text !== modifiers2[index2]))
175924
+ continue;
175925
+ runs.push({ property: property3, modifiers: modifiers2, nodes });
175926
+ }
175927
+ return runs;
175928
+ }
175929
+ function isRewritableRun(source, run) {
175930
+ const written = source.slice(run.nodes[0].offset, run.nodes[run.nodes.length - 1].end);
175931
+ return new RegExp(`^${run.modifiers.join("[ \\t]+")}$`, "u").test(written);
175932
+ }
175933
+ function canonicalModifierOrder(modifiers2) {
175934
+ return modifiers2.map((modifier, index2) => ({ modifier, index: index2, rank: MODIFIER_RANK.get(modifier) ?? 0 })).sort((a2, b) => a2.rank - b.rank || a2.index - b.index).map((entry) => entry.modifier);
175935
+ }
175936
+
175870
175937
  // ../language-server/out/src/messages.js
175871
175938
  var DIAGNOSTIC_MESSAGES = {
175872
175939
  // REQ-006 - a broad diagram anchor cannot prove which typed occurrence owns
@@ -175880,6 +175947,10 @@ var DIAGNOSTIC_MESSAGES = {
175880
175947
  LEX004_INVALID_STRING_ESCAPE: (escape) => `Invalid escape '\\${escape}'. KerML Table 4 permits \\' \\" \\b \\f \\t \\n and \\\\.`,
175881
175948
  LEX008_NON_ASCII_IDENTIFIER: (name) => `Identifier '${name}' contains a non-ASCII character. Wrap it in single quotes ('${name}') to use it as an unrestricted name.`,
175882
175949
  LEX009_TRAILING_WHITESPACE: "Trailing whitespace.",
175950
+ // issue #163: SYN025. The grammar accepts any permutation of the leading
175951
+ // modifiers so a mis-ordered declaration still parses; this names the one word
175952
+ // that is out of place and shows the whole prefix as the BNF writes it.
175953
+ SYN025_MODIFIER_ORDER: (modifier, before, canonical) => `Modifier '${modifier}' must be written before '${before}'. The canonical declaration prefix order is ${CANONICAL_MODIFIER_ORDER}; write '${canonical}'.`,
175883
175954
  // REQ-385 — OMG SysML v2 Part 1 §7.17.3 restricts control nodes to the body of
175884
175955
  // an action definition or usage. Successions are NOT covered (§7.13.5 sanctions
175885
175956
  // `first a then b;` and the `then` occurrence shorthand in a part), so the
@@ -180142,6 +180213,7 @@ var SysmlValidator = class _SysmlValidator {
180142
180213
  this.checkActionFlowStyle(node, accept);
180143
180214
  this.checkKeywordOrdering(node, accept);
180144
180215
  this.checkModifierPlacement(node, accept);
180216
+ this.checkModifierOrder(node, accept);
180145
180217
  this.checkEnumerations(node, accept);
180146
180218
  this.checkVariability(node, accept);
180147
180219
  this.checkMultiplicities(node, accept);
@@ -180950,6 +181022,46 @@ ${baseIndent}}`;
180950
181022
  }
180951
181023
  }
180952
181024
  }
181025
+ // REQ-413 — SYN025 canonical order of the leading declaration modifiers.
181026
+ //
181027
+ // `DeclarationPrefix` accepts any permutation so that a mis-ordered prefix
181028
+ // still parses; this is the rule that then says the order is wrong, and the
181029
+ // only place that knows it is `modifier-order.ts`, shared with the quick fix
181030
+ // and the formatter.
181031
+ //
181032
+ // Read off the parsed AST rather than the text, so a modifier word inside a
181033
+ // comment, a string, a documentation body or a name can never reach it. A run
181034
+ // holding a modifier with no canonical position is skipped whole
181035
+ // (`UNRANKED_MODIFIERS`). One diagnostic per RUN, not per declaration: an end
181036
+ // writes two prefixes (`end ref constant a;`), each with its own fix, but the
181037
+ // fix rewrites a whole run, so a second squiggle within one run would name work
181038
+ // the first has already done.
181039
+ checkModifierOrder(node, accept) {
181040
+ const source = ast_utils_exports.getDocument(node)?.textDocument.getText();
181041
+ for (const child of ast_utils_exports.streamAllContents(node)) {
181042
+ for (const run of modifierRunsOf(child)) {
181043
+ const misplaced = firstMisplacedModifier(run.modifiers);
181044
+ if (!misplaced)
181045
+ continue;
181046
+ const canonical = canonicalModifierOrder(run.modifiers).join(" ");
181047
+ const first2 = run.nodes[0];
181048
+ const last2 = run.nodes[run.nodes.length - 1];
181049
+ accept(severity("SYN025", "warning"), DIAGNOSTIC_MESSAGES.SYN025_MODIFIER_ORDER(run.modifiers[misplaced.index], run.modifiers[misplaced.before], canonical), {
181050
+ node: child,
181051
+ range: run.nodes[misplaced.index].range,
181052
+ code: "SYN025",
181053
+ // The fix rewrites the whole run, so offer it only where a
181054
+ // one-line replacement loses nothing.
181055
+ ...source !== void 0 && isRewritableRun(source, run) ? {
181056
+ data: {
181057
+ replacement: canonical,
181058
+ range: { start: first2.range.start, end: last2.range.end }
181059
+ }
181060
+ } : {}
181061
+ });
181062
+ }
181063
+ }
181064
+ }
180953
181065
  // REQ-409 - Enumeration definitions and usages specialize the general
180954
181066
  // variation, attribute and reference rules with a closed value inventory.
180955
181067
  checkEnumerations(node, accept) {
@@ -184393,6 +184505,16 @@ function isAliasFixData(data) {
184393
184505
  function isReplacementFixData(data) {
184394
184506
  return typeof data === "object" && data !== null && typeof data.replacement === "string";
184395
184507
  }
184508
+ function isReorderFixData(data) {
184509
+ if (typeof data !== "object" || data === null)
184510
+ return false;
184511
+ const { replacement, range } = data;
184512
+ if (typeof replacement !== "string" || typeof range !== "object" || range === null)
184513
+ return false;
184514
+ const { start: start2, end } = range;
184515
+ const isPosition = (p) => typeof p === "object" && p !== null && typeof p.line === "number" && typeof p.character === "number";
184516
+ return isPosition(start2) && isPosition(end);
184517
+ }
184396
184518
  function leafAtOffset2(node, offset2) {
184397
184519
  if (isLeafCstNode(node)) {
184398
184520
  return node.offset <= offset2 && offset2 < node.offset + node.length ? node : void 0;
@@ -184563,6 +184685,18 @@ var SysmlCodeActionProvider = class {
184563
184685
  });
184564
184686
  }
184565
184687
  }
184688
+ if (code === "SYN025" && isReorderFixData(diagnostic.data)) {
184689
+ actions.push({
184690
+ title: `Reorder modifiers to '${diagnostic.data.replacement}'`,
184691
+ kind: import_vscode_languageserver18.CodeActionKind.QuickFix,
184692
+ diagnostics: [diagnostic],
184693
+ edit: {
184694
+ changes: {
184695
+ [uri]: [import_vscode_languageserver18.TextEdit.replace(diagnostic.data.range, diagnostic.data.replacement)]
184696
+ }
184697
+ }
184698
+ });
184699
+ }
184566
184700
  if (code === "RES021") {
184567
184701
  actions.push({
184568
184702
  title: "Make this root import 'private'",
@@ -185291,6 +185425,25 @@ ${line2.indent}${unit}`
185291
185425
  });
185292
185426
  }
185293
185427
  }
185428
+ function modifierOrderRewrites(document2, out) {
185429
+ const root4 = document2.parseResult?.value;
185430
+ if (!root4)
185431
+ return;
185432
+ const source = document2.textDocument.getText();
185433
+ for (const node of ast_utils_exports.streamAllContents(root4)) {
185434
+ for (const run of modifierRunsOf(node)) {
185435
+ if (!firstMisplacedModifier(run.modifiers))
185436
+ continue;
185437
+ if (!isRewritableRun(source, run))
185438
+ continue;
185439
+ out.push({
185440
+ offset: run.nodes[0].offset,
185441
+ end: run.nodes[run.nodes.length - 1].end,
185442
+ newText: canonicalModifierOrder(run.modifiers).join(" ")
185443
+ });
185444
+ }
185445
+ }
185446
+ }
185294
185447
  function withinRange(document2, rewrite, range) {
185295
185448
  if (!range)
185296
185449
  return true;
@@ -185300,25 +185453,26 @@ function withinRange(document2, rewrite, range) {
185300
185453
  function styleEdits(input) {
185301
185454
  const { document: document2, settings, options, baseEdits, protectedRanges, range, reservedKeywords } = input;
185302
185455
  const wantsRewrite = settings.emptyBody !== "preserve" || settings.quotedNames !== "preserve" || settings.documentationIndent !== "preserve" || settings.keywords !== "preserve" || settings.lineWidth > 0;
185303
- if (!wantsRewrite)
185304
- return [];
185305
185456
  const leaves = leavesOf(document2);
185306
185457
  if (leaves.length === 0)
185307
185458
  return [];
185308
- const projection2 = projectFormatted(document2, baseEdits);
185309
185459
  const rewrites = [];
185310
- if (settings.keywords === "symbolic")
185311
- keywordRewrites(leaves, rewrites);
185312
- if (settings.emptyBody !== "preserve") {
185313
- emptyBodyRewrites(document2, leaves, projection2, settings, options, rewrites);
185314
- }
185315
- if (settings.quotedNames === "unquoteSafe")
185316
- quotedNameRewrites(leaves, reservedKeywords, rewrites);
185317
- if (settings.documentationIndent === "align") {
185318
- documentationRewrites(document2, leaves, projection2, options, rewrites);
185319
- }
185320
- if (settings.lineWidth > 0)
185321
- wrapRewrites(leaves, projection2, options, settings.lineWidth, rewrites);
185460
+ modifierOrderRewrites(document2, rewrites);
185461
+ if (wantsRewrite) {
185462
+ const projection2 = projectFormatted(document2, baseEdits);
185463
+ if (settings.keywords === "symbolic")
185464
+ keywordRewrites(leaves, rewrites);
185465
+ if (settings.emptyBody !== "preserve") {
185466
+ emptyBodyRewrites(document2, leaves, projection2, settings, options, rewrites);
185467
+ }
185468
+ if (settings.quotedNames === "unquoteSafe")
185469
+ quotedNameRewrites(leaves, reservedKeywords, rewrites);
185470
+ if (settings.documentationIndent === "align") {
185471
+ documentationRewrites(document2, leaves, projection2, options, rewrites);
185472
+ }
185473
+ if (settings.lineWidth > 0)
185474
+ wrapRewrites(leaves, projection2, options, settings.lineWidth, rewrites);
185475
+ }
185322
185476
  const doc = document2.textDocument;
185323
185477
  const source = doc.getText();
185324
185478
  const accepted = [];
@@ -185343,8 +185497,8 @@ function styleEdits(input) {
185343
185497
 
185344
185498
  // ../language-server/out/src/services/formatter.js
185345
185499
  var INDENT = Formatting.indent({ allowMore: true });
185346
- var DEDENT = Formatting.noIndent();
185347
185500
  var NL = Formatting.newLine();
185501
+ var DEDENT_NL = { options: {}, moves: [{ lines: 1, tabs: -1 }] };
185348
185502
  var SPACE = Formatting.oneSpace();
185349
185503
  var NO_SPACE = Formatting.noSpace();
185350
185504
  var SysmlFormatter = class extends AbstractFormatter {
@@ -185470,14 +185624,15 @@ var SysmlFormatter = class extends AbstractFormatter {
185470
185624
  * leaves every other hidden-node path untouched.
185471
185625
  */
185472
185626
  createTextEdit(a2, b, formatting, context) {
185473
- const edits = super.createTextEdit(a2, b, formatting, context);
185627
+ const action = formatting === DEDENT_NL && context.indentation <= 0 ? NL : formatting;
185628
+ const edits = super.createTextEdit(a2, b, action, context);
185474
185629
  if (!b.hidden)
185475
185630
  return edits;
185476
185631
  const startRange = {
185477
185632
  start: { line: b.range.start.line, character: 0 },
185478
185633
  end: b.range.start
185479
185634
  };
185480
- context.indentation += this.findFittingMove(startRange, formatting.moves, context)?.tabs ?? 0;
185635
+ context.indentation += this.findFittingMove(startRange, action.moves, context)?.tabs ?? 0;
185481
185636
  return edits;
185482
185637
  }
185483
185638
  // REQ-259 — Dispatch formatting from AST node kind
@@ -185606,10 +185761,10 @@ var SysmlFormatter = class extends AbstractFormatter {
185606
185761
  fmtBlock(node, keyword) {
185607
185762
  const f = this.getNodeFormatter(node);
185608
185763
  if (!isDocument(node.$container)) {
185609
- f.keyword(keyword).prepend(Formatting.newLines(1 + this.active.blankLines));
185764
+ this.lineAnchor(node, f, keyword).prepend(Formatting.newLines(1 + this.active.blankLines));
185610
185765
  }
185611
185766
  f.keyword(keyword).append(SPACE);
185612
- this.fmtBraces(f);
185767
+ this.fmtBraces(node, f);
185613
185768
  }
185614
185769
  // REQ-355 — Filtered imports keep the `[@Meta]` condition tight against the path
185615
185770
  fmtImport(node) {
@@ -185625,11 +185780,26 @@ var SysmlFormatter = class extends AbstractFormatter {
185625
185780
  ff.keyword("@@").append(NO_SPACE);
185626
185781
  }
185627
185782
  }
185783
+ /**
185784
+ * REQ-258 — Where a member's line break belongs.
185785
+ *
185786
+ * A declaration's kind keyword is NOT always its first token: a leading
185787
+ * modifier (`derived ref attribute a;`), a visibility (`private package P;`)
185788
+ * or a `standard library` marker is written ahead of it. Prepending the
185789
+ * newline to the keyword split such a declaration over two lines. Ask the CST
185790
+ * where the node actually starts rather than listing the words that can come
185791
+ * first, so a grammar change cannot quietly reintroduce the split.
185792
+ */
185793
+ lineAnchor(node, f, keyword) {
185794
+ const start2 = node.$cstNode?.offset;
185795
+ const at = grammar_utils_exports.findNodeForKeyword(node.$cstNode, keyword)?.offset;
185796
+ return start2 !== void 0 && at !== void 0 && at > start2 ? f.node(node) : f.keyword(keyword);
185797
+ }
185628
185798
  // REQ-258, REQ-260 — Format one element per line with canonical keyword spacing
185629
185799
  fmtElement(node, keyword) {
185630
185800
  const f = this.getNodeFormatter(node);
185631
185801
  if (!isDocument(node.$container))
185632
- f.keyword(keyword).prepend(NL);
185802
+ this.lineAnchor(node, f, keyword).prepend(NL);
185633
185803
  f.keyword(keyword).append(SPACE);
185634
185804
  if (node.isDef) {
185635
185805
  f.keyword("def").prepend(SPACE).append(SPACE);
@@ -185639,50 +185809,59 @@ var SysmlFormatter = class extends AbstractFormatter {
185639
185809
  f.keyword(":>>").surround(SPACE);
185640
185810
  f.keyword("=").surround(SPACE);
185641
185811
  f.keyword(";").prepend(NO_SPACE);
185642
- this.fmtBraces(f);
185812
+ this.fmtBraces(node, f);
185643
185813
  }
185644
185814
  // REQ-260 — Keep multi-word `verification case` keyword phrase together
185645
185815
  fmtVerificationCase(node) {
185646
185816
  const f = this.getNodeFormatter(node);
185647
185817
  if (!isDocument(node.$container))
185648
- f.keyword("verification").prepend(NL);
185818
+ this.lineAnchor(node, f, "verification").prepend(NL);
185649
185819
  f.keyword("verification").append(SPACE);
185650
185820
  f.keyword("case").append(SPACE);
185651
185821
  if (node.isDef)
185652
185822
  f.keyword("def").append(SPACE);
185653
185823
  f.keyword(":").surround(SPACE);
185654
185824
  f.keyword(";").prepend(NO_SPACE);
185655
- this.fmtBraces(f);
185825
+ this.fmtBraces(node, f);
185656
185826
  }
185657
185827
  // REQ-260 — Keep multi-word `analysis case` keyword phrase together
185658
185828
  fmtAnalysisCase(node) {
185659
185829
  const f = this.getNodeFormatter(node);
185660
185830
  if (!isDocument(node.$container))
185661
- f.keyword("analysis").prepend(NL);
185831
+ this.lineAnchor(node, f, "analysis").prepend(NL);
185662
185832
  f.keyword("analysis").append(SPACE);
185663
185833
  f.keyword("case").append(SPACE);
185664
185834
  if (node.isDef)
185665
185835
  f.keyword("def").append(SPACE);
185666
185836
  f.keyword(":").surround(SPACE);
185667
185837
  f.keyword(";").prepend(NO_SPACE);
185668
- this.fmtBraces(f);
185838
+ this.fmtBraces(node, f);
185669
185839
  }
185670
185840
  // REQ-260 — Keep multi-word `use case` keyword phrase together
185671
185841
  fmtUseCase(node) {
185672
185842
  const f = this.getNodeFormatter(node);
185673
185843
  if (!isDocument(node.$container))
185674
- f.keyword("use").prepend(NL);
185844
+ this.lineAnchor(node, f, "use").prepend(NL);
185675
185845
  f.keyword("use").append(SPACE);
185676
185846
  f.keyword("case").append(SPACE);
185677
185847
  if (node.isDef)
185678
185848
  f.keyword("def").append(SPACE);
185679
185849
  f.keyword(":").surround(SPACE);
185680
185850
  f.keyword(";").prepend(NO_SPACE);
185681
- this.fmtBraces(f);
185851
+ this.fmtBraces(node, f);
185682
185852
  }
185683
- fmtBraces(f) {
185853
+ /**
185854
+ * REQ-258 — A block's braces.
185855
+ *
185856
+ * The closing brace steps back out only when the body actually stepped in.
185857
+ * An EMPTY body never opened a level (`{` and `}` are adjacent, and the
185858
+ * indent `{` appends is spent on `}` itself), so dedenting it would take the
185859
+ * brace one level below its owner.
185860
+ */
185861
+ fmtBraces(node, f) {
185684
185862
  f.keyword("{").surround(SPACE).append(INDENT);
185685
- f.keyword("}").prepend(DEDENT).prepend(NL);
185863
+ const members = node.members;
185864
+ f.keyword("}").prepend(members && members.length > 0 ? DEDENT_NL : NL);
185686
185865
  }
185687
185866
  };
185688
185867
 
@@ -210628,7 +210807,7 @@ async function runExport(command) {
210628
210807
  }
210629
210808
 
210630
210809
  // src/main.ts
210631
- var VERSION2 = true ? "0.33.0" : "dev";
210810
+ var VERSION2 = true ? "0.34.0" : "dev";
210632
210811
  function display(file) {
210633
210812
  const rel2 = path9.relative(process.cwd(), file);
210634
210813
  return rel2 && !rel2.startsWith("..") ? rel2.split(path9.sep).join("/") : file;