sysml-v2-lsp 0.38.0 → 0.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/dist/server/browserServerMain.js +97 -18
- package/dist/server/mcpServer.js +72 -9
- package/dist/server/server.js +97 -18
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.39.0]
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- A short name that clashes with a sibling's name or short name (`part def <A> Alpha; part def A;`) is reported as `ambiguous-namespace-name` (KerML 7.2.5.2), and a reference by the name they clash on (`A`) is left unresolved rather than taken for either.
|
|
10
|
+
- Keep ambiguous names unresolved in navigation, hover, references, rename,
|
|
11
|
+
linked editing and hierarchy preparation, including qualified and feature paths.
|
|
12
|
+
Retain every conflicting declaration when both names of an element clash.
|
|
13
|
+
|
|
5
14
|
## [0.38.0]
|
|
6
15
|
|
|
7
16
|
### Added
|
|
@@ -136447,12 +136447,19 @@ ${JSON.stringify(message, null, 4)}`);
|
|
|
136447
136447
|
function findConflictedQualifiedNames(allSymbols) {
|
|
136448
136448
|
return groupConflicts(allSymbols.filter((s) => s.qualifiedName !== void 0), (s) => s.qualifiedName);
|
|
136449
136449
|
}
|
|
136450
|
+
function memberNamesOf(symbol) {
|
|
136451
|
+
return symbol.shortName && symbol.shortName !== symbol.name ? [symbol.name, symbol.shortName] : [symbol.name];
|
|
136452
|
+
}
|
|
136450
136453
|
function findConflictingDeclarations(allSymbols) {
|
|
136451
136454
|
const conflicting = /* @__PURE__ */ new Map();
|
|
136452
136455
|
const add = (groups) => {
|
|
136453
|
-
for (const group of groups
|
|
136456
|
+
for (const group of groups) {
|
|
136457
|
+
for (const s of group) {
|
|
136458
|
+
conflicting.set(s, [.../* @__PURE__ */ new Set([...conflicting.get(s) ?? [], ...group])]);
|
|
136459
|
+
}
|
|
136460
|
+
}
|
|
136454
136461
|
};
|
|
136455
|
-
add(findConflictedQualifiedNames(allSymbols));
|
|
136462
|
+
add(findConflictedQualifiedNames(allSymbols).values());
|
|
136456
136463
|
const membersOfAnonymous = allSymbols.filter((s) => s.qualifiedName === void 0 && !isAnonymous(s) && s.parentId !== void 0);
|
|
136457
136464
|
const byOwner = /* @__PURE__ */ new Map();
|
|
136458
136465
|
for (const s of membersOfAnonymous) {
|
|
@@ -136460,13 +136467,33 @@ ${JSON.stringify(message, null, 4)}`);
|
|
|
136460
136467
|
list.push(s);
|
|
136461
136468
|
byOwner.set(s.parentId, list);
|
|
136462
136469
|
}
|
|
136463
|
-
for (const members of byOwner.values()) add(groupConflicts(members, (s) => s.name));
|
|
136470
|
+
for (const members of byOwner.values()) add(groupConflicts(members, (s) => s.name).values());
|
|
136471
|
+
add([...findConflictingShortNames(allSymbols).values()].map((group) => group.symbols));
|
|
136464
136472
|
return conflicting;
|
|
136465
136473
|
}
|
|
136474
|
+
function findConflictingShortNames(allSymbols) {
|
|
136475
|
+
const byId = new Map(allSymbols.map((s) => [s.symbolId, s]));
|
|
136476
|
+
const entries = [];
|
|
136477
|
+
const keysWithShortName = /* @__PURE__ */ new Set();
|
|
136478
|
+
for (const s of allSymbols) {
|
|
136479
|
+
if (isAnonymous(s)) continue;
|
|
136480
|
+
const owner = s.parentId ? byId.get(s.parentId) : void 0;
|
|
136481
|
+
const namespace = owner === void 0 ? "q:" : owner.qualifiedName !== void 0 ? `q:${owner.qualifiedName}` : `id:${owner.symbolId}`;
|
|
136482
|
+
for (const name of memberNamesOf(s)) {
|
|
136483
|
+
const key = `${namespace}\0${name}`;
|
|
136484
|
+
entries.push({ symbol: s, key });
|
|
136485
|
+
if (name === s.shortName) keysWithShortName.add(key);
|
|
136486
|
+
}
|
|
136487
|
+
}
|
|
136488
|
+
const groups = groupKeyedConflicts(entries.filter((e) => keysWithShortName.has(e.key)));
|
|
136489
|
+
return new Map([...groups].map(([key, symbols]) => [key, { name: key.slice(key.indexOf("\0") + 1), symbols }]));
|
|
136490
|
+
}
|
|
136466
136491
|
function groupConflicts(symbols, keyOf) {
|
|
136492
|
+
return groupKeyedConflicts(symbols.map((symbol) => ({ symbol, key: keyOf(symbol) })));
|
|
136493
|
+
}
|
|
136494
|
+
function groupKeyedConflicts(entries) {
|
|
136467
136495
|
const byKeyAndKind = /* @__PURE__ */ new Map();
|
|
136468
|
-
for (const s of
|
|
136469
|
-
const key = keyOf(s);
|
|
136496
|
+
for (const { symbol: s, key } of entries) {
|
|
136470
136497
|
let byKind = byKeyAndKind.get(key);
|
|
136471
136498
|
if (!byKind) {
|
|
136472
136499
|
byKind = /* @__PURE__ */ new Map();
|
|
@@ -136538,7 +136565,13 @@ ${JSON.stringify(message, null, 4)}`);
|
|
|
136538
136565
|
for (const s of allSymbols) {
|
|
136539
136566
|
byId.set(s.symbolId, s);
|
|
136540
136567
|
}
|
|
136541
|
-
const
|
|
136568
|
+
const clashingShortNames = /* @__PURE__ */ new Map();
|
|
136569
|
+
for (const { name, symbols } of findConflictingShortNames(allSymbols).values()) {
|
|
136570
|
+
const clashing = clashingShortNames.get(name) ?? /* @__PURE__ */ new Set();
|
|
136571
|
+
for (const s of symbols) clashing.add(s);
|
|
136572
|
+
clashingShortNames.set(name, clashing);
|
|
136573
|
+
}
|
|
136574
|
+
const indexes = { byName, byParent, byQualifiedName, byId, definitionsByName, portsByName, clashingShortNames };
|
|
136542
136575
|
for (const s of allSymbols) {
|
|
136543
136576
|
if (isAnonymous(s)) continue;
|
|
136544
136577
|
const nameList = byName.get(s.name) ?? [];
|
|
@@ -136627,6 +136660,16 @@ ${JSON.stringify(message, null, 4)}`);
|
|
|
136627
136660
|
resolveNameIn(namespace, name, indexes) {
|
|
136628
136661
|
return this.resolveQualifiedNameFrom(namespace ? namespaceKeyOf(namespace) : "", name, indexes);
|
|
136629
136662
|
}
|
|
136663
|
+
/** Resolve an editor reference without losing the reason a name is unresolved. */
|
|
136664
|
+
resolveReferenceIn(namespace, name, indexes) {
|
|
136665
|
+
return this.resolveQualifiedReferenceFrom(namespace ? namespaceKeyOf(namespace) : "", name, indexes);
|
|
136666
|
+
}
|
|
136667
|
+
/** Resolve a public qualified or feature-path member, without enclosing-scope fallback. */
|
|
136668
|
+
resolveMemberReference(owner, name, indexes) {
|
|
136669
|
+
const members = this.getResolvedMembers(namespaceKeyOf(owner), indexes).get(name);
|
|
136670
|
+
if (members && this.isAmbiguous(name, members, indexes)) return { ambiguous: true };
|
|
136671
|
+
return this.referenceTo(members?.find((member) => member.visibility === "public")?.symbol, indexes);
|
|
136672
|
+
}
|
|
136630
136673
|
/**
|
|
136631
136674
|
* Resolve a (possibly qualified) name to its symbol per §7.5.1, searching
|
|
136632
136675
|
* outward from namespace `start` and its enclosing namespaces (its own resolved
|
|
@@ -136638,28 +136681,48 @@ ${JSON.stringify(message, null, 4)}`);
|
|
|
136638
136681
|
* its own enclosing package already imported, per §7.5.1/§7.5.3).
|
|
136639
136682
|
*/
|
|
136640
136683
|
resolveQualifiedNameFrom(start, name, indexes) {
|
|
136684
|
+
return this.resolveQualifiedReferenceFrom(start, name, indexes).symbol;
|
|
136685
|
+
}
|
|
136686
|
+
resolveQualifiedReferenceFrom(start, name, indexes) {
|
|
136641
136687
|
const [first, ...rest] = splitQualifiedName(name);
|
|
136642
136688
|
let resolved;
|
|
136643
136689
|
for (const ancestor of this.namespaceAncestorsOf(start, indexes)) {
|
|
136644
136690
|
const candidates = this.getResolvedMembers(ancestor, indexes).get(first);
|
|
136645
136691
|
if (candidates && candidates.length > 0) {
|
|
136692
|
+
if (this.isAmbiguous(first, candidates, indexes)) return { ambiguous: true };
|
|
136646
136693
|
resolved = candidates[0].symbol;
|
|
136647
136694
|
break;
|
|
136648
136695
|
}
|
|
136649
136696
|
}
|
|
136650
|
-
if (resolved === void 0) return
|
|
136697
|
+
if (resolved === void 0) return { ambiguous: false };
|
|
136651
136698
|
const isWithinStart = (namespace) => this.namespaceAncestorsOf(start, indexes).has(namespace);
|
|
136652
136699
|
for (const segment of rest) {
|
|
136653
136700
|
const owner = resolved;
|
|
136654
136701
|
const ownerKey = namespaceKeyOf(owner);
|
|
136655
136702
|
const members = this.getResolvedMembers(ownerKey, indexes).get(segment);
|
|
136703
|
+
if (members && this.isAmbiguous(segment, members, indexes)) return { ambiguous: true };
|
|
136656
136704
|
const visibleMember = members?.find(
|
|
136657
136705
|
(m2) => m2.visibility === "public" || isWithinStart(ownerKey) || m2.visibility === "protected" && this.isProtectedVisibleFrom(start, owner, indexes)
|
|
136658
136706
|
);
|
|
136659
|
-
if (!visibleMember) return
|
|
136707
|
+
if (!visibleMember) return { ambiguous: false };
|
|
136660
136708
|
resolved = visibleMember.symbol;
|
|
136661
136709
|
}
|
|
136662
|
-
return resolved
|
|
136710
|
+
return this.referenceTo(resolved, indexes);
|
|
136711
|
+
}
|
|
136712
|
+
referenceTo(resolved, indexes) {
|
|
136713
|
+
if (!resolved) return { ambiguous: false };
|
|
136714
|
+
const symbol = resolved.qualifiedName !== void 0 ? indexes.byQualifiedName.get(resolved.qualifiedName) : resolved;
|
|
136715
|
+
return { symbol, ambiguous: symbol === void 0 };
|
|
136716
|
+
}
|
|
136717
|
+
/**
|
|
136718
|
+
* Whether `name` names more than one of `candidates` that clash on it
|
|
136719
|
+
* through a short name (`SymbolIndexes.clashingShortNames`), so it can't
|
|
136720
|
+
* be resolved to either (KerML 7.2.5.2). Like a conflicted qualifiedName,
|
|
136721
|
+
* it doesn't fall through to an enclosing namespace's member of that name.
|
|
136722
|
+
*/
|
|
136723
|
+
isAmbiguous(name, candidates, indexes) {
|
|
136724
|
+
const clashing = indexes.clashingShortNames.get(name);
|
|
136725
|
+
return clashing !== void 0 && candidates.filter((c) => clashing.has(c.symbol)).length > 1;
|
|
136663
136726
|
}
|
|
136664
136727
|
/**
|
|
136665
136728
|
* §7.5.3's protected-import exception: "A visibility of protected is the
|
|
@@ -139365,9 +139428,11 @@ ${childIndent}item def ${sourceName};
|
|
|
139365
139428
|
if (target && !path.qualifiedNames.some((name) => name.segments.some((segment) => segment.name === target.name || segment.name === target.shortName))) continue;
|
|
139366
139429
|
const namespace = namespaces.find((ns) => ns.body < path.start && path.end <= ns.end);
|
|
139367
139430
|
let receiver;
|
|
139431
|
+
let receiverAmbiguous = false;
|
|
139368
139432
|
for (let group = 0; group < path.qualifiedNames.length; group++) {
|
|
139369
139433
|
const qualified = path.qualifiedNames[group];
|
|
139370
139434
|
let resolved;
|
|
139435
|
+
let ambiguous = false;
|
|
139371
139436
|
for (let index2 = 0; index2 < qualified.segments.length; index2++) {
|
|
139372
139437
|
const segment = qualified.segments[index2];
|
|
139373
139438
|
const range = import_node3.Range.create(doc.positionAt(segment.start), doc.positionAt(segment.end));
|
|
@@ -139376,17 +139441,27 @@ ${childIndent}item def ${sourceName};
|
|
|
139376
139441
|
while (before >= 0 && /\s/.test(text[before])) before--;
|
|
139377
139442
|
while (after < text.length && /\s/.test(text[after])) after++;
|
|
139378
139443
|
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)));
|
|
139379
|
-
if (declaration)
|
|
139380
|
-
|
|
139381
|
-
|
|
139444
|
+
if (declaration) {
|
|
139445
|
+
resolved = declaration;
|
|
139446
|
+
ambiguous = false;
|
|
139447
|
+
} else if (index2 > 0) {
|
|
139448
|
+
if (resolved) {
|
|
139449
|
+
const result = this.resolver.resolveMemberReference(resolved, segment.name, this.indexes);
|
|
139450
|
+
resolved = result.symbol;
|
|
139451
|
+
ambiguous = result.ambiguous;
|
|
139452
|
+
}
|
|
139382
139453
|
} else if (group > 0) {
|
|
139383
|
-
|
|
139454
|
+
const result = receiver ? this.resolveFeature(receiver, segment.name) : { ambiguous: receiverAmbiguous };
|
|
139455
|
+
resolved = result.symbol;
|
|
139456
|
+
ambiguous = result.ambiguous;
|
|
139384
139457
|
} else {
|
|
139385
|
-
|
|
139458
|
+
const result = this.resolver.resolveReferenceIn(
|
|
139386
139459
|
namespace?.symbol,
|
|
139387
139460
|
joinQualifiedName([segment.name]),
|
|
139388
139461
|
this.indexes
|
|
139389
139462
|
);
|
|
139463
|
+
resolved = result.symbol;
|
|
139464
|
+
ambiguous = result.ambiguous;
|
|
139390
139465
|
}
|
|
139391
139466
|
if (cursor !== void 0 && (cursor < segment.start || cursor > segment.end)) continue;
|
|
139392
139467
|
if (target && segment.name !== target.name && segment.name !== target.shortName) continue;
|
|
@@ -139396,10 +139471,12 @@ ${childIndent}item def ${sourceName};
|
|
|
139396
139471
|
name: segment.name,
|
|
139397
139472
|
qualifiedName: index2 === qualified.segments.length - 1 ? qualified.name : segment.name,
|
|
139398
139473
|
symbol: resolved,
|
|
139399
|
-
isDeclaration: declaration !== void 0
|
|
139474
|
+
isDeclaration: declaration !== void 0,
|
|
139475
|
+
isAmbiguous: ambiguous
|
|
139400
139476
|
});
|
|
139401
139477
|
}
|
|
139402
139478
|
receiver = resolved;
|
|
139479
|
+
receiverAmbiguous = ambiguous;
|
|
139403
139480
|
}
|
|
139404
139481
|
}
|
|
139405
139482
|
return refs;
|
|
@@ -139411,14 +139488,14 @@ ${childIndent}item def ${sourceName};
|
|
|
139411
139488
|
const owner = queue[index2];
|
|
139412
139489
|
if (visited.has(owner)) continue;
|
|
139413
139490
|
visited.add(owner);
|
|
139414
|
-
const member = this.resolver.
|
|
139415
|
-
if (member) return member;
|
|
139491
|
+
const member = this.resolver.resolveMemberReference(owner, name, this.indexes);
|
|
139492
|
+
if (member.symbol || member.ambiguous) return member;
|
|
139416
139493
|
for (const typeName of owner.typeNames) {
|
|
139417
139494
|
const type = this.resolver.resolveNameFrom(owner, typeName, this.indexes);
|
|
139418
139495
|
if (type && !visited.has(type)) queue.push(type);
|
|
139419
139496
|
}
|
|
139420
139497
|
}
|
|
139421
|
-
return
|
|
139498
|
+
return { ambiguous: false };
|
|
139422
139499
|
}
|
|
139423
139500
|
};
|
|
139424
139501
|
|
|
@@ -139435,6 +139512,7 @@ ${childIndent}item def ${sourceName};
|
|
|
139435
139512
|
}
|
|
139436
139513
|
const wsSymbolTable = this.documentManager.getWorkspaceSymbolTable();
|
|
139437
139514
|
const reference = new NameReferences(this.documentManager).at(params.textDocument.uri, params.position);
|
|
139515
|
+
if (reference?.isAmbiguous) return null;
|
|
139438
139516
|
if (reference?.symbol && !reference.isDeclaration) {
|
|
139439
139517
|
return { uri: reference.symbol.uri, range: reference.symbol.selectionRange };
|
|
139440
139518
|
}
|
|
@@ -140049,6 +140127,7 @@ ${childIndent}item def ${sourceName};
|
|
|
140049
140127
|
}
|
|
140050
140128
|
const text = this.documentManager.getText(params.textDocument.uri);
|
|
140051
140129
|
const reference = new NameReferences(this.documentManager).at(params.textDocument.uri, params.position);
|
|
140130
|
+
if (reference?.isAmbiguous) return null;
|
|
140052
140131
|
const word = reference?.qualifiedName ?? (text ? this.getWordAtPosition(text, params.position.line, params.position.character) : void 0);
|
|
140053
140132
|
if (word && word.includes("::") && !reference?.symbol) {
|
|
140054
140133
|
const libHover = this.buildLibraryHover(word);
|
package/dist/server/mcpServer.js
CHANGED
|
@@ -159214,12 +159214,19 @@ var MAX_NAMESPACE_NESTING_DEPTH = 64;
|
|
|
159214
159214
|
function findConflictedQualifiedNames(allSymbols) {
|
|
159215
159215
|
return groupConflicts(allSymbols.filter((s) => s.qualifiedName !== void 0), (s) => s.qualifiedName);
|
|
159216
159216
|
}
|
|
159217
|
+
function memberNamesOf(symbol2) {
|
|
159218
|
+
return symbol2.shortName && symbol2.shortName !== symbol2.name ? [symbol2.name, symbol2.shortName] : [symbol2.name];
|
|
159219
|
+
}
|
|
159217
159220
|
function findConflictingDeclarations(allSymbols) {
|
|
159218
159221
|
const conflicting = /* @__PURE__ */ new Map();
|
|
159219
159222
|
const add = (groups) => {
|
|
159220
|
-
for (const group of groups
|
|
159223
|
+
for (const group of groups) {
|
|
159224
|
+
for (const s of group) {
|
|
159225
|
+
conflicting.set(s, [.../* @__PURE__ */ new Set([...conflicting.get(s) ?? [], ...group])]);
|
|
159226
|
+
}
|
|
159227
|
+
}
|
|
159221
159228
|
};
|
|
159222
|
-
add(findConflictedQualifiedNames(allSymbols));
|
|
159229
|
+
add(findConflictedQualifiedNames(allSymbols).values());
|
|
159223
159230
|
const membersOfAnonymous = allSymbols.filter((s) => s.qualifiedName === void 0 && !isAnonymous(s) && s.parentId !== void 0);
|
|
159224
159231
|
const byOwner = /* @__PURE__ */ new Map();
|
|
159225
159232
|
for (const s of membersOfAnonymous) {
|
|
@@ -159227,13 +159234,33 @@ function findConflictingDeclarations(allSymbols) {
|
|
|
159227
159234
|
list.push(s);
|
|
159228
159235
|
byOwner.set(s.parentId, list);
|
|
159229
159236
|
}
|
|
159230
|
-
for (const members2 of byOwner.values()) add(groupConflicts(members2, (s) => s.name));
|
|
159237
|
+
for (const members2 of byOwner.values()) add(groupConflicts(members2, (s) => s.name).values());
|
|
159238
|
+
add([...findConflictingShortNames(allSymbols).values()].map((group) => group.symbols));
|
|
159231
159239
|
return conflicting;
|
|
159232
159240
|
}
|
|
159241
|
+
function findConflictingShortNames(allSymbols) {
|
|
159242
|
+
const byId = new Map(allSymbols.map((s) => [s.symbolId, s]));
|
|
159243
|
+
const entries = [];
|
|
159244
|
+
const keysWithShortName = /* @__PURE__ */ new Set();
|
|
159245
|
+
for (const s of allSymbols) {
|
|
159246
|
+
if (isAnonymous(s)) continue;
|
|
159247
|
+
const owner = s.parentId ? byId.get(s.parentId) : void 0;
|
|
159248
|
+
const namespace = owner === void 0 ? "q:" : owner.qualifiedName !== void 0 ? `q:${owner.qualifiedName}` : `id:${owner.symbolId}`;
|
|
159249
|
+
for (const name of memberNamesOf(s)) {
|
|
159250
|
+
const key = `${namespace}\0${name}`;
|
|
159251
|
+
entries.push({ symbol: s, key });
|
|
159252
|
+
if (name === s.shortName) keysWithShortName.add(key);
|
|
159253
|
+
}
|
|
159254
|
+
}
|
|
159255
|
+
const groups = groupKeyedConflicts(entries.filter((e) => keysWithShortName.has(e.key)));
|
|
159256
|
+
return new Map([...groups].map(([key, symbols]) => [key, { name: key.slice(key.indexOf("\0") + 1), symbols }]));
|
|
159257
|
+
}
|
|
159233
159258
|
function groupConflicts(symbols, keyOf) {
|
|
159259
|
+
return groupKeyedConflicts(symbols.map((symbol2) => ({ symbol: symbol2, key: keyOf(symbol2) })));
|
|
159260
|
+
}
|
|
159261
|
+
function groupKeyedConflicts(entries) {
|
|
159234
159262
|
const byKeyAndKind = /* @__PURE__ */ new Map();
|
|
159235
|
-
for (const s of
|
|
159236
|
-
const key = keyOf(s);
|
|
159263
|
+
for (const { symbol: s, key } of entries) {
|
|
159237
159264
|
let byKind = byKeyAndKind.get(key);
|
|
159238
159265
|
if (!byKind) {
|
|
159239
159266
|
byKind = /* @__PURE__ */ new Map();
|
|
@@ -159305,7 +159332,13 @@ function buildSymbolIndexes(allSymbols) {
|
|
|
159305
159332
|
for (const s of allSymbols) {
|
|
159306
159333
|
byId.set(s.symbolId, s);
|
|
159307
159334
|
}
|
|
159308
|
-
const
|
|
159335
|
+
const clashingShortNames = /* @__PURE__ */ new Map();
|
|
159336
|
+
for (const { name, symbols } of findConflictingShortNames(allSymbols).values()) {
|
|
159337
|
+
const clashing = clashingShortNames.get(name) ?? /* @__PURE__ */ new Set();
|
|
159338
|
+
for (const s of symbols) clashing.add(s);
|
|
159339
|
+
clashingShortNames.set(name, clashing);
|
|
159340
|
+
}
|
|
159341
|
+
const indexes = { byName, byParent, byQualifiedName, byId, definitionsByName, portsByName, clashingShortNames };
|
|
159309
159342
|
for (const s of allSymbols) {
|
|
159310
159343
|
if (isAnonymous(s)) continue;
|
|
159311
159344
|
const nameList = byName.get(s.name) ?? [];
|
|
@@ -159394,6 +159427,16 @@ var NamespaceResolver = class {
|
|
|
159394
159427
|
resolveNameIn(namespace, name, indexes) {
|
|
159395
159428
|
return this.resolveQualifiedNameFrom(namespace ? namespaceKeyOf(namespace) : "", name, indexes);
|
|
159396
159429
|
}
|
|
159430
|
+
/** Resolve an editor reference without losing the reason a name is unresolved. */
|
|
159431
|
+
resolveReferenceIn(namespace, name, indexes) {
|
|
159432
|
+
return this.resolveQualifiedReferenceFrom(namespace ? namespaceKeyOf(namespace) : "", name, indexes);
|
|
159433
|
+
}
|
|
159434
|
+
/** Resolve a public qualified or feature-path member, without enclosing-scope fallback. */
|
|
159435
|
+
resolveMemberReference(owner, name, indexes) {
|
|
159436
|
+
const members2 = this.getResolvedMembers(namespaceKeyOf(owner), indexes).get(name);
|
|
159437
|
+
if (members2 && this.isAmbiguous(name, members2, indexes)) return { ambiguous: true };
|
|
159438
|
+
return this.referenceTo(members2?.find((member) => member.visibility === "public")?.symbol, indexes);
|
|
159439
|
+
}
|
|
159397
159440
|
/**
|
|
159398
159441
|
* Resolve a (possibly qualified) name to its symbol per §7.5.1, searching
|
|
159399
159442
|
* outward from namespace `start` and its enclosing namespaces (its own resolved
|
|
@@ -159405,28 +159448,48 @@ var NamespaceResolver = class {
|
|
|
159405
159448
|
* its own enclosing package already imported, per §7.5.1/§7.5.3).
|
|
159406
159449
|
*/
|
|
159407
159450
|
resolveQualifiedNameFrom(start, name, indexes) {
|
|
159451
|
+
return this.resolveQualifiedReferenceFrom(start, name, indexes).symbol;
|
|
159452
|
+
}
|
|
159453
|
+
resolveQualifiedReferenceFrom(start, name, indexes) {
|
|
159408
159454
|
const [first, ...rest] = splitQualifiedName(name);
|
|
159409
159455
|
let resolved;
|
|
159410
159456
|
for (const ancestor of this.namespaceAncestorsOf(start, indexes)) {
|
|
159411
159457
|
const candidates = this.getResolvedMembers(ancestor, indexes).get(first);
|
|
159412
159458
|
if (candidates && candidates.length > 0) {
|
|
159459
|
+
if (this.isAmbiguous(first, candidates, indexes)) return { ambiguous: true };
|
|
159413
159460
|
resolved = candidates[0].symbol;
|
|
159414
159461
|
break;
|
|
159415
159462
|
}
|
|
159416
159463
|
}
|
|
159417
|
-
if (resolved === void 0) return
|
|
159464
|
+
if (resolved === void 0) return { ambiguous: false };
|
|
159418
159465
|
const isWithinStart = (namespace) => this.namespaceAncestorsOf(start, indexes).has(namespace);
|
|
159419
159466
|
for (const segment of rest) {
|
|
159420
159467
|
const owner = resolved;
|
|
159421
159468
|
const ownerKey = namespaceKeyOf(owner);
|
|
159422
159469
|
const members2 = this.getResolvedMembers(ownerKey, indexes).get(segment);
|
|
159470
|
+
if (members2 && this.isAmbiguous(segment, members2, indexes)) return { ambiguous: true };
|
|
159423
159471
|
const visibleMember = members2?.find(
|
|
159424
159472
|
(m2) => m2.visibility === "public" || isWithinStart(ownerKey) || m2.visibility === "protected" && this.isProtectedVisibleFrom(start, owner, indexes)
|
|
159425
159473
|
);
|
|
159426
|
-
if (!visibleMember) return
|
|
159474
|
+
if (!visibleMember) return { ambiguous: false };
|
|
159427
159475
|
resolved = visibleMember.symbol;
|
|
159428
159476
|
}
|
|
159429
|
-
return resolved
|
|
159477
|
+
return this.referenceTo(resolved, indexes);
|
|
159478
|
+
}
|
|
159479
|
+
referenceTo(resolved, indexes) {
|
|
159480
|
+
if (!resolved) return { ambiguous: false };
|
|
159481
|
+
const symbol2 = resolved.qualifiedName !== void 0 ? indexes.byQualifiedName.get(resolved.qualifiedName) : resolved;
|
|
159482
|
+
return { symbol: symbol2, ambiguous: symbol2 === void 0 };
|
|
159483
|
+
}
|
|
159484
|
+
/**
|
|
159485
|
+
* Whether `name` names more than one of `candidates` that clash on it
|
|
159486
|
+
* through a short name (`SymbolIndexes.clashingShortNames`), so it can't
|
|
159487
|
+
* be resolved to either (KerML 7.2.5.2). Like a conflicted qualifiedName,
|
|
159488
|
+
* it doesn't fall through to an enclosing namespace's member of that name.
|
|
159489
|
+
*/
|
|
159490
|
+
isAmbiguous(name, candidates, indexes) {
|
|
159491
|
+
const clashing = indexes.clashingShortNames.get(name);
|
|
159492
|
+
return clashing !== void 0 && candidates.filter((c) => clashing.has(c.symbol)).length > 1;
|
|
159430
159493
|
}
|
|
159431
159494
|
/**
|
|
159432
159495
|
* §7.5.3's protected-import exception: "A visibility of protected is the
|
package/dist/server/server.js
CHANGED
|
@@ -125418,12 +125418,19 @@ var MAX_NAMESPACE_NESTING_DEPTH = 64;
|
|
|
125418
125418
|
function findConflictedQualifiedNames(allSymbols) {
|
|
125419
125419
|
return groupConflicts(allSymbols.filter((s) => s.qualifiedName !== void 0), (s) => s.qualifiedName);
|
|
125420
125420
|
}
|
|
125421
|
+
function memberNamesOf(symbol) {
|
|
125422
|
+
return symbol.shortName && symbol.shortName !== symbol.name ? [symbol.name, symbol.shortName] : [symbol.name];
|
|
125423
|
+
}
|
|
125421
125424
|
function findConflictingDeclarations(allSymbols) {
|
|
125422
125425
|
const conflicting = /* @__PURE__ */ new Map();
|
|
125423
125426
|
const add = (groups) => {
|
|
125424
|
-
for (const group of groups
|
|
125427
|
+
for (const group of groups) {
|
|
125428
|
+
for (const s of group) {
|
|
125429
|
+
conflicting.set(s, [.../* @__PURE__ */ new Set([...conflicting.get(s) ?? [], ...group])]);
|
|
125430
|
+
}
|
|
125431
|
+
}
|
|
125425
125432
|
};
|
|
125426
|
-
add(findConflictedQualifiedNames(allSymbols));
|
|
125433
|
+
add(findConflictedQualifiedNames(allSymbols).values());
|
|
125427
125434
|
const membersOfAnonymous = allSymbols.filter((s) => s.qualifiedName === void 0 && !isAnonymous(s) && s.parentId !== void 0);
|
|
125428
125435
|
const byOwner = /* @__PURE__ */ new Map();
|
|
125429
125436
|
for (const s of membersOfAnonymous) {
|
|
@@ -125431,13 +125438,33 @@ function findConflictingDeclarations(allSymbols) {
|
|
|
125431
125438
|
list.push(s);
|
|
125432
125439
|
byOwner.set(s.parentId, list);
|
|
125433
125440
|
}
|
|
125434
|
-
for (const members of byOwner.values()) add(groupConflicts(members, (s) => s.name));
|
|
125441
|
+
for (const members of byOwner.values()) add(groupConflicts(members, (s) => s.name).values());
|
|
125442
|
+
add([...findConflictingShortNames(allSymbols).values()].map((group) => group.symbols));
|
|
125435
125443
|
return conflicting;
|
|
125436
125444
|
}
|
|
125445
|
+
function findConflictingShortNames(allSymbols) {
|
|
125446
|
+
const byId = new Map(allSymbols.map((s) => [s.symbolId, s]));
|
|
125447
|
+
const entries = [];
|
|
125448
|
+
const keysWithShortName = /* @__PURE__ */ new Set();
|
|
125449
|
+
for (const s of allSymbols) {
|
|
125450
|
+
if (isAnonymous(s)) continue;
|
|
125451
|
+
const owner = s.parentId ? byId.get(s.parentId) : void 0;
|
|
125452
|
+
const namespace = owner === void 0 ? "q:" : owner.qualifiedName !== void 0 ? `q:${owner.qualifiedName}` : `id:${owner.symbolId}`;
|
|
125453
|
+
for (const name of memberNamesOf(s)) {
|
|
125454
|
+
const key = `${namespace}\0${name}`;
|
|
125455
|
+
entries.push({ symbol: s, key });
|
|
125456
|
+
if (name === s.shortName) keysWithShortName.add(key);
|
|
125457
|
+
}
|
|
125458
|
+
}
|
|
125459
|
+
const groups = groupKeyedConflicts(entries.filter((e) => keysWithShortName.has(e.key)));
|
|
125460
|
+
return new Map([...groups].map(([key, symbols]) => [key, { name: key.slice(key.indexOf("\0") + 1), symbols }]));
|
|
125461
|
+
}
|
|
125437
125462
|
function groupConflicts(symbols, keyOf) {
|
|
125463
|
+
return groupKeyedConflicts(symbols.map((symbol) => ({ symbol, key: keyOf(symbol) })));
|
|
125464
|
+
}
|
|
125465
|
+
function groupKeyedConflicts(entries) {
|
|
125438
125466
|
const byKeyAndKind = /* @__PURE__ */ new Map();
|
|
125439
|
-
for (const s of
|
|
125440
|
-
const key = keyOf(s);
|
|
125467
|
+
for (const { symbol: s, key } of entries) {
|
|
125441
125468
|
let byKind = byKeyAndKind.get(key);
|
|
125442
125469
|
if (!byKind) {
|
|
125443
125470
|
byKind = /* @__PURE__ */ new Map();
|
|
@@ -125509,7 +125536,13 @@ function buildSymbolIndexes(allSymbols) {
|
|
|
125509
125536
|
for (const s of allSymbols) {
|
|
125510
125537
|
byId.set(s.symbolId, s);
|
|
125511
125538
|
}
|
|
125512
|
-
const
|
|
125539
|
+
const clashingShortNames = /* @__PURE__ */ new Map();
|
|
125540
|
+
for (const { name, symbols } of findConflictingShortNames(allSymbols).values()) {
|
|
125541
|
+
const clashing = clashingShortNames.get(name) ?? /* @__PURE__ */ new Set();
|
|
125542
|
+
for (const s of symbols) clashing.add(s);
|
|
125543
|
+
clashingShortNames.set(name, clashing);
|
|
125544
|
+
}
|
|
125545
|
+
const indexes = { byName, byParent, byQualifiedName, byId, definitionsByName, portsByName, clashingShortNames };
|
|
125513
125546
|
for (const s of allSymbols) {
|
|
125514
125547
|
if (isAnonymous(s)) continue;
|
|
125515
125548
|
const nameList = byName.get(s.name) ?? [];
|
|
@@ -125598,6 +125631,16 @@ var NamespaceResolver = class {
|
|
|
125598
125631
|
resolveNameIn(namespace, name, indexes) {
|
|
125599
125632
|
return this.resolveQualifiedNameFrom(namespace ? namespaceKeyOf(namespace) : "", name, indexes);
|
|
125600
125633
|
}
|
|
125634
|
+
/** Resolve an editor reference without losing the reason a name is unresolved. */
|
|
125635
|
+
resolveReferenceIn(namespace, name, indexes) {
|
|
125636
|
+
return this.resolveQualifiedReferenceFrom(namespace ? namespaceKeyOf(namespace) : "", name, indexes);
|
|
125637
|
+
}
|
|
125638
|
+
/** Resolve a public qualified or feature-path member, without enclosing-scope fallback. */
|
|
125639
|
+
resolveMemberReference(owner, name, indexes) {
|
|
125640
|
+
const members = this.getResolvedMembers(namespaceKeyOf(owner), indexes).get(name);
|
|
125641
|
+
if (members && this.isAmbiguous(name, members, indexes)) return { ambiguous: true };
|
|
125642
|
+
return this.referenceTo(members?.find((member) => member.visibility === "public")?.symbol, indexes);
|
|
125643
|
+
}
|
|
125601
125644
|
/**
|
|
125602
125645
|
* Resolve a (possibly qualified) name to its symbol per §7.5.1, searching
|
|
125603
125646
|
* outward from namespace `start` and its enclosing namespaces (its own resolved
|
|
@@ -125609,28 +125652,48 @@ var NamespaceResolver = class {
|
|
|
125609
125652
|
* its own enclosing package already imported, per §7.5.1/§7.5.3).
|
|
125610
125653
|
*/
|
|
125611
125654
|
resolveQualifiedNameFrom(start, name, indexes) {
|
|
125655
|
+
return this.resolveQualifiedReferenceFrom(start, name, indexes).symbol;
|
|
125656
|
+
}
|
|
125657
|
+
resolveQualifiedReferenceFrom(start, name, indexes) {
|
|
125612
125658
|
const [first, ...rest] = splitQualifiedName(name);
|
|
125613
125659
|
let resolved;
|
|
125614
125660
|
for (const ancestor of this.namespaceAncestorsOf(start, indexes)) {
|
|
125615
125661
|
const candidates = this.getResolvedMembers(ancestor, indexes).get(first);
|
|
125616
125662
|
if (candidates && candidates.length > 0) {
|
|
125663
|
+
if (this.isAmbiguous(first, candidates, indexes)) return { ambiguous: true };
|
|
125617
125664
|
resolved = candidates[0].symbol;
|
|
125618
125665
|
break;
|
|
125619
125666
|
}
|
|
125620
125667
|
}
|
|
125621
|
-
if (resolved === void 0) return
|
|
125668
|
+
if (resolved === void 0) return { ambiguous: false };
|
|
125622
125669
|
const isWithinStart = (namespace) => this.namespaceAncestorsOf(start, indexes).has(namespace);
|
|
125623
125670
|
for (const segment of rest) {
|
|
125624
125671
|
const owner = resolved;
|
|
125625
125672
|
const ownerKey = namespaceKeyOf(owner);
|
|
125626
125673
|
const members = this.getResolvedMembers(ownerKey, indexes).get(segment);
|
|
125674
|
+
if (members && this.isAmbiguous(segment, members, indexes)) return { ambiguous: true };
|
|
125627
125675
|
const visibleMember = members?.find(
|
|
125628
125676
|
(m2) => m2.visibility === "public" || isWithinStart(ownerKey) || m2.visibility === "protected" && this.isProtectedVisibleFrom(start, owner, indexes)
|
|
125629
125677
|
);
|
|
125630
|
-
if (!visibleMember) return
|
|
125678
|
+
if (!visibleMember) return { ambiguous: false };
|
|
125631
125679
|
resolved = visibleMember.symbol;
|
|
125632
125680
|
}
|
|
125633
|
-
return resolved
|
|
125681
|
+
return this.referenceTo(resolved, indexes);
|
|
125682
|
+
}
|
|
125683
|
+
referenceTo(resolved, indexes) {
|
|
125684
|
+
if (!resolved) return { ambiguous: false };
|
|
125685
|
+
const symbol = resolved.qualifiedName !== void 0 ? indexes.byQualifiedName.get(resolved.qualifiedName) : resolved;
|
|
125686
|
+
return { symbol, ambiguous: symbol === void 0 };
|
|
125687
|
+
}
|
|
125688
|
+
/**
|
|
125689
|
+
* Whether `name` names more than one of `candidates` that clash on it
|
|
125690
|
+
* through a short name (`SymbolIndexes.clashingShortNames`), so it can't
|
|
125691
|
+
* be resolved to either (KerML 7.2.5.2). Like a conflicted qualifiedName,
|
|
125692
|
+
* it doesn't fall through to an enclosing namespace's member of that name.
|
|
125693
|
+
*/
|
|
125694
|
+
isAmbiguous(name, candidates, indexes) {
|
|
125695
|
+
const clashing = indexes.clashingShortNames.get(name);
|
|
125696
|
+
return clashing !== void 0 && candidates.filter((c) => clashing.has(c.symbol)).length > 1;
|
|
125634
125697
|
}
|
|
125635
125698
|
/**
|
|
125636
125699
|
* §7.5.3's protected-import exception: "A visibility of protected is the
|
|
@@ -128333,9 +128396,11 @@ var NameReferences = class {
|
|
|
128333
128396
|
if (target && !path3.qualifiedNames.some((name) => name.segments.some((segment) => segment.name === target.name || segment.name === target.shortName))) continue;
|
|
128334
128397
|
const namespace = namespaces.find((ns) => ns.body < path3.start && path3.end <= ns.end);
|
|
128335
128398
|
let receiver;
|
|
128399
|
+
let receiverAmbiguous = false;
|
|
128336
128400
|
for (let group = 0; group < path3.qualifiedNames.length; group++) {
|
|
128337
128401
|
const qualified = path3.qualifiedNames[group];
|
|
128338
128402
|
let resolved;
|
|
128403
|
+
let ambiguous = false;
|
|
128339
128404
|
for (let index2 = 0; index2 < qualified.segments.length; index2++) {
|
|
128340
128405
|
const segment = qualified.segments[index2];
|
|
128341
128406
|
const range = import_node4.Range.create(doc.positionAt(segment.start), doc.positionAt(segment.end));
|
|
@@ -128344,17 +128409,27 @@ var NameReferences = class {
|
|
|
128344
128409
|
while (before >= 0 && /\s/.test(text[before])) before--;
|
|
128345
128410
|
while (after < text.length && /\s/.test(text[after])) after++;
|
|
128346
128411
|
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)));
|
|
128347
|
-
if (declaration)
|
|
128348
|
-
|
|
128349
|
-
|
|
128412
|
+
if (declaration) {
|
|
128413
|
+
resolved = declaration;
|
|
128414
|
+
ambiguous = false;
|
|
128415
|
+
} else if (index2 > 0) {
|
|
128416
|
+
if (resolved) {
|
|
128417
|
+
const result = this.resolver.resolveMemberReference(resolved, segment.name, this.indexes);
|
|
128418
|
+
resolved = result.symbol;
|
|
128419
|
+
ambiguous = result.ambiguous;
|
|
128420
|
+
}
|
|
128350
128421
|
} else if (group > 0) {
|
|
128351
|
-
|
|
128422
|
+
const result = receiver ? this.resolveFeature(receiver, segment.name) : { ambiguous: receiverAmbiguous };
|
|
128423
|
+
resolved = result.symbol;
|
|
128424
|
+
ambiguous = result.ambiguous;
|
|
128352
128425
|
} else {
|
|
128353
|
-
|
|
128426
|
+
const result = this.resolver.resolveReferenceIn(
|
|
128354
128427
|
namespace?.symbol,
|
|
128355
128428
|
joinQualifiedName([segment.name]),
|
|
128356
128429
|
this.indexes
|
|
128357
128430
|
);
|
|
128431
|
+
resolved = result.symbol;
|
|
128432
|
+
ambiguous = result.ambiguous;
|
|
128358
128433
|
}
|
|
128359
128434
|
if (cursor !== void 0 && (cursor < segment.start || cursor > segment.end)) continue;
|
|
128360
128435
|
if (target && segment.name !== target.name && segment.name !== target.shortName) continue;
|
|
@@ -128364,10 +128439,12 @@ var NameReferences = class {
|
|
|
128364
128439
|
name: segment.name,
|
|
128365
128440
|
qualifiedName: index2 === qualified.segments.length - 1 ? qualified.name : segment.name,
|
|
128366
128441
|
symbol: resolved,
|
|
128367
|
-
isDeclaration: declaration !== void 0
|
|
128442
|
+
isDeclaration: declaration !== void 0,
|
|
128443
|
+
isAmbiguous: ambiguous
|
|
128368
128444
|
});
|
|
128369
128445
|
}
|
|
128370
128446
|
receiver = resolved;
|
|
128447
|
+
receiverAmbiguous = ambiguous;
|
|
128371
128448
|
}
|
|
128372
128449
|
}
|
|
128373
128450
|
return refs;
|
|
@@ -128379,14 +128456,14 @@ var NameReferences = class {
|
|
|
128379
128456
|
const owner = queue[index2];
|
|
128380
128457
|
if (visited.has(owner)) continue;
|
|
128381
128458
|
visited.add(owner);
|
|
128382
|
-
const member = this.resolver.
|
|
128383
|
-
if (member) return member;
|
|
128459
|
+
const member = this.resolver.resolveMemberReference(owner, name, this.indexes);
|
|
128460
|
+
if (member.symbol || member.ambiguous) return member;
|
|
128384
128461
|
for (const typeName of owner.typeNames) {
|
|
128385
128462
|
const type = this.resolver.resolveNameFrom(owner, typeName, this.indexes);
|
|
128386
128463
|
if (type && !visited.has(type)) queue.push(type);
|
|
128387
128464
|
}
|
|
128388
128465
|
}
|
|
128389
|
-
return
|
|
128466
|
+
return { ambiguous: false };
|
|
128390
128467
|
}
|
|
128391
128468
|
};
|
|
128392
128469
|
|
|
@@ -128403,6 +128480,7 @@ var DefinitionProvider = class {
|
|
|
128403
128480
|
}
|
|
128404
128481
|
const wsSymbolTable = this.documentManager.getWorkspaceSymbolTable();
|
|
128405
128482
|
const reference = new NameReferences(this.documentManager).at(params.textDocument.uri, params.position);
|
|
128483
|
+
if (reference?.isAmbiguous) return null;
|
|
128406
128484
|
if (reference?.symbol && !reference.isDeclaration) {
|
|
128407
128485
|
return { uri: reference.symbol.uri, range: reference.symbol.selectionRange };
|
|
128408
128486
|
}
|
|
@@ -129017,6 +129095,7 @@ var HoverProvider = class {
|
|
|
129017
129095
|
}
|
|
129018
129096
|
const text = this.documentManager.getText(params.textDocument.uri);
|
|
129019
129097
|
const reference = new NameReferences(this.documentManager).at(params.textDocument.uri, params.position);
|
|
129098
|
+
if (reference?.isAmbiguous) return null;
|
|
129020
129099
|
const word = reference?.qualifiedName ?? (text ? this.getWordAtPosition(text, params.position.line, params.position.character) : void 0);
|
|
129021
129100
|
if (word && word.includes("::") && !reference?.symbol) {
|
|
129022
129101
|
const libHover = this.buildLibraryHover(word);
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "sysml-v2-lsp",
|
|
3
3
|
"displayName": "SysML v2 Language Server",
|
|
4
4
|
"description": "Language Server Protocol implementation for SysML v2, powered by ANTLR4",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.39.0",
|
|
6
6
|
"publisher": "JamieD",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"repository": {
|