sysml-v2-lsp 0.35.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.
@@ -123,30 +123,30 @@
123
123
  Object.defineProperty(exports, "__esModule", { value: true });
124
124
  exports.Message = exports.NotificationType9 = exports.NotificationType8 = exports.NotificationType7 = exports.NotificationType6 = exports.NotificationType5 = exports.NotificationType4 = exports.NotificationType3 = exports.NotificationType2 = exports.NotificationType1 = exports.NotificationType0 = exports.NotificationType = exports.RequestType9 = exports.RequestType8 = exports.RequestType7 = exports.RequestType6 = exports.RequestType5 = exports.RequestType4 = exports.RequestType3 = exports.RequestType2 = exports.RequestType1 = exports.RequestType = exports.RequestType0 = exports.AbstractMessageSignature = exports.ParameterStructures = exports.ResponseError = exports.ErrorCodes = void 0;
125
125
  var is = __importStar(require_is());
126
- var ErrorCodes;
127
- (function(ErrorCodes2) {
128
- ErrorCodes2.ParseError = -32700;
129
- ErrorCodes2.InvalidRequest = -32600;
130
- ErrorCodes2.MethodNotFound = -32601;
131
- ErrorCodes2.InvalidParams = -32602;
132
- ErrorCodes2.InternalError = -32603;
133
- ErrorCodes2.jsonrpcReservedErrorRangeStart = -32099;
134
- ErrorCodes2.serverErrorStart = -32099;
135
- ErrorCodes2.MessageWriteError = -32099;
136
- ErrorCodes2.MessageReadError = -32098;
137
- ErrorCodes2.PendingResponseRejected = -32097;
138
- ErrorCodes2.ConnectionInactive = -32096;
139
- ErrorCodes2.ServerNotInitialized = -32002;
140
- ErrorCodes2.UnknownErrorCode = -32001;
141
- ErrorCodes2.jsonrpcReservedErrorRangeEnd = -32e3;
142
- ErrorCodes2.serverErrorEnd = -32e3;
143
- })(ErrorCodes || (exports.ErrorCodes = ErrorCodes = {}));
144
- var ResponseError = class _ResponseError extends Error {
126
+ var ErrorCodes2;
127
+ (function(ErrorCodes3) {
128
+ ErrorCodes3.ParseError = -32700;
129
+ ErrorCodes3.InvalidRequest = -32600;
130
+ ErrorCodes3.MethodNotFound = -32601;
131
+ ErrorCodes3.InvalidParams = -32602;
132
+ ErrorCodes3.InternalError = -32603;
133
+ ErrorCodes3.jsonrpcReservedErrorRangeStart = -32099;
134
+ ErrorCodes3.serverErrorStart = -32099;
135
+ ErrorCodes3.MessageWriteError = -32099;
136
+ ErrorCodes3.MessageReadError = -32098;
137
+ ErrorCodes3.PendingResponseRejected = -32097;
138
+ ErrorCodes3.ConnectionInactive = -32096;
139
+ ErrorCodes3.ServerNotInitialized = -32002;
140
+ ErrorCodes3.UnknownErrorCode = -32001;
141
+ ErrorCodes3.jsonrpcReservedErrorRangeEnd = -32e3;
142
+ ErrorCodes3.serverErrorEnd = -32e3;
143
+ })(ErrorCodes2 || (exports.ErrorCodes = ErrorCodes2 = {}));
144
+ var ResponseError2 = class _ResponseError extends Error {
145
145
  code;
146
146
  data;
147
147
  constructor(code, message, data) {
148
148
  super(message);
149
- this.code = is.number(code) ? code : ErrorCodes.UnknownErrorCode;
149
+ this.code = is.number(code) ? code : ErrorCodes2.UnknownErrorCode;
150
150
  this.data = data;
151
151
  Object.setPrototypeOf(this, _ResponseError.prototype);
152
152
  }
@@ -161,7 +161,7 @@
161
161
  return result;
162
162
  }
163
163
  };
164
- exports.ResponseError = ResponseError;
164
+ exports.ResponseError = ResponseError2;
165
165
  var ParameterStructures = class _ParameterStructures {
166
166
  kind;
167
167
  /**
@@ -3362,7 +3362,7 @@ ${JSON.stringify(message, null, 4)}`);
3362
3362
  }
3363
3363
  uinteger3.is = is;
3364
3364
  })(uinteger || (uinteger = {}));
3365
- (function(Position4) {
3365
+ (function(Position6) {
3366
3366
  function create(line, character) {
3367
3367
  if (line === Number.MAX_VALUE) {
3368
3368
  line = uinteger.MAX_VALUE;
@@ -3372,14 +3372,14 @@ ${JSON.stringify(message, null, 4)}`);
3372
3372
  }
3373
3373
  return { line, character };
3374
3374
  }
3375
- Position4.create = create;
3375
+ Position6.create = create;
3376
3376
  function is(value) {
3377
3377
  const candidate = value;
3378
3378
  return Is.objectLiteral(candidate) && Is.uinteger(candidate.line) && Is.uinteger(candidate.character);
3379
3379
  }
3380
- Position4.is = is;
3380
+ Position6.is = is;
3381
3381
  })(Position || (Position = {}));
3382
- (function(Range4) {
3382
+ (function(Range8) {
3383
3383
  function create(one, two, three, four) {
3384
3384
  if (Is.uinteger(one) && Is.uinteger(two) && Is.uinteger(three) && Is.uinteger(four)) {
3385
3385
  return { start: Position.create(one, two), end: Position.create(three, four) };
@@ -3389,23 +3389,23 @@ ${JSON.stringify(message, null, 4)}`);
3389
3389
  throw new Error(`Range#create called with invalid arguments[${one}, ${two}, ${three}, ${four}]`);
3390
3390
  }
3391
3391
  }
3392
- Range4.create = create;
3392
+ Range8.create = create;
3393
3393
  function is(value) {
3394
3394
  const candidate = value;
3395
3395
  return Is.objectLiteral(candidate) && Position.is(candidate.start) && Position.is(candidate.end);
3396
3396
  }
3397
- Range4.is = is;
3397
+ Range8.is = is;
3398
3398
  })(Range || (Range = {}));
3399
- (function(Location4) {
3399
+ (function(Location5) {
3400
3400
  function create(uri, range) {
3401
3401
  return { uri, range };
3402
3402
  }
3403
- Location4.create = create;
3403
+ Location5.create = create;
3404
3404
  function is(value) {
3405
3405
  const candidate = value;
3406
3406
  return Is.objectLiteral(candidate) && Range.is(candidate.range) && (Is.string(candidate.uri) || Is.undefined(candidate.uri));
3407
3407
  }
3408
- Location4.is = is;
3408
+ Location5.is = is;
3409
3409
  })(Location || (Location = {}));
3410
3410
  (function(LocationLink3) {
3411
3411
  function create(targetUri, targetRange, targetSelectionRange, originSelectionRange) {
@@ -3580,24 +3580,24 @@ ${JSON.stringify(message, null, 4)}`);
3580
3580
  }
3581
3581
  Command3.is = is;
3582
3582
  })(Command || (Command = {}));
3583
- (function(TextEdit6) {
3583
+ (function(TextEdit7) {
3584
3584
  function replace(range, newText) {
3585
3585
  return { range, newText };
3586
3586
  }
3587
- TextEdit6.replace = replace;
3587
+ TextEdit7.replace = replace;
3588
3588
  function insert(position, newText) {
3589
3589
  return { range: { start: position, end: position }, newText };
3590
3590
  }
3591
- TextEdit6.insert = insert;
3591
+ TextEdit7.insert = insert;
3592
3592
  function del(range) {
3593
3593
  return { range, newText: "" };
3594
3594
  }
3595
- TextEdit6.del = del;
3595
+ TextEdit7.del = del;
3596
3596
  function is(value) {
3597
3597
  const candidate = value;
3598
3598
  return Is.objectLiteral(candidate) && Is.string(candidate.newText) && Range.is(candidate.range);
3599
3599
  }
3600
- TextEdit6.is = is;
3600
+ TextEdit7.is = is;
3601
3601
  })(TextEdit || (TextEdit = {}));
3602
3602
  (function(ChangeAnnotation3) {
3603
3603
  function create(label, needsConfirmation, description) {
@@ -3718,7 +3718,7 @@ ${JSON.stringify(message, null, 4)}`);
3718
3718
  }
3719
3719
  DeleteFile3.is = is;
3720
3720
  })(DeleteFile || (DeleteFile = {}));
3721
- (function(WorkspaceEdit5) {
3721
+ (function(WorkspaceEdit6) {
3722
3722
  function is(value) {
3723
3723
  const candidate = value;
3724
3724
  return candidate && (candidate.changes !== void 0 || candidate.documentChanges !== void 0) && (candidate.documentChanges === void 0 || candidate.documentChanges.every((change) => {
@@ -3729,7 +3729,7 @@ ${JSON.stringify(message, null, 4)}`);
3729
3729
  }
3730
3730
  }));
3731
3731
  }
3732
- WorkspaceEdit5.is = is;
3732
+ WorkspaceEdit6.is = is;
3733
3733
  })(WorkspaceEdit || (WorkspaceEdit = {}));
3734
3734
  TextEditChangeImpl = class {
3735
3735
  constructor(edits, changeAnnotations) {
@@ -9290,28 +9290,28 @@ ${JSON.stringify(message, null, 4)}`);
9290
9290
  Object.defineProperty(exports, "__esModule", { value: true });
9291
9291
  exports.Message = exports.NotificationType9 = exports.NotificationType8 = exports.NotificationType7 = exports.NotificationType6 = exports.NotificationType5 = exports.NotificationType4 = exports.NotificationType3 = exports.NotificationType2 = exports.NotificationType1 = exports.NotificationType0 = exports.NotificationType = exports.RequestType9 = exports.RequestType8 = exports.RequestType7 = exports.RequestType6 = exports.RequestType5 = exports.RequestType4 = exports.RequestType3 = exports.RequestType2 = exports.RequestType1 = exports.RequestType = exports.RequestType0 = exports.AbstractMessageSignature = exports.ParameterStructures = exports.ResponseError = exports.ErrorCodes = void 0;
9292
9292
  var is = require_is4();
9293
- var ErrorCodes;
9294
- (function(ErrorCodes2) {
9295
- ErrorCodes2.ParseError = -32700;
9296
- ErrorCodes2.InvalidRequest = -32600;
9297
- ErrorCodes2.MethodNotFound = -32601;
9298
- ErrorCodes2.InvalidParams = -32602;
9299
- ErrorCodes2.InternalError = -32603;
9300
- ErrorCodes2.jsonrpcReservedErrorRangeStart = -32099;
9301
- ErrorCodes2.serverErrorStart = -32099;
9302
- ErrorCodes2.MessageWriteError = -32099;
9303
- ErrorCodes2.MessageReadError = -32098;
9304
- ErrorCodes2.PendingResponseRejected = -32097;
9305
- ErrorCodes2.ConnectionInactive = -32096;
9306
- ErrorCodes2.ServerNotInitialized = -32002;
9307
- ErrorCodes2.UnknownErrorCode = -32001;
9308
- ErrorCodes2.jsonrpcReservedErrorRangeEnd = -32e3;
9309
- ErrorCodes2.serverErrorEnd = -32e3;
9310
- })(ErrorCodes || (exports.ErrorCodes = ErrorCodes = {}));
9311
- var ResponseError = class _ResponseError extends Error {
9293
+ var ErrorCodes2;
9294
+ (function(ErrorCodes3) {
9295
+ ErrorCodes3.ParseError = -32700;
9296
+ ErrorCodes3.InvalidRequest = -32600;
9297
+ ErrorCodes3.MethodNotFound = -32601;
9298
+ ErrorCodes3.InvalidParams = -32602;
9299
+ ErrorCodes3.InternalError = -32603;
9300
+ ErrorCodes3.jsonrpcReservedErrorRangeStart = -32099;
9301
+ ErrorCodes3.serverErrorStart = -32099;
9302
+ ErrorCodes3.MessageWriteError = -32099;
9303
+ ErrorCodes3.MessageReadError = -32098;
9304
+ ErrorCodes3.PendingResponseRejected = -32097;
9305
+ ErrorCodes3.ConnectionInactive = -32096;
9306
+ ErrorCodes3.ServerNotInitialized = -32002;
9307
+ ErrorCodes3.UnknownErrorCode = -32001;
9308
+ ErrorCodes3.jsonrpcReservedErrorRangeEnd = -32e3;
9309
+ ErrorCodes3.serverErrorEnd = -32e3;
9310
+ })(ErrorCodes2 || (exports.ErrorCodes = ErrorCodes2 = {}));
9311
+ var ResponseError2 = class _ResponseError extends Error {
9312
9312
  constructor(code, message, data) {
9313
9313
  super(message);
9314
- this.code = is.number(code) ? code : ErrorCodes.UnknownErrorCode;
9314
+ this.code = is.number(code) ? code : ErrorCodes2.UnknownErrorCode;
9315
9315
  this.data = data;
9316
9316
  Object.setPrototypeOf(this, _ResponseError.prototype);
9317
9317
  }
@@ -9326,7 +9326,7 @@ ${JSON.stringify(message, null, 4)}`);
9326
9326
  return result;
9327
9327
  }
9328
9328
  };
9329
- exports.ResponseError = ResponseError;
9329
+ exports.ResponseError = ResponseError2;
9330
9330
  var ParameterStructures = class _ParameterStructures {
9331
9331
  constructor(kind) {
9332
9332
  this.kind = kind;
@@ -12435,7 +12435,7 @@ ${JSON.stringify(message, null, 4)}`);
12435
12435
  }
12436
12436
  uinteger3.is = is;
12437
12437
  })(uinteger2 || (uinteger2 = {}));
12438
- (function(Position4) {
12438
+ (function(Position6) {
12439
12439
  function create(line, character) {
12440
12440
  if (line === Number.MAX_VALUE) {
12441
12441
  line = uinteger2.MAX_VALUE;
@@ -12445,14 +12445,14 @@ ${JSON.stringify(message, null, 4)}`);
12445
12445
  }
12446
12446
  return { line, character };
12447
12447
  }
12448
- Position4.create = create;
12448
+ Position6.create = create;
12449
12449
  function is(value) {
12450
12450
  let candidate = value;
12451
12451
  return Is2.objectLiteral(candidate) && Is2.uinteger(candidate.line) && Is2.uinteger(candidate.character);
12452
12452
  }
12453
- Position4.is = is;
12453
+ Position6.is = is;
12454
12454
  })(Position2 || (Position2 = {}));
12455
- (function(Range4) {
12455
+ (function(Range8) {
12456
12456
  function create(one, two, three, four) {
12457
12457
  if (Is2.uinteger(one) && Is2.uinteger(two) && Is2.uinteger(three) && Is2.uinteger(four)) {
12458
12458
  return { start: Position2.create(one, two), end: Position2.create(three, four) };
@@ -12462,23 +12462,23 @@ ${JSON.stringify(message, null, 4)}`);
12462
12462
  throw new Error(`Range#create called with invalid arguments[${one}, ${two}, ${three}, ${four}]`);
12463
12463
  }
12464
12464
  }
12465
- Range4.create = create;
12465
+ Range8.create = create;
12466
12466
  function is(value) {
12467
12467
  let candidate = value;
12468
12468
  return Is2.objectLiteral(candidate) && Position2.is(candidate.start) && Position2.is(candidate.end);
12469
12469
  }
12470
- Range4.is = is;
12470
+ Range8.is = is;
12471
12471
  })(Range2 || (Range2 = {}));
12472
- (function(Location4) {
12472
+ (function(Location5) {
12473
12473
  function create(uri, range) {
12474
12474
  return { uri, range };
12475
12475
  }
12476
- Location4.create = create;
12476
+ Location5.create = create;
12477
12477
  function is(value) {
12478
12478
  let candidate = value;
12479
12479
  return Is2.objectLiteral(candidate) && Range2.is(candidate.range) && (Is2.string(candidate.uri) || Is2.undefined(candidate.uri));
12480
12480
  }
12481
- Location4.is = is;
12481
+ Location5.is = is;
12482
12482
  })(Location2 || (Location2 = {}));
12483
12483
  (function(LocationLink3) {
12484
12484
  function create(targetUri, targetRange, targetSelectionRange, originSelectionRange) {
@@ -12639,24 +12639,24 @@ ${JSON.stringify(message, null, 4)}`);
12639
12639
  }
12640
12640
  Command3.is = is;
12641
12641
  })(Command2 || (Command2 = {}));
12642
- (function(TextEdit6) {
12642
+ (function(TextEdit7) {
12643
12643
  function replace(range, newText) {
12644
12644
  return { range, newText };
12645
12645
  }
12646
- TextEdit6.replace = replace;
12646
+ TextEdit7.replace = replace;
12647
12647
  function insert(position, newText) {
12648
12648
  return { range: { start: position, end: position }, newText };
12649
12649
  }
12650
- TextEdit6.insert = insert;
12650
+ TextEdit7.insert = insert;
12651
12651
  function del(range) {
12652
12652
  return { range, newText: "" };
12653
12653
  }
12654
- TextEdit6.del = del;
12654
+ TextEdit7.del = del;
12655
12655
  function is(value) {
12656
12656
  const candidate = value;
12657
12657
  return Is2.objectLiteral(candidate) && Is2.string(candidate.newText) && Range2.is(candidate.range);
12658
12658
  }
12659
- TextEdit6.is = is;
12659
+ TextEdit7.is = is;
12660
12660
  })(TextEdit2 || (TextEdit2 = {}));
12661
12661
  (function(ChangeAnnotation3) {
12662
12662
  function create(label, needsConfirmation, description) {
@@ -12777,7 +12777,7 @@ ${JSON.stringify(message, null, 4)}`);
12777
12777
  }
12778
12778
  DeleteFile3.is = is;
12779
12779
  })(DeleteFile2 || (DeleteFile2 = {}));
12780
- (function(WorkspaceEdit5) {
12780
+ (function(WorkspaceEdit6) {
12781
12781
  function is(value) {
12782
12782
  let candidate = value;
12783
12783
  return candidate && (candidate.changes !== void 0 || candidate.documentChanges !== void 0) && (candidate.documentChanges === void 0 || candidate.documentChanges.every((change) => {
@@ -12788,7 +12788,7 @@ ${JSON.stringify(message, null, 4)}`);
12788
12788
  }
12789
12789
  }));
12790
12790
  }
12791
- WorkspaceEdit5.is = is;
12791
+ WorkspaceEdit6.is = is;
12792
12792
  })(WorkspaceEdit2 || (WorkspaceEdit2 = {}));
12793
12793
  TextEditChangeImpl2 = class {
12794
12794
  constructor(edits, changeAnnotations) {
@@ -17437,7 +17437,7 @@ ${JSON.stringify(message, null, 4)}`);
17437
17437
  });
17438
17438
 
17439
17439
  // server/src/server.ts
17440
- var import_node11 = __toESM(require_main3());
17440
+ var import_node13 = __toESM(require_main3());
17441
17441
 
17442
17442
  // server/src/platform/shims/fs.ts
17443
17443
  function readFileSync(_path, _enc) {
@@ -130021,18 +130021,71 @@ ${JSON.stringify(message, null, 4)}`);
130021
130021
  }
130022
130022
  };
130023
130023
 
130024
+ // server/src/parser/positionUtils.ts
130025
+ function normalizeUtf16Columns(text, tokens, errors) {
130026
+ if (!/[\uD800-\uDBFF][\uDC00-\uDFFF]/.test(text)) return;
130027
+ const columns = /* @__PURE__ */ new Map();
130028
+ const lines = text.split("\n");
130029
+ for (let line = 0; line < lines.length; line++) {
130030
+ if (!/[\uD800-\uDBFF][\uDC00-\uDFFF]/.test(lines[line])) continue;
130031
+ const offsets = [0];
130032
+ for (const character of lines[line]) offsets.push(offsets[offsets.length - 1] + character.length);
130033
+ columns.set(line, offsets);
130034
+ }
130035
+ for (const token of tokens) {
130036
+ token.column = columns.get(token.line - 1)?.[token.column] ?? token.column;
130037
+ }
130038
+ for (const error of errors) {
130039
+ error.column = columns.get(error.line)?.[error.column] ?? error.column;
130040
+ }
130041
+ }
130042
+ function tokenToPosition(token) {
130043
+ return {
130044
+ line: (token.line ?? 1) - 1,
130045
+ character: token.column ?? 0
130046
+ };
130047
+ }
130048
+ function tokenToRange(token) {
130049
+ const start = tokenToPosition(token);
130050
+ const length = token.text?.length ?? 1;
130051
+ return {
130052
+ start,
130053
+ end: { line: start.line, character: start.character + length }
130054
+ };
130055
+ }
130056
+ function contextToRange(ctx) {
130057
+ const startToken = ctx.start;
130058
+ const stopToken = ctx.stop ?? ctx.start;
130059
+ if (!startToken) {
130060
+ return { start: { line: 0, character: 0 }, end: { line: 0, character: 0 } };
130061
+ }
130062
+ const start = {
130063
+ line: (startToken.line ?? 1) - 1,
130064
+ character: startToken.column ?? 0
130065
+ };
130066
+ const end = stopToken ? {
130067
+ line: (stopToken.line ?? 1) - 1,
130068
+ character: (stopToken.column ?? 0) + (stopToken.text?.length ?? 1)
130069
+ } : { line: start.line, character: start.character + 1 };
130070
+ return { start, end };
130071
+ }
130072
+
130024
130073
  // server/src/parser/parseDocument.ts
