sysml-v2-lsp 0.34.0 → 0.35.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 +18 -0
- package/dist/server/browserServerMain.js +174 -14
- package/dist/server/mcpServer.js +123 -17
- package/dist/server/server.js +174 -14
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.35.0]
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Add Copilot guidance to check generated and upstream-managed files during changes and reviews, fix their source of truth rather than editing overwritten artifacts, and validate fixes after regeneration.
|
|
10
|
+
- A projectId per workspace folder: before scanning a folder, the server asks the client for its `sysml.project` setting (`workspace/configuration`, scoped to the folder), `{ projectId }`. A top-level element of a document in that folder (the innermost one, if nested) gets the URL `urn:uuid:<projectId>/<name>`, so the same name in two folders with different projectIds gives two symbol IDs (KerML 9.1). A folder without one uses an enclosing folder's projectId, else `initializationOptions.projectId`; one whose `projectId` isn't a UUID is reported and left out. The projectIds are asked for again on `workspace/didChangeConfiguration`, and documents already indexed under another projectId get new symbol IDs. Each folder's prefix, and where it comes from, is logged when it changes (`Folder <uri>: top-level elements' URLs start with urn:uuid:<projectId>/ (its projectId)`).
|
|
11
|
+
- Follow workspace folders added or removed while running (`workspace/didChangeWorkspaceFolders`, now requested): an added folder is scanned, as at start, and the documents scanned from a removed folder are dropped.
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- `sysml/model` and `sysml/elementLookup` answer only once the server's `initialized` phase is done (settings and each folder's projectId pulled from the client, library indexed, DFA loaded). A request sent earlier now waits, instead of being answered with symbol IDs that might change once the projectIds arrive. A client that declares the `workspace/configuration` capability must answer those requests.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- A transition is typed by the payload its trigger accepts, read from the parse tree. The payload type ran into whatever followed it in the whitespace-free text (`accept cmd : Command if cmd.code == 0 then busy` gave `Commandifcmd`, `accept cmd : Command then busy` gave `Commandthenbusy`), reported as `unresolved-type`.
|
|
20
|
+
- A state's `entry`, `do` and `exit` actions (`exit action leave : WriteSafeState;`, `exit leave;`) get a symbol, as a `perform action` (the `StatePerformActionUsage` production). They had none, so they were missing from the outline, and an action definition that only typed one was reported as `unused-definition`.
|
|
21
|
+
- Concern definitions and usages (`concern def H { ... }`, `concern c : H { ... }`, and a requirement's framed concerns, `frame concern c : H { ... }`) get a symbol, of the new kinds `concern def` and `concern` (metaclasses `ConcernDefinition`, `ConcernUsage`). They had none, so their members were attributed to the enclosing namespace: two concerns, or two framed concerns of one requirement, that each declared `attribute limit` were reported as `ambiguous-namespace-name`, and concerns were missing from the outline and `sysml/model`.
|
|
22
|
+
|
|
5
23
|
## [0.34.0]
|
|
6
24
|
|
|
7
25
|
### Added
|
|
@@ -130252,6 +130252,10 @@ ${JSON.stringify(message, null, 4)}`);
|
|
|
130252
130252
|
function canonicalUri(uri) {
|
|
130253
130253
|
return uri.replace(/^file:\/\/\/([A-Za-z])(?::|%3[Aa])(?=\/|$)/, (_m, drive) => `file:///${drive.toLowerCase()}:`);
|
|
130254
130254
|
}
|
|
130255
|
+
function isInFolder(uri, folderUri) {
|
|
130256
|
+
const folder = canonicalUri(folderUri);
|
|
130257
|
+
return canonicalUri(uri).startsWith(folder.endsWith("/") ? folder : `${folder}/`);
|
|
130258
|
+
}
|
|
130255
130259
|
function isSameDocumentUri(a, b) {
|
|
130256
130260
|
return a === b || canonicalUri(a) === canonicalUri(b);
|
|
130257
130261
|
}
|
|
@@ -130410,6 +130414,7 @@ ${JSON.stringify(message, null, 4)}`);
|
|
|
130410
130414
|
var NAMESPACE_URL = v5_default.URL;
|
|
130411
130415
|
var DEFAULT_URL_PREFIX = "https://github.com/daltskin/sysml-v2-lsp/";
|
|
130412
130416
|
var urlPrefix = DEFAULT_URL_PREFIX;
|
|
130417
|
+
var folderPrefixes = [];
|
|
130413
130418
|
function setProjectId(projectId) {
|
|
130414
130419
|
if (projectId === void 0) {
|
|
130415
130420
|
urlPrefix = DEFAULT_URL_PREFIX;
|
|
@@ -130419,8 +130424,14 @@ ${JSON.stringify(message, null, 4)}`);
|
|
|
130419
130424
|
urlPrefix = `urn:uuid:${projectId.toLowerCase()}/`;
|
|
130420
130425
|
return true;
|
|
130421
130426
|
}
|
|
130422
|
-
function
|
|
130423
|
-
|
|
130427
|
+
function setFolderProjectIds(projectIds) {
|
|
130428
|
+
const rejected = projectIds.filter((p) => !validate_default(p.projectId));
|
|
130429
|
+
folderPrefixes = projectIds.filter((p) => validate_default(p.projectId)).map((p) => ({ folderUri: p.folderUri, prefix: `urn:uuid:${p.projectId.toLowerCase()}/` })).sort((a, b) => b.folderUri.length - a.folderUri.length);
|
|
130430
|
+
return rejected;
|
|
130431
|
+
}
|
|
130432
|
+
function getUrlPrefix(uri) {
|
|
130433
|
+
const match = uri === void 0 ? void 0 : folderPrefixes.find((f2) => isInFolder(uri, f2.folderUri));
|
|
130434
|
+
return match?.prefix ?? urlPrefix;
|
|
130424
130435
|
}
|
|
130425
130436
|
function uuidV5(namespace, name) {
|
|
130426
130437
|
return v5_default(name, namespace);
|
|
@@ -130502,6 +130513,10 @@ ${JSON.stringify(message, null, 4)}`);
|
|
|
130502
130513
|
return "RequirementDefinition";
|
|
130503
130514
|
case "requirement" /* RequirementUsage */:
|
|
130504
130515
|
return "RequirementUsage";
|
|
130516
|
+
case "concern def" /* ConcernDef */:
|
|
130517
|
+
return "ConcernDefinition";
|
|
130518
|
+
case "concern" /* ConcernUsage */:
|
|
130519
|
+
return "ConcernUsage";
|
|
130505
130520
|
case "constraint def" /* ConstraintDef */:
|
|
130506
130521
|
return "ConstraintDefinition";
|
|
130507
130522
|
case "constraint" /* ConstraintUsage */:
|
|
@@ -130624,7 +130639,7 @@ ${JSON.stringify(message, null, 4)}`);
|
|
|
130624
130639
|
declaration.parentId = owner?.symbolId;
|
|
130625
130640
|
const path = declaration.qualifiedName !== void 0 ? this.qualifiedNameAsWritten(declaration) : owner ? `${this.paths.get(owner)}/${segmentOf(declaration)}` : segmentOf(declaration);
|
|
130626
130641
|
const namespace = owner ? this.topLevelOf(owner).symbolId : NAMESPACE_URL;
|
|
130627
|
-
const key = owner ? path : getUrlPrefix() + encodeURIComponent(path);
|
|
130642
|
+
const key = owner ? path : getUrlPrefix(declaration.uri) + encodeURIComponent(path);
|
|
130628
130643
|
const groupId = this.uuidOf(namespace, key);
|
|
130629
130644
|
this.groupKeys.set(groupId, { namespace, key, path });
|
|
130630
130645
|
this.groupOf.set(declaration, groupId);
|
|
@@ -130809,6 +130824,12 @@ ${JSON.stringify(message, null, 4)}`);
|
|
|
130809
130824
|
// 343
|
|
130810
130825
|
[SysMLv2Parser.RULE_requirementDefinition, "requirement def" /* RequirementDef */],
|
|
130811
130826
|
// 384
|
|
130827
|
+
[SysMLv2Parser.RULE_concernDefinition, "concern def" /* ConcernDef */],
|
|
130828
|
+
// 405
|
|
130829
|
+
[SysMLv2Parser.RULE_concernUsage, "concern" /* ConcernUsage */],
|
|
130830
|
+
// 406
|
|
130831
|
+
[SysMLv2Parser.RULE_framedConcernUsage, "concern" /* ConcernUsage */],
|
|
130832
|
+
// 394
|
|
130812
130833
|
[SysMLv2Parser.RULE_constraintDefinition, "constraint def" /* ConstraintDef */],
|
|
130813
130834
|
// 380
|
|
130814
130835
|
[SysMLv2Parser.RULE_itemDefinition, "item def" /* ItemDef */],
|
|
@@ -130881,6 +130902,10 @@ ${JSON.stringify(message, null, 4)}`);
|
|
|
130881
130902
|
// 268
|
|
130882
130903
|
[SysMLv2Parser.RULE_performActionUsage, "perform action" /* PerformActionUsage */],
|
|
130883
130904
|
// 298
|
|
130905
|
+
// A state's `entry`/`do`/`exit` action (`exit action a : A;`, `exit a;`): the
|
|
130906
|
+
// StatePerformActionUsage production, a PerformActionUsage without `perform`.
|
|
130907
|
+
[SysMLv2Parser.RULE_statePerformActionUsage, "perform action" /* PerformActionUsage */],
|
|
130908
|
+
// 352
|
|
130884
130909
|
[SysMLv2Parser.RULE_exhibitStateUsage, "exhibit state" /* ExhibitStateUsage */],
|
|
130885
130910
|
// 359
|
|
130886
130911
|
[SysMLv2Parser.RULE_transitionUsage, "transition" /* TransitionUsage */],
|
|
@@ -131004,8 +131029,10 @@ ${JSON.stringify(message, null, 4)}`);
|
|
|
131004
131029
|
// 210
|
|
131005
131030
|
SysMLv2Parser.RULE_definition,
|
|
131006
131031
|
// 192
|
|
131007
|
-
SysMLv2Parser.RULE_usage
|
|
131032
|
+
SysMLv2Parser.RULE_usage,
|
|
131008
131033
|
// 208
|
|
131034
|
+
SysMLv2Parser.RULE_payloadFeatureSpecializationPart
|
|
131035
|
+
// 157
|
|
131009
131036
|
]);
|
|
131010
131037
|
var DOC_RULE_INDICES = /* @__PURE__ */ new Set([
|
|
131011
131038
|
SysMLv2Parser.RULE_comment,
|
|
@@ -131630,7 +131657,7 @@ ${JSON.stringify(message, null, 4)}`);
|
|
|
131630
131657
|
const shortName = transition || isFlowUsage(kind) && !declaredName ? void 0 : this.extractShortName(ctx);
|
|
131631
131658
|
const qualifiedName = anonymous || owner && owner.qualifiedName === void 0 ? void 0 : owner ? `${owner.qualifiedName}::${name}` : name;
|
|
131632
131659
|
const selectionRange = anonymous ? ctx.start ? tokenToRange(ctx.start) : range : this.extractNameRange(ctx) ?? range;
|
|
131633
|
-
const typeNames = isFlowUsage(kind) ? this.extractFlowTypeNames(ctx) : this.extractTypeNames(ctx);
|
|
131660
|
+
const typeNames = isFlowUsage(kind) ? this.extractFlowTypeNames(ctx) : transition ? this.extractTransitionTypeNames(ctx) : this.extractTypeNames(ctx);
|
|
131634
131661
|
const specializationNames = this.extractSpecializationNames(ctx);
|
|
131635
131662
|
const typeName = typeNames[0];
|
|
131636
131663
|
const documentation = this.extractDocumentation(ctx);
|
|
@@ -131745,6 +131772,25 @@ ${JSON.stringify(message, null, 4)}`);
|
|
|
131745
131772
|
const typeDeclaration = declaration && (this.findOwnHeaderRule(declaration, SysMLv2Parser.RULE_featureDeclaration) ?? this.findOwnHeaderRule(declaration, SysMLv2Parser.RULE_usageDeclaration));
|
|
131746
131773
|
return typeDeclaration ? this.extractTypeNames(typeDeclaration) : [];
|
|
131747
131774
|
}
|
|
131775
|
+
/**
|
|
131776
|
+
* A transition's own typing, then the types of the payload its trigger
|
|
131777
|
+
* accepts (`accept cmd : Command`, `accept Command`; TriggerAction ->
|
|
131778
|
+
* AcceptParameterPart -> PayloadParameter). Read from the parse tree only:
|
|
131779
|
+
* the regex fallback of `extractTypeNames` runs on whitespace-free text, where
|
|
131780
|
+
* the payload type runs into the guard, effect or target that follows it
|
|
131781
|
+
* (`Commandifcmd`, `Commandthenbusy`).
|
|
131782
|
+
*/
|
|
131783
|
+
extractTransitionTypeNames(ctx) {
|
|
131784
|
+
const names = [];
|
|
131785
|
+
this.collectTypeNamesFromTree(ctx, names, 0);
|
|
131786
|
+
const trigger = this.findOwnHeaderRule(ctx, SysMLv2Parser.RULE_triggerActionMember);
|
|
131787
|
+
const parameter = trigger && this.findRuleContext(trigger, SysMLv2Parser.RULE_payloadParameter);
|
|
131788
|
+
if (parameter) {
|
|
131789
|
+
const payload = this.findRuleContext(parameter, SysMLv2Parser.RULE_payloadFeature) ?? parameter;
|
|
131790
|
+
this.collectTypeNamesFromTree(payload, names, 0);
|
|
131791
|
+
}
|
|
131792
|
+
return names;
|
|
131793
|
+
}
|
|
131748
131794
|
/** Find the first descendant of `ctx` with rule `ruleIndex`, in source order. */
|
|
131749
131795
|
findRuleContext(ctx, ruleIndex) {
|
|
131750
131796
|
const matches = [];
|
|
@@ -131870,7 +131916,7 @@ ${JSON.stringify(message, null, 4)}`);
|
|
|
131870
131916
|
*/
|
|
131871
131917
|
anonymousDeclaration(ctx, kind, transition) {
|
|
131872
131918
|
if (!isDefinition(kind) && !isUsage(kind)) return void 0;
|
|
131873
|
-
if (transition && !(transition.source && transition.target) && this.
|
|
131919
|
+
if (transition && !(transition.source && transition.target) && this.extractTransitionTypeNames(ctx).length === 0) return void 0;
|
|
131874
131920
|
return this.declarationText(ctx);
|
|
131875
131921
|
}
|
|
131876
131922
|
/**
|
|
@@ -132950,6 +132996,17 @@ ${JSON.stringify(message, null, 4)}`);
|
|
|
132950
132996
|
}
|
|
132951
132997
|
return this.wsSymbolTable;
|
|
132952
132998
|
}
|
|
132999
|
+
/**
|
|
133000
|
+
* Rebuild the symbol tables of `uris` on next use, e.g. after their projectId
|
|
133001
|
+
* changed, which changes their symbol IDs (see `setFolderProjectIds`).
|
|
133002
|
+
*/
|
|
133003
|
+
invalidateSymbols(uris) {
|
|
133004
|
+
for (const uri of uris) {
|
|
133005
|
+
const cached = this.cache.get(uri);
|
|
133006
|
+
if (cached) cached.symbolTable = void 0;
|
|
133007
|
+
this.wsBuiltVersions.delete(uri);
|
|
133008
|
+
}
|
|
133009
|
+
}
|
|
132953
133010
|
/**
|
|
132954
133011
|
* Cache semantic diagnostics for the current document version.
|
|
132955
133012
|
*/
|
|
@@ -139305,6 +139362,8 @@ ${childIndent}item def ${unresolvedType};
|
|
|
139305
139362
|
// Requirements → Object
|
|
139306
139363
|
case "requirement def" /* RequirementDef */:
|
|
139307
139364
|
case "requirement" /* RequirementUsage */:
|
|
139365
|
+
case "concern def" /* ConcernDef */:
|
|
139366
|
+
case "concern" /* ConcernUsage */:
|
|
139308
139367
|
case "actor" /* ActorUsage */:
|
|
139309
139368
|
case "subject" /* SubjectUsage */:
|
|
139310
139369
|
case "stakeholder" /* StakeholderUsage */:
|
|
@@ -141704,6 +141763,10 @@ ${info.documentation}`);
|
|
|
141704
141763
|
var hasConfigurationCapability = false;
|
|
141705
141764
|
var hasWorkspaceFolderCapability = false;
|
|
141706
141765
|
var workspaceRoots = [];
|
|
141766
|
+
var workspaceFolderUris = [];
|
|
141767
|
+
function rootsOf(folderUris) {
|
|
141768
|
+
return folderUris.map((uri) => toFsPath(uri)).filter((p) => p !== void 0);
|
|
141769
|
+
}
|
|
141707
141770
|
var isWorkspaceFile = false;
|
|
141708
141771
|
var preloadOnOpen = "workspaceOnly";
|
|
141709
141772
|
var disabledDiagnosticCodes = /* @__PURE__ */ new Set();
|
|
@@ -141715,6 +141778,10 @@ ${info.documentation}`);
|
|
|
141715
141778
|
}
|
|
141716
141779
|
var skipDirs = new Set(DEFAULT_SKIP_DIRS);
|
|
141717
141780
|
var serverReady = false;
|
|
141781
|
+
var resolveInitialization;
|
|
141782
|
+
var initialization = new Promise((resolve) => {
|
|
141783
|
+
resolveInitialization = resolve;
|
|
141784
|
+
});
|
|
141718
141785
|
var earlyOpenUris = /* @__PURE__ */ new Set();
|
|
141719
141786
|
var workerRequestId = 0;
|
|
141720
141787
|
var isBrowserServer = true;
|
|
@@ -141828,7 +141895,8 @@ ${info.documentation}`);
|
|
|
141828
141895
|
connection.console.warn(`projectId is not a UUID: ${initOpts.projectId}; symbol IDs are unique only within this workspace`);
|
|
141829
141896
|
}
|
|
141830
141897
|
if (params.workspaceFolders) {
|
|
141831
|
-
|
|
141898
|
+
workspaceFolderUris = params.workspaceFolders.map((f2) => f2.uri);
|
|
141899
|
+
workspaceRoots = rootsOf(workspaceFolderUris);
|
|
141832
141900
|
} else if (params.rootUri) {
|
|
141833
141901
|
const root = toFsPath(params.rootUri);
|
|
141834
141902
|
if (root) workspaceRoots = [root];
|
|
@@ -141878,7 +141946,8 @@ ${info.documentation}`);
|
|
|
141878
141946
|
if (hasWorkspaceFolderCapability) {
|
|
141879
141947
|
result.capabilities.workspace = {
|
|
141880
141948
|
workspaceFolders: {
|
|
141881
|
-
supported: true
|
|
141949
|
+
supported: true,
|
|
141950
|
+
changeNotifications: true
|
|
141882
141951
|
}
|
|
141883
141952
|
};
|
|
141884
141953
|
}
|
|
@@ -141890,8 +141959,17 @@ ${info.documentation}`);
|
|
|
141890
141959
|
import_node11.DidChangeConfigurationNotification.type,
|
|
141891
141960
|
void 0
|
|
141892
141961
|
);
|
|
141962
|
+
}
|
|
141963
|
+
if (hasWorkspaceFolderCapability) {
|
|
141964
|
+
connection.workspace.onDidChangeWorkspaceFolders((event) => {
|
|
141965
|
+
onWorkspaceFoldersChanged(event).catch((e) => connection.console.error(`Workspace folder change failed: ${e}`));
|
|
141966
|
+
});
|
|
141967
|
+
}
|
|
141968
|
+
if (hasConfigurationCapability) {
|
|
141893
141969
|
await pullSettings().catch(() => {
|
|
141894
141970
|
});
|
|
141971
|
+
await pullFolderProjectIds().catch(() => {
|
|
141972
|
+
});
|
|
141895
141973
|
}
|
|
141896
141974
|
const libCount = initLibraryIndex("/");
|
|
141897
141975
|
connection.console.log(`SysML v2 Language Server initialized (${libCount} library packages indexed)`);
|
|
@@ -141907,14 +141985,13 @@ ${info.documentation}`);
|
|
|
141907
141985
|
);
|
|
141908
141986
|
}
|
|
141909
141987
|
serverReady = true;
|
|
141988
|
+
resolveInitialization();
|
|
141910
141989
|
spawnParseWorker();
|
|
141911
141990
|
if (workspaceRoots.length > 0 && (preloadOnOpen === "always" || preloadOnOpen === "workspaceOnly" && isWorkspaceFile)) {
|
|
141912
|
-
|
|
141913
|
-
scanWorkspaceFoldersAsync(workspaceRoots).then(({ fileCount, scanMs }) => {
|
|
141991
|
+
scanWorkspaceFolders(workspaceRoots).then(({ fileCount, scanMs }) => {
|
|
141914
141992
|
connection.console.log(
|
|
141915
141993
|
`Workspace scan: pre-parsed ${fileCount} .sysml files in ${scanMs} ms`
|
|
141916
141994
|
);
|
|
141917
|
-
documentManager.setWorkspaceScanComplete(true);
|
|
141918
141995
|
revalidateOpenDocuments();
|
|
141919
141996
|
});
|
|
141920
141997
|
}
|
|
@@ -141949,9 +142026,79 @@ ${info.documentation}`);
|
|
|
141949
142026
|
}
|
|
141950
142027
|
}
|
|
141951
142028
|
connection.onDidChangeConfiguration((_change) => {
|
|
141952
|
-
pullSettings().then(() => revalidateOpenDocuments()).catch(() => {
|
|
142029
|
+
pullSettings().then(() => pullFolderProjectIds()).then(() => revalidateOpenDocuments()).catch(() => {
|
|
142030
|
+
});
|
|
142031
|
+
});
|
|
142032
|
+
function latestWins(task) {
|
|
142033
|
+
let calls = 0;
|
|
142034
|
+
let latest = Promise.resolve();
|
|
142035
|
+
return () => {
|
|
142036
|
+
const call = ++calls;
|
|
142037
|
+
const isSuperseded = () => call !== calls;
|
|
142038
|
+
const run = task(isSuperseded).then(() => isSuperseded() ? latest : void 0);
|
|
142039
|
+
latest = run;
|
|
142040
|
+
return run;
|
|
142041
|
+
};
|
|
142042
|
+
}
|
|
142043
|
+
var pullFolderProjectIds = latestWins(async (isSuperseded) => {
|
|
142044
|
+
if (!hasConfigurationCapability) return;
|
|
142045
|
+
const folderUris = [...workspaceFolderUris];
|
|
142046
|
+
const answers = folderUris.length === 0 ? [] : await connection.workspace.getConfiguration(folderUris.map((scopeUri) => ({ scopeUri, section: "sysml.project" })));
|
|
142047
|
+
if (isSuperseded()) return;
|
|
142048
|
+
const projectIds = folderUris.flatMap((folderUri, i) => {
|
|
142049
|
+
const projectId = answers[i]?.projectId;
|
|
142050
|
+
return typeof projectId === "string" ? [{ folderUri, projectId }] : [];
|
|
141953
142051
|
});
|
|
142052
|
+
const uris = documentManager.getUris();
|
|
142053
|
+
const prefixBefore = new Map(uris.map((uri) => [uri, getUrlPrefix(uri)]));
|
|
142054
|
+
const rejected = setFolderProjectIds(projectIds);
|
|
142055
|
+
for (const entry of rejected) {
|
|
142056
|
+
connection.console.warn(`projectId of ${entry.folderUri} is not a UUID: ${entry.projectId}; ignored, so its documents use the projectId of an enclosing folder, else initializationOptions.projectId, else the default prefix`);
|
|
142057
|
+
}
|
|
142058
|
+
documentManager.invalidateSymbols(uris.filter((uri) => getUrlPrefix(uri) !== prefixBefore.get(uri)));
|
|
142059
|
+
logFolderPrefixes(new Set(projectIds.filter((p) => !rejected.includes(p)).map((p) => p.folderUri)));
|
|
141954
142060
|
});
|
|
142061
|
+
var loggedFolderPrefixes = /* @__PURE__ */ new Map();
|
|
142062
|
+
function logFolderPrefixes(ownProjectIds) {
|
|
142063
|
+
for (const folderUri of workspaceFolderUris) {
|
|
142064
|
+
const prefix = getUrlPrefix(`${folderUri.endsWith("/") ? folderUri : `${folderUri}/`}_.sysml`);
|
|
142065
|
+
if (loggedFolderPrefixes.get(folderUri) === prefix) continue;
|
|
142066
|
+
loggedFolderPrefixes.set(folderUri, prefix);
|
|
142067
|
+
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})`);
|
|
142069
|
+
}
|
|
142070
|
+
for (const folderUri of loggedFolderPrefixes.keys()) {
|
|
142071
|
+
if (!workspaceFolderUris.includes(folderUri)) loggedFolderPrefixes.delete(folderUri);
|
|
142072
|
+
}
|
|
142073
|
+
}
|
|
142074
|
+
async function onWorkspaceFoldersChanged(event) {
|
|
142075
|
+
const initialScanPending = !serverReady;
|
|
142076
|
+
const removed = new Set(event.removed.map((f2) => f2.uri));
|
|
142077
|
+
workspaceFolderUris = [...workspaceFolderUris.filter((uri) => !removed.has(uri)), ...event.added.map((f2) => f2.uri)];
|
|
142078
|
+
workspaceRoots = rootsOf(workspaceFolderUris);
|
|
142079
|
+
dropDocumentsOutsideWorkspace(event.removed.map((f2) => f2.uri));
|
|
142080
|
+
await pullFolderProjectIds().catch(() => {
|
|
142081
|
+
});
|
|
142082
|
+
if (initialScanPending) return;
|
|
142083
|
+
const addedRoots = rootsOf(event.added.map((f2) => f2.uri).filter((uri) => workspaceFolderUris.includes(uri)));
|
|
142084
|
+
if (addedRoots.length > 0 && (preloadOnOpen === "always" || preloadOnOpen === "workspaceOnly" && isWorkspaceFile)) {
|
|
142085
|
+
const { fileCount, scanMs } = await scanWorkspaceFolders(addedRoots);
|
|
142086
|
+
connection.console.log(`Workspace scan: pre-parsed ${fileCount} .sysml files of ${addedRoots.length} added folder(s) in ${scanMs} ms`);
|
|
142087
|
+
}
|
|
142088
|
+
revalidateOpenDocuments();
|
|
142089
|
+
}
|
|
142090
|
+
function dropDocumentsOutsideWorkspace(folderUris) {
|
|
142091
|
+
for (const uri of documentManager.getUris()) {
|
|
142092
|
+
if (openDocumentFor(uri)) continue;
|
|
142093
|
+
if (folderUris.some((f2) => isInFolder(uri, f2)) && !isInWorkspace(uri)) {
|
|
142094
|
+
documentManager.remove(uri);
|
|
142095
|
+
modelProvider.removeUri(uri);
|
|
142096
|
+
}
|
|
142097
|
+
}
|
|
142098
|
+
}
|
|
142099
|
+
function isInWorkspace(uri) {
|
|
142100
|
+
return workspaceRoots.some((root) => isInFolder(uri, pathToFileURL(root).toString()));
|
|
142101
|
+
}
|
|
141955
142102
|
function openDocumentFor(uri) {
|
|
141956
142103
|
return documents.get(uri) ?? documents.all().find((d) => isSameDocumentUri(d.uri, uri));
|
|
141957
142104
|
}
|
|
@@ -141976,6 +142123,16 @@ ${info.documentation}`);
|
|
|
141976
142123
|
documentManager.parse(doc);
|
|
141977
142124
|
return true;
|
|
141978
142125
|
}
|
|
142126
|
+
var runningScans = 0;
|
|
142127
|
+
async function scanWorkspaceFolders(roots) {
|
|
142128
|
+
runningScans++;
|
|
142129
|
+
documentManager.setWorkspaceScanComplete(false);
|
|
142130
|
+
try {
|
|
142131
|
+
return await scanWorkspaceFoldersAsync(roots);
|
|
142132
|
+
} finally {
|
|
142133
|
+
if (--runningScans === 0) documentManager.setWorkspaceScanComplete(true);
|
|
142134
|
+
}
|
|
142135
|
+
}
|
|
141979
142136
|
async function scanWorkspaceFoldersAsync(roots) {
|
|
141980
142137
|
const scanT0 = Date.now();
|
|
141981
142138
|
const fileArrays = await Promise.all(roots.map((r) => findSysMLFilesAsync(r, skipDirs)));
|
|
@@ -141987,6 +142144,7 @@ ${info.documentation}`);
|
|
|
141987
142144
|
const filePath = allFiles[i];
|
|
141988
142145
|
const uri = pathToFileURL(filePath).toString();
|
|
141989
142146
|
if (openDocumentFor(uri)) continue;
|
|
142147
|
+
if (!isInWorkspace(uri)) continue;
|
|
141990
142148
|
const content = fileContents.get(filePath);
|
|
141991
142149
|
if (content === void 0) continue;
|
|
141992
142150
|
documentManager.parseBatch(uri, 0, content);
|
|
@@ -142199,14 +142357,16 @@ ${info.documentation}`);
|
|
|
142199
142357
|
return formattingProvider.provideRangeFormatting(params);
|
|
142200
142358
|
}
|
|
142201
142359
|
);
|
|
142202
|
-
connection.onRequest("sysml/model", (params) => {
|
|
142360
|
+
connection.onRequest("sysml/model", async (params) => {
|
|
142361
|
+
await initialization;
|
|
142203
142362
|
return modelProvider.getModel(
|
|
142204
142363
|
params.textDocument.uri,
|
|
142205
142364
|
documentManager.getVersion(params.textDocument.uri),
|
|
142206
142365
|
params.scope
|
|
142207
142366
|
);
|
|
142208
142367
|
});
|
|
142209
|
-
connection.onRequest("sysml/elementLookup", (params) => {
|
|
142368
|
+
connection.onRequest("sysml/elementLookup", async (params) => {
|
|
142369
|
+
await initialization;
|
|
142210
142370
|
return elementLookupProvider.elementLookup(params);
|
|
142211
142371
|
});
|
|
142212
142372
|
connection.onRequest("sysml/serverStats", () => {
|
package/dist/server/mcpServer.js
CHANGED
|
@@ -42741,6 +42741,9 @@ var Protocol = class {
|
|
|
42741
42741
|
this.setRequestHandler(GetTaskPayloadRequestSchema, async (request, extra) => {
|
|
42742
42742
|
const handleTaskResult = async () => {
|
|
42743
42743
|
const taskId = request.params.taskId;
|
|
42744
|
+
if (!await this._taskStore.getTask(taskId, extra.sessionId)) {
|
|
42745
|
+
throw new McpError(ErrorCode.InvalidParams, `Task not found: ${taskId}`);
|
|
42746
|
+
}
|
|
42744
42747
|
if (this._taskMessageQueue) {
|
|
42745
42748
|
let queuedMessage;
|
|
42746
42749
|
while (queuedMessage = await this._taskMessageQueue.dequeue(taskId, extra.sessionId)) {
|
|
@@ -42771,12 +42774,12 @@ var Protocol = class {
|
|
|
42771
42774
|
throw new McpError(ErrorCode.InvalidParams, `Task not found: ${taskId}`);
|
|
42772
42775
|
}
|
|
42773
42776
|
if (!isTerminal(task.status)) {
|
|
42774
|
-
await this._waitForTaskUpdate(taskId, extra.signal);
|
|
42777
|
+
await this._waitForTaskUpdate(taskId, extra.signal, extra.sessionId);
|
|
42775
42778
|
return await handleTaskResult();
|
|
42776
42779
|
}
|
|
42777
42780
|
if (isTerminal(task.status)) {
|
|
42778
42781
|
const result = await this._taskStore.getTaskResult(taskId, extra.sessionId);
|
|
42779
|
-
this._clearTaskQueue(taskId);
|
|
42782
|
+
this._clearTaskQueue(taskId, extra.sessionId);
|
|
42780
42783
|
return {
|
|
42781
42784
|
...result,
|
|
42782
42785
|
_meta: {
|
|
@@ -42813,7 +42816,7 @@ var Protocol = class {
|
|
|
42813
42816
|
throw new McpError(ErrorCode.InvalidParams, `Cannot cancel task in terminal status: ${task.status}`);
|
|
42814
42817
|
}
|
|
42815
42818
|
await this._taskStore.updateTaskStatus(request.params.taskId, "cancelled", "Client cancelled task execution.", extra.sessionId);
|
|
42816
|
-
this._clearTaskQueue(request.params.taskId);
|
|
42819
|
+
this._clearTaskQueue(request.params.taskId, extra.sessionId);
|
|
42817
42820
|
const cancelledTask = await this._taskStore.getTask(request.params.taskId, extra.sessionId);
|
|
42818
42821
|
if (!cancelledTask) {
|
|
42819
42822
|
throw new McpError(ErrorCode.InvalidParams, `Task not found after cancellation: ${request.params.taskId}`);
|
|
@@ -42941,6 +42944,19 @@ var Protocol = class {
|
|
|
42941
42944
|
const handler = this._requestHandlers.get(request.method) ?? this.fallbackRequestHandler;
|
|
42942
42945
|
const capturedTransport = this._transport;
|
|
42943
42946
|
const relatedTaskId = request.params?._meta?.[RELATED_TASK_META_KEY]?.taskId;
|
|
42947
|
+
const sessionId = capturedTransport?.sessionId;
|
|
42948
|
+
const store = this._taskStore;
|
|
42949
|
+
let relatedTaskFound = true;
|
|
42950
|
+
let relatedTaskLookup;
|
|
42951
|
+
if (relatedTaskId && store && this._taskMessageQueue && sessionId !== void 0) {
|
|
42952
|
+
relatedTaskFound = false;
|
|
42953
|
+
relatedTaskLookup = (async () => {
|
|
42954
|
+
if (!await store.getTask(relatedTaskId, sessionId)) {
|
|
42955
|
+
throw new McpError(ErrorCode.InvalidParams, `Task not found: ${relatedTaskId}`);
|
|
42956
|
+
}
|
|
42957
|
+
relatedTaskFound = true;
|
|
42958
|
+
})();
|
|
42959
|
+
}
|
|
42944
42960
|
if (handler === void 0) {
|
|
42945
42961
|
const errorResponse = {
|
|
42946
42962
|
jsonrpc: "2.0",
|
|
@@ -42950,7 +42966,10 @@ var Protocol = class {
|
|
|
42950
42966
|
message: "Method not found"
|
|
42951
42967
|
}
|
|
42952
42968
|
};
|
|
42953
|
-
if (relatedTaskId &&
|
|
42969
|
+
if (relatedTaskId && relatedTaskLookup) {
|
|
42970
|
+
const queuedError = { type: "error", message: errorResponse, timestamp: Date.now() };
|
|
42971
|
+
relatedTaskLookup.then(() => this._enqueueTaskMessage(relatedTaskId, queuedError, sessionId), () => capturedTransport?.send(errorResponse)).catch((error62) => this._onerror(new Error(`Failed to send an error response: ${error62}`)));
|
|
42972
|
+
} else if (relatedTaskId && this._taskMessageQueue) {
|
|
42954
42973
|
this._enqueueTaskMessage(relatedTaskId, {
|
|
42955
42974
|
type: "error",
|
|
42956
42975
|
message: errorResponse,
|
|
@@ -43001,7 +43020,10 @@ var Protocol = class {
|
|
|
43001
43020
|
closeSSEStream: extra?.closeSSEStream,
|
|
43002
43021
|
closeStandaloneSSEStream: extra?.closeStandaloneSSEStream
|
|
43003
43022
|
};
|
|
43004
|
-
Promise.resolve().then(() => {
|
|
43023
|
+
(relatedTaskLookup ?? Promise.resolve()).then(() => {
|
|
43024
|
+
if (relatedTaskLookup && abortController.signal.aborted) {
|
|
43025
|
+
throw new McpError(ErrorCode.ConnectionClosed, "Request was cancelled");
|
|
43026
|
+
}
|
|
43005
43027
|
if (taskCreationParams) {
|
|
43006
43028
|
this.assertTaskHandlerCapability(request.method);
|
|
43007
43029
|
}
|
|
@@ -43036,7 +43058,7 @@ var Protocol = class {
|
|
|
43036
43058
|
...error62["data"] !== void 0 && { data: error62["data"] }
|
|
43037
43059
|
}
|
|
43038
43060
|
};
|
|
43039
|
-
if (relatedTaskId && this._taskMessageQueue) {
|
|
43061
|
+
if (relatedTaskId && this._taskMessageQueue && relatedTaskFound) {
|
|
43040
43062
|
await this._enqueueTaskMessage(relatedTaskId, {
|
|
43041
43063
|
type: "error",
|
|
43042
43064
|
message: errorResponse,
|
|
@@ -43516,7 +43538,7 @@ var Protocol = class {
|
|
|
43516
43538
|
throw new Error("Cannot enqueue task message: taskStore and taskMessageQueue are not configured");
|
|
43517
43539
|
}
|
|
43518
43540
|
const maxQueueSize = this._options?.maxTaskQueueSize;
|
|
43519
|
-
await this._taskMessageQueue.enqueue(taskId, message, sessionId, maxQueueSize);
|
|
43541
|
+
await this._taskMessageQueue.enqueue(taskId, message, sessionId ?? this._transport?.sessionId, maxQueueSize);
|
|
43520
43542
|
}
|
|
43521
43543
|
/**
|
|
43522
43544
|
* Clears the message queue for a task and rejects any pending request resolvers.
|
|
@@ -43545,12 +43567,13 @@ var Protocol = class {
|
|
|
43545
43567
|
* Uses polling to check for updates at the task's configured poll interval.
|
|
43546
43568
|
* @param taskId The task ID to wait for
|
|
43547
43569
|
* @param signal Abort signal to cancel the wait
|
|
43570
|
+
* @param sessionId Session of the request that waits, passed to the task store
|
|
43548
43571
|
* @returns Promise that resolves when an update occurs or rejects if aborted
|
|
43549
43572
|
*/
|
|
43550
|
-
async _waitForTaskUpdate(taskId, signal) {
|
|
43573
|
+
async _waitForTaskUpdate(taskId, signal, sessionId) {
|
|
43551
43574
|
let interval = this._options?.defaultTaskPollInterval ?? 1e3;
|
|
43552
43575
|
try {
|
|
43553
|
-
const task = await this._taskStore?.getTask(taskId);
|
|
43576
|
+
const task = await this._taskStore?.getTask(taskId, sessionId);
|
|
43554
43577
|
if (task?.pollInterval) {
|
|
43555
43578
|
interval = task.pollInterval;
|
|
43556
43579
|
}
|
|
@@ -44429,6 +44452,42 @@ var ExperimentalMcpServerTasks = class {
|
|
|
44429
44452
|
};
|
|
44430
44453
|
|
|
44431
44454
|
// node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js
|
|
44455
|
+
function toolInputElementCount(value, max) {
|
|
44456
|
+
let count = 0;
|
|
44457
|
+
const stack = [value];
|
|
44458
|
+
while (stack.length > 0) {
|
|
44459
|
+
const node2 = stack.pop();
|
|
44460
|
+
if (node2 === null || typeof node2 !== "object")
|
|
44461
|
+
continue;
|
|
44462
|
+
if (Array.isArray(node2)) {
|
|
44463
|
+
for (const child of node2) {
|
|
44464
|
+
if (++count > max)
|
|
44465
|
+
return count;
|
|
44466
|
+
if (child !== null && typeof child === "object")
|
|
44467
|
+
stack.push(child);
|
|
44468
|
+
}
|
|
44469
|
+
} else {
|
|
44470
|
+
for (const key in node2) {
|
|
44471
|
+
if (!Object.prototype.hasOwnProperty.call(node2, key))
|
|
44472
|
+
continue;
|
|
44473
|
+
if (++count > max)
|
|
44474
|
+
return count;
|
|
44475
|
+
const child = node2[key];
|
|
44476
|
+
if (child !== null && typeof child === "object")
|
|
44477
|
+
stack.push(child);
|
|
44478
|
+
}
|
|
44479
|
+
}
|
|
44480
|
+
}
|
|
44481
|
+
return count;
|
|
44482
|
+
}
|
|
44483
|
+
function resolveMaxToolInputElements(value) {
|
|
44484
|
+
if (value === void 0 || value === Infinity)
|
|
44485
|
+
return void 0;
|
|
44486
|
+
if (typeof value !== "number" || Number.isNaN(value) || value < 1) {
|
|
44487
|
+
throw new RangeError(`maxToolInputElements must be a number of at least 1, or Infinity, got ${String(value)}`);
|
|
44488
|
+
}
|
|
44489
|
+
return value;
|
|
44490
|
+
}
|
|
44432
44491
|
var McpServer = class {
|
|
44433
44492
|
constructor(serverInfo, options) {
|
|
44434
44493
|
this._registeredResources = {};
|
|
@@ -44440,6 +44499,7 @@ var McpServer = class {
|
|
|
44440
44499
|
this._resourceHandlersInitialized = false;
|
|
44441
44500
|
this._promptHandlersInitialized = false;
|
|
44442
44501
|
this.server = new Server(serverInfo, options);
|
|
44502
|
+
this._maxToolInputElements = resolveMaxToolInputElements(options?.maxToolInputElements);
|
|
44443
44503
|
}
|
|
44444
44504
|
/**
|
|
44445
44505
|
* Access experimental features.
|
|
@@ -44570,12 +44630,15 @@ var McpServer = class {
|
|
|
44570
44630
|
* Validates tool input arguments against the tool's input schema.
|
|
44571
44631
|
*/
|
|
44572
44632
|
async validateToolInput(tool, args, toolName) {
|
|
44633
|
+
if (this._maxToolInputElements !== void 0 && toolInputElementCount(args, this._maxToolInputElements) > this._maxToolInputElements) {
|
|
44634
|
+
throw new McpError(ErrorCode.InvalidParams, `Invalid arguments for tool ${toolName}: arguments contain more than the maximum of ${this._maxToolInputElements} elements`);
|
|
44635
|
+
}
|
|
44573
44636
|
if (!tool.inputSchema) {
|
|
44574
44637
|
return void 0;
|
|
44575
44638
|
}
|
|
44576
44639
|
const inputObj = normalizeObjectSchema(tool.inputSchema);
|
|
44577
44640
|
const schemaToParse = inputObj ?? tool.inputSchema;
|
|
44578
|
-
const parseResult = await safeParseAsync2(schemaToParse, args);
|
|
44641
|
+
const parseResult = await safeParseAsync2(schemaToParse, args ?? {});
|
|
44579
44642
|
if (!parseResult.success) {
|
|
44580
44643
|
const error62 = "error" in parseResult ? parseResult.error : "Unknown error";
|
|
44581
44644
|
const errorMessage = getParseErrorMessage(error62);
|
|
@@ -44813,7 +44876,7 @@ var McpServer = class {
|
|
|
44813
44876
|
}
|
|
44814
44877
|
if (prompt.argsSchema) {
|
|
44815
44878
|
const argsObj = normalizeObjectSchema(prompt.argsSchema);
|
|
44816
|
-
const parseResult = await safeParseAsync2(argsObj, request.params.arguments);
|
|
44879
|
+
const parseResult = await safeParseAsync2(argsObj, request.params.arguments ?? {});
|
|
44817
44880
|
if (!parseResult.success) {
|
|
44818
44881
|
const error62 = "error" in parseResult ? parseResult.error : "Unknown error";
|
|
44819
44882
|
const errorMessage = getParseErrorMessage(error62);
|
|
@@ -45355,6 +45418,8 @@ var SysMLElementKind = /* @__PURE__ */ ((SysMLElementKind2) => {
|
|
|
45355
45418
|
SysMLElementKind2["TransitionUsage"] = "transition";
|
|
45356
45419
|
SysMLElementKind2["RequirementDef"] = "requirement def";
|
|
45357
45420
|
SysMLElementKind2["RequirementUsage"] = "requirement";
|
|
45421
|
+
SysMLElementKind2["ConcernDef"] = "concern def";
|
|
45422
|
+
SysMLElementKind2["ConcernUsage"] = "concern";
|
|
45358
45423
|
SysMLElementKind2["ConstraintDef"] = "constraint def";
|
|
45359
45424
|
SysMLElementKind2["ConstraintUsage"] = "constraint";
|
|
45360
45425
|
SysMLElementKind2["ItemDef"] = "item def";
|
|
@@ -45466,6 +45531,10 @@ function toMetaclassName(kind) {
|
|
|
45466
45531
|
return "RequirementDefinition";
|
|
45467
45532
|
case "requirement" /* RequirementUsage */:
|
|
45468
45533
|
return "RequirementUsage";
|
|
45534
|
+
case "concern def" /* ConcernDef */:
|
|
45535
|
+
return "ConcernDefinition";
|
|
45536
|
+
case "concern" /* ConcernUsage */:
|
|
45537
|
+
return "ConcernUsage";
|
|
45469
45538
|
case "constraint def" /* ConstraintDef */:
|
|
45470
45539
|
return "ConstraintDefinition";
|
|
45471
45540
|
case "constraint" /* ConstraintUsage */:
|
|
@@ -158884,6 +158953,10 @@ function getLibraryPackageNames() {
|
|
|
158884
158953
|
function canonicalUri(uri) {
|
|
158885
158954
|
return uri.replace(/^file:\/\/\/([A-Za-z])(?::|%3[Aa])(?=\/|$)/, (_m, drive) => `file:///${drive.toLowerCase()}:`);
|
|
158886
158955
|
}
|
|
158956
|
+
function isInFolder(uri, folderUri) {
|
|
158957
|
+
const folder = canonicalUri(folderUri);
|
|
158958
|
+
return canonicalUri(uri).startsWith(folder.endsWith("/") ? folder : `${folder}/`);
|
|
158959
|
+
}
|
|
158887
158960
|
function isSameDocumentUri(a, b) {
|
|
158888
158961
|
return a === b || canonicalUri(a) === canonicalUri(b);
|
|
158889
158962
|
}
|
|
@@ -159474,6 +159547,7 @@ var NAMESPACE_URL = v5_default.URL;
|
|
|
159474
159547
|
var DEFAULT_URL_PREFIX = "https://github.com/daltskin/sysml-v2-lsp/";
|
|
159475
159548
|
var PROJECT_ID_ENV_VAR = "SYSML_PROJECT_ID";
|
|
159476
159549
|
var urlPrefix = DEFAULT_URL_PREFIX;
|
|
159550
|
+
var folderPrefixes = [];
|
|
159477
159551
|
function setProjectId(projectId2) {
|
|
159478
159552
|
if (projectId2 === void 0) {
|
|
159479
159553
|
urlPrefix = DEFAULT_URL_PREFIX;
|
|
@@ -159483,8 +159557,9 @@ function setProjectId(projectId2) {
|
|
|
159483
159557
|
urlPrefix = `urn:uuid:${projectId2.toLowerCase()}/`;
|
|
159484
159558
|
return true;
|
|
159485
159559
|
}
|
|
159486
|
-
function getUrlPrefix() {
|
|
159487
|
-
|
|
159560
|
+
function getUrlPrefix(uri) {
|
|
159561
|
+
const match = uri === void 0 ? void 0 : folderPrefixes.find((f) => isInFolder(uri, f.folderUri));
|
|
159562
|
+
return match?.prefix ?? urlPrefix;
|
|
159488
159563
|
}
|
|
159489
159564
|
function uuidV5(namespace, name) {
|
|
159490
159565
|
return v5_default(name, namespace);
|
|
@@ -159544,7 +159619,7 @@ var IdRegistry = class {
|
|
|
159544
159619
|
declaration.parentId = owner?.symbolId;
|
|
159545
159620
|
const path = declaration.qualifiedName !== void 0 ? this.qualifiedNameAsWritten(declaration) : owner ? `${this.paths.get(owner)}/${segmentOf(declaration)}` : segmentOf(declaration);
|
|
159546
159621
|
const namespace = owner ? this.topLevelOf(owner).symbolId : NAMESPACE_URL;
|
|
159547
|
-
const key = owner ? path : getUrlPrefix() + encodeURIComponent(path);
|
|
159622
|
+
const key = owner ? path : getUrlPrefix(declaration.uri) + encodeURIComponent(path);
|
|
159548
159623
|
const groupId = this.uuidOf(namespace, key);
|
|
159549
159624
|
this.groupKeys.set(groupId, { namespace, key, path });
|
|
159550
159625
|
this.groupOf.set(declaration, groupId);
|
|
@@ -159729,6 +159804,12 @@ var RULE_INDEX_TO_KIND = /* @__PURE__ */ new Map([
|
|
|
159729
159804
|
// 343
|
|
159730
159805
|
[SysMLv2Parser.RULE_requirementDefinition, "requirement def" /* RequirementDef */],
|
|
159731
159806
|
// 384
|
|
159807
|
+
[SysMLv2Parser.RULE_concernDefinition, "concern def" /* ConcernDef */],
|
|
159808
|
+
// 405
|
|
159809
|
+
[SysMLv2Parser.RULE_concernUsage, "concern" /* ConcernUsage */],
|
|
159810
|
+
// 406
|
|
159811
|
+
[SysMLv2Parser.RULE_framedConcernUsage, "concern" /* ConcernUsage */],
|
|
159812
|
+
// 394
|
|
159732
159813
|
[SysMLv2Parser.RULE_constraintDefinition, "constraint def" /* ConstraintDef */],
|
|
159733
159814
|
// 380
|
|
159734
159815
|
[SysMLv2Parser.RULE_itemDefinition, "item def" /* ItemDef */],
|
|
@@ -159801,6 +159882,10 @@ var RULE_INDEX_TO_KIND = /* @__PURE__ */ new Map([
|
|
|
159801
159882
|
// 268
|
|
159802
159883
|
[SysMLv2Parser.RULE_performActionUsage, "perform action" /* PerformActionUsage */],
|
|
159803
159884
|
// 298
|
|
159885
|
+
// A state's `entry`/`do`/`exit` action (`exit action a : A;`, `exit a;`): the
|
|
159886
|
+
// StatePerformActionUsage production, a PerformActionUsage without `perform`.
|
|
159887
|
+
[SysMLv2Parser.RULE_statePerformActionUsage, "perform action" /* PerformActionUsage */],
|
|
159888
|
+
// 352
|
|
159804
159889
|
[SysMLv2Parser.RULE_exhibitStateUsage, "exhibit state" /* ExhibitStateUsage */],
|
|
159805
159890
|
// 359
|
|
159806
159891
|
[SysMLv2Parser.RULE_transitionUsage, "transition" /* TransitionUsage */],
|
|
@@ -159924,8 +160009,10 @@ var TYPE_RECURSE_RULE_INDICES = /* @__PURE__ */ new Set([
|
|
|
159924
160009
|
// 210
|
|
159925
160010
|
SysMLv2Parser.RULE_definition,
|
|
159926
160011
|
// 192
|
|
159927
|
-
SysMLv2Parser.RULE_usage
|
|
160012
|
+
SysMLv2Parser.RULE_usage,
|
|
159928
160013
|
// 208
|
|
160014
|
+
SysMLv2Parser.RULE_payloadFeatureSpecializationPart
|
|
160015
|
+
// 157
|
|
159929
160016
|
]);
|
|
159930
160017
|
var DOC_RULE_INDICES = /* @__PURE__ */ new Set([
|
|
159931
160018
|
SysMLv2Parser.RULE_comment,
|
|
@@ -160550,7 +160637,7 @@ var SymbolTable = class {
|
|
|
160550
160637
|
const shortName = transition || isFlowUsage(kind) && !declaredName ? void 0 : this.extractShortName(ctx2);
|
|
160551
160638
|
const qualifiedName = anonymous || owner && owner.qualifiedName === void 0 ? void 0 : owner ? `${owner.qualifiedName}::${name}` : name;
|
|
160552
160639
|
const selectionRange = anonymous ? ctx2.start ? tokenToRange(ctx2.start) : range : this.extractNameRange(ctx2) ?? range;
|
|
160553
|
-
const typeNames = isFlowUsage(kind) ? this.extractFlowTypeNames(ctx2) : this.extractTypeNames(ctx2);
|
|
160640
|
+
const typeNames = isFlowUsage(kind) ? this.extractFlowTypeNames(ctx2) : transition ? this.extractTransitionTypeNames(ctx2) : this.extractTypeNames(ctx2);
|
|
160554
160641
|
const specializationNames = this.extractSpecializationNames(ctx2);
|
|
160555
160642
|
const typeName = typeNames[0];
|
|
160556
160643
|
const documentation = this.extractDocumentation(ctx2);
|
|
@@ -160665,6 +160752,25 @@ var SymbolTable = class {
|
|
|
160665
160752
|
const typeDeclaration = declaration && (this.findOwnHeaderRule(declaration, SysMLv2Parser.RULE_featureDeclaration) ?? this.findOwnHeaderRule(declaration, SysMLv2Parser.RULE_usageDeclaration));
|
|
160666
160753
|
return typeDeclaration ? this.extractTypeNames(typeDeclaration) : [];
|
|
160667
160754
|
}
|
|
160755
|
+
/**
|
|
160756
|
+
* A transition's own typing, then the types of the payload its trigger
|
|
160757
|
+
* accepts (`accept cmd : Command`, `accept Command`; TriggerAction ->
|
|
160758
|
+
* AcceptParameterPart -> PayloadParameter). Read from the parse tree only:
|
|
160759
|
+
* the regex fallback of `extractTypeNames` runs on whitespace-free text, where
|
|
160760
|
+
* the payload type runs into the guard, effect or target that follows it
|
|
160761
|
+
* (`Commandifcmd`, `Commandthenbusy`).
|
|
160762
|
+
*/
|
|
160763
|
+
extractTransitionTypeNames(ctx2) {
|
|
160764
|
+
const names = [];
|
|
160765
|
+
this.collectTypeNamesFromTree(ctx2, names, 0);
|
|
160766
|
+
const trigger = this.findOwnHeaderRule(ctx2, SysMLv2Parser.RULE_triggerActionMember);
|
|
160767
|
+
const parameter = trigger && this.findRuleContext(trigger, SysMLv2Parser.RULE_payloadParameter);
|
|
160768
|
+
if (parameter) {
|
|
160769
|
+
const payload = this.findRuleContext(parameter, SysMLv2Parser.RULE_payloadFeature) ?? parameter;
|
|
160770
|
+
this.collectTypeNamesFromTree(payload, names, 0);
|
|
160771
|
+
}
|
|
160772
|
+
return names;
|
|
160773
|
+
}
|
|
160668
160774
|
/** Find the first descendant of `ctx` with rule `ruleIndex`, in source order. */
|
|
160669
160775
|
findRuleContext(ctx2, ruleIndex) {
|
|
160670
160776
|
const matches = [];
|
|
@@ -160790,7 +160896,7 @@ var SymbolTable = class {
|
|
|
160790
160896
|
*/
|
|
160791
160897
|
anonymousDeclaration(ctx2, kind, transition) {
|
|
160792
160898
|
if (!isDefinition(kind) && !isUsage(kind)) return void 0;
|
|
160793
|
-
if (transition && !(transition.source && transition.target) && this.
|
|
160899
|
+
if (transition && !(transition.source && transition.target) && this.extractTransitionTypeNames(ctx2).length === 0) return void 0;
|
|
160794
160900
|
return this.declarationText(ctx2);
|
|
160795
160901
|
}
|
|
160796
160902
|
/**
|
package/dist/server/server.js
CHANGED
|
@@ -121638,6 +121638,10 @@ var SYSML_KEYWORDS = new Set(SYSML_KEYWORDS_ARRAY);
|
|
|
121638
121638
|
function canonicalUri(uri) {
|
|
121639
121639
|
return uri.replace(/^file:\/\/\/([A-Za-z])(?::|%3[Aa])(?=\/|$)/, (_m, drive) => `file:///${drive.toLowerCase()}:`);
|
|
121640
121640
|
}
|
|
121641
|
+
function isInFolder(uri, folderUri) {
|
|
121642
|
+
const folder = canonicalUri(folderUri);
|
|
121643
|
+
return canonicalUri(uri).startsWith(folder.endsWith("/") ? folder : `${folder}/`);
|
|
121644
|
+
}
|
|
121641
121645
|
function isSameDocumentUri(a, b) {
|
|
121642
121646
|
return a === b || canonicalUri(a) === canonicalUri(b);
|
|
121643
121647
|
}
|
|
@@ -121740,6 +121744,7 @@ var v5_default = v5;
|
|
|
121740
121744
|
var NAMESPACE_URL = v5_default.URL;
|
|
121741
121745
|
var DEFAULT_URL_PREFIX = "https://github.com/daltskin/sysml-v2-lsp/";
|
|
121742
121746
|
var urlPrefix = DEFAULT_URL_PREFIX;
|
|
121747
|
+
var folderPrefixes = [];
|
|
121743
121748
|
function setProjectId(projectId) {
|
|
121744
121749
|
if (projectId === void 0) {
|
|
121745
121750
|
urlPrefix = DEFAULT_URL_PREFIX;
|
|
@@ -121749,8 +121754,14 @@ function setProjectId(projectId) {
|
|
|
121749
121754
|
urlPrefix = `urn:uuid:${projectId.toLowerCase()}/`;
|
|
121750
121755
|
return true;
|
|
121751
121756
|
}
|
|
121752
|
-
function
|
|
121753
|
-
|
|
121757
|
+
function setFolderProjectIds(projectIds) {
|
|
121758
|
+
const rejected = projectIds.filter((p) => !validate_default(p.projectId));
|
|
121759
|
+
folderPrefixes = projectIds.filter((p) => validate_default(p.projectId)).map((p) => ({ folderUri: p.folderUri, prefix: `urn:uuid:${p.projectId.toLowerCase()}/` })).sort((a, b) => b.folderUri.length - a.folderUri.length);
|
|
121760
|
+
return rejected;
|
|
121761
|
+
}
|
|
121762
|
+
function getUrlPrefix(uri) {
|
|
121763
|
+
const match = uri === void 0 ? void 0 : folderPrefixes.find((f) => isInFolder(uri, f.folderUri));
|
|
121764
|
+
return match?.prefix ?? urlPrefix;
|
|
121754
121765
|
}
|
|
121755
121766
|
function uuidV5(namespace, name) {
|
|
121756
121767
|
return v5_default(name, namespace);
|
|
@@ -121832,6 +121843,10 @@ function toMetaclassName(kind) {
|
|
|
121832
121843
|
return "RequirementDefinition";
|
|
121833
121844
|
case "requirement" /* RequirementUsage */:
|
|
121834
121845
|
return "RequirementUsage";
|
|
121846
|
+
case "concern def" /* ConcernDef */:
|
|
121847
|
+
return "ConcernDefinition";
|
|
121848
|
+
case "concern" /* ConcernUsage */:
|
|
121849
|
+
return "ConcernUsage";
|
|
121835
121850
|
case "constraint def" /* ConstraintDef */:
|
|
121836
121851
|
return "ConstraintDefinition";
|
|
121837
121852
|
case "constraint" /* ConstraintUsage */:
|
|
@@ -121954,7 +121969,7 @@ var IdRegistry = class {
|
|
|
121954
121969
|
declaration.parentId = owner?.symbolId;
|
|
121955
121970
|
const path3 = declaration.qualifiedName !== void 0 ? this.qualifiedNameAsWritten(declaration) : owner ? `${this.paths.get(owner)}/${segmentOf(declaration)}` : segmentOf(declaration);
|
|
121956
121971
|
const namespace = owner ? this.topLevelOf(owner).symbolId : NAMESPACE_URL;
|
|
121957
|
-
const key = owner ? path3 : getUrlPrefix() + encodeURIComponent(path3);
|
|
121972
|
+
const key = owner ? path3 : getUrlPrefix(declaration.uri) + encodeURIComponent(path3);
|
|
121958
121973
|
const groupId = this.uuidOf(namespace, key);
|
|
121959
121974
|
this.groupKeys.set(groupId, { namespace, key, path: path3 });
|
|
121960
121975
|
this.groupOf.set(declaration, groupId);
|
|
@@ -122139,6 +122154,12 @@ var RULE_INDEX_TO_KIND = /* @__PURE__ */ new Map([
|
|
|
122139
122154
|
// 343
|
|
122140
122155
|
[SysMLv2Parser.RULE_requirementDefinition, "requirement def" /* RequirementDef */],
|
|
122141
122156
|
// 384
|
|
122157
|
+
[SysMLv2Parser.RULE_concernDefinition, "concern def" /* ConcernDef */],
|
|
122158
|
+
// 405
|
|
122159
|
+
[SysMLv2Parser.RULE_concernUsage, "concern" /* ConcernUsage */],
|
|
122160
|
+
// 406
|
|
122161
|
+
[SysMLv2Parser.RULE_framedConcernUsage, "concern" /* ConcernUsage */],
|
|
122162
|
+
// 394
|
|
122142
122163
|
[SysMLv2Parser.RULE_constraintDefinition, "constraint def" /* ConstraintDef */],
|
|
122143
122164
|
// 380
|
|
122144
122165
|
[SysMLv2Parser.RULE_itemDefinition, "item def" /* ItemDef */],
|
|
@@ -122211,6 +122232,10 @@ var RULE_INDEX_TO_KIND = /* @__PURE__ */ new Map([
|
|
|
122211
122232
|
// 268
|
|
122212
122233
|
[SysMLv2Parser.RULE_performActionUsage, "perform action" /* PerformActionUsage */],
|
|
122213
122234
|
// 298
|
|
122235
|
+
// A state's `entry`/`do`/`exit` action (`exit action a : A;`, `exit a;`): the
|
|
122236
|
+
// StatePerformActionUsage production, a PerformActionUsage without `perform`.
|
|
122237
|
+
[SysMLv2Parser.RULE_statePerformActionUsage, "perform action" /* PerformActionUsage */],
|
|
122238
|
+
// 352
|
|
122214
122239
|
[SysMLv2Parser.RULE_exhibitStateUsage, "exhibit state" /* ExhibitStateUsage */],
|
|
122215
122240
|
// 359
|
|
122216
122241
|
[SysMLv2Parser.RULE_transitionUsage, "transition" /* TransitionUsage */],
|
|
@@ -122334,8 +122359,10 @@ var TYPE_RECURSE_RULE_INDICES = /* @__PURE__ */ new Set([
|
|
|
122334
122359
|
// 210
|
|
122335
122360
|
SysMLv2Parser.RULE_definition,
|
|
122336
122361
|
// 192
|
|
122337
|
-
SysMLv2Parser.RULE_usage
|
|
122362
|
+
SysMLv2Parser.RULE_usage,
|
|
122338
122363
|
// 208
|
|
122364
|
+
SysMLv2Parser.RULE_payloadFeatureSpecializationPart
|
|
122365
|
+
// 157
|
|
122339
122366
|
]);
|
|
122340
122367
|
var DOC_RULE_INDICES = /* @__PURE__ */ new Set([
|
|
122341
122368
|
SysMLv2Parser.RULE_comment,
|
|
@@ -122960,7 +122987,7 @@ var SymbolTable = class {
|
|
|
122960
122987
|
const shortName = transition || isFlowUsage(kind) && !declaredName ? void 0 : this.extractShortName(ctx);
|
|
122961
122988
|
const qualifiedName = anonymous || owner && owner.qualifiedName === void 0 ? void 0 : owner ? `${owner.qualifiedName}::${name}` : name;
|
|
122962
122989
|
const selectionRange = anonymous ? ctx.start ? tokenToRange(ctx.start) : range : this.extractNameRange(ctx) ?? range;
|
|
122963
|
-
const typeNames = isFlowUsage(kind) ? this.extractFlowTypeNames(ctx) : this.extractTypeNames(ctx);
|
|
122990
|
+
const typeNames = isFlowUsage(kind) ? this.extractFlowTypeNames(ctx) : transition ? this.extractTransitionTypeNames(ctx) : this.extractTypeNames(ctx);
|
|
122964
122991
|
const specializationNames = this.extractSpecializationNames(ctx);
|
|
122965
122992
|
const typeName = typeNames[0];
|
|
122966
122993
|
const documentation = this.extractDocumentation(ctx);
|
|
@@ -123075,6 +123102,25 @@ var SymbolTable = class {
|
|
|
123075
123102
|
const typeDeclaration = declaration && (this.findOwnHeaderRule(declaration, SysMLv2Parser.RULE_featureDeclaration) ?? this.findOwnHeaderRule(declaration, SysMLv2Parser.RULE_usageDeclaration));
|
|
123076
123103
|
return typeDeclaration ? this.extractTypeNames(typeDeclaration) : [];
|
|
123077
123104
|
}
|
|
123105
|
+
/**
|
|
123106
|
+
* A transition's own typing, then the types of the payload its trigger
|
|
123107
|
+
* accepts (`accept cmd : Command`, `accept Command`; TriggerAction ->
|
|
123108
|
+
* AcceptParameterPart -> PayloadParameter). Read from the parse tree only:
|
|
123109
|
+
* the regex fallback of `extractTypeNames` runs on whitespace-free text, where
|
|
123110
|
+
* the payload type runs into the guard, effect or target that follows it
|
|
123111
|
+
* (`Commandifcmd`, `Commandthenbusy`).
|
|
123112
|
+
*/
|
|
123113
|
+
extractTransitionTypeNames(ctx) {
|
|
123114
|
+
const names = [];
|
|
123115
|
+
this.collectTypeNamesFromTree(ctx, names, 0);
|
|
123116
|
+
const trigger = this.findOwnHeaderRule(ctx, SysMLv2Parser.RULE_triggerActionMember);
|
|
123117
|
+
const parameter = trigger && this.findRuleContext(trigger, SysMLv2Parser.RULE_payloadParameter);
|
|
123118
|
+
if (parameter) {
|
|
123119
|
+
const payload = this.findRuleContext(parameter, SysMLv2Parser.RULE_payloadFeature) ?? parameter;
|
|
123120
|
+
this.collectTypeNamesFromTree(payload, names, 0);
|
|
123121
|
+
}
|
|
123122
|
+
return names;
|
|
123123
|
+
}
|
|
123078
123124
|
/** Find the first descendant of `ctx` with rule `ruleIndex`, in source order. */
|
|
123079
123125
|
findRuleContext(ctx, ruleIndex) {
|
|
123080
123126
|
const matches = [];
|
|
@@ -123200,7 +123246,7 @@ var SymbolTable = class {
|
|
|
123200
123246
|
*/
|
|
123201
123247
|
anonymousDeclaration(ctx, kind, transition) {
|
|
123202
123248
|
if (!isDefinition(kind) && !isUsage(kind)) return void 0;
|
|
123203
|
-
if (transition && !(transition.source && transition.target) && this.
|
|
123249
|
+
if (transition && !(transition.source && transition.target) && this.extractTransitionTypeNames(ctx).length === 0) return void 0;
|
|
123204
123250
|
return this.declarationText(ctx);
|
|
123205
123251
|
}
|
|
123206
123252
|
/**
|
|
@@ -124280,6 +124326,17 @@ var DocumentManager = class {
|
|
|
124280
124326
|
}
|
|
124281
124327
|
return this.wsSymbolTable;
|
|
124282
124328
|
}
|
|
124329
|
+
/**
|
|
124330
|
+
* Rebuild the symbol tables of `uris` on next use, e.g. after their projectId
|
|
124331
|
+
* changed, which changes their symbol IDs (see `setFolderProjectIds`).
|
|
124332
|
+
*/
|
|
124333
|
+
invalidateSymbols(uris) {
|
|
124334
|
+
for (const uri of uris) {
|
|
124335
|
+
const cached = this.cache.get(uri);
|
|
124336
|
+
if (cached) cached.symbolTable = void 0;
|
|
124337
|
+
this.wsBuiltVersions.delete(uri);
|
|
124338
|
+
}
|
|
124339
|
+
}
|
|
124283
124340
|
/**
|
|
124284
124341
|
* Cache semantic diagnostics for the current document version.
|
|
124285
124342
|
*/
|
|
@@ -128273,6 +128330,8 @@ function toSysMLSymbolKind(kind) {
|
|
|
128273
128330
|
// Requirements → Object
|
|
128274
128331
|
case "requirement def" /* RequirementDef */:
|
|
128275
128332
|
case "requirement" /* RequirementUsage */:
|
|
128333
|
+
case "concern def" /* ConcernDef */:
|
|
128334
|
+
case "concern" /* ConcernUsage */:
|
|
128276
128335
|
case "actor" /* ActorUsage */:
|
|
128277
128336
|
case "subject" /* SubjectUsage */:
|
|
128278
128337
|
case "stakeholder" /* StakeholderUsage */:
|
|
@@ -130666,6 +130725,10 @@ hoverProvider.setSemanticValidator(semanticValidator);
|
|
|
130666
130725
|
var hasConfigurationCapability = false;
|
|
130667
130726
|
var hasWorkspaceFolderCapability = false;
|
|
130668
130727
|
var workspaceRoots = [];
|
|
130728
|
+
var workspaceFolderUris = [];
|
|
130729
|
+
function rootsOf(folderUris) {
|
|
130730
|
+
return folderUris.map((uri) => toFsPath(uri)).filter((p) => p !== void 0);
|
|
130731
|
+
}
|
|
130669
130732
|
var isWorkspaceFile = false;
|
|
130670
130733
|
var preloadOnOpen = "workspaceOnly";
|
|
130671
130734
|
var disabledDiagnosticCodes = /* @__PURE__ */ new Set();
|
|
@@ -130677,6 +130740,10 @@ function publishDiagnostics(uri, diagnostics) {
|
|
|
130677
130740
|
}
|
|
130678
130741
|
var skipDirs = new Set(DEFAULT_SKIP_DIRS);
|
|
130679
130742
|
var serverReady = false;
|
|
130743
|
+
var resolveInitialization;
|
|
130744
|
+
var initialization = new Promise((resolve2) => {
|
|
130745
|
+
resolveInitialization = resolve2;
|
|
130746
|
+
});
|
|
130680
130747
|
var earlyOpenUris = /* @__PURE__ */ new Set();
|
|
130681
130748
|
var workerRequestId = 0;
|
|
130682
130749
|
var isBrowserServer = typeof __SYSML_BROWSER_SERVER__ !== "undefined" && __SYSML_BROWSER_SERVER__;
|
|
@@ -130790,7 +130857,8 @@ connection.onInitialize((params) => {
|
|
|
130790
130857
|
connection.console.warn(`projectId is not a UUID: ${initOpts.projectId}; symbol IDs are unique only within this workspace`);
|
|
130791
130858
|
}
|
|
130792
130859
|
if (params.workspaceFolders) {
|
|
130793
|
-
|
|
130860
|
+
workspaceFolderUris = params.workspaceFolders.map((f) => f.uri);
|
|
130861
|
+
workspaceRoots = rootsOf(workspaceFolderUris);
|
|
130794
130862
|
} else if (params.rootUri) {
|
|
130795
130863
|
const root = toFsPath(params.rootUri);
|
|
130796
130864
|
if (root) workspaceRoots = [root];
|
|
@@ -130840,7 +130908,8 @@ connection.onInitialize((params) => {
|
|
|
130840
130908
|
if (hasWorkspaceFolderCapability) {
|
|
130841
130909
|
result.capabilities.workspace = {
|
|
130842
130910
|
workspaceFolders: {
|
|
130843
|
-
supported: true
|
|
130911
|
+
supported: true,
|
|
130912
|
+
changeNotifications: true
|
|
130844
130913
|
}
|
|
130845
130914
|
};
|
|
130846
130915
|
}
|
|
@@ -130852,8 +130921,17 @@ connection.onInitialized(async () => {
|
|
|
130852
130921
|
import_node12.DidChangeConfigurationNotification.type,
|
|
130853
130922
|
void 0
|
|
130854
130923
|
);
|
|
130924
|
+
}
|
|
130925
|
+
if (hasWorkspaceFolderCapability) {
|
|
130926
|
+
connection.workspace.onDidChangeWorkspaceFolders((event) => {
|
|
130927
|
+
onWorkspaceFoldersChanged(event).catch((e) => connection.console.error(`Workspace folder change failed: ${e}`));
|
|
130928
|
+
});
|
|
130929
|
+
}
|
|
130930
|
+
if (hasConfigurationCapability) {
|
|
130855
130931
|
await pullSettings().catch(() => {
|
|
130856
130932
|
});
|
|
130933
|
+
await pullFolderProjectIds().catch(() => {
|
|
130934
|
+
});
|
|
130857
130935
|
}
|
|
130858
130936
|
const libCount = initLibraryIndex(__dirname);
|
|
130859
130937
|
connection.console.log(`SysML v2 Language Server initialized (${libCount} library packages indexed)`);
|
|
@@ -130869,14 +130947,13 @@ connection.onInitialized(async () => {
|
|
|
130869
130947
|
);
|
|
130870
130948
|
}
|
|
130871
130949
|
serverReady = true;
|
|
130950
|
+
resolveInitialization();
|
|
130872
130951
|
spawnParseWorker();
|
|
130873
130952
|
if (workspaceRoots.length > 0 && (preloadOnOpen === "always" || preloadOnOpen === "workspaceOnly" && isWorkspaceFile)) {
|
|
130874
|
-
|
|
130875
|
-
scanWorkspaceFoldersAsync(workspaceRoots).then(({ fileCount, scanMs }) => {
|
|
130953
|
+
scanWorkspaceFolders(workspaceRoots).then(({ fileCount, scanMs }) => {
|
|
130876
130954
|
connection.console.log(
|
|
130877
130955
|
`Workspace scan: pre-parsed ${fileCount} .sysml files in ${scanMs} ms`
|
|
130878
130956
|
);
|
|
130879
|
-
documentManager.setWorkspaceScanComplete(true);
|
|
130880
130957
|
revalidateOpenDocuments();
|
|
130881
130958
|
});
|
|
130882
130959
|
}
|
|
@@ -130911,9 +130988,79 @@ function applySettings(config) {
|
|
|
130911
130988
|
}
|
|
130912
130989
|
}
|
|
130913
130990
|
connection.onDidChangeConfiguration((_change) => {
|
|
130914
|
-
pullSettings().then(() => revalidateOpenDocuments()).catch(() => {
|
|
130991
|
+
pullSettings().then(() => pullFolderProjectIds()).then(() => revalidateOpenDocuments()).catch(() => {
|
|
130915
130992
|
});
|
|
130916
130993
|
});
|
|
130994
|
+
function latestWins(task) {
|
|
130995
|
+
let calls = 0;
|
|
130996
|
+
let latest = Promise.resolve();
|
|
130997
|
+
return () => {
|
|
130998
|
+
const call = ++calls;
|
|
130999
|
+
const isSuperseded = () => call !== calls;
|
|
131000
|
+
const run = task(isSuperseded).then(() => isSuperseded() ? latest : void 0);
|
|
131001
|
+
latest = run;
|
|
131002
|
+
return run;
|
|
131003
|
+
};
|
|
131004
|
+
}
|
|
131005
|
+
var pullFolderProjectIds = latestWins(async (isSuperseded) => {
|
|
131006
|
+
if (!hasConfigurationCapability) return;
|
|
131007
|
+
const folderUris = [...workspaceFolderUris];
|
|
131008
|
+
const answers = folderUris.length === 0 ? [] : await connection.workspace.getConfiguration(folderUris.map((scopeUri) => ({ scopeUri, section: "sysml.project" })));
|
|
131009
|
+
if (isSuperseded()) return;
|
|
131010
|
+
const projectIds = folderUris.flatMap((folderUri, i) => {
|
|
131011
|
+
const projectId = answers[i]?.projectId;
|
|
131012
|
+
return typeof projectId === "string" ? [{ folderUri, projectId }] : [];
|
|
131013
|
+
});
|
|
131014
|
+
const uris = documentManager.getUris();
|
|
131015
|
+
const prefixBefore = new Map(uris.map((uri) => [uri, getUrlPrefix(uri)]));
|
|
131016
|
+
const rejected = setFolderProjectIds(projectIds);
|
|
131017
|
+
for (const entry of rejected) {
|
|
131018
|
+
connection.console.warn(`projectId of ${entry.folderUri} is not a UUID: ${entry.projectId}; ignored, so its documents use the projectId of an enclosing folder, else initializationOptions.projectId, else the default prefix`);
|
|
131019
|
+
}
|
|
131020
|
+
documentManager.invalidateSymbols(uris.filter((uri) => getUrlPrefix(uri) !== prefixBefore.get(uri)));
|
|
131021
|
+
logFolderPrefixes(new Set(projectIds.filter((p) => !rejected.includes(p)).map((p) => p.folderUri)));
|
|
131022
|
+
});
|
|
131023
|
+
var loggedFolderPrefixes = /* @__PURE__ */ new Map();
|
|
131024
|
+
function logFolderPrefixes(ownProjectIds) {
|
|
131025
|
+
for (const folderUri of workspaceFolderUris) {
|
|
131026
|
+
const prefix = getUrlPrefix(`${folderUri.endsWith("/") ? folderUri : `${folderUri}/`}_.sysml`);
|
|
131027
|
+
if (loggedFolderPrefixes.get(folderUri) === prefix) continue;
|
|
131028
|
+
loggedFolderPrefixes.set(folderUri, prefix);
|
|
131029
|
+
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";
|
|
131030
|
+
connection.console.info(`Folder ${folderUri}: top-level elements' URLs start with ${prefix} (${source})`);
|
|
131031
|
+
}
|
|
131032
|
+
for (const folderUri of loggedFolderPrefixes.keys()) {
|
|
131033
|
+
if (!workspaceFolderUris.includes(folderUri)) loggedFolderPrefixes.delete(folderUri);
|
|
131034
|
+
}
|
|
131035
|
+
}
|
|
131036
|
+
async function onWorkspaceFoldersChanged(event) {
|
|
131037
|
+
const initialScanPending = !serverReady;
|
|
131038
|
+
const removed = new Set(event.removed.map((f) => f.uri));
|
|
131039
|
+
workspaceFolderUris = [...workspaceFolderUris.filter((uri) => !removed.has(uri)), ...event.added.map((f) => f.uri)];
|
|
131040
|
+
workspaceRoots = rootsOf(workspaceFolderUris);
|
|
131041
|
+
dropDocumentsOutsideWorkspace(event.removed.map((f) => f.uri));
|
|
131042
|
+
await pullFolderProjectIds().catch(() => {
|
|
131043
|
+
});
|
|
131044
|
+
if (initialScanPending) return;
|
|
131045
|
+
const addedRoots = rootsOf(event.added.map((f) => f.uri).filter((uri) => workspaceFolderUris.includes(uri)));
|
|
131046
|
+
if (addedRoots.length > 0 && (preloadOnOpen === "always" || preloadOnOpen === "workspaceOnly" && isWorkspaceFile)) {
|
|
131047
|
+
const { fileCount, scanMs } = await scanWorkspaceFolders(addedRoots);
|
|
131048
|
+
connection.console.log(`Workspace scan: pre-parsed ${fileCount} .sysml files of ${addedRoots.length} added folder(s) in ${scanMs} ms`);
|
|
131049
|
+
}
|
|
131050
|
+
revalidateOpenDocuments();
|
|
131051
|
+
}
|
|
131052
|
+
function dropDocumentsOutsideWorkspace(folderUris) {
|
|
131053
|
+
for (const uri of documentManager.getUris()) {
|
|
131054
|
+
if (openDocumentFor(uri)) continue;
|
|
131055
|
+
if (folderUris.some((f) => isInFolder(uri, f)) && !isInWorkspace(uri)) {
|
|
131056
|
+
documentManager.remove(uri);
|
|
131057
|
+
modelProvider.removeUri(uri);
|
|
131058
|
+
}
|
|
131059
|
+
}
|
|
131060
|
+
}
|
|
131061
|
+
function isInWorkspace(uri) {
|
|
131062
|
+
return workspaceRoots.some((root) => isInFolder(uri, (0, import_node_url2.pathToFileURL)(root).toString()));
|
|
131063
|
+
}
|
|
130917
131064
|
function openDocumentFor(uri) {
|
|
130918
131065
|
return documents.get(uri) ?? documents.all().find((d) => isSameDocumentUri(d.uri, uri));
|
|
130919
131066
|
}
|
|
@@ -130938,6 +131085,16 @@ function parseWorkspaceFile(filePath, uri = (0, import_node_url2.pathToFileURL)(
|
|
|
130938
131085
|
documentManager.parse(doc);
|
|
130939
131086
|
return true;
|
|
130940
131087
|
}
|
|
131088
|
+
var runningScans = 0;
|
|
131089
|
+
async function scanWorkspaceFolders(roots) {
|
|
131090
|
+
runningScans++;
|
|
131091
|
+
documentManager.setWorkspaceScanComplete(false);
|
|
131092
|
+
try {
|
|
131093
|
+
return await scanWorkspaceFoldersAsync(roots);
|
|
131094
|
+
} finally {
|
|
131095
|
+
if (--runningScans === 0) documentManager.setWorkspaceScanComplete(true);
|
|
131096
|
+
}
|
|
131097
|
+
}
|
|
130941
131098
|
async function scanWorkspaceFoldersAsync(roots) {
|
|
130942
131099
|
const scanT0 = Date.now();
|
|
130943
131100
|
const fileArrays = await Promise.all(roots.map((r) => findSysMLFilesAsync(r, skipDirs)));
|
|
@@ -130949,6 +131106,7 @@ async function scanWorkspaceFoldersAsync(roots) {
|
|
|
130949
131106
|
const filePath = allFiles[i];
|
|
130950
131107
|
const uri = (0, import_node_url2.pathToFileURL)(filePath).toString();
|
|
130951
131108
|
if (openDocumentFor(uri)) continue;
|
|
131109
|
+
if (!isInWorkspace(uri)) continue;
|
|
130952
131110
|
const content = fileContents.get(filePath);
|
|
130953
131111
|
if (content === void 0) continue;
|
|
130954
131112
|
documentManager.parseBatch(uri, 0, content);
|
|
@@ -131161,14 +131319,16 @@ connection.onDocumentRangeFormatting(
|
|
|
131161
131319
|
return formattingProvider.provideRangeFormatting(params);
|
|
131162
131320
|
}
|
|
131163
131321
|
);
|
|
131164
|
-
connection.onRequest("sysml/model", (params) => {
|
|
131322
|
+
connection.onRequest("sysml/model", async (params) => {
|
|
131323
|
+
await initialization;
|
|
131165
131324
|
return modelProvider.getModel(
|
|
131166
131325
|
params.textDocument.uri,
|
|
131167
131326
|
documentManager.getVersion(params.textDocument.uri),
|
|
131168
131327
|
params.scope
|
|
131169
131328
|
);
|
|
131170
131329
|
});
|
|
131171
|
-
connection.onRequest("sysml/elementLookup", (params) => {
|
|
131330
|
+
connection.onRequest("sysml/elementLookup", async (params) => {
|
|
131331
|
+
await initialization;
|
|
131172
131332
|
return elementLookupProvider.elementLookup(params);
|
|
131173
131333
|
});
|
|
131174
131334
|
connection.onRequest("sysml/serverStats", () => {
|
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.35.0",
|
|
6
6
|
"publisher": "JamieD",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"repository": {
|