sysml-diagram 0.31.2 → 0.33.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
@@ -164097,7 +164097,7 @@ function boundValue(bound) {
164097
164097
  function declaredMultiplicity(node) {
164098
164098
  const feature = node;
164099
164099
  const body = feature.members?.find((member) => member.$type === "MultiplicityDecl");
164100
- const written = feature.multiplicity ?? body?.multiplicity;
164100
+ const written = feature.multiplicity ?? body?.multiplicity ?? feature.innerMultiplicity ?? feature.endMultiplicity;
164101
164101
  if (!written) {
164102
164102
  for (const relationship of relationshipsOf(node)) {
164103
164103
  const tail = relationship.targets?.at(-1);
@@ -164945,6 +164945,7 @@ function expressionKindOf(node) {
164945
164945
  }
164946
164946
  var ConformanceModel = class {
164947
164947
  resolve;
164948
+ implicitBases;
164948
164949
  closures = /* @__PURE__ */ new Map();
164949
164950
  /**
164950
164951
  * @param resolve A written type name → its declaration, or `undefined` when
@@ -164952,9 +164953,24 @@ var ConformanceModel = class {
164952
164953
  * validator supplies its `resolveUnique`, so an ambiguous name is treated
164953
164954
  * exactly as an unreadable one: it makes the walk incomplete rather than
164954
164955
  * resolving to an arbitrary same-named element.
164956
+ * @param implicitBases REQ-411 — issue #161: the standard-library names a
164957
+ * declaration's KEYWORD contributes, which the source never writes. A
164958
+ * `part def Vehicle;` is a `Parts::Part`, and without this the closure said
164959
+ * it was unrelated to one.
164960
+ *
164961
+ * The contribution is the WHOLE chain above the base, not the base alone,
164962
+ * and it reports whether that chain could be read. Both halves matter:
164963
+ * `Parts::Part :> Items::Item` in the vendored library is what makes a
164964
+ * `part def` a legitimate narrowing of an `Items::Item` feature, and a
164965
+ * contribution that named only `Part` while still calling the closure
164966
+ * COMPLETE would let SSM017 reject that narrowing on a picture it knew was
164967
+ * partial. An unreadable chain therefore makes the closure incomplete, and
164968
+ * every caller stays silent on `unknown` — the same rule the rest of this
164969
+ * file follows, applied to the edge the source does not write.
164955
164970
  */
164956
- constructor(resolve8) {
164971
+ constructor(resolve8, implicitBases) {
164957
164972
  this.resolve = resolve8;
164973
+ this.implicitBases = implicitBases;
164958
164974
  }
164959
164975
  /** The transitive supertype names of the type written as `name`. */
164960
164976
  closureOf(name) {
@@ -164987,6 +165003,12 @@ var ConformanceModel = class {
164987
165003
  for (const supertype of [...declaredTypesOf(node).map((t) => t.text), ...specializedNamesOf(node)]) {
164988
165004
  absorb(this.walk(supertype, visiting));
164989
165005
  }
165006
+ const implicit = this.implicitBases?.(node);
165007
+ if (implicit) {
165008
+ for (const base of implicit.names)
165009
+ names.add(simpleTypeName(base));
165010
+ complete &&= implicit.complete;
165011
+ }
164990
165012
  for (const group of compositionGroupsOf(node)) {
164991
165013
  if (group.kind === "intersects") {
164992
165014
  for (const operand of group.targets)
@@ -165353,6 +165375,264 @@ function eventReferenceOf(node) {
165353
165375
  return { kind: "self", node };
165354
165376
  }
165355
165377
 
165378
+ // ../language-server/out/src/services/individuals.js
165379
+ var INDIVIDUAL_MULTIPLICITY = "[1]";
165380
+ var MAX_TYPE_DEPTH = 32;
165381
+ function modifiersOf(node) {
165382
+ const decl = node;
165383
+ const own = Array.isArray(decl.modifiers) ? decl.modifiers : [];
165384
+ const post = Array.isArray(decl.postModifiers) ? decl.postModifiers : [];
165385
+ const wrapper = prefixMetadataModifiersOf(node);
165386
+ if (post.length === 0 && wrapper.length === 0)
165387
+ return own;
165388
+ return [...own, ...post, ...wrapper];
165389
+ }
165390
+ function prefixMetadataModifiersOf(node) {
165391
+ const container = node.$container;
165392
+ if (!container || container.$type !== "PrefixMetadataMember")
165393
+ return [];
165394
+ if (container.element !== node)
165395
+ return [];
165396
+ return Array.isArray(container.modifiers) ? container.modifiers : [];
165397
+ }
165398
+ function isIndividualDecl(node) {
165399
+ return modifiersOf(node).includes("individual");
165400
+ }
165401
+ function portionKindOf(node) {
165402
+ return modifiersOf(node).find((m) => m === "timeslice" || m === "snapshot");
165403
+ }
165404
+ function isDefinitionDecl(node) {
165405
+ return node.isDef === true || node.$type === "BareDefDecl";
165406
+ }
165407
+ var NON_OCCURRENCE_DECL_TYPES = /* @__PURE__ */ new Set([
165408
+ "AttributeDecl",
165409
+ "EnumDecl",
165410
+ "EnumValueDecl",
165411
+ "MetadataDecl",
165412
+ "MultiplicityDecl",
165413
+ // A KerML `datatype` IS the data-valued root an attribute is typed by
165414
+ // (KerML 8.3.4 DataType, which Occurrence deliberately does not specialize),
165415
+ // so it has no life either. Its siblings stay OUT: a KerML `class` is by
165416
+ // definition a classifier whose instances are occurrences, and `struct`,
165417
+ // `assoc struct`, `behavior`, `function` and `predicate` all specialize it.
165418
+ "DatatypeDecl"
165419
+ ]);
165420
+ var NAMESPACE_DECL_TYPES = /* @__PURE__ */ new Set([
165421
+ // Every name here is a real `$type` from the generated AST. `PackageDecl` and
165422
+ // `ImportDecl` were both invented: the rules are `Package` and `Import`, so
165423
+ // those two entries matched nothing and claimed a coverage they did not have.
165424
+ "Package",
165425
+ "NamespaceDecl",
165426
+ "Document",
165427
+ "AliasDecl",
165428
+ "Import"
165429
+ ]);
165430
+ var NON_OCCURRENCE_LABELS = {
165431
+ AttributeDecl: "an attribute",
165432
+ EnumDecl: "an enumeration",
165433
+ EnumValueDecl: "an enumeration value",
165434
+ MetadataDecl: "a metadata usage",
165435
+ MultiplicityDecl: "a multiplicity",
165436
+ DatatypeDecl: "a datatype",
165437
+ Package: "a package",
165438
+ NamespaceDecl: "a namespace",
165439
+ AliasDecl: "an alias",
165440
+ Import: "an import"
165441
+ };
165442
+ function nonOccurrenceLabel(node) {
165443
+ return NON_OCCURRENCE_LABELS[node.$type] ?? "not an occurrence";
165444
+ }
165445
+ function isOccurrenceShapedDecl(node) {
165446
+ return !NON_OCCURRENCE_DECL_TYPES.has(node.$type) && !NAMESPACE_DECL_TYPES.has(node.$type);
165447
+ }
165448
+ function writtenTypesOf(node) {
165449
+ const decl = node;
165450
+ const out = [];
165451
+ for (const typing of [decl.typing, ...decl.moreTypings ?? []]) {
165452
+ if (!typing)
165453
+ continue;
165454
+ const conjugated = typing.conjugate === true;
165455
+ for (const ref of [typing.type, ...typing.moreTypes ?? []]) {
165456
+ const text = ref?.$refText?.trim();
165457
+ if (text)
165458
+ out.push({ text, ref: ref?.ref, conjugated });
165459
+ }
165460
+ }
165461
+ return out;
165462
+ }
165463
+ function candidatesOf(node) {
165464
+ const out = [];
165465
+ for (const written of writtenTypesOf(node)) {
165466
+ if (written.conjugated)
165467
+ continue;
165468
+ out.push({ text: written.text, ref: written.ref });
165469
+ }
165470
+ for (const target of specializationTargetsOf(node))
165471
+ out.push({ text: target });
165472
+ return out;
165473
+ }
165474
+ var TRANSPARENT_WRAPPER_TYPES = /* @__PURE__ */ new Set([
165475
+ "PrefixMetadataMember",
165476
+ "MemberPrefixDecl",
165477
+ "ThenActionMember"
165478
+ ]);
165479
+ var OWNER_WALK_STOPS = /* @__PURE__ */ new Set([
165480
+ "Package",
165481
+ "PackageDecl",
165482
+ "NamespaceDecl",
165483
+ "Document"
165484
+ ]);
165485
+ function owningOccurrenceOf(node) {
165486
+ let owner = node.$container;
165487
+ while (owner && TRANSPARENT_WRAPPER_TYPES.has(owner.$type))
165488
+ owner = owner.$container;
165489
+ if (!owner || OWNER_WALK_STOPS.has(owner.$type))
165490
+ return void 0;
165491
+ return NON_OCCURRENCE_DECL_TYPES.has(owner.$type) ? void 0 : owner;
165492
+ }
165493
+ var MAX_ALIAS_HOPS = 8;
165494
+ var SPECIALIZATION_KINDS3 = /* @__PURE__ */ new Set([
165495
+ ":>",
165496
+ "subsets",
165497
+ ":>>",
165498
+ "redefines",
165499
+ "specializes",
165500
+ "subtype"
165501
+ ]);
165502
+ function specializationTargetsOf(node) {
165503
+ const decl = node;
165504
+ const out = [];
165505
+ for (const rel2 of [...decl.preRelationships ?? [], ...decl.relationships ?? []]) {
165506
+ if (!rel2.kind || !SPECIALIZATION_KINDS3.has(rel2.kind))
165507
+ continue;
165508
+ for (const target of rel2.targets ?? []) {
165509
+ const text = target.trim();
165510
+ if (text)
165511
+ out.push(text);
165512
+ }
165513
+ }
165514
+ return out;
165515
+ }
165516
+ function linkedIndividualDefinitionsOf(node) {
165517
+ return individualClosureOf(node, documentLocalResolverFor(node)).definitions;
165518
+ }
165519
+ function documentLocalResolverFor(node) {
165520
+ const resolve8 = localResolverFor(node);
165521
+ return (name) => {
165522
+ const candidates = resolve8(name, node).filter((candidate) => candidate.node);
165523
+ return candidates.length === 1 ? candidates[0].node : void 0;
165524
+ };
165525
+ }
165526
+ function individualClosureOf(node, resolve8) {
165527
+ const definitions = [];
165528
+ const seenNodes = /* @__PURE__ */ new Set([node]);
165529
+ let complete = true;
165530
+ const record = (text, target) => {
165531
+ if (!isIndividualDecl(target) || !isDefinitionDecl(target))
165532
+ return;
165533
+ if (definitions.some((each) => each.node === target))
165534
+ return;
165535
+ definitions.push({ text, node: target });
165536
+ };
165537
+ const targetOf = (candidate) => dealias(candidate.ref ?? resolve8(candidate.text));
165538
+ const dealias = (target) => {
165539
+ let current2 = target;
165540
+ for (let hop = 0; current2?.$type === "AliasDecl" && hop < MAX_ALIAS_HOPS; hop++) {
165541
+ const to = current2.target;
165542
+ current2 = to ? resolve8(to) : void 0;
165543
+ }
165544
+ return current2?.$type === "AliasDecl" ? void 0 : current2;
165545
+ };
165546
+ const walk = (current2, depth) => {
165547
+ if (depth > MAX_TYPE_DEPTH) {
165548
+ complete = false;
165549
+ return;
165550
+ }
165551
+ const ordinaryDefinition = isDefinitionDecl(current2) && !isIndividualDecl(current2);
165552
+ for (const candidate of candidatesOf(current2)) {
165553
+ const target = targetOf(candidate);
165554
+ if (!target) {
165555
+ if (!ordinaryDefinition)
165556
+ complete = false;
165557
+ continue;
165558
+ }
165559
+ record(candidate.text, target);
165560
+ if (seenNodes.has(target))
165561
+ continue;
165562
+ seenNodes.add(target);
165563
+ walk(target, depth + 1);
165564
+ }
165565
+ };
165566
+ walk(node, 0);
165567
+ if (portionKindOf(node)) {
165568
+ const owner = owningOccurrenceOf(node);
165569
+ if (owner) {
165570
+ const inherited = individualClosureOf(owner, resolve8);
165571
+ for (const each of inherited.definitions)
165572
+ record(each.text, each.node);
165573
+ if (!inherited.complete)
165574
+ complete = false;
165575
+ }
165576
+ }
165577
+ const direct = [];
165578
+ for (const written of writtenTypesOf(node)) {
165579
+ if (written.conjugated)
165580
+ continue;
165581
+ const target = targetOf(written);
165582
+ if (!target || !isIndividualDecl(target) || !isDefinitionDecl(target))
165583
+ continue;
165584
+ if (direct.some((each) => each.node === target))
165585
+ continue;
165586
+ direct.push({ text: written.text, node: target });
165587
+ }
165588
+ return { definitions, direct, complete };
165589
+ }
165590
+ function identityOf(node) {
165591
+ if (!isIndividualDecl(node) && !portionKindOf(node))
165592
+ return void 0;
165593
+ return effectiveIndividualOf(node, linkedIndividualDefinitionsOf(node));
165594
+ }
165595
+ function effectiveIndividualOf(node, definitions = []) {
165596
+ const explicit = isIndividualDecl(node);
165597
+ const portion = portionKindOf(node);
165598
+ if (!explicit && !portion)
165599
+ return void 0;
165600
+ return {
165601
+ explicit,
165602
+ portion,
165603
+ definition: definitions[0]?.text,
165604
+ multiplicity: writtenMultiplicityTextOf(node) ?? INDIVIDUAL_MULTIPLICITY
165605
+ };
165606
+ }
165607
+ function boundTextOf(bound) {
165608
+ if (!bound)
165609
+ return void 0;
165610
+ if (bound.star)
165611
+ return "*";
165612
+ if (typeof bound.intVal === "number")
165613
+ return String(bound.intVal);
165614
+ return bound.bound;
165615
+ }
165616
+ function writtenMultiplicityTextOf(node) {
165617
+ const decl = node;
165618
+ const mult = decl.multiplicity ?? decl.innerMultiplicity ?? decl.endMultiplicity;
165619
+ if (!mult)
165620
+ return void 0;
165621
+ const lo = boundTextOf(mult.lower);
165622
+ const hi = boundTextOf(mult.upper);
165623
+ if (lo === void 0 && hi === void 0)
165624
+ return void 0;
165625
+ return hi === void 0 || hi === lo ? `[${lo}]` : `[${lo}..${hi}]`;
165626
+ }
165627
+ function individualModifierCarrier(node) {
165628
+ const own = node;
165629
+ if ((own.modifiers ?? []).includes("individual"))
165630
+ return node;
165631
+ if ((own.postModifiers ?? []).includes("individual"))
165632
+ return node;
165633
+ return prefixMetadataModifiersOf(node).includes("individual") ? node.$container : void 0;
165634
+ }
165635
+
165356
165636
  // ../language-server/out/src/services/diagram-model-provider.js
165357
165637
  var lastSeg = (name) => {
165358
165638
  const i = Math.max(name.lastIndexOf("::"), name.lastIndexOf("."));
@@ -165740,12 +166020,12 @@ var withoutCompartments = (compartments, ...titles) => {
165740
166020
  const kept = (compartments ?? []).filter((compartment) => !titles.includes(compartment.title));
165741
166021
  return kept.length ? kept : void 0;
165742
166022
  };
165743
- var modifiersOf = (node) => {
166023
+ var modifiersOf2 = (node) => {
165744
166024
  const mods = node.modifiers;
165745
166025
  return Array.isArray(mods) ? mods : [];
165746
166026
  };
165747
166027
  var ANONYMOUS_INTERFACE_NAME = "(anonymous)";
165748
- var isEndMember = (node) => node.$type === "EndDecl" || modifiersOf(node).includes("end");
166028
+ var isEndMember = (node) => node.$type === "EndDecl" || modifiersOf2(node).includes("end");
165749
166029
  function endRowText(node) {
165750
166030
  const end = node;
165751
166031
  const name = nameOf2(node) ?? end.innerName;
@@ -165756,9 +166036,28 @@ function endRowText(node) {
165756
166036
  return void 0;
165757
166037
  return `${head2}${mult ? ` ${mult}` : ""}`;
165758
166038
  }
165759
- var portionKindOf = (node) => modifiersOf(node).find((m) => m === "timeslice" || m === "snapshot");
165760
- var isIndividualOccurrence = (node) => modifiersOf(node).includes("individual");
166039
+ var isIndividualOccurrence = isIndividualDecl;
165761
166040
  var isOccurrenceModified = (node) => portionKindOf(node) !== void 0 || isIndividualOccurrence(node);
166041
+ var mergedIndividualMeta = (node, existing) => {
166042
+ const identity6 = individualMetaOf(node);
166043
+ if (!identity6)
166044
+ return {};
166045
+ return { meta: { ...identity6, ...existing ?? {} } };
166046
+ };
166047
+ var individualMetaOf = (node) => {
166048
+ const effective = identityOf(node);
166049
+ if (!effective)
166050
+ return void 0;
166051
+ const isDef = isDefinitionDecl(node);
166052
+ return {
166053
+ individual: {
166054
+ explicit: effective.explicit,
166055
+ ...isDef ? {} : { multiplicity: effective.multiplicity },
166056
+ ...!isDef && effective.definition ? { definition: effective.definition } : {},
166057
+ ...effective.portion ? { portion: effective.portion } : {}
166058
+ }
166059
+ };
166060
+ };
165762
166061
  var redefinedNameOf = (node) => {
165763
166062
  const names = effectiveNamesOf(node, localResolverFor(node));
165764
166063
  return names.origin === "derived" || names.origin === "written" ? names.name ?? names.shortName : void 0;
@@ -167089,7 +167388,7 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
167089
167388
  isInheritedLibraryBackboneFeature(source, usage, index2) {
167090
167389
  if (!isLibraryDocument(ast_utils_exports.getDocument(usage)))
167091
167390
  return false;
167092
- if (modifiersOf(usage).includes("abstract"))
167391
+ if (modifiersOf2(usage).includes("abstract"))
167093
167392
  return true;
167094
167393
  const ownerType = source.isDef === true ? source : this.resolveType(source, index2);
167095
167394
  const usageType = this.resolveType(usage, index2);
@@ -167258,7 +167557,10 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
167258
167557
  compartments: extra?.compartments ?? this.compartmentsFor(n2, uri, index2, shape === "box"),
167259
167558
  ...packageOf2(n2),
167260
167559
  source: sourceOf2(n2, uri),
167261
- ...extra
167560
+ ...extra,
167561
+ // issue #162 — identity meta merges UNDER whatever the caller
167562
+ // passes, so a caller's own `meta` never loses a key to it.
167563
+ ...mergedIndividualMeta(n2, extra?.meta)
167262
167564
  });
167263
167565
  };
167264
167566
  for (const n2 of defNodes)
@@ -167797,7 +168099,7 @@ ${edge.to}`));
167797
168099
  gvTypeInherited: usage && !typeText(original) && !!definition || void 0,
167798
168100
  // REQ-405 - Tree alias suppression follows an explicit ref.
167799
168101
  // Intrinsic references such as package parts remain visible.
167800
- gvTreeExcluded: modifiersOf(original).includes("ref") && (!valueTextOf(original) || isPathExpr(original.value) || !!referenceTarget && belongsToDrawnFeatureTree(referenceTarget)) || void 0,
168102
+ gvTreeExcluded: modifiersOf2(original).includes("ref") && (!valueTextOf(original) || isPathExpr(original.value) || !!referenceTarget && belongsToDrawnFeatureTree(referenceTarget)) || void 0,
167801
168103
  ...directionOf(original) ? { direction: directionOf(original) } : {}
167802
168104
  };
167803
168105
  if (!ownerId || !byId.has(ownerId) || ownerId === node.id)
@@ -174359,7 +174661,6 @@ var sysmlInlayHintSettings = {
174359
174661
  dimension: false,
174360
174662
  visibility: false,
174361
174663
  modifiers: false,
174362
- specialization: false,
174363
174664
  redefinition: false,
174364
174665
  effectiveNames: false,
174365
174666
  importedNames: false,
@@ -174567,7 +174868,7 @@ function outlineGroupForType(astType) {
174567
174868
  }
174568
174869
 
174569
174870
  // ../language-server/out/src/services/document-symbol-provider.js
174570
- var SPECIALIZATION_KINDS3 = /* @__PURE__ */ new Set([":>", "specializes"]);
174871
+ var SPECIALIZATION_KINDS4 = /* @__PURE__ */ new Set([":>", "specializes"]);
174571
174872
  var REDEFINITION_KINDS2 = /* @__PURE__ */ new Set([":>>", "redefines"]);
174572
174873
  var INHERITABLE_FEATURE_TYPES = /* @__PURE__ */ new Set([
174573
174874
  "ActionDecl",
@@ -174639,7 +174940,7 @@ function specializationTargets2(node) {
174639
174940
  const n2 = node;
174640
174941
  const out = [];
174641
174942
  for (const rel2 of [...n2.preRelationships ?? [], ...n2.relationships ?? []]) {
174642
- if (rel2.kind && SPECIALIZATION_KINDS3.has(rel2.kind))
174943
+ if (rel2.kind && SPECIALIZATION_KINDS4.has(rel2.kind))
174643
174944
  out.push(...rel2.targets ?? []);
174644
174945
  }
174645
174946
  return out;
@@ -175025,6 +175326,547 @@ function resolveEffectiveSubject(node) {
175025
175326
  return void 0;
175026
175327
  }
175027
175328
 
175329
+ // ../language-server/out/src/services/implicit-specialization.js
175330
+ var EXPLICIT_SPECIALIZATION_KINDS = /* @__PURE__ */ new Set([
175331
+ ":>",
175332
+ ":>>",
175333
+ "::>",
175334
+ "=>",
175335
+ "specializes",
175336
+ "subsets",
175337
+ "redefines",
175338
+ "references",
175339
+ "crosses",
175340
+ "conjugates"
175341
+ ]);
175342
+ var IMPLICIT_BASES = Object.freeze({
175343
+ PartDecl: { def: "Parts::Part", usage: "Parts::parts" },
175344
+ ItemDecl: { def: "Items::Item", usage: "Items::items" },
175345
+ PortDecl: { def: "Ports::Port", usage: "Ports::ports" },
175346
+ ActionDecl: { def: "Actions::Action", usage: "Actions::actions" },
175347
+ StateDecl: { def: "States::StateAction", usage: "States::stateActions" },
175348
+ ConnectionDecl: { def: "Connections::Connection", usage: "Connections::connections" },
175349
+ InterfaceDecl: { def: "Interfaces::Interface", usage: "Interfaces::interfaces" },
175350
+ CaseDecl: { def: "Cases::Case", usage: "Cases::cases" },
175351
+ UseCaseDecl: { def: "UseCases::UseCase", usage: "UseCases::useCases" },
175352
+ AnalysisCaseDecl: { def: "AnalysisCases::AnalysisCase", usage: "AnalysisCases::analysisCases" },
175353
+ VerificationCaseDecl: { def: "VerificationCases::VerificationCase", usage: "VerificationCases::verificationCases" },
175354
+ ViewDecl: { def: "Views::View", usage: "Views::views" },
175355
+ ViewpointDecl: { def: "Views::ViewpointCheck", usage: "Views::viewpointChecks" },
175356
+ RenderingDecl: { def: "Views::Rendering", usage: "Views::renderings" },
175357
+ RequirementDecl: { def: "Requirements::RequirementCheck", usage: "Requirements::requirementChecks" },
175358
+ ConcernDecl: { def: "Requirements::ConcernCheck", usage: "Requirements::concernChecks" },
175359
+ ConstraintDecl: { def: "Constraints::ConstraintCheck", usage: "Constraints::constraintChecks" },
175360
+ CalcDecl: { def: "Calculations::Calculation", usage: "Calculations::calculations" },
175361
+ AllocationDecl: { def: "Allocations::Allocation", usage: "Allocations::allocations" },
175362
+ AttributeDecl: { def: "Attributes::AttributeValue", usage: "Attributes::attributeValues" },
175363
+ OccurrenceDecl: { def: "Occurrences::Occurrence", usage: "Occurrences::occurrences" },
175364
+ MetadataDecl: { def: "Metadata::MetadataItem", usage: "Metadata::metadataItems" }
175365
+ });
175366
+ var KERML_CLASSIFIER_BASES = Object.freeze({
175367
+ ClassDecl: "Occurrences::Occurrence",
175368
+ StructDecl: "Objects::Object",
175369
+ MetaclassDecl: "Metaobjects::Metaobject",
175370
+ BehaviorDecl: "Performances::Performance",
175371
+ DatatypeDecl: "Base::DataValue"
175372
+ });
175373
+ var KERML_FEATURE_BASES = Object.freeze({
175374
+ StepDecl: "Performances::performances"
175375
+ });
175376
+ var ASSOCIATION_BASES = Object.freeze({ link: "Links::Link", linkObject: "Objects::LinkObject" });
175377
+ var LIBRARY_BASE_CHAINS = Object.freeze({
175378
+ "Actions::Action": ["Performance", "Occurrence", "Anything"],
175379
+ "Actions::actions": ["Action", "Performance", "Occurrence", "Anything", "performances", "occurrences", "things"],
175380
+ "Allocations::Allocation": [
175381
+ "BinaryConnection",
175382
+ "BinaryLinkObject",
175383
+ "BinaryLink",
175384
+ "Link",
175385
+ "Anything",
175386
+ "LinkObject",
175387
+ "Object",
175388
+ "Occurrence",
175389
+ "Connection",
175390
+ "Part",
175391
+ "Item"
175392
+ ],
175393
+ "Allocations::allocations": [
175394
+ "Allocation",
175395
+ "BinaryConnection",
175396
+ "BinaryLinkObject",
175397
+ "BinaryLink",
175398
+ "Link",
175399
+ "Anything",
175400
+ "LinkObject",
175401
+ "Object",
175402
+ "Occurrence",
175403
+ "Connection",
175404
+ "Part",
175405
+ "Item",
175406
+ "binaryConnections",
175407
+ "connections",
175408
+ "linkObjects",
175409
+ "links",
175410
+ "things",
175411
+ "objects",
175412
+ "occurrences",
175413
+ "parts",
175414
+ "items",
175415
+ "binaryLinkObjects",
175416
+ "binaryLinks"
175417
+ ],
175418
+ "AnalysisCases::AnalysisCase": [
175419
+ "Case",
175420
+ "Calculation",
175421
+ "Action",
175422
+ "Performance",
175423
+ "Occurrence",
175424
+ "Anything",
175425
+ "Evaluation"
175426
+ ],
175427
+ "AnalysisCases::analysisCases": [
175428
+ "AnalysisCase",
175429
+ "Case",
175430
+ "Calculation",
175431
+ "Action",
175432
+ "Performance",
175433
+ "Occurrence",
175434
+ "Anything",
175435
+ "Evaluation",
175436
+ "cases",
175437
+ "calculations",
175438
+ "actions",
175439
+ "performances",
175440
+ "occurrences",
175441
+ "things",
175442
+ "evaluations"
175443
+ ],
175444
+ "Attributes::AttributeValue": ["DataValue", "Anything"],
175445
+ "Attributes::attributeValues": ["dataValues", "DataValue", "Anything", "things"],
175446
+ "Base::DataValue": ["Anything"],
175447
+ "Calculations::Calculation": ["Action", "Performance", "Occurrence", "Anything", "Evaluation"],
175448
+ "Calculations::calculations": [
175449
+ "Calculation",
175450
+ "Action",
175451
+ "Performance",
175452
+ "Occurrence",
175453
+ "Anything",
175454
+ "Evaluation",
175455
+ "actions",
175456
+ "performances",
175457
+ "occurrences",
175458
+ "things",
175459
+ "evaluations"
175460
+ ],
175461
+ "Cases::Case": ["Calculation", "Action", "Performance", "Occurrence", "Anything", "Evaluation"],
175462
+ "Cases::cases": [
175463
+ "Case",
175464
+ "Calculation",
175465
+ "Action",
175466
+ "Performance",
175467
+ "Occurrence",
175468
+ "Anything",
175469
+ "Evaluation",
175470
+ "calculations",
175471
+ "actions",
175472
+ "performances",
175473
+ "occurrences",
175474
+ "things",
175475
+ "evaluations"
175476
+ ],
175477
+ "Connections::Connection": ["LinkObject", "Link", "Anything", "Object", "Occurrence", "Part", "Item"],
175478
+ "Connections::connections": [
175479
+ "Connection",
175480
+ "LinkObject",
175481
+ "Link",
175482
+ "Anything",
175483
+ "Object",
175484
+ "Occurrence",
175485
+ "Part",
175486
+ "Item",
175487
+ "linkObjects",
175488
+ "links",
175489
+ "things",
175490
+ "objects",
175491
+ "occurrences",
175492
+ "parts",
175493
+ "items"
175494
+ ],
175495
+ "Constraints::ConstraintCheck": ["BooleanEvaluation", "Evaluation", "Performance", "Occurrence", "Anything"],
175496
+ "Constraints::constraintChecks": [
175497
+ "ConstraintCheck",
175498
+ "BooleanEvaluation",
175499
+ "Evaluation",
175500
+ "Performance",
175501
+ "Occurrence",
175502
+ "Anything",
175503
+ "booleanEvaluations",
175504
+ "evaluations",
175505
+ "performances",
175506
+ "occurrences",
175507
+ "things"
175508
+ ],
175509
+ "Interfaces::Interface": ["Connection", "LinkObject", "Link", "Anything", "Object", "Occurrence", "Part", "Item"],
175510
+ "Interfaces::interfaces": [
175511
+ "Interface",
175512
+ "Connection",
175513
+ "LinkObject",
175514
+ "Link",
175515
+ "Anything",
175516
+ "Object",
175517
+ "Occurrence",
175518
+ "Part",
175519
+ "Item",
175520
+ "connections",
175521
+ "linkObjects",
175522
+ "links",
175523
+ "things",
175524
+ "objects",
175525
+ "occurrences",
175526
+ "parts",
175527
+ "items"
175528
+ ],
175529
+ "Items::Item": ["Object", "Occurrence", "Anything"],
175530
+ "Items::items": ["Item", "Object", "Occurrence", "Anything", "objects", "occurrences", "things"],
175531
+ "Links::Link": ["Anything"],
175532
+ "Metadata::MetadataItem": ["Metaobject", "Object", "Occurrence", "Anything", "Item"],
175533
+ "Metadata::metadataItems": [
175534
+ "MetadataItem",
175535
+ "Metaobject",
175536
+ "Object",
175537
+ "Occurrence",
175538
+ "Anything",
175539
+ "Item",
175540
+ "metaobjects",
175541
+ "objects",
175542
+ "occurrences",
175543
+ "things",
175544
+ "items"
175545
+ ],
175546
+ "Metaobjects::Metaobject": ["Object", "Occurrence", "Anything"],
175547
+ "Objects::LinkObject": ["Link", "Anything", "Object", "Occurrence"],
175548
+ "Objects::Object": ["Occurrence", "Anything"],
175549
+ "Occurrences::Occurrence": ["Anything"],
175550
+ "Occurrences::occurrences": ["Occurrence", "Anything", "things"],
175551
+ "Parts::Part": ["Item", "Object", "Occurrence", "Anything"],
175552
+ "Parts::parts": ["Part", "Item", "Object", "Occurrence", "Anything", "items", "objects", "occurrences", "things"],
175553
+ "Performances::Performance": ["Occurrence", "Anything"],
175554
+ "Performances::performances": ["Performance", "Occurrence", "Anything", "occurrences", "things"],
175555
+ "Ports::Port": ["Object", "Occurrence", "Anything"],
175556
+ "Ports::ports": ["Port", "Object", "Occurrence", "Anything", "objects", "occurrences", "things"],
175557
+ "Requirements::ConcernCheck": [
175558
+ "RequirementCheck",
175559
+ "RequirementConstraintCheck",
175560
+ "ConstraintCheck",
175561
+ "BooleanEvaluation",
175562
+ "Evaluation",
175563
+ "Performance",
175564
+ "Occurrence",
175565
+ "Anything"
175566
+ ],
175567
+ "Requirements::RequirementCheck": [
175568
+ "RequirementConstraintCheck",
175569
+ "ConstraintCheck",
175570
+ "BooleanEvaluation",
175571
+ "Evaluation",
175572
+ "Performance",
175573
+ "Occurrence",
175574
+ "Anything"
175575
+ ],
175576
+ "Requirements::concernChecks": [
175577
+ "ConcernCheck",
175578
+ "RequirementCheck",
175579
+ "RequirementConstraintCheck",
175580
+ "ConstraintCheck",
175581
+ "BooleanEvaluation",
175582
+ "Evaluation",
175583
+ "Performance",
175584
+ "Occurrence",
175585
+ "Anything",
175586
+ "requirementChecks",
175587
+ "constraintChecks",
175588
+ "booleanEvaluations",
175589
+ "evaluations",
175590
+ "performances",
175591
+ "occurrences",
175592
+ "things"
175593
+ ],
175594
+ "Requirements::requirementChecks": [
175595
+ "RequirementCheck",
175596
+ "RequirementConstraintCheck",
175597
+ "ConstraintCheck",
175598
+ "BooleanEvaluation",
175599
+ "Evaluation",
175600
+ "Performance",
175601
+ "Occurrence",
175602
+ "Anything",
175603
+ "constraintChecks",
175604
+ "booleanEvaluations",
175605
+ "evaluations",
175606
+ "performances",
175607
+ "occurrences",
175608
+ "things"
175609
+ ],
175610
+ "States::StateAction": [
175611
+ "Action",
175612
+ "Performance",
175613
+ "Occurrence",
175614
+ "Anything",
175615
+ "StatePerformance",
175616
+ "DecisionPerformance"
175617
+ ],
175618
+ "States::stateActions": [
175619
+ "StateAction",
175620
+ "Action",
175621
+ "Performance",
175622
+ "Occurrence",
175623
+ "Anything",
175624
+ "StatePerformance",
175625
+ "DecisionPerformance",
175626
+ "actions",
175627
+ "performances",
175628
+ "occurrences",
175629
+ "things"
175630
+ ],
175631
+ "UseCases::UseCase": ["Case", "Calculation", "Action", "Performance", "Occurrence", "Anything", "Evaluation"],
175632
+ "UseCases::useCases": [
175633
+ "UseCase",
175634
+ "Case",
175635
+ "Calculation",
175636
+ "Action",
175637
+ "Performance",
175638
+ "Occurrence",
175639
+ "Anything",
175640
+ "Evaluation",
175641
+ "cases",
175642
+ "calculations",
175643
+ "actions",
175644
+ "performances",
175645
+ "occurrences",
175646
+ "things",
175647
+ "evaluations"
175648
+ ],
175649
+ "VerificationCases::VerificationCase": [
175650
+ "Case",
175651
+ "Calculation",
175652
+ "Action",
175653
+ "Performance",
175654
+ "Occurrence",
175655
+ "Anything",
175656
+ "Evaluation"
175657
+ ],
175658
+ "VerificationCases::verificationCases": [
175659
+ "VerificationCase",
175660
+ "Case",
175661
+ "Calculation",
175662
+ "Action",
175663
+ "Performance",
175664
+ "Occurrence",
175665
+ "Anything",
175666
+ "Evaluation",
175667
+ "cases",
175668
+ "calculations",
175669
+ "actions",
175670
+ "performances",
175671
+ "occurrences",
175672
+ "things",
175673
+ "evaluations"
175674
+ ],
175675
+ "Views::Rendering": ["Part", "Item", "Object", "Occurrence", "Anything"],
175676
+ "Views::View": ["Part", "Item", "Object", "Occurrence", "Anything"],
175677
+ "Views::ViewpointCheck": [
175678
+ "RequirementCheck",
175679
+ "RequirementConstraintCheck",
175680
+ "ConstraintCheck",
175681
+ "BooleanEvaluation",
175682
+ "Evaluation",
175683
+ "Performance",
175684
+ "Occurrence",
175685
+ "Anything"
175686
+ ],
175687
+ "Views::renderings": [
175688
+ "Rendering",
175689
+ "Part",
175690
+ "Item",
175691
+ "Object",
175692
+ "Occurrence",
175693
+ "Anything",
175694
+ "parts",
175695
+ "items",
175696
+ "objects",
175697
+ "occurrences",
175698
+ "things"
175699
+ ],
175700
+ "Views::viewpointChecks": [
175701
+ "ViewpointCheck",
175702
+ "RequirementCheck",
175703
+ "RequirementConstraintCheck",
175704
+ "ConstraintCheck",
175705
+ "BooleanEvaluation",
175706
+ "Evaluation",
175707
+ "Performance",
175708
+ "Occurrence",
175709
+ "Anything",
175710
+ "requirementChecks",
175711
+ "constraintChecks",
175712
+ "booleanEvaluations",
175713
+ "evaluations",
175714
+ "performances",
175715
+ "occurrences",
175716
+ "things"
175717
+ ],
175718
+ "Views::views": [
175719
+ "View",
175720
+ "Part",
175721
+ "Item",
175722
+ "Object",
175723
+ "Occurrence",
175724
+ "Anything",
175725
+ "parts",
175726
+ "items",
175727
+ "objects",
175728
+ "occurrences",
175729
+ "things"
175730
+ ]
175731
+ });
175732
+ function allRelationships(node) {
175733
+ return [...node.preRelationships ?? [], ...node.relationships ?? []];
175734
+ }
175735
+ function statesExplicitSpecialization(node) {
175736
+ const decl = node;
175737
+ if (decl.typing?.type?.$refText)
175738
+ return true;
175739
+ return allRelationships(decl).some((rel2) => (
175740
+ // The SYMBOLIC conjugation has no keyword: `port def In ~ Out;` parses as
175741
+ // a relationship with `conjugate: true` and NO `kind` at all (the
175742
+ // grammar's `conjugate?='~' targets+=RelationPath` alternative). Reading
175743
+ // `kind` alone therefore missed it and offered `Ports::Port` beside a
175744
+ // relationship that already says what the declaration is.
175745
+ rel2.conjugate === true || rel2.kind !== void 0 && EXPLICIT_SPECIALIZATION_KINDS.has(rel2.kind)
175746
+ ));
175747
+ }
175748
+ function implicitBaseOf(node) {
175749
+ const decl = node;
175750
+ const found = qualifiedBaseOf(decl);
175751
+ if (!found)
175752
+ return void 0;
175753
+ const [qualified, isUsage2] = found;
175754
+ return {
175755
+ qualified,
175756
+ simple: simpleTypeName(qualified),
175757
+ isUsage: isUsage2,
175758
+ metaclass: isUsage2 ? "Subsetting" : "Specialization"
175759
+ };
175760
+ }
175761
+ function qualifiedBaseOf(decl) {
175762
+ const classifier = decl.$type === "AssociationDecl" ? decl.isStruct === true ? ASSOCIATION_BASES.linkObject : ASSOCIATION_BASES.link : KERML_CLASSIFIER_BASES[decl.$type];
175763
+ if (classifier)
175764
+ return [classifier, false];
175765
+ const feature = KERML_FEATURE_BASES[decl.$type];
175766
+ if (feature)
175767
+ return [feature, true];
175768
+ const entry = IMPLICIT_BASES[decl.$type];
175769
+ if (!entry)
175770
+ return void 0;
175771
+ const isUsage2 = decl.isDef !== true;
175772
+ return [isUsage2 ? entry.usage : entry.def, isUsage2];
175773
+ }
175774
+ function impliedBaseOf(node) {
175775
+ if (statesExplicitSpecialization(node))
175776
+ return void 0;
175777
+ return implicitBaseOf(node);
175778
+ }
175779
+ var ImplicitSpecializationModel = class {
175780
+ lookup;
175781
+ /** Resolved bases, keyed by qualified name. A MISS is never cached: the
175782
+ * library index may still be loading, and a cached miss would outlive it. */
175783
+ bases = /* @__PURE__ */ new Map();
175784
+ constructor(lookup) {
175785
+ this.lookup = lookup;
175786
+ }
175787
+ /** Drop everything a rebuilt index could change. The chain table is a
175788
+ * constant and survives; only a resolved description can go stale. */
175789
+ invalidate() {
175790
+ this.bases.clear();
175791
+ }
175792
+ /** The implied base of one declaration, or `undefined` when there is none. */
175793
+ baseOf(node) {
175794
+ return impliedBaseOf(node);
175795
+ }
175796
+ /**
175797
+ * The index description of a base, so a consumer can link to it.
175798
+ *
175799
+ * The full qualified spelling must resolve inside the standard library.
175800
+ * A workspace namesake or an unrelated library element with the same simple
175801
+ * name cannot supply this relationship.
175802
+ */
175803
+ descriptionOf(base) {
175804
+ const cached = this.bases.get(base.qualified);
175805
+ if (cached)
175806
+ return cached;
175807
+ if (!this.lookup)
175808
+ return void 0;
175809
+ const exact = this.lookup.descriptions(base.qualified).find((description) => {
175810
+ const uri = description.documentUri instanceof URI2 ? description.documentUri : URI2.parse(String(description.documentUri));
175811
+ return isStandardLibraryUri(uri);
175812
+ });
175813
+ if (exact)
175814
+ this.bases.set(base.qualified, exact);
175815
+ return exact;
175816
+ }
175817
+ /**
175818
+ * The implied base of `node` and every library name above it.
175819
+ *
175820
+ * Answered from {@link LIBRARY_BASE_CHAINS}, so it needs no index, no parse
175821
+ * and no network of loaded documents: the desktop host, the web worker and
175822
+ * the headless CLIs all give the same answer, and a workspace with no
175823
+ * library loaded still gets the real hierarchy rather than a shrug. A
175824
+ * declaration with no implicit base has an empty closure, which is complete
175825
+ * in the only sense that matters: there is nothing missing from it.
175826
+ *
175827
+ * A base the table does not cover is reported INCOMPLETE rather than as a
175828
+ * bare name, because a caller may conclude nothing from a name's absence
175829
+ * when the hierarchy above it was never known.
175830
+ */
175831
+ closureOf(node) {
175832
+ const base = this.baseOf(node);
175833
+ if (!base)
175834
+ return { names: /* @__PURE__ */ new Set(), complete: true };
175835
+ const chain = LIBRARY_BASE_CHAINS[base.qualified];
175836
+ return {
175837
+ names: /* @__PURE__ */ new Set([base.simple, ...(chain ?? []).map(simpleTypeName)]),
175838
+ complete: chain !== void 0
175839
+ };
175840
+ }
175841
+ /**
175842
+ * The chain the library puts above one base, for a caller that wants to
175843
+ * check the table against the library it was read from.
175844
+ */
175845
+ static libraryChainOf(qualified) {
175846
+ return LIBRARY_BASE_CHAINS[qualified];
175847
+ }
175848
+ /** Every base the chain table covers, for the same reason. */
175849
+ static coveredBases() {
175850
+ return Object.keys(LIBRARY_BASE_CHAINS);
175851
+ }
175852
+ };
175853
+ var models = /* @__PURE__ */ new WeakMap();
175854
+ function implicitSpecializationsFor(shared) {
175855
+ if (!shared)
175856
+ return void 0;
175857
+ const existing = models.get(shared);
175858
+ if (existing)
175859
+ return existing;
175860
+ const created = new ImplicitSpecializationModel(nameLookupFor(shared));
175861
+ models.set(shared, created);
175862
+ shared.workspace.DocumentBuilder.onBuildPhase(
175863
+ // Indexing is the only phase that can change what a base resolves to.
175864
+ DocumentState.IndexedContent,
175865
+ () => created.invalidate()
175866
+ );
175867
+ return created;
175868
+ }
175869
+
175028
175870
  // ../language-server/out/src/messages.js
175029
175871
  var DIAGNOSTIC_MESSAGES = {
175030
175872
  // REQ-006 - a broad diagram anchor cannot prove which typed occurrence owns
@@ -175175,6 +176017,13 @@ var DIAGNOSTIC_MESSAGES = {
175175
176017
  SSM025_ACTION_PARAMETER_DIRECTION: (position, mine, typeName, theirs) => `Parameter ${position} is '${mine}' but the corresponding parameter of '${typeName}' is '${theirs}'. Positional correspondence redefines that parameter, and a redefinition cannot reverse a parameter's direction.`,
175176
176018
  SSM026_REDEFINITION_DIRECTION: (feature, mine, theirs) => `Direction '${mine}' reverses the redefined feature '${feature}', which is '${theirs}'. A redefinition refines a feature \u2014 it cannot turn an input into an output.`,
175177
176019
  SSM027_INTERFACE_END_TYPE: (position, endType, definition, expected) => `End ${position} is a '${endType}', but '${definition}' declares that end as '${expected}'. An interface usage connects through the ends its definition declares.`,
176020
+ // issue #162 — individual identity (OMG SysML v2 Part 1 §7.9.4 Individuals).
176021
+ // Each message names the life the model claims and the thing that cannot have
176022
+ // one, because the fix is always to move the keyword or to name the definition
176023
+ // that carries the identity.
176024
+ SSM040_INDIVIDUAL_NOT_OCCURRENCE: (name, kind) => `'individual' names one occurrence with an identity of its own, and ${name} is ${kind}, which has no life to identify. Remove 'individual', or move it to the occurrence this belongs to.`,
176025
+ SSM041_INDIVIDUAL_MULTIPLE_DEFINITIONS: (name, first2, second) => `${name} is typed by two individual definitions, '${first2}' and '${second}'. An individual usage names ONE life, so at most one of its types may be an 'individual def'.`,
176026
+ SSM042_INDIVIDUAL_WITHOUT_DEFINITION: (name) => `${name} is declared 'individual' but names no individual definition. An individual usage is typed by exactly one 'individual def' - the definition that carries the identity it names.`,
175178
176027
  // REQ-392 — a `sysml-format` comment the formatter cannot act on. Advisory:
175179
176028
  // the directive is inert, and saying so beats leaving the author to wonder
175180
176029
  // why their layout was reformatted anyway.
@@ -175379,6 +176228,12 @@ var OPERATOR_TOOLTIPS = {
175379
176228
  "@": { desc: "**Metadata application** shorthand - applies a metadata definition to the next element.", precedence: 0, example: "@Safety\npart def Engine;", cite: "OMG SysML v2.0 Part 1 \xA78.2.2.27 (Metadata)" },
175380
176229
  "@@": { desc: "**Metaclass application** - applies a metaclass annotation.", precedence: 0, example: "@@StandardProfile", cite: "OMG SysML v2.0 Part 1 \xA78.2.2.27 (Metadata)" }
175381
176230
  };
176231
+ var IMPLICIT_SPECIALIZATION_MESSAGES = {
176232
+ makeExplicit: (base) => `Make implicit specialization explicit (':> ${base}')`,
176233
+ specializes: "implicitly specializes",
176234
+ subsets: "implicitly subsets",
176235
+ source: " Source: the standard library, through the declaration keyword (OMG SysML v2 Part 1 section 7.6.8)."
176236
+ };
175382
176237
 
175383
176238
  // ../language-server/out/src/services/hover-provider.js
175384
176239
  var MAX_HOVER_LINES = 30;
@@ -175473,7 +176328,7 @@ function directionLabel(node) {
175473
176328
  const dir = modifiers2.find((m) => m === "in" || m === "out" || m === "inout");
175474
176329
  return dir ? `${dir} ` : "";
175475
176330
  }
175476
- function allRelationships(node) {
176331
+ function allRelationships2(node) {
175477
176332
  return [...node.preRelationships ?? [], ...node.relationships ?? []];
175478
176333
  }
175479
176334
  function relationshipTargets(rel2) {
@@ -175537,7 +176392,7 @@ function declarationLine(node, resolver, enumResolver) {
175537
176392
  const name = externalVariantName(node) ?? identificationLabel(named2) ?? effectiveIdentificationLabel(named2) ?? "(anonymous)";
175538
176393
  let typing = typingLabel(named2.typing);
175539
176394
  const mult = multiplicityLabel(node, resolver);
175540
- let rels = relationshipLabel(allRelationships(named2));
176395
+ let rels = relationshipLabel(allRelationships2(named2));
175541
176396
  const implicitVariant = implicitVariantSpecialization(node);
175542
176397
  if (!typing && !implicitVariant && enumResolver && isEnumerationUsage(node)) {
175543
176398
  const types = effectiveEnumerationTypes(node, enumResolver);
@@ -175607,7 +176462,7 @@ function memberSummary(node, resolver) {
175607
176462
  const kind = kindLabel(node);
175608
176463
  const typing = typingLabel(named2.typing);
175609
176464
  const mult = multiplicityLabel(node, resolver);
175610
- const rels = relationshipLabel(allRelationships(named2));
176465
+ const rels = relationshipLabel(allRelationships2(named2));
175611
176466
  return `${dir}${kind} ${name}${typing}${mult}${rels}`;
175612
176467
  }
175613
176468
  function memberList(node, resolver) {
@@ -175780,7 +176635,7 @@ function supertypeCandidates(node) {
175780
176635
  if (more.$refText)
175781
176636
  out.push({ refText: more.$refText, ref: more.ref });
175782
176637
  }
175783
- for (const rel2 of allRelationships(named2)) {
176638
+ for (const rel2 of allRelationships2(named2)) {
175784
176639
  if (!rel2.kind || !DOC_SPECIALIZATION_KINDS.has(rel2.kind))
175785
176640
  continue;
175786
176641
  for (const target of rel2.targets ?? [])
@@ -175822,6 +176677,9 @@ ${headerLines.join("\n")}
175822
176677
  if (composition.isFeature) {
175823
176678
  parts.push(`*Ownership:* ${composition.isComposite ? "Composite feature" : "Referential feature"}`);
175824
176679
  }
176680
+ const individual = individualSection(node);
176681
+ if (individual)
176682
+ parts.push(individual);
175825
176683
  const subject = subjectInheritanceSection(node);
175826
176684
  if (subject)
175827
176685
  parts.push(subject);
@@ -175836,6 +176694,23 @@ ${headerLines.join("\n")}
175836
176694
  parts.push(sourceFooter(nodeSource(node)));
175837
176695
  return parts.join("\n\n");
175838
176696
  }
176697
+ function writesOwnMultiplicity(node) {
176698
+ const n2 = node;
176699
+ return n2.multiplicity !== void 0 || n2.innerMultiplicity !== void 0 || n2.endMultiplicity !== void 0;
176700
+ }
176701
+ function individualSection(node) {
176702
+ const effective = identityOf(node);
176703
+ if (!effective)
176704
+ return void 0;
176705
+ if (isDefinitionDecl(node)) {
176706
+ return effective.explicit ? "*Individual:* one life. Every usage of this definition is a portion of the same occurrence." : void 0;
176707
+ }
176708
+ if (!effective.explicit && !effective.definition)
176709
+ return void 0;
176710
+ const identity6 = effective.definition ? `the life of \`${effective.definition}\`` : "one life";
176711
+ const what = effective.portion ? `A \`${effective.portion}\` of ${identity6}` : `Identifies ${identity6}`;
176712
+ return writesOwnMultiplicity(node) ? `*Individual:* ${what}.` : `*Individual:* ${what}, so it has multiplicity \`${effective.multiplicity}\`.`;
176713
+ }
175839
176714
  function subjectInheritanceSection(node) {
175840
176715
  const effective = resolveEffectiveSubject(node);
175841
176716
  if (!effective || !effective.inherited)
@@ -176162,12 +177037,15 @@ var SysmlHoverProvider = class {
176162
177037
  enumerations;
176163
177038
  /** REQ-394 — the linker's lazy standard-library load, reused rather than duplicated. */
176164
177039
  linker;
177040
+ /** REQ-411 — issue #161: the shared implicit-specialization model. */
177041
+ implicit;
176165
177042
  constructor(services) {
176166
177043
  this.references = services.references.References;
176167
177044
  this.astNodeLocator = services.workspace.AstNodeLocator;
176168
177045
  this.documents = services.shared.workspace.LangiumDocuments;
176169
177046
  this.indexManager = services.shared.workspace.IndexManager;
176170
177047
  this.linker = services.references.Linker;
177048
+ this.implicit = implicitSpecializationsFor(services.shared);
176171
177049
  const paths = new FeaturePathResolver(services);
176172
177050
  this.featureProperties = featurePropertyResolver(paths);
176173
177051
  this.enumerations = enumerationResolver(paths);
@@ -176311,8 +177189,10 @@ var SysmlHoverProvider = class {
176311
177189
  // target kind, and target declaration line instead of only echoing `:>`/`:>>`.
176312
177190
  async relationshipDetailSection(node) {
176313
177191
  const named2 = node;
176314
- const rels = allRelationships(named2);
176315
- if (rels.length === 0)
177192
+ const rels = allRelationships2(named2);
177193
+ const implied = this.implicit?.baseOf(node);
177194
+ const impliedBase = implied && this.implicit?.descriptionOf(implied) ? implied : void 0;
177195
+ if (rels.length === 0 && !impliedBase)
176316
177196
  return void 0;
176317
177197
  const sourceKind = kindLabel(node);
176318
177198
  const sourceName = identificationLabel(named2) ?? "(anonymous)";
@@ -176334,6 +177214,10 @@ var SysmlHoverProvider = class {
176334
177214
  }
176335
177215
  }
176336
177216
  }
177217
+ if (impliedBase) {
177218
+ const phrase = impliedBase.isUsage ? IMPLICIT_SPECIALIZATION_MESSAGES.subsets : IMPLICIT_SPECIALIZATION_MESSAGES.specializes;
177219
+ lines.push(`- ${sourceKind} \`${sourceName}\` ${phrase} \`${impliedBase.qualified}\``, IMPLICIT_SPECIALIZATION_MESSAGES.source);
177220
+ }
176337
177221
  return lines.length > 0 ? `*Relationships:*
176338
177222
  ${lines.join("\n")}` : void 0;
176339
177223
  }
@@ -177718,7 +178602,7 @@ var import_vscode_languageserver16 = __toESM(require_main4(), 1);
177718
178602
 
177719
178603
  // ../language-server/out/src/services/metadata-filter.js
177720
178604
  var INCONCLUSIVE2 = { kind: "inconclusive" };
177721
- var SPECIALIZATION_KINDS4 = /* @__PURE__ */ new Set([":>", "specializes", ":>>", "redefines", "subsets"]);
178605
+ var SPECIALIZATION_KINDS5 = /* @__PURE__ */ new Set([":>", "specializes", ":>>", "redefines", "subsets"]);
177722
178606
  var MAX_SPECIALIZATION_DEPTH = 32;
177723
178607
  var MAX_VALUE_DEPTH = 16;
177724
178608
  function evaluateFilterCondition(condition, element, options) {
@@ -177821,7 +178705,7 @@ function declaresFeature2(node, name) {
177821
178705
  if (node.name === name)
177822
178706
  return true;
177823
178707
  for (const rel2 of [...node.preRelationships ?? [], ...node.relationships ?? []]) {
177824
- if (rel2.kind && SPECIALIZATION_KINDS4.has(rel2.kind) && (rel2.targets ?? []).includes(name))
178708
+ if (rel2.kind && SPECIALIZATION_KINDS5.has(rel2.kind) && (rel2.targets ?? []).includes(name))
177825
178709
  return true;
177826
178710
  }
177827
178711
  return false;
@@ -177988,7 +178872,7 @@ function nameScope(ctx, depth = 0) {
177988
178872
  function specializationTargets3(node) {
177989
178873
  const targets = [];
177990
178874
  for (const rel2 of [...node.preRelationships ?? [], ...node.relationships ?? []]) {
177991
- if (rel2.kind && SPECIALIZATION_KINDS4.has(rel2.kind))
178875
+ if (rel2.kind && SPECIALIZATION_KINDS5.has(rel2.kind))
177992
178876
  targets.push(...rel2.targets ?? []);
177993
178877
  }
177994
178878
  return targets;
@@ -178779,7 +179663,7 @@ function maskNonCode(text) {
178779
179663
  }
178780
179664
  return out.join("");
178781
179665
  }
178782
- var SPECIALIZATION_KINDS5 = /* @__PURE__ */ new Set([":>", ":>>", "specializes", "subsets", "redefines"]);
179666
+ var SPECIALIZATION_KINDS6 = /* @__PURE__ */ new Set([":>", ":>>", "specializes", "subsets", "redefines"]);
178783
179667
  var CONSTRAINT_SIDE_EFFECT_TYPES = /* @__PURE__ */ new Set([
178784
179668
  "AssignNode",
178785
179669
  "SendNode",
@@ -178844,12 +179728,6 @@ function actionOnlyConstruct(node) {
178844
179728
  const keyword = CONTROL_NODE_KEYWORDS[node.$type];
178845
179729
  return keyword ? { construct: `A '${keyword}' control node`, clause: "7.17.3" } : void 0;
178846
179730
  }
178847
- function portionKindOf2(node) {
178848
- const mods = node.modifiers;
178849
- if (!Array.isArray(mods))
178850
- return void 0;
178851
- return mods.find((m) => m === "timeslice" || m === "snapshot");
178852
- }
178853
179731
  var NAMESPACE_ONLY_TYPES = /* @__PURE__ */ new Set(["Package", "Document", "NamespaceDecl"]);
178854
179732
  function owningTypeOf(node) {
178855
179733
  let owner = node.$container;
@@ -178897,12 +179775,18 @@ var SysmlValidator = class _SysmlValidator {
178897
179775
  // captured here. The two share one grammar today; this keeps that from becoming
178898
179776
  // load-bearing.
178899
179777
  serviceRegistry;
179778
+ // REQ-411 — issue #161: the shared implicit-specialization model. The walk
179779
+ // above a base needs a PARSED library declaration, so it goes through the
179780
+ // linker's own lazy single-file load rather than pulling the library into
179781
+ // the workspace; the model memoizes each chain for the whole session.
179782
+ implicit;
178900
179783
  constructor(services) {
178901
179784
  this.serviceRegistry = services.shared.ServiceRegistry;
178902
179785
  this.indexManager = services.shared.workspace.IndexManager;
178903
179786
  this.langiumDocuments = services.shared.workspace.LangiumDocuments;
178904
179787
  this.astNodeLocator = services.workspace.AstNodeLocator;
178905
179788
  this.featurePaths = new FeaturePathResolver(services);
179789
+ this.implicit = implicitSpecializationsFor(services.shared);
178906
179790
  this.featureProperties = featurePropertyResolver(this.featurePaths);
178907
179791
  this.compositionTypes = compositionTypeResolver(this.featurePaths);
178908
179792
  this.enumerations = enumerationResolver(this.featurePaths);
@@ -179271,6 +180155,7 @@ var SysmlValidator = class _SysmlValidator {
179271
180155
  this.checkKermlWellFormedness(node, accept);
179272
180156
  this.checkFilterExpressions(node, accept);
179273
180157
  this.checkOccurrencePortions(node, accept);
180158
+ this.checkIndividualDeclarations(node, accept);
179274
180159
  this.checkCrossReferences(node, accept);
179275
180160
  this.checkAutoImportSuggestions(node, accept);
179276
180161
  this.checkUnits(node, accept);
@@ -180201,7 +181086,7 @@ ${baseIndent}}`;
180201
181086
  accept(severity("SYN019", "error"), DIAGNOSTIC_MESSAGES.SYN019_ABSTRACT_VARIATION, { node: child, code: "SYN019" });
180202
181087
  }
180203
181088
  for (const relation of [...decl.preRelationships ?? [], ...decl.relationships ?? []]) {
180204
- if (!relation.kind || !SPECIALIZATION_KINDS5.has(relation.kind))
181089
+ if (!relation.kind || !SPECIALIZATION_KINDS6.has(relation.kind))
180205
181090
  continue;
180206
181091
  for (let index2 = 0; index2 < (relation.targets?.length ?? 0); index2 += 1) {
180207
181092
  const resolution = this.featurePaths.resolvePropertyPath(relation, "targets", index2);
@@ -180628,7 +181513,7 @@ ${baseIndent}}`;
180628
181513
  // `unknown` and no diagnostic. That is what keeps the OMG corpus clean while
180629
181514
  // still catching the workspace-local mistakes these codes exist for.
180630
181515
  checkTypeConformance(decls, index2, accept) {
180631
- const model = new ConformanceModel((name) => this.resolveUnique(name, index2));
181516
+ const model = new ConformanceModel((name) => this.resolveUnique(name, index2), (node) => this.implicit?.closureOf(node) ?? { names: /* @__PURE__ */ new Set(), complete: true });
180632
181517
  for (const decl of decls) {
180633
181518
  this.checkRedefinitionTypeConformance(decl, model, index2, accept);
180634
181519
  this.checkValueAssignability(decl, model, accept);
@@ -180641,6 +181526,49 @@ ${baseIndent}}`;
180641
181526
  this.checkActionParameterCorrespondence(decl, model, accept);
180642
181527
  this.checkRedefinitionDirection(decl, index2, accept);
180643
181528
  this.checkInterfaceEndTypes(decl, model, index2, accept);
181529
+ this.checkIndividualDefinitions(decl, model, accept);
181530
+ }
181531
+ }
181532
+ // issue #162 — SSM041 / SSM042: the identity an individual usage names.
181533
+ //
181534
+ // OMG SysML v2 Part 1 §7.9.4 derives `OccurrenceUsage::individualDefinition`
181535
+ // as the usage's types that are individual occurrence definitions, and
181536
+ // constrains it twice: at most one for ANY occurrence usage, and exactly one
181537
+ // for a usage written `individual`. Both say the same thing — an individual
181538
+ // usage names ONE life — from the two sides.
181539
+ //
181540
+ // SSM041 — two individual definitions written on the same usage. Judged on the
181541
+ // DIRECTLY written types only, exactly as the metamodel derives them:
181542
+ // reaching a second identity through a supertype is how the canonical
181543
+ // models legitimately relate an individual to the family it belongs to.
181544
+ // SSM042 — an `individual` usage that reaches no individual definition at all.
181545
+ // Judged over the whole type-and-specialization walk, because a usage
181546
+ // inherits identity (`individual timeslice t :> ind;` takes its
181547
+ // definition from the `ind` it subsets), and only when that walk was
181548
+ // COMPLETE: an unread supertype may never be read as an absence.
181549
+ // issue #162 — the node whose own text contains the `individual` keyword. It is
181550
+ // the declaration itself, unless an enclosing `#Tag` wrapper carries the prefix.
181551
+ // REQ-412 — SSM041/SSM042: the identity an individual usage names
181552
+ checkIndividualDefinitions(decl, model, accept) {
181553
+ if (decl.isDef === true || decl.$type === "BareDefDecl")
181554
+ return;
181555
+ if (!isOccurrenceShapedDecl(decl))
181556
+ return;
181557
+ const explicit = isIndividualDecl(decl);
181558
+ if (!explicit && writtenTypesOf(decl).filter((each) => !each.conjugated).length < 2)
181559
+ return;
181560
+ const closure2 = individualClosureOf(decl, (name) => model.declarationOf(name));
181561
+ const label = decl.name ? `'${decl.name}'` : `This '${kindLabel2(decl)}'`;
181562
+ if (closure2.direct.length > 1) {
181563
+ accept(severity("SSM041", "error"), DIAGNOSTIC_MESSAGES.SSM041_INDIVIDUAL_MULTIPLE_DEFINITIONS(label, closure2.direct[0].text, closure2.direct[1].text), {
181564
+ node: decl,
181565
+ code: "SSM041",
181566
+ relatedInformation: declarationSite(closure2.direct[1].node, closure2.direct[1].text)
181567
+ });
181568
+ return;
181569
+ }
181570
+ if (explicit && closure2.definitions.length === 0 && closure2.complete) {
181571
+ accept(severity("SSM042", "error"), DIAGNOSTIC_MESSAGES.SSM042_INDIVIDUAL_WITHOUT_DEFINITION(label), { node: decl, code: "SSM042" });
180644
181572
  }
180645
181573
  }
180646
181574
  // REQ-390 — SSM017: a redefining feature narrows the feature it redefines, so
@@ -180970,8 +181898,9 @@ ${baseIndent}}`;
180970
181898
  // SysML usage kind IS an OccurrenceUsage (part, item, action, state, port,
180971
181899
  // connection, case, …) while the data-valued ones are few and closed: an
180972
181900
  // AttributeUsage is typed by a DataType and an enumeration is a special attribute,
180973
- // neither of which has a life to carve up.
180974
- static NON_OCCURRENCE_OWNER_TYPES = /* @__PURE__ */ new Set(["AttributeDecl", "EnumDecl", "EnumValueDecl", "MetadataDecl", "MultiplicityDecl"]);
181901
+ // neither of which has a life to carve up. issue #162 — SSM040 judges an
181902
+ // `individual` against the same list, so the two share one spelling of it.
181903
+ static NON_OCCURRENCE_OWNER_TYPES = NON_OCCURRENCE_DECL_TYPES;
180975
181904
  // REQ-160 — OMG SysML v2 §8.2.2.9 (Occurrences) with the Kernel Semantic Library
180976
181905
  // `Occurrences::TimeSlice` / `Occurrences::Snapshot`:
180977
181906
  //
@@ -180987,7 +181916,7 @@ ${baseIndent}}`;
180987
181916
  // without resolving a single cross-reference.
180988
181917
  checkOccurrencePortions(node, accept) {
180989
181918
  for (const child of ast_utils_exports.streamAllContents(node)) {
180990
- const kind = portionKindOf2(child);
181919
+ const kind = portionKindOf(child);
180991
181920
  if (!kind)
180992
181921
  continue;
180993
181922
  const label = declLabel(child, kind);
@@ -181000,11 +181929,36 @@ ${baseIndent}}`;
181000
181929
  accept(severity("SSM015", "error"), `A '${kind}' is a portion of an occurrence's life, and '${owner.name ?? owner.$type}' is not an occurrence.`, { node: child, code: "SSM015" });
181001
181930
  continue;
181002
181931
  }
181003
- if (kind === "timeslice" && portionKindOf2(owner) === "snapshot") {
181932
+ if (kind === "timeslice" && portionKindOf(owner) === "snapshot") {
181004
181933
  accept(severity("SSM016", "error"), `A 'snapshot' is a zero-duration timeslice, so ${label} cannot be a timeslice of it - a portion of an instant is itself a snapshot.`, { node: child, code: "SSM016" });
181005
181934
  }
181006
181935
  }
181007
181936
  }
181937
+ // ══════════════════════════════════════════════════════════════════════
181938
+ // issue #162 — SSM040: `individual` presupposes an occurrence
181939
+ // ══════════════════════════════════════════════════════════════════════
181940
+ // OMG SysML v2 Part 1 §7.9.4 puts `isIndividual` on OccurrenceDefinition and
181941
+ // OccurrenceUsage, and nowhere else. An attribute is typed by a DataType and
181942
+ // has no life; a package is a namespace and is not a type at all. Writing
181943
+ // `individual` there claims an identity over time for something that has none.
181944
+ //
181945
+ // Structural: it reads the modifier and the declaration kind only, so it holds
181946
+ // with nothing resolved. The quick fix removes the keyword.
181947
+ // REQ-412 — SSM040: `individual` on a declaration that is not an occurrence
181948
+ checkIndividualDeclarations(node, accept) {
181949
+ for (const child of ast_utils_exports.streamAllContents(node)) {
181950
+ if (!isIndividualDecl(child) || isOccurrenceShapedDecl(child))
181951
+ continue;
181952
+ const name = child.name;
181953
+ const carrier = individualModifierCarrier(child);
181954
+ accept(severity("SSM040", "error"), DIAGNOSTIC_MESSAGES.SSM040_INDIVIDUAL_NOT_OCCURRENCE(name ? `'${name}'` : "this declaration", nonOccurrenceLabel(child)), {
181955
+ node: child,
181956
+ code: "SSM040",
181957
+ data: { individualModifier: true },
181958
+ ...carrier?.$cstNode ? { range: carrier.$cstNode.range } : {}
181959
+ });
181960
+ }
181961
+ }
181008
181962
  // REQ-328 — KSM008: a `filter` membership condition must be Boolean. Only a
181009
181963
  // *definitely* non-Boolean expression is flagged — a string or numeric/quantity
181010
181964
  // literal, or an arithmetic/range binary expression. A bare feature path is left
@@ -182038,7 +182992,7 @@ function specializationTargets4(node) {
182038
182992
  ...node.relationships ?? []
182039
182993
  ];
182040
182994
  for (const rel2 of rels) {
182041
- if (rel2.kind && SPECIALIZATION_KINDS5.has(rel2.kind))
182995
+ if (rel2.kind && SPECIALIZATION_KINDS6.has(rel2.kind))
182042
182996
  out.push(...rel2.targets);
182043
182997
  }
182044
182998
  return out;
@@ -182814,12 +183768,12 @@ function importSignature(imp) {
182814
183768
  const segments = imp.segs.map((seg) => `${seg.name ?? ""}${seg.star ? "*" : ""}${seg.recursive ? "**" : ""}`);
182815
183769
  return `${importVisibility(imp)} ${imp.head}::${segments.join("::")}${imp.alias ? ` as ${imp.alias}` : ""}`;
182816
183770
  }
182817
- var SPECIALIZATION_KINDS6 = /* @__PURE__ */ new Set([":>", ":>>", "specializes", "subsets", "redefines"]);
183771
+ var SPECIALIZATION_KINDS7 = /* @__PURE__ */ new Set([":>", ":>>", "specializes", "subsets", "redefines"]);
182818
183772
  function specializationTargets5(node) {
182819
183773
  const n2 = node;
182820
183774
  const out = [];
182821
183775
  for (const rel2 of [...n2.preRelationships ?? [], ...n2.relationships ?? []]) {
182822
- if (rel2.kind && SPECIALIZATION_KINDS6.has(rel2.kind))
183776
+ if (rel2.kind && SPECIALIZATION_KINDS7.has(rel2.kind))
182823
183777
  out.push(...rel2.targets ?? []);
182824
183778
  }
182825
183779
  return out;
@@ -183107,12 +184061,12 @@ function directImportEntries(imp, descriptions) {
183107
184061
  }
183108
184062
  return applyFilters(imp, selectMemberships(path10, form, descriptions), options);
183109
184063
  }
183110
- var SPECIALIZATION_KINDS7 = /* @__PURE__ */ new Set([":>", ":>>", "specializes", "subsets", "redefines"]);
184064
+ var SPECIALIZATION_KINDS8 = /* @__PURE__ */ new Set([":>", ":>>", "specializes", "subsets", "redefines"]);
183111
184065
  function specializationTargets6(node) {
183112
184066
  const value = node;
183113
184067
  const targets = [];
183114
184068
  for (const relationship of [...value.preRelationships ?? [], ...value.relationships ?? []]) {
183115
- if (relationship.kind && SPECIALIZATION_KINDS7.has(relationship.kind)) {
184069
+ if (relationship.kind && SPECIALIZATION_KINDS8.has(relationship.kind)) {
183116
184070
  targets.push(...relationship.targets ?? []);
183117
184071
  }
183118
184072
  }
@@ -183402,6 +184356,21 @@ function nearestDefAware(node) {
183402
184356
  }
183403
184357
  return void 0;
183404
184358
  }
184359
+ function nearestImplicitBaseOwner(node) {
184360
+ for (let cur = node; cur; cur = cur.$container) {
184361
+ if (implicitBaseOf(cur))
184362
+ return cur;
184363
+ }
184364
+ return void 0;
184365
+ }
184366
+ var DECLARATION_HEAD_ENDS = /* @__PURE__ */ new Set(["{", ";", "=", ":=", "default"]);
184367
+ function declarationTailPosition(node) {
184368
+ const leaves = cst_utils_exports.flattenCst(node).toArray().filter((leaf) => !leaf.hidden);
184369
+ const stop = leaves.findIndex((leaf) => DECLARATION_HEAD_ENDS.has(leaf.text));
184370
+ if (stop > 0)
184371
+ return leaves[stop - 1].range.end;
184372
+ return node.range.end;
184373
+ }
183405
184374
  function isSubjectBearing(node) {
183406
184375
  return !!node && (isRequirementDecl(node) || isCaseDecl(node) || isUseCaseDecl(node) || isVerificationCaseDecl(node) || isAnalysisCaseDecl(node) || isConcernDecl(node));
183407
184376
  }
@@ -183447,8 +184416,12 @@ function astNodeAtRange(document2, diagnostic) {
183447
184416
  }
183448
184417
  var SysmlCodeActionProvider = class {
183449
184418
  documents;
184419
+ /** REQ-411 — issue #161: the shared implicit-specialization model, so the
184420
+ * action offers only a base the loaded library actually holds. */
184421
+ implicit;
183450
184422
  constructor(services) {
183451
184423
  this.documents = services.shared.workspace.LangiumDocuments;
184424
+ this.implicit = implicitSpecializationsFor(services.shared);
183452
184425
  }
183453
184426
  getCodeActions(document2, params) {
183454
184427
  const actions = [];
@@ -183712,6 +184685,26 @@ ${indent}}`)]
183712
184685
  }
183713
184686
  });
183714
184687
  }
184688
+ if (code === "SSM040" && diagnostic.data && diagnostic.data.individualModifier === true) {
184689
+ const declText = document2.textDocument.getText(diagnostic.range);
184690
+ const match = /\bindividual\b[ \t]*/u.exec(declText);
184691
+ if (match) {
184692
+ const start2 = document2.textDocument.offsetAt(diagnostic.range.start) + match.index;
184693
+ actions.push({
184694
+ title: "Remove 'individual'",
184695
+ kind: import_vscode_languageserver18.CodeActionKind.QuickFix,
184696
+ diagnostics: [diagnostic],
184697
+ edit: {
184698
+ changes: {
184699
+ [uri]: [import_vscode_languageserver18.TextEdit.replace({
184700
+ start: document2.textDocument.positionAt(start2),
184701
+ end: document2.textDocument.positionAt(start2 + match[0].length)
184702
+ }, "")]
184703
+ }
184704
+ }
184705
+ });
184706
+ }
184707
+ }
183715
184708
  if (code === "STYL006") {
183716
184709
  const suffix = document2.textDocument.getText(diagnostic.range).replace(/\s+/gu, "");
183717
184710
  if (suffix === "::**") {
@@ -183750,6 +184743,19 @@ ${indent}}`)]
183750
184743
  });
183751
184744
  }
183752
184745
  }
184746
+ const implicitOwner = nearestImplicitBaseOwner(rangeNode);
184747
+ const implicitBase = implicitOwner ? impliedBaseOf(implicitOwner) : void 0;
184748
+ if (implicitOwner?.$cstNode && implicitBase && this.implicit?.descriptionOf(implicitBase)) {
184749
+ actions.push({
184750
+ title: IMPLICIT_SPECIALIZATION_MESSAGES.makeExplicit(implicitBase.qualified),
184751
+ kind: import_vscode_languageserver18.CodeActionKind.RefactorRewrite,
184752
+ edit: {
184753
+ changes: {
184754
+ [uri]: [import_vscode_languageserver18.TextEdit.insert(declarationTailPosition(implicitOwner.$cstNode), ` :> ${implicitBase.qualified}`)]
184755
+ }
184756
+ }
184757
+ });
184758
+ }
183753
184759
  const importNode = nearestAncestor2(rangeNode, isImport);
183754
184760
  if (importNode?.$cstNode && importNode.alias && importNode.segs.every((s) => !s.star && s.name)) {
183755
184761
  const path10 = [importNode.head, ...importNode.segs.map((s) => s.name)].join("::");
@@ -185027,18 +186033,6 @@ function typeAnchor(node, refText) {
185027
186033
  }
185028
186034
  return void 0;
185029
186035
  }
185030
- var EXPLICIT_SPECIALIZATION_KINDS = /* @__PURE__ */ new Set([
185031
- ":>",
185032
- ":>>",
185033
- "::>",
185034
- "=>",
185035
- "specializes",
185036
- "subsets",
185037
- "redefines",
185038
- "references",
185039
- "crosses",
185040
- "conjugates"
185041
- ]);
185042
186036
  var REDEFINITION_KINDS4 = /* @__PURE__ */ new Set([":>>", "redefines"]);
185043
186037
  var CONSTANT_CARRYING_KINDS = /* @__PURE__ */ new Set([
185044
186038
  ":>",
@@ -185083,30 +186077,6 @@ var ACTION_KIND_USAGES = /* @__PURE__ */ new Set([
185083
186077
  "VerificationCaseDecl"
185084
186078
  ]);
185085
186079
  var KERML_FEATURE_DECLS = /* @__PURE__ */ new Set(["FeatureDecl", "StepDecl", "ExpressionDecl"]);
185086
- var IMPLICIT_BASES = Object.freeze({
185087
- PartDecl: { def: "Parts::Part", usage: "Parts::parts" },
185088
- ItemDecl: { def: "Items::Item", usage: "Items::items" },
185089
- PortDecl: { def: "Ports::Port", usage: "Ports::ports" },
185090
- ActionDecl: { def: "Actions::Action", usage: "Actions::actions" },
185091
- StateDecl: { def: "States::StateAction", usage: "States::stateActions" },
185092
- ConnectionDecl: { def: "Connections::Connection", usage: "Connections::connections" },
185093
- InterfaceDecl: { def: "Interfaces::Interface", usage: "Interfaces::interfaces" },
185094
- CaseDecl: { def: "Cases::Case", usage: "Cases::cases" },
185095
- UseCaseDecl: { def: "UseCases::UseCase", usage: "UseCases::useCases" },
185096
- AnalysisCaseDecl: { def: "AnalysisCases::AnalysisCase", usage: "AnalysisCases::analysisCases" },
185097
- VerificationCaseDecl: { def: "VerificationCases::VerificationCase", usage: "VerificationCases::verificationCases" },
185098
- ViewDecl: { def: "Views::View", usage: "Views::views" },
185099
- ViewpointDecl: { def: "Views::ViewpointCheck", usage: "Views::viewpointChecks" },
185100
- RenderingDecl: { def: "Views::Rendering", usage: "Views::renderings" },
185101
- RequirementDecl: { def: "Requirements::RequirementCheck", usage: "Requirements::requirementChecks" },
185102
- ConcernDecl: { def: "Requirements::ConcernCheck", usage: "Requirements::concernChecks" },
185103
- ConstraintDecl: { def: "Constraints::ConstraintCheck", usage: "Constraints::constraintChecks" },
185104
- CalcDecl: { def: "Calculations::Calculation", usage: "Calculations::calculations" },
185105
- AllocationDecl: { def: "Allocations::Allocation", usage: "Allocations::allocations" },
185106
- AttributeDecl: { def: "Attributes::AttributeValue", usage: "Attributes::attributeValues" },
185107
- OccurrenceDecl: { def: "Occurrences::Occurrence", usage: "Occurrences::occurrences" },
185108
- MetadataDecl: { def: "Metadata::MetadataItem", usage: "Metadata::metadataItems" }
185109
- });
185110
186080
  var OCCURRENCE_KIND_OWNERS = /* @__PURE__ */ new Set([
185111
186081
  ...Object.keys(IMPLICIT_BASES).filter((kind) => kind !== "AttributeDecl"),
185112
186082
  // KerML fixes a library base per classifier kind too, in the same way and in
@@ -185141,14 +186111,9 @@ var NON_VARYING_LIBRARY_TYPES = /* @__PURE__ */ new Set(["SelfLink", "HappensLin
185141
186111
  function markdown(value) {
185142
186112
  return { kind: import_vscode_languageserver20.MarkupKind.Markdown, value };
185143
186113
  }
185144
- function allRelationships2(node) {
186114
+ function allRelationships3(node) {
185145
186115
  return [...node.preRelationships ?? [], ...node.relationships ?? []];
185146
186116
  }
185147
- function hasExplicitSpecialization(node) {
185148
- if (node.typing?.type?.$refText)
185149
- return true;
185150
- return allRelationships2(node).some((rel2) => rel2.kind && EXPLICIT_SPECIALIZATION_KINDS.has(rel2.kind));
185151
- }
185152
186117
  function keywordLeaf(node, keyword) {
185153
186118
  const cst = node.$cstNode;
185154
186119
  if (!cst)
@@ -185172,7 +186137,7 @@ function specializesNonVaryingLibraryType(node) {
185172
186137
  const typing = node.typing?.type?.$refText;
185173
186138
  if (typing && NON_VARYING_LIBRARY_TYPES.has(lastSegment3(typing)))
185174
186139
  return true;
185175
- return allRelationships2(node).flatMap((rel2) => rel2.targets ?? []).some((target) => NON_VARYING_LIBRARY_TYPES.has(lastSegment3(target)));
186140
+ return allRelationships3(node).flatMap((rel2) => rel2.targets ?? []).some((target) => NON_VARYING_LIBRARY_TYPES.has(lastSegment3(target)));
185176
186141
  }
185177
186142
  function constantAnchor(node) {
185178
186143
  const cst = node.$cstNode;
@@ -185236,16 +186201,6 @@ function callArguments(node) {
185236
186201
  }
185237
186202
  var SysmlInlayHintProvider = class {
185238
186203
  services;
185239
- /**
185240
- * Resolved implicit bases, keyed by the qualified name in
185241
- * {@link IMPLICIT_BASES}. A base the index does not hold is NOT cached — the
185242
- * library may still be loading — and issue #240 made that miss cheap: two
185243
- * lookups in the shared name index rather than the full index scan it used
185244
- * to be, on a request VS Code re-issues on every scroll. A HIT is cached
185245
- * until the index is rebuilt, so the description a label links to always
185246
- * carries the ranges of the generation it was read from.
185247
- */
185248
- baseCache = /* @__PURE__ */ new Map();
185249
186204
  /**
185250
186205
  * REQ-395 — issue #240: the shared name lookup, built once per index
185251
186206
  * generation. Every category that resolves a WRITTEN name goes through it,
@@ -185290,7 +186245,6 @@ var SysmlInlayHintProvider = class {
185290
186245
  this.linker = services?.references.Linker;
185291
186246
  this.featureProperties = featurePropertyResolver(new FeaturePathResolver(services));
185292
186247
  services?.shared.workspace.DocumentBuilder.onBuildPhase(DocumentState.IndexedContent, () => {
185293
- this.baseCache.clear();
185294
186248
  this.constantCache.clear();
185295
186249
  this.declaredNameCache.clear();
185296
186250
  this.effectiveNameResolvers = /* @__PURE__ */ new WeakMap();
@@ -185398,26 +186352,6 @@ var SysmlInlayHintProvider = class {
185398
186352
  ...node.$type === "VariantReference" || isOwnedEnumerationValue(node) ? {} : { textEdits: [{ range: { start: at, end: at }, newText: "ref " }] }
185399
186353
  });
185400
186354
  }
185401
- if (settings.specialization && node.$cstNode && decl.name && !hasExplicitSpecialization(decl)) {
185402
- const entry = IMPLICIT_BASES[node.$type];
185403
- const qualified = entry ? decl.isDef ? entry.def : entry.usage : void 0;
185404
- const description = qualified ? this.resolveImplicitBase(qualified, decl.isDef !== true) : void 0;
185405
- if (qualified && description) {
185406
- hints.push({
185407
- position: multiplicityAnchor(node.$cstNode),
185408
- label: [{
185409
- value: ` :> ${qualified}`,
185410
- location: {
185411
- uri: description.documentUri.toString(),
185412
- range: descriptionRange(description)
185413
- }
185414
- }],
185415
- kind: import_vscode_languageserver20.InlayHintKind.Type,
185416
- paddingLeft: true,
185417
- tooltip: markdown(`Implicitly specializes \`${qualified}\` from the standard library.`)
185418
- });
185419
- }
185420
- }
185421
186355
  if (settings.redefinition)
185422
186356
  hints.push(...this.parameterRedefinitionHints(decl));
185423
186357
  if (settings.effectiveNames) {
@@ -185488,7 +186422,7 @@ var SysmlInlayHintProvider = class {
185488
186422
  const parameter = mine[index2].node;
185489
186423
  if (!parameter.name || !parameter.$cstNode)
185490
186424
  continue;
185491
- if (allRelationships2(parameter).some((rel2) => rel2.kind && REDEFINITION_KINDS4.has(rel2.kind)))
186425
+ if (allRelationships3(parameter).some((rel2) => rel2.kind && REDEFINITION_KINDS4.has(rel2.kind)))
185492
186426
  continue;
185493
186427
  const target = theirs[index2].node;
185494
186428
  if (!target.name || target.name === parameter.name)
@@ -185683,7 +186617,7 @@ var SysmlInlayHintProvider = class {
185683
186617
  return void 0;
185684
186618
  if (specializesNonVaryingLibraryType(node))
185685
186619
  return void 0;
185686
- const carrier = allRelationships2(node).filter((rel2) => rel2.kind && CONSTANT_CARRYING_KINDS.has(rel2.kind)).flatMap((rel2) => rel2.targets ?? []).find((target) => this.isConstantFeature(target));
186620
+ const carrier = allRelationships3(node).filter((rel2) => rel2.kind && CONSTANT_CARRYING_KINDS.has(rel2.kind)).flatMap((rel2) => rel2.targets ?? []).find((target) => this.isConstantFeature(target));
185687
186621
  if (!carrier)
185688
186622
  return void 0;
185689
186623
  const anchor = constantAnchor(node);
@@ -185727,41 +186661,11 @@ var SysmlInlayHintProvider = class {
185727
186661
  this.constantCache.set(key2, answer);
185728
186662
  return answer;
185729
186663
  }
185730
- /**
185731
- * REQ-395 — Find one implicit base in the index.
185732
- *
185733
- * A description whose name is the full qualified spelling wins outright. The
185734
- * index otherwise keys library symbols by their simple name, so the fallback
185735
- * requires BOTH a standard-library document and the right side of the
185736
- * definition/usage split, which the precomputed index records — that is what
185737
- * keeps `Parts::Part` from matching a `part Part` somewhere else.
185738
- */
185739
- resolveImplicitBase(qualified, wantUsage) {
185740
- const cached = this.baseCache.get(qualified);
185741
- if (cached)
185742
- return cached;
185743
- if (!this.lookup)
185744
- return void 0;
185745
- const exact = this.lookup.descriptions(qualified).at(0);
185746
- if (exact) {
185747
- this.baseCache.set(qualified, exact);
185748
- return exact;
185749
- }
185750
- const fallback = this.lookup.descriptions(lastSegment3(qualified)).find((description) => {
185751
- const uri = description.documentUri instanceof URI2 ? description.documentUri : URI2.parse(String(description.documentUri));
185752
- if (!isStandardLibraryUri(uri))
185753
- return false;
185754
- return description.isUsage === true === wantUsage;
185755
- });
185756
- if (fallback)
185757
- this.baseCache.set(qualified, fallback);
185758
- return fallback;
185759
- }
185760
186664
  };
185761
186665
  function effectiveNameHint(node, resolver) {
185762
186666
  if (node.name || node.shortName?.name || !node.$cstNode)
185763
186667
  return void 0;
185764
- const redefinition = allRelationships2(node).find((rel2) => rel2.kind && REDEFINITION_KINDS4.has(rel2.kind) && (rel2.targets?.length ?? 0) > 0);
186668
+ const redefinition = allRelationships3(node).find((rel2) => rel2.kind && REDEFINITION_KINDS4.has(rel2.kind) && (rel2.targets?.length ?? 0) > 0);
185765
186669
  if (!redefinition?.targets?.[0])
185766
186670
  return void 0;
185767
186671
  const names = effectiveNamesOf(node, resolver);
@@ -187094,6 +187998,8 @@ function ownedRelationshipTargets(element, typePattern) {
187094
187998
  for (const relationship of toArray(element.ownedRelationship)) {
187095
187999
  if (!isObject3(relationship))
187096
188000
  continue;
188001
+ if (relationship.isImplied === true)
188002
+ continue;
187097
188003
  const type = stringValue(relationship["@type"]) ?? "";
187098
188004
  if (!typePattern.test(type))
187099
188005
  continue;
@@ -209722,7 +210628,7 @@ async function runExport(command) {
209722
210628
  }
209723
210629
 
209724
210630
  // src/main.ts
209725
- var VERSION2 = true ? "0.31.2" : "dev";
210631
+ var VERSION2 = true ? "0.33.0" : "dev";
209726
210632
  function display(file) {
209727
210633
  const rel2 = path9.relative(process.cwd(), file);
209728
210634
  return rel2 && !rel2.startsWith("..") ? rel2.split(path9.sep).join("/") : file;