sysml-v2-lsp 0.36.0 → 0.37.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.
@@ -20332,6 +20332,7 @@ __export(util_exports, {
20332
20332
  required: () => required,
20333
20333
  safeExtend: () => safeExtend,
20334
20334
  shallowClone: () => shallowClone,
20335
+ sizeCaps: () => sizeCaps,
20335
20336
  slugify: () => slugify,
20336
20337
  stringifyPrimitive: () => stringifyPrimitive,
20337
20338
  toZod: () => toZod,
@@ -20851,6 +20852,18 @@ function prefixIssues(path, issues) {
20851
20852
  function unwrapMessage(message) {
20852
20853
  return typeof message === "string" ? message : message?.message;
20853
20854
  }
20855
+ function sizeCaps(defChecks) {
20856
+ const caps = [];
20857
+ for (const ch of defChecks ?? []) {
20858
+ const d = ch._zod.def;
20859
+ if (!/_(length|size)$|_equals$/.test(d.check))
20860
+ break;
20861
+ const max = d.maximum ?? d.length ?? d.size;
20862
+ if (max >= 0)
20863
+ caps.push([max, ch]);
20864
+ }
20865
+ return caps;
20866
+ }
20854
20867
  function attachSchema(issues, start, inst) {
20855
20868
  var _a3;
20856
20869
  for (let i = start; i < issues.length; i++) {
@@ -22271,7 +22284,7 @@ ${content.join("\n")}
22271
22284
  var version = {
22272
22285
  major: 4,
22273
22286
  minor: 6,
22274
- patch: 5
22287
+ patch: 6
22275
22288
  };
22276
22289
 
22277
22290
  // node_modules/zod/v4/core/schemas.js
@@ -23027,6 +23040,31 @@ var $ZodDate = /* @__PURE__ */ $constructor("$ZodDate", (inst, def) => {
23027
23040
  return payload;
23028
23041
  };
23029
23042
  });
23043
+ function capSize(inst, size) {
23044
+ const caps = sizeCaps(inst._zod.def.checks);
23045
+ if (!caps.length)
23046
+ return;
23047
+ const cap = Math.min(...caps.map((c) => c[0]));
23048
+ const parse4 = inst._zod.parse;
23049
+ inst._zod.parse = (payload, ctx2) => {
23050
+ const n2 = size(payload.value);
23051
+ if (n2 > cap && !ctx2?.skipChecks && ctx2?.direction !== "backward") {
23052
+ for (const [max, ch] of sizeCaps(inst._zod.def.checks)) {
23053
+ if (n2 > max && ch._zod.def.when(payload)) {
23054
+ const start = payload.issues.length;
23055
+ ch._zod.check(payload);
23056
+ payload.issues[start].continue = false;
23057
+ attachSchema(payload.issues, start, inst);
23058
+ return payload;
23059
+ }
23060
+ }
23061
+ }
23062
+ return parse4(payload, ctx2);
23063
+ };
23064
+ }
23065
+ var arraySize = (input2) => Array.isArray(input2) ? input2.length : -1;
23066
+ var mapSize = (input2) => input2 instanceof Map ? input2.size : -1;
23067
+ var setSize = (input2) => input2 instanceof Set ? input2.size : -1;
23030
23068
  function handleArrayResult(result, final, index2) {
23031
23069
  if (result.issues.length) {
23032
23070
  final.issues.push(...prefixIssues(index2, result.issues));
@@ -23070,6 +23108,7 @@ var $ZodArray = /* @__PURE__ */ $constructor("$ZodArray", (inst, def) => {
23070
23108
  }
23071
23109
  return payload;
23072
23110
  };
23111
+ capSize(inst, arraySize);
23073
23112
  });
23074
23113
  function handlePropertyResult(result, final, key, input2, optin, optout) {
23075
23114
  const isPresent = key in input2;
@@ -24026,6 +24065,7 @@ var $ZodMap = /* @__PURE__ */ $constructor("$ZodMap", (inst, def) => {
24026
24065
  return Promise.all(proms).then(() => payload);
24027
24066
  return payload;
24028
24067
  };
24068
+ capSize(inst, mapSize);
24029
24069
  });
24030
24070
  function handleMapResult(keyResult, valueResult, final, key, input2, inst, ctx2) {
24031
24071
  if (keyResult.issues.length) {
@@ -24092,6 +24132,7 @@ var $ZodSet = /* @__PURE__ */ $constructor("$ZodSet", (inst, def) => {
24092
24132
  return Promise.all(proms).then(() => payload);
24093
24133
  return payload;
24094
24134
  };
24135
+ capSize(inst, setSize);
24095
24136
  });
24096
24137
  function handleSetResult(result, final) {
24097
24138
  if (result.issues.length) {
@@ -33622,9 +33663,15 @@ function generateNullableCheck(doc, ctx2, schema, accessor, buildsValue = true)
33622
33663
  doc.write(`}`);
33623
33664
  return outputVar;
33624
33665
  }
33666
+ function generateSizeGate(doc, schema, size) {
33667
+ for (const [max, check2] of sizeCaps(schema._zod.def.checks)) {
33668
+ doc.write(`if (${size} > ${numericOperand(max, check2._zod.def.check)}) return INVALID;`);
33669
+ }
33670
+ }
33625
33671
  function generateArrayCheck(doc, ctx2, schema, accessor, buildsValue = true) {
33626
33672
  const def = schema._zod.def;
33627
33673
  doc.write(`if (!Array.isArray(${accessor})) return INVALID;`);
33674
+ generateSizeGate(doc, schema, `${accessor}.length`);
33628
33675
  const outputVar = buildsValue ? newVar(ctx2) : null;
33629
33676
  const iVar = newVar(ctx2);
33630
33677
  const elemVar = newVar(ctx2);
@@ -34024,6 +34071,7 @@ function literalPropertyKey(ctx2, key) {
34024
34071
  function generateMapCheck(doc, ctx2, schema, accessor) {
34025
34072
  const def = schema._zod.def;
34026
34073
  doc.write(`if (!(${accessor} instanceof Map)) return INVALID;`);
34074
+ generateSizeGate(doc, schema, `${accessor}.size`);
34027
34075
  const outputVar = newVar(ctx2);
34028
34076
  const kVar = newVar(ctx2);
34029
34077
  const valVar = newVar(ctx2);
@@ -34040,6 +34088,7 @@ function generateMapCheck(doc, ctx2, schema, accessor) {
34040
34088
  function generateSetCheck(doc, ctx2, schema, accessor) {
34041
34089
  const def = schema._zod.def;
34042
34090
  doc.write(`if (!(${accessor} instanceof Set)) return INVALID;`);
34091
+ generateSizeGate(doc, schema, `${accessor}.size`);
34043
34092
  const outputVar = newVar(ctx2);
34044
34093
  const valVar = newVar(ctx2);
34045
34094
  doc.write(`const ${outputVar} = new Set();`);
@@ -158824,18 +158873,71 @@ var SysMLErrorListener = class extends BaseErrorListener {
158824
158873
  }
158825
158874
  };
158826
158875
 
158876
+ // server/src/parser/positionUtils.ts
158877
+ function normalizeUtf16Columns(text, tokens, errors) {
158878
+ if (!/[\uD800-\uDBFF][\uDC00-\uDFFF]/.test(text)) return;
158879
+ const columns = /* @__PURE__ */ new Map();
158880
+ const lines = text.split("\n");
158881
+ for (let line = 0; line < lines.length; line++) {
158882
+ if (!/[\uD800-\uDBFF][\uDC00-\uDFFF]/.test(lines[line])) continue;
158883
+ const offsets = [0];
158884
+ for (const character of lines[line]) offsets.push(offsets[offsets.length - 1] + character.length);
158885
+ columns.set(line, offsets);
158886
+ }
158887
+ for (const token of tokens) {
158888
+ token.column = columns.get(token.line - 1)?.[token.column] ?? token.column;
158889
+ }
158890
+ for (const error62 of errors) {
158891
+ error62.column = columns.get(error62.line)?.[error62.column] ?? error62.column;
158892
+ }
158893
+ }
158894
+ function tokenToPosition(token) {
158895
+ return {
158896
+ line: (token.line ?? 1) - 1,
158897
+ character: token.column ?? 0
158898
+ };
158899
+ }
158900
+ function tokenToRange(token) {
158901
+ const start = tokenToPosition(token);
158902
+ const length = token.text?.length ?? 1;
158903
+ return {
158904
+ start,
158905
+ end: { line: start.line, character: start.character + length }
158906
+ };
158907
+ }
158908
+ function contextToRange(ctx2) {
158909
+ const startToken = ctx2.start;
158910
+ const stopToken = ctx2.stop ?? ctx2.start;
158911
+ if (!startToken) {
158912
+ return { start: { line: 0, character: 0 }, end: { line: 0, character: 0 } };
158913
+ }
158914
+ const start = {
158915
+ line: (startToken.line ?? 1) - 1,
158916
+ character: startToken.column ?? 0
158917
+ };
158918
+ const end = stopToken ? {
158919
+ line: (stopToken.line ?? 1) - 1,
158920
+ character: (stopToken.column ?? 0) + (stopToken.text?.length ?? 1)
158921
+ } : { line: start.line, character: start.character + 1 };
158922
+ return { start, end };
158923
+ }
158924
+
158827
158925
  // server/src/parser/parseDocument.ts
158926
+ function withUtf16Columns(text, result) {
158927
+ normalizeUtf16Columns(text, result.tokenStream.getTokens(), result.errors);
158928
+ return result;
158929
+ }
158828
158930
  function parseDocument(text) {
158829
158931
  const result = parseDocumentCore(text);
158830
158932
  if (result.errors.length > 0 && hasStaleDfaStates()) {
158831
158933
  markDfaNotPreSeeded();
158832
158934
  clearAllDFAStates();
158833
- return parseDocumentLL(text, result.lexer, result.tokenStream);
158935
+ return withUtf16Columns(text, parseDocumentLL(text, result.lexer, result.tokenStream));
158834
158936
  }
158835
158937
  if (isDfaPreSeeded()) {
158836
158938
  markDfaNotPreSeeded();
158837
158939
  }
158838
- return result;
158940
+ return withUtf16Columns(text, result);
158839
158941
  }
158840
158942
  function parseDocumentCore(text) {
158841
158943
  const inputStream = CharStream.fromString(text);
@@ -158924,10 +159026,152 @@ var _batchDefaultStrategy = new DefaultErrorStrategy();
158924
159026
  // server/src/providers/semanticValidator.ts
158925
159027
  var import_node = __toESM(require_node3());
158926
159028
 
159029
+ // server/src/utils/sysmlKeywords.ts
159030
+ var SYSML_KEYWORDS_ARRAY = SysMLv2Lexer.literalNames.filter((n2) => n2 != null).map((n2) => n2.replace(/^'|'$/g, "")).filter((n2) => /^[a-z]+$/.test(n2)).sort();
159031
+ var SYSML_KEYWORDS = new Set(SYSML_KEYWORDS_ARRAY);
159032
+
158927
159033
  // server/src/utils/identUtils.ts
159034
+ function isIdentStart(c) {
159035
+ return c >= 65 && c <= 90 || c >= 97 && c <= 122 || c === 95;
159036
+ }
158928
159037
  function isIdentPart(c) {
158929
159038
  return c >= 65 && c <= 90 || c >= 97 && c <= 122 || c >= 48 && c <= 57 || c === 95;
158930
159039
  }
159040
+ var ESCAPES = {
159041
+ b: "\b",
159042
+ t: " ",
159043
+ n: "\n",
159044
+ f: "\f",
159045
+ r: "\r",
159046
+ "'": "'",
159047
+ '"': '"',
159048
+ "\\": "\\"
159049
+ };
159050
+ function unquoteName(text) {
159051
+ if (!text.startsWith("'") || !text.endsWith("'")) return text;
159052
+ return text.slice(1, -1).replace(/\\([btnfr'"\\])/g, (_, ch) => ESCAPES[ch]);
159053
+ }
159054
+ function quoteName(name) {
159055
+ if (/^[A-Za-z_][A-Za-z_0-9]*$/.test(name) && !SYSML_KEYWORDS.has(name)) return name;
159056
+ const escaped = name.replace(/[\\'\b\t\n\f\r]/g, (ch) => {
159057
+ const entry = Object.entries(ESCAPES).find(([, value]) => value === ch);
159058
+ return `\\${entry[0]}`;
159059
+ });
159060
+ return `'${escaped}'`;
159061
+ }
159062
+ function splitQualifiedName(text) {
159063
+ const parts = [];
159064
+ let start = 0;
159065
+ let quoted = false;
159066
+ for (let i = 0; i < text.length; i++) {
159067
+ if (quoted && text[i] === "\\") {
159068
+ i++;
159069
+ continue;
159070
+ }
159071
+ if (text[i] === "'" && (quoted || i === start)) quoted = !quoted;
159072
+ if (!quoted && text.startsWith("::", i)) {
159073
+ parts.push(unquoteName(text.slice(start, i).trim()));
159074
+ start = i + 2;
159075
+ i++;
159076
+ }
159077
+ }
159078
+ parts.push(unquoteName(text.slice(start).trim()));
159079
+ return parts;
159080
+ }
159081
+ function joinQualifiedName(parts) {
159082
+ return parts.map((part) => /::|['\\\r\n\t\b\f]/.test(part) ? quoteName(part) : part).join("::");
159083
+ }
159084
+ function readNameAt(text, start, allowIncomplete = false) {
159085
+ if (text[start] === "'") {
159086
+ let end2 = start + 1;
159087
+ while (end2 < text.length && text[end2] !== "'") {
159088
+ if (text[end2] === "\r" || text[end2] === "\n") return void 0;
159089
+ if (text[end2] === "\\") {
159090
+ if (!Object.hasOwn(ESCAPES, text[end2 + 1])) return void 0;
159091
+ end2++;
159092
+ }
159093
+ end2++;
159094
+ }
159095
+ if (end2 >= text.length) {
159096
+ return allowIncomplete ? { name: unquoteName(`${text.slice(start)}'`), start, end: text.length } : void 0;
159097
+ }
159098
+ if (end2 === start + 1 && !allowIncomplete) return void 0;
159099
+ return { name: unquoteName(text.slice(start, end2 + 1)), start, end: end2 + 1 };
159100
+ }
159101
+ if (!isIdentStart(text.charCodeAt(start))) return void 0;
159102
+ let end = start + 1;
159103
+ while (end < text.length && isIdentPart(text.charCodeAt(end))) end++;
159104
+ return { name: text.slice(start, end), start, end };
159105
+ }
159106
+ function readQualifiedNameAt(text, start, allowIncomplete = false) {
159107
+ const first = readNameAt(text, start, allowIncomplete);
159108
+ if (!first) return void 0;
159109
+ const segments = [first];
159110
+ let end = first.end;
159111
+ while (end < text.length) {
159112
+ let next = end;
159113
+ while (/\s/.test(text[next] ?? "") && next < text.length) next++;
159114
+ if (!text.startsWith("::", next)) break;
159115
+ next += 2;
159116
+ while (/\s/.test(text[next] ?? "") && next < text.length) next++;
159117
+ const segment = readNameAt(text, next, allowIncomplete);
159118
+ if (!segment) break;
159119
+ segments.push(segment);
159120
+ end = segment.end;
159121
+ }
159122
+ return { name: joinQualifiedName(segments.map((s) => s.name)), start, end, segments };
159123
+ }
159124
+ function* scanQualifiedNames(text, allowIncomplete = false) {
159125
+ let i = 0;
159126
+ while (i < text.length) {
159127
+ if (text.startsWith("//", i)) {
159128
+ const end = text.indexOf("\n", i + 2);
159129
+ i = end < 0 ? text.length : end + 1;
159130
+ } else if (text.startsWith("/*", i)) {
159131
+ const end = text.indexOf("*/", i + 2);
159132
+ i = end < 0 ? text.length : end + 2;
159133
+ } else if (text[i] === '"') {
159134
+ i++;
159135
+ while (i < text.length && text[i] !== '"') i += text[i] === "\\" ? 2 : 1;
159136
+ i++;
159137
+ } else if (/\d/.test(text[i]) || text[i] === "." && /\d/.test(text[i + 1] ?? "")) {
159138
+ const number4 = text.slice(i).match(/^(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?/);
159139
+ i += number4[0].length;
159140
+ } else {
159141
+ const name = readQualifiedNameAt(text, i, allowIncomplete);
159142
+ if (name) {
159143
+ yield name;
159144
+ i = name.end;
159145
+ } else if (text[i] === "'") {
159146
+ i++;
159147
+ while (i < text.length && text[i] !== "'" && text[i] !== "\n") {
159148
+ i += text[i] === "\\" ? 2 : 1;
159149
+ }
159150
+ if (text[i] === "'") i++;
159151
+ } else {
159152
+ i++;
159153
+ }
159154
+ }
159155
+ }
159156
+ }
159157
+ function* scanFeaturePaths(text) {
159158
+ const names = [...scanQualifiedNames(text)];
159159
+ for (let i = 0; i < names.length; i++) {
159160
+ const first = names[i];
159161
+ const parts = [first.name];
159162
+ const qualifiedNames = [first];
159163
+ let end = first.end;
159164
+ while (i + 1 < names.length && /^\s*\.\s*$/.test(text.slice(end, names[i + 1].start))) {
159165
+ parts.push(names[++i].name);
159166
+ qualifiedNames.push(names[i]);
159167
+ end = names[i].end;
159168
+ }
159169
+ yield { name: parts.join("."), start: first.start, end, qualifiedNames, parts: parts.map((part) => {
159170
+ const segments = splitQualifiedName(part);
159171
+ return segments.length === 1 ? segments[0] : part;
159172
+ }) };
159173
+ }
159174
+ }
158931
159175
  function stripComments(text) {
158932
159176
  return text.replace(/\/\*[\s\S]*?\*\//g, (m2) => m2.replace(/[^\n]/g, " ")).replace(/\/\/[^\n]*/g, (m2) => " ".repeat(m2.length));
158933
159177
  }
@@ -158937,10 +159181,12 @@ var index;
158937
159181
  var typeIndex;
158938
159182
  function resolveLibraryType(name) {
158939
159183
  if (!typeIndex) return void 0;
159184
+ const segments = splitQualifiedName(name);
159185
+ name = segments.length === 1 ? segments[0] : joinQualifiedName(segments);
158940
159186
  const exact = typeIndex.get(name);
158941
159187
  if (exact) return exact;
158942
- if (name.includes("::")) {
158943
- const member = name.split("::").pop();
159188
+ if (segments.length > 1) {
159189
+ const member = segments[segments.length - 1];
158944
159190
  return typeIndex.get(member);
158945
159191
  }
158946
159192
  return void 0;
@@ -159144,6 +159390,10 @@ var NamespaceResolver = class {
159144
159390
  resolveNameFrom(symbol2, name, indexes) {
159145
159391
  return this.resolveQualifiedNameFrom(ownerKeyOf(symbol2, indexes.byId), name, indexes);
159146
159392
  }
159393
+ /** Resolve an editor reference within its enclosing namespace, including the root. */
159394
+ resolveNameIn(namespace, name, indexes) {
159395
+ return this.resolveQualifiedNameFrom(namespace ? namespaceKeyOf(namespace) : "", name, indexes);
159396
+ }
159147
159397
  /**
159148
159398
  * Resolve a (possibly qualified) name to its symbol per §7.5.1, searching
159149
159399
  * outward from namespace `start` and its enclosing namespaces (its own resolved
@@ -159155,7 +159405,7 @@ var NamespaceResolver = class {
159155
159405
  * its own enclosing package already imported, per §7.5.1/§7.5.3).
159156
159406
  */
159157
159407
  resolveQualifiedNameFrom(start, name, indexes) {
159158
- const [first, ...rest] = name.split("::");
159408
+ const [first, ...rest] = splitQualifiedName(name);
159159
159409
  let resolved;
159160
159410
  for (const ancestor of this.namespaceAncestorsOf(start, indexes)) {
159161
159411
  const candidates = this.getResolvedMembers(ancestor, indexes).get(first);
@@ -159322,6 +159572,9 @@ var NamespaceResolver = class {
159322
159572
  };
159323
159573
  for (const owned of indexes.byParent.get(namespace) ?? []) {
159324
159574
  addMember(owned.name, { symbol: owned, visibility: owned.visibility ?? "public" });
159575
+ if (owned.shortName) {
159576
+ addMember(owned.shortName, { symbol: owned, visibility: owned.visibility ?? "public" });
159577
+ }
159325
159578
  }
159326
159579
  perIndexesCache.set(namespace, members2);
159327
159580
  const owner = typeof namespace === "string" ? indexes.byQualifiedName.get(namespace) : namespace;
@@ -159357,13 +159610,17 @@ var NamespaceResolver = class {
159357
159610
  switch (imp.kind) {
159358
159611
  case "membership": {
159359
159612
  const target = this.resolveQualifiedNameFrom(importingNamespace, imp.target, indexes);
159360
- if (target) addMember(target.name, { symbol: target, visibility: imp.visibility });
159613
+ if (target) {
159614
+ addMember(target.name, { symbol: target, visibility: imp.visibility });
159615
+ if (target.shortName) addMember(target.shortName, { symbol: target, visibility: imp.visibility });
159616
+ }
159361
159617
  break;
159362
159618
  }
159363
159619
  case "membership-deep": {
159364
159620
  const target = this.resolveQualifiedNameFrom(importingNamespace, imp.target, indexes);
159365
159621
  if (target) {
159366
159622
  addMember(target.name, { symbol: target, visibility: imp.visibility });
159623
+ if (target.shortName) addMember(target.shortName, { symbol: target, visibility: imp.visibility });
159367
159624
  this.importVisibleMembers(namespaceKeyOf(target), imp.visibility, indexes, addMember, true);
159368
159625
  }
159369
159626
  break;
@@ -159419,42 +159676,6 @@ var NamespaceResolver = class {
159419
159676
  }
159420
159677
  };
159421
159678
 
159422
- // server/src/parser/positionUtils.ts
159423
- function tokenToPosition(token) {
159424
- return {
159425
- line: (token.line ?? 1) - 1,
159426
- character: token.column ?? 0
159427
- };
159428
- }
159429
- function tokenToRange(token) {
159430
- const start = tokenToPosition(token);
159431
- const length = token.text?.length ?? 1;
159432
- return {
159433
- start,
159434
- end: { line: start.line, character: start.character + length }
159435
- };
159436
- }
159437
- function contextToRange(ctx2) {
159438
- const startToken = ctx2.start;
159439
- const stopToken = ctx2.stop ?? ctx2.start;
159440
- if (!startToken) {
159441
- return { start: { line: 0, character: 0 }, end: { line: 0, character: 0 } };
159442
- }
159443
- const start = {
159444
- line: (startToken.line ?? 1) - 1,
159445
- character: startToken.column ?? 0
159446
- };
159447
- const end = stopToken ? {
159448
- line: (stopToken.line ?? 1) - 1,
159449
- character: (stopToken.column ?? 0) + (stopToken.text?.length ?? 1)
159450
- } : { line: start.line, character: start.character + 1 };
159451
- return { start, end };
159452
- }
159453
-
159454
- // server/src/utils/sysmlKeywords.ts
159455
- var SYSML_KEYWORDS_ARRAY = SysMLv2Lexer.literalNames.filter((n2) => n2 != null).map((n2) => n2.replace(/^'|'$/g, "")).filter((n2) => /^[a-z]+$/.test(n2)).sort();
159456
- var SYSML_KEYWORDS = new Set(SYSML_KEYWORDS_ARRAY);
159457
-
159458
159679
  // server/src/utils/names.ts
159459
159680
  var BASIC_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
159460
159681
  function escapeName(name) {
@@ -160068,7 +160289,7 @@ var RE_SPEC_WITH_SUBSETS = /(?:specializes|subsets|:>|:>>)\s*('[^']+'|[A-Za-z_]\
160068
160289
  var RE_DEFINED_BY = /definedby\s*([A-Za-z_]\w*(?:::\w+)*(?:\s*,\s*[A-Za-z_]\w*(?:::\w+)*)*)/;
160069
160290
  var MAX_RULE_SEARCH_DEPTH = 6;
160070
160291
  var RE_TYPING = /:(?![:>])\s*('[^']+'|[A-Za-z_]\w*(?:::\w+)*)/;
160071
- var RE_QUOTED_NAME = /'([^']+)'/;
160292
+ var RE_QUOTED_NAME = /^\s*(?:\$::)?(?:(?:[A-Za-z_]\w*|'\d+')::)*'(\d+)'/;
160072
160293
  var RE_IDENT_START = /^([A-Za-z_]\w*(?:::\w+)*)/;
160073
160294
  var SymbolTable = class {
160074
160295
  /** All symbols indexed by qualified name */
@@ -160135,7 +160356,12 @@ var SymbolTable = class {
160135
160356
  * Find a symbol by name (simple name, not qualified).
160136
160357
  */
160137
160358
  findByName(name) {
160138
- return this.symbolsByName.get(name) ?? [];
160359
+ const exact = this.symbolsByName.get(name);
160360
+ if (exact) return exact;
160361
+ const segments = splitQualifiedName(name);
160362
+ if (segments.length === 1) return this.symbolsByName.get(segments[0]) ?? [];
160363
+ const qualified = this.getSymbol(joinQualifiedName(segments));
160364
+ return qualified ? [qualified] : [];
160139
160365
  }
160140
160366
  /**
160141
160367
  * Find all symbols in a given URI.
@@ -160642,7 +160868,7 @@ var SymbolTable = class {
160642
160868
  const anonymous = !declaredName;
160643
160869
  const name = declaredName ?? "";
160644
160870
  const shortName = transition || isFlowUsage(kind) && !declaredName ? void 0 : this.extractShortName(ctx2);
160645
- const qualifiedName = anonymous || owner && owner.qualifiedName === void 0 ? void 0 : owner ? `${owner.qualifiedName}::${name}` : name;
160871
+ const qualifiedName = anonymous || owner && owner.qualifiedName === void 0 ? void 0 : owner ? `${owner.qualifiedName}::${joinQualifiedName([name])}` : joinQualifiedName([name]);
160646
160872
  const selectionRange = anonymous ? ctx2.start ? tokenToRange(ctx2.start) : range : this.extractNameRange(ctx2) ?? range;
160647
160873
  const typeNames = isFlowUsage(kind) ? this.extractFlowTypeNames(ctx2) : transition ? this.extractTransitionTypeNames(ctx2) : this.extractTypeNames(ctx2);
160648
160874
  const specializationNames = this.extractSpecializationNames(ctx2);
@@ -160802,7 +161028,10 @@ var SymbolTable = class {
160802
161028
  }
160803
161029
  /** Remove SysML quoting while retaining qualified and dotted references. */
160804
161030
  cleanTransitionText(text) {
160805
- const cleaned = text.replace(/'([^']+)'/g, "$1").trim();
161031
+ const cleaned = text.replace(
161032
+ /'(?:\\.|[^'\\])*'/g,
161033
+ (name) => joinQualifiedName([unquoteName(name)])
161034
+ ).trim();
160806
161035
  return cleaned || void 0;
160807
161036
  }
160808
161037
  /** Extract explicit first/then successions owned by an action body. */
@@ -160975,8 +161204,8 @@ var SymbolTable = class {
160975
161204
  }
160976
161205
  /** The name of the feature a reference such as `a.b` or `P::a` ends at (`b`, `a`). */
160977
161206
  lastNameSegment(reference) {
160978
- const segment = reference.getText().split(/::|\./).pop();
160979
- return segment ? this.unquoteName(segment) : void 0;
161207
+ const names = [...scanQualifiedNames(reference.getText())];
161208
+ return names.at(-1)?.segments.at(-1)?.name;
160980
161209
  }
160981
161210
  declarationTokens(ctx2) {
160982
161211
  const tokens = [];
@@ -161112,6 +161341,16 @@ var SymbolTable = class {
161112
161341
  * Extract the range of just the name token.
161113
161342
  */
161114
161343
  extractNameRange(ctx2) {
161344
+ if (ctx2.ruleIndex === SysMLv2Parser.RULE_identification || ctx2.ruleIndex === SysMLv2Parser.RULE_featureIdentification) {
161345
+ let name;
161346
+ for (let i = 0; i < ctx2.getChildCount(); i++) {
161347
+ const child = ctx2.getChild(i);
161348
+ if (child instanceof ParserRuleContext && child.ruleIndex === SysMLv2Parser.RULE_name) {
161349
+ name = child;
161350
+ }
161351
+ }
161352
+ if (name) return contextToRange(name);
161353
+ }
161115
161354
  for (let i = 0; i < ctx2.getChildCount(); i++) {
161116
161355
  const child = ctx2.getChild(i);
161117
161356
  if (child instanceof TerminalNode && this.isNameTerminal(child)) {
@@ -161152,7 +161391,7 @@ var SymbolTable = class {
161152
161391
  for (const part of specStr.split(",")) {
161153
161392
  const quoted = quotedName(part);
161154
161393
  if (quoted !== void 0) {
161155
- names.push(quoted);
161394
+ names.push(joinQualifiedName([quoted]));
161156
161395
  continue;
161157
161396
  }
161158
161397
  const m2 = part.trim().match(RE_IDENT_START);
@@ -161175,7 +161414,7 @@ var SymbolTable = class {
161175
161414
  for (const part of afterColon.split(",")) {
161176
161415
  const quoted = quotedName(part);
161177
161416
  if (quoted !== void 0) {
161178
- names.push(quoted);
161417
+ names.push(joinQualifiedName([quoted]));
161179
161418
  continue;
161180
161419
  }
161181
161420
  const m2 = part.trim().match(RE_IDENT_START);
@@ -161186,18 +161425,20 @@ var SymbolTable = class {
161186
161425
  return names;
161187
161426
  }
161188
161427
  /**
161189
- * The declaration tokens before the body, with each lexer STRING token
161428
+ * The declaration tokens before the value or body, with each lexer STRING token
161190
161429
  * replaced by a numbered placeholder (`'0'`, `'1'`, ...), and
161191
161430
  * `quotedName`, which turns a placeholder in a part of that text back into
161192
- * the name. SysML 2.0 section 7.2.2 permits punctuation in unrestricted
161193
- * names (the STRING lexer production), so fallback regexes must never see
161194
- * their `:`, `:>`, `{` or keywords. Documentation is not a name token.
161431
+ * the name, when it ends the qualified name the part starts with. SysML
161432
+ * 2.0 section 7.2.2 permits punctuation in unrestricted names (the STRING
161433
+ * lexer production), so fallback regexes must never see their `:`, `:>`,
161434
+ * `{` or keywords. Documentation is not a name token.
161195
161435
  */
161196
161436
  maskedDeclaration(ctx2) {
161197
161437
  const quoted = [];
161198
- const masked = this.declarationTokens(ctx2).map((token) => {
161438
+ const valueStart = this.findOwnHeaderRule(ctx2, SysMLv2Parser.RULE_valuePart)?.start?.tokenIndex;
161439
+ const masked = this.declarationTokens(ctx2).filter((token) => valueStart === void 0 || token.tokenIndex < valueStart).map((token) => {
161199
161440
  const text = token.text ?? "";
161200
- return token.type === SysMLv2Lexer.STRING ? `'${quoted.push(text.slice(1, -1)) - 1}'` : text;
161441
+ return token.type === SysMLv2Lexer.STRING ? `'${quoted.push(unquoteName(text)) - 1}'` : text;
161201
161442
  }).join("");
161202
161443
  return {
161203
161444
  text: masked,
@@ -161225,7 +161466,7 @@ var SymbolTable = class {
161225
161466
  for (const part of specStr.split(",")) {
161226
161467
  const quoted = quotedName(part);
161227
161468
  if (quoted !== void 0) {
161228
- names.push(quoted);
161469
+ names.push(joinQualifiedName([quoted]));
161229
161470
  continue;
161230
161471
  }
161231
161472
  const m2 = part.trim().match(RE_IDENT_START);
@@ -161254,17 +161495,7 @@ var SymbolTable = class {
161254
161495
  if (!(child instanceof ParserRuleContext)) continue;
161255
161496
  const ri = child.ruleIndex;
161256
161497
  if (extractionRules.has(ri)) {
161257
- const childText = child.getText();
161258
- const stripped = childText.replace(/^(specializes|:>>|:>|:|definedby|subsets|redefines|references|conjugates|disjoints)/i, "");
161259
- for (const part of stripped.split(",")) {
161260
- const qm = part.match(/'([^']+)'/);
161261
- if (qm) {
161262
- names.push(qm[1]);
161263
- } else {
161264
- const m2 = part.match(/([A-Za-z_]\w*(?:::\w+)*)/);
161265
- if (m2) names.push(m2[1]);
161266
- }
161267
- }
161498
+ this.collectQualifiedTypeNames(child, names);
161268
161499
  } else if (
161269
161500
  // Recurse into declaration / part / body wrappers that may
161270
161501
  // contain nested typing rules (but NOT into body rules that
@@ -161277,6 +161508,17 @@ var SymbolTable = class {
161277
161508
  }
161278
161509
  }
161279
161510
  }
161511
+ collectQualifiedTypeNames(ctx2, names) {
161512
+ if (ctx2.ruleIndex === SysMLv2Parser.RULE_qualifiedName) {
161513
+ const name = this.extractTextFromSubtree(ctx2);
161514
+ if (name) names.push(name);
161515
+ return;
161516
+ }
161517
+ for (let i = 0; i < ctx2.getChildCount(); i++) {
161518
+ const child = ctx2.getChild(i);
161519
+ if (child instanceof ParserRuleContext) this.collectQualifiedTypeNames(child, names);
161520
+ }
161521
+ }
161280
161522
  /**
161281
161523
  * Extract documentation owned by this element.
161282
161524
  *
@@ -161437,10 +161679,7 @@ var SymbolTable = class {
161437
161679
  * Returns the text unchanged if not quoted.
161438
161680
  */
161439
161681
  unquoteName(text) {
161440
- if (this.isQuotedName(text)) {
161441
- return text.slice(1, -1);
161442
- }
161443
- return text;
161682
+ return unquoteName(text);
161444
161683
  }
161445
161684
  /**
161446
161685
  * Check if a text is a SysML keyword.
@@ -161728,7 +161967,7 @@ var SymbolTable = class {
161728
161967
  const child = ctx2.getChild(i);
161729
161968
  if (child instanceof TerminalNode) {
161730
161969
  const text = child.symbol.text;
161731
- if (text) parts.push(text);
161970
+ if (text) parts.push(child.symbol.type === SysMLv2Lexer.STRING ? joinQualifiedName([unquoteName(text)]) : text);
161732
161971
  } else if (child instanceof ParserRuleContext) {
161733
161972
  this.collectExposeText(child, parts);
161734
161973
  }
@@ -161790,17 +162029,18 @@ var SymbolTable = class {
161790
162029
  * Extract all text content from a subtree (concatenate terminal nodes).
161791
162030
  */
161792
162031
  extractTextFromSubtree(ctx2) {
162032
+ if (ctx2.ruleIndex === SysMLv2Parser.RULE_name) return unquoteName(ctx2.getText());
161793
162033
  const parts = [];
161794
162034
  for (let i = 0; i < ctx2.getChildCount(); i++) {
161795
162035
  const child = ctx2.getChild(i);
161796
162036
  if (child instanceof TerminalNode) {
161797
162037
  const text = child.symbol.text;
161798
162038
  if (text && this.isNameTerminal(child)) {
161799
- parts.push(this.unquoteName(text));
162039
+ parts.push(joinQualifiedName([this.unquoteName(text)]));
161800
162040
  }
161801
162041
  } else if (child instanceof ParserRuleContext) {
161802
162042
  const sub = this.extractTextFromSubtree(child);
161803
- if (sub) parts.push(sub);
162043
+ if (sub) parts.push(child.ruleIndex === SysMLv2Parser.RULE_name ? joinQualifiedName([sub]) : sub);
161804
162044
  }
161805
162045
  }
161806
162046
  return parts.length > 0 ? parts.join("::") : void 0;
@@ -161916,7 +162156,7 @@ function isISQValueType(name) {
161916
162156
  function resolveTypeName(typeName, symbol2, resolver, indexes, libraryNames) {
161917
162157
  const kwMatch = typeName.match(/^([A-Z][A-Za-z_0-9]*?)(redefines|subsets|references|connect|bind|default|via|accept|send|flow|allocate|assign|decide|merge|join|fork)([A-Z])/);
161918
162158
  const strippedTypeName = kwMatch ? kwMatch[1] : typeName;
161919
- const rootSegment = strippedTypeName.split("::")[0];
162159
+ const rootSegment = splitQualifiedName(strippedTypeName)[0];
161920
162160
  const resolved = resolver.isLocallyVisible(symbol2, strippedTypeName, indexes) || STANDARD_LIBRARY_TYPES.has(strippedTypeName) || STANDARD_LIBRARY_TYPES.has(rootSegment) || libraryNames.has(rootSegment) || isISQValueType(strippedTypeName) || resolveLibraryType(strippedTypeName) !== void 0 || resolveLibraryType(rootSegment) !== void 0 || // Names starting with lowercase are feature references (subsettings
161921
162161
  // via :>), not type references — don't flag them as unresolved types.
161922
162162
  strippedTypeName.charCodeAt(0) >= 97 && strippedTypeName.charCodeAt(0) <= 122;
@@ -163637,19 +163877,19 @@ var SemanticValidator = class _SemanticValidator {
163637
163877
  );
163638
163878
  const defsInScope = targetUri ? defs.filter((def) => def.uri === targetUri) : defs;
163639
163879
  const referencedTypes = new Set(
163640
- symbols.filter((s) => s.kind !== "package" /* Package */).flatMap((s) => s.typeNames)
163880
+ symbols.filter((s) => s.kind !== "package" /* Package */).flatMap((s) => s.typeNames.flatMap((name) => [name, splitQualifiedName(name).at(-1)]))
163641
163881
  );
163642
163882
  for (const s of symbols) {
163643
163883
  if (s.exposeTargets) {
163644
163884
  for (const target of s.exposeTargets) {
163645
- const simpleName = target.replace(/::\*{1,2}$/, "").split("::").pop();
163885
+ const simpleName = splitQualifiedName(target.replace(/::\*{1,2}$/, "")).pop();
163646
163886
  if (simpleName) referencedTypes.add(simpleName);
163647
163887
  }
163648
163888
  }
163649
163889
  }
163650
163890
  const diagnostics = [];
163651
163891
  for (const def of defsInScope) {
163652
- const isReferenced = referencedTypes.has(def.name);
163892
+ const isReferenced = referencedTypes.has(def.name) || def.shortName !== void 0 && referencedTypes.has(def.shortName);
163653
163893
  const hasBaseType = (def.typeNames?.length ?? 0) > 0;
163654
163894
  if (!isReferenced && !hasBaseType) {
163655
163895
  diagnostics.push({
@@ -164075,14 +164315,15 @@ var SemanticValidator = class _SemanticValidator {
164075
164315
  if (!text) return [];
164076
164316
  const diagnostics = [];
164077
164317
  const lines = text.split("\n");
164078
- const re = /\bconnect\s+([A-Za-z_][\w.]*)\s+to\s+([A-Za-z_][\w.]*)/g;
164079
- let m2;
164080
- while ((m2 = re.exec(text)) !== null) {
164081
- const leftPath = m2[1].split(".");
164082
- const rightPath = m2[2].split(".");
164318
+ const paths = [...scanFeaturePaths(text)];
164319
+ for (let i = 0; i + 3 < paths.length; i++) {
164320
+ const [connect, leftEnd, to, rightEnd] = paths.slice(i, i + 4);
164321
+ if (text.slice(connect.start, connect.end) !== "connect" || text.slice(to.start, to.end) !== "to" || !/^\s+$/.test(text.slice(connect.end, leftEnd.start)) || !/^\s+$/.test(text.slice(leftEnd.end, to.start)) || !/^\s+$/.test(text.slice(to.end, rightEnd.start))) continue;
164322
+ const leftPath = [...leftEnd.parts];
164323
+ const rightPath = [...rightEnd.parts];
164083
164324
  const left = leftPath[leftPath.length - 1];
164084
164325
  const right = rightPath[rightPath.length - 1];
164085
- const scope = this.connectorScope(symbolsInUri, this.indexToRange(text, m2.index, 0).start, indexes);
164326
+ const scope = this.connectorScope(symbolsInUri, this.indexToRange(text, connect.start, 0).start, indexes);
164086
164327
  const lSym = this.resolveConnectorEnd(leftPath, scope, indexes);
164087
164328
  const rSym = this.resolveConnectorEnd(rightPath, scope, indexes);
164088
164329
  if (!lSym || !rSym) continue;
@@ -164092,10 +164333,10 @@ var SemanticValidator = class _SemanticValidator {
164092
164333
  if (lType === "~" + rType || rType === "~" + lType) continue;
164093
164334
  if (lType.startsWith("~") && lType.slice(1) === rType) continue;
164094
164335
  if (rType.startsWith("~") && rType.slice(1) === lType) continue;
164095
- const matchLine = text.substring(0, m2.index).split("\n").length - 1;
164336
+ const matchLine = text.substring(0, connect.start).split("\n").length - 1;
164096
164337
  let insideInterfaceDef = false;
164097
- for (let i = matchLine; i >= 0 && i >= matchLine - 30; i--) {
164098
- const line = (lines[i] || "").trim();
164338
+ for (let i2 = matchLine; i2 >= 0 && i2 >= matchLine - 30; i2--) {
164339
+ const line = (lines[i2] || "").trim();
164099
164340
  if (/\binterface\s+def\b/.test(line)) {
164100
164341
  insideInterfaceDef = true;
164101
164342
  break;
@@ -164103,7 +164344,7 @@ var SemanticValidator = class _SemanticValidator {
164103
164344
  if (/^\s*package\b/.test(line)) break;
164104
164345
  }
164105
164346
  if (insideInterfaceDef) continue;
164106
- const precedingText = text.substring(Math.max(0, m2.index - 300), m2.index);
164347
+ const precedingText = text.substring(Math.max(0, connect.start - 300), connect.start);
164107
164348
  if (/\binterface\s+\w[\w']*(:\w[\w']*)?\s*$/m.test(precedingText)) continue;
164108
164349
  const lDefSyms = indexes.byName.get(lType) ?? [];
164109
164350
  const rDefSyms = indexes.byName.get(rType) ?? [];
@@ -164122,14 +164363,14 @@ var SemanticValidator = class _SemanticValidator {
164122
164363
  const hasSharedFeature = rChildren.some((c) => lChildNames.has(c.name));
164123
164364
  if (hasSharedFeature) continue;
164124
164365
  }
164125
- const range = this.indexToRange(text, m2.index, m2[0].length);
164366
+ const range = this.indexToRange(text, connect.start, rightEnd.end - connect.start);
164126
164367
  diagnostics.push({
164127
164368
  severity: import_node.DiagnosticSeverity.Warning,
164128
164369
  range,
164129
164370
  message: `Port compatibility issue: '${left}' (${lType}) is connected to '${right}' (${rType})`,
164130
164371
  source: "sysml",
164131
164372
  code: "incompatible-port-types",
164132
- data: { uri }
164373
+ data: { uri, left, right, leftType: lType }
164133
164374
  });
164134
164375
  }
164135
164376
  return diagnostics;
@@ -164232,15 +164473,11 @@ var SemanticValidator = class _SemanticValidator {
164232
164473
  if (!parent) continue;
164233
164474
  const parentMembers = this.getConstraintScopeMembers(parent, indexes);
164234
164475
  if (parentMembers.length === 0) continue;
164235
- const ignoredRanges = this.getIgnoredBodyRanges(b.body);
164236
- const idRe = /\b([A-Za-z_][\w]*(?:\.[A-Za-z_][\w]*)*)\b/g;
164237
- let im;
164238
- while ((im = idRe.exec(b.body)) !== null) {
164239
- if (this.isIndexInRanges(im.index, ignoredRanges)) continue;
164240
- const expr = im[1];
164476
+ for (const reference of scanFeaturePaths(b.body)) {
164477
+ const expr = reference.name;
164241
164478
  if (this.isConstraintKeyword(expr)) continue;
164242
164479
  if (/^\d/.test(expr)) continue;
164243
- const path = expr.split(".");
164480
+ const path = [...reference.parts];
164244
164481
  const ok = this.resolvePathFromParent(path, parentMembers, indexes);
164245
164482
  if (ok) continue;
164246
164483
  if (path.length === 1) {
@@ -164249,14 +164486,14 @@ var SemanticValidator = class _SemanticValidator {
164249
164486
  continue;
164250
164487
  }
164251
164488
  }
164252
- const absoluteStart = b.bodyOffset + im.index;
164489
+ const absoluteStart = b.bodyOffset + reference.start;
164253
164490
  diagnostics.push({
164254
164491
  severity: import_node.DiagnosticSeverity.Warning,
164255
- range: this.indexToRange(text, absoluteStart, expr.length),
164492
+ range: this.indexToRange(text, absoluteStart, reference.end - reference.start),
164256
164493
  message: `Unresolved constraint reference '${expr}' in scope '${displayName(parent)}'`,
164257
164494
  source: "sysml",
164258
164495
  code: "unresolved-constraint-reference",
164259
- data: { uri }
164496
+ data: { uri, scopeName: parent.name }
164260
164497
  });
164261
164498
  }
164262
164499
  }
@@ -164450,25 +164687,6 @@ var SemanticValidator = class _SemanticValidator {
164450
164687
  isConstraintKeyword(value) {
164451
164688
  return CONSTRAINT_KEYWORDS.has(value);
164452
164689
  }
164453
- getIgnoredBodyRanges(body) {
164454
- const ranges = [];
164455
- const blockRe = /\/\*[\s\S]*?\*\//g;
164456
- let m2;
164457
- while ((m2 = blockRe.exec(body)) !== null) {
164458
- ranges.push({ start: m2.index, end: m2.index + m2[0].length });
164459
- }
164460
- const lineRe = /\/\/[^\n\r]*/g;
164461
- while ((m2 = lineRe.exec(body)) !== null) {
164462
- ranges.push({ start: m2.index, end: m2.index + m2[0].length });
164463
- }
164464
- return ranges;
164465
- }
164466
- isIndexInRanges(index2, ranges) {
164467
- for (const r of ranges) {
164468
- if (index2 >= r.start && index2 < r.end) return true;
164469
- }
164470
- return false;
164471
- }
164472
164690
  hasDocumentationOnlyConstraintBody(body) {
164473
164691
  const trimmed = body.trim();
164474
164692
  if (!trimmed) return false;