sysml-validate 0.24.0 → 0.26.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/out/main.js +774 -24
- package/out/main.js.map +4 -4
- package/package.json +1 -1
- package/resources/sysml.dimension-table.json +1 -1
package/out/main.js
CHANGED
|
@@ -57970,7 +57970,9 @@ var sysmlInlayHintSettings = {
|
|
|
57970
57970
|
modifiers: false,
|
|
57971
57971
|
specialization: false,
|
|
57972
57972
|
redefinition: false,
|
|
57973
|
-
effectiveNames: false
|
|
57973
|
+
effectiveNames: false,
|
|
57974
|
+
importedNames: false,
|
|
57975
|
+
parameterNames: false
|
|
57974
57976
|
};
|
|
57975
57977
|
function asDiagnosticLevel(value, fallback = "off") {
|
|
57976
57978
|
return value === "off" || value === "warning" || value === "error" ? value : fallback;
|
|
@@ -69973,6 +69975,329 @@ var SysmlSemanticTokenProvider = class extends AbstractSemanticTokenProvider {
|
|
|
69973
69975
|
|
|
69974
69976
|
// ../language-server/out/src/services/inlay-hint-provider.js
|
|
69975
69977
|
var import_vscode_languageserver20 = __toESM(require_main4(), 1);
|
|
69978
|
+
|
|
69979
|
+
// ../language-server/out/src/services/name-lookup.js
|
|
69980
|
+
function unquoteName3(name) {
|
|
69981
|
+
return name.replace(/^'(.*)'$/u, "$1");
|
|
69982
|
+
}
|
|
69983
|
+
function pathSegments(path10) {
|
|
69984
|
+
const segments = [];
|
|
69985
|
+
let current2 = "";
|
|
69986
|
+
let quoted = false;
|
|
69987
|
+
for (let index = 0; index < path10.length; index++) {
|
|
69988
|
+
const char = path10[index];
|
|
69989
|
+
if (char === "'") {
|
|
69990
|
+
quoted = !quoted;
|
|
69991
|
+
current2 += char;
|
|
69992
|
+
continue;
|
|
69993
|
+
}
|
|
69994
|
+
if (!quoted && char === ":" && path10[index + 1] === ":") {
|
|
69995
|
+
segments.push(current2);
|
|
69996
|
+
current2 = "";
|
|
69997
|
+
index++;
|
|
69998
|
+
continue;
|
|
69999
|
+
}
|
|
70000
|
+
if (!quoted && char === ".") {
|
|
70001
|
+
segments.push(current2);
|
|
70002
|
+
current2 = "";
|
|
70003
|
+
continue;
|
|
70004
|
+
}
|
|
70005
|
+
current2 += char;
|
|
70006
|
+
}
|
|
70007
|
+
segments.push(current2);
|
|
70008
|
+
return segments;
|
|
70009
|
+
}
|
|
70010
|
+
function simpleNameOf2(name) {
|
|
70011
|
+
return pathSegments(name).at(-1) ?? name;
|
|
70012
|
+
}
|
|
70013
|
+
var ELEMENT_SEPARATOR = "\0";
|
|
70014
|
+
function elementKey2(description) {
|
|
70015
|
+
return `${description.documentUri.toString()}${ELEMENT_SEPARATOR}${description.path}`;
|
|
70016
|
+
}
|
|
70017
|
+
function isDeclaredSpelling(description) {
|
|
70018
|
+
const kind = description.derivedKind;
|
|
70019
|
+
if (kind === "reexport" || kind === "inherited")
|
|
70020
|
+
return false;
|
|
70021
|
+
return pathSegments(description.name).length === 1;
|
|
70022
|
+
}
|
|
70023
|
+
var SysmlNameLookup = class {
|
|
70024
|
+
shared;
|
|
70025
|
+
byName;
|
|
70026
|
+
/** Element key → the declared spellings the index holds for that element. */
|
|
70027
|
+
spellings;
|
|
70028
|
+
constructor(shared) {
|
|
70029
|
+
this.shared = shared;
|
|
70030
|
+
this.shared.workspace.DocumentBuilder.onBuildPhase(DocumentState.IndexedContent, () => {
|
|
70031
|
+
this.byName = void 0;
|
|
70032
|
+
this.spellings = void 0;
|
|
70033
|
+
});
|
|
70034
|
+
}
|
|
70035
|
+
/** Every description indexed under `name`, in either spelling of an escaped name. */
|
|
70036
|
+
descriptions(name) {
|
|
70037
|
+
return this.index().get(name) ?? [];
|
|
70038
|
+
}
|
|
70039
|
+
/**
|
|
70040
|
+
* The ONE element `name` names, or `undefined` when the answer is not
|
|
70041
|
+
* certain: no element, or more than one. `accept` narrows the candidates
|
|
70042
|
+
* before ambiguity is judged, so "the only CALLABLE called `f`" is a
|
|
70043
|
+
* decidable question even where a part shares the name.
|
|
70044
|
+
*/
|
|
70045
|
+
unique(name, accept) {
|
|
70046
|
+
const candidates = this.descriptions(name).filter((candidate) => !accept || accept(candidate));
|
|
70047
|
+
let found;
|
|
70048
|
+
let key;
|
|
70049
|
+
for (const candidate of candidates) {
|
|
70050
|
+
const candidateKey = elementKey2(candidate);
|
|
70051
|
+
if (found === void 0) {
|
|
70052
|
+
found = candidate;
|
|
70053
|
+
key = candidateKey;
|
|
70054
|
+
continue;
|
|
70055
|
+
}
|
|
70056
|
+
if (candidateKey !== key)
|
|
70057
|
+
return void 0;
|
|
70058
|
+
}
|
|
70059
|
+
return found;
|
|
70060
|
+
}
|
|
70061
|
+
/**
|
|
70062
|
+
* Resolve a written path: the spelling the index holds verbatim first, then
|
|
70063
|
+
* its final segment. Both readings must name exactly one element.
|
|
70064
|
+
*/
|
|
70065
|
+
uniqueForPath(path10, accept) {
|
|
70066
|
+
return this.unique(path10, accept) ?? this.unique(simpleNameOf2(path10), accept);
|
|
70067
|
+
}
|
|
70068
|
+
/**
|
|
70069
|
+
* The declared spellings of the element `description` names — its regular
|
|
70070
|
+
* name and its `<short>` name — minus `written`.
|
|
70071
|
+
*/
|
|
70072
|
+
otherNames(description, written) {
|
|
70073
|
+
const all = this.spellingIndex().get(elementKey2(description)) ?? [];
|
|
70074
|
+
const seen = unquoteName3(written);
|
|
70075
|
+
return all.filter((name) => unquoteName3(name) !== seen);
|
|
70076
|
+
}
|
|
70077
|
+
index() {
|
|
70078
|
+
if (!this.byName)
|
|
70079
|
+
this.build();
|
|
70080
|
+
return this.byName;
|
|
70081
|
+
}
|
|
70082
|
+
spellingIndex() {
|
|
70083
|
+
if (!this.spellings)
|
|
70084
|
+
this.build();
|
|
70085
|
+
return this.spellings;
|
|
70086
|
+
}
|
|
70087
|
+
/** One pass over the index feeds both maps; neither is worth a second. */
|
|
70088
|
+
build() {
|
|
70089
|
+
const byName = /* @__PURE__ */ new Map();
|
|
70090
|
+
const spellings = /* @__PURE__ */ new Map();
|
|
70091
|
+
const add = (key, description) => {
|
|
70092
|
+
const bucket = byName.get(key);
|
|
70093
|
+
if (bucket)
|
|
70094
|
+
bucket.push(description);
|
|
70095
|
+
else
|
|
70096
|
+
byName.set(key, [description]);
|
|
70097
|
+
};
|
|
70098
|
+
for (const description of this.shared.workspace.IndexManager.allElements()) {
|
|
70099
|
+
add(description.name, description);
|
|
70100
|
+
const unquoted = unquoteName3(description.name);
|
|
70101
|
+
if (unquoted !== description.name)
|
|
70102
|
+
add(unquoted, description);
|
|
70103
|
+
if (!isDeclaredSpelling(description))
|
|
70104
|
+
continue;
|
|
70105
|
+
const key = elementKey2(description);
|
|
70106
|
+
const names = spellings.get(key);
|
|
70107
|
+
if (names) {
|
|
70108
|
+
if (!names.includes(description.name))
|
|
70109
|
+
names.push(description.name);
|
|
70110
|
+
} else {
|
|
70111
|
+
spellings.set(key, [description.name]);
|
|
70112
|
+
}
|
|
70113
|
+
}
|
|
70114
|
+
this.byName = byName;
|
|
70115
|
+
this.spellings = spellings;
|
|
70116
|
+
}
|
|
70117
|
+
};
|
|
70118
|
+
var lookups = /* @__PURE__ */ new WeakMap();
|
|
70119
|
+
function nameLookupFor(shared) {
|
|
70120
|
+
if (!shared)
|
|
70121
|
+
return void 0;
|
|
70122
|
+
const existing = lookups.get(shared);
|
|
70123
|
+
if (existing)
|
|
70124
|
+
return existing;
|
|
70125
|
+
const created = new SysmlNameLookup(shared);
|
|
70126
|
+
lookups.set(shared, created);
|
|
70127
|
+
return created;
|
|
70128
|
+
}
|
|
70129
|
+
|
|
70130
|
+
// ../language-server/out/src/services/callable-resolver.js
|
|
70131
|
+
var CALLABLE_TYPES = /* @__PURE__ */ new Set([
|
|
70132
|
+
"CalcDecl",
|
|
70133
|
+
"ActionDecl",
|
|
70134
|
+
"ConstraintDecl",
|
|
70135
|
+
"FunctionDecl",
|
|
70136
|
+
"PredicateDecl",
|
|
70137
|
+
"BehaviorDecl",
|
|
70138
|
+
"InteractionDecl"
|
|
70139
|
+
]);
|
|
70140
|
+
var CallableResolver = class {
|
|
70141
|
+
services;
|
|
70142
|
+
lookup;
|
|
70143
|
+
linker;
|
|
70144
|
+
constructor(services) {
|
|
70145
|
+
this.services = services;
|
|
70146
|
+
this.lookup = nameLookupFor(services?.shared);
|
|
70147
|
+
this.linker = services?.references.Linker;
|
|
70148
|
+
}
|
|
70149
|
+
/**
|
|
70150
|
+
* Every indexed callable that answers to `name`, so a caller can decide what
|
|
70151
|
+
* ambiguity costs it. Signature help is transient and follows the cursor, so
|
|
70152
|
+
* it takes the first; an inlay hint is a permanent annotation, so it takes a
|
|
70153
|
+
* candidate only when it is the ONLY element with that name.
|
|
70154
|
+
*/
|
|
70155
|
+
candidates(name) {
|
|
70156
|
+
const simple = simpleNameOf2(name);
|
|
70157
|
+
return (this.lookup?.descriptions(simple) ?? []).filter((description) => CALLABLE_TYPES.has(description.type));
|
|
70158
|
+
}
|
|
70159
|
+
/**
|
|
70160
|
+
* The one callable `name` unambiguously names in the index, if any: the
|
|
70161
|
+
* written spelling first, then its final segment, and either reading must
|
|
70162
|
+
* name exactly one element.
|
|
70163
|
+
*/
|
|
70164
|
+
uniqueCandidate(name) {
|
|
70165
|
+
return this.lookup?.uniqueForPath(name, (description) => CALLABLE_TYPES.has(description.type));
|
|
70166
|
+
}
|
|
70167
|
+
/** The callable declaration `name` invokes in `document`, resolved locally. */
|
|
70168
|
+
findLocal(document, name) {
|
|
70169
|
+
const root3 = document.parseResult?.value;
|
|
70170
|
+
if (!root3)
|
|
70171
|
+
return void 0;
|
|
70172
|
+
return collectCallables([root3, ...ast_utils_exports.streamAllContents(root3).toArray()]).get(unquoteName3(simpleNameOf2(name)));
|
|
70173
|
+
}
|
|
70174
|
+
/**
|
|
70175
|
+
* SYNCHRONOUS resolution: a qualified spelling the index holds verbatim,
|
|
70176
|
+
* then the document's own tree, then an unambiguous indexed callable —
|
|
70177
|
+
* resolved through the linker's off-to-the-side library parse. Nothing here
|
|
70178
|
+
* grows `LangiumDocuments`, and nothing here awaits, so it is safe on a
|
|
70179
|
+
* request VS Code re-issues on every scroll.
|
|
70180
|
+
*/
|
|
70181
|
+
resolve(document, name, local) {
|
|
70182
|
+
if (name.includes("::") || name.includes(".")) {
|
|
70183
|
+
const exact = this.lookup?.unique(name, (description) => CALLABLE_TYPES.has(description.type));
|
|
70184
|
+
const node = exact ? this.nodeOf(exact) : void 0;
|
|
70185
|
+
if (node)
|
|
70186
|
+
return node;
|
|
70187
|
+
}
|
|
70188
|
+
const found = local ? local(unquoteName3(simpleNameOf2(name))) : this.findLocal(document, name);
|
|
70189
|
+
if (found)
|
|
70190
|
+
return found;
|
|
70191
|
+
const candidate = this.uniqueCandidate(name);
|
|
70192
|
+
return candidate ? this.nodeOf(candidate) : void 0;
|
|
70193
|
+
}
|
|
70194
|
+
/** An indexed description as a node, through the linker's lazy library parse. */
|
|
70195
|
+
nodeOf(description) {
|
|
70196
|
+
return this.linker?.resolveIndexedNode?.(description) ?? description.node;
|
|
70197
|
+
}
|
|
70198
|
+
/**
|
|
70199
|
+
* Resolution that may load a workspace document. Signature help uses it: it
|
|
70200
|
+
* runs on an explicit editor gesture, not on every scroll, and a callable in
|
|
70201
|
+
* a workspace file the user has not opened yet still deserves a signature.
|
|
70202
|
+
*/
|
|
70203
|
+
// REQ-263 — Signature help on `(` / `,` / `->`
|
|
70204
|
+
async resolveAsync(document, name) {
|
|
70205
|
+
const direct = this.resolve(document, name);
|
|
70206
|
+
if (direct)
|
|
70207
|
+
return direct;
|
|
70208
|
+
const candidate = this.candidates(name).at(0);
|
|
70209
|
+
if (!candidate)
|
|
70210
|
+
return void 0;
|
|
70211
|
+
if (candidate.node)
|
|
70212
|
+
return candidate.node;
|
|
70213
|
+
const documents = this.services?.shared.workspace.LangiumDocuments;
|
|
70214
|
+
const locator = this.services?.workspace.AstNodeLocator;
|
|
70215
|
+
if (!documents || !locator)
|
|
70216
|
+
return void 0;
|
|
70217
|
+
const doc = documents.getDocument(candidate.documentUri) ?? await documents.getOrCreateDocument(candidate.documentUri);
|
|
70218
|
+
const root3 = doc?.parseResult?.value;
|
|
70219
|
+
return root3 ? locator.getAstNode(root3, candidate.path) : void 0;
|
|
70220
|
+
}
|
|
70221
|
+
/** {@link callableParameters} — the parameters, in written order. */
|
|
70222
|
+
parameters(node) {
|
|
70223
|
+
return callableParameters(node);
|
|
70224
|
+
}
|
|
70225
|
+
/**
|
|
70226
|
+
* The parameters a positional argument list binds to: the INPUTS, in written
|
|
70227
|
+
* order. An `out` parameter and the result are not written at the call site
|
|
70228
|
+
* (OMG KerML v1.0 binds an `InvocationExpression`'s arguments to the
|
|
70229
|
+
* invoked type's input features).
|
|
70230
|
+
*/
|
|
70231
|
+
inputParameters(node) {
|
|
70232
|
+
return this.parameters(node).filter((parameter) => !parameter.isReturn && parameter.direction !== "out");
|
|
70233
|
+
}
|
|
70234
|
+
};
|
|
70235
|
+
function callableParameters(node) {
|
|
70236
|
+
const directed = new Map(directedParameters(node).map((entry) => [entry.node, entry.direction]));
|
|
70237
|
+
const result = [];
|
|
70238
|
+
for (const member of membersOf(node)) {
|
|
70239
|
+
const direction = directed.get(member);
|
|
70240
|
+
const isReturn = member.$type === "ReturnDecl";
|
|
70241
|
+
if (!direction && !isReturn)
|
|
70242
|
+
continue;
|
|
70243
|
+
const name = nodeName2(member);
|
|
70244
|
+
if (!name && !direction)
|
|
70245
|
+
continue;
|
|
70246
|
+
result.push({
|
|
70247
|
+
node: member,
|
|
70248
|
+
direction: direction ?? "return",
|
|
70249
|
+
name,
|
|
70250
|
+
type: typingText(member),
|
|
70251
|
+
multiplicity: multiplicityText(member),
|
|
70252
|
+
isReturn
|
|
70253
|
+
});
|
|
70254
|
+
}
|
|
70255
|
+
return result;
|
|
70256
|
+
}
|
|
70257
|
+
function collectCallables(nodes) {
|
|
70258
|
+
const callables = /* @__PURE__ */ new Map();
|
|
70259
|
+
const byDefinition = /* @__PURE__ */ new Set();
|
|
70260
|
+
for (const node of nodes) {
|
|
70261
|
+
if (!CALLABLE_TYPES.has(node.$type) && callableParameters(node).length === 0)
|
|
70262
|
+
continue;
|
|
70263
|
+
const isDefinition = node.isDef === true;
|
|
70264
|
+
for (const name of [nodeName2(node), shortNameOf2(node)]) {
|
|
70265
|
+
if (!name)
|
|
70266
|
+
continue;
|
|
70267
|
+
if (callables.has(name) && !(isDefinition && !byDefinition.has(name)))
|
|
70268
|
+
continue;
|
|
70269
|
+
callables.set(name, node);
|
|
70270
|
+
if (isDefinition)
|
|
70271
|
+
byDefinition.add(name);
|
|
70272
|
+
}
|
|
70273
|
+
}
|
|
70274
|
+
return callables;
|
|
70275
|
+
}
|
|
70276
|
+
function membersOf(node) {
|
|
70277
|
+
const members = node?.members;
|
|
70278
|
+
return Array.isArray(members) ? members.filter(isAstNode3) : [];
|
|
70279
|
+
}
|
|
70280
|
+
function isAstNode3(value) {
|
|
70281
|
+
return typeof value === "object" && value !== null && typeof value.$type === "string";
|
|
70282
|
+
}
|
|
70283
|
+
function nodeName2(node) {
|
|
70284
|
+
const value = node?.name;
|
|
70285
|
+
return typeof value === "string" && value.length > 0 ? unquoteName3(value) : void 0;
|
|
70286
|
+
}
|
|
70287
|
+
function shortNameOf2(node) {
|
|
70288
|
+
const value = node?.shortName?.name;
|
|
70289
|
+
return typeof value === "string" && value.length > 0 ? unquoteName3(value) : void 0;
|
|
70290
|
+
}
|
|
70291
|
+
function typingText(node) {
|
|
70292
|
+
const text = node?.typing?.type?.$refText;
|
|
70293
|
+
return typeof text === "string" && text.length > 0 ? text : void 0;
|
|
70294
|
+
}
|
|
70295
|
+
function multiplicityText(node) {
|
|
70296
|
+
const text = node?.multiplicity?.$cstNode?.text;
|
|
70297
|
+
return typeof text === "string" && text.length > 0 ? text.trim() : void 0;
|
|
70298
|
+
}
|
|
70299
|
+
|
|
70300
|
+
// ../language-server/out/src/services/inlay-hint-provider.js
|
|
69976
70301
|
function multiplicityAnchor(node) {
|
|
69977
70302
|
const leaves = cst_utils_exports.flattenCst(node).toArray();
|
|
69978
70303
|
const bodyStart = leaves.find((leaf) => leaf.text === "{");
|
|
@@ -70031,6 +70356,50 @@ var EXPLICIT_SPECIALIZATION_KINDS = /* @__PURE__ */ new Set([
|
|
|
70031
70356
|
"conjugates"
|
|
70032
70357
|
]);
|
|
70033
70358
|
var REDEFINITION_KINDS2 = /* @__PURE__ */ new Set([":>>", "redefines"]);
|
|
70359
|
+
var CONSTANT_CARRYING_KINDS = /* @__PURE__ */ new Set([
|
|
70360
|
+
":>",
|
|
70361
|
+
"subsets",
|
|
70362
|
+
":>>",
|
|
70363
|
+
"redefines",
|
|
70364
|
+
"::>",
|
|
70365
|
+
"references",
|
|
70366
|
+
"=>",
|
|
70367
|
+
"crosses"
|
|
70368
|
+
]);
|
|
70369
|
+
var CONSTANT_MODIFIERS = /* @__PURE__ */ new Set(["constant", "const"]);
|
|
70370
|
+
function constantKeyword(languageId) {
|
|
70371
|
+
return languageId === "kerml" ? "const" : "constant";
|
|
70372
|
+
}
|
|
70373
|
+
var PREFIXES_BEFORE_CONSTANT = /* @__PURE__ */ new Set([
|
|
70374
|
+
"public",
|
|
70375
|
+
"private",
|
|
70376
|
+
"protected",
|
|
70377
|
+
"in",
|
|
70378
|
+
"out",
|
|
70379
|
+
"inout",
|
|
70380
|
+
"abstract",
|
|
70381
|
+
"variation",
|
|
70382
|
+
"variant",
|
|
70383
|
+
"derived",
|
|
70384
|
+
"readonly",
|
|
70385
|
+
"composite",
|
|
70386
|
+
"portion",
|
|
70387
|
+
"ordered",
|
|
70388
|
+
"nonunique",
|
|
70389
|
+
"parallel"
|
|
70390
|
+
]);
|
|
70391
|
+
var PORTION_MODIFIERS = /* @__PURE__ */ new Set(["portion", "snapshot", "timeslice"]);
|
|
70392
|
+
var ACTION_KIND_USAGES = /* @__PURE__ */ new Set([
|
|
70393
|
+
"ActionDecl",
|
|
70394
|
+
"StateDecl",
|
|
70395
|
+
"CalcDecl",
|
|
70396
|
+
"CaseDecl",
|
|
70397
|
+
"UseCaseDecl",
|
|
70398
|
+
"AnalysisCaseDecl",
|
|
70399
|
+
"VerificationCaseDecl"
|
|
70400
|
+
]);
|
|
70401
|
+
var KERML_FEATURE_DECLS = /* @__PURE__ */ new Set(["FeatureDecl", "StepDecl", "ExpressionDecl"]);
|
|
70402
|
+
var REFERENCE_MODIFIERS = /* @__PURE__ */ new Set(["ref", "in", "out", "inout"]);
|
|
70034
70403
|
var IMPLICIT_BASES = Object.freeze({
|
|
70035
70404
|
PartDecl: { def: "Parts::Part", usage: "Parts::parts" },
|
|
70036
70405
|
ItemDecl: { def: "Items::Item", usage: "Items::items" },
|
|
@@ -70055,6 +70424,37 @@ var IMPLICIT_BASES = Object.freeze({
|
|
|
70055
70424
|
OccurrenceDecl: { def: "Occurrences::Occurrence", usage: "Occurrences::occurrences" },
|
|
70056
70425
|
MetadataDecl: { def: "Metadata::MetadataItem", usage: "Metadata::metadataItems" }
|
|
70057
70426
|
});
|
|
70427
|
+
var OCCURRENCE_KIND_OWNERS = /* @__PURE__ */ new Set([
|
|
70428
|
+
...Object.keys(IMPLICIT_BASES).filter((kind) => kind !== "AttributeDecl"),
|
|
70429
|
+
// KerML fixes a library base per classifier kind too, in the same way and in
|
|
70430
|
+
// the same normative place: `Class` specializes `Occurrences::Occurrence`,
|
|
70431
|
+
// `Structure` specializes `Objects::Object`, `Metaclass` specializes
|
|
70432
|
+
// `Metaobjects::Metaobject`, `Behavior` specializes
|
|
70433
|
+
// `Performances::Performance`, `Function` and `Interaction` are Behaviors,
|
|
70434
|
+
// `Predicate` is a Function, `Step` specializes `Performances::performances`
|
|
70435
|
+
// and `Expression` is a Step. All of them reach `Occurrence`.
|
|
70436
|
+
"ClassDecl",
|
|
70437
|
+
"StructDecl",
|
|
70438
|
+
"MetaclassDecl",
|
|
70439
|
+
"BehaviorDecl",
|
|
70440
|
+
"InteractionDecl",
|
|
70441
|
+
"FunctionDecl",
|
|
70442
|
+
"PredicateDecl",
|
|
70443
|
+
"StepDecl",
|
|
70444
|
+
"ExpressionDecl"
|
|
70445
|
+
// Left out because their base is NOT an occurrence: `DatatypeDecl`
|
|
70446
|
+
// (`Base::DataValue`, declared disjoint from `Occurrence`) and plain
|
|
70447
|
+
// `AssociationDecl` (`Links::Link`, which specializes `Base::Anything`) —
|
|
70448
|
+
// `assoc struct` is handled separately, since it is a `LinkObject`.
|
|
70449
|
+
// Left out because their base is WRITTEN rather than fixed by the kind:
|
|
70450
|
+
// `TypeDecl`, `ClassifierDecl`, `FeatureDecl`.
|
|
70451
|
+
]);
|
|
70452
|
+
function isOccurrenceKindOwner(owner) {
|
|
70453
|
+
if (owner.$type === "AssociationDecl")
|
|
70454
|
+
return owner.isStruct === true;
|
|
70455
|
+
return OCCURRENCE_KIND_OWNERS.has(owner.$type);
|
|
70456
|
+
}
|
|
70457
|
+
var NON_VARYING_LIBRARY_TYPES = /* @__PURE__ */ new Set(["SelfLink", "HappensLink"]);
|
|
70058
70458
|
function markdown(value) {
|
|
70059
70459
|
return { kind: import_vscode_languageserver20.MarkupKind.Markdown, value };
|
|
70060
70460
|
}
|
|
@@ -70076,19 +70476,130 @@ function descriptionRange(description) {
|
|
|
70076
70476
|
const segment = description.nameSegment ?? description.selectionSegment;
|
|
70077
70477
|
return segment?.range ?? { start: { line: 0, character: 0 }, end: { line: 0, character: 0 } };
|
|
70078
70478
|
}
|
|
70479
|
+
function descriptionLocation(description) {
|
|
70480
|
+
return { uri: description.documentUri.toString(), range: descriptionRange(description) };
|
|
70481
|
+
}
|
|
70482
|
+
function nodeLocation(node) {
|
|
70483
|
+
const range = node.$cstNode?.range;
|
|
70484
|
+
if (!range)
|
|
70485
|
+
return void 0;
|
|
70486
|
+
return { uri: ast_utils_exports.getDocument(node).uri.toString(), range };
|
|
70487
|
+
}
|
|
70488
|
+
function specializesNonVaryingLibraryType(node) {
|
|
70489
|
+
const typing = node.typing?.type?.$refText;
|
|
70490
|
+
if (typing && NON_VARYING_LIBRARY_TYPES.has(lastSegment3(typing)))
|
|
70491
|
+
return true;
|
|
70492
|
+
return allRelationships2(node).flatMap((rel) => rel.targets ?? []).some((target) => NON_VARYING_LIBRARY_TYPES.has(lastSegment3(target)));
|
|
70493
|
+
}
|
|
70494
|
+
function constantAnchor(node) {
|
|
70495
|
+
const cst = node.$cstNode;
|
|
70496
|
+
if (!cst)
|
|
70497
|
+
return void 0;
|
|
70498
|
+
for (const leaf of cst_utils_exports.flattenCst(cst)) {
|
|
70499
|
+
if (leaf.hidden)
|
|
70500
|
+
continue;
|
|
70501
|
+
if (PREFIXES_BEFORE_CONSTANT.has(leaf.text))
|
|
70502
|
+
continue;
|
|
70503
|
+
return /^[a-z]+$/u.test(leaf.text) ? leaf : void 0;
|
|
70504
|
+
}
|
|
70505
|
+
return void 0;
|
|
70506
|
+
}
|
|
70507
|
+
function membershipImportPath(node) {
|
|
70508
|
+
if (isImport(node) && node.alias)
|
|
70509
|
+
return void 0;
|
|
70510
|
+
if (isExposePath(node) && node.dotSegs.length > 0)
|
|
70511
|
+
return void 0;
|
|
70512
|
+
if (node.segs.some((seg) => seg.star || seg.recursive || !seg.name))
|
|
70513
|
+
return void 0;
|
|
70514
|
+
const last2 = node.segs.at(-1);
|
|
70515
|
+
const written = last2?.name ?? node.head;
|
|
70516
|
+
const anchor = last2 ? grammar_utils_exports.findNodeForProperty(last2.$cstNode, "name") : grammar_utils_exports.findNodeForProperty(node.$cstNode, "head");
|
|
70517
|
+
if (!anchor)
|
|
70518
|
+
return void 0;
|
|
70519
|
+
return { path: [node.head, ...node.segs.map((seg) => seg.name)].join("::"), written, anchor };
|
|
70520
|
+
}
|
|
70521
|
+
function publicFeatures(type) {
|
|
70522
|
+
const members = type.members;
|
|
70523
|
+
if (!Array.isArray(members))
|
|
70524
|
+
return [];
|
|
70525
|
+
return members.filter((member) => {
|
|
70526
|
+
if (typeof member?.$type !== "string")
|
|
70527
|
+
return false;
|
|
70528
|
+
const decl = member;
|
|
70529
|
+
if (decl.isDef !== false && decl.$type !== "FeatureDecl")
|
|
70530
|
+
return false;
|
|
70531
|
+
return decl.visibility === void 0 || decl.visibility === "public";
|
|
70532
|
+
});
|
|
70533
|
+
}
|
|
70534
|
+
function calleeName(node) {
|
|
70535
|
+
if (node.call) {
|
|
70536
|
+
if (isPathExpr(node.target))
|
|
70537
|
+
return node.target.path;
|
|
70538
|
+
const target = node.target;
|
|
70539
|
+
if (isPostfixOp(target) && target.dot && target.field)
|
|
70540
|
+
return target.field;
|
|
70541
|
+
return void 0;
|
|
70542
|
+
}
|
|
70543
|
+
if (node.arrow && node.invoke)
|
|
70544
|
+
return node.invoke;
|
|
70545
|
+
return void 0;
|
|
70546
|
+
}
|
|
70547
|
+
function callArguments(node) {
|
|
70548
|
+
if (node.call)
|
|
70549
|
+
return { args: node.callArgs, firstParameter: 0 };
|
|
70550
|
+
if (node.arrow && node.invoke)
|
|
70551
|
+
return { args: node.args, firstParameter: 1 };
|
|
70552
|
+
return void 0;
|
|
70553
|
+
}
|
|
70079
70554
|
var SysmlInlayHintProvider = class {
|
|
70080
70555
|
services;
|
|
70081
70556
|
/**
|
|
70082
70557
|
* Resolved implicit bases, keyed by the qualified name in
|
|
70083
|
-
* {@link IMPLICIT_BASES}.
|
|
70084
|
-
*
|
|
70085
|
-
*
|
|
70086
|
-
*
|
|
70087
|
-
*
|
|
70558
|
+
* {@link IMPLICIT_BASES}. A base the index does not hold is NOT cached — the
|
|
70559
|
+
* library may still be loading — and issue #240 made that miss cheap: two
|
|
70560
|
+
* lookups in the shared name index rather than the full index scan it used
|
|
70561
|
+
* to be, on a request VS Code re-issues on every scroll. A HIT is cached
|
|
70562
|
+
* until the index is rebuilt, so the description a label links to always
|
|
70563
|
+
* carries the ranges of the generation it was read from.
|
|
70088
70564
|
*/
|
|
70089
70565
|
baseCache = /* @__PURE__ */ new Map();
|
|
70566
|
+
/**
|
|
70567
|
+
* REQ-395 — issue #240: the shared name lookup, built once per index
|
|
70568
|
+
* generation. Every category that resolves a WRITTEN name goes through it,
|
|
70569
|
+
* so no request puts an index scan on the hint path.
|
|
70570
|
+
*/
|
|
70571
|
+
lookup;
|
|
70572
|
+
/** REQ-395 — issue #240: the callee resolution signature help also uses. */
|
|
70573
|
+
callables;
|
|
70574
|
+
/** REQ-395 — issue #240: the linker's lazy standard-library parse. */
|
|
70575
|
+
linker;
|
|
70576
|
+
/**
|
|
70577
|
+
* REQ-395 — issue #240: "does this element declare `constant`?", memoized by
|
|
70578
|
+
* element identity, because answering it may cost one lazily parsed library
|
|
70579
|
+
* file. Editing away the `constant` on the SUBSETTED feature changes the
|
|
70580
|
+
* answer without changing the key, so this is dropped whenever the index is
|
|
70581
|
+
* rebuilt, exactly like the shared name lookup.
|
|
70582
|
+
*/
|
|
70583
|
+
constantCache = /* @__PURE__ */ new Map();
|
|
70584
|
+
/**
|
|
70585
|
+
* REQ-395 — issue #240: an element's own written names, memoized by element
|
|
70586
|
+
* identity. Reading them tells a `<short>` name from a regular one, which is
|
|
70587
|
+
* what lets the imported-name hint print the notation the source would have
|
|
70588
|
+
* written. It costs at most one lazily parsed library file, only for an
|
|
70589
|
+
* element that actually has two names, and it is dropped with the rest when
|
|
70590
|
+
* the index is rebuilt.
|
|
70591
|
+
*/
|
|
70592
|
+
declaredNameCache = /* @__PURE__ */ new Map();
|
|
70090
70593
|
constructor(services) {
|
|
70091
70594
|
this.services = services;
|
|
70595
|
+
this.lookup = nameLookupFor(services?.shared);
|
|
70596
|
+
this.callables = new CallableResolver(services);
|
|
70597
|
+
this.linker = services?.references.Linker;
|
|
70598
|
+
services?.shared.workspace.DocumentBuilder.onBuildPhase(DocumentState.IndexedContent, () => {
|
|
70599
|
+
this.baseCache.clear();
|
|
70600
|
+
this.constantCache.clear();
|
|
70601
|
+
this.declaredNameCache.clear();
|
|
70602
|
+
});
|
|
70092
70603
|
}
|
|
70093
70604
|
getInlayHints(document, _params) {
|
|
70094
70605
|
const root3 = document.parseResult?.value;
|
|
@@ -70096,7 +70607,14 @@ var SysmlInlayHintProvider = class {
|
|
|
70096
70607
|
return void 0;
|
|
70097
70608
|
const settings = sysmlInlayHintSettings;
|
|
70098
70609
|
const hints = [];
|
|
70099
|
-
|
|
70610
|
+
const nodes = allAstNodes(root3);
|
|
70611
|
+
let localCallables;
|
|
70612
|
+
const localCallable = (simple) => {
|
|
70613
|
+
localCallables ??= collectCallables(nodes);
|
|
70614
|
+
return localCallables.get(simple);
|
|
70615
|
+
};
|
|
70616
|
+
const callees = /* @__PURE__ */ new Map();
|
|
70617
|
+
for (const node of nodes) {
|
|
70100
70618
|
const decl = node;
|
|
70101
70619
|
if (settings.multiplicity && (isPartDecl(node) || isPortDecl(node) || isAttributeDecl(node)) && !decl.isDef && !decl.multiplicity && node.$cstNode && decl.name) {
|
|
70102
70620
|
hints.push({
|
|
@@ -70123,6 +70641,11 @@ var SysmlInlayHintProvider = class {
|
|
|
70123
70641
|
});
|
|
70124
70642
|
}
|
|
70125
70643
|
}
|
|
70644
|
+
if (settings.modifiers) {
|
|
70645
|
+
const constant2 = this.implicitConstantHint(decl);
|
|
70646
|
+
if (constant2)
|
|
70647
|
+
hints.push(constant2);
|
|
70648
|
+
}
|
|
70126
70649
|
if (settings.modifiers && isAttributeDecl(node) && !decl.isDef && !(decl.modifiers ?? []).includes("ref")) {
|
|
70127
70650
|
const keyword = keywordLeaf(node, "attribute");
|
|
70128
70651
|
if (keyword) {
|
|
@@ -70164,6 +70687,17 @@ var SysmlInlayHintProvider = class {
|
|
|
70164
70687
|
if (effective)
|
|
70165
70688
|
hints.push(effective);
|
|
70166
70689
|
}
|
|
70690
|
+
if (settings.importedNames && (isImport(node) || isExposePath(node))) {
|
|
70691
|
+
const imported = this.importedNameHint(node);
|
|
70692
|
+
if (imported)
|
|
70693
|
+
hints.push(imported);
|
|
70694
|
+
}
|
|
70695
|
+
if (settings.parameterNames && isPostfixOp(node)) {
|
|
70696
|
+
hints.push(...this.argumentNameHints(node, document, callees, localCallable));
|
|
70697
|
+
}
|
|
70698
|
+
if (settings.parameterNames && isNewExpr(node)) {
|
|
70699
|
+
hints.push(...this.constructorArgumentHints(node));
|
|
70700
|
+
}
|
|
70167
70701
|
if (!settings.dimension)
|
|
70168
70702
|
continue;
|
|
70169
70703
|
if (isNumericPrimary(node)) {
|
|
@@ -70233,6 +70767,228 @@ var SysmlInlayHintProvider = class {
|
|
|
70233
70767
|
}
|
|
70234
70768
|
return hints;
|
|
70235
70769
|
}
|
|
70770
|
+
/**
|
|
70771
|
+
* REQ-395 — issue #240: the other name a membership `import` brings in.
|
|
70772
|
+
*
|
|
70773
|
+
* An element may declare both a regular name and a `<short>` name, and an
|
|
70774
|
+
* import brings in BOTH — the one the path does not write is invisible in
|
|
70775
|
+
* the source, which is exactly what the hint is for. The written path is a
|
|
70776
|
+
* datatype string, not a cross-reference, so the element is found through
|
|
70777
|
+
* the shared name lookup: the spelling the index holds verbatim first, then
|
|
70778
|
+
* the final segment, and either reading must name exactly ONE element. A
|
|
70779
|
+
* name two packages both declare yields nothing rather than whichever the
|
|
70780
|
+
* index lists first.
|
|
70781
|
+
*/
|
|
70782
|
+
importedNameHint(node) {
|
|
70783
|
+
const written = membershipImportPath(node);
|
|
70784
|
+
if (!written || !this.lookup)
|
|
70785
|
+
return void 0;
|
|
70786
|
+
const description = this.lookup.uniqueForPath(written.path);
|
|
70787
|
+
if (!description)
|
|
70788
|
+
return void 0;
|
|
70789
|
+
const others = this.lookup.otherNames(description, written.written);
|
|
70790
|
+
if (others.length === 0)
|
|
70791
|
+
return void 0;
|
|
70792
|
+
const declared = this.declaredNames(description);
|
|
70793
|
+
const shown = others.map((name) => declared?.shortName === name ? `<${name}>` : name);
|
|
70794
|
+
const kind = isImport(node) ? "import" : "expose";
|
|
70795
|
+
return {
|
|
70796
|
+
position: written.anchor.range.end,
|
|
70797
|
+
label: [{
|
|
70798
|
+
value: ` also ${shown.join(", ")}`,
|
|
70799
|
+
location: descriptionLocation(description)
|
|
70800
|
+
}],
|
|
70801
|
+
kind: import_vscode_languageserver20.InlayHintKind.Parameter,
|
|
70802
|
+
paddingLeft: true,
|
|
70803
|
+
tooltip: markdown(`This \`${kind}\` also brings \`${shown.join("`, `")}\` into scope: an element is addressable by its regular name and by its short name, and a membership import carries both.`)
|
|
70804
|
+
};
|
|
70805
|
+
}
|
|
70806
|
+
/**
|
|
70807
|
+
* REQ-395 — issue #240: the names an indexed element declares for itself.
|
|
70808
|
+
*
|
|
70809
|
+
* The index records the spellings but not which of them is the `<short>`
|
|
70810
|
+
* one, so the declaration is resolved through the linker's off-to-the-side
|
|
70811
|
+
* library parse — the budget REQ-251 sets, spent only for an element that
|
|
70812
|
+
* has more than one name, and memoized until the index is rebuilt.
|
|
70813
|
+
*/
|
|
70814
|
+
declaredNames(description) {
|
|
70815
|
+
const key = elementKey2(description);
|
|
70816
|
+
const cached = this.declaredNameCache.get(key);
|
|
70817
|
+
if (cached)
|
|
70818
|
+
return cached;
|
|
70819
|
+
const node = this.linker?.resolveIndexedNode?.(description) ?? description.node;
|
|
70820
|
+
if (!node)
|
|
70821
|
+
return void 0;
|
|
70822
|
+
const decl = node;
|
|
70823
|
+
const names = { name: decl.name, shortName: decl.shortName?.name };
|
|
70824
|
+
this.declaredNameCache.set(key, names);
|
|
70825
|
+
return names;
|
|
70826
|
+
}
|
|
70827
|
+
/**
|
|
70828
|
+
* REQ-395 — issue #240: the feature each `new Type(…)` argument binds to.
|
|
70829
|
+
*
|
|
70830
|
+
* A `ConstructorExpression` binds its arguments to the PUBLIC features of
|
|
70831
|
+
* the instantiated type, in order (OMG KerML v1.0, `ConstructorExpression`)
|
|
70832
|
+
* — not to input parameters, which is what an `InvocationExpression` binds.
|
|
70833
|
+
* The instantiated type IS a cross-reference here, so there is nothing to
|
|
70834
|
+
* resolve by name: an unresolved one simply yields no hints.
|
|
70835
|
+
*/
|
|
70836
|
+
constructorArgumentHints(node) {
|
|
70837
|
+
if (node.args.length === 0)
|
|
70838
|
+
return [];
|
|
70839
|
+
if (node.args.every((argument) => argument.name !== void 0))
|
|
70840
|
+
return [];
|
|
70841
|
+
const instantiated = node.type?.ref;
|
|
70842
|
+
if (!instantiated)
|
|
70843
|
+
return [];
|
|
70844
|
+
const features = publicFeatures(instantiated);
|
|
70845
|
+
if (features.length === 0)
|
|
70846
|
+
return [];
|
|
70847
|
+
const hints = [];
|
|
70848
|
+
for (let index = 0; index < node.args.length; index++) {
|
|
70849
|
+
const argument = node.args[index];
|
|
70850
|
+
if (argument.name || !argument.$cstNode)
|
|
70851
|
+
continue;
|
|
70852
|
+
const feature = features[index];
|
|
70853
|
+
const name = feature?.name;
|
|
70854
|
+
if (!feature || !name)
|
|
70855
|
+
continue;
|
|
70856
|
+
const location = nodeLocation(feature);
|
|
70857
|
+
hints.push({
|
|
70858
|
+
position: argument.$cstNode.range.start,
|
|
70859
|
+
label: [{ value: `${name} =`, ...location ? { location } : {} }],
|
|
70860
|
+
kind: import_vscode_languageserver20.InlayHintKind.Parameter,
|
|
70861
|
+
paddingRight: true,
|
|
70862
|
+
tooltip: markdown(`Argument ${index + 1} binds to \`${name}\` of \`${node.type.$refText}\`.`)
|
|
70863
|
+
});
|
|
70864
|
+
}
|
|
70865
|
+
return hints;
|
|
70866
|
+
}
|
|
70867
|
+
/**
|
|
70868
|
+
* REQ-395 — issue #240: the parameter a POSITIONAL invocation argument binds
|
|
70869
|
+
* to.
|
|
70870
|
+
*
|
|
70871
|
+
* The callee of a call is an expression rather than a cross-reference, so
|
|
70872
|
+
* the name is resolved through the shared {@link CallableResolver} — the
|
|
70873
|
+
* same one signature help uses, which is why naming these arguments does not
|
|
70874
|
+
* add a second resolution path. An argument that writes its own name has
|
|
70875
|
+
* stated the correspondence, so it gets no hint.
|
|
70876
|
+
*/
|
|
70877
|
+
argumentNameHints(node, document, callees, localCallable) {
|
|
70878
|
+
const call = callArguments(node);
|
|
70879
|
+
const callee = calleeName(node);
|
|
70880
|
+
if (!call || !callee || call.args.length === 0)
|
|
70881
|
+
return [];
|
|
70882
|
+
if (call.args.every((argument) => argument.argName !== void 0))
|
|
70883
|
+
return [];
|
|
70884
|
+
let callable = callees.get(callee);
|
|
70885
|
+
if (callable === void 0 && !callees.has(callee)) {
|
|
70886
|
+
callable = this.callables.resolve(document, callee, localCallable);
|
|
70887
|
+
callees.set(callee, callable);
|
|
70888
|
+
}
|
|
70889
|
+
if (!callable)
|
|
70890
|
+
return [];
|
|
70891
|
+
const parameters = this.callables.inputParameters(callable);
|
|
70892
|
+
if (parameters.length === 0)
|
|
70893
|
+
return [];
|
|
70894
|
+
const hints = [];
|
|
70895
|
+
for (let index = 0; index < call.args.length; index++) {
|
|
70896
|
+
const argument = call.args[index];
|
|
70897
|
+
if (argument.argName || !argument.$cstNode)
|
|
70898
|
+
continue;
|
|
70899
|
+
const parameter = parameters[index + call.firstParameter];
|
|
70900
|
+
if (!parameter?.name)
|
|
70901
|
+
continue;
|
|
70902
|
+
const location = nodeLocation(parameter.node);
|
|
70903
|
+
hints.push({
|
|
70904
|
+
position: argument.$cstNode.range.start,
|
|
70905
|
+
label: [{ value: `${parameter.name} =`, ...location ? { location } : {} }],
|
|
70906
|
+
kind: import_vscode_languageserver20.InlayHintKind.Parameter,
|
|
70907
|
+
paddingRight: true,
|
|
70908
|
+
tooltip: markdown(`Argument ${index + 1} binds to \`${parameter.direction} ${parameter.name}\` of \`${callee}\`.`)
|
|
70909
|
+
});
|
|
70910
|
+
}
|
|
70911
|
+
return hints;
|
|
70912
|
+
}
|
|
70913
|
+
/**
|
|
70914
|
+
* REQ-395 — issue #240: implicit `constant`.
|
|
70915
|
+
*
|
|
70916
|
+
* OMG KerML v1.0 constrains `Subsetting`: `subsettedFeature.isConstant and
|
|
70917
|
+
* subsettingFeature.isVariable implies subsettingFeature.isConstant`. So a
|
|
70918
|
+
* usage that subsets or redefines a feature declared `constant` IS constant,
|
|
70919
|
+
* without writing it — provided it can vary at all, because `Feature` also
|
|
70920
|
+
* constrains `isConstant implies isVariable`.
|
|
70921
|
+
*
|
|
70922
|
+
* Whether it can vary is `Usage::mayTimeVary`, which OMG SysML v2 Part 1
|
|
70923
|
+
* derives as "owned by a type that specializes `Occurrences::Occurrence`,
|
|
70924
|
+
* and not a portion, a self/happens link, or a composite action". All four
|
|
70925
|
+
* are decided here from the declaration kinds and what the source writes
|
|
70926
|
+
* ({@link isOccurrenceKindOwner}, {@link PORTION_MODIFIERS},
|
|
70927
|
+
* {@link ACTION_KIND_USAGES} with {@link REFERENCE_MODIFIERS}, and
|
|
70928
|
+
* {@link specializesNonVaryingLibraryType}); an owner whose base is written
|
|
70929
|
+
* rather than fixed by its kind leaves the category quiet, as an
|
|
70930
|
+
* undecidable model must.
|
|
70931
|
+
*/
|
|
70932
|
+
implicitConstantHint(node) {
|
|
70933
|
+
const isFeature = node.isDef === false || KERML_FEATURE_DECLS.has(node.$type);
|
|
70934
|
+
if (!isFeature)
|
|
70935
|
+
return void 0;
|
|
70936
|
+
const modifiers2 = node.modifiers ?? [];
|
|
70937
|
+
if (modifiers2.some((modifier) => CONSTANT_MODIFIERS.has(modifier)))
|
|
70938
|
+
return void 0;
|
|
70939
|
+
if (modifiers2.some((modifier) => PORTION_MODIFIERS.has(modifier)))
|
|
70940
|
+
return void 0;
|
|
70941
|
+
if (ACTION_KIND_USAGES.has(node.$type) && !modifiers2.some((modifier) => REFERENCE_MODIFIERS.has(modifier)))
|
|
70942
|
+
return void 0;
|
|
70943
|
+
const owner = node.$container;
|
|
70944
|
+
if (!owner || !isOccurrenceKindOwner(owner))
|
|
70945
|
+
return void 0;
|
|
70946
|
+
if (specializesNonVaryingLibraryType(node))
|
|
70947
|
+
return void 0;
|
|
70948
|
+
const carrier = allRelationships2(node).filter((rel) => rel.kind && CONSTANT_CARRYING_KINDS.has(rel.kind)).flatMap((rel) => rel.targets ?? []).find((target) => this.isConstantFeature(target));
|
|
70949
|
+
if (!carrier)
|
|
70950
|
+
return void 0;
|
|
70951
|
+
const anchor = constantAnchor(node);
|
|
70952
|
+
const at = anchor?.range.start ?? node.$cstNode?.range.start;
|
|
70953
|
+
if (!at)
|
|
70954
|
+
return void 0;
|
|
70955
|
+
const keyword = constantKeyword(this.services?.LanguageMetaData.languageId);
|
|
70956
|
+
return {
|
|
70957
|
+
position: at,
|
|
70958
|
+
label: keyword,
|
|
70959
|
+
kind: import_vscode_languageserver20.InlayHintKind.Type,
|
|
70960
|
+
paddingRight: true,
|
|
70961
|
+
tooltip: markdown(`Implicitly \`${keyword}\`: this feature subsets \`${lastSegment3(carrier)}\`, which is declared constant, and a subsetting feature that may vary takes the constancy of what it subsets.`),
|
|
70962
|
+
// Writing the modifier is mechanically safe — it is a leading
|
|
70963
|
+
// declaration prefix, and OMG puts it exactly here, before `ref`
|
|
70964
|
+
// and the kind keyword.
|
|
70965
|
+
...anchor ? { textEdits: [{ range: { start: at, end: at }, newText: `${keyword} ` }] } : {}
|
|
70966
|
+
};
|
|
70967
|
+
}
|
|
70968
|
+
/**
|
|
70969
|
+
* REQ-395 — issue #240: does the feature this path names declare `constant`?
|
|
70970
|
+
*
|
|
70971
|
+
* The path must name exactly one element, and that element is resolved
|
|
70972
|
+
* through the linker's off-to-the-side library parse — one lazily parsed
|
|
70973
|
+
* indexed target, the budget REQ-251 sets, and never a document added to the
|
|
70974
|
+
* workspace. The answer is memoized, so a scroll does not repeat it.
|
|
70975
|
+
*/
|
|
70976
|
+
isConstantFeature(target) {
|
|
70977
|
+
if (!this.lookup)
|
|
70978
|
+
return false;
|
|
70979
|
+
const description = this.lookup.uniqueForPath(target);
|
|
70980
|
+
if (!description)
|
|
70981
|
+
return false;
|
|
70982
|
+
const key = elementKey2(description);
|
|
70983
|
+
const cached = this.constantCache.get(key);
|
|
70984
|
+
if (cached !== void 0)
|
|
70985
|
+
return cached;
|
|
70986
|
+
const node = this.linker?.resolveIndexedNode?.(description) ?? description.node;
|
|
70987
|
+
const modifiers2 = node?.modifiers ?? [];
|
|
70988
|
+
const answer = modifiers2.some((modifier) => CONSTANT_MODIFIERS.has(modifier));
|
|
70989
|
+
this.constantCache.set(key, answer);
|
|
70990
|
+
return answer;
|
|
70991
|
+
}
|
|
70236
70992
|
/**
|
|
70237
70993
|
* REQ-395 — Find one implicit base in the index.
|
|
70238
70994
|
*
|
|
@@ -70246,25 +71002,19 @@ var SysmlInlayHintProvider = class {
|
|
|
70246
71002
|
const cached = this.baseCache.get(qualified);
|
|
70247
71003
|
if (cached)
|
|
70248
71004
|
return cached;
|
|
70249
|
-
|
|
70250
|
-
if (!index)
|
|
71005
|
+
if (!this.lookup)
|
|
70251
71006
|
return void 0;
|
|
70252
|
-
const
|
|
70253
|
-
|
|
70254
|
-
|
|
70255
|
-
|
|
70256
|
-
|
|
70257
|
-
|
|
70258
|
-
}
|
|
70259
|
-
if (fallback || description.name !== simple)
|
|
70260
|
-
continue;
|
|
71007
|
+
const exact = this.lookup.descriptions(qualified).at(0);
|
|
71008
|
+
if (exact) {
|
|
71009
|
+
this.baseCache.set(qualified, exact);
|
|
71010
|
+
return exact;
|
|
71011
|
+
}
|
|
71012
|
+
const fallback = this.lookup.descriptions(lastSegment3(qualified)).find((description) => {
|
|
70261
71013
|
const uri = description.documentUri instanceof URI2 ? description.documentUri : URI2.parse(String(description.documentUri));
|
|
70262
71014
|
if (!isStandardLibraryUri(uri))
|
|
70263
|
-
|
|
70264
|
-
|
|
70265
|
-
|
|
70266
|
-
fallback = description;
|
|
70267
|
-
}
|
|
71015
|
+
return false;
|
|
71016
|
+
return description.isUsage === true === wantUsage;
|
|
71017
|
+
});
|
|
70268
71018
|
if (fallback)
|
|
70269
71019
|
this.baseCache.set(qualified, fallback);
|
|
70270
71020
|
return fallback;
|
|
@@ -72319,7 +73069,7 @@ async function runValidation(command) {
|
|
|
72319
73069
|
}
|
|
72320
73070
|
|
|
72321
73071
|
// src/main.ts
|
|
72322
|
-
var VERSION2 = true ? "0.
|
|
73072
|
+
var VERSION2 = true ? "0.26.0" : "dev";
|
|
72323
73073
|
async function main(argv) {
|
|
72324
73074
|
const command = parseArgs(argv);
|
|
72325
73075
|
if (command.kind === "help") {
|