130074
+ function withUtf16Columns(text, result) {
130075
+ normalizeUtf16Columns(text, result.tokenStream.getTokens(), result.errors);
130076
+ return result;
130077
+ }
130025
130078
  function parseDocument(text) {
130026
130079
  const result = parseDocumentCore(text);
130027
130080
  if (result.errors.length > 0 && hasStaleDfaStates()) {
130028
130081
  markDfaNotPreSeeded();
130029
130082
  clearAllDFAStates();
130030
- return parseDocumentLL(text, result.lexer, result.tokenStream);
130083
+ return withUtf16Columns(text, parseDocumentLL(text, result.lexer, result.tokenStream));
130031
130084
  }
130032
130085
  if (isDfaPreSeeded()) {
130033
130086
  markDfaNotPreSeeded();
130034
130087
  }
130035
- return result;
130088
+ return withUtf16Columns(text, result);
130036
130089
  }
130037
130090
  function parseDocumentCore(text) {
130038
130091
  const inputStream = CharStream.fromString(text);
@@ -130174,19 +130227,19 @@ ${JSON.stringify(message, null, 4)}`);
130174
130227
  if (errors.length > 0 && hasStaleDfaStates()) {
130175
130228
  markDfaNotPreSeeded();
130176
130229
  clearAllDFAStates();
130177
- return parseDocumentBatchLL(text, lexer, tokenStream, lexMs);
130230
+ return withUtf16Columns(text, parseDocumentBatchLL(text, lexer, tokenStream, lexMs));
130178
130231
  }
130179
130232
  if (isDfaPreSeeded()) {
130180
130233
  markDfaNotPreSeeded();
130181
130234
  }
130182
- return {
130235
+ return withUtf16Columns(text, {
130183
130236
  tree,
130184
130237
  tokenStream,
130185
130238
  parser,
130186
130239
  lexer,
130187
130240
  errors,
130188
130241
  timing: { lexMs, parseMs }
130189
- };
130242
+ });
130190
130243
  }
130191
130244
  function parseDocumentBatchLL(_text, lexer, tokenStream, lexMs) {
130192
130245
  tokenStream.seek(0);
@@ -130212,41 +130265,162 @@ ${JSON.stringify(message, null, 4)}`);
130212
130265
  };
130213
130266
  }
130214
130267
 
