sysml-validate 0.11.0 → 0.14.2

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.
Files changed (121) hide show
  1. package/LICENSE +27 -27
  2. package/README.md +200 -200
  3. package/out/main.js +596 -141
  4. package/out/main.js.map +4 -4
  5. package/package.json +57 -57
  6. package/resources/sysml.dimension-table.json +1 -1
  7. package/resources/sysml.library/Domain Libraries/Analysis/.meta.json +9 -9
  8. package/resources/sysml.library/Domain Libraries/Analysis/.project.json +26 -26
  9. package/resources/sysml.library/Domain Libraries/Analysis/AnalysisTooling.sysml +33 -33
  10. package/resources/sysml.library/Domain Libraries/Analysis/SampledFunctions.sysml +118 -118
  11. package/resources/sysml.library/Domain Libraries/Analysis/StateSpaceRepresentation.sysml +143 -143
  12. package/resources/sysml.library/Domain Libraries/Analysis/TradeStudies.sysml +170 -170
  13. package/resources/sysml.library/Domain Libraries/Cause and Effect/.meta.json +7 -7
  14. package/resources/sysml.library/Domain Libraries/Cause and Effect/.project.json +22 -22
  15. package/resources/sysml.library/Domain Libraries/Cause and Effect/CausationConnections.sysml +82 -82
  16. package/resources/sysml.library/Domain Libraries/Cause and Effect/CauseAndEffect.sysml +81 -81
  17. package/resources/sysml.library/Domain Libraries/Geometry/.meta.json +7 -7
  18. package/resources/sysml.library/Domain Libraries/Geometry/.project.json +26 -26
  19. package/resources/sysml.library/Domain Libraries/Geometry/ShapeItems.sysml +898 -898
  20. package/resources/sysml.library/Domain Libraries/Geometry/SpatialItems.sysml +167 -167
  21. package/resources/sysml.library/Domain Libraries/Metadata/.meta.json +9 -9
  22. package/resources/sysml.library/Domain Libraries/Metadata/.project.json +18 -18
  23. package/resources/sysml.library/Domain Libraries/Metadata/ImageMetadata.sysml +77 -77
  24. package/resources/sysml.library/Domain Libraries/Metadata/ModelingMetadata.sysml +142 -142
  25. package/resources/sysml.library/Domain Libraries/Metadata/ParametersOfInterestMetadata.sysml +38 -38
  26. package/resources/sysml.library/Domain Libraries/Metadata/RiskMetadata.sysml +99 -99
  27. package/resources/sysml.library/Domain Libraries/Quantities and Units/.meta.json +28 -28
  28. package/resources/sysml.library/Domain Libraries/Quantities and Units/.project.json +22 -22
  29. package/resources/sysml.library/Domain Libraries/Quantities and Units/ISQ.sysml +42 -42
  30. package/resources/sysml.library/Domain Libraries/Quantities and Units/ISQAcoustics.sysml +439 -439
  31. package/resources/sysml.library/Domain Libraries/Quantities and Units/ISQAtomicNuclear.sysml +2726 -2726
  32. package/resources/sysml.library/Domain Libraries/Quantities and Units/ISQBase.sysml +206 -206
  33. package/resources/sysml.library/Domain Libraries/Quantities and Units/ISQCharacteristicNumbers.sysml +1991 -1991
  34. package/resources/sysml.library/Domain Libraries/Quantities and Units/ISQChemistryMolecular.sysml +1353 -1353
  35. package/resources/sysml.library/Domain Libraries/Quantities and Units/ISQCondensedMatter.sysml +1223 -1223
  36. package/resources/sysml.library/Domain Libraries/Quantities and Units/ISQElectromagnetism.sysml +2333 -2333
  37. package/resources/sysml.library/Domain Libraries/Quantities and Units/ISQInformation.sysml +958 -958
  38. package/resources/sysml.library/Domain Libraries/Quantities and Units/ISQLight.sysml +1537 -1537
  39. package/resources/sysml.library/Domain Libraries/Quantities and Units/ISQMechanics.sysml +1564 -1564
  40. package/resources/sysml.library/Domain Libraries/Quantities and Units/ISQSpaceTime.sysml +1169 -1169
  41. package/resources/sysml.library/Domain Libraries/Quantities and Units/ISQThermodynamics.sysml +1256 -1256
  42. package/resources/sysml.library/Domain Libraries/Quantities and Units/MeasurementRefCalculations.sysml +30 -30
  43. package/resources/sysml.library/Domain Libraries/Quantities and Units/MeasurementReferences.sysml +526 -526
  44. package/resources/sysml.library/Domain Libraries/Quantities and Units/Quantities.sysml +107 -107
  45. package/resources/sysml.library/Domain Libraries/Quantities and Units/QuantityCalculations.sysml +70 -70
  46. package/resources/sysml.library/Domain Libraries/Quantities and Units/SI.sysml +378 -378
  47. package/resources/sysml.library/Domain Libraries/Quantities and Units/SIPrefixes.sysml +48 -48
  48. package/resources/sysml.library/Domain Libraries/Quantities and Units/TensorCalculations.sysml +49 -49
  49. package/resources/sysml.library/Domain Libraries/Quantities and Units/Time.sysml +274 -274
  50. package/resources/sysml.library/Domain Libraries/Quantities and Units/USCustomaryUnits.sysml +260 -260
  51. package/resources/sysml.library/Domain Libraries/Quantities and Units/VectorCalculations.sysml +62 -62
  52. package/resources/sysml.library/Domain Libraries/Requirement Derivation/.meta.json +7 -7
  53. package/resources/sysml.library/Domain Libraries/Requirement Derivation/.project.json +18 -18
  54. package/resources/sysml.library/Domain Libraries/Requirement Derivation/DerivationConnections.sysml +62 -62
  55. package/resources/sysml.library/Domain Libraries/Requirement Derivation/RequirementDerivation.sysml +38 -38
  56. package/resources/sysml.library/Kernel Libraries/Kernel Data Type Library/.meta.json +8 -8
  57. package/resources/sysml.library/Kernel Libraries/Kernel Data Type Library/.project.json +10 -10
  58. package/resources/sysml.library/Kernel Libraries/Kernel Data Type Library/Collections.kerml +176 -176
  59. package/resources/sysml.library/Kernel Libraries/Kernel Data Type Library/ScalarValues.kerml +23 -23
  60. package/resources/sysml.library/Kernel Libraries/Kernel Data Type Library/VectorValues.kerml +63 -63
  61. package/resources/sysml.library/Kernel Libraries/Kernel Function Library/.meta.json +22 -22
  62. package/resources/sysml.library/Kernel Libraries/Kernel Function Library/.project.json +14 -14
  63. package/resources/sysml.library/Kernel Libraries/Kernel Function Library/BaseFunctions.kerml +79 -79
  64. package/resources/sysml.library/Kernel Libraries/Kernel Function Library/BooleanFunctions.kerml +22 -22
  65. package/resources/sysml.library/Kernel Libraries/Kernel Function Library/CollectionFunctions.kerml +68 -68
  66. package/resources/sysml.library/Kernel Libraries/Kernel Function Library/ComplexFunctions.kerml +47 -47
  67. package/resources/sysml.library/Kernel Libraries/Kernel Function Library/ControlFunctions.kerml +116 -116
  68. package/resources/sysml.library/Kernel Libraries/Kernel Function Library/DataFunctions.kerml +42 -42
  69. package/resources/sysml.library/Kernel Libraries/Kernel Function Library/IntegerFunctions.kerml +43 -43
  70. package/resources/sysml.library/Kernel Libraries/Kernel Function Library/NaturalFunctions.kerml +27 -27
  71. package/resources/sysml.library/Kernel Libraries/Kernel Function Library/NumericalFunctions.kerml +42 -42
  72. package/resources/sysml.library/Kernel Libraries/Kernel Function Library/OccurrenceFunctions.kerml +153 -153
  73. package/resources/sysml.library/Kernel Libraries/Kernel Function Library/RationalFunctions.kerml +49 -49
  74. package/resources/sysml.library/Kernel Libraries/Kernel Function Library/RealFunctions.kerml +56 -56
  75. package/resources/sysml.library/Kernel Libraries/Kernel Function Library/ScalarFunctions.kerml +32 -32
  76. package/resources/sysml.library/Kernel Libraries/Kernel Function Library/SequenceFunctions.kerml +110 -110
  77. package/resources/sysml.library/Kernel Libraries/Kernel Function Library/StringFunctions.kerml +25 -25
  78. package/resources/sysml.library/Kernel Libraries/Kernel Function Library/TrigFunctions.kerml +34 -34
  79. package/resources/sysml.library/Kernel Libraries/Kernel Function Library/VectorFunctions.kerml +272 -272
  80. package/resources/sysml.library/Kernel Libraries/Kernel Semantic Library/.meta.json +21 -21
  81. package/resources/sysml.library/Kernel Libraries/Kernel Semantic Library/.project.json +14 -14
  82. package/resources/sysml.library/Kernel Libraries/Kernel Semantic Library/Base.kerml +94 -94
  83. package/resources/sysml.library/Kernel Libraries/Kernel Semantic Library/Clocks.kerml +155 -155
  84. package/resources/sysml.library/Kernel Libraries/Kernel Semantic Library/ControlPerformances.kerml +134 -134
  85. package/resources/sysml.library/Kernel Libraries/Kernel Semantic Library/FeatureReferencingPerformances.kerml +189 -189
  86. package/resources/sysml.library/Kernel Libraries/Kernel Semantic Library/KerML.kerml +483 -483
  87. package/resources/sysml.library/Kernel Libraries/Kernel Semantic Library/Links.kerml +66 -66
  88. package/resources/sysml.library/Kernel Libraries/Kernel Semantic Library/Metaobjects.kerml +57 -57
  89. package/resources/sysml.library/Kernel Libraries/Kernel Semantic Library/Objects.kerml +212 -212
  90. package/resources/sysml.library/Kernel Libraries/Kernel Semantic Library/Observation.kerml +160 -160
  91. package/resources/sysml.library/Kernel Libraries/Kernel Semantic Library/Occurrences.kerml +992 -992
  92. package/resources/sysml.library/Kernel Libraries/Kernel Semantic Library/Performances.kerml +292 -292
  93. package/resources/sysml.library/Kernel Libraries/Kernel Semantic Library/SpatialFrames.kerml +196 -196
  94. package/resources/sysml.library/Kernel Libraries/Kernel Semantic Library/StatePerformances.kerml +144 -144
  95. package/resources/sysml.library/Kernel Libraries/Kernel Semantic Library/Transfers.kerml +280 -280
  96. package/resources/sysml.library/Kernel Libraries/Kernel Semantic Library/TransitionPerformances.kerml +65 -65
  97. package/resources/sysml.library/Kernel Libraries/Kernel Semantic Library/Triggers.kerml +187 -187
  98. package/resources/sysml.library/LICENSE +276 -276
  99. package/resources/sysml.library/NOTICE.md +20 -20
  100. package/resources/sysml.library/Systems Library/Actions.sysml +556 -556
  101. package/resources/sysml.library/Systems Library/Allocations.sysml +28 -28
  102. package/resources/sysml.library/Systems Library/AnalysisCases.sysml +37 -37
  103. package/resources/sysml.library/Systems Library/Attributes.sysml +24 -24
  104. package/resources/sysml.library/Systems Library/Calculations.sysml +36 -36
  105. package/resources/sysml.library/Systems Library/Cases.sysml +70 -70
  106. package/resources/sysml.library/Systems Library/Connections.sysml +59 -59
  107. package/resources/sysml.library/Systems Library/Constraints.sysml +43 -43
  108. package/resources/sysml.library/Systems Library/Flows.sysml +125 -125
  109. package/resources/sysml.library/Systems Library/Interfaces.sysml +88 -88
  110. package/resources/sysml.library/Systems Library/Items.sysml +152 -152
  111. package/resources/sysml.library/Systems Library/Metadata.sysml +31 -31
  112. package/resources/sysml.library/Systems Library/Parts.sysml +80 -80
  113. package/resources/sysml.library/Systems Library/Ports.sysml +53 -53
  114. package/resources/sysml.library/Systems Library/Requirements.sysml +193 -193
  115. package/resources/sysml.library/Systems Library/StandardViewDefinitions.sysml +123 -123
  116. package/resources/sysml.library/Systems Library/States.sysml +102 -102
  117. package/resources/sysml.library/Systems Library/SysML.sysml +539 -539
  118. package/resources/sysml.library/Systems Library/UseCases.sysml +56 -56
  119. package/resources/sysml.library/Systems Library/VerificationCases.sysml +102 -102
  120. package/resources/sysml.library/Systems Library/Views.sysml +163 -163
  121. package/resources/sysml.library.index.json +1 -1
