sysml-diagram 0.15.0 → 0.15.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/out/main.js CHANGED
@@ -133689,6 +133689,9 @@ function isExhibitStateDecl(item) {
133689
133689
  var ExitAction = "ExitAction";
133690
133690
  var ExposeMember = "ExposeMember";
133691
133691
  var ExposePath = "ExposePath";
133692
+ function isExposePath(item) {
133693
+ return reflection2.isInstance(item, ExposePath);
133694
+ }
133692
133695
  var ExpressionDecl = "ExpressionDecl";
133693
133696
  var FeatureDecl = "FeatureDecl";
133694
133697
  function isFeatureDecl(item) {
@@ -168010,6 +168013,13 @@ var DIAGNOSTIC_MESSAGES = {
168010
168013
  // implicit-redefinition resolution this validator does not yet model.
168011
168014
  RES017_DUPLICATE_MEMBER: (name) => `'${name}' is already declared in this namespace. Members must be distinguishable by name \u2014 rename or remove the duplicate.`,
168012
168015
  RES017_DUPLICATE_SHORT_NAME: (name) => `Short name '<${name}>' is already used in this namespace. Members must be distinguishable \u2014 rename the short name.`,
168016
+ // issue #102 — REQ-387. The filter evaluator (`import-visibility.ts`,
168017
+ // `evaluateFilterCondition`) decides metadata-presence tests and the Boolean
168018
+ // operators over them; every other form fails OPEN, keeping the member. Failing
168019
+ // open is the right default — under-importing would manufacture spurious
168020
+ // RES001s — but an unevaluated filter produces a scope or view that looks
168021
+ // authoritative and is not, so the fail-open is stated rather than assumed.
168022
+ RES018_UNEVALUATED_FILTER: (subject, construct) => `${subject} filter is not evaluated: ${construct} is outside the metadata-filter evaluator, which decides '@'/'@@' metadata tests combined with 'not', 'and'/'&', and 'or'/'|'. The filter fails open \u2014 it is treated as pass-through and removes nothing.`,
168013
168023
  // REQ-007 — SysML v1 → v2 migration guardrail.
168014
168024
  MIG001_V1_KEYWORD: (keyword, v2, note) => `'${keyword}' is a SysML v1 construct, not a SysML v2 keyword. ${note} Use '${v2}'.`,
168015
168025
  MIG002_V1_STEREOTYPE_KNOWN: (stereotype, v2, note) => `SysML v2 has no stereotypes. ${note} Replace \xAB${stereotype}\xBB with '${v2}'.`,
@@ -170467,14 +170477,14 @@ function evaluateFilterCondition(node, metadataTypes, resolveRefs) {
170467
170477
  return node.items.length === 1 ? evaluateFilterCondition(node.items[0], metadataTypes, resolveRefs) : void 0;
170468
170478
  }
170469
170479
  if (isBinExpr(node)) {
170470
- if (node.op === "and" || node.op === "&") {
170480
+ if (CONJUNCTION_OPERATORS.has(node.op)) {
170471
170481
  const left = evaluateFilterCondition(node.left, metadataTypes, resolveRefs);
170472
170482
  const right = evaluateFilterCondition(node.right, metadataTypes, resolveRefs);
170473
170483
  if (left === false || right === false)
170474
170484
  return false;
170475
170485
  return left === void 0 || right === void 0 ? void 0 : true;
170476
170486
  }
170477
- if (node.op === "or" || node.op === "|") {
170487
+ if (DISJUNCTION_OPERATORS.has(node.op)) {
170478
170488
  const left = evaluateFilterCondition(node.left, metadataTypes, resolveRefs);
170479
170489
  const right = evaluateFilterCondition(node.right, metadataTypes, resolveRefs);
170480
170490
  if (left === true || right === true)
@@ -170485,6 +170495,42 @@ function evaluateFilterCondition(node, metadataTypes, resolveRefs) {
170485
170495
  }
170486
170496
  return void 0;
170487
170497
  }
170498
+ var CONJUNCTION_OPERATORS = /* @__PURE__ */ new Set(["and", "&"]);
170499
+ var DISJUNCTION_OPERATORS = /* @__PURE__ */ new Set(["or", "|"]);
170500
+ function undecidableFilterCondition(condition) {
170501
+ if (!condition)
170502
+ return void 0;
170503
+ if (isSelfClassifyExpr(condition)) {
170504
+ return condition.op === "@" || condition.op === "@@" ? void 0 : { node: condition, construct: `the '${condition.op}' classification operator` };
170505
+ }
170506
+ if (isNotExpr(condition) && condition.operand) {
170507
+ return undecidableFilterCondition(condition.operand);
170508
+ }
170509
+ if (condition.$type === "NotExpr")
170510
+ return void 0;
170511
+ if (isParenExpr(condition)) {
170512
+ return condition.items.length === 1 ? undecidableFilterCondition(condition.items[0]) : { node: condition, construct: "a parenthesized expression list" };
170513
+ }
170514
+ if (isBinExpr(condition)) {
170515
+ if (CONJUNCTION_OPERATORS.has(condition.op) || DISJUNCTION_OPERATORS.has(condition.op)) {
170516
+ return undecidableFilterCondition(condition.left) ?? undecidableFilterCondition(condition.right);
170517
+ }
170518
+ return { node: condition, construct: `the '${condition.op}' operator` };
170519
+ }
170520
+ return { node: condition, construct: describeFilterExpr(condition) };
170521
+ }
170522
+ function describeFilterExpr(node) {
170523
+ if (isPostfixOp(node)) {
170524
+ if ((node.dot || node.select) && node.field)
170525
+ return `the '.${node.field}' feature access`;
170526
+ if (node.arrow && node.invoke)
170527
+ return `the '->${node.invoke}' invocation`;
170528
+ return "this postfix expression";
170529
+ }
170530
+ if (isPathExpr(node))
170531
+ return "a plain feature reference";
170532
+ return "this expression form";
170533
+ }
170488
170534
  function attachedMetadataTypes(node, resolveRefs) {
170489
170535
  const siblings = node.$container?.members;
170490
170536
  if (!Array.isArray(siblings))
@@ -171784,6 +171830,7 @@ ${baseIndent}}`;
171784
171830
  checkCrossReferences(node, accept) {
171785
171831
  const index2 = this.buildIndex();
171786
171832
  const imports = [];
171833
+ const exposePaths = [];
171787
171834
  const decls = [];
171788
171835
  const verifyStmts = [];
171789
171836
  const satisfyStmts = [];
@@ -171795,7 +171842,9 @@ ${baseIndent}}`;
171795
171842
  const path10 = importedPath(child);
171796
171843
  if (alias && path10 && importWildcard(child) === "none")
171797
171844
  aliasMap.set(alias, path10);
171798
- } else if (isVerifyStmt(child))
171845
+ } else if (isExposePath(child))
171846
+ exposePaths.push(child);
171847
+ else if (isVerifyStmt(child))
171799
171848
  verifyStmts.push(child);
171800
171849
  else if (isSatisfyStmt(child))
171801
171850
  satisfyStmts.push(child);
@@ -171811,6 +171860,7 @@ ${baseIndent}}`;
171811
171860
  this.checkPrivateImports(imports, index2, accept);
171812
171861
  this.checkPrivateWildcardReferences(node, imports, index2, accept);
171813
171862
  this.checkImportCycles(imports, index2, accept);
171863
+ this.checkUnevaluatedFilters(imports, exposePaths, accept);
171814
171864
  if (sysmlDiagnosticSettings.unusedImports !== "off") {
171815
171865
  this.checkUnusedImports(node, imports, index2, sysmlDiagnosticSettings.unusedImports, accept);
171816
171866
  }
@@ -172429,6 +172479,34 @@ ${baseIndent}}`;
172429
172479
  }
172430
172480
  return false;
172431
172481
  }
172482
+ /**
172483
+ * REQ-387 — RES018: an `import` or `expose` filter the metadata-filter
172484
+ * evaluator cannot decide (issue #102).
172485
+ *
172486
+ * The evaluator keeps a member it cannot decide, so an unevaluated filter
172487
+ * silently contributes the members it was written to exclude — a scope or a
172488
+ * view that reads as authoritative and is not. Failing open stays (narrowing
172489
+ * on a guess would manufacture unresolved-name errors); what changes is that
172490
+ * the model now says so at the filter that is not applied.
172491
+ *
172492
+ * Default severity is `info` rather than a warning: the model is legal and the
172493
+ * limitation is this evaluator's, not the author's. Teams that want an
172494
+ * unevaluated filter to break a build raise it per code through
172495
+ * `sysml.validation.severities` (REQ-240).
172496
+ */
172497
+ checkUnevaluatedFilters(imports, exposePaths, accept) {
172498
+ const report2 = (condition, subject) => {
172499
+ const undecidable = undecidableFilterCondition(condition);
172500
+ if (!undecidable)
172501
+ return;
172502
+ accept(severity("RES018", "info"), DIAGNOSTIC_MESSAGES.RES018_UNEVALUATED_FILTER(subject, undecidable.construct), { node: undecidable.node, code: "RES018" });
172503
+ };
172504
+ for (const imp of imports)
172505
+ for (const filter4 of imp.filters)
172506
+ report2(filter4.condition, "Import");
172507
+ for (const path10 of exposePaths)
172508
+ report2(path10.condition, "Expose");
172509
+ }
172432
172510
  // REQ-324 — RES009 unused import (configurable, OFF by default)
172433
172511
  checkUnusedImports(root4, imports, index2, level, accept) {
172434
172512
  if (imports.length === 0)
@@ -194492,7 +194570,7 @@ async function runExport(command) {
194492
194570
  }
194493
194571
 
194494
194572
  // src/main.ts
194495
- var VERSION2 = true ? "0.15.0" : "dev";
194573
+ var VERSION2 = true ? "0.15.1" : "dev";
194496
194574
  function display(file) {
194497
194575
  const rel2 = path9.relative(process.cwd(), file);
194498
194576
  return rel2 && !rel2.startsWith("..") ? rel2.split(path9.sep).join("/") : file;