130215
- // server/src/parser/positionUtils.ts
130216
- function tokenToPosition(token) {
130217
- return {
130218
- line: (token.line ?? 1) - 1,
130219
- character: token.column ?? 0
130220
- };
130268
+ // server/src/utils/sysmlKeywords.ts
130269
+ var SYSML_KEYWORDS_ARRAY = SysMLv2Lexer.literalNames.filter((n2) => n2 != null).map((n2) => n2.replace(/^'|'$/g, "")).filter((n2) => /^[a-z]+$/.test(n2)).sort();
130270
+ var SYSML_KEYWORDS = new Set(SYSML_KEYWORDS_ARRAY);
130271
+
130272
+ // server/src/utils/identUtils.ts
130273
+ function isIdentStart(c) {
130274
+ return c >= 65 && c <= 90 || c >= 97 && c <= 122 || c === 95;
130221
130275
  }
130222
- function tokenToRange(token) {
130223
- const start = tokenToPosition(token);
130224
- const length = token.text?.length ?? 1;
130225
- return {
130226
- start,
130227
- end: { line: start.line, character: start.character + length }
130228
- };
130276
+ function isIdentPart(c) {
130277
+ return c >= 65 && c <= 90 || c >= 97 && c <= 122 || c >= 48 && c <= 57 || c === 95;
130229
130278
  }
130230
- function contextToRange(ctx) {
130231
- const startToken = ctx.start;
130232
- const stopToken = ctx.stop ?? ctx.start;
130233
- if (!startToken) {
130234
- return { start: { line: 0, character: 0 }, end: { line: 0, character: 0 } };
130279
+ var ESCAPES = {
130280
+ b: "\b",
130281
+ t: " ",
130282
+ n: "\n",
130283
+ f: "\f",
130284
+ r: "\r",
130285
+ "'": "'",
130286
+ '"': '"',
130287
+ "\\": "\\"
130288
+ };
130289
+ function unquoteName(text) {
130290
+ if (!text.startsWith("'") || !text.endsWith("'")) return text;
130291
+ return text.slice(1, -1).replace(/\\([btnfr'"\\])/g, (_, ch) => ESCAPES[ch]);
130292
+ }
130293
+ function quoteName(name) {
130294
+ if (/^[A-Za-z_][A-Za-z_0-9]*$/.test(name) && !SYSML_KEYWORDS.has(name)) return name;
130295
+ const escaped = name.replace(/[\\'\b\t\n\f\r]/g, (ch) => {
130296
+ const entry = Object.entries(ESCAPES).find(([, value]) => value === ch);
130297
+ return `\\${entry[0]}`;
130298
+ });
130299
+ return `'${escaped}'`;
130300
+ }
130301
+ function splitQualifiedName(text) {
130302
+ const parts = [];
130303
+ let start = 0;
130304
+ let quoted = false;
130305
+ for (let i = 0; i < text.length; i++) {
130306
+ if (quoted && text[i] === "\\") {
130307
+ i++;
130308
+ continue;
130309
+ }
130310
+ if (text[i] === "'" && (quoted || i === start)) quoted = !quoted;
130311
+ if (!quoted && text.startsWith("::", i)) {
130312
+ parts.push(unquoteName(text.slice(start, i).trim()));
130313
+ start = i + 2;
130314
+ i++;
130315
+ }
130235
130316
  }
130236
- const start = {
130237
- line: (startToken.line ?? 1) - 1,
130238
- character: startToken.column ?? 0
130239
- };
130240
- const end = stopToken ? {
130241
- line: (stopToken.line ?? 1) - 1,
130242
- character: (stopToken.column ?? 0) + (stopToken.text?.length ?? 1)
130243
- } : { line: start.line, character: start.character + 1 };
130244
- return { start, end };
130317
+ parts.push(unquoteName(text.slice(start).trim()));
130318
+ return parts;
130319
+ }
130320
+ function joinQualifiedName(parts) {
130321
+ return parts.map((part) => /::|['\\\r\n\t\b\f]/.test(part) ? quoteName(part) : part).join("::");
130322
+ }
130323
+ function readNameAt(text, start, allowIncomplete = false) {
130324
+ if (text[start] === "'") {
130325
+ let end2 = start + 1;
130326
+ while (end2 < text.length && text[end2] !== "'") {
130327
+ if (text[end2] === "\r" || text[end2] === "\n") return void 0;
130328
+ if (text[end2] === "\\") {
130329
+ if (!Object.hasOwn(ESCAPES, text[end2 + 1])) return void 0;
130330
+ end2++;
130331
+ }
130332
+ end2++;
130333
+ }
130334
+ if (end2 >= text.length) {
130335
+ return allowIncomplete ? { name: unquoteName(`${text.slice(start)}'`), start, end: text.length } : void 0;
130336
+ }
130337
+ if (end2 === start + 1 && !allowIncomplete) return void 0;
130338
+ return { name: unquoteName(text.slice(start, end2 + 1)), start, end: end2 + 1 };
130339
+ }
130340
+ if (!isIdentStart(text.charCodeAt(start))) return void 0;
130341
+ let end = start + 1;
130342
+ while (end < text.length && isIdentPart(text.charCodeAt(end))) end++;
130343
+ return { name: text.slice(start, end), start, end };
130344
+ }
130345
+ function readQualifiedNameAt(text, start, allowIncomplete = false) {
130346
+ const first = readNameAt(text, start, allowIncomplete);
130347
+ if (!first) return void 0;
130348
+ const segments = [first];
130349
+ let end = first.end;
130350
+ while (end < text.length) {
130351
+ let next = end;
130352
+ while (/\s/.test(text[next] ?? "") && next < text.length) next++;
130353
+ if (!text.startsWith("::", next)) break;
130354
+ next += 2;
130355
+ while (/\s/.test(text[next] ?? "") && next < text.length) next++;
130356
+ const segment = readNameAt(text, next, allowIncomplete);
130357
+ if (!segment) break;
130358
+ segments.push(segment);
130359
+ end = segment.end;
130360
+ }
130361
+ return { name: joinQualifiedName(segments.map((s) => s.name)), start, end, segments };
130362
+ }
130363
+ function* scanQualifiedNames(text, allowIncomplete = false) {
130364
+ let i = 0;
130365
+ while (i < text.length) {
130366
+ if (text.startsWith("//", i)) {
130367
+ const end = text.indexOf("\n", i + 2);
130368
+ i = end < 0 ? text.length : end + 1;
130369
+ } else if (text.startsWith("/*", i)) {
130370
+ const end = text.indexOf("*/", i + 2);
130371
+ i = end < 0 ? text.length : end + 2;
130372
+ } else if (text[i] === '"') {
130373
+ i++;
130374
+ while (i < text.length && text[i] !== '"') i += text[i] === "\\" ? 2 : 1;
130375
+ i++;
130376
+ } else if (/\d/.test(text[i]) || text[i] === "." && /\d/.test(text[i + 1] ?? "")) {
130377
+ const number = text.slice(i).match(/^(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?/);
130378
+ i += number[0].length;
130379
+ } else {
130380
+ const name = readQualifiedNameAt(text, i, allowIncomplete);
130381
+ if (name) {
130382
+ yield name;
130383
+ i = name.end;
130384
+ } else if (text[i] === "'") {
130385
+ i++;
130386
+ while (i < text.length && text[i] !== "'" && text[i] !== "\n") {
130387
+ i += text[i] === "\\" ? 2 : 1;
130388
+ }
130389
+ if (text[i] === "'") i++;
130390
+ } else {
130391
+ i++;
130392
+ }
130393
+ }
130394
+ }
130395
+ }
130396
+ function* scanFeaturePaths(text) {
130397
+ const names = [...scanQualifiedNames(text)];
130398
+ for (let i = 0; i < names.length; i++) {
130399
+ const first = names[i];
130400
+ const parts = [first.name];
130401
+ const qualifiedNames = [first];
130402
+ let end = first.end;
130403
+ while (i + 1 < names.length && /^\s*\.\s*$/.test(text.slice(end, names[i + 1].start))) {
130404
+ parts.push(names[++i].name);
130405
+ qualifiedNames.push(names[i]);
130406
+ end = names[i].end;
130407
+ }
130408
+ yield { name: parts.join("."), start: first.start, end, qualifiedNames, parts: parts.map((part) => {
130409
+ const segments = splitQualifiedName(part);
130410
+ return segments.length === 1 ? segments[0] : part;
130411
+ }) };
130412
+ }
130413
+ }
130414
+ function extractQualifiedNameAt(text, character) {
130415
+ for (const name of scanQualifiedNames(text)) {
130416
+ if (character >= name.start && character <= name.end) return name.name;
130417
+ if (name.start > character) break;
130418
+ }
130419
+ return void 0;
130420
+ }
130421
+ function stripComments(text) {
130422
+ return text.replace(/\/\*[\s\S]*?\*\//g, (m2) => m2.replace(/[^\n]/g, " ")).replace(/\/\/[^\n]*/g, (m2) => " ".repeat(m2.length));
130245
130423
  }
130246
-
130247
- // server/src/utils/sysmlKeywords.ts
130248
- var SYSML_KEYWORDS_ARRAY = SysMLv2Lexer.literalNames.filter((n2) => n2 != null).map((n2) => n2.replace(/^'|'$/g, "")).filter((n2) => /^[a-z]+$/.test(n2)).sort();
130249
- var SYSML_KEYWORDS = new Set(SYSML_KEYWORDS_ARRAY);
130250
130424
 
130251
130425
  // server/src/utils/documentUri.ts
130252
130426
  function canonicalUri(uri) {
@@ -131081,7 +131255,7 @@ ${JSON.stringify(message, null, 4)}`);
131081
131255
  var RE_DEFINED_BY = /definedby\s*([A-Za-z_]\w*(?:::\w+)*(?:\s*,\s*[A-Za-z_]\w*(?:::\w+)*)*)/;
131082
131256
  var MAX_RULE_SEARCH_DEPTH = 6;
131083
131257
  var RE_TYPING = /:(?![:>])\s*('[^']+'|[A-Za-z_]\w*(?:::\w+)*)/;
131084
- var RE_QUOTED_NAME = /'([^']+)'/;
131258
+ var RE_QUOTED_NAME = /^\s*(?:\$::)?(?:(?:[A-Za-z_]\w*|'\d+')::)*'(\d+)'/;
131085
131259
  var RE_IDENT_START = /^([A-Za-z_]\w*(?:::\w+)*)/;
131086
131260
  var SymbolTable = class {
131087
131261
  /** All symbols indexed by qualified name */
@@ -131148,7 +131322,12 @@ ${JSON.stringify(message, null, 4)}`);
131148
131322
  * Find a symbol by name (simple name, not qualified).
131149
131323
  */
131150
131324
  findByName(name) {
131151
- return this.symbolsByName.get(name) ?? [];
131325
+ const exact = this.symbolsByName.get(name);
131326
+ if (exact) return exact;
131327
+ const segments = splitQualifiedName(name);
131328
+ if (segments.length === 1) return this.symbolsByName.get(segments[0]) ?? [];
131329
+ const qualified = this.getSymbol(joinQualifiedName(segments));
131330
+ return qualified ? [qualified] : [];
131152
131331
  }
131153
131332
  /**
131154
131333
  * Find all symbols in a given URI.
@@ -131655,10 +131834,11 @@ ${JSON.stringify(message, null, 4)}`);
131655
131834
  const anonymous = !declaredName;
131656
131835
  const name = declaredName ?? "";
131657
131836
  const shortName = transition || isFlowUsage(kind) && !declaredName ? void 0 : this.extractShortName(ctx);
131658
- const qualifiedName = anonymous || owner && owner.qualifiedName === void 0 ? void 0 : owner ? `${owner.qualifiedName}::${name}` : name;
131837
+ const qualifiedName = anonymous || owner && owner.qualifiedName === void 0 ? void 0 : owner ? `${owner.qualifiedName}::${joinQualifiedName([name])}` : joinQualifiedName([name]);
131659
131838
  const selectionRange = anonymous ? ctx.start ? tokenToRange(ctx.start) : range : this.extractNameRange(ctx) ?? range;
131660
131839
  const typeNames = isFlowUsage(kind) ? this.extractFlowTypeNames(ctx) : transition ? this.extractTransitionTypeNames(ctx) : this.extractTypeNames(ctx);
131661
131840
  const specializationNames = this.extractSpecializationNames(ctx);
131841
+ const redefinedFeatureTargets = this.extractRedefinedFeatureTargets(ctx);
131662
131842
  const typeName = typeNames[0];
131663
131843
  const documentation = this.extractDocumentation(ctx);
131664
131844
  const visibility = this.extractVisibility(ctx);
@@ -131689,6 +131869,7 @@ ${JSON.stringify(message, null, 4)}`);
131689
131869
  typeName,
131690
131870
  typeNames,
131691
131871
  specializationNames,
131872
+ redefinedFeatureTargets: redefinedFeatureTargets.length > 0 ? redefinedFeatureTargets : void 0,
131692
131873
  documentation,
131693
131874
  visibility,
131694
131875
  source: transition?.source,
@@ -131813,7 +131994,10 @@ ${JSON.stringify(message, null, 4)}`);
131813
131994
  }
131814
131995
  /** Remove SysML quoting while retaining qualified and dotted references. */
131815
131996
  cleanTransitionText(text) {
131816
- const cleaned = text.replace(/'([^']+)'/g, "$1").trim();
131997
+ const cleaned = text.replace(
131998
+ /'(?:\\.|[^'\\])*'/g,
131999
+ (name) => joinQualifiedName([unquoteName(name)])
132000
+ ).trim();
131817
132001
  return cleaned || void 0;
131818
132002
  }
131819
132003
  /** Extract explicit first/then successions owned by an action body. */
@@ -131940,15 +132124,28 @@ ${JSON.stringify(message, null, 4)}`);
131940
132124
  * such as `#metadata`.
131941
132125
  */
131942
132126
  findOwnHeaderRule(ctx, ruleIndex) {
132127
+ const matches = [];
132128
+ this.findOwnHeaderRules(ctx, ruleIndex, matches, true);
132129
+ return matches[0];
132130
+ }
132131
+ findOwnHeaderRules(ctx, ruleIndex, matches, firstOnly = false) {
131943
132132
  for (let i = 0; i < ctx.getChildCount(); i++) {
131944
132133
  const child = ctx.getChild(i);
131945
132134
  if (!(child instanceof ParserRuleContext)) continue;
131946
- if (child.ruleIndex === ruleIndex) return child;
132135
+ if (child.ruleIndex === ruleIndex) {
132136
+ matches.push(child);
132137
+ if (firstOnly) return;
132138
+ continue;
132139
+ }
131947
132140
  if (RULE_INDEX_TO_KIND.has(child.ruleIndex) || BODY_RULE_INDICES.has(child.ruleIndex) || child.ruleIndex === SysMLv2Parser.RULE_valuePart || FLOW_PART_RULE_INDICES.has(child.ruleIndex) || child.ruleIndex === SysMLv2Parser.RULE_ownedCrossMultiplicityMember || this.isPrefixOrExtensionContext(child)) continue;
131948
- const found = this.findOwnHeaderRule(child, ruleIndex);
131949
- if (found) return found;
132141
+ this.findOwnHeaderRules(child, ruleIndex, matches, firstOnly);
132142
+ if (firstOnly && matches.length > 0) return;
131950
132143
  }
131951
- return void 0;
132144
+ }
132145
+ extractRedefinedFeatureTargets(ctx) {
132146
+ const targets = [];
132147
+ this.findOwnHeaderRules(ctx, SysMLv2Parser.RULE_ownedRedefinition, targets);
132148
+ return targets.map((target) => target.getText());
131952
132149
  }
131953
132150
  /**
131954
132151
  * A connection, interface or allocation usage's end reference paths, in
@@ -131973,16 +132170,10 @@ ${JSON.stringify(message, null, 4)}`);
131973
132170
  }
131974
132171
  /** The name of the feature a reference such as `a.b` or `P::a` ends at (`b`, `a`). */
131975
132172
  lastNameSegment(reference) {
131976
- const segment = reference.getText().split(/::|\./).pop();
131977
- return segment ? this.unquoteName(segment) : void 0;
132173
+ const names = [...scanQualifiedNames(reference.getText())];
132174
+ return names.at(-1)?.segments.at(-1)?.name;
131978
132175
  }
131979
- /**
131980
- * An element's declaration as written, without its body: its tokens up to
131981
- * its body or closing `;`, each exactly as written (a quoted name keeps its
131982
- * spaces), with one space wherever the source has whitespace or a comment
131983
- * between two of them (`connect a.p to b.p`, `connection : Conn`).
131984
- */
131985
- declarationText(ctx) {
132176
+ declarationTokens(ctx) {
131986
132177
  const tokens = [];
131987
132178
  const visit = (node) => {
131988
132179
  for (let i = 0; i < node.getChildCount(); i++) {
@@ -131997,6 +132188,16 @@ ${JSON.stringify(message, null, 4)}`);
131997
132188
  return false;
131998
132189
  };
131999
132190
  visit(ctx);
132191
+ return tokens;
132192
+ }
132193
+ /**
132194
+ * An element's declaration as written, without its body: its tokens up to
132195
+ * its body or closing `;`, each exactly as written (a quoted name keeps its
132196
+ * spaces), with one space wherever the source has whitespace or a comment
132197
+ * between two of them (`connect a.p to b.p`, `connection : Conn`).
132198
+ */
132199
+ declarationText(ctx) {
132200
+ const tokens = this.declarationTokens(ctx);
132000
132201
  let text = "";
132001
132202
  tokens.forEach((token, i) => {
132002
132203
  if (i > 0 && token.start > tokens[i - 1].stop + 1) text += " ";
@@ -132106,6 +132307,16 @@ ${JSON.stringify(message, null, 4)}`);
132106
132307
  * Extract the range of just the name token.
132107
132308
  */
132108
132309
  extractNameRange(ctx) {
132310
+ if (ctx.ruleIndex === SysMLv2Parser.RULE_identification || ctx.ruleIndex === SysMLv2Parser.RULE_featureIdentification) {
132311
+ let name;
132312
+ for (let i = 0; i < ctx.getChildCount(); i++) {
132313
+ const child = ctx.getChild(i);
132314
+ if (child instanceof ParserRuleContext && child.ruleIndex === SysMLv2Parser.RULE_name) {
132315
+ name = child;
132316
+ }
132317
+ }
132318
+ if (name) return contextToRange(name);
132319
+ }
132109
132320
  for (let i = 0; i < ctx.getChildCount(); i++) {
132110
132321
  const child = ctx.getChild(i);
132111
132322
  if (child instanceof TerminalNode && this.isNameTerminal(child)) {
@@ -132137,17 +132348,16 @@ ${JSON.stringify(message, null, 4)}`);
132137
132348
  const names = [];
132138
132349
  this.collectTypeNamesFromTree(ctx, names, 0);
132139
132350
  if (names.length > 0) return names;
132140
- const fullText = ctx.getText();
132141
- const braceIdx = fullText.indexOf("{");
132142
- let text = braceIdx >= 0 ? fullText.substring(0, braceIdx) : fullText;
132351
+ const { text: declarationText, quotedName } = this.maskedDeclaration(ctx);
132352
+ let text = declarationText;
132143
132353
  text = text.replace(RE_KEYWORD_TRUNCATE, "");
132144
132354
  const specMatch = text.match(RE_SPEC);
132145
132355
  if (specMatch) {
132146
132356
  const specStr = text.substring(text.indexOf(specMatch[0]) + specMatch[0].indexOf(specMatch[1]));
132147
132357
  for (const part of specStr.split(",")) {
132148
- const qm = part.match(RE_QUOTED_NAME);
132149
- if (qm) {
132150
- names.push(qm[1]);
132358
+ const quoted = quotedName(part);
132359
+ if (quoted !== void 0) {
132360
+ names.push(joinQualifiedName([quoted]));
132151
132361
  continue;
132152
132362
  }
132153
132363
  const m2 = part.trim().match(RE_IDENT_START);
@@ -132168,9 +132378,9 @@ ${JSON.stringify(message, null, 4)}`);
132168
132378
  const fullMatchIdx = text.indexOf(typingMatch[0]);
132169
132379
  const afterColon = text.substring(fullMatchIdx + 1).trim();
132170
132380
  for (const part of afterColon.split(",")) {
132171
- const qm = part.match(RE_QUOTED_NAME);
132172
- if (qm) {
132173
- names.push(qm[1]);
132381
+ const quoted = quotedName(part);
132382
+ if (quoted !== void 0) {
132383
+ names.push(joinQualifiedName([quoted]));
132174
132384
  continue;
132175
132385
  }
132176
132386
  const m2 = part.trim().match(RE_IDENT_START);
@@ -132180,6 +132390,30 @@ ${JSON.stringify(message, null, 4)}`);
132180
132390
  }
132181
132391
  return names;
132182
132392
  }
132393
+ /**
132394
+ * The declaration tokens before the value or body, with each lexer STRING token
132395
+ * replaced by a numbered placeholder (`'0'`, `'1'`, ...), and
132396
+ * `quotedName`, which turns a placeholder in a part of that text back into
132397
+ * the name, when it ends the qualified name the part starts with. SysML
132398
+ * 2.0 section 7.2.2 permits punctuation in unrestricted names (the STRING
132399
+ * lexer production), so fallback regexes must never see their `:`, `:>`,
132400
+ * `{` or keywords. Documentation is not a name token.
132401
+ */
132402
+ maskedDeclaration(ctx) {
132403
+ const quoted = [];
132404
+ const valueStart = this.findOwnHeaderRule(ctx, SysMLv2Parser.RULE_valuePart)?.start?.tokenIndex;
132405
+ const masked = this.declarationTokens(ctx).filter((token) => valueStart === void 0 || token.tokenIndex < valueStart).map((token) => {
132406
+ const text = token.text ?? "";
132407
+ return token.type === SysMLv2Lexer.STRING ? `'${quoted.push(unquoteName(text)) - 1}'` : text;
132408
+ }).join("");
132409
+ return {
132410
+ text: masked,
132411
+ quotedName: (part) => {
132412
+ const qm = part.match(RE_QUOTED_NAME);
132413
+ return qm ? quoted[Number(qm[1])] : void 0;
132414
+ }
132415
+ };
132416
+ }
132183
132417
  /**
132184
132418
  * Extract only the specialization names (:> / specializes / subsets) from a context.
132185
132419
  * Uses the same tree-walk as extractTypeNames but restricted to
@@ -132190,17 +132424,15 @@ ${JSON.stringify(message, null, 4)}`);
132190
132424
  const names = [];
132191
132425
  this.collectNamesFromTree(ctx, names, 0, TYPE_SPECIALIZATION_RULE_INDICES);
132192
132426
  if (names.length > 0) return names;
132193
- const fullText = ctx.getText();
132194
- const braceIdx = fullText.indexOf("{");
132195
- let text = braceIdx >= 0 ? fullText.substring(0, braceIdx) : fullText;
132196
- text = text.replace(RE_KEYWORD_TRUNCATE_SPEC, "");
132427
+ const { text: declarationText, quotedName } = this.maskedDeclaration(ctx);
132428
+ const text = declarationText.replace(RE_KEYWORD_TRUNCATE_SPEC, "");
132197
132429
  const specMatch = text.match(RE_SPEC_WITH_SUBSETS);
132198
132430
  if (specMatch) {
132199
132431
  const specStr = text.substring(text.indexOf(specMatch[0]) + specMatch[0].indexOf(specMatch[1]));
132200
132432
  for (const part of specStr.split(",")) {
132201
- const qm = part.match(RE_QUOTED_NAME);
132202
- if (qm) {
132203
- names.push(qm[1]);
132433
+ const quoted = quotedName(part);
132434
+ if (quoted !== void 0) {
132435
+ names.push(joinQualifiedName([quoted]));
132204
132436
  continue;
132205
132437
  }
132206
132438
  const m2 = part.trim().match(RE_IDENT_START);
@@ -132229,17 +132461,7 @@ ${JSON.stringify(message, null, 4)}`);
132229
132461
  if (!(child instanceof ParserRuleContext)) continue;
132230
132462
  const ri = child.ruleIndex;
132231
132463
  if (extractionRules.has(ri)) {
132232
- const childText = child.getText();
132233
- const stripped = childText.replace(/^(specializes|:>>|:>|:|definedby|subsets|redefines|references|conjugates|disjoints)/i, "");
132234
- for (const part of stripped.split(",")) {
132235
- const qm = part.match(/'([^']+)'/);
132236
- if (qm) {
132237
- names.push(qm[1]);
132238
- } else {
132239
- const m2 = part.match(/([A-Za-z_]\w*(?:::\w+)*)/);
132240
- if (m2) names.push(m2[1]);
132241
- }
132242
- }
132464
+ this.collectQualifiedTypeNames(child, names);
132243
132465
  } else if (
132244
132466
  // Recurse into declaration / part / body wrappers that may
132245
132467
  // contain nested typing rules (but NOT into body rules that
@@ -132252,6 +132474,17 @@ ${JSON.stringify(message, null, 4)}`);
132252
132474
  }
132253
132475
  }
132254
132476
  }
132477
+ collectQualifiedTypeNames(ctx, names) {
132478
+ if (ctx.ruleIndex === SysMLv2Parser.RULE_qualifiedName) {
132479
+ const name = this.extractTextFromSubtree(ctx);
132480
+ if (name) names.push(name);
132481
+ return;
132482
+ }
132483
+ for (let i = 0; i < ctx.getChildCount(); i++) {
132484
+ const child = ctx.getChild(i);
132485
+ if (child instanceof ParserRuleContext) this.collectQualifiedTypeNames(child, names);
132486
+ }
132487
+ }
132255
132488
  /**
132256
132489
  * Extract documentation owned by this element.
132257
132490
  *
@@ -132412,10 +132645,7 @@ ${JSON.stringify(message, null, 4)}`);
132412
132645
  * Returns the text unchanged if not quoted.
132413
132646
  */
132414
132647
  unquoteName(text) {
132415
- if (this.isQuotedName(text)) {
132416
- return text.slice(1, -1);
132417
- }
132418
- return text;
132648
+ return unquoteName(text);
132419
132649
  }
132420
132650
  /**
132421
132651
  * Check if a text is a SysML keyword.
@@ -132703,7 +132933,7 @@ ${JSON.stringify(message, null, 4)}`);
132703
132933
  const child = ctx.getChild(i);
132704
132934
  if (child instanceof TerminalNode) {
132705
132935
  const text = child.symbol.text;
132706
- if (text) parts.push(text);
132936
+ if (text) parts.push(child.symbol.type === SysMLv2Lexer.STRING ? joinQualifiedName([unquoteName(text)]) : text);
132707
132937
  } else if (child instanceof ParserRuleContext) {
132708
132938
  this.collectExposeText(child, parts);
132709
132939
  }
@@ -132765,58 +132995,24 @@ ${JSON.stringify(message, null, 4)}`);
132765
132995
  * Extract all text content from a subtree (concatenate terminal nodes).
132766
132996
  */
132767
132997
  extractTextFromSubtree(ctx) {
132998
+ if (ctx.ruleIndex === SysMLv2Parser.RULE_name) return unquoteName(ctx.getText());
132768
132999
  const parts = [];
132769
133000
  for (let i = 0; i < ctx.getChildCount(); i++) {
132770
133001
  const child = ctx.getChild(i);
132771
133002
  if (child instanceof TerminalNode) {
132772
133003
  const text = child.symbol.text;
132773
133004
  if (text && this.isNameTerminal(child)) {
132774
- parts.push(this.unquoteName(text));
133005
+ parts.push(joinQualifiedName([this.unquoteName(text)]));
132775
133006
  }
132776
133007
  } else if (child instanceof ParserRuleContext) {
132777
133008
  const sub = this.extractTextFromSubtree(child);
132778
- if (sub) parts.push(sub);
133009
+ if (sub) parts.push(child.ruleIndex === SysMLv2Parser.RULE_name ? joinQualifiedName([sub]) : sub);
132779
133010
  }
132780
133011
  }
132781
133012
  return parts.length > 0 ? parts.join("::") : void 0;
132782
133013
  }
132783
133014
  };
132784
133015
 
132785
- // server/src/utils/identUtils.ts
132786
- function isIdentStart(c) {
132787
- return c >= 65 && c <= 90 || c >= 97 && c <= 122 || c === 95;
132788
- }
132789
- function isIdentPart(c) {
132790
- return c >= 65 && c <= 90 || c >= 97 && c <= 122 || c >= 48 && c <= 57 || c === 95;
132791
- }
132792
- function extractQualifiedNameAt(lineText, character) {
132793
- const len = lineText.length;
132794
- let i = 0;
132795
- while (i < len) {
132796
- if (!isIdentStart(lineText.charCodeAt(i))) {
132797
- i++;
132798
- continue;
132799
- }
132800
- const wordStart = i;
132801
- while (i < len) {
132802
- while (i < len && isIdentPart(lineText.charCodeAt(i))) i++;
132803
- if (i + 2 <= len && lineText[i] === ":" && lineText[i + 1] === ":" && i + 2 < len && isIdentStart(lineText.charCodeAt(i + 2))) {
132804
- i += 2;
132805
- } else {
132806
- break;
132807
- }
132808
- }
132809
- const wordEnd = i;
132810
- if (character >= wordStart && character <= wordEnd) {
132811
- return lineText.substring(wordStart, wordEnd);
132812
- }
132813
- }
132814
- return void 0;
132815
- }
132816
- function stripComments(text) {
132817
- return text.replace(/\/\*[\s\S]*?\*\//g, (m2) => m2.replace(/[^\n]/g, " ")).replace(/\/\/[^\n]*/g, (m2) => " ".repeat(m2.length));
132818
- }
132819
-
132820
133016
  // server/src/documentManager.ts
132821
133017
  var DocumentManager = class {
132822
133018
  cache = /* @__PURE__ */ new Map();
@@ -135470,55 +135666,30 @@ ${JSON.stringify(message, null, 4)}`);
135470
135666
  while (pos < line.length && isIdentPart(line.charCodeAt(pos))) pos++;
135471
135667
  return pos > start ? [line.slice(start, pos), pos] : void 0;
135472
135668
  }
135669
+ function readSimpleName(line, pos) {
135670
+ const name = readNameAt(line, skipSpaces(line, pos));
135671
+ return name ? [name.name, name.end] : void 0;
135672
+ }
135473
135673
  function readName(line, pos) {
135474
135674
  pos = skipSpaces(line, pos);
135475
- if (pos < line.length && line[pos] === "'") {
135476
- pos++;
135477
- const start = pos;
135478
- while (pos < line.length && isIdentPart(line.charCodeAt(pos))) pos++;
135479
- const name = line.slice(start, pos);
135480
- if (pos < line.length && line[pos] === "'") pos++;
135481
- return name ? [name, pos] : void 0;
135482
- }
135483
135675
  if (pos < line.length && line[pos] === "<") {
135484
- pos++;
135485
- const start = pos;
135486
- while (pos < line.length && line[pos] !== ">") pos++;
135487
- const shortName = line.slice(start, pos).trim();
135488
- if (pos < line.length && line[pos] === ">") pos++;
135489
- pos = skipSpaces(line, pos);
135490
- if (pos < line.length && line[pos] === "'") {
135491
- pos++;
135492
- while (pos < line.length && line[pos] !== "'") pos++;
135493
- if (pos < line.length) pos++;
135494
- } else if (pos < line.length && isIdentPart(line.charCodeAt(pos))) {
135495
- while (pos < line.length && isIdentPart(line.charCodeAt(pos))) pos++;
135496
- }
135497
- return shortName ? [shortName, pos] : void 0;
135498
- }
135499
- return readWord(line, pos);
135676
+ const short = readSimpleName(line, pos + 1);
135677
+ if (!short) return void 0;
135678
+ pos = skipSpaces(line, short[1]);
135679
+ if (line[pos] !== ">") return void 0;
135680
+ const long = readSimpleName(line, pos + 1);
135681
+ return [short[0], long?.[1] ?? pos + 1];
135682
+ }
135683
+ return readSimpleName(line, pos);
135500
135684
  }
135501
135685
  function readLongName(line, pos) {
135502
135686
  pos = skipSpaces(line, pos);
135503
135687
  if (pos >= line.length || line[pos] !== "<") return void 0;
135504
- while (pos < line.length && line[pos] !== ">") pos++;
135505
- if (pos < line.length) pos++;
135506
- pos = skipSpaces(line, pos);
135507
- if (pos >= line.length) return void 0;
135508
- if (line[pos] === "'") {
135509
- pos++;
135510
- const start = pos;
135511
- while (pos < line.length && line[pos] !== "'") pos++;
135512
- const longName = line.slice(start, pos).trim();
135513
- if (longName && /^[A-Za-z_]\w*$/.test(longName)) return longName;
135514
- return void 0;
135515
- }
135516
- if (isIdentPart(line.charCodeAt(pos))) {
135517
- const start = pos;
135518
- while (pos < line.length && isIdentPart(line.charCodeAt(pos))) pos++;
135519
- return line.slice(start, pos);
135520
- }
135521
- return void 0;
135688
+ const short = readSimpleName(line, pos + 1);
135689
+ if (!short) return void 0;
135690
+ pos = skipSpaces(line, short[1]);
135691
+ if (line[pos] !== ">") return void 0;
135692
+ return readSimpleName(line, pos + 1)?.[0];
135522
135693
  }
135523
135694
  function matchWord(line, pos, keyword) {
135524
135695
  if (!line.startsWith(keyword, pos)) return false;
@@ -135590,7 +135761,7 @@ ${JSON.stringify(message, null, 4)}`);
135590
135761
  if (close < 0) continue;
135591
135762
  pos = skipSpaces(line, close + 1);
135592
135763
  }
135593
- const w = readWord(line, pos);
135764
+ const w = readName(line, pos);
135594
135765
  if (w) return w[0];
135595
135766
  }
135596
135767
  return void 0;
@@ -135715,7 +135886,7 @@ ${JSON.stringify(message, null, 4)}`);
135715
135886
  types.set(usageName, { uri: fileUri, line: i });
135716
135887
  }
135717
135888
  if (pkgName) {
135718
- const qualName = `${pkgName}::${usageName}`;
135889
+ const qualName = joinQualifiedName([pkgName, usageName]);
135719
135890
  if (!types.has(qualName)) {
135720
135891
  types.set(qualName, { uri: fileUri, line: i });
135721
135892
  }
@@ -135726,7 +135897,7 @@ ${JSON.stringify(message, null, 4)}`);
135726
135897
  types.set(longName, { uri: fileUri, line: i });
135727
135898
  }
135728
135899
  if (pkgName) {
135729
- const qualLong = `${pkgName}::${longName}`;
135900
+ const qualLong = joinQualifiedName([pkgName, longName]);
135730
135901
  if (!types.has(qualLong)) {
135731
135902
  types.set(qualLong, { uri: fileUri, line: i });
135732
135903
  }
@@ -135758,15 +135929,17 @@ ${JSON.stringify(message, null, 4)}`);
135758
135929
  }
135759
135930
  function resolveLibraryPackage(name) {
135760
135931
  if (!index) return void 0;
135761
- const pkg = name.split("::")[0];
135932
+ const pkg = splitQualifiedName(name)[0];
135762
135933
  return index.get(pkg);
135763
135934
  }
135764
135935
  function resolveLibraryType(name) {
135765
135936
  if (!typeIndex) return void 0;
135937
+ const segments = splitQualifiedName(name);
135938
+ name = segments.length === 1 ? segments[0] : joinQualifiedName(segments);
135766
135939
  const exact = typeIndex.get(name);
135767
135940
  if (exact) return exact;
135768
- if (name.includes("::")) {
135769
- const member = name.split("::").pop();
135941
+ if (segments.length > 1) {
135942
+ const member = segments[segments.length - 1];
135770
135943
  return typeIndex.get(member);
135771
135944
  }
135772
135945
  return void 0;
@@ -136405,20 +136578,31 @@ ${JSON.stringify(message, null, 4)}`);
136405
136578
  * namespace.
136406
136579
  */
136407
136580
  isLocallyVisible(symbol, name, indexes) {
136408
- return this.resolveQualifiedNameFrom(ownerKeyOf(symbol, indexes.byId), name, indexes) !== void 0;
136581
+ return this.resolveNameFrom(symbol, name, indexes) !== void 0;
136582
+ }
136583
+ /**
136584
+ * Resolve a (possibly qualified) name from the namespace containing
136585
+ * `symbol`, respecting namespace membership and visibility.
136586
+ */
136587
+ resolveNameFrom(symbol, name, indexes) {
136588
+ return this.resolveQualifiedNameFrom(ownerKeyOf(symbol, indexes.byId), name, indexes);
136589
+ }
136590
+ /** Resolve an editor reference within its enclosing namespace, including the root. */
136591
+ resolveNameIn(namespace, name, indexes) {
136592
+ return this.resolveQualifiedNameFrom(namespace ? namespaceKeyOf(namespace) : "", name, indexes);
136409
136593
  }
136410
136594
  /**
136411
136595
  * Resolve a (possibly qualified) name to its symbol per §7.5.1, searching
136412
136596
  * outward from namespace `start` and its enclosing namespaces (its own resolved
136413
136597
  * members first, then its parent's, ...). Shared by `isLocallyVisible` (an
136414
- * ordinary reference resolving relative to its own enclosing namespace) and
136415
- * import-target resolution (an `import` declaration's target is itself a
136598
+ * ordinary reference resolving relative to its own enclosing namespace),
136599
+ * `resolveNameFrom`, and import-target resolution (an `import` declaration's target is itself a
136416
136600
  * qualifiedName, resolved the same relative way -- not as an absolute/global
136417
136601
  * name -- so a bare `import C;` inside a nested package can pick up a `C`
136418
136602
  * its own enclosing package already imported, per §7.5.1/§7.5.3).
136419
136603
  */
136420
136604
  resolveQualifiedNameFrom(start, name, indexes) {
136421
- const [first, ...rest] = name.split("::");
136605
+ const [first, ...rest] = splitQualifiedName(name);
136422
136606
  let resolved;
136423
136607
  for (const ancestor of this.namespaceAncestorsOf(start, indexes)) {
136424
136608
  const candidates = this.getResolvedMembers(ancestor, indexes).get(first);
@@ -136585,6 +136769,9 @@ ${JSON.stringify(message, null, 4)}`);
136585
136769
  };
136586
136770
  for (const owned of indexes.byParent.get(namespace) ?? []) {
136587
136771
  addMember(owned.name, { symbol: owned, visibility: owned.visibility ?? "public" });
136772
+ if (owned.shortName) {
136773
+ addMember(owned.shortName, { symbol: owned, visibility: owned.visibility ?? "public" });
136774
+ }
136588
136775
  }
136589
136776
  perIndexesCache.set(namespace, members);
136590
136777
  const owner = typeof namespace === "string" ? indexes.byQualifiedName.get(namespace) : namespace;
@@ -136620,13 +136807,17 @@ ${JSON.stringify(message, null, 4)}`);
136620
136807
  switch (imp.kind) {
136621
136808
  case "membership": {
136622
136809
  const target = this.resolveQualifiedNameFrom(importingNamespace, imp.target, indexes);
136623
- if (target) addMember(target.name, { symbol: target, visibility: imp.visibility });
136810
+ if (target) {
136811
+ addMember(target.name, { symbol: target, visibility: imp.visibility });
136812
+ if (target.shortName) addMember(target.shortName, { symbol: target, visibility: imp.visibility });
136813
+ }
136624
136814
  break;
136625
136815
  }
136626
136816
  case "membership-deep": {
136627
136817
  const target = this.resolveQualifiedNameFrom(importingNamespace, imp.target, indexes);
136628
136818
  if (target) {
136629
136819
  addMember(target.name, { symbol: target, visibility: imp.visibility });
136820
+ if (target.shortName) addMember(target.shortName, { symbol: target, visibility: imp.visibility });
136630
136821
  this.importVisibleMembers(namespaceKeyOf(target), imp.visibility, indexes, addMember, true);
136631
136822
  }
136632
136823
  break;
@@ -136791,7 +136982,7 @@ ${JSON.stringify(message, null, 4)}`);
136791
136982
  function resolveTypeName(typeName, symbol, resolver, indexes, libraryNames) {
136792
136983
  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])/);
136793
136984
  const strippedTypeName = kwMatch ? kwMatch[1] : typeName;
136794
- const rootSegment = strippedTypeName.split("::")[0];
136985
+ const rootSegment = splitQualifiedName(strippedTypeName)[0];
136795
136986
  const resolved = resolver.isLocallyVisible(symbol, 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
136796
136987
  // via :>), not type references — don't flag them as unresolved types.
136797
136988
  strippedTypeName.charCodeAt(0) >= 97 && strippedTypeName.charCodeAt(0) <= 122;
@@ -138339,11 +138530,11 @@ ${this.followingBranchStatements(symbol, lines)}`;
138339
138530
  const packageNames = /* @__PURE__ */ new Set();
138340
138531
  for (const s of allSymbols) {
138341
138532
  if (!isDefinition(s.kind)) continue;
138342
- if (s.name !== unresolvedType) continue;
138533
+ if (s.name !== unquoteName(unresolvedType)) continue;
138343
138534
  if (s.uri === uri) continue;
138344
- const pkg = (s.qualifiedName?.split("::")[0] ?? "").trim();
138535
+ const pkg = s.qualifiedName ? splitQualifiedName(s.qualifiedName)[0] : "";
138345
138536
  if (!pkg || pkg === unresolvedType) continue;
138346
- if (pkg) packageNames.add(pkg);
138537
+ packageNames.add(quoteName(pkg));
138347
138538
  }
138348
138539
  for (const pkg of packageNames) {
138349
138540
  if (this.hasImportForPackage(text, pkg)) {
@@ -138452,7 +138643,7 @@ ${this.followingBranchStatements(symbol, lines)}`;
138452
138643
  const edit = {
138453
138644
  changes: {
138454
138645
  [uri]: [
138455
- import_node.TextEdit.replace(diagnostic.range, newName)
138646
+ import_node.TextEdit.replace(diagnostic.range, quoteName(newName))
138456
138647
  ]
138457
138648
  }
138458
138649
  };
@@ -138561,7 +138752,7 @@ ${childIndent}enum value2;`;
138561
138752
  const edit = {
138562
138753
  changes: {
138563
138754
  [uri]: [
138564
- import_node.TextEdit.replace(diagnostic.range, newName)
138755
+ import_node.TextEdit.replace(diagnostic.range, quoteName(newName))
138565
138756
  ]
138566
138757
  }
138567
138758
  };
@@ -138622,10 +138813,11 @@ ${childIndent}enum value2;`;
138622
138813
  if (diagnostic.code !== "incompatible-port-types") return void 0;
138623
138814
  const msg = diagnostic.message;
138624
138815
  const m2 = msg.match(/'([^']+)'\s+\(([^)]+)\)\s+is connected to\s+'([^']+)'\s+\(([^)]+)\)/);
138625
- if (!m2) return void 0;
138626
- const left = m2[1];
138627
- const leftType = m2[2];
138628
- const right = m2[3];
138816
+ const data = diagnostic.data;
138817
+ const left = data?.left ?? m2?.[1];
138818
+ const leftType = data?.leftType ?? m2?.[2];
138819
+ const right = data?.right ?? m2?.[3];
138820
+ if (!left || !leftType || !right) return void 0;
138629
138821
  const symbolTable = this.documentManager.getWorkspaceSymbolTable();
138630
138822
  const symbolsInUri = symbolTable.getSymbolsForUri(uri);
138631
138823
  const compatible = symbolsInUri.find(
@@ -138640,8 +138832,10 @@ ${childIndent}enum value2;`;
138640
138832
  if (start.line !== end.line) return void 0;
138641
138833
  const segment = (lines[start.line] ?? "").slice(start.character, end.character);
138642
138834
  if (!segment) return void 0;
138643
- const replaced = segment.replace(new RegExp(`\\b${right}\\b`), compatible.name);
138644
- if (replaced === segment) return void 0;
138835
+ const rightPath = [...scanFeaturePaths(segment)].reverse().find((path) => path.parts[path.parts.length - 1] === right);
138836
+ const rightName = rightPath?.qualifiedNames.at(-1)?.segments.at(-1);
138837
+ if (!rightName) return void 0;
138838
+ const replaced = segment.slice(0, rightName.start) + quoteName(compatible.name) + segment.slice(rightName.end);
138645
138839
  const edit = {
138646
138840
  changes: {
138647
138841
  [uri]: [
@@ -138676,12 +138870,14 @@ ${childIndent}enum value2;`;
138676
138870
  diagnostic.range.end.character
138677
138871
  ) : "";
138678
138872
  const m2 = msg.match(/Unresolved constraint reference\s+'([^']+)'(?:\s+in scope\s+'([^']+)')?/);
138873
+ const data = diagnostic.data;
138679
138874
  const expr = rangeExpr && rangeExpr.includes(".") ? rangeExpr : tokenExpr && tokenExpr.includes(".") ? tokenExpr : m2?.[1] ?? "";
138680
- const scopeName = m2?.[2];
138875
+ const scopeName = data?.scopeName ?? m2?.[2];
138681
138876
  if (!expr) return void 0;
138682
138877
  if (!expr.includes(".")) return void 0;
138683
- const parts = expr.split(".");
138684
- if (parts.length < 2) return void 0;
138878
+ const path = [...scanFeaturePaths(expr)].find((path2) => path2.qualifiedNames.length > 1);
138879
+ if (!path) return void 0;
138880
+ const parts = path.parts;
138685
138881
  const root = parts[0];
138686
138882
  const unresolvedLeaf = parts[parts.length - 1];
138687
138883
  const symbolTable = this.documentManager.getWorkspaceSymbolTable();
@@ -138693,7 +138889,7 @@ ${childIndent}enum value2;`;
138693
138889
  const rootType = rootUsage ? rootUsage.typeNames[0] ?? rootUsage.typeName : void 0;
138694
138890
  let memberNames = [];
138695
138891
  if (rootType) {
138696
- const typeDef = allSymbols.find((s) => s.name === rootType && s.kind.endsWith(" def"));
138892
+ const typeDef = symbolTable.findByName(rootType).find((s) => isDefinition(s.kind));
138697
138893
  if (typeDef) {
138698
138894
  memberNames = allSymbols.filter((s) => s.parentId === typeDef.symbolId).map((s) => s.name);
138699
138895
  }
@@ -138715,7 +138911,8 @@ ${childIndent}enum value2;`;
138715
138911
  }
138716
138912
  }
138717
138913
  if (!best || best.dist > 4 || best.name === unresolvedLeaf) return void 0;
138718
- const fixedExpr = `${root}.${best.name}`;
138914
+ const leaf = path.qualifiedNames.at(-1);
138915
+ const fixedExpr = expr.slice(0, leaf.start) + quoteName(best.name) + expr.slice(leaf.end);
138719
138916
  const edit = {
138720
138917
  changes: {
138721
138918
  [uri]: [
@@ -138791,6 +138988,13 @@ ${childIndent}enum value2;`;
138791
138988
  isAttributeTypeContext(text, diagnostic, unresolvedType) {
138792
138989
  const lines = text.split("\n");
138793
138990
  const line = lines[diagnostic.range.start.line] ?? "";
138991
+ const names = [...scanQualifiedNames(line)];
138992
+ const attribute = names.findIndex((name) => line.slice(name.start, name.end) === "attribute");
138993
+ const usage = names[attribute + 1];
138994
+ const type = names[attribute + 2];
138995
+ if (attribute >= 0 && usage && type && type.name === unresolvedType && /^\s*:\s*$/.test(line.slice(usage.end, type.start))) {
138996
+ return true;
138997
+ }
138794
138998
  const beforeRange = line.slice(0, diagnostic.range.start.character);
138795
138999
  const unresolvedInLine = line.slice(diagnostic.range.start.character, diagnostic.range.end.character);
138796
139000
  const escapedType = unresolvedType.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -138803,18 +139007,19 @@ ${childIndent}enum value2;`;
138803
139007
  return /\battribute\s+[A-Za-z_][A-Za-z0-9_]*\s*:\s*[A-Za-z_][A-Za-z0-9_]*\b/.test(beforeRange + unresolvedInLine);
138804
139008
  }
138805
139009
  buildLocalTypeStub(text, diagnostic, unresolvedType, childIndent) {
139010
+ const sourceName = quoteName(unquoteName(unresolvedType));
138806
139011
  if (this.isAttributeTypeContext(text, diagnostic, unresolvedType)) {
138807
139012
  return {
138808
- title: `Create local 'attribute def ${unresolvedType};'`,
139013
+ title: `Create local 'attribute def ${sourceName};'`,
138809
139014
  stubText: `
138810
- ${childIndent}attribute def ${unresolvedType};
139015
+ ${childIndent}attribute def ${sourceName};
138811
139016
  `
138812
139017
  };
138813
139018
  }
138814
139019
  return {
138815
- title: `Create local 'item def ${unresolvedType};'`,
139020
+ title: `Create local 'item def ${sourceName};'`,
138816
139021
  stubText: `
138817
- ${childIndent}item def ${unresolvedType};
139022
+ ${childIndent}item def ${sourceName};
138818
139023
  `
138819
139024
  };
138820
139025
  }
@@ -138850,13 +139055,12 @@ ${childIndent}item def ${unresolvedType};
138850
139055
  }
138851
139056
  function extractDottedTokenAtRange(line, start, end) {
138852
139057
  if (!line || start < 0 || end < 0 || start > line.length || end > line.length) return "";
138853
- const isTokenChar = (ch) => ch >= "a" && ch <= "z" || ch >= "A" && ch <= "Z" || ch >= "0" && ch <= "9" || ch === "_" || ch === ".";
138854
- let left = Math.max(0, start);
138855
- while (left > 0 && isTokenChar(line[left - 1])) left--;
138856
- let right = Math.min(line.length, end);
138857
- while (right < line.length && isTokenChar(line[right])) right++;
138858
- const token = line.slice(left, right).trim();
138859
- return token.includes(".") ? token : "";
139058
+ for (const path of scanFeaturePaths(line)) {
139059
+ if (path.qualifiedNames.length > 1 && path.start <= start && path.end >= end) {
139060
+ return line.slice(path.start, path.end);
139061
+ }
139062
+ }
139063
+ return "";
138860
139064
  }
138861
139065
  function extractLikelyMemberNames(text, excludeName) {
138862
139066
  const names = /* @__PURE__ */ new Set();
@@ -138968,6 +139172,7 @@ ${childIndent}item def ${unresolvedType};
138968
139172
  seen.add(sym.name);
138969
139173
  defItems.push({
138970
139174
  label: sym.name,
139175
+ insertText: quoteName(sym.name),
138971
139176
  kind: this.mapSymbolKindToCompletionKind(sym.kind),
138972
139177
  detail: `${sym.kind}${sym.qualifiedName !== void 0 && sym.qualifiedName !== sym.name ? ` (${sym.qualifiedName})` : ""}`,
138973
139178
  documentation: sym.documentation,
@@ -138988,6 +139193,7 @@ ${childIndent}item def ${unresolvedType};
138988
139193
  seenPorts.add(sym.name);
138989
139194
  items.push({
138990
139195
  label: sym.name,
139196
+ insertText: quoteName(sym.name),
138991
139197
  kind: import_node2.CompletionItemKind.Interface,
138992
139198
  detail: `${sym.kind}${sym.typeNames[0] ? ` : ${sym.typeNames[0]}` : ""}`,
138993
139199
  data: sym.qualifiedName,
@@ -138995,13 +139201,17 @@ ${childIndent}item def ${unresolvedType};
138995
139201
  });
138996
139202
  }
138997
139203
  }
138998
- if (context === "type-annotation") {
138999
- return items.filter((i) => this.isTypeOrDefinitionCompletion(i));
139000
- }
139001
- if (context === "connect-endpoint") {
139002
- return items.filter((i) => this.isConnectContextCompletion(i));
139003
- }
139004
- return items;
139204
+ const filtered = context === "type-annotation" ? items.filter((i) => this.isTypeOrDefinitionCompletion(i)) : context === "connect-endpoint" ? items.filter((i) => this.isConnectContextCompletion(i)) : items;
139205
+ const line = this.documentManager.getText(uri)?.split("\n")[params.position.line] ?? "";
139206
+ const segment = [...scanQualifiedNames(line, true)].flatMap((name) => name.segments).find((name) => name.start <= params.position.character && name.end >= params.position.character);
139207
+ if (!segment) return filtered;
139208
+ return filtered.map((item) => item.insertTextFormat === import_node2.InsertTextFormat.Snippet ? item : {
139209
+ ...item,
139210
+ textEdit: {
139211
+ range: import_node2.Range.create(params.position.line, segment.start, params.position.line, segment.end),
139212
+ newText: item.insertText ?? item.label
139213
+ }
139214
+ });
139005
139215
  }
139006
139216
  resolveCompletion(item) {
139007
139217
  return item;
@@ -139074,6 +139284,108 @@ ${childIndent}item def ${unresolvedType};
139074
139284
  }
139075
139285
  };
139076
139286
 
139287
+ // server/src/symbols/nameReferences.ts
139288
+ var import_node3 = __toESM(require_main3());
139289
+ var NameReferences = class {
139290
+ constructor(documents2) {
139291
+ this.documents = documents2;
139292
+ this.symbols = documents2.getWorkspaceSymbolTable().getAllSymbols();
139293
+ this.indexes = buildSymbolIndexes(this.symbols);
139294
+ }
139295
+ documents;
139296
+ symbols;
139297
+ indexes;
139298
+ resolver = new NamespaceResolver();
139299
+ at(uri, position) {
139300
+ return this.inDocument(uri, position).find((ref) => ref.range.start.line === position.line && ref.range.start.character <= position.character && ref.range.end.character >= position.character);
139301
+ }
139302
+ to(symbol, includeDeclaration = true) {
139303
+ return this.documents.getUris().flatMap((uri) => this.inDocument(uri, void 0, symbol)).filter((ref) => ref.symbol?.symbolId === symbol.symbolId && (includeDeclaration || !ref.isDeclaration));
139304
+ }
139305
+ inDocument(uri, position, target) {
139306
+ const text = this.documents.getText(uri);
139307
+ const parsed = this.documents.get(uri);
139308
+ if (text === void 0 || !parsed) return [];
139309
+ const doc = TextDocument2.create(uri, "sysml", 0, text);
139310
+ const symbols = this.symbols.filter((symbol) => symbol.uri === uri);
139311
+ const braces = parsed.tokenStream.getTokens().filter((token) => token.type === SysMLv2Lexer.LBRACE).map((token) => doc.offsetAt({ line: token.line - 1, character: token.column }));
139312
+ const namespaces = symbols.flatMap((symbol) => {
139313
+ const start = doc.offsetAt(symbol.range.start);
139314
+ const end = doc.offsetAt(symbol.range.end);
139315
+ let lo = 0;
139316
+ let hi = braces.length;
139317
+ while (lo < hi) {
139318
+ const mid = lo + hi >>> 1;
139319
+ if (braces[mid] < start) lo = mid + 1;
139320
+ else hi = mid;
139321
+ }
139322
+ const body = braces[lo];
139323
+ return body === void 0 || body >= end ? [] : [{ symbol, body, end }];
139324
+ }).sort((a, b) => a.end - a.body - (b.end - b.body));
139325
+ const refs = [];
139326
+ const cursor = position ? doc.offsetAt(position) : void 0;
139327
+ for (const path of scanFeaturePaths(text)) {
139328
+ if (cursor !== void 0 && (cursor < path.start || cursor > path.end)) continue;
139329
+ if (target && !path.qualifiedNames.some((name) => name.segments.some((segment) => segment.name === target.name || segment.name === target.shortName))) continue;
139330
+ const namespace = namespaces.find((ns) => ns.body < path.start && path.end <= ns.end);
139331
+ let receiver;
139332
+ for (let group = 0; group < path.qualifiedNames.length; group++) {
139333
+ const qualified = path.qualifiedNames[group];
139334
+ let resolved;
139335
+ for (let index2 = 0; index2 < qualified.segments.length; index2++) {
139336
+ const segment = qualified.segments[index2];
139337
+ const range = import_node3.Range.create(doc.positionAt(segment.start), doc.positionAt(segment.end));
139338
+ let before = segment.start - 1;
139339
+ let after = segment.end;
139340
+ while (before >= 0 && /\s/.test(text[before])) before--;
139341
+ while (after < text.length && /\s/.test(text[after])) after++;
139342
+ const declaration = symbols.find((symbol) => !isAnonymous(symbol) && (symbol.selectionRange.start.line === range.start.line && symbol.selectionRange.start.character === range.start.character && symbol.selectionRange.end.character === range.end.character || symbol.shortName === segment.name && text[before] === "<" && text[after] === ">" && doc.offsetAt(symbol.range.start) <= segment.start && segment.end < doc.offsetAt(symbol.selectionRange.start)));
139343
+ if (declaration) resolved = declaration;
139344
+ else if (index2 > 0) {
139345
+ resolved = resolved ? this.resolver.getResolvedMembers(namespaceKeyOf(resolved), this.indexes).get(segment.name)?.find((entry) => entry.visibility === "public")?.symbol : void 0;
139346
+ } else if (group > 0) {
139347
+ resolved = receiver ? this.resolveFeature(receiver, segment.name) : void 0;
139348
+ } else {
139349
+ resolved = this.resolver.resolveNameIn(
139350
+ namespace?.symbol,
139351
+ joinQualifiedName([segment.name]),
139352
+ this.indexes
139353
+ );
139354
+ }
139355
+ if (cursor !== void 0 && (cursor < segment.start || cursor > segment.end)) continue;
139356
+ if (target && segment.name !== target.name && segment.name !== target.shortName) continue;
139357
+ refs.push({
139358
+ uri,
139359
+ range,
139360
+ name: segment.name,
139361
+ qualifiedName: index2 === qualified.segments.length - 1 ? qualified.name : segment.name,
139362
+ symbol: resolved,
139363
+ isDeclaration: declaration !== void 0
139364
+ });
139365
+ }
139366
+ receiver = resolved;
139367
+ }
139368
+ }
139369
+ return refs;
139370
+ }
139371
+ resolveFeature(receiver, name) {
139372
+ const queue = [receiver];
139373
+ const visited = /* @__PURE__ */ new Set();
139374
+ for (let index2 = 0; index2 < queue.length; index2++) {
139375
+ const owner = queue[index2];
139376
+ if (visited.has(owner)) continue;
139377
+ visited.add(owner);
139378
+ const member = this.resolver.getResolvedMembers(namespaceKeyOf(owner), this.indexes).get(name)?.find((entry) => entry.visibility === "public")?.symbol;
139379
+ if (member) return member;
139380
+ for (const typeName of owner.typeNames) {
139381
+ const type = this.resolver.resolveNameFrom(owner, typeName, this.indexes);
139382
+ if (type && !visited.has(type)) queue.push(type);
139383
+ }
139384
+ }
139385
+ return void 0;
139386
+ }
139387
+ };
139388
+
139077
139389
  // server/src/providers/definitionProvider.ts
139078
139390
  var DefinitionProvider = class {
139079
139391
  constructor(documentManager2) {
@@ -139086,6 +139398,10 @@ ${childIndent}item def ${unresolvedType};
139086
139398
  return null;
139087
139399
  }
139088
139400
  const wsSymbolTable = this.documentManager.getWorkspaceSymbolTable();
139401
+ const reference = new NameReferences(this.documentManager).at(params.textDocument.uri, params.position);
139402
+ if (reference?.symbol && !reference.isDeclaration) {
139403
+ return { uri: reference.symbol.uri, range: reference.symbol.selectionRange };
139404
+ }
139089
139405
  const symbol = symbolTable.findSymbolAtPosition(
139090
139406
  params.textDocument.uri,
139091
139407
  params.position.line,
@@ -139193,7 +139509,7 @@ ${childIndent}item def ${unresolvedType};
139193
139509
  };
139194
139510
 
139195
139511
  // server/src/providers/diagnosticsProvider.ts
139196
- var import_node3 = __toESM(require_main3());
139512
+ var import_node4 = __toESM(require_main3());
139197
139513
  var EXPRESSION_OPERATOR_RE = /(\w\s*[+\-*/^]\s*\w)|(\w\s*\*\*\s*\w)|->|\.(?:\?)|:=|;\s*doc\b|#\w+\s+dependency/;
139198
139514
  var DiagnosticsProvider = class {
139199
139515
  constructor(documentManager2) {
@@ -139245,7 +139561,7 @@ ${childIndent}item def ${unresolvedType};
139245
139561
  message = `'${word}' is a reserved SysML keyword and cannot be used as a name. Consider renaming it (e.g., '${suggestion}').`;
139246
139562
  }
139247
139563
  return {
139248
- severity: import_node3.DiagnosticSeverity.Error,
139564
+ severity: import_node4.DiagnosticSeverity.Error,
139249
139565
  range: {
139250
139566
  start: { line: error.line, character: error.column },
139251
139567
  end: { line: error.line, character: error.column + error.length }
@@ -139314,51 +139630,51 @@ ${childIndent}item def ${unresolvedType};
139314
139630
  };
139315
139631
 
139316
139632
  // server/src/providers/symbolKindMapping.ts
139317
- var import_node4 = __toESM(require_main3());
139633
+ var import_node5 = __toESM(require_main3());
139318
139634
  function toSysMLSymbolKind(kind) {
139319
139635
  switch (kind) {
139320
139636
  // Structural definitions → Class (they *are* types)
139321
139637
  case "part def" /* PartDef */:
139322
139638
  case "occurrence def" /* OccurrenceDef */:
139323
- return import_node4.SymbolKind.Class;
139639
+ return import_node5.SymbolKind.Class;
139324
139640
  // Structural usages → Field (instances / typed features)
139325
139641
  case "part" /* PartUsage */:
139326
139642
  case "occurrence" /* OccurrenceUsage */:
139327
139643
  case "ref" /* RefUsage */:
139328
- return import_node4.SymbolKind.Field;
139644
+ return import_node5.SymbolKind.Field;
139329
139645
  // Attributes
139330
139646
  case "attribute def" /* AttributeDef */:
139331
139647
  case "attribute" /* AttributeUsage */:
139332
- return import_node4.SymbolKind.Property;
139648
+ return import_node5.SymbolKind.Property;
139333
139649
  // Ports & Interfaces → Interface
139334
139650
  case "port def" /* PortDef */:
139335
139651
  case "port" /* PortUsage */:
139336
139652
  case "interface def" /* InterfaceDef */:
139337
139653
  case "interface" /* InterfaceUsage */:
139338
- return import_node4.SymbolKind.Interface;
139654
+ return import_node5.SymbolKind.Interface;
139339
139655
  // Connections
139340
139656
  case "connection def" /* ConnectionDef */:
139341
139657
  case "connection" /* ConnectionUsage */:
139342
- return import_node4.SymbolKind.Interface;
139658
+ return import_node5.SymbolKind.Interface;
139343
139659
  // Behavioral: actions → Method
139344
139660
  case "action def" /* ActionDef */:
139345
139661
  case "action" /* ActionUsage */:
139346
139662
  case "perform action" /* PerformActionUsage */:
139347
- return import_node4.SymbolKind.Method;
139663
+ return import_node5.SymbolKind.Method;
139348
139664
  // Control-flow nodes (fork/join/merge/decide) → Event
139349
139665
  case "fork" /* ForkNode */:
139350
139666
  case "join" /* JoinNode */:
139351
139667
  case "merge" /* MergeNode */:
139352
139668
  case "decide" /* DecisionNode */:
139353
- return import_node4.SymbolKind.Event;
139669
+ return import_node5.SymbolKind.Event;
139354
139670
  // Behavioral: states → Event (better semantic fit than Enum)
139355
139671
  case "state def" /* StateDef */:
139356
139672
  case "state" /* StateUsage */:
139357
139673
  case "exhibit state" /* ExhibitStateUsage */:
139358
- return import_node4.SymbolKind.Event;
139674
+ return import_node5.SymbolKind.Event;
139359
139675
  // Transitions → Event
139360
139676
  case "transition" /* TransitionUsage */:
139361
- return import_node4.SymbolKind.Event;
139677
+ return import_node5.SymbolKind.Event;
139362
139678
  // Requirements → Object
139363
139679
  case "requirement def" /* RequirementDef */:
139364
139680
  case "requirement" /* RequirementUsage */:
@@ -139367,58 +139683,58 @@ ${childIndent}item def ${unresolvedType};
139367
139683
  case "actor" /* ActorUsage */:
139368
139684
  case "subject" /* SubjectUsage */:
139369
139685
  case "stakeholder" /* StakeholderUsage */:
139370
- return import_node4.SymbolKind.Object;
139686
+ return import_node5.SymbolKind.Object;
139371
139687
  // Constraints → Constant (boolean-valued)
139372
139688
  case "constraint def" /* ConstraintDef */:
139373
139689
  case "constraint" /* ConstraintUsage */:
139374
- return import_node4.SymbolKind.Constant;
139690
+ return import_node5.SymbolKind.Constant;
139375
139691
  // Items → Struct (physical things, data)
139376
139692
  case "item def" /* ItemDef */:
139377
139693
  case "item" /* ItemUsage */:
139378
- return import_node4.SymbolKind.Struct;
139694
+ return import_node5.SymbolKind.Struct;
139379
139695
  // Allocations → TypeParameter (cross-concern mapping)
139380
139696
  case "allocation def" /* AllocationDef */:
139381
139697
  case "allocation" /* AllocationUsage */:
139382
- return import_node4.SymbolKind.TypeParameter;
139698
+ return import_node5.SymbolKind.TypeParameter;
139383
139699
  // Enumerations
139384
139700
  case "enum def" /* EnumDef */:
139385
- return import_node4.SymbolKind.Enum;
139701
+ return import_node5.SymbolKind.Enum;
139386
139702
  case "enum" /* EnumUsage */:
139387
- return import_node4.SymbolKind.EnumMember;
139703
+ return import_node5.SymbolKind.EnumMember;
139388
139704
  // Calculations → Function
139389
139705
  case "calc def" /* CalcDef */:
139390
139706
  case "calc" /* CalcUsage */:
139391
139707
  case "analysis case def" /* AnalysisCaseDef */:
139392
139708
  case "verification case def" /* VerificationCaseDef */:
139393
- return import_node4.SymbolKind.Function;
139709
+ return import_node5.SymbolKind.Function;
139394
139710
  // Use cases → Event
139395
139711
  case "use case def" /* UseCaseDef */:
139396
139712
  case "use case" /* UseCaseUsage */:
139397
139713
  case "include use case" /* IncludeUseCaseUsage */:
139398
- return import_node4.SymbolKind.Event;
139714
+ return import_node5.SymbolKind.Event;
139399
139715
  // Views → Namespace
139400
139716
  case "view def" /* ViewDef */:
139401
139717
  case "view" /* ViewUsage */:
139402
139718
  case "viewpoint def" /* ViewpointDef */:
139403
139719
  case "viewpoint" /* ViewpointUsage */:
139404
139720
  case "rendering def" /* RenderingDef */:
139405
- return import_node4.SymbolKind.Namespace;
139721
+ return import_node5.SymbolKind.Namespace;
139406
139722
  // Metadata → TypeParameter
139407
139723
  case "metadata def" /* MetadataDef */:
139408
- return import_node4.SymbolKind.TypeParameter;
139724
+ return import_node5.SymbolKind.TypeParameter;
139409
139725
  // Package
139410
139726
  case "package" /* Package */:
139411
- return import_node4.SymbolKind.Package;
139727
+ return import_node5.SymbolKind.Package;
139412
139728
  // Comments / docs
139413
139729
  case "comment" /* Comment */:
139414
139730
  case "doc" /* Doc */:
139415
- return import_node4.SymbolKind.String;
139731
+ return import_node5.SymbolKind.String;
139416
139732
  // Import / Alias
139417
139733
  case "import" /* Import */:
139418
139734
  case "alias" /* Alias */:
139419
- return import_node4.SymbolKind.Module;
139735
+ return import_node5.SymbolKind.Module;
139420
139736
  default:
139421
- return import_node4.SymbolKind.Variable;
139737
+ return import_node5.SymbolKind.Variable;
139422
139738
  }
139423
139739
  }
139424
139740
 
@@ -139465,7 +139781,7 @@ ${childIndent}item def ${unresolvedType};
139465
139781
  };
139466
139782
 
139467
139783
  // server/src/providers/foldingRangeProvider.ts
139468
- var import_node5 = __toESM(require_main3());
139784
+ var import_node6 = __toESM(require_main3());
139469
139785
  var FoldingRangeProvider = class {
139470
139786
  constructor(documentManager2) {
139471
139787
  this.documentManager = documentManager2;
@@ -139488,7 +139804,7 @@ ${childIndent}item def ${unresolvedType};
139488
139804
  ranges.push({
139489
139805
  startLine: commentStart,
139490
139806
  endLine: i,
139491
- kind: import_node5.FoldingRangeKind.Comment
139807
+ kind: import_node6.FoldingRangeKind.Comment
139492
139808
  });
139493
139809
  commentStart = void 0;
139494
139810
  }
@@ -139501,7 +139817,7 @@ ${childIndent}item def ${unresolvedType};
139501
139817
  ranges.push({
139502
139818
  startLine,
139503
139819
  endLine: i,
139504
- kind: import_node5.FoldingRangeKind.Region
139820
+ kind: import_node6.FoldingRangeKind.Region
139505
139821
  });
139506
139822
  }
139507
139823
  }
@@ -139512,7 +139828,7 @@ ${childIndent}item def ${unresolvedType};
139512
139828
  };
139513
139829
 
139514
139830
  // server/src/providers/formattingProvider.ts
139515
- var import_node6 = __toESM(require_main3());
139831
+ var import_node7 = __toESM(require_main3());
139516
139832
  var FormattingProvider = class {
139517
139833
  constructor(documents2) {
139518
139834
  this.documents = documents2;
@@ -139528,8 +139844,8 @@ ${childIndent}item def ${unresolvedType};
139528
139844
  const formatted = this.formatSysML(text, indent);
139529
139845
  if (formatted === text) return [];
139530
139846
  return [
139531
- import_node6.TextEdit.replace(
139532
- import_node6.Range.create(0, 0, doc.lineCount, 0),
139847
+ import_node7.TextEdit.replace(
139848
+ import_node7.Range.create(0, 0, doc.lineCount, 0),
139533
139849
  formatted
139534
139850
  )
139535
139851
  ];
@@ -139543,7 +139859,7 @@ ${childIndent}item def ${unresolvedType};
139543
139859
  const rangeText = doc.getText(params.range);
139544
139860
  const formatted = this.formatSysML(rangeText, indent);
139545
139861
  if (formatted === rangeText) return [];
139546
- return [import_node6.TextEdit.replace(params.range, formatted)];
139862
+ return [import_node7.TextEdit.replace(params.range, formatted)];
139547
139863
  }
139548
139864
  formatSysML(text, indent) {
139549
139865
  const lines = text.split("\n");
@@ -139679,7 +139995,7 @@ ${childIndent}item def ${unresolvedType};
139679
139995
  };
139680
139996
 
139681
139997
  // server/src/providers/hoverProvider.ts
139682
- var import_node7 = __toESM(require_main3());
139998
+ var import_node8 = __toESM(require_main3());
139683
139999
  var HoverProvider = class {
139684
140000
  constructor(documentManager2) {
139685
140001
  this.documentManager = documentManager2;
@@ -139696,12 +140012,13 @@ ${childIndent}item def ${unresolvedType};
139696
140012
  return null;
139697
140013
  }
139698
140014
  const text = this.documentManager.getText(params.textDocument.uri);
139699
- const word = text ? this.getWordAtPosition(text, params.position.line, params.position.character) : void 0;
139700
- if (word && word.includes("::")) {
140015
+ const reference = new NameReferences(this.documentManager).at(params.textDocument.uri, params.position);
140016
+ const word = reference?.qualifiedName ?? (text ? this.getWordAtPosition(text, params.position.line, params.position.character) : void 0);
140017
+ if (word && word.includes("::") && !reference?.symbol) {
139701
140018
  const libHover = this.buildLibraryHover(word);
139702
140019
  if (libHover) return libHover;
139703
140020
  }
139704
- const symbol = symbolTable.findSymbolAtPosition(
140021
+ const symbol = reference?.symbol ?? symbolTable.findSymbolAtPosition(
139705
140022
  params.textDocument.uri,
139706
140023
  params.position.line,
139707
140024
  params.position.character
@@ -139753,7 +140070,7 @@ ${symbol.documentation}`);
139753
140070
  if (hoverDiags.length > 0) {
139754
140071
  lines.push("\n---\n**Semantic Feedback**");
139755
140072
  for (const d of hoverDiags.slice(0, 3)) {
139756
- const sev = d.severity === import_node7.DiagnosticSeverity.Error ? "Error" : d.severity === import_node7.DiagnosticSeverity.Warning ? "Warning" : "Hint";
140073
+ const sev = d.severity === import_node8.DiagnosticSeverity.Error ? "Error" : d.severity === import_node8.DiagnosticSeverity.Warning ? "Warning" : "Hint";
139757
140074
  lines.push(`- **${sev}**: ${d.message}`);
139758
140075
  const hint = this.getRepairHint(String(d.code ?? ""));
139759
140076
  if (hint) {
@@ -139762,12 +140079,12 @@ ${symbol.documentation}`);
139762
140079
  }
139763
140080
  }
139764
140081
  const content = {
139765
- kind: import_node7.MarkupKind.Markdown,
140082
+ kind: import_node8.MarkupKind.Markdown,
139766
140083
  value: lines.join("\n")
139767
140084
  };
139768
140085
  return {
139769
140086
  contents: content,
139770
- range: symbol.selectionRange
140087
+ range: reference?.range ?? symbol.selectionRange
139771
140088
  };
139772
140089
  }
139773
140090
  /**
@@ -139794,7 +140111,7 @@ ${info.documentation}`);
139794
140111
  }
139795
140112
  return {
139796
140113
  contents: {
139797
- kind: import_node7.MarkupKind.Markdown,
140114
+ kind: import_node8.MarkupKind.Markdown,
139798
140115
  value: lines.join("\n")
139799
140116
  }
139800
140117
  };
@@ -139834,7 +140151,7 @@ ${info.documentation}`);
139834
140151
  };
139835
140152
 
139836
140153
  // server/src/providers/keywordValidator.ts
139837
- var import_node8 = __toESM(require_main3());
140154
+ var import_node9 = __toESM(require_main3());
139838
140155
 
139839
140156
  // server/src/utils/emptyNames.ts
139840
140157
  var EMPTY_NAME_MESSAGE = "Empty name '': a name in single quotes must contain at least one character";
@@ -140233,7 +140550,7 @@ ${info.documentation}`);
140233
140550
  const line2 = (token.line ?? 1) - 1;
140234
140551
  const char2 = token.column ?? 0;
140235
140552
  diagnostics.push({
140236
- severity: import_node8.DiagnosticSeverity.Error,
140553
+ severity: import_node9.DiagnosticSeverity.Error,
140237
140554
  range: { start: { line: line2, character: char2 }, end: { line: line2, character: char2 + 2 } },
140238
140555
  message: EMPTY_NAME_MESSAGE,
140239
140556
  source: "sysml",
@@ -140251,7 +140568,7 @@ ${info.documentation}`);
140251
140568
  const char = token.column ?? 0;
140252
140569
  const message = `Unknown keyword '${text}'. Did you mean '${suggestion}'?`;
140253
140570
  diagnostics.push({
140254
- severity: import_node8.DiagnosticSeverity.Error,
140571
+ severity: import_node9.DiagnosticSeverity.Error,
140255
140572
  range: {
140256
140573
  start: { line, character: char },
140257
140574
  end: { line, character: char + text.length }
@@ -140271,115 +140588,50 @@ ${info.documentation}`);
140271
140588
  }
140272
140589
  documentManager;
140273
140590
  provideReferences(params) {
140274
- const result = this.documentManager.get(params.textDocument.uri);
140275
- if (!result) {
140276
- return [];
140277
- }
140278
- const symbolTable = this.documentManager.getWorkspaceSymbolTable();
140279
- const symbol = symbolTable.findSymbolAtPosition(
140280
- params.textDocument.uri,
140281
- params.position.line,
140282
- params.position.character
140283
- );
140284
- if (!symbol || isAnonymous(symbol)) {
140285
- return [];
140286
- }
140287
- const references = symbolTable.findReferences(symbol.name);
140288
- const locations = [];
140289
- for (const ref of references) {
140290
- locations.push({
140291
- uri: ref.uri,
140292
- range: ref.selectionRange
140293
- });
140294
- }
140295
- if (params.context.includeDeclaration) {
140296
- }
140297
- return locations;
140591
+ const references = new NameReferences(this.documentManager);
140592
+ const ref = references.at(params.textDocument.uri, params.position);
140593
+ return ref?.symbol ? references.to(ref.symbol, params.context.includeDeclaration).map(({ uri, range }) => ({ uri, range })) : [];
140298
140594
  }
140299
140595
  };
140300
140596
 
140301
140597
  // server/src/providers/renameProvider.ts
140302
- function findWordOccurrences(line, word) {
140303
- const positions = [];
140304
- let from = 0;
140305
- while (from <= line.length - word.length) {
140306
- const idx = line.indexOf(word, from);
140307
- if (idx < 0) break;
140308
- if ((idx === 0 || !isIdentPart(line.charCodeAt(idx - 1))) && (idx + word.length >= line.length || !isIdentPart(line.charCodeAt(idx + word.length)))) {
140309
- positions.push(idx);
140310
- }
140311
- from = idx + 1;
140312
- }
140313
- return positions;
140314
- }
140598
+ var import_node10 = __toESM(require_main3());
140315
140599
  var RenameProvider = class {
140316
140600
  constructor(documentManager2) {
140317
140601
  this.documentManager = documentManager2;
140318
140602
  }
140319
140603
  documentManager;
140320
- /**
140321
- * Check if the token at position is renameable and return its range.
140322
- */
140323
140604
  prepareRename(params) {
140324
- const symbolTable = this.documentManager.getSymbolTable(params.textDocument.uri);
140325
- if (!symbolTable) return null;
140326
- const symbol = symbolTable.findSymbolAtPosition(
140327
- params.textDocument.uri,
140328
- params.position.line,
140329
- params.position.character
140330
- );
140331
- if (!symbol || isAnonymous(symbol)) return null;
140332
- return symbol.selectionRange;
140605
+ const ref = new NameReferences(this.documentManager).at(params.textDocument.uri, params.position);
140606
+ return ref?.symbol ? ref.range : null;
140333
140607
  }
140334
- /**
140335
- * Perform the rename — update the symbol and all references.
140336
- */
140337
140608
  provideRename(params) {
140338
- const symbolTable = this.documentManager.getSymbolTable(params.textDocument.uri);
140339
- if (!symbolTable) return null;
140340
- const symbol = symbolTable.findSymbolAtPosition(
140341
- params.textDocument.uri,
140342
- params.position.line,
140343
- params.position.character
140344
- );
140345
- if (!symbol || isAnonymous(symbol)) return null;
140346
- const text = this.documentManager.getText(params.textDocument.uri);
140347
- if (!text) return null;
140348
- const edits = [];
140349
- const oldName = symbol.name;
140350
- const newName = params.newName;
140351
- const references = symbolTable.findReferences(oldName);
140352
- for (const ref of references) {
140353
- if (ref.uri === params.textDocument.uri) {
140354
- edits.push({
140355
- range: ref.selectionRange,
140356
- newText: newName
140357
- });
140358
- }
140609
+ const references = new NameReferences(this.documentManager);
140610
+ const ref = references.at(params.textDocument.uri, params.position);
140611
+ if (!ref?.symbol) return null;
140612
+ const invalidControl = [...params.newName].some((ch) => {
140613
+ const code = ch.charCodeAt(0);
140614
+ return code < 32 && !" \n\r".includes(ch) || code === 127;
140615
+ });
140616
+ if (!params.newName || invalidControl) {
140617
+ throw new import_node10.ResponseError(import_node10.ErrorCodes.InvalidParams, "A SysML name must be non-empty and contain printable characters or escaped whitespace.");
140359
140618
  }
140360
- const lines = text.split("\n");
140361
- for (let i = 0; i < lines.length; i++) {
140362
- for (const col of findWordOccurrences(lines[i], oldName)) {
140363
- const range = {
140364
- start: { line: i, character: col },
140365
- end: { line: i, character: col + oldName.length }
140366
- };
140367
- if (!edits.some((e) => e.range.start.line === i && e.range.start.character === col)) {
140368
- edits.push({ range, newText: newName });
140369
- }
140370
- }
140619
+ const parsed = params.newName.startsWith("'") ? readNameAt(params.newName, 0) : void 0;
140620
+ if (params.newName.startsWith("'") && parsed?.end !== params.newName.length) {
140621
+ throw new import_node10.ResponseError(import_node10.ErrorCodes.InvalidParams, "The quoted SysML name is incomplete or contains an invalid escape sequence.");
140371
140622
  }
140372
- if (edits.length === 0) return null;
140373
- return {
140374
- changes: {
140375
- [params.textDocument.uri]: edits
140376
- }
140377
- };
140623
+ const newText = quoteName(parsed?.name ?? params.newName);
140624
+ const changes = {};
140625
+ for (const occurrence of references.to(ref.symbol)) {
140626
+ if (occurrence.name !== ref.name) continue;
140627
+ (changes[occurrence.uri] ??= []).push({ range: occurrence.range, newText });
140628
+ }
140629
+ return Object.keys(changes).length > 0 ? { changes } : null;
140378
140630
  }
140379
140631
  };
140380
140632
 
140381
140633
  // server/src/providers/semanticTokensProvider.ts
140382
- var import_node9 = __toESM(require_main3());
140634
+ var import_node11 = __toESM(require_main3());
140383
140635
  var OPERATOR_TOKENS = /* @__PURE__ */ new Set([
140384
140636
  SysMLv2Lexer.BANG_EQ_EQ,
140385
140637
  // !==
@@ -140520,7 +140772,7 @@ ${info.documentation}`);
140520
140772
  if (this.tokenCache && this.tokenCache.uri === uri && this.tokenCache.version === version) {
140521
140773
  return this.tokenCache.tokens;
140522
140774
  }
140523
- const builder = new import_node9.SemanticTokensBuilder();
140775
+ const builder = new import_node11.SemanticTokensBuilder();
140524
140776
  const result = this.documentManager.get(uri);
140525
140777
  if (!result) {
140526
140778
  return builder.build();
@@ -140600,7 +140852,7 @@ ${info.documentation}`);
140600
140852
  };
140601
140853
 
140602
140854
  // server/src/providers/semanticValidator.ts
140603
- var import_node10 = __toESM(require_main3());
140855
+ var import_node12 = __toESM(require_main3());
140604
140856
  var CONSTRAINT_KEYWORDS = /* @__PURE__ */ new Set([
140605
140857
  "and",
140606
140858
  "or",
@@ -140622,6 +140874,13 @@ ${info.documentation}`);
140622
140874
  "assert",
140623
140875
  "assume"
140624
140876
  ]);
140877
+ var CONNECTOR_KINDS = /* @__PURE__ */ new Set([
140878
+ "connection" /* ConnectionUsage */,
140879
+ "interface" /* InterfaceUsage */,
140880
+ "allocation" /* AllocationUsage */,
140881
+ "flow" /* FlowUsage */,
140882
+ "succession flow" /* SuccessionFlowUsage */
140883
+ ]);
140625
140884
  var SemanticValidator = class _SemanticValidator {
140626
140885
  constructor(documentManager2) {
140627
140886
  this.documentManager = documentManager2;
@@ -140698,7 +140957,7 @@ ${info.documentation}`);
140698
140957
  diagnostics.push(...this.checkAmbiguousNamespaceName(symbols, allSymbols));
140699
140958
  diagnostics.push(...this.checkUnusedDefinitions(allSymbols, uri));
140700
140959
  diagnostics.push(...this.checkRedefinitionMultiplicity(symbols, indexes, text));
140701
- diagnostics.push(...this.checkPortCompatibility(text, uri, indexes));
140960
+ diagnostics.push(...this.checkPortCompatibility(text, uri, symbols, indexes));
140702
140961
  diagnostics.push(...this.checkConstraintBodyReferences(text, uri, symbols, indexes));
140703
140962
  diagnostics.push(...this.checkCircularSpecialization(symbols, indexes));
140704
140963
  diagnostics.push(...this.checkUnsatisfiedRequirements(symbols, indexes));
@@ -140719,7 +140978,7 @@ ${info.documentation}`);
140719
140978
  const { resolved, strippedTypeName: typeName } = resolveTypeName(symbol.typeName, symbol, this.namespaceResolver, indexes, libraryNames);
140720
140979
  if (resolved) return [];
140721
140980
  const isMandatory = symbol.multiplicityRange && symbol.multiplicityRange.lower >= 1;
140722
- const severity = isMandatory ? import_node10.DiagnosticSeverity.Error : import_node10.DiagnosticSeverity.Warning;
140981
+ const severity = isMandatory ? import_node12.DiagnosticSeverity.Error : import_node12.DiagnosticSeverity.Warning;
140723
140982
  let message = `Type '${typeName}' is not defined in the current document or standard library`;
140724
140983
  if (isMandatory) {
140725
140984
  const multStr = symbol.multiplicity ?? "1";
@@ -140745,7 +141004,7 @@ ${info.documentation}`);
140745
141004
  const { lower, upper } = symbol.multiplicityRange;
140746
141005
  if (typeof upper === "number" && lower > upper) {
140747
141006
  return [{
140748
- severity: import_node10.DiagnosticSeverity.Error,
141007
+ severity: import_node12.DiagnosticSeverity.Error,
140749
141008
  range: symbol.selectionRange,
140750
141009
  message: `Invalid multiplicity [${symbol.multiplicity}]: lower bound (${lower}) exceeds upper bound (${upper})`,
140751
141010
  source: "sysml",
@@ -140754,7 +141013,7 @@ ${info.documentation}`);
140754
141013
  }
140755
141014
  if (lower < 0) {
140756
141015
  return [{
140757
- severity: import_node10.DiagnosticSeverity.Error,
141016
+ severity: import_node12.DiagnosticSeverity.Error,
140758
141017
  range: symbol.selectionRange,
140759
141018
  message: `Invalid multiplicity [${symbol.multiplicity}]: lower bound cannot be negative`,
140760
141019
  source: "sysml",
@@ -140778,7 +141037,7 @@ ${info.documentation}`);
140778
141037
  );
140779
141038
  if (!hasEnumValues) {
140780
141039
  return [{
140781
- severity: import_node10.DiagnosticSeverity.Information,
141040
+ severity: import_node12.DiagnosticSeverity.Information,
140782
141041
  range: symbol.selectionRange,
140783
141042
  message: `Enumeration '${displayName(symbol)}' has no enum values defined`,
140784
141043
  source: "sysml",
@@ -140798,7 +141057,7 @@ ${info.documentation}`);
140798
141057
  const ch = symbol.name[0];
140799
141058
  if (ch === ch.toLowerCase() && ch !== ch.toUpperCase()) {
140800
141059
  return [{
140801
- severity: import_node10.DiagnosticSeverity.Hint,
141060
+ severity: import_node12.DiagnosticSeverity.Hint,
140802
141061
  range: symbol.selectionRange,
140803
141062
  message: `Definition '${symbol.name}' should use PascalCase`,
140804
141063
  source: "sysml",
@@ -140810,7 +141069,7 @@ ${info.documentation}`);
140810
141069
  const ch = symbol.name[0];
140811
141070
  if (ch === ch.toUpperCase() && ch !== ch.toLowerCase()) {
140812
141071
  return [{
140813
- severity: import_node10.DiagnosticSeverity.Hint,
141072
+ severity: import_node12.DiagnosticSeverity.Hint,
140814
141073
  range: symbol.selectionRange,
140815
141074
  message: `Usage '${symbol.name}' should use camelCase`,
140816
141075
  source: "sysml",
@@ -140829,7 +141088,7 @@ ${info.documentation}`);
140829
141088
  if (!isDefinition(symbol.kind)) return [];
140830
141089
  if (symbol.documentation) return [];
140831
141090
  return [{
140832
- severity: import_node10.DiagnosticSeverity.Information,
141091
+ severity: import_node12.DiagnosticSeverity.Information,
140833
141092
  range: symbol.selectionRange,
140834
141093
  message: `Definition '${displayName(symbol)}' has no documentation`,
140835
141094
  source: "sysml",
@@ -140848,23 +141107,23 @@ ${info.documentation}`);
140848
141107
  );
140849
141108
  const defsInScope = targetUri ? defs.filter((def) => def.uri === targetUri) : defs;
140850
141109
  const referencedTypes = new Set(
140851
- symbols.filter((s) => s.kind !== "package" /* Package */).flatMap((s) => s.typeNames)
141110
+ symbols.filter((s) => s.kind !== "package" /* Package */).flatMap((s) => s.typeNames.flatMap((name) => [name, splitQualifiedName(name).at(-1)]))
140852
141111
  );
140853
141112
  for (const s of symbols) {
140854
141113
  if (s.exposeTargets) {
140855
141114
  for (const target of s.exposeTargets) {
140856
- const simpleName = target.replace(/::\*{1,2}$/, "").split("::").pop();
141115
+ const simpleName = splitQualifiedName(target.replace(/::\*{1,2}$/, "")).pop();
140857
141116
  if (simpleName) referencedTypes.add(simpleName);
140858
141117
  }
140859
141118
  }
140860
141119
  }
140861
141120
  const diagnostics = [];
140862
141121
  for (const def of defsInScope) {
140863
- const isReferenced = referencedTypes.has(def.name);
141122
+ const isReferenced = referencedTypes.has(def.name) || def.shortName !== void 0 && referencedTypes.has(def.shortName);
140864
141123
  const hasBaseType = (def.typeNames?.length ?? 0) > 0;
140865
141124
  if (!isReferenced && !hasBaseType) {
140866
141125
  diagnostics.push({
140867
- severity: import_node10.DiagnosticSeverity.Warning,
141126
+ severity: import_node12.DiagnosticSeverity.Warning,
140868
141127
  range: def.selectionRange,
140869
141128
  message: `Definition '${def.name}' is not referenced by any usage in the workspace`,
140870
141129
  source: "sysml",
@@ -140919,7 +141178,7 @@ ${info.documentation}`);
140919
141178
  opts?.text ? [opts.text] : []
140920
141179
  ));
140921
141180
  if (opts?.text && opts.uri) {
140922
- diagnostics.push(...instance.checkPortCompatibility(opts.text, opts.uri, indexes));
141181
+ diagnostics.push(...instance.checkPortCompatibility(opts.text, opts.uri, symbolsInUri, indexes));
140923
141182
  diagnostics.push(...instance.checkConstraintBodyReferences(opts.text, opts.uri, symbolsInUri, indexes));
140924
141183
  }
140925
141184
  return instance.dedupeDiagnostics(diagnostics);
@@ -140939,7 +141198,7 @@ ${info.documentation}`);
140939
141198
  const cycle = this.followSpecializationChain(def.name, def.typeNames, visited, indexes);
140940
141199
  if (cycle) {
140941
141200
  diagnostics.push({
140942
- severity: import_node10.DiagnosticSeverity.Error,
141201
+ severity: import_node12.DiagnosticSeverity.Error,
140943
141202
  range: def.selectionRange,
140944
141203
  message: `Circular specialization: ${cycle.join(" :> ")} :> ${cycle[0]}`,
140945
141204
  source: "sysml",
@@ -141027,7 +141286,7 @@ ${info.documentation}`);
141027
141286
  const isSatisfied = satisfiedNames.has(req.name) || req.qualifiedName !== void 0 && satisfiedNames.has(req.qualifiedName);
141028
141287
  if (!isSatisfied) {
141029
141288
  diagnostics.push({
141030
- severity: import_node10.DiagnosticSeverity.Warning,
141289
+ severity: import_node12.DiagnosticSeverity.Warning,
141031
141290
  range: req.selectionRange,
141032
141291
  message: `Requirement '${req.name}' is not satisfied by any element`,
141033
141292
  source: "sysml",
@@ -141164,7 +141423,7 @@ ${info.documentation}`);
141164
141423
  if (!isVerified) {
141165
141424
  const message = isSatisfied ? `Requirement '${req.name}' is satisfied but has no verification case \u2014 consider adding: verify ${req.name} by <VerificationCase>;` : `Requirement '${req.name}' has no verification case \u2014 consider adding: verify ${req.name} by <VerificationCase>;`;
141166
141425
  diagnostics.push({
141167
- severity: import_node10.DiagnosticSeverity.Warning,
141426
+ severity: import_node12.DiagnosticSeverity.Warning,
141168
141427
  range: req.selectionRange,
141169
141428
  message,
141170
141429
  source: "sysml",
@@ -141224,7 +141483,7 @@ ${info.documentation}`);
141224
141483
  const hasFilter = view.viewFilters && view.viewFilters.length > 0;
141225
141484
  if (!hasExpose && !hasFilter) {
141226
141485
  diagnostics.push({
141227
- severity: import_node10.DiagnosticSeverity.Information,
141486
+ severity: import_node12.DiagnosticSeverity.Information,
141228
141487
  range: view.selectionRange,
141229
141488
  message: `View '${view.name}' has no expose or filter directives \u2014 it will show all elements`,
141230
141489
  source: "sysml",
@@ -141264,7 +141523,7 @@ ${info.documentation}`);
141264
141523
  const upperOk = baseUpper === "*" || curUpper !== "*" && curUpper <= baseUpper;
141265
141524
  if (lowerOk && upperOk) continue;
141266
141525
  diagnostics.push({
141267
- severity: import_node10.DiagnosticSeverity.Error,
141526
+ severity: import_node12.DiagnosticSeverity.Error,
141268
141527
  range: s.selectionRange,
141269
141528
  message: `Redefinition multiplicity [${s.multiplicity ?? "?"}] is incompatible with base '${base.name}' multiplicity [${base.multiplicity ?? "?"}]`,
141270
141529
  source: "sysml",
@@ -141282,17 +141541,21 @@ ${info.documentation}`);
141282
141541
  * - The connection is within an interface usage
141283
141542
  * - Both ports are untyped (empty port defs with no features)
141284
141543
  */
141285
- checkPortCompatibility(text, uri, indexes) {
141544
+ checkPortCompatibility(text, uri, symbolsInUri, indexes) {
141286
141545
  if (!text) return [];
141287
141546
  const diagnostics = [];
141288
141547
  const lines = text.split("\n");
141289
- const re = /\bconnect\s+([A-Za-z_][\w.]*)\s+to\s+([A-Za-z_][\w.]*)/g;
141290
- let m2;
141291
- while ((m2 = re.exec(text)) !== null) {
141292
- const left = m2[1].split(".").pop();
141293
- const right = m2[2].split(".").pop();
141294
- const lSym = (indexes.portsByName.get(left) ?? [])[0];
141295
- const rSym = (indexes.portsByName.get(right) ?? [])[0];
141548
+ const paths = [...scanFeaturePaths(text)];
141549
+ for (let i = 0; i + 3 < paths.length; i++) {
141550
+ const [connect, leftEnd, to, rightEnd] = paths.slice(i, i + 4);
141551
+ 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;
141552
+ const leftPath = [...leftEnd.parts];
141553
+ const rightPath = [...rightEnd.parts];
141554
+ const left = leftPath[leftPath.length - 1];
141555
+ const right = rightPath[rightPath.length - 1];
141556
+ const scope = this.connectorScope(symbolsInUri, this.indexToRange(text, connect.start, 0).start, indexes);
141557
+ const lSym = this.resolveConnectorEnd(leftPath, scope, indexes);
141558
+ const rSym = this.resolveConnectorEnd(rightPath, scope, indexes);
141296
141559
  if (!lSym || !rSym) continue;
141297
141560
  const lType = lSym.typeNames[0] ?? lSym.typeName;
141298
141561
  const rType = rSym.typeNames[0] ?? rSym.typeName;
@@ -141300,10 +141563,10 @@ ${info.documentation}`);
141300
141563
  if (lType === "~" + rType || rType === "~" + lType) continue;
141301
141564
  if (lType.startsWith("~") && lType.slice(1) === rType) continue;
141302
141565
  if (rType.startsWith("~") && rType.slice(1) === lType) continue;
141303
- const matchLine = text.substring(0, m2.index).split("\n").length - 1;
141566
+ const matchLine = text.substring(0, connect.start).split("\n").length - 1;
141304
141567
  let insideInterfaceDef = false;
141305
- for (let i = matchLine; i >= 0 && i >= matchLine - 30; i--) {
141306
- const line = (lines[i] || "").trim();
141568
+ for (let i2 = matchLine; i2 >= 0 && i2 >= matchLine - 30; i2--) {
141569
+ const line = (lines[i2] || "").trim();
141307
141570
  if (/\binterface\s+def\b/.test(line)) {
141308
141571
  insideInterfaceDef = true;
141309
141572
  break;
@@ -141311,7 +141574,7 @@ ${info.documentation}`);
141311
141574
  if (/^\s*package\b/.test(line)) break;
141312
141575
  }
141313
141576
  if (insideInterfaceDef) continue;
141314
- const precedingText = text.substring(Math.max(0, m2.index - 300), m2.index);
141577
+ const precedingText = text.substring(Math.max(0, connect.start - 300), connect.start);
141315
141578
  if (/\binterface\s+\w[\w']*(:\w[\w']*)?\s*$/m.test(precedingText)) continue;
141316
141579
  const lDefSyms = indexes.byName.get(lType) ?? [];
141317
141580
  const rDefSyms = indexes.byName.get(rType) ?? [];
@@ -141330,18 +141593,67 @@ ${info.documentation}`);
141330
141593
  const hasSharedFeature = rChildren.some((c) => lChildNames.has(c.name));
141331
141594
  if (hasSharedFeature) continue;
141332
141595
  }
141333
- const range = this.indexToRange(text, m2.index, m2[0].length);
141596
+ const range = this.indexToRange(text, connect.start, rightEnd.end - connect.start);
141334
141597
  diagnostics.push({
141335
- severity: import_node10.DiagnosticSeverity.Warning,
141598
+ severity: import_node12.DiagnosticSeverity.Warning,
141336
141599
  range,
141337
141600
  message: `Port compatibility issue: '${left}' (${lType}) is connected to '${right}' (${rType})`,
141338
141601
  source: "sysml",
141339
141602
  code: "incompatible-port-types",
141340
- data: { uri }
141603
+ data: { uri, left, right, leftType: lType }
141341
141604
  });
141342
141605
  }
141343
141606
  return diagnostics;
141344
141607
  }
141608
+ /**
141609
+ * The innermost element around `position` that owns a connector declared
141610
+ * there: the connector's own symbol, when it has one, is skipped.
141611
+ */
141612
+ connectorScope(symbols, position, indexes) {
141613
+ const before = (a, b) => a.line < b.line || a.line === b.line && a.character <= b.character;
141614
+ const size = (r) => (r.end.line - r.start.line) * 1e6 + (r.end.character - r.start.character);
141615
+ let scope;
141616
+ for (const s of symbols) {
141617
+ if (!before(s.range.start, position) || !before(position, s.range.end)) continue;
141618
+ if (!scope || size(s.range) < size(scope.range)) scope = s;
141619
+ }
141620
+ while (scope && CONNECTOR_KINDS.has(scope.kind)) scope = ownerOf(scope, indexes);
141621
+ return scope;
141622
+ }
141623
+ /**
141624
+ * The port that a connector end (`a.p`, `a.p.q`) names, resolved from
141625
+ * `scope` outward: its first segment is a feature of `scope` or of one of
141626
+ * its owners, each next one a feature of the one before. Two parts can each
141627
+ * have a port of the same name, so an end is never matched by its last
141628
+ * segment alone, except when the path does not resolve and the workspace
141629
+ * has only one port of that name.
141630
+ */
141631
+ resolveConnectorEnd(path, scope, indexes) {
141632
+ let feature;
141633
+ for (let namespace = scope; namespace && !feature; namespace = ownerOf(namespace, indexes)) {
141634
+ feature = this.findFeature(namespace, path[0], indexes);
141635
+ }
141636
+ for (const name of path.slice(1)) {
141637
+ feature = feature && this.findFeature(feature, name, indexes);
141638
+ }
141639
+ if (feature) return feature.kind === "port" /* PortUsage */ ? feature : void 0;
141640
+ const sameName = indexes.portsByName.get(path[path.length - 1]) ?? [];
141641
+ return sameName.length === 1 ? sameName[0] : void 0;
141642
+ }
141643
+ /** The feature `name` of `owner`: its own member, else a member of one of its types or their supertypes. */
141644
+ findFeature(owner, name, indexes) {
141645
+ const own = (indexes.byParent.get(namespaceKeyOf(owner)) ?? []).find((s) => s.name === name);
141646
+ if (own) return own;
141647
+ for (const typeName of owner.typeNames) {
141648
+ const type = this.namespaceResolver.resolveNameFrom(owner, typeName, indexes);
141649
+ if (!type || !isDefinition(type.kind)) continue;
141650
+ for (const definition of this.getSpecializationHierarchy(type, indexes).flat()) {
141651
+ const member = (indexes.byParent.get(namespaceKeyOf(definition)) ?? []).find((s) => s.name === name);
141652
+ if (member) return member;
141653
+ }
141654
+ }
141655
+ return void 0;
141656
+ }
141345
141657
  /**
141346
141658
  * Resolve the full type hierarchy for a type name by following
141347
141659
  * specialization chains transitively (max depth 10).
@@ -141378,7 +141690,7 @@ ${info.documentation}`);
141378
141690
  const startInBody = trimStart >= 0 ? trimStart : 0;
141379
141691
  const trimmedLen = Math.max(1, b.body.trim().length);
141380
141692
  diagnostics.push({
141381
- severity: import_node10.DiagnosticSeverity.Warning,
141693
+ severity: import_node12.DiagnosticSeverity.Warning,
141382
141694
  range: this.indexToRange(text, b.bodyOffset + startInBody, trimmedLen),
141383
141695
  message: "Invalid constraint body: expected expression, found documentation text",
141384
141696
  source: "sysml",
@@ -141389,17 +141701,13 @@ ${info.documentation}`);
141389
141701
  }
141390
141702
  const parent = this.findConstraintScopeSymbol(symbolsInUri, indexes, b.startLine);
141391
141703
  if (!parent) continue;
141392
- const parentMembers = indexes.byParent.get(namespaceKeyOf(parent)) ?? [];
141704
+ const parentMembers = this.getConstraintScopeMembers(parent, indexes);
141393
141705
  if (parentMembers.length === 0) continue;
141394
- const ignoredRanges = this.getIgnoredBodyRanges(b.body);
141395
- const idRe = /\b([A-Za-z_][\w]*(?:\.[A-Za-z_][\w]*)*)\b/g;
141396
- let im;
141397
- while ((im = idRe.exec(b.body)) !== null) {
141398
- if (this.isIndexInRanges(im.index, ignoredRanges)) continue;
141399
- const expr = im[1];
141706
+ for (const reference of scanFeaturePaths(b.body)) {
141707
+ const expr = reference.name;
141400
141708
  if (this.isConstraintKeyword(expr)) continue;
141401
141709
  if (/^\d/.test(expr)) continue;
141402
- const path = expr.split(".");
141710
+ const path = [...reference.parts];
141403
141711
  const ok = this.resolvePathFromParent(path, parentMembers, indexes);
141404
141712
  if (ok) continue;
141405
141713
  if (path.length === 1) {
@@ -141408,14 +141716,14 @@ ${info.documentation}`);
141408
141716
  continue;
141409
141717
  }
141410
141718
  }
141411
- const absoluteStart = b.bodyOffset + im.index;
141719
+ const absoluteStart = b.bodyOffset + reference.start;
141412
141720
  diagnostics.push({
141413
- severity: import_node10.DiagnosticSeverity.Warning,
141414
- range: this.indexToRange(text, absoluteStart, expr.length),
141721
+ severity: import_node12.DiagnosticSeverity.Warning,
141722
+ range: this.indexToRange(text, absoluteStart, reference.end - reference.start),
141415
141723
  message: `Unresolved constraint reference '${expr}' in scope '${displayName(parent)}'`,
141416
141724
  source: "sysml",
141417
141725
  code: "unresolved-constraint-reference",
141418
- data: { uri }
141726
+ data: { uri, scopeName: parent.name }
141419
141727
  });
141420
141728
  }
141421
141729
  }
@@ -141448,18 +141756,135 @@ ${info.documentation}`);
141448
141756
  const root = parentMembers.find((s) => s.name === path[0]);
141449
141757
  if (!root) return false;
141450
141758
  if (path.length === 1) return true;
141451
- let typeName = root.typeNames[0] ?? root.typeName;
141759
+ let current = root;
141452
141760
  for (let i = 1; i < path.length; i++) {
141761
+ const typeName = current.typeNames[0] ?? current.typeName;
141453
141762
  if (!typeName) return false;
141454
- const typeDefs = indexes.definitionsByName.get(typeName) ?? [];
141455
- const typeDef = typeDefs[0];
141456
- if (!typeDef) return false;
141457
- const member = (indexes.byParent.get(namespaceKeyOf(typeDef)) ?? []).find((s) => s.name === path[i]);
141763
+ const typeDef = this.namespaceResolver.resolveNameFrom(current, typeName, indexes);
141764
+ if (!typeDef || !isDefinition(typeDef.kind)) return false;
141765
+ const member = this.getConstraintScopeMembers(typeDef, indexes, true).find((s) => s.name === path[i]);
141458
141766
  if (!member) return false;
141459
- typeName = member.typeNames[0] ?? member.typeName;
141767
+ current = member;
141460
141768
  }
141461
141769
  return true;
141462
141770
  }
141771
+ getConstraintScopeMembers(scope, indexes, publicOnly = false) {
141772
+ const hierarchy = [[scope]];
141773
+ const visited = /* @__PURE__ */ new Set([scope]);
141774
+ let frontier = [scope];
141775
+ while (frontier.length > 0) {
141776
+ const next = [];
141777
+ for (const current of frontier) {
141778
+ for (const typeName of current.typeNames) {
141779
+ const supertype = this.namespaceResolver.resolveNameFrom(current, typeName, indexes);
141780
+ if (!supertype || !isDefinition(supertype.kind) || visited.has(supertype)) continue;
141781
+ visited.add(supertype);
141782
+ next.push(supertype);
141783
+ }
141784
+ }
141785
+ if (next.length > 0) hierarchy.push(next);
141786
+ frontier = next;
141787
+ }
141788
+ const membersByLevel = hierarchy.map((level) => level.flatMap((namespace) => indexes.byParent.get(namespaceKeyOf(namespace)) ?? []));
141789
+ const hiddenMembers = /* @__PURE__ */ new Set();
141790
+ for (let level = membersByLevel.length - 1; level >= 0; level--) {
141791
+ for (const redefining of membersByLevel[level]) {
141792
+ for (const target of redefining.redefinedFeatureTargets ?? []) {
141793
+ const owner = ownerOf(redefining, indexes);
141794
+ if (!owner) continue;
141795
+ for (const candidate of this.resolveInheritedRedefinitionTarget(owner, target, hiddenMembers, indexes)) {
141796
+ hiddenMembers.add(candidate.symbolId);
141797
+ }
141798
+ }
141799
+ if (redefining.kind === "subject" /* SubjectUsage */) {
141800
+ const owner = ownerOf(redefining, indexes);
141801
+ if (!owner) continue;
141802
+ for (const ancestor of this.getSpecializationHierarchy(owner, indexes).slice(1).flat()) {
141803
+ for (const candidate of indexes.byParent.get(namespaceKeyOf(ancestor)) ?? []) {
141804
+ if (candidate.kind === "subject" /* SubjectUsage */) hiddenMembers.add(candidate.symbolId);
141805
+ }
141806
+ }
141807
+ }
141808
+ }
141809
+ }
141810
+ const membersByName = /* @__PURE__ */ new Map();
141811
+ for (let level = 0; level < membersByLevel.length; level++) {
141812
+ for (const member of membersByLevel[level]) {
141813
+ if (level > 0 && member.visibility === "private") continue;
141814
+ if (publicOnly && member.visibility !== void 0 && member.visibility !== "public") continue;
141815
+ if (hiddenMembers.has(member.symbolId) || membersByName.has(member.name)) continue;
141816
+ membersByName.set(member.name, member);
141817
+ }
141818
+ }
141819
+ return [...membersByName.values()];
141820
+ }
141821
+ resolveInheritedRedefinitionTarget(owner, target, alreadyRedefined, indexes) {
141822
+ if (target.includes(".")) return [];
141823
+ const segments = target.split("::");
141824
+ const targetName = segments.pop()?.replace(/^'|'$/g, "");
141825
+ if (!targetName) return [];
141826
+ const qualifier = segments.join("::").replace(/^'|'$/g, "");
141827
+ const matches = /* @__PURE__ */ new Map();
141828
+ for (const supertype of this.resolveDirectSupertypes(owner, indexes)) {
141829
+ const branch = this.getSpecializationHierarchy(supertype, indexes);
141830
+ const anchors = qualifier ? branch.flat().filter((type) => this.matchesSpecializationQualifier(type, qualifier)) : [supertype];
141831
+ for (const anchor of anchors) {
141832
+ let frontier = [anchor];
141833
+ const visited = new Set(frontier);
141834
+ const candidates = [];
141835
+ while (frontier.length > 0 && candidates.length === 0) {
141836
+ for (const type of frontier) {
141837
+ for (const member of indexes.byParent.get(namespaceKeyOf(type)) ?? []) {
141838
+ if (member.name === targetName && member.visibility !== "private" && !alreadyRedefined.has(member.symbolId)) {
141839
+ candidates.push(member);
141840
+ }
141841
+ }
141842
+ }
141843
+ if (candidates.length > 0) break;
141844
+ const next = /* @__PURE__ */ new Map();
141845
+ for (const type of frontier) {
141846
+ for (const parent of this.resolveDirectSupertypes(type, indexes)) {
141847
+ if (visited.has(parent)) continue;
141848
+ visited.add(parent);
141849
+ next.set(parent.symbolId, parent);
141850
+ }
141851
+ }
141852
+ frontier = [...next.values()];
141853
+ }
141854
+ for (const candidate of candidates) matches.set(candidate.symbolId, candidate);
141855
+ }
141856
+ }
141857
+ return matches.size === 1 ? [...matches.values()] : [];
141858
+ }
141859
+ resolveDirectSupertypes(scope, indexes) {
141860
+ const supertypes = /* @__PURE__ */ new Map();
141861
+ for (const typeName of scope.typeNames) {
141862
+ const supertype = this.namespaceResolver.resolveNameFrom(scope, typeName, indexes);
141863
+ if (supertype && isDefinition(supertype.kind)) supertypes.set(supertype.symbolId, supertype);
141864
+ }
141865
+ return [...supertypes.values()];
141866
+ }
141867
+ getSpecializationHierarchy(scope, indexes) {
141868
+ const levels = [[scope]];
141869
+ const visited = /* @__PURE__ */ new Set([scope]);
141870
+ let frontier = [scope];
141871
+ while (frontier.length > 0) {
141872
+ const next = [];
141873
+ for (const type of frontier) {
141874
+ for (const parent of this.resolveDirectSupertypes(type, indexes)) {
141875
+ if (visited.has(parent)) continue;
141876
+ visited.add(parent);
141877
+ next.push(parent);
141878
+ }
141879
+ }
141880
+ if (next.length > 0) levels.push(next);
141881
+ frontier = next;
141882
+ }
141883
+ return levels;
141884
+ }
141885
+ matchesSpecializationQualifier(type, qualifier) {
141886
+ return type.name === qualifier || type.qualifiedName === qualifier || type.qualifiedName?.endsWith(`::${qualifier}`) === true;
141887
+ }
141463
141888
  findContainingSymbolByLine(symbols, line) {
141464
141889
  return symbols.filter((s) => s.range.start.line <= line && s.range.end.line >= line).sort((a, b) => {
141465
141890
  const ar = (a.range.end.line - a.range.start.line) * 1e3 + (a.range.end.character - a.range.start.character);
@@ -141470,7 +141895,7 @@ ${info.documentation}`);
141470
141895
  findConstraintScopeSymbol(symbolsInUri, indexes, line) {
141471
141896
  let scope = this.findContainingSymbolByLine(symbolsInUri, line);
141472
141897
  while (scope) {
141473
- const members = indexes.byParent.get(namespaceKeyOf(scope)) ?? [];
141898
+ const members = this.getConstraintScopeMembers(scope, indexes);
141474
141899
  if (members.length > 0) return scope;
141475
141900
  if (!scope.parentId) return scope;
141476
141901
  scope = ownerOf(scope, indexes);
@@ -141492,25 +141917,6 @@ ${info.documentation}`);
141492
141917
  isConstraintKeyword(value) {
141493
141918
  return CONSTRAINT_KEYWORDS.has(value);
141494
141919
  }
141495
- getIgnoredBodyRanges(body) {
141496
- const ranges = [];
141497
- const blockRe = /\/\*[\s\S]*?\*\//g;
141498
- let m2;
141499
- while ((m2 = blockRe.exec(body)) !== null) {
141500
- ranges.push({ start: m2.index, end: m2.index + m2[0].length });
141501
- }
141502
- const lineRe = /\/\/[^\n\r]*/g;
141503
- while ((m2 = lineRe.exec(body)) !== null) {
141504
- ranges.push({ start: m2.index, end: m2.index + m2[0].length });
141505
- }
141506
- return ranges;
141507
- }
141508
- isIndexInRanges(index2, ranges) {
141509
- for (const r of ranges) {
141510
- if (index2 >= r.start && index2 < r.end) return true;
141511
- }
141512
- return false;
141513
- }
141514
141920
  hasDocumentationOnlyConstraintBody(body) {
141515
141921
  const trimmed = body.trim();
141516
141922
  if (!trimmed) return false;
@@ -141608,7 +142014,7 @@ ${info.documentation}`);
141608
142014
  if (defs.length > 1) {
141609
142015
  for (const def of defs) {
141610
142016
  diagnostics.push({
141611
- severity: import_node10.DiagnosticSeverity.Warning,
142017
+ severity: import_node12.DiagnosticSeverity.Warning,
141612
142018
  range: def.selectionRange,
141613
142019
  message: `Duplicate definition: '${name}' is defined ${defs.length} times in the same scope`,
141614
142020
  source: "sysml",
@@ -141650,7 +142056,7 @@ ${info.documentation}`);
141650
142056
  if (!conflicting) continue;
141651
142057
  const others = otherDeclarations(conflicting, symbol);
141652
142058
  diagnostics.push({
141653
- severity: import_node10.DiagnosticSeverity.Error,
142059
+ severity: import_node12.DiagnosticSeverity.Error,
141654
142060
  range: symbol.selectionRange,
141655
142061
  message: `Ambiguous name '${symbol.name}': also declared as ${describeConflictingDeclarations(others, symbol.uri)}.`,
141656
142062
  source: "sysml",
@@ -141742,7 +142148,7 @@ ${info.documentation}`);
141742
142148
  return void 0;
141743
142149
  }
141744
142150
  var connection = createServerConnection();
141745
- var documents = new import_node11.TextDocuments(TextDocument2);
142151
+ var documents = new import_node13.TextDocuments(TextDocument2);
141746
142152
  var serverStartTime = Date.now();
141747
142153
  var documentManager = new DocumentManager();
141748
142154
  var modelProvider = new SysMLModelProvider(documentManager);
@@ -141907,7 +142313,7 @@ ${info.documentation}`);
141907
142313
  };
141908
142314
  const result = {
141909
142315
  capabilities: {
141910
- textDocumentSync: import_node11.TextDocumentSyncKind.Incremental,
142316
+ textDocumentSync: import_node13.TextDocumentSyncKind.Incremental,
141911
142317
  // Completion
141912
142318
  completionProvider: {
141913
142319
  resolveProvider: true,
@@ -141935,7 +142341,7 @@ ${info.documentation}`);
141935
142341
  // Code actions (quick fixes)
141936
142342
  codeActionProvider: {
141937
142343
  codeActionKinds: [
141938
- import_node11.CodeActionKind.QuickFix
142344
+ import_node13.CodeActionKind.QuickFix
141939
142345
  ]
141940
142346
  },
141941
142347
  // Document formatting
@@ -141956,7 +142362,7 @@ ${info.documentation}`);
141956
142362
  connection.onInitialized(async () => {
141957
142363
  if (hasConfigurationCapability) {
141958
142364
  connection.client.register(
141959
- import_node11.DidChangeConfigurationNotification.type,
142365
+ import_node13.DidChangeConfigurationNotification.type,
141960
142366
  void 0
141961
142367
  );
141962
142368
  }
@@ -142065,7 +142471,8 @@ ${info.documentation}`);
142065
142471
  if (loggedFolderPrefixes.get(folderUri) === prefix) continue;
142066
142472
  loggedFolderPrefixes.set(folderUri, prefix);
142067
142473
  const source = ownProjectIds.has(folderUri) ? "its projectId" : prefix === getUrlPrefix() ? prefix === DEFAULT_URL_PREFIX ? "the default prefix, no projectId" : "initializationOptions.projectId" : "an enclosing folder's projectId";
142068
- connection.console.info(`Folder ${folderUri}: top-level elements' URLs start with ${prefix} (${source})`);
142474
+ const folderPath = toFsPath(folderUri) ?? folderUri;
142475
+ connection.console.debug(`Folder ${folderPath}: element ID namespace ${prefix} (${source}; ID namespace only, no network access)`);
142069
142476
  }
142070
142477
  for (const folderUri of loggedFolderPrefixes.keys()) {
142071
142478
  if (!workspaceFolderUris.includes(folderUri)) loggedFolderPrefixes.delete(folderUri);