sysml-diagram 0.41.0 → 0.42.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
@@ -177829,6 +177829,28 @@ var DIAGNOSTIC_MESSAGES = {
177829
177829
  // include binds one of the included use case's actor parameters.
177830
177830
  SSM047_INCLUDE_SUBJECT_TYPE: (included, includedType, containerType) => `Included use case '${included}' has a subject of type '${includedType}', which does not conform to the including case's subject of type '${containerType}'. An included use case is investigated on the same subject.`,
177831
177831
  SSM048_INCLUDE_ACTOR_BINDING: (actor, included, known2) => `'${actor}' is not an actor parameter of the included use case '${included}'. It declares ${known2}.`,
177832
+ // issue #168 - a metadata usage annotates an element with ONE metadata
177833
+ // definition or metaclass (OMG SysML v2 Part 1 §7.27.1). A second type has
177834
+ // no place to put its own feature values, so the body becomes unreadable.
177835
+ SSM049_METADATA_MULTIPLE_TYPES: (first2, second) => `A metadata usage names more than one type ('${first2}' and '${second}'). A metadata usage applies exactly one metadata definition or metaclass, so keep one and write the other as a second annotation.`,
177836
+ // issue #168 - a feature the metadata definition declares without a
177837
+ // multiplicity is required, and nothing else can supply its value: the
177838
+ // annotation IS the place the model states it.
177839
+ SSM050_METADATA_BINDING_MISSING: (type, features) => `This '${type}' annotation binds no value for ${features}. A metadata feature with no multiplicity is required, so give it a value in the body or declare it '[0..1]' on the definition.`,
177840
+ // issue #168 - two members that name one feature state two values for it.
177841
+ SSM051_METADATA_BINDING_DUPLICATE: (feature, type) => `'${feature}' is bound twice in this '${type}' annotation. A metadata feature takes one value, so remove one of the two members.`,
177842
+ // issue #168 - a body member with no `ref` and no `:>>` redefines the
177843
+ // same-named feature of the metadata type (§7.27.2), so a name the type does
177844
+ // not declare redefines nothing and its value is never read.
177845
+ SSM052_METADATA_FEATURE_UNKNOWN: (feature, type, known2) => `'${feature}' is not a feature of the metadata definition '${type}'. It declares ${known2}.`,
177846
+ // issue #168 - metadata is part of the model's own syntax, so its values
177847
+ // have to be readable without instances.
177848
+ SSM053_METADATA_VALUE_NOT_MODEL_LEVEL: (feature, written) => `The value bound to '${feature}' reads '${written}', which exists only once the model is instantiated. A metadata value must be readable from the model alone, so use a literal, an enumeration value, or a feature that carries one.`,
177849
+ SSM054_METADATA_VALUE_TYPE: (feature, valueType, featureType) => `'${feature}' is typed '${featureType}', but the value bound to it is a '${valueType}'. Bind a value of the feature's own type.`,
177850
+ // issue #168 - `metadata def Classified { ref :>> annotatedElement : SysML::Usage; }`
177851
+ // states what the definition may annotate; every explicit `about` target and
177852
+ // the element an untargeted usage sits on bind that same feature.
177853
+ SSM055_METADATA_TARGET_NOT_APPLICABLE: (target, targetKind, type, allowed) => `'${target}' is a '${targetKind}', but '${type}' annotates ${allowed}. Annotate an element of one of those kinds, or widen the definition's 'annotatedElement'.`,
177832
177854
  // REQ-392 — a `sysml-format` comment the formatter cannot act on. Advisory:
177833
177855
  // the directive is inert, and saying so beats leaving the author to wonder
177834
177856
  // why their layout was reformatted anyway.
@@ -181461,8 +181483,334 @@ function compositionProblemsOf(node, resolve8) {
181461
181483
  return problems;
181462
181484
  }
181463
181485
 
181486
+ // ../language-server/out/src/services/metadata-semantics.js
181487
+ var MAX_DEPTH = 32;
181488
+ var SPECIALIZATION_KINDS7 = /* @__PURE__ */ new Set([
181489
+ ":>",
181490
+ "specializes",
181491
+ ":>>",
181492
+ "redefines",
181493
+ "subsets"
181494
+ ]);
181495
+ var REDEFINITION_KINDS4 = /* @__PURE__ */ new Set([":>>", "redefines"]);
181496
+ var STRUCTURAL_FEATURE_NAMES = /* @__PURE__ */ new Set(["self", "annotatedElement"]);
181497
+ var ANNOTATED_ELEMENT = "annotatedElement";
181498
+ function isMetadataUsage(node) {
181499
+ if (node.$type === "MetadataAnnotation")
181500
+ return true;
181501
+ return node.$type === "MetadataDecl" && node.isDef !== true;
181502
+ }
181503
+ function isMetadataPrefixTag(node) {
181504
+ return node.$type === "PrefixMetadataTag";
181505
+ }
181506
+ function metadataTypeNamesOf(node) {
181507
+ const usage = node;
181508
+ const names = [];
181509
+ const add = (text) => {
181510
+ const trimmed = text?.trim();
181511
+ if (trimmed)
181512
+ names.push(trimmed);
181513
+ };
181514
+ add((usage.type ?? usage.typing?.type)?.$refText);
181515
+ for (const more of usage.typing?.moreTypes ?? [])
181516
+ add(more.$refText);
181517
+ for (const typing of usage.moreTypings ?? []) {
181518
+ add(typing.type?.$refText);
181519
+ for (const more of typing.moreTypes ?? [])
181520
+ add(more.$refText);
181521
+ }
181522
+ return names;
181523
+ }
181524
+ function metadataTypeNodeOf(node, resolve8) {
181525
+ const usage = node;
181526
+ const reference = usage.type ?? usage.typing?.type;
181527
+ if (reference?.ref)
181528
+ return reference.ref;
181529
+ const written = reference?.$refText?.trim();
181530
+ return written ? resolve8(written, node) : void 0;
181531
+ }
181532
+ function metadataBindingsOf(node) {
181533
+ const bindings = [];
181534
+ for (const member of node.members ?? []) {
181535
+ if (NON_BINDING_MEMBER_TYPES.has(member.$type))
181536
+ continue;
181537
+ const redefined = redefinedNameOf2(member);
181538
+ if (redefined) {
181539
+ bindings.push({ name: redefined, form: "redefinition", node: member, value: member.value });
181540
+ continue;
181541
+ }
181542
+ if (member.name) {
181543
+ bindings.push({ name: member.name, form: "shorthand", node: member, value: member.value });
181544
+ }
181545
+ }
181546
+ return bindings;
181547
+ }
181548
+ var NON_BINDING_MEMBER_TYPES = /* @__PURE__ */ new Set([
181549
+ "DocCommentMember",
181550
+ "CommentStmt",
181551
+ "RepStmt",
181552
+ "MetadataAnnotation",
181553
+ "PrefixMetadataMember",
181554
+ "Import",
181555
+ "AliasDecl",
181556
+ "FilterMember"
181557
+ ]);
181558
+ function redefinedNameOf2(member) {
181559
+ for (const relationship of [...member.preRelationships ?? [], ...member.relationships ?? []]) {
181560
+ if (!relationship.kind || !REDEFINITION_KINDS4.has(relationship.kind))
181561
+ continue;
181562
+ const target = (relationship.targets ?? [])[0];
181563
+ const simple = target?.split(/::|\./u).pop()?.trim();
181564
+ if (simple)
181565
+ return simple;
181566
+ }
181567
+ return void 0;
181568
+ }
181569
+ function metadataFeaturesOf(type, resolve8, implicitBaseNames = () => []) {
181570
+ const features = /* @__PURE__ */ new Map();
181571
+ const inherited = new Set(STRUCTURAL_FEATURE_NAMES);
181572
+ const seen = /* @__PURE__ */ new Set();
181573
+ let complete = true;
181574
+ const collectNames = (owner, depth, visited) => {
181575
+ if (!owner || depth > MAX_DEPTH || visited.has(owner))
181576
+ return;
181577
+ visited.add(owner);
181578
+ for (const member of owner.members ?? []) {
181579
+ const name = member.name ?? redefinedNameOf2(member);
181580
+ if (name)
181581
+ inherited.add(name);
181582
+ }
181583
+ for (const supertype of specializationTargetsOf2(owner)) {
181584
+ collectNames(resolve8(supertype, owner), depth + 1, visited);
181585
+ }
181586
+ };
181587
+ const walk = (owner, depth) => {
181588
+ if (!owner || depth > MAX_DEPTH || seen.has(owner)) {
181589
+ if (!owner)
181590
+ complete = false;
181591
+ return;
181592
+ }
181593
+ seen.add(owner);
181594
+ for (const base of implicitBaseNames(owner)) {
181595
+ collectNames(resolve8(base, owner), 0, /* @__PURE__ */ new Set());
181596
+ }
181597
+ for (const member of owner.members ?? []) {
181598
+ if (!isFeatureMember(member))
181599
+ continue;
181600
+ const name = member.name ?? redefinedNameOf2(member);
181601
+ if (!name)
181602
+ continue;
181603
+ const known2 = features.get(name);
181604
+ if (known2) {
181605
+ if (suppliedValueOf(member) !== void 0) {
181606
+ known2.hasDefault = true;
181607
+ known2.required = false;
181608
+ }
181609
+ continue;
181610
+ }
181611
+ features.set(name, {
181612
+ name,
181613
+ node: member,
181614
+ typeName: writtenTypeNameOf(member),
181615
+ hasDefault: suppliedValueOf(member) !== void 0,
181616
+ required: isRequiredFeature(member)
181617
+ });
181618
+ }
181619
+ for (const supertype of specializationTargetsOf2(owner)) {
181620
+ const resolved = resolve8(supertype, owner);
181621
+ if (!resolved) {
181622
+ complete = false;
181623
+ continue;
181624
+ }
181625
+ walk(resolved, depth + 1);
181626
+ }
181627
+ };
181628
+ if (!type)
181629
+ return { features: [], inherited, complete: false };
181630
+ walk(type, 0);
181631
+ return { features: [...features.values()], inherited, complete };
181632
+ }
181633
+ function isFeatureMember(member) {
181634
+ if (NON_BINDING_MEMBER_TYPES.has(member.$type))
181635
+ return false;
181636
+ if (member.$type === "MetadataDecl" && member.isDef === true)
181637
+ return false;
181638
+ return member.name !== void 0 || redefinedNameOf2(member) !== void 0;
181639
+ }
181640
+ function writtenTypeNameOf(member) {
181641
+ const written = member.typing?.type?.$refText?.trim();
181642
+ return written && written.length > 0 ? written : void 0;
181643
+ }
181644
+ function suppliedValueOf(member) {
181645
+ return member.value ?? member.default?.value;
181646
+ }
181647
+ function isRequiredFeature(member) {
181648
+ if (suppliedValueOf(member) !== void 0)
181649
+ return false;
181650
+ if ((member.modifiers ?? []).includes("abstract"))
181651
+ return false;
181652
+ if (STRUCTURAL_FEATURE_NAMES.has(member.name ?? ""))
181653
+ return false;
181654
+ if (STRUCTURAL_FEATURE_NAMES.has(redefinedNameOf2(member) ?? ""))
181655
+ return false;
181656
+ const lower2 = member.multiplicity?.lower;
181657
+ if (!lower2)
181658
+ return true;
181659
+ if (lower2.star === true)
181660
+ return false;
181661
+ if (lower2.intVal === void 0)
181662
+ return false;
181663
+ return lower2.intVal >= 1;
181664
+ }
181665
+ function annotatedElementRestrictionsOf(type, resolve8) {
181666
+ const restrictions = [];
181667
+ const seen = /* @__PURE__ */ new Set();
181668
+ const walk = (owner, depth) => {
181669
+ if (!owner || depth > MAX_DEPTH || seen.has(owner))
181670
+ return;
181671
+ seen.add(owner);
181672
+ for (const member of owner.members ?? []) {
181673
+ const binds = member.name === ANNOTATED_ELEMENT || redefinedNameOf2(member) === ANNOTATED_ELEMENT || subsetTargetsOf(member).includes(ANNOTATED_ELEMENT);
181674
+ if (!binds)
181675
+ continue;
181676
+ const typeName = writtenTypeNameOf(member);
181677
+ if (typeName) {
181678
+ restrictions.push({ typeName, node: member, owner, resolvedType: resolve8(typeName, member) });
181679
+ }
181680
+ }
181681
+ for (const supertype of specializationTargetsOf2(owner))
181682
+ walk(resolve8(supertype, owner), depth + 1);
181683
+ };
181684
+ walk(type, 0);
181685
+ return restrictions;
181686
+ }
181687
+ function subsetTargetsOf(member) {
181688
+ const targets = [];
181689
+ for (const relationship of [...member.preRelationships ?? [], ...member.relationships ?? []]) {
181690
+ if (relationship.kind !== ":>" && relationship.kind !== "subsets")
181691
+ continue;
181692
+ for (const target of relationship.targets ?? []) {
181693
+ const simple = target.split(/::|\./u).pop()?.trim();
181694
+ if (simple)
181695
+ targets.push(simple);
181696
+ }
181697
+ }
181698
+ return targets;
181699
+ }
181700
+ function metadataTargetsOf(node, resolve8) {
181701
+ const usage = node;
181702
+ const written = usage.targets ?? [];
181703
+ if (written.length > 0) {
181704
+ return written.map((text, occurrence) => ({
181705
+ text: text.trim(),
181706
+ node: resolve8(text.trim(), occurrence),
181707
+ explicit: true
181708
+ }));
181709
+ }
181710
+ const owner = annotatedOwnerOf(node);
181711
+ if (!owner)
181712
+ return [];
181713
+ return [{ text: owner.name ?? owner.$type, node: owner, explicit: false }];
181714
+ }
181715
+ function annotatedOwnerOf(node) {
181716
+ const container = node.$container;
181717
+ if (container?.$type === "PrefixMetadataMember") {
181718
+ return container.element;
181719
+ }
181720
+ if (!container)
181721
+ return void 0;
181722
+ if (!NON_ANNOTATED_CONTAINERS.has(container.$type))
181723
+ return container;
181724
+ if (node.$type !== "MetadataAnnotation")
181725
+ return void 0;
181726
+ return followingDeclarationOf(node, container);
181727
+ }
181728
+ function followingDeclarationOf(node, container) {
181729
+ const members = container.members ?? container.elements ?? [];
181730
+ const index2 = members.indexOf(node);
181731
+ if (index2 < 0)
181732
+ return void 0;
181733
+ for (let next = index2 + 1; next < members.length; next += 1) {
181734
+ const candidate = members[next];
181735
+ if (candidate.$type === "MetadataAnnotation")
181736
+ continue;
181737
+ return candidate;
181738
+ }
181739
+ return void 0;
181740
+ }
181741
+ var NON_ANNOTATED_CONTAINERS = /* @__PURE__ */ new Set(["Document", "Package", "NamespaceDecl"]);
181742
+ function valueEvaluability(value, resolve8) {
181743
+ if (!value)
181744
+ return "unknown";
181745
+ let verdict = "model-level";
181746
+ for (const node of [value, ...ast_utils_exports.streamAllContents(value)]) {
181747
+ if (node.$type !== "PathExpr")
181748
+ continue;
181749
+ const written = pathTextOf(node);
181750
+ if (!written)
181751
+ return "unknown";
181752
+ const segments = written.split(/::|\./u).map((segment) => segment.trim()).filter(Boolean);
181753
+ const root4 = segments.length > 0 ? resolve8(segments[0], node) : void 0;
181754
+ if (root4 && isOccurrenceUsage(root4))
181755
+ return "instance-level";
181756
+ if (segments.length > 1) {
181757
+ if (!root4)
181758
+ return "unknown";
181759
+ continue;
181760
+ }
181761
+ const target = resolve8(written, node);
181762
+ if (!target)
181763
+ return "unknown";
181764
+ if (referentEvaluability(target) === "unknown")
181765
+ verdict = "unknown";
181766
+ }
181767
+ return verdict;
181768
+ }
181769
+ function pathTextOf(node) {
181770
+ const text = node.$cstNode?.text?.trim();
181771
+ return text && text.length > 0 ? text : void 0;
181772
+ }
181773
+ function referentEvaluability(target) {
181774
+ if (isOwnedEnumerationValue(target))
181775
+ return "model-level";
181776
+ const node = target;
181777
+ if (node.isDef === true)
181778
+ return "model-level";
181779
+ if (node.value !== void 0)
181780
+ return "model-level";
181781
+ return isOccurrenceUsage(node) ? "instance-level" : "unknown";
181782
+ }
181783
+ function isOccurrenceUsage(node) {
181784
+ return node.isDef !== true && OCCURRENCE_USAGE_TYPES.has(node.$type);
181785
+ }
181786
+ var OCCURRENCE_USAGE_TYPES = /* @__PURE__ */ new Set([
181787
+ "PartDecl",
181788
+ "ItemDecl",
181789
+ "PortDecl",
181790
+ "ActionDecl",
181791
+ "StateDecl",
181792
+ "OccurrenceDecl",
181793
+ "ConnectionDecl",
181794
+ "InterfaceDecl",
181795
+ "AllocationDecl",
181796
+ "EventDecl"
181797
+ ]);
181798
+ function specializationTargetsOf2(node) {
181799
+ const owner = node;
181800
+ const targets = [];
181801
+ for (const relationship of [...owner.preRelationships ?? [], ...owner.relationships ?? []]) {
181802
+ if (relationship.kind && SPECIALIZATION_KINDS7.has(relationship.kind)) {
181803
+ targets.push(...relationship.targets ?? []);
181804
+ }
181805
+ }
181806
+ const typed = owner.typing?.type?.$refText;
181807
+ if (typed)
181808
+ targets.push(typed);
181809
+ return targets.map((target) => target.trim()).filter((target) => target.length > 0);
181810
+ }
181811
+
181464
181812
  // ../language-server/out/src/services/validator.js
181465
- var REDEFINITION_KINDS4 = /* @__PURE__ */ new Set([
181813
+ var REDEFINITION_KINDS5 = /* @__PURE__ */ new Set([
181466
181814
  ":>>",
181467
181815
  "redefines",
181468
181816
  ":>",
@@ -181556,7 +181904,7 @@ function maskNonCode(text) {
181556
181904
  }
181557
181905
  return out.join("");
181558
181906
  }
181559
- var SPECIALIZATION_KINDS7 = /* @__PURE__ */ new Set([":>", ":>>", "specializes", "subsets", "redefines"]);
181907
+ var SPECIALIZATION_KINDS8 = /* @__PURE__ */ new Set([":>", ":>>", "specializes", "subsets", "redefines"]);
181560
181908
  var CONSTRAINT_SIDE_EFFECT_TYPES = /* @__PURE__ */ new Set([
181561
181909
  "AssignNode",
181562
181910
  "SendNode",
@@ -181685,6 +182033,18 @@ function owningTypeOf(node) {
181685
182033
  return void 0;
181686
182034
  return NAMESPACE_ONLY_TYPES.has(owner.$type) ? void 0 : owner;
181687
182035
  }
182036
+ var MAX_LISTED_FEATURES = 8;
182037
+ function quotedList(names) {
182038
+ return names.map((name) => `'${name}'`).join(", ");
182039
+ }
182040
+ function knownFeatureList(features) {
182041
+ const names = features.map((feature) => feature.name);
182042
+ if (names.length === 0)
182043
+ return "no features";
182044
+ if (names.length <= MAX_LISTED_FEATURES)
182045
+ return quotedList(names);
182046
+ return `${quotedList(names.slice(0, MAX_LISTED_FEATURES))} and ${names.length - MAX_LISTED_FEATURES} more`;
182047
+ }
181688
182048
  function declLabel(node, kind) {
181689
182049
  const name = node.name;
181690
182050
  return name ? `'${name}'` : `this '${kind}'`;
@@ -181727,8 +182087,16 @@ var SysmlValidator = class _SysmlValidator {
181727
182087
  // linker's own lazy single-file load rather than pulling the library into
181728
182088
  // the workspace; the model memoizes each chain for the whole session.
181729
182089
  implicit;
182090
+ // REQ-419 - issue #168: the metadata checks read the SHIPPED metadata model
182091
+ // - `Metaobjects::Metaobject::annotatedElement` and the `SysML.sysml`
182092
+ // metaclass hierarchy - which the workspace never parses. The linker's own
182093
+ // lazy single-file load is the one path that reads an indexed library
182094
+ // declaration without pulling its document into `LangiumDocuments`, so the
182095
+ // metadata resolver goes through it rather than a second loader.
182096
+ linker;
181730
182097
  constructor(services) {
181731
182098
  this.serviceRegistry = services.shared.ServiceRegistry;
182099
+ this.linker = services.references.Linker;
181732
182100
  this.indexManager = services.shared.workspace.IndexManager;
181733
182101
  this.langiumDocuments = services.shared.workspace.LangiumDocuments;
181734
182102
  this.astNodeLocator = services.workspace.AstNodeLocator;
@@ -181798,7 +182166,7 @@ var SysmlValidator = class _SysmlValidator {
181798
182166
  // inventory completely. A later segment depends on the KerML semantic model
181799
182167
  // this resolver does not evaluate.
181800
182168
  checkRelationshipTargets(node, accept) {
181801
- if (!node.kind || !REDEFINITION_KINDS4.has(node.kind))
182169
+ if (!node.kind || !REDEFINITION_KINDS5.has(node.kind))
181802
182170
  return;
181803
182171
  for (let ordinal = 0; ordinal < node.targets.length; ordinal += 1) {
181804
182172
  const resolution = this.featurePaths.resolvePropertyPath(node, "targets", ordinal);
@@ -183189,7 +183557,7 @@ ${baseIndent}}`;
183189
183557
  accept(severity("SYN019", "error"), DIAGNOSTIC_MESSAGES.SYN019_ABSTRACT_VARIATION, { node: child, code: "SYN019" });
183190
183558
  }
183191
183559
  for (const relation of [...decl.preRelationships ?? [], ...decl.relationships ?? []]) {
183192
- if (!relation.kind || !SPECIALIZATION_KINDS7.has(relation.kind))
183560
+ if (!relation.kind || !SPECIALIZATION_KINDS8.has(relation.kind))
183193
183561
  continue;
183194
183562
  for (let index2 = 0; index2 < (relation.targets?.length ?? 0); index2 += 1) {
183195
183563
  const resolution = this.featurePaths.resolvePropertyPath(relation, "targets", index2);
@@ -183548,6 +183916,7 @@ ${baseIndent}}`;
183548
183916
  const verifyStmts = [];
183549
183917
  const satisfyStmts = [];
183550
183918
  const includeStmts = [];
183919
+ const metadataUsages = [];
183551
183920
  const aliasMap = /* @__PURE__ */ new Map();
183552
183921
  for (const child of ast_utils_exports.streamAllContents(node)) {
183553
183922
  if (isImport(child)) {
@@ -183573,6 +183942,8 @@ ${baseIndent}}`;
183573
183942
  }
183574
183943
  if (child.$type === "IncludeStmt")
183575
183944
  includeStmts.push(child);
183945
+ if (isMetadataUsage(child) || isMetadataPrefixTag(child))
183946
+ metadataUsages.push(child);
183576
183947
  }
183577
183948
  this.checkAmbiguousReferences(node, imports, index2, accept);
183578
183949
  this.checkPrivateImports(imports, index2, accept);
@@ -183608,7 +183979,7 @@ ${baseIndent}}`;
183608
183979
  this.checkInverseOfTargets(decl, index2, accept);
183609
183980
  this.checkTypeComposition(decl, index2, accept);
183610
183981
  }
183611
- this.checkTypeConformance(decls, satisfyStmts, includeStmts, index2, accept);
183982
+ this.checkTypeConformance(decls, satisfyStmts, includeStmts, metadataUsages, index2, accept);
183612
183983
  }
183613
183984
  // ══════════════════════════════════════════════════════════════════════
183614
183985
  // REQ-390 — SSM017-SSM021: whole-model type conformance (issue #104)
@@ -183618,7 +183989,7 @@ ${baseIndent}}`;
183618
183989
  // the walk, so a type rooted in the unparsed standard library yields
183619
183990
  // `unknown` and no diagnostic. That is what keeps the OMG corpus clean while
183620
183991
  // still catching the workspace-local mistakes these codes exist for.
183621
- checkTypeConformance(decls, satisfyStmts, includeStmts, index2, accept) {
183992
+ checkTypeConformance(decls, satisfyStmts, includeStmts, metadataUsages, index2, accept) {
183622
183993
  const model = new ConformanceModel((name) => this.resolveUnique(name, index2), (node) => this.implicit?.closureOf(node) ?? { names: /* @__PURE__ */ new Set(), complete: true });
183623
183994
  for (const decl of decls) {
183624
183995
  this.checkRedefinitionTypeConformance(decl, model, index2, accept);
@@ -183640,6 +184011,189 @@ ${baseIndent}}`;
183640
184011
  this.checkSatisfierSubjectType(stmt, model, index2, accept);
183641
184012
  for (const stmt of includeStmts)
183642
184013
  this.checkIncludeBindings(stmt, model, index2, accept);
184014
+ if (metadataUsages.length > 0)
184015
+ this.checkMetadataUsages(metadataUsages, index2, accept);
184016
+ }
184017
+ // ══════════════════════════════════════════════════════════════════════
184018
+ // REQ-419 - SSM049-SSM055: metadata bindings and applicability (issue #168)
184019
+ // ══════════════════════════════════════════════════════════════════════
184020
+ /**
184021
+ * REQ-419 - a name resolved for the metadata family, INCLUDING the standard
184022
+ * library.
184023
+ *
184024
+ * `resolveUnique` reads the workspace, where a description carries a live
184025
+ * node. Every metadata question reaches past it - `annotatedElement` is
184026
+ * declared in `Metaobjects.kerml` and the metaclass hierarchy in
184027
+ * `SysML.sysml` - and those documents are served from the precomputed index
184028
+ * with no parse behind them. The index holds one description PER SPELLING of
184029
+ * the same element (`PartUsage`, `SysML::PartUsage`, …), so the entries are
184030
+ * deduplicated by document and path first: a name is ambiguous only when it
184031
+ * reaches two different elements, and a single element is then read through
184032
+ * the linker's lazy single-file load.
184033
+ */
184034
+ resolveMetadataName(name, index2, from) {
184035
+ if (from) {
184036
+ const scoped = this.featurePaths.resolveVisibleNameCandidates(from, name);
184037
+ if (scoped.length === 1)
184038
+ return scoped[0];
184039
+ }
184040
+ const direct = this.resolveUnique(name, index2);
184041
+ if (direct)
184042
+ return direct;
184043
+ const normalized = name.trim();
184044
+ let descs = index2.get(normalized);
184045
+ if (!descs || descs.length === 0) {
184046
+ const simple = normalized.split(/::|\./u).pop();
184047
+ descs = simple ? index2.get(simple) : void 0;
184048
+ }
184049
+ if (!descs || descs.length === 0)
184050
+ return void 0;
184051
+ const unique = /* @__PURE__ */ new Map();
184052
+ for (const desc of descs)
184053
+ unique.set(`${String(desc.documentUri)}#${desc.path}`, desc);
184054
+ if (unique.size !== 1)
184055
+ return void 0;
184056
+ const only = [...unique.values()][0];
184057
+ return this.nodeOf(only) ?? this.linker?.resolveIndexedNode(only);
184058
+ }
184059
+ checkMetadataUsages(usages, index2, accept) {
184060
+ const resolve8 = (name, from) => this.resolveMetadataName(name, index2, from);
184061
+ const root4 = usages[0] ? ast_utils_exports.getDocument(usages[0]).parseResult.value : void 0;
184062
+ const model = new ConformanceModel((name) => this.resolveMetadataName(name, index2, root4), (node) => this.implicit?.closureOf(node) ?? { names: /* @__PURE__ */ new Set(), complete: true });
184063
+ const inventories = /* @__PURE__ */ new Map();
184064
+ const inventoryOf = (type) => {
184065
+ if (!type)
184066
+ return metadataFeaturesOf(void 0, resolve8);
184067
+ const cached = inventories.get(type);
184068
+ if (cached)
184069
+ return cached;
184070
+ const built = metadataFeaturesOf(type, resolve8, (node) => this.implicit?.closureOf(node).names ?? []);
184071
+ inventories.set(type, built);
184072
+ return built;
184073
+ };
184074
+ const restrictions = /* @__PURE__ */ new Map();
184075
+ const restrictionsOf = (type) => {
184076
+ const cached = restrictions.get(type);
184077
+ if (cached)
184078
+ return cached;
184079
+ const built = annotatedElementRestrictionsOf(type, resolve8);
184080
+ restrictions.set(type, built);
184081
+ return built;
184082
+ };
184083
+ for (const usage of usages) {
184084
+ if (this.checkMetadataTypeCount(usage, accept))
184085
+ continue;
184086
+ const type = metadataTypeNodeOf(usage, resolve8);
184087
+ if (type)
184088
+ this.checkMetadataTargets(usage, restrictionsOf(type), model, accept);
184089
+ if (isMetadataPrefixTag(usage))
184090
+ continue;
184091
+ this.checkMetadataBindings(usage, inventoryOf(type), model, resolve8, accept);
184092
+ }
184093
+ }
184094
+ // SSM049 - OMG SysML v2 Part 1 §7.27.1: a metadata usage applies ONE
184095
+ // metadata definition or metaclass. The grammar accepts a second type
184096
+ // because `MetadataTyping` shares its shape with the general typing rule,
184097
+ // and a body that binds a feature would then have two types to redefine
184098
+ // against. `SSM022` already judges the KIND of the type; this judges how
184099
+ // many there are.
184100
+ checkMetadataTypeCount(usage, accept) {
184101
+ const names = metadataTypeNamesOf(usage);
184102
+ if (names.length < 2)
184103
+ return false;
184104
+ accept(severity("SSM049", "error"), DIAGNOSTIC_MESSAGES.SSM049_METADATA_MULTIPLE_TYPES(names[0], names[1]), { node: usage, code: "SSM049" });
184105
+ return true;
184106
+ }
184107
+ // SSM050 / SSM051 / SSM052 / SSM053 / SSM054 - the body.
184108
+ //
184109
+ // Calling a written feature unknown, or a required one unbound, is a claim
184110
+ // about what the metadata type does NOT have, so both need its complete
184111
+ // feature inventory: a supertype this workspace could not read makes the
184112
+ // claim unsound. A duplicate binding and a value fault are claims about what
184113
+ // the body itself says, so they stand on the body alone.
184114
+ checkMetadataBindings(usage, inventory, model, resolve8, accept) {
184115
+ const bindings = metadataBindingsOf(usage);
184116
+ const typeName = metadataTypeNamesOf(usage)[0] ?? "this metadata definition";
184117
+ const bound = /* @__PURE__ */ new Map();
184118
+ for (const binding of bindings) {
184119
+ const first2 = bound.get(binding.name);
184120
+ if (!first2) {
184121
+ bound.set(binding.name, binding);
184122
+ continue;
184123
+ }
184124
+ if (first2.form !== "redefinition" && binding.form !== "redefinition")
184125
+ continue;
184126
+ accept(severity("SSM051", "error"), DIAGNOSTIC_MESSAGES.SSM051_METADATA_BINDING_DUPLICATE(binding.name, typeName), { node: binding.node, code: "SSM051" });
184127
+ }
184128
+ const features = new Map(inventory.features.map((feature) => [feature.name, feature]));
184129
+ for (const binding of bindings) {
184130
+ const feature = features.get(binding.name);
184131
+ if (!feature) {
184132
+ if (!inventory.complete || inventory.inherited.has(binding.name))
184133
+ continue;
184134
+ accept(severity("SSM052", "error"), DIAGNOSTIC_MESSAGES.SSM052_METADATA_FEATURE_UNKNOWN(binding.name, typeName, knownFeatureList(inventory.features)), { node: binding.node, code: "SSM052" });
184135
+ continue;
184136
+ }
184137
+ if (!binding.value)
184138
+ continue;
184139
+ if (valueEvaluability(binding.value, resolve8) === "instance-level") {
184140
+ accept(severity("SSM053", "warning"), DIAGNOSTIC_MESSAGES.SSM053_METADATA_VALUE_NOT_MODEL_LEVEL(binding.name, binding.value.$cstNode?.text.trim() ?? binding.name), { node: binding.value, code: "SSM053" });
184141
+ continue;
184142
+ }
184143
+ this.checkMetadataValueType(binding, feature.typeName, model, accept);
184144
+ }
184145
+ if (!inventory.complete)
184146
+ return;
184147
+ const missing = inventory.features.filter((feature) => feature.required && !bound.has(feature.name)).map((feature) => feature.name);
184148
+ if (missing.length === 0)
184149
+ return;
184150
+ accept(severity("SSM050", "warning"), DIAGNOSTIC_MESSAGES.SSM050_METADATA_BINDING_MISSING(typeName, quotedList(missing)), { node: usage, code: "SSM050" });
184151
+ }
184152
+ // SSM054 - the shape of a bound value against the feature it binds. This is
184153
+ // the SSM019 question asked where SSM019 cannot reach: a body member written
184154
+ // as `level = "high";` declares no type of its own, so the type it has to
184155
+ // match is the one the metadata definition gives the feature it redefines. A
184156
+ // member that DOES write its own type is left to SSM019, which already reads
184157
+ // it, rather than reported twice.
184158
+ checkMetadataValueType(binding, featureTypeName, model, accept) {
184159
+ if (!featureTypeName || !binding.value)
184160
+ return;
184161
+ if (soleDeclaredType(binding.node))
184162
+ return;
184163
+ const expected = model.literalKindAccepted(featureTypeName);
184164
+ if (!expected)
184165
+ return;
184166
+ const actual = expressionKindOf(binding.value);
184167
+ if (!actual || actual === expected)
184168
+ return;
184169
+ accept(severity("SSM054", "error"), DIAGNOSTIC_MESSAGES.SSM054_METADATA_VALUE_TYPE(binding.name, actual, featureTypeName), { node: binding.value, code: "SSM054" });
184170
+ }
184171
+ // SSM055 - applicability. `metadata def Classified { ref :>> annotatedElement
184172
+ // : SysML::Usage; }` narrows the `annotatedElement` every `Metaobject`
184173
+ // carries, and both an explicit `about` target and the element an untargeted
184174
+ // usage sits on bind it. The comparison is between the target's METACLASS -
184175
+ // `part x` is a `PartUsage` - and the restriction, walked through the
184176
+ // reflective metaclass model the library ships.
184177
+ checkMetadataTargets(usage, restrictions, model, accept) {
184178
+ if (restrictions.length === 0)
184179
+ return;
184180
+ if (restrictions.some((restriction) => !restriction.resolvedType))
184181
+ return;
184182
+ const typeName = metadataTypeNamesOf(usage)[0] ?? "this metadata definition";
184183
+ const allowed = [...new Set(restrictions.map((restriction) => simpleTypeName(restriction.typeName)))];
184184
+ const targets = metadataTargetsOf(usage, (_text, occurrence) => {
184185
+ const candidates = this.featurePaths.resolvePropertyPathCandidates(usage, "targets", occurrence);
184186
+ return candidates.length === 1 ? candidates[0] : void 0;
184187
+ });
184188
+ for (const target of targets) {
184189
+ if (!target.node)
184190
+ continue;
184191
+ const metaclass = metaclassNameOf(target.node);
184192
+ const verdicts = restrictions.map((restriction) => model.conforms(metaclass, restriction.typeName));
184193
+ if (verdicts.some((verdict) => verdict !== "unrelated"))
184194
+ continue;
184195
+ accept(severity("SSM055", "error"), DIAGNOSTIC_MESSAGES.SSM055_METADATA_TARGET_NOT_APPLICABLE(target.text, metaclass, typeName, quotedList(allowed)), { node: usage, code: "SSM055" });
184196
+ }
183643
184197
  }
183644
184198
  // ══════════════════════════════════════════════════════════════════════
183645
184199
  // REQ-417 — SSM045-SSM048: the bindings a case makes (issue #166)
@@ -185220,7 +185774,7 @@ function specializationTargets4(node) {
185220
185774
  ...node.relationships ?? []
185221
185775
  ];
185222
185776
  for (const rel2 of rels) {
185223
- if (rel2.kind && SPECIALIZATION_KINDS7.has(rel2.kind))
185777
+ if (rel2.kind && SPECIALIZATION_KINDS8.has(rel2.kind))
185224
185778
  out.push(...rel2.targets);
185225
185779
  }
185226
185780
  return out;
@@ -186005,12 +186559,12 @@ function importSignature(imp) {
186005
186559
  const segments = imp.segs.map((seg) => `${seg.name ?? ""}${seg.star ? "*" : ""}${seg.recursive ? "**" : ""}`);
186006
186560
  return `${importVisibility(imp)} ${imp.head}::${segments.join("::")}${imp.alias ? ` as ${imp.alias}` : ""}`;
186007
186561
  }
186008
- var SPECIALIZATION_KINDS8 = /* @__PURE__ */ new Set([":>", ":>>", "specializes", "subsets", "redefines"]);
186562
+ var SPECIALIZATION_KINDS9 = /* @__PURE__ */ new Set([":>", ":>>", "specializes", "subsets", "redefines"]);
186009
186563
  function specializationTargets5(node) {
186010
186564
  const n2 = node;
186011
186565
  const out = [];
186012
186566
  for (const rel2 of [...n2.preRelationships ?? [], ...n2.relationships ?? []]) {
186013
- if (rel2.kind && SPECIALIZATION_KINDS8.has(rel2.kind))
186567
+ if (rel2.kind && SPECIALIZATION_KINDS9.has(rel2.kind))
186014
186568
  out.push(...rel2.targets ?? []);
186015
186569
  }
186016
186570
  return out;
@@ -186300,12 +186854,12 @@ function directImportEntries(imp, descriptions) {
186300
186854
  }
186301
186855
  return applyFilters(imp, selectMemberships(path10, form, descriptions), options);
186302
186856
  }
186303
- var SPECIALIZATION_KINDS9 = /* @__PURE__ */ new Set([":>", ":>>", "specializes", "subsets", "redefines"]);
186857
+ var SPECIALIZATION_KINDS10 = /* @__PURE__ */ new Set([":>", ":>>", "specializes", "subsets", "redefines"]);
186304
186858
  function specializationTargets6(node) {
186305
186859
  const value = node;
186306
186860
  const targets = [];
186307
186861
  for (const relationship of [...value.preRelationships ?? [], ...value.relationships ?? []]) {
186308
- if (relationship.kind && SPECIALIZATION_KINDS9.has(relationship.kind)) {
186862
+ if (relationship.kind && SPECIALIZATION_KINDS10.has(relationship.kind)) {
186309
186863
  targets.push(...relationship.targets ?? []);
186310
186864
  }
186311
186865
  }
@@ -188339,7 +188893,7 @@ function typeAnchor(node, refText) {
188339
188893
  }
188340
188894
  return void 0;
188341
188895
  }
188342
- var REDEFINITION_KINDS5 = /* @__PURE__ */ new Set([":>>", "redefines"]);
188896
+ var REDEFINITION_KINDS6 = /* @__PURE__ */ new Set([":>>", "redefines"]);
188343
188897
  var CONSTANT_CARRYING_KINDS = /* @__PURE__ */ new Set([
188344
188898
  ":>",
188345
188899
  "subsets",
@@ -188728,7 +189282,7 @@ var SysmlInlayHintProvider = class {
188728
189282
  const parameter = mine[index2].node;
188729
189283
  if (!parameter.name || !parameter.$cstNode)
188730
189284
  continue;
188731
- if (allRelationships3(parameter).some((rel2) => rel2.kind && REDEFINITION_KINDS5.has(rel2.kind)))
189285
+ if (allRelationships3(parameter).some((rel2) => rel2.kind && REDEFINITION_KINDS6.has(rel2.kind)))
188732
189286
  continue;
188733
189287
  const target = theirs[index2].node;
188734
189288
  if (!target.name || target.name === parameter.name)
@@ -188971,7 +189525,7 @@ var SysmlInlayHintProvider = class {
188971
189525
  function effectiveNameHint(node, resolver) {
188972
189526
  if (node.name || node.shortName?.name || !node.$cstNode)
188973
189527
  return void 0;
188974
- const redefinition = allRelationships3(node).find((rel2) => rel2.kind && REDEFINITION_KINDS5.has(rel2.kind) && (rel2.targets?.length ?? 0) > 0);
189528
+ const redefinition = allRelationships3(node).find((rel2) => rel2.kind && REDEFINITION_KINDS6.has(rel2.kind) && (rel2.targets?.length ?? 0) > 0);
188975
189529
  if (!redefinition?.targets?.[0])
188976
189530
  return void 0;
188977
189531
  const names = effectiveNamesOf(node, resolver);
@@ -212996,7 +213550,7 @@ async function runExport(command) {
212996
213550
  }
212997
213551
 
212998
213552
  // src/main.ts
212999
- var VERSION2 = true ? "0.41.0" : "dev";
213553
+ var VERSION2 = true ? "0.42.0" : "dev";
213000
213554
  function display(file) {
213001
213555
  const rel2 = path9.relative(process.cwd(), file);
213002
213556
  return rel2 && !rel2.startsWith("..") ? rel2.split(path9.sep).join("/") : file;