sysml-v2-lsp 0.35.0 → 0.36.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 +12 -0
- package/dist/server/browserServerMain.js +280 -58
- package/dist/server/mcpServer.js +297 -76
- package/dist/server/server.js +299 -77
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.36.0]
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- `incompatible-port-types` resolves each end of a `connect` through the features its path names (`a.p.q`), not by the port's name alone. Feature types and their supertypes are resolved in their declaring namespace, so unrelated same-named definitions cannot hide a real mismatch. When two parts each had a port of the same name, the first one declared stood in for both, causing false warnings or missed mismatches. An unresolved path still falls back to the name when only one port has it (#135).
|
|
10
|
+
- A colon, `:>`, `{` or keyword inside a quoted name is no longer read as part of a declaration: `package 'Structure: System Context'` was typed `System` and reported as `unresolved-type`, and `part def 'Unit: Main'` was typed `Main`. Type and specialization fallback extraction masks the declaration's lexer `STRING` tokens, without scanning documentation or nested members, avoiding quadratic regex backtracking on quote-heavy comments (#134).
|
|
11
|
+
- Visit each specialization ancestor only once when resolving inherited constraint features, preventing exponential queue growth through layered diamond inheritance (#127).
|
|
12
|
+
- Hide implicitly redefined requirement subjects according to the declaring requirement's specialization ancestors, including redundant direct bases in multiple inheritance, while preserving subjects from unrelated branches.
|
|
13
|
+
- Display decoded filesystem paths in workspace-folder logs and clarify that
|
|
14
|
+
element ID namespaces are used locally, without network access. Emit this
|
|
15
|
+
internal namespace information at debug level instead of info.
|
|
16
|
+
|
|
5
17
|
## [0.35.0]
|
|
6
18
|
|
|
7
19
|
### Added
|
|
@@ -3362,7 +3362,7 @@ ${JSON.stringify(message, null, 4)}`);
|
|
|
3362
3362
|
}
|
|
3363
3363
|
uinteger3.is = is;
|
|
3364
3364
|
})(uinteger || (uinteger = {}));
|
|
3365
|
-
(function(
|
|
3365
|
+
(function(Position5) {
|
|
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
|
-
|
|
3375
|
+
Position5.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
|
-
|
|
3380
|
+
Position5.is = is;
|
|
3381
3381
|
})(Position || (Position = {}));
|
|
3382
|
-
(function(
|
|
3382
|
+
(function(Range5) {
|
|
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,12 +3389,12 @@ ${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
|
-
|
|
3392
|
+
Range5.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
|
-
|
|
3397
|
+
Range5.is = is;
|
|
3398
3398
|
})(Range || (Range = {}));
|
|
3399
3399
|
(function(Location4) {
|
|
3400
3400
|
function create(uri, range) {
|
|
@@ -12435,7 +12435,7 @@ ${JSON.stringify(message, null, 4)}`);
|
|
|
12435
12435
|
}
|
|
12436
12436
|
uinteger3.is = is;
|
|
12437
12437
|
})(uinteger2 || (uinteger2 = {}));
|
|
12438
|
-
(function(
|
|
12438
|
+
(function(Position5) {
|
|
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
|
-
|
|
12448
|
+
Position5.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
|
-
|
|
12453
|
+
Position5.is = is;
|
|
12454
12454
|
})(Position2 || (Position2 = {}));
|
|
12455
|
-
(function(
|
|
12455
|
+
(function(Range5) {
|
|
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,12 +12462,12 @@ ${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
|
-
|
|
12465
|
+
Range5.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
|
-
|
|
12470
|
+
Range5.is = is;
|
|
12471
12471
|
})(Range2 || (Range2 = {}));
|
|
12472
12472
|
(function(Location4) {
|
|
12473
12473
|
function create(uri, range) {
|
|
@@ -131659,6 +131659,7 @@ ${JSON.stringify(message, null, 4)}`);
|
|
|
131659
131659
|
const selectionRange = anonymous ? ctx.start ? tokenToRange(ctx.start) : range : this.extractNameRange(ctx) ?? range;
|
|
131660
131660
|
const typeNames = isFlowUsage(kind) ? this.extractFlowTypeNames(ctx) : transition ? this.extractTransitionTypeNames(ctx) : this.extractTypeNames(ctx);
|
|
131661
131661
|
const specializationNames = this.extractSpecializationNames(ctx);
|
|
131662
|
+
const redefinedFeatureTargets = this.extractRedefinedFeatureTargets(ctx);
|
|
131662
131663
|
const typeName = typeNames[0];
|
|
131663
131664
|
const documentation = this.extractDocumentation(ctx);
|
|
131664
131665
|
const visibility = this.extractVisibility(ctx);
|
|
@@ -131689,6 +131690,7 @@ ${JSON.stringify(message, null, 4)}`);
|
|
|
131689
131690
|
typeName,
|
|
131690
131691
|
typeNames,
|
|
131691
131692
|
specializationNames,
|
|
131693
|
+
redefinedFeatureTargets: redefinedFeatureTargets.length > 0 ? redefinedFeatureTargets : void 0,
|
|
131692
131694
|
documentation,
|
|
131693
131695
|
visibility,
|
|
131694
131696
|
source: transition?.source,
|
|
@@ -131940,15 +131942,28 @@ ${JSON.stringify(message, null, 4)}`);
|
|
|
131940
131942
|
* such as `#metadata`.
|
|
131941
131943
|
*/
|
|
131942
131944
|
findOwnHeaderRule(ctx, ruleIndex) {
|
|
131945
|
+
const matches = [];
|
|
131946
|
+
this.findOwnHeaderRules(ctx, ruleIndex, matches, true);
|
|
131947
|
+
return matches[0];
|
|
131948
|
+
}
|
|
131949
|
+
findOwnHeaderRules(ctx, ruleIndex, matches, firstOnly = false) {
|
|
131943
131950
|
for (let i = 0; i < ctx.getChildCount(); i++) {
|
|
131944
131951
|
const child = ctx.getChild(i);
|
|
131945
131952
|
if (!(child instanceof ParserRuleContext)) continue;
|
|
131946
|
-
if (child.ruleIndex === ruleIndex)
|
|
131953
|
+
if (child.ruleIndex === ruleIndex) {
|
|
131954
|
+
matches.push(child);
|
|
131955
|
+
if (firstOnly) return;
|
|
131956
|
+
continue;
|
|
131957
|
+
}
|
|
131947
131958
|
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
|
-
|
|
131949
|
-
if (
|
|
131959
|
+
this.findOwnHeaderRules(child, ruleIndex, matches, firstOnly);
|
|
131960
|
+
if (firstOnly && matches.length > 0) return;
|
|
131950
131961
|
}
|
|
131951
|
-
|
|
131962
|
+
}
|
|
131963
|
+
extractRedefinedFeatureTargets(ctx) {
|
|
131964
|
+
const targets = [];
|
|
131965
|
+
this.findOwnHeaderRules(ctx, SysMLv2Parser.RULE_ownedRedefinition, targets);
|
|
131966
|
+
return targets.map((target) => target.getText());
|
|
131952
131967
|
}
|
|
131953
131968
|
/**
|
|
131954
131969
|
* A connection, interface or allocation usage's end reference paths, in
|
|
@@ -131976,13 +131991,7 @@ ${JSON.stringify(message, null, 4)}`);
|
|
|
131976
131991
|
const segment = reference.getText().split(/::|\./).pop();
|
|
131977
131992
|
return segment ? this.unquoteName(segment) : void 0;
|
|
131978
131993
|
}
|
|
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) {
|
|
131994
|
+
declarationTokens(ctx) {
|
|
131986
131995
|
const tokens = [];
|
|
131987
131996
|
const visit = (node) => {
|
|
131988
131997
|
for (let i = 0; i < node.getChildCount(); i++) {
|
|
@@ -131997,6 +132006,16 @@ ${JSON.stringify(message, null, 4)}`);
|
|
|
131997
132006
|
return false;
|
|
131998
132007
|
};
|
|
131999
132008
|
visit(ctx);
|
|
132009
|
+
return tokens;
|
|
132010
|
+
}
|
|
132011
|
+
/**
|
|
132012
|
+
* An element's declaration as written, without its body: its tokens up to
|
|
132013
|
+
* its body or closing `;`, each exactly as written (a quoted name keeps its
|
|
132014
|
+
* spaces), with one space wherever the source has whitespace or a comment
|
|
132015
|
+
* between two of them (`connect a.p to b.p`, `connection : Conn`).
|
|
132016
|
+
*/
|
|
132017
|
+
declarationText(ctx) {
|
|
132018
|
+
const tokens = this.declarationTokens(ctx);
|
|
132000
132019
|
let text = "";
|
|
132001
132020
|
tokens.forEach((token, i) => {
|
|
132002
132021
|
if (i > 0 && token.start > tokens[i - 1].stop + 1) text += " ";
|
|
@@ -132137,17 +132156,16 @@ ${JSON.stringify(message, null, 4)}`);
|
|
|
132137
132156
|
const names = [];
|
|
132138
132157
|
this.collectTypeNamesFromTree(ctx, names, 0);
|
|
132139
132158
|
if (names.length > 0) return names;
|
|
132140
|
-
const
|
|
132141
|
-
|
|
132142
|
-
let text = braceIdx >= 0 ? fullText.substring(0, braceIdx) : fullText;
|
|
132159
|
+
const { text: declarationText, quotedName } = this.maskedDeclaration(ctx);
|
|
132160
|
+
let text = declarationText;
|
|
132143
132161
|
text = text.replace(RE_KEYWORD_TRUNCATE, "");
|
|
132144
132162
|
const specMatch = text.match(RE_SPEC);
|
|
132145
132163
|
if (specMatch) {
|
|
132146
132164
|
const specStr = text.substring(text.indexOf(specMatch[0]) + specMatch[0].indexOf(specMatch[1]));
|
|
132147
132165
|
for (const part of specStr.split(",")) {
|
|
132148
|
-
const
|
|
132149
|
-
if (
|
|
132150
|
-
names.push(
|
|
132166
|
+
const quoted = quotedName(part);
|
|
132167
|
+
if (quoted !== void 0) {
|
|
132168
|
+
names.push(quoted);
|
|
132151
132169
|
continue;
|
|
132152
132170
|
}
|
|
132153
132171
|
const m2 = part.trim().match(RE_IDENT_START);
|
|
@@ -132168,9 +132186,9 @@ ${JSON.stringify(message, null, 4)}`);
|
|
|
132168
132186
|
const fullMatchIdx = text.indexOf(typingMatch[0]);
|
|
132169
132187
|
const afterColon = text.substring(fullMatchIdx + 1).trim();
|
|
132170
132188
|
for (const part of afterColon.split(",")) {
|
|
132171
|
-
const
|
|
132172
|
-
if (
|
|
132173
|
-
names.push(
|
|
132189
|
+
const quoted = quotedName(part);
|
|
132190
|
+
if (quoted !== void 0) {
|
|
132191
|
+
names.push(quoted);
|
|
132174
132192
|
continue;
|
|
132175
132193
|
}
|
|
132176
132194
|
const m2 = part.trim().match(RE_IDENT_START);
|
|
@@ -132180,6 +132198,28 @@ ${JSON.stringify(message, null, 4)}`);
|
|
|
132180
132198
|
}
|
|
132181
132199
|
return names;
|
|
132182
132200
|
}
|
|
132201
|
+
/**
|
|
132202
|
+
* The declaration tokens before the body, with each lexer STRING token
|
|
132203
|
+
* replaced by a numbered placeholder (`'0'`, `'1'`, ...), and
|
|
132204
|
+
* `quotedName`, which turns a placeholder in a part of that text back into
|
|
132205
|
+
* the name. SysML 2.0 section 7.2.2 permits punctuation in unrestricted
|
|
132206
|
+
* names (the STRING lexer production), so fallback regexes must never see
|
|
132207
|
+
* their `:`, `:>`, `{` or keywords. Documentation is not a name token.
|
|
132208
|
+
*/
|
|
132209
|
+
maskedDeclaration(ctx) {
|
|
132210
|
+
const quoted = [];
|
|
132211
|
+
const masked = this.declarationTokens(ctx).map((token) => {
|
|
132212
|
+
const text = token.text ?? "";
|
|
132213
|
+
return token.type === SysMLv2Lexer.STRING ? `'${quoted.push(text.slice(1, -1)) - 1}'` : text;
|
|
132214
|
+
}).join("");
|
|
132215
|
+
return {
|
|
132216
|
+
text: masked,
|
|
132217
|
+
quotedName: (part) => {
|
|
132218
|
+
const qm = part.match(RE_QUOTED_NAME);
|
|
132219
|
+
return qm ? quoted[Number(qm[1])] : void 0;
|
|
132220
|
+
}
|
|
132221
|
+
};
|
|
132222
|
+
}
|
|
132183
132223
|
/**
|
|
132184
132224
|
* Extract only the specialization names (:> / specializes / subsets) from a context.
|
|
132185
132225
|
* Uses the same tree-walk as extractTypeNames but restricted to
|
|
@@ -132190,17 +132230,15 @@ ${JSON.stringify(message, null, 4)}`);
|
|
|
132190
132230
|
const names = [];
|
|
132191
132231
|
this.collectNamesFromTree(ctx, names, 0, TYPE_SPECIALIZATION_RULE_INDICES);
|
|
132192
132232
|
if (names.length > 0) return names;
|
|
132193
|
-
const
|
|
132194
|
-
const
|
|
132195
|
-
let text = braceIdx >= 0 ? fullText.substring(0, braceIdx) : fullText;
|
|
132196
|
-
text = text.replace(RE_KEYWORD_TRUNCATE_SPEC, "");
|
|
132233
|
+
const { text: declarationText, quotedName } = this.maskedDeclaration(ctx);
|
|
132234
|
+
const text = declarationText.replace(RE_KEYWORD_TRUNCATE_SPEC, "");
|
|
132197
132235
|
const specMatch = text.match(RE_SPEC_WITH_SUBSETS);
|
|
132198
132236
|
if (specMatch) {
|
|
132199
132237
|
const specStr = text.substring(text.indexOf(specMatch[0]) + specMatch[0].indexOf(specMatch[1]));
|
|
132200
132238
|
for (const part of specStr.split(",")) {
|
|
132201
|
-
const
|
|
132202
|
-
if (
|
|
132203
|
-
names.push(
|
|
132239
|
+
const quoted = quotedName(part);
|
|
132240
|
+
if (quoted !== void 0) {
|
|
132241
|
+
names.push(quoted);
|
|
132204
132242
|
continue;
|
|
132205
132243
|
}
|
|
132206
132244
|
const m2 = part.trim().match(RE_IDENT_START);
|
|
@@ -136405,14 +136443,21 @@ ${JSON.stringify(message, null, 4)}`);
|
|
|
136405
136443
|
* namespace.
|
|
136406
136444
|
*/
|
|
136407
136445
|
isLocallyVisible(symbol, name, indexes) {
|
|
136408
|
-
return this.
|
|
136446
|
+
return this.resolveNameFrom(symbol, name, indexes) !== void 0;
|
|
136447
|
+
}
|
|
136448
|
+
/**
|
|
136449
|
+
* Resolve a (possibly qualified) name from the namespace containing
|
|
136450
|
+
* `symbol`, respecting namespace membership and visibility.
|
|
136451
|
+
*/
|
|
136452
|
+
resolveNameFrom(symbol, name, indexes) {
|
|
136453
|
+
return this.resolveQualifiedNameFrom(ownerKeyOf(symbol, indexes.byId), name, indexes);
|
|
136409
136454
|
}
|
|
136410
136455
|
/**
|
|
136411
136456
|
* Resolve a (possibly qualified) name to its symbol per §7.5.1, searching
|
|
136412
136457
|
* outward from namespace `start` and its enclosing namespaces (its own resolved
|
|
136413
136458
|
* members first, then its parent's, ...). Shared by `isLocallyVisible` (an
|
|
136414
|
-
* ordinary reference resolving relative to its own enclosing namespace)
|
|
136415
|
-
* import-target resolution (an `import` declaration's target is itself a
|
|
136459
|
+
* ordinary reference resolving relative to its own enclosing namespace),
|
|
136460
|
+
* `resolveNameFrom`, and import-target resolution (an `import` declaration's target is itself a
|
|
136416
136461
|
* qualifiedName, resolved the same relative way -- not as an absolute/global
|
|
136417
136462
|
* name -- so a bare `import C;` inside a nested package can pick up a `C`
|
|
136418
136463
|
* its own enclosing package already imported, per §7.5.1/§7.5.3).
|
|
@@ -140622,6 +140667,13 @@ ${info.documentation}`);
|
|
|
140622
140667
|
"assert",
|
|
140623
140668
|
"assume"
|
|
140624
140669
|
]);
|
|
140670
|
+
var CONNECTOR_KINDS = /* @__PURE__ */ new Set([
|
|
140671
|
+
"connection" /* ConnectionUsage */,
|
|
140672
|
+
"interface" /* InterfaceUsage */,
|
|
140673
|
+
"allocation" /* AllocationUsage */,
|
|
140674
|
+
"flow" /* FlowUsage */,
|
|
140675
|
+
"succession flow" /* SuccessionFlowUsage */
|
|
140676
|
+
]);
|
|
140625
140677
|
var SemanticValidator = class _SemanticValidator {
|
|
140626
140678
|
constructor(documentManager2) {
|
|
140627
140679
|
this.documentManager = documentManager2;
|
|
@@ -140698,7 +140750,7 @@ ${info.documentation}`);
|
|
|
140698
140750
|
diagnostics.push(...this.checkAmbiguousNamespaceName(symbols, allSymbols));
|
|
140699
140751
|
diagnostics.push(...this.checkUnusedDefinitions(allSymbols, uri));
|
|
140700
140752
|
diagnostics.push(...this.checkRedefinitionMultiplicity(symbols, indexes, text));
|
|
140701
|
-
diagnostics.push(...this.checkPortCompatibility(text, uri, indexes));
|
|
140753
|
+
diagnostics.push(...this.checkPortCompatibility(text, uri, symbols, indexes));
|
|
140702
140754
|
diagnostics.push(...this.checkConstraintBodyReferences(text, uri, symbols, indexes));
|
|
140703
140755
|
diagnostics.push(...this.checkCircularSpecialization(symbols, indexes));
|
|
140704
140756
|
diagnostics.push(...this.checkUnsatisfiedRequirements(symbols, indexes));
|
|
@@ -140919,7 +140971,7 @@ ${info.documentation}`);
|
|
|
140919
140971
|
opts?.text ? [opts.text] : []
|
|
140920
140972
|
));
|
|
140921
140973
|
if (opts?.text && opts.uri) {
|
|
140922
|
-
diagnostics.push(...instance.checkPortCompatibility(opts.text, opts.uri, indexes));
|
|
140974
|
+
diagnostics.push(...instance.checkPortCompatibility(opts.text, opts.uri, symbolsInUri, indexes));
|
|
140923
140975
|
diagnostics.push(...instance.checkConstraintBodyReferences(opts.text, opts.uri, symbolsInUri, indexes));
|
|
140924
140976
|
}
|
|
140925
140977
|
return instance.dedupeDiagnostics(diagnostics);
|
|
@@ -141282,17 +141334,20 @@ ${info.documentation}`);
|
|
|
141282
141334
|
* - The connection is within an interface usage
|
|
141283
141335
|
* - Both ports are untyped (empty port defs with no features)
|
|
141284
141336
|
*/
|
|
141285
|
-
checkPortCompatibility(text, uri, indexes) {
|
|
141337
|
+
checkPortCompatibility(text, uri, symbolsInUri, indexes) {
|
|
141286
141338
|
if (!text) return [];
|
|
141287
141339
|
const diagnostics = [];
|
|
141288
141340
|
const lines = text.split("\n");
|
|
141289
141341
|
const re = /\bconnect\s+([A-Za-z_][\w.]*)\s+to\s+([A-Za-z_][\w.]*)/g;
|
|
141290
141342
|
let m2;
|
|
141291
141343
|
while ((m2 = re.exec(text)) !== null) {
|
|
141292
|
-
const
|
|
141293
|
-
const
|
|
141294
|
-
const
|
|
141295
|
-
const
|
|
141344
|
+
const leftPath = m2[1].split(".");
|
|
141345
|
+
const rightPath = m2[2].split(".");
|
|
141346
|
+
const left = leftPath[leftPath.length - 1];
|
|
141347
|
+
const right = rightPath[rightPath.length - 1];
|
|
141348
|
+
const scope = this.connectorScope(symbolsInUri, this.indexToRange(text, m2.index, 0).start, indexes);
|
|
141349
|
+
const lSym = this.resolveConnectorEnd(leftPath, scope, indexes);
|
|
141350
|
+
const rSym = this.resolveConnectorEnd(rightPath, scope, indexes);
|
|
141296
141351
|
if (!lSym || !rSym) continue;
|
|
141297
141352
|
const lType = lSym.typeNames[0] ?? lSym.typeName;
|
|
141298
141353
|
const rType = rSym.typeNames[0] ?? rSym.typeName;
|
|
@@ -141342,6 +141397,55 @@ ${info.documentation}`);
|
|
|
141342
141397
|
}
|
|
141343
141398
|
return diagnostics;
|
|
141344
141399
|
}
|
|
141400
|
+
/**
|
|
141401
|
+
* The innermost element around `position` that owns a connector declared
|
|
141402
|
+
* there: the connector's own symbol, when it has one, is skipped.
|
|
141403
|
+
*/
|
|
141404
|
+
connectorScope(symbols, position, indexes) {
|
|
141405
|
+
const before = (a, b) => a.line < b.line || a.line === b.line && a.character <= b.character;
|
|
141406
|
+
const size = (r) => (r.end.line - r.start.line) * 1e6 + (r.end.character - r.start.character);
|
|
141407
|
+
let scope;
|
|
141408
|
+
for (const s of symbols) {
|
|
141409
|
+
if (!before(s.range.start, position) || !before(position, s.range.end)) continue;
|
|
141410
|
+
if (!scope || size(s.range) < size(scope.range)) scope = s;
|
|
141411
|
+
}
|
|
141412
|
+
while (scope && CONNECTOR_KINDS.has(scope.kind)) scope = ownerOf(scope, indexes);
|
|
141413
|
+
return scope;
|
|
141414
|
+
}
|
|
141415
|
+
/**
|
|
141416
|
+
* The port that a connector end (`a.p`, `a.p.q`) names, resolved from
|
|
141417
|
+
* `scope` outward: its first segment is a feature of `scope` or of one of
|
|
141418
|
+
* its owners, each next one a feature of the one before. Two parts can each
|
|
141419
|
+
* have a port of the same name, so an end is never matched by its last
|
|
141420
|
+
* segment alone, except when the path does not resolve and the workspace
|
|
141421
|
+
* has only one port of that name.
|
|
141422
|
+
*/
|
|
141423
|
+
resolveConnectorEnd(path, scope, indexes) {
|
|
141424
|
+
let feature;
|
|
141425
|
+
for (let namespace = scope; namespace && !feature; namespace = ownerOf(namespace, indexes)) {
|
|
141426
|
+
feature = this.findFeature(namespace, path[0], indexes);
|
|
141427
|
+
}
|
|
141428
|
+
for (const name of path.slice(1)) {
|
|
141429
|
+
feature = feature && this.findFeature(feature, name, indexes);
|
|
141430
|
+
}
|
|
141431
|
+
if (feature) return feature.kind === "port" /* PortUsage */ ? feature : void 0;
|
|
141432
|
+
const sameName = indexes.portsByName.get(path[path.length - 1]) ?? [];
|
|
141433
|
+
return sameName.length === 1 ? sameName[0] : void 0;
|
|
141434
|
+
}
|
|
141435
|
+
/** The feature `name` of `owner`: its own member, else a member of one of its types or their supertypes. */
|
|
141436
|
+
findFeature(owner, name, indexes) {
|
|
141437
|
+
const own = (indexes.byParent.get(namespaceKeyOf(owner)) ?? []).find((s) => s.name === name);
|
|
141438
|
+
if (own) return own;
|
|
141439
|
+
for (const typeName of owner.typeNames) {
|
|
141440
|
+
const type = this.namespaceResolver.resolveNameFrom(owner, typeName, indexes);
|
|
141441
|
+
if (!type || !isDefinition(type.kind)) continue;
|
|
141442
|
+
for (const definition of this.getSpecializationHierarchy(type, indexes).flat()) {
|
|
141443
|
+
const member = (indexes.byParent.get(namespaceKeyOf(definition)) ?? []).find((s) => s.name === name);
|
|
141444
|
+
if (member) return member;
|
|
141445
|
+
}
|
|
141446
|
+
}
|
|
141447
|
+
return void 0;
|
|
141448
|
+
}
|
|
141345
141449
|
/**
|
|
141346
141450
|
* Resolve the full type hierarchy for a type name by following
|
|
141347
141451
|
* specialization chains transitively (max depth 10).
|
|
@@ -141389,7 +141493,7 @@ ${info.documentation}`);
|
|
|
141389
141493
|
}
|
|
141390
141494
|
const parent = this.findConstraintScopeSymbol(symbolsInUri, indexes, b.startLine);
|
|
141391
141495
|
if (!parent) continue;
|
|
141392
|
-
const parentMembers =
|
|
141496
|
+
const parentMembers = this.getConstraintScopeMembers(parent, indexes);
|
|
141393
141497
|
if (parentMembers.length === 0) continue;
|
|
141394
141498
|
const ignoredRanges = this.getIgnoredBodyRanges(b.body);
|
|
141395
141499
|
const idRe = /\b([A-Za-z_][\w]*(?:\.[A-Za-z_][\w]*)*)\b/g;
|
|
@@ -141448,18 +141552,135 @@ ${info.documentation}`);
|
|
|
141448
141552
|
const root = parentMembers.find((s) => s.name === path[0]);
|
|
141449
141553
|
if (!root) return false;
|
|
141450
141554
|
if (path.length === 1) return true;
|
|
141451
|
-
let
|
|
141555
|
+
let current = root;
|
|
141452
141556
|
for (let i = 1; i < path.length; i++) {
|
|
141557
|
+
const typeName = current.typeNames[0] ?? current.typeName;
|
|
141453
141558
|
if (!typeName) return false;
|
|
141454
|
-
const
|
|
141455
|
-
|
|
141456
|
-
|
|
141457
|
-
const member = (indexes.byParent.get(namespaceKeyOf(typeDef)) ?? []).find((s) => s.name === path[i]);
|
|
141559
|
+
const typeDef = this.namespaceResolver.resolveNameFrom(current, typeName, indexes);
|
|
141560
|
+
if (!typeDef || !isDefinition(typeDef.kind)) return false;
|
|
141561
|
+
const member = this.getConstraintScopeMembers(typeDef, indexes, true).find((s) => s.name === path[i]);
|
|
141458
141562
|
if (!member) return false;
|
|
141459
|
-
|
|
141563
|
+
current = member;
|
|
141460
141564
|
}
|
|
141461
141565
|
return true;
|
|
141462
141566
|
}
|
|
141567
|
+
getConstraintScopeMembers(scope, indexes, publicOnly = false) {
|
|
141568
|
+
const hierarchy = [[scope]];
|
|
141569
|
+
const visited = /* @__PURE__ */ new Set([scope]);
|
|
141570
|
+
let frontier = [scope];
|
|
141571
|
+
while (frontier.length > 0) {
|
|
141572
|
+
const next = [];
|
|
141573
|
+
for (const current of frontier) {
|
|
141574
|
+
for (const typeName of current.typeNames) {
|
|
141575
|
+
const supertype = this.namespaceResolver.resolveNameFrom(current, typeName, indexes);
|
|
141576
|
+
if (!supertype || !isDefinition(supertype.kind) || visited.has(supertype)) continue;
|
|
141577
|
+
visited.add(supertype);
|
|
141578
|
+
next.push(supertype);
|
|
141579
|
+
}
|
|
141580
|
+
}
|
|
141581
|
+
if (next.length > 0) hierarchy.push(next);
|
|
141582
|
+
frontier = next;
|
|
141583
|
+
}
|
|
141584
|
+
const membersByLevel = hierarchy.map((level) => level.flatMap((namespace) => indexes.byParent.get(namespaceKeyOf(namespace)) ?? []));
|
|
141585
|
+
const hiddenMembers = /* @__PURE__ */ new Set();
|
|
141586
|
+
for (let level = membersByLevel.length - 1; level >= 0; level--) {
|
|
141587
|
+
for (const redefining of membersByLevel[level]) {
|
|
141588
|
+
for (const target of redefining.redefinedFeatureTargets ?? []) {
|
|
141589
|
+
const owner = ownerOf(redefining, indexes);
|
|
141590
|
+
if (!owner) continue;
|
|
141591
|
+
for (const candidate of this.resolveInheritedRedefinitionTarget(owner, target, hiddenMembers, indexes)) {
|
|
141592
|
+
hiddenMembers.add(candidate.symbolId);
|
|
141593
|
+
}
|
|
141594
|
+
}
|
|
141595
|
+
if (redefining.kind === "subject" /* SubjectUsage */) {
|
|
141596
|
+
const owner = ownerOf(redefining, indexes);
|
|
141597
|
+
if (!owner) continue;
|
|
141598
|
+
for (const ancestor of this.getSpecializationHierarchy(owner, indexes).slice(1).flat()) {
|
|
141599
|
+
for (const candidate of indexes.byParent.get(namespaceKeyOf(ancestor)) ?? []) {
|
|
141600
|
+
if (candidate.kind === "subject" /* SubjectUsage */) hiddenMembers.add(candidate.symbolId);
|
|
141601
|
+
}
|
|
141602
|
+
}
|
|
141603
|
+
}
|
|
141604
|
+
}
|
|
141605
|
+
}
|
|
141606
|
+
const membersByName = /* @__PURE__ */ new Map();
|
|
141607
|
+
for (let level = 0; level < membersByLevel.length; level++) {
|
|
141608
|
+
for (const member of membersByLevel[level]) {
|
|
141609
|
+
if (level > 0 && member.visibility === "private") continue;
|
|
141610
|
+
if (publicOnly && member.visibility !== void 0 && member.visibility !== "public") continue;
|
|
141611
|
+
if (hiddenMembers.has(member.symbolId) || membersByName.has(member.name)) continue;
|
|
141612
|
+
membersByName.set(member.name, member);
|
|
141613
|
+
}
|
|
141614
|
+
}
|
|
141615
|
+
return [...membersByName.values()];
|
|
141616
|
+
}
|
|
141617
|
+
resolveInheritedRedefinitionTarget(owner, target, alreadyRedefined, indexes) {
|
|
141618
|
+
if (target.includes(".")) return [];
|
|
141619
|
+
const segments = target.split("::");
|
|
141620
|
+
const targetName = segments.pop()?.replace(/^'|'$/g, "");
|
|
141621
|
+
if (!targetName) return [];
|
|
141622
|
+
const qualifier = segments.join("::").replace(/^'|'$/g, "");
|
|
141623
|
+
const matches = /* @__PURE__ */ new Map();
|
|
141624
|
+
for (const supertype of this.resolveDirectSupertypes(owner, indexes)) {
|
|
141625
|
+
const branch = this.getSpecializationHierarchy(supertype, indexes);
|
|
141626
|
+
const anchors = qualifier ? branch.flat().filter((type) => this.matchesSpecializationQualifier(type, qualifier)) : [supertype];
|
|
141627
|
+
for (const anchor of anchors) {
|
|
141628
|
+
let frontier = [anchor];
|
|
141629
|
+
const visited = new Set(frontier);
|
|
141630
|
+
const candidates = [];
|
|
141631
|
+
while (frontier.length > 0 && candidates.length === 0) {
|
|
141632
|
+
for (const type of frontier) {
|
|
141633
|
+
for (const member of indexes.byParent.get(namespaceKeyOf(type)) ?? []) {
|
|
141634
|
+
if (member.name === targetName && member.visibility !== "private" && !alreadyRedefined.has(member.symbolId)) {
|
|
141635
|
+
candidates.push(member);
|
|
141636
|
+
}
|
|
141637
|
+
}
|
|
141638
|
+
}
|
|
141639
|
+
if (candidates.length > 0) break;
|
|
141640
|
+
const next = /* @__PURE__ */ new Map();
|
|
141641
|
+
for (const type of frontier) {
|
|
141642
|
+
for (const parent of this.resolveDirectSupertypes(type, indexes)) {
|
|
141643
|
+
if (visited.has(parent)) continue;
|
|
141644
|
+
visited.add(parent);
|
|
141645
|
+
next.set(parent.symbolId, parent);
|
|
141646
|
+
}
|
|
141647
|
+
}
|
|
141648
|
+
frontier = [...next.values()];
|
|
141649
|
+
}
|
|
141650
|
+
for (const candidate of candidates) matches.set(candidate.symbolId, candidate);
|
|
141651
|
+
}
|
|
141652
|
+
}
|
|
141653
|
+
return matches.size === 1 ? [...matches.values()] : [];
|
|
141654
|
+
}
|
|
141655
|
+
resolveDirectSupertypes(scope, indexes) {
|
|
141656
|
+
const supertypes = /* @__PURE__ */ new Map();
|
|
141657
|
+
for (const typeName of scope.typeNames) {
|
|
141658
|
+
const supertype = this.namespaceResolver.resolveNameFrom(scope, typeName, indexes);
|
|
141659
|
+
if (supertype && isDefinition(supertype.kind)) supertypes.set(supertype.symbolId, supertype);
|
|
141660
|
+
}
|
|
141661
|
+
return [...supertypes.values()];
|
|
141662
|
+
}
|
|
141663
|
+
getSpecializationHierarchy(scope, indexes) {
|
|
141664
|
+
const levels = [[scope]];
|
|
141665
|
+
const visited = /* @__PURE__ */ new Set([scope]);
|
|
141666
|
+
let frontier = [scope];
|
|
141667
|
+
while (frontier.length > 0) {
|
|
141668
|
+
const next = [];
|
|
141669
|
+
for (const type of frontier) {
|
|
141670
|
+
for (const parent of this.resolveDirectSupertypes(type, indexes)) {
|
|
141671
|
+
if (visited.has(parent)) continue;
|
|
141672
|
+
visited.add(parent);
|
|
141673
|
+
next.push(parent);
|
|
141674
|
+
}
|
|
141675
|
+
}
|
|
141676
|
+
if (next.length > 0) levels.push(next);
|
|
141677
|
+
frontier = next;
|
|
141678
|
+
}
|
|
141679
|
+
return levels;
|
|
141680
|
+
}
|
|
141681
|
+
matchesSpecializationQualifier(type, qualifier) {
|
|
141682
|
+
return type.name === qualifier || type.qualifiedName === qualifier || type.qualifiedName?.endsWith(`::${qualifier}`) === true;
|
|
141683
|
+
}
|
|
141463
141684
|
findContainingSymbolByLine(symbols, line) {
|
|
141464
141685
|
return symbols.filter((s) => s.range.start.line <= line && s.range.end.line >= line).sort((a, b) => {
|
|
141465
141686
|
const ar = (a.range.end.line - a.range.start.line) * 1e3 + (a.range.end.character - a.range.start.character);
|
|
@@ -141470,7 +141691,7 @@ ${info.documentation}`);
|
|
|
141470
141691
|
findConstraintScopeSymbol(symbolsInUri, indexes, line) {
|
|
141471
141692
|
let scope = this.findContainingSymbolByLine(symbolsInUri, line);
|
|
141472
141693
|
while (scope) {
|
|
141473
|
-
const members =
|
|
141694
|
+
const members = this.getConstraintScopeMembers(scope, indexes);
|
|
141474
141695
|
if (members.length > 0) return scope;
|
|
141475
141696
|
if (!scope.parentId) return scope;
|
|
141476
141697
|
scope = ownerOf(scope, indexes);
|
|
@@ -142065,7 +142286,8 @@ ${info.documentation}`);
|
|
|
142065
142286
|
if (loggedFolderPrefixes.get(folderUri) === prefix) continue;
|
|
142066
142287
|
loggedFolderPrefixes.set(folderUri, prefix);
|
|
142067
142288
|
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
|
-
|
|
142289
|
+
const folderPath = toFsPath(folderUri) ?? folderUri;
|
|
142290
|
+
connection.console.debug(`Folder ${folderPath}: element ID namespace ${prefix} (${source}; ID namespace only, no network access)`);
|
|
142069
142291
|
}
|
|
142070
142292
|
for (const folderUri of loggedFolderPrefixes.keys()) {
|
|
142071
142293
|
if (!workspaceFolderUris.includes(folderUri)) loggedFolderPrefixes.delete(folderUri);
|