package/out/main.js CHANGED
@@ -57907,9 +57907,53 @@ function asDiagnosticLevel(value, fallback = "off") {
57907
57907
  }
57908
57908
 
57909
57909
  // ../language-server/out/src/services/import-visibility.js
57910
+ var GlobalDescriptionIndex = class _GlobalDescriptionIndex {
57911
+ /** Reuse an existing index; wrap a plain list. */
57912
+ static from(source) {
57913
+ return source instanceof _GlobalDescriptionIndex ? source : new _GlobalDescriptionIndex(source);
57914
+ }
57915
+ /** Exact name → descriptions carrying it (qualified and simple names alike). */
57916
+ byName = /* @__PURE__ */ new Map();
57917
+ /** Namespace path → descriptions for its DIRECT members (`A::B` → `A::B::C`). */
57918
+ directMembers = /* @__PURE__ */ new Map();
57919
+ /** Namespace path → descriptions for all its descendants (`A` → `A::B::C`). */
57920
+ nestedMembers = /* @__PURE__ */ new Map();
57921
+ constructor(descriptions) {
57922
+ for (const desc of descriptions) {
57923
+ push(this.byName, desc.name, desc);
57924
+ let sep2 = desc.name.indexOf("::");
57925
+ while (sep2 >= 0) {
57926
+ const prefix = desc.name.slice(0, sep2);
57927
+ push(this.nestedMembers, prefix, desc);
57928
+ const next = desc.name.indexOf("::", sep2 + 2);
57929
+ if (next < 0)
57930
+ push(this.directMembers, prefix, desc);
57931
+ sep2 = next;
57932
+ }
57933
+ }
57934
+ }
57935
+ named(name) {
57936
+ return this.byName.get(name) ?? EMPTY_DESCRIPTIONS;
57937
+ }
57938
+ firstNamed(name) {
57939
+ return this.byName.get(name)?.[0];
57940
+ }
57941
+ membersOf(path10, wildcard) {
57942
+ const map3 = wildcard === "shallow" ? this.directMembers : this.nestedMembers;
57943
+ return map3.get(path10) ?? EMPTY_DESCRIPTIONS;
57944
+ }
57945
+ };
57946
+ var EMPTY_DESCRIPTIONS = [];
57947
+ function push(map3, key, desc) {
57948
+ const list = map3.get(key);
57949
+ if (list)
57950
+ list.push(desc);
57951
+ else
57952
+ map3.set(key, [desc]);
57953
+ }
57910
57954
  function expandImportEntries(imp, globalDescriptions, options = {}) {
57911
57955
  const out = [];
57912
- expandImportInto(imp, globalDescriptions, out, options, /* @__PURE__ */ new Set());
57956
+ expandImportInto(imp, GlobalDescriptionIndex.from(globalDescriptions), out, options, /* @__PURE__ */ new Set());
57913
57957
  return dedupeEntries(out);
57914
57958
  }
57915
57959
  function importedPath(imp) {
@@ -57934,12 +57978,13 @@ function importVisibility(imp) {
57934
57978
  return imp.visibility ?? "private";
57935
57979
  }
57936
57980
  function resolveDescription(name, globalDescriptions) {
57981
+ const index = GlobalDescriptionIndex.from(globalDescriptions);
57937
57982
  const normalized = name.trim();
57938
- const direct = globalDescriptions.find((desc) => desc.name === normalized);
57983
+ const direct = index.firstNamed(normalized);
57939
57984
  if (direct)
57940
57985
  return direct;
57941
57986
  const simple = normalized.split(/::|\./).pop();
57942
- return simple ? globalDescriptions.find((desc) => desc.name === simple) : void 0;
57987
+ return simple ? index.firstNamed(simple) : void 0;
57943
57988
  }
57944
57989
  function descriptionKey(description) {
57945
57990
  return `${description.documentUri.toString()}#${description.path}`;
@@ -58064,7 +58109,7 @@ function qualifiedNameMatches(a2, b) {
58064
58109
  return true;
58065
58110
  }
58066
58111
  function resolveImportedDescription(path10, globalDescriptions, options, visitedNamespaces) {
58067
- const direct = globalDescriptions.find((desc) => desc.name === path10);
58112
+ const direct = globalDescriptions.firstNamed(path10);
58068
58113
  if (direct)
58069
58114
  return direct;
58070
58115
  const split = path10.lastIndexOf("::");
@@ -58077,23 +58122,17 @@ function resolveImportedDescription(path10, globalDescriptions, options, visited
58077
58122
  return exported.find((entry) => entry.name === simpleName2)?.description;
58078
58123
  }
58079
58124
  function expandNamespaceMembers(path10, wildcard, globalDescriptions, out) {
58080
- const prefix = path10 + "::";
58081
- for (const desc of globalDescriptions) {
58082
- if (!desc.name.startsWith(prefix))
58083
- continue;
58125
+ const prefixLength = path10.length + 2;
58126
+ for (const desc of globalDescriptions.membersOf(path10, wildcard)) {
58084
58127
  if (isPrivateDescription(desc))
58085
58128
  continue;
58086
- const rest = desc.name.slice(prefix.length);
58087
- if (wildcard === "shallow" && rest.includes("::"))
58088
- continue;
58129
+ const rest = desc.name.slice(prefixLength);
58089
58130
  const simple = rest.includes("::") ? rest.slice(rest.lastIndexOf("::") + 2) : rest;
58090
58131
  out.push({ name: simple, targetName: desc.name, description: desc });
58091
58132
  }
58092
58133
  }
58093
58134
  function expandNamespaceImports(path10, globalDescriptions, out, options, visitedNamespaces) {
58094
- for (const namespaceDesc of globalDescriptions) {
58095
- if (namespaceDesc.name !== path10)
58096
- continue;
58135
+ for (const namespaceDesc of globalDescriptions.named(path10)) {
58097
58136
  const key = descriptionKey(namespaceDesc);
58098
58137
  if (visitedNamespaces.has(key))
58099
58138
  continue;
@@ -58269,7 +58308,7 @@ function splitUnitFactors(symbol) {
58269
58308
  let start = 0;
58270
58309
  let quote = false;
58271
58310
  let nextOp = "*";
58272
- const push = (end) => {
58311
+ const push2 = (end) => {
58273
58312
  const text = symbol.slice(start, end).trim();
58274
58313
  if (!text)
58275
58314
  return false;
@@ -58289,13 +58328,13 @@ function splitUnitFactors(symbol) {
58289
58328
  continue;
58290
58329
  }
58291
58330
  if (ch === "*" || ch === "/" || ch === "\u22C5") {
58292
- if (!push(i))
58331
+ if (!push2(i))
58293
58332
  return void 0;
58294
58333
  nextOp = ch === "/" ? "/" : "*";
58295
58334
  start = i + 1;
58296
58335
  }
58297
58336
  }
58298
- if (quote || !push(symbol.length))
58337
+ if (quote || !push2(symbol.length))
58299
58338
  return void 0;
58300
58339
  return tokens;
58301
58340
  }
@@ -58651,6 +58690,8 @@ function nearestUnits(symbol, limit) {
58651
58690
 
58652
58691
  // ../language-server/out/src/messages.js
58653
58692
  var DIAGNOSTIC_MESSAGES = {
58693
+ // REQ-317 — expression paths diagnose the exact missing feature segment.
58694
+ RES001_FEATURE_PATH_SEGMENT: (segment, owner) => `Feature path segment '${segment}' does not exist on '${owner}'.`,
58654
58695
  LEX001_UNTERMINATED_STRING: `Unterminated string literal \u2014 missing closing '"'.`,
58655
58696
  LEX002_UNTERMINATED_BLOCK_COMMENT: "Unterminated block comment - '/*' is never closed with '*/'.",
58656
58697
  LEX003_UNTERMINATED_UNRESTRICTED_NAME: `Unterminated unrestricted name \u2014 missing closing "'".`,
@@ -58969,6 +59010,352 @@ function isLibraryDocument(doc) {
58969
59010
  return doc.isLibraryDocument === true || isStandardLibraryUri(doc.uri);
58970
59011
  }
58971
59012
 
59013
+ // ../language-server/out/src/services/escaped-name.js
59014
+ function decodeEscapes(body) {
59015
+ return body.replace(/\\(.)/gu, (_m, ch) => {
59016
+ switch (ch) {
59017
+ case "n":
59018
+ return "\n";
59019
+ case "t":
59020
+ return " ";
59021
+ case "b":
59022
+ return "\b";
59023
+ case "f":
59024
+ return "\f";
59025
+ default:
59026
+ return ch;
59027
+ }
59028
+ });
59029
+ }
59030
+ function canonicalEscapedName(token) {
59031
+ if (token.length < 2 || !token.startsWith("'") || !token.endsWith("'"))
59032
+ return token;
59033
+ return "'" + decodeEscapes(token.slice(1, -1)) + "'";
59034
+ }
59035
+ function decodeUnrestrictedName(token) {
59036
+ if (token.length >= 2 && token.startsWith("'") && token.endsWith("'")) {
59037
+ return decodeEscapes(token.slice(1, -1));
59038
+ }
59039
+ return token;
59040
+ }
59041
+ var BARE_ID = /^[_a-zA-Z]\w*$/u;
59042
+ function encodeUnrestrictedName(value) {
59043
+ const raw = value.length >= 2 && value.startsWith("'") && value.endsWith("'") ? decodeUnrestrictedName(value) : value;
59044
+ if (BARE_ID.test(raw))
59045
+ return raw;
59046
+ const escaped = raw.replace(/\r\n?/gu, "\n").replace(/[\\']/gu, (ch) => `\\${ch}`).replace(/\n/gu, "\\n").replace(/\t/gu, "\\t").replace(/[\f]/gu, "\\f").replace(/[\b]/gu, "\\b");
59047
+ return `'${escaped}'`;
59048
+ }
59049
+
59050
+ // ../language-server/out/src/services/feature-path-resolver.js
59051
+ var SPECIALIZATION_KINDS = /* @__PURE__ */ new Set([":>", ":>>", "specializes", "subsets", "redefines"]);
59052
+ function nameOf(node) {
59053
+ const name = node?.name;
59054
+ if (typeof name === "string" && name.length > 0)
59055
+ return name;
59056
+ if (node?.$type === "FeatureRedefinitionShorthand") {
59057
+ const leading = node.preRelationships?.[0]?.targets?.[0];
59058
+ return leading ? lastSegment2(leading) : void 0;
59059
+ }
59060
+ if (node?.$type === "FeatureShorthand") {
59061
+ const text = node.$cstNode?.text;
59062
+ const head2 = text?.split(/(?=\s(?::|:>|:>>|=|\[|\{|;))/u, 1)[0]?.trim();
59063
+ const tokens = head2?.match(/'(?:\\.|[^'])*'|[\p{L}_][\p{L}\p{N}_]*/gu);
59064
+ if (tokens && tokens.length > 1)
59065
+ return canonicalEscapedName(tokens.at(-1));
59066
+ }
59067
+ if (node?.$container?.$type === "EnumDecl") {
59068
+ const literal = node.$cstNode?.text.trim().replace(/;$/u, "").trim();
59069
+ if (literal && !/[\s{}[\]=:]/u.test(literal))
59070
+ return canonicalEscapedName(literal);
59071
+ }
59072
+ return void 0;
59073
+ }
59074
+ function unwrap(node) {
59075
+ if (node.$type !== "PrefixMetadataMember")
59076
+ return node;
59077
+ return node.element ?? node;
59078
+ }
59079
+ function directNamedChildren(node) {
59080
+ const result = [];
59081
+ const seen = /* @__PURE__ */ new Set();
59082
+ for (const raw of ast_utils_exports.streamContents(node)) {
59083
+ const child = unwrap(raw);
59084
+ if (!nameOf(child) || seen.has(child))
59085
+ continue;
59086
+ seen.add(child);
59087
+ result.push(child);
59088
+ }
59089
+ return result;
59090
+ }
59091
+ function isAncestor(candidate, node) {
59092
+ if (!candidate)
59093
+ return false;
59094
+ for (let current2 = node; current2; current2 = current2.$container) {
59095
+ if (current2 === candidate)
59096
+ return true;
59097
+ }
59098
+ return false;
59099
+ }
59100
+ function lastSegment2(path10) {
59101
+ return path10.split(/::|\./u).pop() ?? path10;
59102
+ }
59103
+ var FeaturePathResolver = class {
59104
+ indexManager;
59105
+ descriptions;
59106
+ documents;
59107
+ locator;
59108
+ snapshots = /* @__PURE__ */ new WeakMap();
59109
+ constructor(services) {
59110
+ this.indexManager = services?.shared.workspace.IndexManager;
59111
+ this.descriptions = services?.workspace.AstNodeDescriptionProvider;
59112
+ this.documents = services?.shared.workspace.LangiumDocuments;
59113
+ this.locator = services?.workspace.AstNodeLocator;
59114
+ services?.shared.workspace.DocumentBuilder.onBuildPhase(DocumentState.IndexedContent, () => {
59115
+ this.snapshots = /* @__PURE__ */ new WeakMap();
59116
+ });
59117
+ }
59118
+ // REQ-220/317 — resolve every independently clickable/diagnosable segment.
59119
+ resolve(node) {
59120
+ const segments = this.segmentsOf(node);
59121
+ if (segments.length === 0)
59122
+ return { segments };
59123
+ const root3 = ast_utils_exports.getDocument(node).parseResult.value;
59124
+ const snapshot = this.snapshot(root3);
59125
+ let current2 = this.resolveRoot(node, segments[0].text, snapshot);
59126
+ this.applyTarget(segments[0], current2);
59127
+ if (!current2.node && !current2.description) {
59128
+ return { segments, indeterminateIndex: 0 };
59129
+ }
59130
+ for (let index = 1; index < segments.length; index += 1) {
59131
+ const segment = segments[index];
59132
+ const next = this.resolveChild(current2, segment.text, segments, index, snapshot);
59133
+ this.applyTarget(segment, next);
59134
+ if (!next.node && !next.description) {
59135
+ if (!current2.node && current2.description || !current2.certain) {
59136
+ return { segments, indeterminateIndex: index };
59137
+ }
59138
+ return { segments, unresolvedIndex: index };
59139
+ }
59140
+ current2 = next;
59141
+ }
59142
+ return { segments };
59143
+ }
59144
+ isPathExpr(node) {
59145
+ return isPathExpr(node);
59146
+ }
59147
+ segmentsOf(node) {
59148
+ const cst = node.$cstNode;
59149
+ if (!cst)
59150
+ return [];
59151
+ const segments = [];
59152
+ let separator;
59153
+ for (const leaf of cst_utils_exports.flattenCst(cst)) {
59154
+ if (leaf.text === "$")
59155
+ continue;
59156
+ if (leaf.text === "." || leaf.text === "::") {
59157
+ separator = leaf.text;
59158
+ continue;
59159
+ }
59160
+ segments.push({
59161
+ text: canonicalEscapedName(leaf.text),
59162
+ separator: segments.length === 0 ? void 0 : separator,
59163
+ cst: leaf
59164
+ });
59165
+ separator = void 0;
59166
+ }
59167
+ return segments;
59168
+ }
59169
+ resolveRoot(node, name, snapshot) {
59170
+ if (name === "self" || name === "this" || name === "that") {
59171
+ for (let owner = node.$container; owner; owner = owner.$container) {
59172
+ if (nameOf(owner)) {
59173
+ return this.targetForNode(owner, this.memberInventoryKnown(owner, snapshot));
59174
+ }
59175
+ }
59176
+ }
59177
+ for (let owner = node.$container; owner; owner = owner.$container) {
59178
+ const local = directNamedChildren(owner).find((candidate) => nameOf(candidate) === name && !isAncestor(candidate, node));
59179
+ if (local)
59180
+ return this.targetForNode(local, this.memberInventoryKnown(local, snapshot));
59181
+ }
59182
+ return this.targetFromDescriptions(snapshot.byName.get(name), node);
59183
+ }
59184
+ resolveChild(current2, name, segments, index, snapshot) {
59185
+ const owner = this.followAlias(current2, snapshot);
59186
+ if (owner.node) {
59187
+ const direct = directNamedChildren(owner.node).find((candidate) => nameOf(candidate) === name);
59188
+ if (direct) {
59189
+ return this.targetForNode(direct, current2.certain === true && this.memberInventoryKnown(direct, snapshot));
59190
+ }
59191
+ for (const inheritedOwner of this.typedAndSpecializedOwners(owner.node, snapshot)) {
59192
+ const inherited = directNamedChildren(inheritedOwner).find((candidate) => nameOf(candidate) === name);
59193
+ if (inherited) {
59194
+ return this.targetForNode(inherited, current2.certain === true && this.memberInventoryKnown(inherited, snapshot));
59195
+ }
59196
+ }
59197
+ }
59198
+ if (segments.slice(1, index + 1).every((segment) => segment.separator === "::")) {
59199
+ const exact = segments.slice(0, index + 1).map((segment) => segment.text).join("::");
59200
+ const indexed = this.targetFromDescriptions(snapshot.byName.get(exact));
59201
+ if (indexed.node || indexed.description)
59202
+ return indexed;
59203
+ }
59204
+ return {};
59205
+ }
59206
+ typedAndSpecializedOwners(node, snapshot) {
59207
+ const result = [];
59208
+ const seen = /* @__PURE__ */ new Set();
59209
+ const visit = (candidate) => {
59210
+ if (!candidate || seen.has(candidate))
59211
+ return;
59212
+ seen.add(candidate);
59213
+ result.push(candidate);
59214
+ visit(this.typingTarget(candidate, snapshot));
59215
+ for (const specialized of this.specializationTargets(candidate, snapshot))
59216
+ visit(specialized);
59217
+ };
59218
+ visit(this.typingTarget(node, snapshot));
59219
+ for (const specialized of this.specializationTargets(node, snapshot))
59220
+ visit(specialized);
59221
+ return result;
59222
+ }
59223
+ typingTarget(node, snapshot) {
59224
+ const typing = node.typing?.type;
59225
+ let typed;
59226
+ try {
59227
+ typed = typing?.ref;
59228
+ } catch {
59229
+ typed = void 0;
59230
+ }
59231
+ if (!typed && typing?.$refText) {
59232
+ typed = this.nodeOf(this.pickDescription(snapshot.byName.get(typing.$refText))) ?? this.nodeOf(this.pickDescription(snapshot.byName.get(lastSegment2(typing.$refText))));
59233
+ }
59234
+ return typed;
59235
+ }
59236
+ specializationTargets(node, snapshot) {
59237
+ const relNode = node;
59238
+ const result = [];
59239
+ for (const relation of [...relNode.preRelationships ?? [], ...relNode.relationships ?? []]) {
59240
+ if (!relation.kind || !SPECIALIZATION_KINDS.has(relation.kind))
59241
+ continue;
59242
+ for (const target of relation.targets ?? []) {
59243
+ const description = this.pickDescription(snapshot.byName.get(target)) ?? this.pickDescription(snapshot.byName.get(lastSegment2(target)));
59244
+ const resolved = this.nodeOf(description);
59245
+ if (resolved)
59246
+ result.push(resolved);
59247
+ }
59248
+ }
59249
+ return result;
59250
+ }
59251
+ memberInventoryKnown(node, snapshot) {
59252
+ const record = node;
59253
+ if (record.isDef === true || node.$type === "ClassDecl" || node.$type === "StructDecl" || node.$type === "EnumDecl" || node.$type === "DatatypeDecl" || node.$type === "FunctionDecl" || node.$type === "PredicateDecl") {
59254
+ return true;
59255
+ }
59256
+ const typed = this.typingTarget(node, snapshot);
59257
+ if (typed) {
59258
+ const localUri = ast_utils_exports.getDocument(node).uri.toString();
59259
+ const typedUri = ast_utils_exports.getDocument(typed).uri.toString();
59260
+ if (localUri === typedUri)
59261
+ return true;
59262
+ const refText = record.typing?.type?.$refText;
59263
+ const candidates = refText ? snapshot.byName.get(refText) ?? snapshot.byName.get(lastSegment2(refText)) : void 0;
59264
+ return candidates?.length === 1;
59265
+ }
59266
+ const semanticRelationships = [...record.preRelationships ?? [], ...record.relationships ?? []].filter((relation) => relation.kind && SPECIALIZATION_KINDS.has(relation.kind));
59267
+ return semanticRelationships.length > 0 && semanticRelationships.every((relation) => (relation.targets ?? []).every((target) => Boolean(this.nodeOf(this.pickDescription(snapshot.byName.get(target))) ?? this.nodeOf(this.pickDescription(snapshot.byName.get(lastSegment2(target)))))));
59268
+ }
59269
+ followAlias(target, snapshot) {
59270
+ const node = target.node;
59271
+ if (node?.$type !== "AliasDecl")
59272
+ return target;
59273
+ const aliasTarget = node.target;
59274
+ if (!aliasTarget)
59275
+ return target;
59276
+ const exact = this.targetFromDescriptions(snapshot.byName.get(aliasTarget));
59277
+ if (exact.node || exact.description)
59278
+ return exact;
59279
+ const simple = this.targetFromDescriptions(snapshot.byName.get(lastSegment2(aliasTarget)));
59280
+ return simple.node || simple.description ? simple : target;
59281
+ }
59282
+ targetForNode(node, certain = false) {
59283
+ const name = nameOf(node);
59284
+ let description;
59285
+ if (name && this.descriptions) {
59286
+ try {
59287
+ description = this.descriptions.createDescription(node, name);
59288
+ } catch {
59289
+ description = void 0;
59290
+ }
59291
+ }
59292
+ return { node, description, certain };
59293
+ }
59294
+ targetFromDescriptions(descriptions, context) {
59295
+ const description = this.pickDescription(descriptions, context);
59296
+ return description ? { description, node: this.nodeOf(description) } : {};
59297
+ }
59298
+ pickDescription(descriptions, context) {
59299
+ if (!descriptions?.length)
59300
+ return void 0;
59301
+ if (context) {
59302
+ const uri = ast_utils_exports.getDocument(context).uri.toString();
59303
+ const local = descriptions.find((description) => description.documentUri.toString() === uri && !isAncestor(description.node, context));
59304
+ if (local)
59305
+ return local;
59306
+ }
59307
+ return descriptions.find((description) => !context || !isAncestor(description.node, context));
59308
+ }
59309
+ nodeOf(description) {
59310
+ if (!description)
59311
+ return void 0;
59312
+ if (description.node)
59313
+ return description.node;
59314
+ const root3 = this.documents?.getDocument(description.documentUri)?.parseResult.value;
59315
+ return root3 && this.locator ? this.locator.getAstNode(root3, description.path) : void 0;
59316
+ }
59317
+ applyTarget(segment, target) {
59318
+ segment.target = target.node;
59319
+ segment.description = target.description;
59320
+ }
59321
+ snapshot(root3) {
59322
+ const cached = this.snapshots.get(root3);
59323
+ if (cached)
59324
+ return cached;
59325
+ const byName = /* @__PURE__ */ new Map();
59326
+ if (this.indexManager) {
59327
+ for (const description of this.indexManager.allElements()) {
59328
+ const values2 = byName.get(description.name) ?? [];
59329
+ values2.push(description);
59330
+ byName.set(description.name, values2);
59331
+ }
59332
+ } else {
59333
+ for (const node of [root3, ...ast_utils_exports.streamAllContents(root3)]) {
59334
+ const name = nameOf(node);
59335
+ if (!name)
59336
+ continue;
59337
+ const values2 = byName.get(name) ?? [];
59338
+ const target = this.targetForNode(node);
59339
+ if (target.description)
59340
+ values2.push(target.description);
59341
+ else {
59342
+ values2.push({
59343
+ name,
59344
+ type: node.$type,
59345
+ documentUri: ast_utils_exports.getDocument(node).uri,
59346
+ path: "",
59347
+ node
59348
+ });
59349
+ }
59350
+ byName.set(name, values2);
59351
+ }
59352
+ }
59353
+ const snapshot = { byName };
59354
+ this.snapshots.set(root3, snapshot);
59355
+ return snapshot;
59356
+ }
59357
+ };
59358
+
58972
59359
  // ../language-server/out/src/services/validator.js
58973
59360
  var severityOverrides = {};
58974
59361
  function setSeverityOverrides(overrides) {
@@ -59038,7 +59425,7 @@ function maskNonCode(text) {
59038
59425
  }
59039
59426
  return out.join("");
59040
59427
  }
59041
- var SPECIALIZATION_KINDS = /* @__PURE__ */ new Set([":>", ":>>", "specializes", "subsets", "redefines"]);
59428
+ var SPECIALIZATION_KINDS2 = /* @__PURE__ */ new Set([":>", ":>>", "specializes", "subsets", "redefines"]);
59042
59429
  var CONSTRAINT_SIDE_EFFECT_TYPES = /* @__PURE__ */ new Set([
59043
59430
  "AssignNode",
59044
59431
  "SendNode",
@@ -59065,10 +59452,12 @@ var SysmlValidator = class _SysmlValidator {
59065
59452
  indexManager;
59066
59453
  langiumDocuments;
59067
59454
  astNodeLocator;
59455
+ featurePaths;
59068
59456
  constructor(services) {
59069
59457
  this.indexManager = services.shared.workspace.IndexManager;
59070
59458
  this.langiumDocuments = services.shared.workspace.LangiumDocuments;
59071
59459
  this.astNodeLocator = services.workspace.AstNodeLocator;
59460
+ this.featurePaths = new FeaturePathResolver(services);
59072
59461
  }
59073
59462
  // ══════════════════════════════════════════════════════════════════════
59074
59463
  // STYL — naming conventions (REQ-169, REQ-332)
@@ -59076,6 +59465,28 @@ var SysmlValidator = class _SysmlValidator {
59076
59465
  // REQ-330 — SSM014 support: message-endpoint root features per interaction,
59077
59466
  // computed once per interaction AST node instead of once per participant.
59078
59467
  interactionMessageRoots = /* @__PURE__ */ new WeakMap();
59468
+ // REQ-317 — PathExpr is stored as one datatype string, so the ordinary
59469
+ // Langium linker cannot diagnose a missing intermediate feature. Resolve the
59470
+ // chain here and underline only the first invalid segment.
59471
+ checkPathExpr(node, accept) {
59472
+ let declaration = node.$container;
59473
+ while (declaration && !isPartDecl(declaration))
59474
+ declaration = declaration.$container;
59475
+ const modifiers2 = declaration?.modifiers ?? [];
59476
+ if (!declaration || !modifiers2.includes("ref"))
59477
+ return;
59478
+ const resolution = this.featurePaths.resolve(node);
59479
+ if (resolution.unresolvedIndex === void 0)
59480
+ return;
59481
+ const invalid = resolution.segments[resolution.unresolvedIndex];
59482
+ const owner = resolution.unresolvedIndex > 0 ? resolution.segments[resolution.unresolvedIndex - 1].text : "the current scope";
59483
+ accept(severity("RES001", "error"), DIAGNOSTIC_MESSAGES.RES001_FEATURE_PATH_SEGMENT(invalid.text, owner), {
59484
+ node,
59485
+ range: invalid.cst.range,
59486
+ code: "RES001",
59487
+ data: { featurePathSegment: true }
59488
+ });
59489
+ }
59079
59490
  // REQ-169, REQ-329 — SSM001 def/usage mismatch for parts
59080
59491
  checkPartDecl(node, accept) {
59081
59492
  if (!node.isDef && node.name && /^[A-Z]/.test(node.name)) {
@@ -60843,6 +61254,7 @@ ${baseIndent}}`;
60843
61254
  return {
60844
61255
  Document: this.checkDocument.bind(this),
60845
61256
  PartDecl: this.checkPartDecl.bind(this),
61257
+ PathExpr: this.checkPathExpr.bind(this),
60846
61258
  RequirementDecl: this.checkRequirementDecl.bind(this),
60847
61259
  AttributeDecl: this.checkAttributeDecl.bind(this),
60848
61260
  ConstraintDecl: this.checkConstraintDecl.bind(this),
@@ -61063,7 +61475,7 @@ function specializationTargets(node) {
61063
61475
  ...node.relationships ?? []
61064
61476
  ];
61065
61477
  for (const rel of rels) {
61066
- if (rel.kind && SPECIALIZATION_KINDS.has(rel.kind))
61478
+ if (rel.kind && SPECIALIZATION_KINDS2.has(rel.kind))
61067
61479
  out.push(...rel.targets);
61068
61480
  }
61069
61481
  return out;
@@ -61303,8 +61715,17 @@ function isWithinNamespaceOf(inner, target) {
61303
61715
  }
61304
61716
  return false;
61305
61717
  }
61718
+ var globalIndexes = /* @__PURE__ */ new WeakMap();
61719
+ function globalIndexFor(index) {
61720
+ let globalIndex = globalIndexes.get(index);
61721
+ if (!globalIndex) {
61722
+ globalIndex = new GlobalDescriptionIndex(Array.from(index.values()).flat());
61723
+ globalIndexes.set(index, globalIndex);
61724
+ }
61725
+ return globalIndex;
61726
+ }
61306
61727
  function introducedNames(imp, index, nodeOf) {
61307
- const globalDescs = Array.from(index.values()).flat();
61728
+ const globalDescs = globalIndexFor(index);
61308
61729
  const protectedNamespaceKeys = protectedNamespaceKeysFor(imp.$container, globalDescs, nodeOf);
61309
61730
  return expandImportEntries(imp, globalDescs, {
61310
61731
  nodeOf,
@@ -61937,7 +62358,7 @@ function trailingBlockBody(node) {
61937
62358
  }
61938
62359
 
61939
62360
  // ../language-server/out/src/services/document-symbol-provider.js
61940
- var SPECIALIZATION_KINDS2 = /* @__PURE__ */ new Set([":>", "specializes"]);
62361
+ var SPECIALIZATION_KINDS3 = /* @__PURE__ */ new Set([":>", "specializes"]);
61941
62362
  var REDEFINITION_KINDS = /* @__PURE__ */ new Set([":>>", "redefines"]);
61942
62363
  var INHERITABLE_FEATURE_TYPES = /* @__PURE__ */ new Set([
61943
62364
  "ActionDecl",
@@ -62006,7 +62427,7 @@ function specializationTargets2(node) {
62006
62427
  const n = node;
62007
62428
  const out = [];
62008
62429
  for (const rel of [...n.preRelationships ?? [], ...n.relationships ?? []]) {
62009
- if (rel.kind && SPECIALIZATION_KINDS2.has(rel.kind))
62430
+ if (rel.kind && SPECIALIZATION_KINDS3.has(rel.kind))
62010
62431
  out.push(...rel.targets ?? []);
62011
62432
  }
62012
62433
  return out;
@@ -63841,12 +64262,17 @@ var SNIPPETS = [
63841
64262
  ];
63842
64263
  var SysmlCompletionProvider = class extends DefaultCompletionProvider {
63843
64264
  indexManager;
64265
+ // REQ-245, REQ-268 — Qualified names of every indexed element, keyed by the
64266
+ // element it names. Built once per workspace build and evicted with the rest
64267
+ // of the workspace caches; see [[qualifiedNamesByElement]].
64268
+ qualifiedNameCache;
63844
64269
  completionOptions = {
63845
64270
  triggerCharacters: COMPLETION_TRIGGER_CHARACTERS
63846
64271
  };
63847
64272
  constructor(services) {
63848
64273
  super(services);
63849
64274
  this.indexManager = services.shared.workspace.IndexManager;
64275
+ this.qualifiedNameCache = new WorkspaceCache(services.shared);
63850
64276
  }
63851
64277
  async getCompletion(document, params) {
63852
64278
  const defaultResult = await super.getCompletion(document, params);
@@ -64010,8 +64436,34 @@ var SysmlCompletionProvider = class extends DefaultCompletionProvider {
64010
64436
  qualifiedNameFor(desc) {
64011
64437
  if (desc.name.includes("::"))
64012
64438
  return desc.name;
64013
- const candidates = this.indexManager.allElements().toArray().filter((other) => other.documentUri.toString() === desc.documentUri.toString()).filter((other) => other.path === desc.path && other.type === desc.type).map((other) => other.name).filter((name) => name.includes("::") && simpleName(name) === desc.name).sort((a2, b) => a2.length - b.length || a2.localeCompare(b));
64014
- return candidates[0];
64439
+ const candidates = this.qualifiedNamesByElement().get(elementKey(desc));
64440
+ return candidates?.find((name) => simpleName(name) === desc.name);
64441
+ }
64442
+ // REQ-245, REQ-268 — An element's qualified names, shortest first, keyed by
64443
+ // the element. A type-context completion offers thousands of symbols and each
64444
+ // one needs its qualified name to plan an auto-import; looking that up by
64445
+ // scanning the whole index per candidate made the index-sized scan happen
64446
+ // thousands of times, and a single `: ` keystroke blocked the server for
64447
+ // 10 s — long enough for the editor to report the request as timed out. One
64448
+ // grouped pass per build answers all of them.
64449
+ qualifiedNamesByElement() {
64450
+ return this.qualifiedNameCache.get("all", () => {
64451
+ const byElement = /* @__PURE__ */ new Map();
64452
+ for (const desc of this.indexManager.allElements()) {
64453
+ if (!desc.name.includes("::"))
64454
+ continue;
64455
+ const key = elementKey(desc);
64456
+ const names = byElement.get(key);
64457
+ if (names)
64458
+ names.push(desc.name);
64459
+ else
64460
+ byElement.set(key, [desc.name]);
64461
+ }
64462
+ for (const names of byElement.values()) {
64463
+ names.sort((a2, b) => a2.length - b.length || a2.localeCompare(b));
64464
+ }
64465
+ return byElement;
64466
+ });
64015
64467
  }
64016
64468
  importPathItems(importPrefix) {
64017
64469
  const prefix = importPrefix.trim();
@@ -64215,6 +64667,9 @@ function isPackageBody(prefix) {
64215
64667
  return true;
64216
64668
  return /\bpackage\s+(?:<[^>]+>\s*)?[\p{L}_'][^;{}]*$/u.test(prefix.slice(Math.max(0, open - 160), open));
64217
64669
  }
64670
+ function elementKey(desc) {
64671
+ return `${desc.documentUri.toString()}#${desc.path}#${desc.type}`;
64672
+ }
64218
64673
  function isDefinitionDescription(desc) {
64219
64674
  const node = desc.node;
64220
64675
  return node?.isDef === void 0 || node.isDef === true;
@@ -64567,11 +65022,16 @@ var SysmlScopeProvider = class extends DefaultScopeProvider {
64567
65022
  // global symbol table, which made indexing the standard library O(refs ×
64568
65023
  // symbols) — minutes of unusable startup. See REQ-073/REQ-220.
64569
65024
  importCache;
65025
+ // REQ-268 — The global symbol table, indexed by name and by namespace prefix.
65026
+ // Built once per reference type per build and evicted with the same
65027
+ // `DocumentBuilder` update that evicts Langium's own global-scope cache.
65028
+ globalIndexCache;
64570
65029
  langiumDocuments;
64571
65030
  astNodeLocator;
64572
65031
  constructor(services) {
64573
65032
  super(services);
64574
65033
  this.importCache = new DocumentCache(services.shared);
65034
+ this.globalIndexCache = new WorkspaceCache(services.shared);
64575
65035
  this.langiumDocuments = services.shared.workspace.LangiumDocuments;
64576
65036
  this.astNodeLocator = services.workspace.AstNodeLocator;
64577
65037
  }
@@ -64591,8 +65051,9 @@ var SysmlScopeProvider = class extends DefaultScopeProvider {
64591
65051
  const refType = this.reflection.getReferenceType(context);
64592
65052
  const globalScope = this.getGlobalScope(refType, context);
64593
65053
  const doc = ast_utils_exports.getDocument(context.container);
64594
- const contextKey = this.importContextKey(context.container);
64595
- const imported = this.importCache.get(doc.uri, `${refType}|${contextKey}`, () => this.computeImportedDescriptions(doc, refType, context.container));
65054
+ const protectedNamespaces = this.protectedNamespacesFor(context.container, this.globalIndex(refType));
65055
+ const contextKey = this.importContextKey(context.container, protectedNamespaces);
65056
+ const imported = this.importCache.get(doc.uri, `${refType} ${contextKey}`, () => this.computeImportedDescriptions(doc, refType, context.container, protectedNamespaces));
64596
65057
  let scope = imported.length > 0 ? this.createScope(imported, globalScope) : globalScope;
64597
65058
  const localLayers = this.localScopeLayers(context.container, refType);
64598
65059
  for (let i = localLayers.length - 1; i >= 0; i--) {
@@ -64624,12 +65085,11 @@ var SysmlScopeProvider = class extends DefaultScopeProvider {
64624
65085
  // REQ-067, REQ-069 — Collect import- and alias-visible descriptions for a
64625
65086
  // document. Computed once per (document, reference type) and cached; the
64626
65087
  // global element list is scanned a single time here rather than per reference.
64627
- computeImportedDescriptions(doc, refType, contextNode) {
65088
+ computeImportedDescriptions(doc, refType, contextNode, protectedNamespaces) {
64628
65089
  const root3 = doc.parseResult?.value;
64629
65090
  if (!root3 || !isDocument(root3))
64630
65091
  return [];
64631
- const globalDescs = Array.from(this.indexManager.allElements(refType));
64632
- const protectedNamespaces = this.protectedNamespacesFor(contextNode, globalDescs);
65092
+ const globalDescs = this.globalIndex(refType);
64633
65093
  const options = {
64634
65094
  nodeOf: this.nodeOf.bind(this),
64635
65095
  protectedNamespaceKeys: protectedNamespaces.keys,
@@ -64652,6 +65112,10 @@ var SysmlScopeProvider = class extends DefaultScopeProvider {
64652
65112
  }
64653
65113
  return dedupeDescriptions(result);
64654
65114
  }
65115
+ // REQ-268 — One index over the global symbol table per reference type.
65116
+ globalIndex(refType) {
65117
+ return this.globalIndexCache.get(refType, () => new GlobalDescriptionIndex(Array.from(this.indexManager.allElements(refType))));
65118
+ }
64655
65119
  // REQ-067, REQ-068, REQ-069, REQ-323 — Expand import forms and visibility re-exports
64656
65120
  expandImport(imp, globalDescs, out, options) {
64657
65121
  for (const entry of expandImportEntries(imp, globalDescs, options)) {
@@ -64677,6 +65141,16 @@ var SysmlScopeProvider = class extends DefaultScopeProvider {
64677
65141
  }
64678
65142
  return imports;
64679
65143
  }
65144
+ // REQ-060, REQ-068 — The namespaces a context specializes (transitively) that
65145
+ // re-export their `protected` imports to it.
65146
+ //
65147
+ // REQ-268 — Only a namespace that actually OWNS a protected import can change
65148
+ // an expansion: `expandNamespaceImports` consults the key set for exactly that
65149
+ // case, and the re-export loop iterates exactly those members. Namespaces
65150
+ // without one are therefore dropped here rather than carried into the cache
65151
+ // key, so the common model — where nothing is imported `protected` — resolves
65152
+ // every reference against one cached expansion instead of one per specializing
65153
+ // element.
64680
65154
  protectedNamespacesFor(contextNode, globalDescs) {
64681
65155
  const keys3 = /* @__PURE__ */ new Set();
64682
65156
  const nodes = [];
@@ -64688,7 +65162,7 @@ var SysmlScopeProvider = class extends DefaultScopeProvider {
64688
65162
  }
64689
65163
  cur = cur.$container;
64690
65164
  }
64691
- return { keys: keys3, nodes };
65165
+ return { keys: keys3, nodes, key: keys3.size === 0 ? "" : [...keys3].sort().join(" ") };
64692
65166
  }
64693
65167
  collectProtectedNamespace(targetName, globalDescs, keys3, nodes, visitedTargets) {
64694
65168
  if (visitedTargets.has(targetName))
@@ -64698,26 +65172,43 @@ var SysmlScopeProvider = class extends DefaultScopeProvider {
64698
65172
  if (!desc)
64699
65173
  return;
64700
65174
  const key = descriptionKey(desc);
64701
- const wasNew = !keys3.has(key);
64702
- keys3.add(key);
64703
65175
  const node = this.nodeOf(desc);
64704
65176
  if (!node)
64705
65177
  return;
64706
- if (wasNew)
65178
+ if (ownsProtectedImport(node) && !keys3.has(key)) {
65179
+ keys3.add(key);
64707
65180
  nodes.push(node);
65181
+ }
64708
65182
  for (const inherited of specializationTargets3(node)) {
64709
65183
  this.collectProtectedNamespace(inherited, globalDescs, keys3, nodes, visitedTargets);
64710
65184
  }
64711
65185
  }
64712
- importContextKey(contextNode) {
65186
+ // REQ-268 — The cache key for a context's import expansion.
65187
+ //
65188
+ // The expansion is a pure function of exactly two things: the imports visible
65189
+ // from the context (innermost namespace outwards) and the protected-import
65190
+ // re-exports its specializations open up. Every import resolves its path
65191
+ // against the GLOBAL symbol table, so an import expands to the same members
65192
+ // wherever it is written; two contexts that see the same import text in the
65193
+ // same order, under the same protected re-exports, get the same result.
65194
+ //
65195
+ // Keying on those inputs rather than on the nearest enclosing namespace NODE
65196
+ // is what makes the cache useful: a model file has one or two distinct import
65197
+ // sets but hundreds of namespace nodes, so the node key missed on nearly
65198
+ // every reference and re-expanded the whole standard library each time
65199
+ // (measured on a 1 500-line model: 226 misses over 349 references, 16 s).
65200
+ importContextKey(contextNode, protectedNamespaces) {
65201
+ const parts = [];
64713
65202
  let cur = contextNode;
64714
65203
  while (cur) {
64715
- if (isDocument(cur) || namespaceMembers(cur).length > 0 || specializationTargets3(cur).length > 0) {
64716
- return this.nodeKey(cur);
65204
+ for (const member of namespaceMembers(cur)) {
65205
+ if (isImport(member))
65206
+ parts.push(importSignature(member));
64717
65207
  }
64718
65208
  cur = cur.$container;
64719
65209
  }
64720
- return "root";
65210
+ const imports = parts.length > 0 ? parts.join(" ") : "root";
65211
+ return protectedNamespaces.key ? `${imports} ${protectedNamespaces.key}` : imports;
64721
65212
  }
64722
65213
  nodeOf(desc) {
64723
65214
  if (desc.node)
@@ -64728,16 +65219,23 @@ var SysmlScopeProvider = class extends DefaultScopeProvider {
64728
65219
  return void 0;
64729
65220
  return this.astNodeLocator.getAstNode(root3, desc.path);
64730
65221
  }
64731
- nodeKey(node) {
64732
- return `${ast_utils_exports.getDocument(node).uri.toString()}#${this.astNodeLocator.getAstNodePath(node)}`;
64733
- }
64734
65222
  };
64735
- var SPECIALIZATION_KINDS3 = /* @__PURE__ */ new Set([":>", ":>>", "specializes", "subsets", "redefines"]);
65223
+ function ownsProtectedImport(node) {
65224
+ return namespaceMembers(node).some((member) => isImport(member) && importVisibility(member) === "protected");
65225
+ }
65226
+ function importSignature(imp) {
65227
+ const text = imp.$cstNode?.text;
65228
+ if (text)
65229
+ return text;
65230
+ const segments = imp.segs.map((seg) => `${seg.name ?? ""}${seg.star ? "*" : ""}${seg.recursive ? "**" : ""}`);
65231
+ return `${importVisibility(imp)} ${imp.head}::${segments.join("::")}${imp.alias ? ` as ${imp.alias}` : ""}`;
65232
+ }
65233
+ var SPECIALIZATION_KINDS4 = /* @__PURE__ */ new Set([":>", ":>>", "specializes", "subsets", "redefines"]);
64736
65234
  function specializationTargets3(node) {
64737
65235
  const n = node;
64738
65236
  const out = [];
64739
65237
  for (const rel of [...n.preRelationships ?? [], ...n.relationships ?? []]) {
64740
- if (rel.kind && SPECIALIZATION_KINDS3.has(rel.kind))
65238
+ if (rel.kind && SPECIALIZATION_KINDS4.has(rel.kind))
64741
65239
  out.push(...rel.targets ?? []);
64742
65240
  }
64743
65241
  return out;
@@ -64797,20 +65295,21 @@ var SysmlScopeComputation = class extends DefaultScopeComputation {
64797
65295
  const imports = Array.from(ast_utils_exports.streamAllContents(root3)).filter(isImport).filter((imp) => importVisibility(imp) === "public");
64798
65296
  if (imports.length === 0)
64799
65297
  return;
64800
- const physicalExports = [...exports2];
65298
+ const physicalAliases = aliasesByNode(exports2);
64801
65299
  const ownerAliases = /* @__PURE__ */ new Map();
64802
65300
  for (const imp of imports) {
64803
65301
  const owner = imp.$container;
64804
- ownerAliases.set(imp, owner ? physicalExports.filter((desc) => desc.node === owner && !desc.name.includes(".")).map((desc) => desc.name) : []);
65302
+ ownerAliases.set(imp, owner && physicalAliases.get(owner) || []);
64805
65303
  }
64806
65304
  const seen = new Set(exports2.map(exportAliasKey));
64807
65305
  for (let pass = 0; pass < imports.length + 1; pass++) {
64808
65306
  let changed = false;
65307
+ const indexed = new GlobalDescriptionIndex(exports2);
64809
65308
  for (const imp of imports) {
64810
65309
  const aliases = ownerAliases.get(imp) ?? [];
64811
65310
  if (aliases.length === 0)
64812
65311
  continue;
64813
- for (const entry of directImportEntries(imp, exports2)) {
65312
+ for (const entry of directImportEntries(imp, indexed)) {
64814
65313
  for (const ownerAlias of aliases) {
64815
65314
  const description = {
64816
65315
  ...entry.description,
@@ -64835,28 +65334,23 @@ var SysmlScopeComputation = class extends DefaultScopeComputation {
64835
65334
  // where Country owns Life). Materialize those same-document aliases so the
64836
65335
  // linker can resolve the qualified spelling without a full type evaluator.
64837
65336
  addInheritedQualifiedAliases(root3, exports2) {
64838
- const physicalExports = [...exports2];
64839
65337
  const seen = new Set(exports2.map(exportAliasKey));
64840
- const nodes = Array.from(ast_utils_exports.streamAllContents(root3));
64841
- const ownerAliases = /* @__PURE__ */ new Map();
64842
- for (const node of nodes) {
64843
- ownerAliases.set(node, physicalExports.filter((desc) => desc.node === node && !desc.name.includes(".")).map((desc) => desc.name));
64844
- }
65338
+ const nodes = Array.from(ast_utils_exports.streamAllContents(root3)).filter((node) => specializationTargets4(node).length > 0);
65339
+ if (nodes.length === 0)
65340
+ return;
65341
+ const ownerAliases = aliasesByNode(exports2);
64845
65342
  for (let pass = 0; pass < nodes.length; pass++) {
64846
- const sourceDescriptions = [...exports2];
65343
+ const sourceDescriptions = new GlobalDescriptionIndex(exports2);
64847
65344
  const additions = [];
64848
65345
  for (const node of nodes) {
64849
65346
  const targets = specializationTargets4(node);
64850
- if (targets.length === 0)
64851
- continue;
64852
65347
  const aliases = ownerAliases.get(node) ?? [];
65348
+ if (aliases.length === 0)
65349
+ continue;
64853
65350
  for (const target of targets) {
64854
- for (const inherited of sourceDescriptions) {
64855
- const prefix = `${target}::`;
64856
- if (!inherited.name.startsWith(prefix))
64857
- continue;
64858
- const suffix = inherited.name.slice(prefix.length);
64859
- if (!suffix || suffix.includes("::"))
65351
+ for (const inherited of sourceDescriptions.membersOf(target, "shallow")) {
65352
+ const suffix = inherited.name.slice(target.length + 2);
65353
+ if (!suffix)
64860
65354
  continue;
64861
65355
  for (const ownerAlias of aliases) {
64862
65356
  const description = {
@@ -64974,28 +65468,38 @@ function nodeVisibility(node) {
64974
65468
  function exportAliasKey(description) {
64975
65469
  return `${description.name}|${description.documentUri.toString()}|${description.path}`;
64976
65470
  }
65471
+ function aliasesByNode(exports2) {
65472
+ const byNode = /* @__PURE__ */ new Map();
65473
+ for (const desc of exports2) {
65474
+ if (!desc.node || desc.name.includes("."))
65475
+ continue;
65476
+ const names = byNode.get(desc.node);
65477
+ if (names)
65478
+ names.push(desc.name);
65479
+ else
65480
+ byNode.set(desc.node, [desc.name]);
65481
+ }
65482
+ return byNode;
65483
+ }
64977
65484
  function directImportEntries(imp, descriptions) {
64978
65485
  const path10 = importedPath(imp);
64979
65486
  if (!path10)
64980
65487
  return [];
64981
65488
  const wildcard = importWildcard(imp);
64982
65489
  if (wildcard === "none") {
64983
- const description = descriptions.find((candidate) => candidate.name === path10);
65490
+ const description = descriptions.firstNamed(path10);
64984
65491
  if (!description)
64985
65492
  return [];
64986
65493
  return [{ name: imp.alias ?? path10.split("::").pop() ?? path10, description }];
64987
65494
  }
64988
- const prefix = `${path10}::`;
64989
65495
  const entries = [];
64990
65496
  const seen = /* @__PURE__ */ new Set();
64991
- for (const description of descriptions) {
64992
- if (!description.name.startsWith(prefix))
64993
- continue;
65497
+ for (const description of descriptions.membersOf(path10, wildcard)) {
64994
65498
  const visibility = description;
64995
65499
  if (visibility.isPrivate || visibility.visibility === "private")
64996
65500
  continue;
64997
- const rest = description.name.slice(prefix.length);
64998
- if (!rest || wildcard === "shallow" && rest.includes("::"))
65501
+ const rest = description.name.slice(path10.length + 2);
65502
+ if (!rest)
64999
65503
  continue;
65000
65504
  const name = rest.split("::").pop();
65001
65505
  if (!name)
@@ -65008,12 +65512,12 @@ function directImportEntries(imp, descriptions) {
65008
65512
  }
65009
65513
  return entries;
65010
65514
  }
65011
- var SPECIALIZATION_KINDS4 = /* @__PURE__ */ new Set([":>", ":>>", "specializes", "subsets", "redefines"]);
65515
+ var SPECIALIZATION_KINDS5 = /* @__PURE__ */ new Set([":>", ":>>", "specializes", "subsets", "redefines"]);
65012
65516
  function specializationTargets4(node) {
65013
65517
  const value = node;
65014
65518
  const targets = [];
65015
65519
  for (const relationship of [...value.preRelationships ?? [], ...value.relationships ?? []]) {
65016
- if (relationship.kind && SPECIALIZATION_KINDS4.has(relationship.kind)) {
65520
+ if (relationship.kind && SPECIALIZATION_KINDS5.has(relationship.kind)) {
65017
65521
  targets.push(...relationship.targets ?? []);
65018
65522
  }
65019
65523
  }
@@ -65062,43 +65566,6 @@ var SysmlLinker = class extends DefaultLinker {
65062
65566
  }
65063
65567
  };
65064
65568
 
65065
- // ../language-server/out/src/services/escaped-name.js
65066
- function decodeEscapes(body) {
65067
- return body.replace(/\\(.)/gu, (_m, ch) => {
65068
- switch (ch) {
65069
- case "n":
65070
- return "\n";
65071
- case "t":
65072
- return " ";
65073
- case "b":
65074
- return "\b";
65075
- case "f":
65076
- return "\f";
65077
- default:
65078
- return ch;
65079
- }
65080
- });
65081
- }
65082
- function canonicalEscapedName(token) {
65083
- if (token.length < 2 || !token.startsWith("'") || !token.endsWith("'"))
65084
- return token;
65085
- return "'" + decodeEscapes(token.slice(1, -1)) + "'";
65086
- }
65087
- function decodeUnrestrictedName(token) {
65088
- if (token.length >= 2 && token.startsWith("'") && token.endsWith("'")) {
65089
- return decodeEscapes(token.slice(1, -1));
65090
- }
65091
- return token;
65092
- }
65093
- var BARE_ID = /^[_a-zA-Z]\w*$/u;
65094
- function encodeUnrestrictedName(value) {
65095
- const raw = value.length >= 2 && value.startsWith("'") && value.endsWith("'") ? decodeUnrestrictedName(value) : value;
65096
- if (BARE_ID.test(raw))
65097
- return raw;
65098
- const escaped = raw.replace(/\r\n?/gu, "\n").replace(/[\\']/gu, (ch) => `\\${ch}`).replace(/\n/gu, "\\n").replace(/\t/gu, "\\t").replace(/[\f]/gu, "\\f").replace(/[\b]/gu, "\\b");
65099
- return `'${escaped}'`;
65100
- }
65101
-
65102
65569
  // ../language-server/out/src/services/rename-provider.js
65103
65570
  var SysmlRenameProvider = class extends DefaultRenameProvider {
65104
65571
  langiumDocuments;
@@ -65228,7 +65695,7 @@ var SysmlCodeActionProvider = class {
65228
65695
  }
65229
65696
  });
65230
65697
  }
65231
- if (code === "RES001") {
65698
+ if (code === "RES001" && !(typeof diagnostic.data === "object" && diagnostic.data !== null && diagnostic.data.featurePathSegment === true)) {
65232
65699
  const start = diagnostic.range.start;
65233
65700
  const end = diagnostic.range.end;
65234
65701
  const name = document.textDocument.getText({ start, end });
@@ -66039,7 +66506,7 @@ function multiplicityAnchor(node) {
66039
66506
  function allAstNodes(root3) {
66040
66507
  return [root3, ...ast_utils_exports.streamAllContents(root3).toArray()];
66041
66508
  }
66042
- function lastSegment2(name) {
66509
+ function lastSegment3(name) {
66043
66510
  const idx = name.lastIndexOf("::");
66044
66511
  return (idx >= 0 ? name.slice(idx + 2) : name).replace(/^'(.*)'$/u, "$1");
66045
66512
  }
@@ -66062,7 +66529,7 @@ function typeAnchor(node, refText) {
66062
66529
  const cst = node.$cstNode;
66063
66530
  if (!cst)
66064
66531
  return void 0;
66065
- const target = lastSegment2(refText);
66532
+ const target = lastSegment3(refText);
66066
66533
  const leaves = cst_utils_exports.flattenCst(cst).toArray();
66067
66534
  for (let index = leaves.length - 1; index >= 0; index--) {
66068
66535
  const leaf = leaves[index];
@@ -66476,7 +66943,7 @@ function indexByName(root3, type) {
66476
66943
  });
66477
66944
  return map3;
66478
66945
  }
66479
- function lastSegment3(path10) {
66946
+ function lastSegment4(path10) {
66480
66947
  if (!path10)
66481
66948
  return void 0;
66482
66949
  return path10.split(/::|\./).pop();
@@ -66495,17 +66962,6 @@ function qualifiedNameOf2(node) {
66495
66962
  function isDiagramAnchor(node) {
66496
66963
  return isPackage(node) || isPartDecl(node) || isStateDecl(node) || isExhibitStateDecl(node) || isActionDecl(node) || isOccurrenceDecl(node) || isUseCaseDecl(node) || isVerificationCaseDecl(node);
66497
66964
  }
66498
- function hasDiagrammableContent(root3) {
66499
- let found = false;
66500
- walkAst(root3, (n) => {
66501
- if (found)
66502
- return;
66503
- const name = n.name;
66504
- if (typeof name === "string" && name.length > 0)
66505
- found = true;
66506
- });
66507
- return found;
66508
- }
66509
66965
  function naturalKindFor(node) {
66510
66966
  if (node.isDef)
66511
66967
  return void 0;
@@ -66552,20 +67008,6 @@ var SysmlCodeLensProvider = class {
66552
67008
  return void 0;
66553
67009
  const lenses = [];
66554
67010
  const uri = document.uri.toString();
66555
- if (hasDiagrammableContent(root3)) {
66556
- const firstLine = {
66557
- start: { line: 0, character: 0 },
66558
- end: { line: 0, character: 0 }
66559
- };
66560
- lenses.push({
66561
- range: firstLine,
66562
- command: {
66563
- title: "$(graph) Show all diagrams",
66564
- command: "sysml.preview.showDiagram",
66565
- arguments: [uri]
66566
- }
66567
- });
66568
- }
66569
67011
  const requirements = indexByName(root3, "RequirementDecl");
66570
67012
  const parts = indexByName(root3, "PartDecl");
66571
67013
  walkAst(root3, (node) => {
@@ -66574,7 +67016,7 @@ var SysmlCodeLensProvider = class {
66574
67016
  return;
66575
67017
  const range = cst.range;
66576
67018
  if (isSatisfyStmt(node)) {
66577
- const reqName = lastSegment3(node.target);
67019
+ const reqName = lastSegment4(node.target);
66578
67020
  const req = reqName ? requirements.get(reqName) : void 0;
66579
67021
  if (req) {
66580
67022
  const bound = bindingName(node.by);
@@ -66677,11 +67119,24 @@ var SysmlDocumentHighlightProvider = class {
66677
67119
  var import_vscode_languageserver22 = __toESM(require_main4(), 1);
66678
67120
  var SysmlDefinitionProvider = class extends DefaultDefinitionProvider {
66679
67121
  indexManager;
67122
+ featurePaths;
66680
67123
  constructor(services) {
66681
67124
  super(services);
66682
67125
  this.indexManager = services.shared.workspace.IndexManager;
67126
+ this.featurePaths = new FeaturePathResolver(services);
66683
67127
  }
66684
67128
  collectLocationLinks(sourceCstNode, params) {
67129
+ if (isPathExpr(sourceCstNode.astNode)) {
67130
+ const resolution = this.featurePaths.resolve(sourceCstNode.astNode);
67131
+ const segment = resolution.segments.find((candidate) => candidate.cst.offset <= sourceCstNode.offset && candidate.cst.end >= sourceCstNode.end);
67132
+ if (segment?.description) {
67133
+ const link2 = this.linkFromDescription(segment.description, segment.cst);
67134
+ if (link2)
67135
+ return [link2];
67136
+ }
67137
+ if (segment)
67138
+ return void 0;
67139
+ }
66685
67140
  const referenced = this.references.findDeclaration(sourceCstNode);
66686
67141
  if (referenced && isAliasDecl(referenced)) {
66687
67142
  const followed = this.resolveAliasTarget(referenced);
@@ -66816,7 +67271,7 @@ var SysmlDeclarationProvider = class {
66816
67271
 
66817
67272
  // ../language-server/out/src/services/references-provider.js
66818
67273
  var import_vscode_languageserver24 = __toESM(require_main4(), 1);
66819
- function lastSegment4(qualified) {
67274
+ function lastSegment5(qualified) {
66820
67275
  return qualified.split(/::|\./u).pop() ?? qualified;
66821
67276
  }
66822
67277
  function locationKey(uri, cst) {
@@ -66838,7 +67293,7 @@ var SysmlReferencesProvider = class extends DefaultReferencesProvider {
66838
67293
  const targetNames = this.namesOf(targetNode);
66839
67294
  if (targetNames.size === 0)
66840
67295
  return base;
66841
- const targetSimpleNames = new Set([...targetNames].map(lastSegment4));
67296
+ const targetSimpleNames = new Set([...targetNames].map(lastSegment5));
66842
67297
  const seen = /* @__PURE__ */ new Set();
66843
67298
  const out = [];
66844
67299
  for (const location of base) {
@@ -66880,7 +67335,7 @@ var SysmlReferencesProvider = class extends DefaultReferencesProvider {
66880
67335
  }
66881
67336
  const names = this.namesOf(targetNode);
66882
67337
  if (names.size > 0) {
66883
- const simpleNames = new Set([...names].map(lastSegment4));
67338
+ const simpleNames = new Set([...names].map(lastSegment5));
66884
67339
  for (const doc of this.langiumDocuments.all) {
66885
67340
  const root3 = doc.parseResult?.value;
66886
67341
  if (!root3)
@@ -66919,7 +67374,7 @@ var SysmlReferencesProvider = class extends DefaultReferencesProvider {
66919
67374
  resolveByName(text) {
66920
67375
  if (!text)
66921
67376
  return void 0;
66922
- const simple = lastSegment4(text);
67377
+ const simple = lastSegment5(text);
66923
67378
  const all = this.indexManager.allElements().toArray();
66924
67379
  return all.find((d) => d.name === text)?.node ?? all.find((d) => d.name === simple)?.node;
66925
67380
  }
@@ -68439,7 +68894,7 @@ async function runValidation(command) {
68439
68894
  }
68440
68895
 
68441
68896
  // src/main.ts
68442
- var VERSION2 = true ? "0.11.0" : "dev";
68897
+ var VERSION2 = true ? "0.14.2" : "dev";
68443
68898
  async function main(argv) {
68444
68899
  const command = parseArgs(argv);
68445
68900
  if (command.kind === "help") {