sysml-validate 0.16.0 → 0.18.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 CHANGED
@@ -57816,229 +57816,640 @@ function asDiagnosticLevel(value, fallback = "off") {
57816
57816
  return value === "off" || value === "warning" || value === "error" ? value : fallback;
57817
57817
  }
57818
57818
 
57819
- // ../language-server/out/src/services/import-visibility.js
57820
- var GlobalDescriptionIndex = class _GlobalDescriptionIndex {
57821
- /** Reuse an existing index; wrap a plain list. */
57822
- static from(source) {
57823
- return source instanceof _GlobalDescriptionIndex ? source : new _GlobalDescriptionIndex(source);
57819
+ // ../language-server/out/src/services/requirement-eval.js
57820
+ var UNRESOLVED = { kind: "unresolved" };
57821
+ var INCONCLUSIVE = { kind: "inconclusive" };
57822
+ var NULL_VALUE = { kind: "null" };
57823
+ var REDEFINE_KINDS = /* @__PURE__ */ new Set([":>>", ":>", "redefines", "subsets"]);
57824
+ function declaresFeature(node, name) {
57825
+ if (node.name === name)
57826
+ return true;
57827
+ for (const rel of [...node.preRelationships ?? [], ...node.relationships ?? []]) {
57828
+ if (rel.kind && REDEFINE_KINDS.has(rel.kind) && (rel.targets ?? []).includes(name))
57829
+ return true;
57824
57830
  }
57825
- /** Exact name → descriptions carrying it (qualified and simple names alike). */
57826
- byName = /* @__PURE__ */ new Map();
57827
- /** Namespace path → descriptions for its DIRECT members (`A::B` `A::B::C`). */
57828
- directMembers = /* @__PURE__ */ new Map();
57829
- /** Namespace path → descriptions for all its descendants (`A` → `A::B::C`). */
57830
- nestedMembers = /* @__PURE__ */ new Map();
57831
- constructor(descriptions) {
57832
- for (const desc of descriptions) {
57833
- push(this.byName, desc.name, desc);
57834
- let sep2 = desc.name.indexOf("::");
57835
- while (sep2 >= 0) {
57836
- const prefix = desc.name.slice(0, sep2);
57837
- push(this.nestedMembers, prefix, desc);
57838
- const next = desc.name.indexOf("::", sep2 + 2);
57839
- if (next < 0)
57840
- push(this.directMembers, prefix, desc);
57841
- sep2 = next;
57842
- }
57831
+ return false;
57832
+ }
57833
+ function evaluateExpr(node, scope, ext) {
57834
+ if (!node)
57835
+ return INCONCLUSIVE;
57836
+ const extended = ext?.(node, (child) => evaluateExpr(child, scope, ext));
57837
+ if (extended)
57838
+ return extended;
57839
+ const n = node;
57840
+ switch (n.$type) {
57841
+ case "NumericPrimary":
57842
+ return typeof n.numVal === "number" ? { kind: "number", value: n.numVal } : INCONCLUSIVE;
57843
+ case "LiteralBool":
57844
+ return { kind: "boolean", value: n.value === "true" };
57845
+ case "LiteralStr":
57846
+ return { kind: "string", value: decodeStringLiteral(String(n.value ?? "")) };
57847
+ case "LiteralNull":
57848
+ return INCONCLUSIVE;
57849
+ case "ParenExpr": {
57850
+ const items = n.items ?? [];
57851
+ return items.length === 1 ? evaluateExpr(items[0], scope, ext) : INCONCLUSIVE;
57843
57852
  }
57853
+ case "UnaryMinusExpr": {
57854
+ const v = evaluateExpr(n.operand, scope, ext);
57855
+ return v.kind === "number" ? { kind: "number", value: -v.value } : passThrough(v);
57856
+ }
57857
+ case "UnaryPlusExpr":
57858
+ return evaluateExpr(n.operand, scope, ext);
57859
+ case "NotExpr": {
57860
+ if (!n.operand)
57861
+ return INCONCLUSIVE;
57862
+ const v = evaluateExpr(n.operand, scope, ext);
57863
+ return v.kind === "boolean" ? { kind: "boolean", value: !v.value } : passThrough(v);
57864
+ }
57865
+ case "PathExpr":
57866
+ return scope(String(n.path).split("."));
57867
+ case "IfExpr": {
57868
+ const cond = evaluateExpr(n.cond, scope, ext);
57869
+ if (cond.kind !== "boolean")
57870
+ return passThrough(cond);
57871
+ return cond.value ? evaluateExpr(n.thenExpr, scope, ext) : evaluateExpr(n.elseExpr, scope, ext);
57872
+ }
57873
+ case "PostfixOp": {
57874
+ if (n.unit && n.unitValue)
57875
+ return evaluateExpr(n.unitValue, scope, ext);
57876
+ if (n.operand)
57877
+ return evaluateExpr(n.operand, scope, ext);
57878
+ return INCONCLUSIVE;
57879
+ }
57880
+ case "BinExpr":
57881
+ return evaluateBin(n, scope, ext);
57882
+ default:
57883
+ return INCONCLUSIVE;
57844
57884
  }
57845
- named(name) {
57846
- return this.byName.get(name) ?? EMPTY_DESCRIPTIONS;
57847
- }
57848
- firstNamed(name) {
57849
- return this.byName.get(name)?.[0];
57850
- }
57851
- membersOf(path10, wildcard) {
57852
- const map3 = wildcard === "shallow" ? this.directMembers : this.nestedMembers;
57853
- return map3.get(path10) ?? EMPTY_DESCRIPTIONS;
57854
- }
57855
- };
57856
- var EMPTY_DESCRIPTIONS = [];
57857
- function push(map3, key, desc) {
57858
- const list = map3.get(key);
57859
- if (list)
57860
- list.push(desc);
57861
- else
57862
- map3.set(key, [desc]);
57863
57885
  }
57864
- function expandImportEntries(imp, globalDescriptions, options = {}) {
57865
- const out = [];
57866
- expandImportInto(imp, GlobalDescriptionIndex.from(globalDescriptions), out, options, /* @__PURE__ */ new Set());
57867
- return dedupeEntries(out);
57886
+ function passThrough(v) {
57887
+ return v.kind === "unresolved" ? UNRESOLVED : INCONCLUSIVE;
57868
57888
  }
57869
- function importedPath(imp) {
57870
- const segments = [imp.head];
57871
- for (const seg of imp.segs) {
57872
- if (seg.name)
57873
- segments.push(seg.name);
57889
+ function decodeStringLiteral(raw) {
57890
+ let body = raw;
57891
+ if (body.length >= 2 && body.startsWith('"') && body.endsWith('"')) {
57892
+ body = body.slice(1, -1);
57874
57893
  }
57875
- return segments.length > 0 ? segments.join("::") : void 0;
57894
+ return body.replace(/\\(.)/gu, (_m, ch) => {
57895
+ switch (ch) {
57896
+ case "n":
57897
+ return "\n";
57898
+ case "t":
57899
+ return " ";
57900
+ case "b":
57901
+ return "\b";
57902
+ case "f":
57903
+ return "\f";
57904
+ default:
57905
+ return ch;
57906
+ }
57907
+ });
57876
57908
  }
57877
- function importWildcard(imp) {
57878
- let wildcard = "none";
57879
- for (const seg of imp.segs) {
57880
- if (seg.recursive)
57881
- wildcard = "recursive";
57882
- else if (seg.star)
57883
- wildcard = "shallow";
57909
+ function evaluateBin(node, scope, ext) {
57910
+ const op = String(node.op);
57911
+ const left = evaluateExpr(node.left, scope, ext);
57912
+ if (op === "and" || op === "&") {
57913
+ if (left.kind === "boolean" && !left.value)
57914
+ return { kind: "boolean", value: false };
57915
+ } else if (op === "or" || op === "|") {
57916
+ if (left.kind === "boolean" && left.value)
57917
+ return { kind: "boolean", value: true };
57918
+ } else if (op === "implies") {
57919
+ if (left.kind === "boolean" && !left.value)
57920
+ return { kind: "boolean", value: true };
57884
57921
  }
57885
- return wildcard;
57886
- }
57887
- function importVisibility(imp) {
57888
- return imp.visibility ?? "private";
57889
- }
57890
- function resolveDescription(name, globalDescriptions) {
57891
- const index = GlobalDescriptionIndex.from(globalDescriptions);
57892
- const normalized = name.trim();
57893
- const direct = index.firstNamed(normalized);
57894
- if (direct)
57895
- return direct;
57896
- const simple = normalized.split(/::|\./).pop();
57897
- return simple ? index.firstNamed(simple) : void 0;
57898
- }
57899
- function descriptionKey(description) {
57900
- return `${description.documentUri.toString()}#${description.path}`;
57901
- }
57902
- function namespaceMembers(node) {
57903
- const n = node;
57904
- return [...n?.elements ?? [], ...n?.members ?? []];
57905
- }
57906
- function expandImportInto(imp, globalDescriptions, out, options, visitedNamespaces) {
57907
- const path10 = importedPath(imp);
57908
- if (!path10)
57909
- return;
57910
- const start = out.length;
57911
- const namedSegments = path10.split("::");
57912
- const wildcard = importWildcard(imp);
57913
- if (wildcard === "none") {
57914
- const targetDesc = resolveImportedDescription(path10, globalDescriptions, options, visitedNamespaces);
57915
- if (targetDesc) {
57916
- const alias = imp.alias ?? namedSegments[namedSegments.length - 1];
57917
- if (alias)
57918
- out.push({ name: alias, targetName: targetDesc.name, description: targetDesc });
57922
+ const right = evaluateExpr(node.right, scope, ext);
57923
+ if (left.kind === "unresolved" || right.kind === "unresolved")
57924
+ return UNRESOLVED;
57925
+ if (left.kind === "inconclusive" || right.kind === "inconclusive")
57926
+ return INCONCLUSIVE;
57927
+ switch (op) {
57928
+ case "+":
57929
+ case "-":
57930
+ case "*":
57931
+ case "/":
57932
+ case "%":
57933
+ case "**":
57934
+ case "^":
57935
+ if (left.kind === "number" && right.kind === "number") {
57936
+ return { kind: "number", value: arith(op, left.value, right.value) };
57937
+ }
57938
+ return INCONCLUSIVE;
57939
+ case "<":
57940
+ case ">":
57941
+ case "<=":
57942
+ case ">=":
57943
+ if (left.kind === "number" && right.kind === "number") {
57944
+ return { kind: "boolean", value: compare(op, left.value, right.value) };
57945
+ }
57946
+ return INCONCLUSIVE;
57947
+ case "==":
57948
+ case "!=":
57949
+ case "===":
57950
+ case "!==": {
57951
+ const eq3 = valuesEqual(left, right);
57952
+ if (eq3 === void 0)
57953
+ return INCONCLUSIVE;
57954
+ return { kind: "boolean", value: op.startsWith("!") ? !eq3 : eq3 };
57919
57955
  }
57920
- } else {
57921
- expandNamespaceMembers(path10, wildcard, globalDescriptions, out);
57922
- expandNamespaceImports(path10, globalDescriptions, out, options, visitedNamespaces);
57956
+ case "and":
57957
+ case "&":
57958
+ return bothBool(left, right, (a2, b) => a2 && b);
57959
+ case "or":
57960
+ case "|":
57961
+ return bothBool(left, right, (a2, b) => a2 || b);
57962
+ case "xor":
57963
+ return bothBool(left, right, (a2, b) => a2 !== b);
57964
+ case "implies":
57965
+ return bothBool(left, right, (a2, b) => !a2 || b);
57966
+ default:
57967
+ return INCONCLUSIVE;
57923
57968
  }
57924
- applyImportFilters(imp, out, start, options);
57925
57969
  }
57926
- function applyImportFilters(imp, out, start, options) {
57927
- const filters = imp.filters;
57928
- if (!filters || filters.length === 0 || out.length === start)
57929
- return;
57930
- const resolveRefs = options.resolveReferences !== false;
57931
- const kept = [];
57932
- for (let i = start; i < out.length; i++) {
57933
- const entry = out[i];
57934
- const node = options.nodeOf?.(entry.description) ?? entry.description.node;
57935
- if (!node || entryMatchesAllFilters(node, filters, resolveRefs))
57936
- kept.push(entry);
57970
+ function arith(op, a2, b) {
57971
+ switch (op) {
57972
+ case "+":
57973
+ return a2 + b;
57974
+ case "-":
57975
+ return a2 - b;
57976
+ case "*":
57977
+ return a2 * b;
57978
+ case "/":
57979
+ return a2 / b;
57980
+ case "%":
57981
+ return a2 % b;
57982
+ case "**":
57983
+ case "^":
57984
+ return a2 ** b;
57985
+ default:
57986
+ return NaN;
57937
57987
  }
57938
- out.length = start;
57939
- out.push(...kept);
57940
57988
  }
57941
- function entryMatchesAllFilters(node, filters, resolveRefs) {
57942
- const metadataTypes = attachedMetadataTypes(node, resolveRefs);
57943
- for (const filter3 of filters) {
57944
- const result = evaluateFilterCondition(filter3.condition, metadataTypes, resolveRefs);
57945
- if (result === false)
57989
+ function compare(op, a2, b) {
57990
+ switch (op) {
57991
+ case "<":
57992
+ return a2 < b;
57993
+ case ">":
57994
+ return a2 > b;
57995
+ case "<=":
57996
+ return a2 <= b;
57997
+ case ">=":
57998
+ return a2 >= b;
57999
+ default:
57946
58000
  return false;
57947
58001
  }
57948
- return true;
57949
58002
  }
57950
- function evaluateFilterCondition(node, metadataTypes, resolveRefs) {
57951
- if (isSelfClassifyExpr(node)) {
57952
- if (node.op !== "@" && node.op !== "@@")
57953
- return void 0;
57954
- return metadataTypeMatches(node.type, metadataTypes, resolveRefs);
57955
- }
57956
- if (isNotExpr(node) && node.operand) {
57957
- const operand = evaluateFilterCondition(node.operand, metadataTypes, resolveRefs);
57958
- return operand === void 0 ? void 0 : !operand;
57959
- }
57960
- if (isParenExpr(node)) {
57961
- return node.items.length === 1 ? evaluateFilterCondition(node.items[0], metadataTypes, resolveRefs) : void 0;
57962
- }
57963
- if (isBinExpr(node)) {
57964
- if (CONJUNCTION_OPERATORS.has(node.op)) {
57965
- const left = evaluateFilterCondition(node.left, metadataTypes, resolveRefs);
57966
- const right = evaluateFilterCondition(node.right, metadataTypes, resolveRefs);
57967
- if (left === false || right === false)
57968
- return false;
57969
- return left === void 0 || right === void 0 ? void 0 : true;
57970
- }
57971
- if (DISJUNCTION_OPERATORS.has(node.op)) {
57972
- const left = evaluateFilterCondition(node.left, metadataTypes, resolveRefs);
57973
- const right = evaluateFilterCondition(node.right, metadataTypes, resolveRefs);
57974
- if (left === true || right === true)
57975
- return true;
57976
- return left === void 0 || right === void 0 ? void 0 : false;
58003
+ function valuesEqual(a2, b) {
58004
+ if (a2.kind === "null" || b.kind === "null")
58005
+ return a2.kind === b.kind;
58006
+ if (a2.kind === "number" && b.kind === "number")
58007
+ return a2.value === b.value;
58008
+ if (a2.kind === "boolean" && b.kind === "boolean")
58009
+ return a2.value === b.value;
58010
+ if (a2.kind === "string" && b.kind === "string")
58011
+ return a2.value === b.value;
58012
+ return void 0;
58013
+ }
58014
+ function bothBool(a2, b, f) {
58015
+ if (a2.kind === "boolean" && b.kind === "boolean")
58016
+ return { kind: "boolean", value: f(a2.value, b.value) };
58017
+ return INCONCLUSIVE;
58018
+ }
58019
+ function memberNamed(node, name, seen = /* @__PURE__ */ new Set()) {
58020
+ if (!node || seen.has(node))
58021
+ return void 0;
58022
+ seen.add(node);
58023
+ for (const member of node.members ?? []) {
58024
+ if (member.value !== void 0 && declaresFeature(member, name))
58025
+ return member;
58026
+ }
58027
+ for (const member of node.members ?? []) {
58028
+ if (declaresFeature(member, name))
58029
+ return member;
58030
+ }
58031
+ const typeRef = node.typing?.type?.ref;
58032
+ return typeRef ? memberNamed(typeRef, name, seen) : void 0;
58033
+ }
58034
+ function resolveFeatureValue(root3, segments) {
58035
+ let cur = root3;
58036
+ for (const seg of segments) {
58037
+ cur = memberNamed(cur, seg);
58038
+ if (!cur)
58039
+ return UNRESOLVED;
58040
+ }
58041
+ if (cur.value)
58042
+ return evaluateExpr(cur.value, () => INCONCLUSIVE);
58043
+ return INCONCLUSIVE;
58044
+ }
58045
+ function subjectScope(subjectName, subjectBinding) {
58046
+ const binding = subjectBinding;
58047
+ return (segments) => {
58048
+ if (!binding)
58049
+ return INCONCLUSIVE;
58050
+ if (subjectName && segments[0] === subjectName) {
58051
+ const rest = segments.slice(1);
58052
+ if (rest.length === 0)
58053
+ return INCONCLUSIVE;
58054
+ return resolveFeatureValue(binding, rest);
58055
+ }
58056
+ return resolveFeatureValue(binding, segments);
58057
+ };
58058
+ }
58059
+ function subjectNameOf(req) {
58060
+ const subject = (req.members ?? []).find((m) => m.$type === "SubjectDecl");
58061
+ return subject?.name;
58062
+ }
58063
+ function gatherConstraints(req) {
58064
+ const out = [];
58065
+ for (const member of req.members ?? []) {
58066
+ if (member.$type === "RequireConstraintStmt" && member.body) {
58067
+ out.push({ kind: "require", body: member.body, text: exprText(member.body) });
58068
+ } else if (member.$type === "AssumeConstraintStmt" && member.body) {
58069
+ out.push({ kind: "assume", body: member.body, text: exprText(member.body) });
57977
58070
  }
58071
+ }
58072
+ return out;
58073
+ }
58074
+ function exprText(node) {
58075
+ return node.$cstNode?.text?.trim() ?? "";
58076
+ }
58077
+ function evaluateRequirement(req, subjectBinding) {
58078
+ const requirement = req;
58079
+ const subjectName = subjectNameOf(requirement);
58080
+ const scope = subjectScope(subjectName, subjectBinding);
58081
+ const constraints = gatherConstraints(requirement);
58082
+ const details = [];
58083
+ let sawInconclusive = false;
58084
+ let sawUnresolved = false;
58085
+ let failed = false;
58086
+ for (const c of constraints) {
58087
+ const v = evaluateExpr(c.body, scope);
58088
+ let status2;
58089
+ if (v.kind === "unresolved") {
58090
+ status2 = "unresolved";
58091
+ sawUnresolved = true;
58092
+ } else if (v.kind !== "boolean") {
58093
+ status2 = "inconclusive";
58094
+ sawInconclusive = true;
58095
+ } else if (v.value) {
58096
+ status2 = "pass";
58097
+ } else if (c.kind === "require") {
58098
+ status2 = "fail";
58099
+ failed = true;
58100
+ } else {
58101
+ status2 = "inconclusive";
58102
+ sawInconclusive = true;
58103
+ }
58104
+ details.push({ kind: c.kind, status: status2, text: c.text });
58105
+ }
58106
+ let status;
58107
+ if (constraints.length === 0)
58108
+ status = "inconclusive";
58109
+ else if (failed)
58110
+ status = "fail";
58111
+ else if (sawUnresolved)
58112
+ status = "unresolved";
58113
+ else if (sawInconclusive)
58114
+ status = "inconclusive";
58115
+ else
58116
+ status = "pass";
58117
+ return { status, details };
58118
+ }
58119
+ function bindingName(by) {
58120
+ const n = by;
58121
+ if (n?.$type !== "PathExpr")
57978
58122
  return void 0;
58123
+ return n.path?.split(/::|\./).pop();
58124
+ }
58125
+ function evaluateVerificationCase(caseNode, resolveRequirement, resolvePart) {
58126
+ const node = caseNode;
58127
+ const subject = (node.members ?? []).find((m) => m.$type === "SubjectDecl");
58128
+ const subjectBoundName = bindingName(subject?.value);
58129
+ const subjectBinding = (subjectBoundName ? resolvePart(subjectBoundName) : void 0) ?? subject;
58130
+ const verifies = [];
58131
+ for (const member of node.members ?? []) {
58132
+ if (member.$type !== "VerifyStmt")
58133
+ continue;
58134
+ const targetName = String(member.target ?? "").split(/::|\./).pop();
58135
+ if (!targetName)
58136
+ continue;
58137
+ const req = resolveRequirement(targetName);
58138
+ if (!req) {
58139
+ verifies.push({ requirement: targetName, status: "unresolved" });
58140
+ continue;
58141
+ }
58142
+ const boundName = bindingName(member.by);
58143
+ const binding = (boundName ? resolvePart(boundName) : void 0) ?? subjectBinding;
58144
+ verifies.push({ requirement: targetName, status: evaluateRequirement(req, binding).status });
57979
58145
  }
57980
- return void 0;
58146
+ let status = "inconclusive";
58147
+ if (verifies.length === 0)
58148
+ status = "inconclusive";
58149
+ else if (verifies.some((v) => v.status === "fail"))
58150
+ status = "fail";
58151
+ else if (verifies.some((v) => v.status === "unresolved"))
58152
+ status = "error";
58153
+ else if (verifies.some((v) => v.status === "inconclusive"))
58154
+ status = "inconclusive";
58155
+ else
58156
+ status = "pass";
58157
+ return { status, verifies };
57981
58158
  }
57982
- var CONJUNCTION_OPERATORS = /* @__PURE__ */ new Set(["and", "&"]);
57983
- var DISJUNCTION_OPERATORS = /* @__PURE__ */ new Set(["or", "|"]);
57984
- function undecidableFilterCondition(condition) {
58159
+
58160
+ // ../language-server/out/src/services/metadata-filter.js
58161
+ var INCONCLUSIVE2 = { kind: "inconclusive" };
58162
+ var SPECIALIZATION_KINDS = /* @__PURE__ */ new Set([":>", "specializes", ":>>", "redefines", "subsets"]);
58163
+ var MAX_SPECIALIZATION_DEPTH = 32;
58164
+ var MAX_VALUE_DEPTH = 16;
58165
+ function evaluateFilterCondition(condition, element, options) {
57985
58166
  if (!condition)
57986
58167
  return void 0;
57987
- if (isSelfClassifyExpr(condition)) {
57988
- return condition.op === "@" || condition.op === "@@" ? void 0 : { node: condition, construct: `the '${condition.op}' classification operator` };
58168
+ const ctx = {
58169
+ element,
58170
+ options,
58171
+ metadata: attachedMetadata(element)
58172
+ };
58173
+ const value = evaluateExpr(condition, nameScope(ctx), extensionFor(ctx));
58174
+ return value.kind === "boolean" ? value.value : void 0;
58175
+ }
58176
+ function extensionFor(ctx) {
58177
+ const ext = (node, evaluate2) => {
58178
+ switch (node.$type) {
58179
+ case "SelfClassifyExpr":
58180
+ return classify(node, ctx);
58181
+ case "LiteralNull":
58182
+ return NULL_VALUE;
58183
+ case "PostfixOp":
58184
+ return featureAccess(node, ctx, ext);
58185
+ default:
58186
+ return void 0;
58187
+ }
58188
+ };
58189
+ return ext;
58190
+ }
58191
+ function classify(node, ctx) {
58192
+ const op = node.op;
58193
+ if (op === "@" || op === "@@" || op === "as" || op === "meta") {
58194
+ const found = findMetadata(node.type, ctx);
58195
+ return found === "unknown" ? INCONCLUSIVE2 : { kind: "boolean", value: found !== void 0 };
57989
58196
  }
57990
- if (isNotExpr(condition) && condition.operand) {
57991
- return undecidableFilterCondition(condition.operand);
58197
+ if (op === "istype" || op === "hastype")
58198
+ return classifyByType(op, node.type, ctx);
58199
+ return INCONCLUSIVE2;
58200
+ }
58201
+ function featureAccess(node, ctx, ext) {
58202
+ const segments = [];
58203
+ let cur = node;
58204
+ while (cur?.$type === "PostfixOp") {
58205
+ const postfix = cur;
58206
+ if (!(postfix.dot || postfix.select) || !postfix.field)
58207
+ return void 0;
58208
+ segments.unshift(postfix.field);
58209
+ cur = postfix.target;
57992
58210
  }
57993
- if (condition.$type === "NotExpr")
58211
+ const root3 = unwrapParen(cur);
58212
+ const rootOp = root3?.op;
58213
+ if (root3?.$type !== "SelfClassifyExpr" || !rootOp)
57994
58214
  return void 0;
57995
- if (isParenExpr(condition)) {
57996
- return condition.items.length === 1 ? undecidableFilterCondition(condition.items[0]) : { node: condition, construct: "a parenthesized expression list" };
58215
+ if (rootOp !== "as" && rootOp !== "meta" && rootOp !== "@" && rootOp !== "@@")
58216
+ return void 0;
58217
+ const found = findMetadata(root3.type, ctx);
58218
+ if (found === "unknown")
58219
+ return INCONCLUSIVE2;
58220
+ if (found === void 0)
58221
+ return NULL_VALUE;
58222
+ if (!found.annotation)
58223
+ return INCONCLUSIVE2;
58224
+ return metadataFeatureValue(found.annotation, segments, ctx, ext);
58225
+ }
58226
+ function metadataFeatureValue(annotation, segments, ctx, ext, depth = 0) {
58227
+ if (segments.length === 0 || depth > MAX_VALUE_DEPTH)
58228
+ return INCONCLUSIVE2;
58229
+ const [head2, ...rest] = segments;
58230
+ const definition = typeNodeOf(annotation, ctx);
58231
+ const member = memberNamed2(annotation, head2, ctx) ?? memberNamed2(definition, head2, ctx);
58232
+ if (!member)
58233
+ return INCONCLUSIVE2;
58234
+ if (rest.length > 0)
58235
+ return metadataFeatureValue(member, rest, ctx, ext, depth + 1);
58236
+ if (member.value)
58237
+ return evaluateExpr(member.value, nameScope(ctx), ext);
58238
+ return NULL_VALUE;
58239
+ }
58240
+ function memberNamed2(owner, name, ctx, depth = 0) {
58241
+ if (!owner || depth > MAX_SPECIALIZATION_DEPTH)
58242
+ return void 0;
58243
+ const members = owner.members ?? [];
58244
+ for (const member of members) {
58245
+ if (member.value !== void 0 && declaresFeature2(member, name))
58246
+ return member;
57997
58247
  }
57998
- if (isBinExpr(condition)) {
57999
- if (CONJUNCTION_OPERATORS.has(condition.op) || DISJUNCTION_OPERATORS.has(condition.op)) {
58000
- return undecidableFilterCondition(condition.left) ?? undecidableFilterCondition(condition.right);
58001
- }
58002
- return { node: condition, construct: `the '${condition.op}' operator` };
58248
+ for (const member of members) {
58249
+ if (declaresFeature2(member, name))
58250
+ return member;
58003
58251
  }
58004
- return { node: condition, construct: describeFilterExpr(condition) };
58252
+ for (const target of specializationTargets(owner)) {
58253
+ const resolved = ctx.options.resolveName?.(target);
58254
+ const inherited = memberNamed2(resolved, name, ctx, depth + 1);
58255
+ if (inherited)
58256
+ return inherited;
58257
+ }
58258
+ const typed = typeNodeOf(owner, ctx);
58259
+ return typed ? memberNamed2(typed, name, ctx, depth + 1) : void 0;
58005
58260
  }
58006
- function describeFilterExpr(node) {
58007
- if (isPostfixOp(node)) {
58008
- if ((node.dot || node.select) && node.field)
58009
- return `the '.${node.field}' feature access`;
58010
- if (node.arrow && node.invoke)
58011
- return `the '->${node.invoke}' invocation`;
58012
- return "this postfix expression";
58261
+ function declaresFeature2(node, name) {
58262
+ if (node.name === name)
58263
+ return true;
58264
+ for (const rel of [...node.preRelationships ?? [], ...node.relationships ?? []]) {
58265
+ if (rel.kind && SPECIALIZATION_KINDS.has(rel.kind) && (rel.targets ?? []).includes(name))
58266
+ return true;
58013
58267
  }
58014
- if (isPathExpr(node))
58015
- return "a plain feature reference";
58016
- return "this expression form";
58268
+ return false;
58017
58269
  }
58018
- function attachedMetadataTypes(node, resolveRefs) {
58019
- const siblings = node.$container?.members;
58020
- if (!Array.isArray(siblings))
58021
- return [];
58022
- const index = siblings.indexOf(node);
58023
- if (index < 0)
58270
+ function attachedMetadata(node) {
58271
+ if (!node)
58024
58272
  return [];
58025
- const types = [];
58026
- for (let i = index - 1; i >= 0; i--) {
58027
- const sibling = siblings[i];
58028
- if (sibling.$type !== "MetadataAnnotation")
58029
- break;
58030
- types.push({ ref: resolveRefs ? sibling.type?.ref : void 0, qname: sibling.type?.$refText });
58273
+ const found = [];
58274
+ for (const member of node.members ?? []) {
58275
+ if (member.$type === "MetadataAnnotation")
58276
+ addMetadata(found, member, member.type);
58277
+ }
58278
+ const container = node.$container;
58279
+ if (container?.$type === "PrefixMetadataMember") {
58280
+ for (const tag of container.tags ?? [])
58281
+ addMetadata(found, void 0, tag.type);
58031
58282
  }
58032
- return types;
58283
+ found.push(...container ? annotationsByMember(container).get(node) ?? [] : []);
58284
+ return found;
58033
58285
  }
58034
- function metadataTypeMatches(type, metadataTypes, resolveRefs) {
58035
- const filterRef = resolveRefs ? type.ref : void 0;
58036
- const filterName = type.$refText;
58037
- return metadataTypes.some((meta) => {
58038
- if (filterRef && meta.ref)
58039
- return meta.ref === filterRef;
58040
- return qualifiedNameMatches(filterName, meta.qname);
58041
- });
58286
+ function addMetadata(found, annotation, type) {
58287
+ if (type)
58288
+ found.push({ annotation, type });
58289
+ }
58290
+ var annotationsByContainer = /* @__PURE__ */ new WeakMap();
58291
+ function annotationsByMember(container) {
58292
+ const cached = annotationsByContainer.get(container);
58293
+ if (cached)
58294
+ return cached;
58295
+ const byMember = /* @__PURE__ */ new Map();
58296
+ const byName = /* @__PURE__ */ new Map();
58297
+ const attach = (member, entry) => {
58298
+ const list = byMember.get(member);
58299
+ if (list)
58300
+ list.push(entry);
58301
+ else
58302
+ byMember.set(member, [entry]);
58303
+ };
58304
+ const members = container.members ?? [];
58305
+ let pending = [];
58306
+ for (const member of members) {
58307
+ if (member.$type === "MetadataAnnotation" || member.$type === "MetadataDecl") {
58308
+ const type = member.$type === "MetadataAnnotation" ? member.type : member.typing?.type;
58309
+ if (!type)
58310
+ continue;
58311
+ const entry = { annotation: member, type };
58312
+ const targets = member.targets ?? [];
58313
+ if (targets.length > 0) {
58314
+ for (const target of targets) {
58315
+ const simple = target.split(/::|\./).pop();
58316
+ if (!simple)
58317
+ continue;
58318
+ const list = byName.get(simple);
58319
+ if (list)
58320
+ list.push(entry);
58321
+ else
58322
+ byName.set(simple, [entry]);
58323
+ }
58324
+ } else if (member.$type === "MetadataAnnotation") {
58325
+ pending.push(entry);
58326
+ }
58327
+ continue;
58328
+ }
58329
+ for (const entry of pending)
58330
+ attach(member, entry);
58331
+ pending = [];
58332
+ }
58333
+ if (byName.size > 0) {
58334
+ for (const member of members) {
58335
+ const entries = member.name ? byName.get(member.name) : void 0;
58336
+ if (entries)
58337
+ for (const entry of entries)
58338
+ attach(member, entry);
58339
+ }
58340
+ }
58341
+ annotationsByContainer.set(container, byMember);
58342
+ return byMember;
58343
+ }
58344
+ function findMetadata(type, ctx) {
58345
+ if (!type)
58346
+ return "unknown";
58347
+ for (const meta of ctx.metadata) {
58348
+ if (metadataMatches(type, meta, ctx))
58349
+ return meta;
58350
+ }
58351
+ if (metaclassMatches(type, ctx))
58352
+ return { type };
58353
+ return ctx.element ? void 0 : "unknown";
58354
+ }
58355
+ function metadataMatches(type, meta, ctx) {
58356
+ const filterRef = ctx.options.resolveReferences ? type.ref : void 0;
58357
+ const metaRef = ctx.options.resolveReferences ? meta.type.ref : void 0;
58358
+ if (filterRef && metaRef && filterRef === metaRef)
58359
+ return true;
58360
+ const metaName = meta.type.$refText;
58361
+ if (qualifiedNameMatches(type.$refText, metaName))
58362
+ return true;
58363
+ const metaDefinition = metaRef ?? (metaName ? ctx.options.resolveName?.(metaName) : void 0);
58364
+ return specializes(metaDefinition, type, ctx);
58365
+ }
58366
+ function specializes(node, type, ctx, depth = 0, seen = /* @__PURE__ */ new Set()) {
58367
+ if (!node || depth > MAX_SPECIALIZATION_DEPTH || seen.has(node))
58368
+ return false;
58369
+ seen.add(node);
58370
+ for (const target of specializationTargets(node)) {
58371
+ if (qualifiedNameMatches(type.$refText, target))
58372
+ return true;
58373
+ const resolved = ctx.options.resolveName?.(target);
58374
+ if (resolved && ctx.options.resolveReferences && resolved === type.ref)
58375
+ return true;
58376
+ if (specializes(resolved, type, ctx, depth + 1, seen))
58377
+ return true;
58378
+ }
58379
+ return false;
58380
+ }
58381
+ function metaclassMatches(type, ctx) {
58382
+ if (!ctx.element)
58383
+ return false;
58384
+ const metaclass = metaclassNameOf(ctx.element);
58385
+ const written = type.$refText;
58386
+ if (!written)
58387
+ return false;
58388
+ if (qualifiedNameMatches(written, metaclass))
58389
+ return true;
58390
+ const definition = ctx.options.resolveName?.(`SysML::${metaclass}`) ?? ctx.options.resolveName?.(metaclass);
58391
+ return specializes(definition, type, ctx);
58392
+ }
58393
+ function metaclassNameOf(node) {
58394
+ if (isPackage(node))
58395
+ return "Package";
58396
+ const type = node.$type.endsWith("Decl") ? node.$type.slice(0, -"Decl".length) : node.$type;
58397
+ const isDef = node.isDef;
58398
+ if (typeof isDef === "boolean")
58399
+ return `${type}${isDef ? "Definition" : "Usage"}`;
58400
+ return type;
58401
+ }
58402
+ function classifyByType(op, type, ctx) {
58403
+ if (!type || !ctx.element)
58404
+ return INCONCLUSIVE2;
58405
+ const declared = ctx.element.typing?.type;
58406
+ if (!declared)
58407
+ return INCONCLUSIVE2;
58408
+ if (qualifiedNameMatches(type.$refText, declared.$refText))
58409
+ return { kind: "boolean", value: true };
58410
+ if (ctx.options.resolveReferences && type.ref && declared.ref === type.ref)
58411
+ return { kind: "boolean", value: true };
58412
+ if (op === "hastype")
58413
+ return { kind: "boolean", value: false };
58414
+ const declaredNode = (ctx.options.resolveReferences ? declared.ref : void 0) ?? (declared.$refText ? ctx.options.resolveName?.(declared.$refText) : void 0);
58415
+ if (!declaredNode)
58416
+ return INCONCLUSIVE2;
58417
+ return { kind: "boolean", value: specializes(declaredNode, type, ctx) };
58418
+ }
58419
+ function nameScope(ctx, depth = 0) {
58420
+ return (segments) => {
58421
+ if (depth > MAX_VALUE_DEPTH)
58422
+ return INCONCLUSIVE2;
58423
+ const resolved = ctx.options.resolveName?.(segments.join("::"));
58424
+ if (!resolved?.value)
58425
+ return INCONCLUSIVE2;
58426
+ return evaluateExpr(resolved.value, nameScope(ctx, depth + 1), extensionFor(ctx));
58427
+ };
58428
+ }
58429
+ function specializationTargets(node) {
58430
+ const targets = [];
58431
+ for (const rel of [...node.preRelationships ?? [], ...node.relationships ?? []]) {
58432
+ if (rel.kind && SPECIALIZATION_KINDS.has(rel.kind))
58433
+ targets.push(...rel.targets ?? []);
58434
+ }
58435
+ return targets;
58436
+ }
58437
+ function typeNodeOf(node, ctx) {
58438
+ const type = node?.type ?? node?.typing?.type;
58439
+ if (!type)
58440
+ return void 0;
58441
+ const ref = ctx.options.resolveReferences ? type.ref : void 0;
58442
+ return ref ?? (type.$refText ? ctx.options.resolveName?.(type.$refText) : void 0);
58443
+ }
58444
+ function unwrapParen(node) {
58445
+ let cur = node;
58446
+ while (cur?.$type === "ParenExpr") {
58447
+ const items = cur.items ?? [];
58448
+ if (items.length !== 1)
58449
+ return cur;
58450
+ cur = items[0];
58451
+ }
58452
+ return cur;
58042
58453
  }
58043
58454
  function qualifiedNameMatches(a2, b) {
58044
58455
  if (!a2 || !b)
@@ -58054,32 +58465,253 @@ function qualifiedNameMatches(a2, b) {
58054
58465
  }
58055
58466
  return true;
58056
58467
  }
58057
- function resolveImportedDescription(path10, globalDescriptions, options, visitedNamespaces) {
58058
- const direct = globalDescriptions.firstNamed(path10);
58059
- if (direct)
58060
- return direct;
58061
- const split = path10.lastIndexOf("::");
58062
- if (split < 0)
58063
- return void 0;
58064
- const ownerPath = path10.slice(0, split);
58065
- const simpleName2 = path10.slice(split + 2);
58066
- const exported = [];
58067
- expandNamespaceImports(ownerPath, globalDescriptions, exported, options, visitedNamespaces);
58068
- return exported.find((entry) => entry.name === simpleName2)?.description;
58069
- }
58070
- function expandNamespaceMembers(path10, wildcard, globalDescriptions, out) {
58071
- const prefixLength = path10.length + 2;
58072
- for (const desc of globalDescriptions.membersOf(path10, wildcard)) {
58073
- if (isPrivateDescription(desc))
58074
- continue;
58075
- const rest = desc.name.slice(prefixLength);
58076
- const simple = rest.includes("::") ? rest.slice(rest.lastIndexOf("::") + 2) : rest;
58077
- out.push({ name: simple, targetName: desc.name, description: desc });
58078
- }
58079
- }
58080
- function expandNamespaceImports(path10, globalDescriptions, out, options, visitedNamespaces) {
58081
- for (const namespaceDesc of globalDescriptions.named(path10)) {
58082
- const key = descriptionKey(namespaceDesc);
58468
+
58469
+ // ../language-server/out/src/services/import-visibility.js
58470
+ var GlobalDescriptionIndex = class _GlobalDescriptionIndex {
58471
+ /** Reuse an existing index; wrap a plain list. */
58472
+ static from(source) {
58473
+ return source instanceof _GlobalDescriptionIndex ? source : new _GlobalDescriptionIndex(source);
58474
+ }
58475
+ /** Exact name → descriptions carrying it (qualified and simple names alike). */
58476
+ byName = /* @__PURE__ */ new Map();
58477
+ /** Namespace path → descriptions for its DIRECT members (`A::B` → `A::B::C`). */
58478
+ directMembers = /* @__PURE__ */ new Map();
58479
+ /** Namespace path → descriptions for all its descendants (`A` `A::B::C`). */
58480
+ nestedMembers = /* @__PURE__ */ new Map();
58481
+ constructor(descriptions) {
58482
+ for (const desc of descriptions) {
58483
+ push(this.byName, desc.name, desc);
58484
+ let sep2 = desc.name.indexOf("::");
58485
+ while (sep2 >= 0) {
58486
+ const prefix = desc.name.slice(0, sep2);
58487
+ push(this.nestedMembers, prefix, desc);
58488
+ const next = desc.name.indexOf("::", sep2 + 2);
58489
+ if (next < 0)
58490
+ push(this.directMembers, prefix, desc);
58491
+ sep2 = next;
58492
+ }
58493
+ }
58494
+ }
58495
+ named(name) {
58496
+ return this.byName.get(name) ?? EMPTY_DESCRIPTIONS;
58497
+ }
58498
+ firstNamed(name) {
58499
+ return this.byName.get(name)?.[0];
58500
+ }
58501
+ membersOf(path10, wildcard) {
58502
+ const map3 = wildcard === "shallow" ? this.directMembers : this.nestedMembers;
58503
+ return map3.get(path10) ?? EMPTY_DESCRIPTIONS;
58504
+ }
58505
+ };
58506
+ var EMPTY_DESCRIPTIONS = [];
58507
+ function push(map3, key, desc) {
58508
+ const list = map3.get(key);
58509
+ if (list)
58510
+ list.push(desc);
58511
+ else
58512
+ map3.set(key, [desc]);
58513
+ }
58514
+ function expandImportEntries(imp, globalDescriptions, options = {}) {
58515
+ const out = [];
58516
+ expandImportInto(imp, GlobalDescriptionIndex.from(globalDescriptions), out, options, /* @__PURE__ */ new Set());
58517
+ return dedupeEntries(out);
58518
+ }
58519
+ function importedPath(imp) {
58520
+ const segments = [imp.head];
58521
+ for (const seg of imp.segs) {
58522
+ if (seg.name)
58523
+ segments.push(seg.name);
58524
+ }
58525
+ return segments.length > 0 ? segments.join("::") : void 0;
58526
+ }
58527
+ function importForm(imp) {
58528
+ let wildcard = "none";
58529
+ let includesSelf = false;
58530
+ const importAll = imp.isImportAll === true;
58531
+ for (const seg of imp.segs) {
58532
+ if (seg.recursive) {
58533
+ wildcard = "recursive";
58534
+ includesSelf = !seg.star;
58535
+ } else if (seg.star) {
58536
+ wildcard = "shallow";
58537
+ includesSelf = false;
58538
+ }
58539
+ }
58540
+ return { wildcard, includesSelf, importAll };
58541
+ }
58542
+ function importWildcard(imp) {
58543
+ return importForm(imp).wildcard;
58544
+ }
58545
+ function importVisibility(imp) {
58546
+ return imp.visibility ?? "private";
58547
+ }
58548
+ function resolveDescription(name, globalDescriptions) {
58549
+ const index = GlobalDescriptionIndex.from(globalDescriptions);
58550
+ const normalized = name.trim();
58551
+ const direct = index.firstNamed(normalized);
58552
+ if (direct)
58553
+ return direct;
58554
+ const simple = normalized.split(/::|\./).pop();
58555
+ return simple ? index.firstNamed(simple) : void 0;
58556
+ }
58557
+ function descriptionKey(description) {
58558
+ return `${description.documentUri.toString()}#${description.path}`;
58559
+ }
58560
+ function namespaceMembers(node) {
58561
+ const n = node;
58562
+ return [...n?.elements ?? [], ...n?.members ?? []];
58563
+ }
58564
+ function expandImportInto(imp, globalDescriptions, out, options, visitedNamespaces) {
58565
+ const path10 = importedPath(imp);
58566
+ if (!path10)
58567
+ return;
58568
+ const start = out.length;
58569
+ const namedSegments = path10.split("::");
58570
+ const form = importForm(imp);
58571
+ if (form.wildcard === "none") {
58572
+ const targetDesc = resolveImportedDescription(path10, globalDescriptions, options, visitedNamespaces, form.importAll);
58573
+ if (targetDesc) {
58574
+ const alias = imp.alias ?? namedSegments[namedSegments.length - 1];
58575
+ if (alias)
58576
+ out.push({ name: alias, targetName: targetDesc.name, description: targetDesc });
58577
+ }
58578
+ } else {
58579
+ out.push(...selectMemberships(path10, form, globalDescriptions));
58580
+ expandNamespaceImports(path10, globalDescriptions, out, options, visitedNamespaces, form.importAll);
58581
+ }
58582
+ applyImportFilters(imp, out, start, options);
58583
+ }
58584
+ function applyImportFilters(imp, out, start, options) {
58585
+ const conditions = filterConditionsFor(imp);
58586
+ if (conditions.length === 0 || out.length === start)
58587
+ return;
58588
+ const kept = keepMatching(conditions, out.slice(start), options);
58589
+ out.length = start;
58590
+ out.push(...kept);
58591
+ }
58592
+ function applyFilters(imp, entries, options = {}) {
58593
+ const conditions = filterConditionsFor(imp);
58594
+ return conditions.length === 0 ? entries : keepMatching(conditions, entries, options);
58595
+ }
58596
+ function keepMatching(conditions, entries, options) {
58597
+ const evalOptions = {
58598
+ resolveReferences: options.resolveReferences !== false,
58599
+ resolveName: options.resolveName
58600
+ };
58601
+ return entries.filter((entry) => {
58602
+ const node = options.nodeOf?.(entry.description) ?? entry.description.node;
58603
+ return !node || conditions.every((c) => evaluateFilterCondition(c, node, evalOptions) !== false);
58604
+ });
58605
+ }
58606
+ function filterConditionsFor(imp) {
58607
+ const conditions = [];
58608
+ const owner = imp.$container;
58609
+ if (governsImportFilters(owner)) {
58610
+ for (const member of namespaceMembers(owner)) {
58611
+ const condition = member.condition;
58612
+ if (member.$type === "FilterMember" && condition)
58613
+ conditions.push(condition);
58614
+ }
58615
+ }
58616
+ for (const filter3 of imp.filters ?? []) {
58617
+ if (filter3.condition)
58618
+ conditions.push(filter3.condition);
58619
+ }
58620
+ return conditions;
58621
+ }
58622
+ function governsImportFilters(owner) {
58623
+ return !!owner && (isPackage(owner) || owner.$type === "Document");
58624
+ }
58625
+ function undecidableFilterCondition(condition, resolveName) {
58626
+ if (!condition)
58627
+ return void 0;
58628
+ if (isSelfClassifyExpr(condition))
58629
+ return void 0;
58630
+ if (isNotExpr(condition) && condition.operand) {
58631
+ return undecidableFilterCondition(condition.operand, resolveName);
58632
+ }
58633
+ if (condition.$type === "NotExpr")
58634
+ return void 0;
58635
+ if (isParenExpr(condition)) {
58636
+ return condition.items.length === 1 ? undecidableFilterCondition(condition.items[0], resolveName) : { node: condition, construct: "a parenthesized expression list" };
58637
+ }
58638
+ if (isBinExpr(condition)) {
58639
+ return undecidableFilterCondition(condition.left, resolveName) ?? undecidableFilterCondition(condition.right, resolveName);
58640
+ }
58641
+ if (isPostfixOp(condition)) {
58642
+ if ((condition.dot || condition.select) && condition.field) {
58643
+ return undecidableFilterCondition(condition.target, resolveName);
58644
+ }
58645
+ if (condition.arrow && condition.invoke)
58646
+ return { node: condition, construct: `the '->${condition.invoke}' invocation` };
58647
+ return { node: condition, construct: "this postfix expression" };
58648
+ }
58649
+ if (isPathExpr(condition)) {
58650
+ const target = resolveName?.(condition.path);
58651
+ return target?.value !== void 0 ? void 0 : { node: condition, construct: "a plain feature reference" };
58652
+ }
58653
+ if (condition.$type === "IfExpr") {
58654
+ const conditional = condition;
58655
+ return undecidableFilterCondition(conditional.cond, resolveName) ?? undecidableFilterCondition(conditional.thenExpr, resolveName) ?? undecidableFilterCondition(conditional.elseExpr, resolveName);
58656
+ }
58657
+ if (DECIDABLE_LITERAL_TYPES.has(condition.$type))
58658
+ return void 0;
58659
+ return { node: condition, construct: "this expression form" };
58660
+ }
58661
+ var DECIDABLE_LITERAL_TYPES = /* @__PURE__ */ new Set([
58662
+ "NumericPrimary",
58663
+ "LiteralBool",
58664
+ "LiteralStr",
58665
+ "LiteralNull"
58666
+ ]);
58667
+ function resolveImportedDescription(path10, globalDescriptions, options, visitedNamespaces, importAll = false) {
58668
+ const direct = globalDescriptions.firstNamed(path10);
58669
+ if (direct)
58670
+ return direct;
58671
+ const split = path10.lastIndexOf("::");
58672
+ if (split < 0)
58673
+ return void 0;
58674
+ const ownerPath = path10.slice(0, split);
58675
+ const simpleName2 = path10.slice(split + 2);
58676
+ const exported = [];
58677
+ expandNamespaceImports(ownerPath, globalDescriptions, exported, options, visitedNamespaces, importAll);
58678
+ return exported.find((entry) => entry.name === simpleName2)?.description;
58679
+ }
58680
+ function selectMemberships(path10, form, globalDescriptions) {
58681
+ if (form.wildcard === "none")
58682
+ return [];
58683
+ const index = GlobalDescriptionIndex.from(globalDescriptions);
58684
+ const entries = [];
58685
+ if (form.includesSelf) {
58686
+ const simple = simpleNameOf(path10);
58687
+ const self2 = index.named(path10).find((desc) => form.importAll || !isPrivateDescription(desc));
58688
+ if (self2)
58689
+ entries.push({ name: simple, targetName: self2.name, description: self2 });
58690
+ }
58691
+ const prefixLength = path10.length + 2;
58692
+ for (const desc of index.membersOf(path10, form.wildcard)) {
58693
+ if (!form.importAll && isPrivateDescription(desc))
58694
+ continue;
58695
+ const rest = desc.name.slice(prefixLength);
58696
+ if (!rest)
58697
+ continue;
58698
+ const nested = rest.includes("::");
58699
+ if (nested && !isOwnedMembership(desc))
58700
+ continue;
58701
+ entries.push({ name: nested ? rest.slice(rest.lastIndexOf("::") + 2) : rest, targetName: desc.name, description: desc });
58702
+ }
58703
+ return entries;
58704
+ }
58705
+ function simpleNameOf(path10) {
58706
+ return path10.includes("::") ? path10.slice(path10.lastIndexOf("::") + 2) : path10;
58707
+ }
58708
+ function isOwnedMembership(desc) {
58709
+ const kind = desc.derivedKind;
58710
+ return kind !== "reexport" && kind !== "inherited";
58711
+ }
58712
+ function expandNamespaceImports(path10, globalDescriptions, out, options, visitedNamespaces, importAll = false) {
58713
+ for (const namespaceDesc of globalDescriptions.named(path10)) {
58714
+ const key = descriptionKey(namespaceDesc);
58083
58715
  if (visitedNamespaces.has(key))
58084
58716
  continue;
58085
58717
  visitedNamespaces.add(key);
@@ -58087,11 +58719,13 @@ function expandNamespaceImports(path10, globalDescriptions, out, options, visite
58087
58719
  for (const member of namespaceMembers(owner)) {
58088
58720
  if (!isImport(member))
58089
58721
  continue;
58090
- const visibility = importVisibility(member);
58091
- if (visibility === "private")
58092
- continue;
58093
- if (visibility === "protected" && !options.protectedNamespaceKeys?.has(key))
58094
- continue;
58722
+ if (!importAll) {
58723
+ const visibility = importVisibility(member);
58724
+ if (visibility === "private")
58725
+ continue;
58726
+ if (visibility === "protected" && !options.protectedNamespaceKeys?.has(key))
58727
+ continue;
58728
+ }
58095
58729
  expandImportInto(member, globalDescriptions, out, options, visitedNamespaces);
58096
58730
  }
58097
58731
  }
@@ -58505,11 +59139,11 @@ function evaluate(node, mode, ctx) {
58505
59139
  return { kind: "unknown" };
58506
59140
  }
58507
59141
  if (isBinExpr(node)) {
58508
- return evaluateBin(node, mode, ctx);
59142
+ return evaluateBin2(node, mode, ctx);
58509
59143
  }
58510
59144
  return { kind: "unknown" };
58511
59145
  }
58512
- function evaluateBin(node, mode, ctx) {
59146
+ function evaluateBin2(node, mode, ctx) {
58513
59147
  const op = node.op;
58514
59148
  const left = evaluate(node.left, mode, ctx);
58515
59149
  const right = evaluate(node.right, mode, ctx);
@@ -58649,6 +59283,18 @@ var DIAGNOSTIC_MESSAGES = {
58649
59283
  // `first a then b;` and the `then` occurrence shorthand in a part), so the
58650
59284
  // message names the construct it means rather than "action language".
58651
59285
  SEM011_ACTION_ONLY_CONSTRUCT: (construct, clause, owner) => `${construct} may only be declared in the body of an action definition or usage (OMG SysML v2 Part 1 \xA7${clause}), not in ${owner}.`,
59286
+ // REQ-392 — issue #150. A `rep … language "sysml"` body is a legal representation
59287
+ // of the element it annotates (OMG KerML §7.4.3), so the two faults are "this is
59288
+ // not SysML" and "this is not THIS element". The parser's own wording is carried
59289
+ // through verbatim, because it names the token the reader has to go and fix.
59290
+ SYN076_EMBEDDED_REPRESENTATION_SYNTAX: (language, detail) => `This representation declares language "${language}", so its body must be valid ${language}: ${detail}`,
59291
+ SEM012_REPRESENTATION_WRONG_KIND: (expected, actual) => `A textual representation must represent the element it annotates. This body represents '${actual}', but it annotates '${expected}'.`,
59292
+ // REQ-392 — The body is resolved in the represented element's own context, so an
59293
+ // unresolvable name there is the same defect it would be in ordinary code. It is
59294
+ // reported under its own code so a team can tune representations separately.
59295
+ RES020_REPRESENTATION_UNRESOLVED: (name, language) => `'${name}' cannot be resolved from here, so this ${language} representation is not a valid representation of the element it annotates.`,
59296
+ RES020_REPRESENTATION_PATH_SEGMENT: (segment, owner, language) => `Feature path segment '${segment}' does not exist on '${owner}', so this ${language} representation is not a valid representation of the element it annotates.`,
59297
+ SEM012_REPRESENTATION_WRONG_NAME: (expected, actual) => `A textual representation must represent the element it annotates. This body represents '${actual}', but it annotates '${expected}'.`,
58652
59298
  RES016_LIBRARY_SHADOWING: (name) => `'${name}' shadows a standard-library element of the same name; the library symbol is hidden in this scope.`,
58653
59299
  // issue #183 — KerML namespace distinguishability (validateNamespaceDistinguishability).
58654
59300
  // Owned siblings sharing a name/short name (or an alias clashing with an owned
@@ -58658,13 +59304,26 @@ var DIAGNOSTIC_MESSAGES = {
58658
59304
  // implicit-redefinition resolution this validator does not yet model.
58659
59305
  RES017_DUPLICATE_MEMBER: (name) => `'${name}' is already declared in this namespace. Members must be distinguishable by name \u2014 rename or remove the duplicate.`,
58660
59306
  RES017_DUPLICATE_SHORT_NAME: (name) => `Short name '<${name}>' is already used in this namespace. Members must be distinguishable \u2014 rename the short name.`,
58661
- // issue #102 — REQ-387. The filter evaluator (`import-visibility.ts`,
58662
- // `evaluateFilterCondition`) decides metadata-presence tests and the Boolean
58663
- // operators over them; every other form fails OPEN, keeping the member. Failing
58664
- // open is the right default — under-importing would manufacture spurious
58665
- // RES001s — but an unevaluated filter produces a scope or view that looks
58666
- // authoritative and is not, so the fail-open is stated rather than assumed.
58667
- RES018_UNEVALUATED_FILTER: (subject, construct) => `${subject} filter is not evaluated: ${construct} is outside the metadata-filter evaluator, which decides '@'/'@@' metadata tests combined with 'not', 'and'/'&', and 'or'/'|'. The filter fails open \u2014 it is treated as pass-through and removes nothing.`,
59307
+ // issue #102 — REQ-387. The filter evaluator (`metadata-filter.ts`,
59308
+ // `evaluateFilterCondition`) decides the model-level predicate surface; the
59309
+ // invocation and collection forms outside it fail OPEN, keeping the member.
59310
+ // Failing open is the right default — under-importing would manufacture
59311
+ // spurious RES001s — but an unevaluated filter produces a scope or view that
59312
+ // looks authoritative and is not, so the fail-open is stated, not assumed.
59313
+ RES018_UNEVALUATED_FILTER: (subject, construct) => `${subject} filter is not evaluated: ${construct} is outside the metadata-filter evaluator, which decides metadata tests, the classification operators, metadata feature access, and the Boolean, comparison and arithmetic operators over them. The filter fails open \u2014 it is treated as pass-through and removes nothing.`,
59314
+ // issue #154 — OMG SysML v2 Part 1 §7.5.5 (Root Namespace). The root
59315
+ // namespace of a file is anonymous and unnamed, so nothing can import it:
59316
+ // a `public` or `protected` import owned directly by it claims a re-export
59317
+ // no other namespace is able to consume. The Release BNF requires `private`
59318
+ // there, and rewriting it is mechanical — the import keeps working exactly
59319
+ // as it did, since a root import was never re-exported to begin with.
59320
+ RES021_ROOT_IMPORT_VISIBILITY: (visibility) => `An import in a file's root namespace must be 'private' \u2014 nothing can import the root namespace, so '${visibility}' re-exports to no one.`,
59321
+ // issue #153 — OMG SysML v2 Part 1 §7.5.4 (Filtered Packages) puts an element
59322
+ // filter in a package, where it restricts that package's imported memberships;
59323
+ // a view body is the one other place it is defined for (it restricts what the
59324
+ // view exposes). Anywhere else the member parses but nothing consumes it, so
59325
+ // it silently does nothing.
59326
+ KSM012_FILTER_PLACEMENT: (owner) => `A 'filter' member is only meaningful in a package or a view \u2014 it has no effect in a ${owner} body.`,
58668
59327
  // REQ-389 — Namespace qualification versus feature chaining in every written path
58669
59328
  // issue #213 — the KerML textual BNF binds `::` tighter than `.`: each
58670
59329
  // dot-separated link of a FeatureChain is a complete QualifiedName, and only
@@ -58911,7 +59570,7 @@ function commentBody(text) {
58911
59570
  return text.slice(2, -2);
58912
59571
  return void 0;
58913
59572
  }
58914
- function classify(text) {
59573
+ function classify2(text) {
58915
59574
  const body = commentBody(text);
58916
59575
  if (body === void 0)
58917
59576
  return void 0;
@@ -58966,7 +59625,7 @@ function scanFormatDirectives(document) {
58966
59625
  const leaf = leaves[index];
58967
59626
  if (!leaf.hidden)
58968
59627
  continue;
58969
- const classified = classify(leaf.text);
59628
+ const classified = classify2(leaf.text);
58970
59629
  if (!classified)
58971
59630
  continue;
58972
59631
  const comment = { offset: leaf.offset, end: leaf.end };
@@ -59067,6 +59726,8 @@ var SysmlIndexManager = class extends DefaultIndexManager {
59067
59726
  // REQ-068 — preserve declared visibility for wildcard re-export.
59068
59727
  ...symbol.isPrivate ? { isPrivate: true } : {},
59069
59728
  ...symbol.visibility ? { visibility: symbol.visibility } : {},
59729
+ // issue #152 — a re-exported alias is not owned nesting.
59730
+ ...symbol.derivedKind ? { derivedKind: symbol.derivedKind } : {},
59070
59731
  // REQ-242 — issue #103 — keeps type completion to definitions.
59071
59732
  ...symbol.isUsage ? { isUsage: true } : {}
59072
59733
  };
@@ -59142,7 +59803,7 @@ function encodeUnrestrictedName(value) {
59142
59803
  }
59143
59804
 
59144
59805
  // ../language-server/out/src/services/feature-path-resolver.js
59145
- var SPECIALIZATION_KINDS = /* @__PURE__ */ new Set([":>", ":>>", "specializes", "subsets", "redefines"]);
59806
+ var SPECIALIZATION_KINDS2 = /* @__PURE__ */ new Set([":>", ":>>", "specializes", "subsets", "redefines"]);
59146
59807
  function nameOf(node) {
59147
59808
  const name = node?.name;
59148
59809
  if (typeof name === "string" && name.length > 0)
@@ -59455,7 +60116,7 @@ var FeaturePathResolver = class {
59455
60116
  const relNode = node;
59456
60117
  const result = [];
59457
60118
  for (const relation of [...relNode.preRelationships ?? [], ...relNode.relationships ?? []]) {
59458
- if (!relation.kind || !SPECIALIZATION_KINDS.has(relation.kind))
60119
+ if (!relation.kind || !SPECIALIZATION_KINDS2.has(relation.kind))
59459
60120
  continue;
59460
60121
  for (const target of relation.targets ?? []) {
59461
60122
  const description = this.pickDescription(snapshot.byName.get(target)) ?? this.pickDescription(snapshot.byName.get(lastSegment2(target)));
@@ -59481,7 +60142,7 @@ var FeaturePathResolver = class {
59481
60142
  const candidates = refText ? snapshot.byName.get(refText) ?? snapshot.byName.get(lastSegment2(refText)) : void 0;
59482
60143
  return candidates?.length === 1;
59483
60144
  }
59484
- const semanticRelationships = [...record.preRelationships ?? [], ...record.relationships ?? []].filter((relation) => relation.kind && SPECIALIZATION_KINDS.has(relation.kind));
60145
+ const semanticRelationships = [...record.preRelationships ?? [], ...record.relationships ?? []].filter((relation) => relation.kind && SPECIALIZATION_KINDS2.has(relation.kind));
59485
60146
  return semanticRelationships.length > 0 && semanticRelationships.every((relation) => (relation.targets ?? []).every((target) => Boolean(this.nodeOf(this.pickDescription(snapshot.byName.get(target))) ?? this.nodeOf(this.pickDescription(snapshot.byName.get(lastSegment2(target)))))));
59486
60147
  }
59487
60148
  followAlias(target, snapshot) {
@@ -59596,84 +60257,352 @@ function isNamespaceOnlyDecl(node) {
59596
60257
  return node.isDef === true;
59597
60258
  }
59598
60259
 
59599
- // ../language-server/out/src/services/conformance.js
59600
- var SPECIALIZATION_KINDS2 = /* @__PURE__ */ new Set([
59601
- ":>",
59602
- ":>>",
59603
- "specializes",
59604
- "subsets",
59605
- "redefines"
59606
- ]);
59607
- var COMPOSITION_KINDS = /* @__PURE__ */ new Set(["unions", "intersects", "differences"]);
59608
- var MAX_CLOSURE_DEPTH = 32;
59609
- function simpleTypeName(name) {
59610
- const last2 = name.trim().split(/::|\./u).pop() ?? name.trim();
59611
- return last2.replace(/^'(.*)'$/u, "$1");
60260
+ // ../language-server/out/src/services/comment-body.js
60261
+ function sourceOf(node) {
60262
+ return node.$cstNode?.root.fullText;
59612
60263
  }
59613
- function declaredTypesOf(node) {
59614
- const decl = node;
59615
- const out = [];
59616
- for (const typing of [decl.typing, ...decl.moreTypings ?? []]) {
59617
- if (!typing)
59618
- continue;
59619
- const conjugated = typing.conjugate === true;
59620
- for (const ref of [typing.type, ...typing.moreTypes ?? []]) {
59621
- const text = ref?.$refText?.trim();
59622
- if (text)
59623
- out.push({ text, simple: simpleTypeName(text), conjugated });
59624
- }
60264
+ function cleanBlockBodyLines(raw, rawOffset) {
60265
+ let cut = raw.length - raw.trimStart().length;
60266
+ let body = raw.slice(cut).trimEnd();
60267
+ if (body.startsWith("/*")) {
60268
+ body = body.slice(2);
60269
+ cut += 2;
59625
60270
  }
59626
- return out;
59627
- }
59628
- function specializedNamesOf(node) {
59629
- const decl = node;
59630
- const out = [];
59631
- for (const rel of [...decl.preRelationships ?? [], ...decl.relationships ?? []]) {
59632
- if (!rel.kind || !SPECIALIZATION_KINDS2.has(rel.kind))
59633
- continue;
59634
- for (const target of rel.targets ?? []) {
59635
- const text = target.trim();
59636
- if (text)
59637
- out.push(text);
59638
- }
60271
+ if (body.endsWith("*/"))
60272
+ body = body.slice(0, -2);
60273
+ const lines = [];
60274
+ let cursor = cut;
60275
+ for (const rawLine of body.split("\n")) {
60276
+ const gutter = /^\s*\*+ ?/u.exec(rawLine);
60277
+ const skip = gutter ? gutter[0].length : 0;
60278
+ lines.push({
60279
+ text: rawLine.slice(skip).replace(/\s+$/u, ""),
60280
+ offset: rawOffset + cursor + skip
60281
+ });
60282
+ cursor += rawLine.length + 1;
59639
60283
  }
59640
- return out;
59641
- }
59642
- function compositionGroupsOf(node) {
59643
- const decl = node;
59644
- const out = [];
59645
- for (const rel of [...decl.preRelationships ?? [], ...decl.relationships ?? []]) {
59646
- if (!rel.kind || !COMPOSITION_KINDS.has(rel.kind))
59647
- continue;
59648
- const targets = (rel.targets ?? []).map((t) => t.trim()).filter((t) => t.length > 0);
59649
- if (targets.length > 0)
59650
- out.push({ kind: rel.kind, targets });
60284
+ while (lines.length > 0 && lines[0].text.trim() === "")
60285
+ lines.shift();
60286
+ while (lines.length > 0 && lines[lines.length - 1].text.trim() === "")
60287
+ lines.pop();
60288
+ if (lines.length > 0) {
60289
+ const lead = lines[0].text.length - lines[0].text.trimStart().length;
60290
+ if (lead > 0)
60291
+ lines[0] = { text: lines[0].text.slice(lead), offset: lines[0].offset + lead };
59651
60292
  }
59652
- return out;
60293
+ return lines;
59653
60294
  }
59654
- function isAbstractDecl(node) {
59655
- return (node.modifiers ?? []).includes("abstract");
60295
+ function cleanBlockBody(inner) {
60296
+ return cleanBlockBodyLines(inner, 0).map((line) => line.text).join("\n");
59656
60297
  }
59657
- var SCALAR_ROOT_KINDS = {
59658
- String: "string",
59659
- Boolean: "boolean",
59660
- NumericalValue: "number",
59661
- Number: "number",
59662
- Integer: "number",
59663
- Rational: "number",
59664
- Real: "number",
59665
- Complex: "number",
59666
- Natural: "number",
59667
- Positive: "number",
59668
- Cardinal: "number"
59669
- };
59670
- function literalKindOf(node) {
59671
- if (!node)
60298
+ function docCommentBody(node) {
60299
+ const raw = node.doc;
60300
+ if (typeof raw !== "string")
59672
60301
  return void 0;
59673
- switch (node.$type) {
59674
- case "LiteralStr":
59675
- return "string";
59676
- case "LiteralBool":
60302
+ const start = raw.indexOf("/*");
60303
+ const end = raw.lastIndexOf("*/");
60304
+ if (start < 0 || end < start)
60305
+ return void 0;
60306
+ const body = cleanBlockBody(raw.slice(start, end + 2));
60307
+ return body.length > 0 ? body : void 0;
60308
+ }
60309
+ function trailingBlockBodySpan(node) {
60310
+ const cst = node.$cstNode;
60311
+ const text = sourceOf(node);
60312
+ if (!cst || text === void 0)
60313
+ return void 0;
60314
+ const rest = text.slice(cst.end);
60315
+ const open = rest.indexOf("/*");
60316
+ if (open < 0)
60317
+ return void 0;
60318
+ if (rest.slice(0, open).trim() !== "")
60319
+ return void 0;
60320
+ const close = rest.indexOf("*/", open + 2);
60321
+ if (close < 0)
60322
+ return void 0;
60323
+ const raw = rest.slice(open, close + 2);
60324
+ const lines = cleanBlockBodyLines(raw, cst.end + open);
60325
+ const body = lines.map((line) => line.text).join("\n");
60326
+ if (body.length === 0)
60327
+ return void 0;
60328
+ return { text: body, lines, open: cst.end + open, close: cst.end + close + 2 };
60329
+ }
60330
+ function trailingBlockBody(node) {
60331
+ return trailingBlockBodySpan(node)?.text;
60332
+ }
60333
+ function bodyOffsetAt(span, line, character) {
60334
+ const entry = Number.isInteger(line) ? span.lines[line] : void 0;
60335
+ if (!entry)
60336
+ return span.open;
60337
+ const column = Number.isFinite(character) ? character : 0;
60338
+ return entry.offset + Math.max(0, Math.min(column, entry.text.length));
60339
+ }
60340
+
60341
+ // ../language-server/out/src/services/embedded-representation.js
60342
+ var EMBEDDED_LANGUAGES = /* @__PURE__ */ new Set(["sysml", "kerml"]);
60343
+ var EXPRESSION_VALUED_OWNERS = /* @__PURE__ */ new Set([
60344
+ "AssertConstraintStmt",
60345
+ "AssumeConstraintStmt",
60346
+ "RequireConstraintStmt",
60347
+ "ConstraintDecl",
60348
+ "InvShorthand",
60349
+ "CalcDecl",
60350
+ "ExpressionDecl"
60351
+ ]);
60352
+ function isEmbeddedLanguage(raw) {
60353
+ if (typeof raw !== "string")
60354
+ return false;
60355
+ return EMBEDDED_LANGUAGES.has(raw.replace(/^"|"$/gu, "").trim().toLowerCase());
60356
+ }
60357
+ function bareName(node) {
60358
+ const name = node?.name;
60359
+ return typeof name === "string" && name.length > 0 ? name.replace(/^'|'$/gu, "") : void 0;
60360
+ }
60361
+ function kindOf(node) {
60362
+ const decl = /^([A-Z][a-z]+)Decl$/.exec(node.$type);
60363
+ if (decl) {
60364
+ const base = decl[1].toLowerCase();
60365
+ return node.isDef ? `${base} def` : base;
60366
+ }
60367
+ switch (node.$type) {
60368
+ case "Package":
60369
+ return "package";
60370
+ case "InvShorthand":
60371
+ return "inv";
60372
+ case "AssertConstraintStmt":
60373
+ return "assert constraint";
60374
+ case "AssumeConstraintStmt":
60375
+ return "assume constraint";
60376
+ case "RequireConstraintStmt":
60377
+ return "require constraint";
60378
+ default:
60379
+ return node.$type;
60380
+ }
60381
+ }
60382
+ function hasErrors(result) {
60383
+ return result.lexerErrors.length > 0 || result.parserErrors.length > 0;
60384
+ }
60385
+ function describeParserError(error) {
60386
+ const image = error.token?.image ?? "";
60387
+ const expecting = /Expecting token of type '([^']+)'/u.exec(error.message ?? "");
60388
+ if (image === "") {
60389
+ return expecting ? `the body ends while '${expecting[1]}' is still expected.` : "the body ends before it is complete.";
60390
+ }
60391
+ if (error.name === "NotAllInputParsedException") {
60392
+ return `'${image}' is left over after the representation is already complete.`;
60393
+ }
60394
+ if (expecting)
60395
+ return `expected '${expecting[1]}' but found '${image}'.`;
60396
+ return `unexpected '${image}'.`;
60397
+ }
60398
+ function describeLexerError(error) {
60399
+ const character = /unexpected character: ->(.*?)<-/u.exec(error.message ?? "");
60400
+ return character ? `unexpected character '${character[1]}'.` : error.message ?? "the body cannot be read.";
60401
+ }
60402
+ function failureOf(result, span) {
60403
+ const endLine = Math.max(0, span.lines.length - 1);
60404
+ const end = { line: endLine, character: span.lines[endLine]?.text.length ?? 0 };
60405
+ const lexical = result.lexerErrors[0];
60406
+ const syntactic = result.parserErrors[0];
60407
+ if (lexical && Number.isFinite(lexical.line)) {
60408
+ return {
60409
+ line: lexical.line - 1,
60410
+ character: Math.max(0, (Number.isFinite(lexical.column) ? lexical.column : 1) - 1),
60411
+ message: describeLexerError(lexical)
60412
+ };
60413
+ }
60414
+ if (syntactic) {
60415
+ const token = syntactic.token;
60416
+ const message = describeParserError(syntactic);
60417
+ if (Number.isFinite(token?.startLine) && Number.isFinite(token?.startColumn)) {
60418
+ return { line: token.startLine - 1, character: token.startColumn - 1, message };
60419
+ }
60420
+ return { ...end, message };
60421
+ }
60422
+ return { ...end, message: lexical ? describeLexerError(lexical) : "the body is not valid SysML." };
60423
+ }
60424
+ function conformance(parsed, owner) {
60425
+ if (!parsed || !owner || owner.$type === "Document")
60426
+ return { status: "ok" };
60427
+ const sameKind = parsed.$type === owner.$type && Boolean(parsed.isDef) === Boolean(owner.isDef);
60428
+ if (!sameKind) {
60429
+ return { status: "mismatch", mismatch: { reason: "kind", expected: kindOf(owner), actual: kindOf(parsed) } };
60430
+ }
60431
+ const expected = bareName(owner);
60432
+ const actual = bareName(parsed);
60433
+ if (expected && actual && expected !== actual) {
60434
+ return { status: "mismatch", mismatch: { reason: "name", expected, actual } };
60435
+ }
60436
+ return { status: "ok" };
60437
+ }
60438
+ function nodesOf(root3) {
60439
+ return [root3, ...ast_utils_exports.streamAllContents(root3)];
60440
+ }
60441
+ function declaredNames(root3) {
60442
+ const names = /* @__PURE__ */ new Set();
60443
+ for (const node of nodesOf(root3)) {
60444
+ const name = node.name;
60445
+ if (typeof name === "string" && name.length > 0)
60446
+ names.add(name.replace(/^'|'$/gu, ""));
60447
+ }
60448
+ return names;
60449
+ }
60450
+ function graftInto(fragment, owner) {
60451
+ const mutable = fragment;
60452
+ mutable.$container = owner;
60453
+ mutable.$containerProperty = "members";
60454
+ }
60455
+ function firstSegment(refText) {
60456
+ return (refText.split("::")[0] ?? refText).replace(/^'|'$/gu, "").trim();
60457
+ }
60458
+ function unresolvedReferences(fragment, owner) {
60459
+ graftInto(fragment, owner);
60460
+ const own = declaredNames(fragment);
60461
+ const out = [];
60462
+ for (const node of nodesOf(fragment)) {
60463
+ for (const [property3, value] of Object.entries(node)) {
60464
+ if (property3.startsWith("$"))
60465
+ continue;
60466
+ for (const candidate of Array.isArray(value) ? value : [value]) {
60467
+ if (!isReference(candidate))
60468
+ continue;
60469
+ const reference = candidate;
60470
+ const refText = reference.$refText;
60471
+ if (!refText || own.has(firstSegment(refText)))
60472
+ continue;
60473
+ let resolved;
60474
+ try {
60475
+ resolved = reference.ref;
60476
+ } catch {
60477
+ return [];
60478
+ }
60479
+ if (resolved)
60480
+ continue;
60481
+ const range = reference.$refNode?.range;
60482
+ if (!range)
60483
+ continue;
60484
+ out.push({
60485
+ refText,
60486
+ line: range.start.line,
60487
+ character: range.start.character,
60488
+ length: Math.max(1, range.end.character - range.start.character)
60489
+ });
60490
+ }
60491
+ }
60492
+ }
60493
+ return out;
60494
+ }
60495
+ function evaluateRepresentation(parser, rep) {
60496
+ if (!isEmbeddedLanguage(rep.language))
60497
+ return void 0;
60498
+ const span = trailingBlockBodySpan(rep);
60499
+ if (!span)
60500
+ return void 0;
60501
+ const owner = rep.$container;
60502
+ const context = owner && owner.$type !== "Document" ? owner : void 0;
60503
+ const declaration = parser.parse(span.text, { rule: "NamespaceElement" });
60504
+ if (!hasErrors(declaration)) {
60505
+ return {
60506
+ span,
60507
+ verdict: conformance(declaration.value, owner),
60508
+ unresolved: context ? unresolvedReferences(declaration.value, context) : [],
60509
+ fragment: declaration.value,
60510
+ tier: "declaration"
60511
+ };
60512
+ }
60513
+ if (owner && EXPRESSION_VALUED_OWNERS.has(owner.$type)) {
60514
+ const expression = parser.parse(span.text, { rule: "Expr" });
60515
+ if (!hasErrors(expression)) {
60516
+ return {
60517
+ span,
60518
+ verdict: { status: "ok" },
60519
+ unresolved: context ? unresolvedReferences(expression.value, context) : [],
60520
+ fragment: expression.value,
60521
+ tier: "expression"
60522
+ };
60523
+ }
60524
+ }
60525
+ return { span, verdict: { status: "unparsed", failure: failureOf(declaration, span) }, unresolved: [] };
60526
+ }
60527
+
60528
+ // ../language-server/out/src/services/conformance.js
60529
+ var SPECIALIZATION_KINDS3 = /* @__PURE__ */ new Set([
60530
+ ":>",
60531
+ ":>>",
60532
+ "specializes",
60533
+ "subsets",
60534
+ "redefines"
60535
+ ]);
60536
+ var COMPOSITION_KINDS = /* @__PURE__ */ new Set(["unions", "intersects", "differences"]);
60537
+ var MAX_CLOSURE_DEPTH = 32;
60538
+ function simpleTypeName(name) {
60539
+ const last2 = name.trim().split(/::|\./u).pop() ?? name.trim();
60540
+ return last2.replace(/^'(.*)'$/u, "$1");
60541
+ }
60542
+ function declaredTypesOf(node) {
60543
+ const decl = node;
60544
+ const out = [];
60545
+ for (const typing of [decl.typing, ...decl.moreTypings ?? []]) {
60546
+ if (!typing)
60547
+ continue;
60548
+ const conjugated = typing.conjugate === true;
60549
+ for (const ref of [typing.type, ...typing.moreTypes ?? []]) {
60550
+ const text = ref?.$refText?.trim();
60551
+ if (text)
60552
+ out.push({ text, simple: simpleTypeName(text), conjugated });
60553
+ }
60554
+ }
60555
+ return out;
60556
+ }
60557
+ function specializedNamesOf(node) {
60558
+ const decl = node;
60559
+ const out = [];
60560
+ for (const rel of [...decl.preRelationships ?? [], ...decl.relationships ?? []]) {
60561
+ if (!rel.kind || !SPECIALIZATION_KINDS3.has(rel.kind))
60562
+ continue;
60563
+ for (const target of rel.targets ?? []) {
60564
+ const text = target.trim();
60565
+ if (text)
60566
+ out.push(text);
60567
+ }
60568
+ }
60569
+ return out;
60570
+ }
60571
+ function compositionGroupsOf(node) {
60572
+ const decl = node;
60573
+ const out = [];
60574
+ for (const rel of [...decl.preRelationships ?? [], ...decl.relationships ?? []]) {
60575
+ if (!rel.kind || !COMPOSITION_KINDS.has(rel.kind))
60576
+ continue;
60577
+ const targets = (rel.targets ?? []).map((t) => t.trim()).filter((t) => t.length > 0);
60578
+ if (targets.length > 0)
60579
+ out.push({ kind: rel.kind, targets });
60580
+ }
60581
+ return out;
60582
+ }
60583
+ function isAbstractDecl(node) {
60584
+ return (node.modifiers ?? []).includes("abstract");
60585
+ }
60586
+ var SCALAR_ROOT_KINDS = {
60587
+ String: "string",
60588
+ Boolean: "boolean",
60589
+ NumericalValue: "number",
60590
+ Number: "number",
60591
+ Integer: "number",
60592
+ Rational: "number",
60593
+ Real: "number",
60594
+ Complex: "number",
60595
+ Natural: "number",
60596
+ Positive: "number",
60597
+ Cardinal: "number"
60598
+ };
60599
+ function literalKindOf(node) {
60600
+ if (!node)
60601
+ return void 0;
60602
+ switch (node.$type) {
60603
+ case "LiteralStr":
60604
+ return "string";
60605
+ case "LiteralBool":
59677
60606
  return "boolean";
59678
60607
  case "NumericPrimary":
59679
60608
  return "number";
@@ -59944,7 +60873,7 @@ function maskNonCode(text) {
59944
60873
  }
59945
60874
  return out.join("");
59946
60875
  }
59947
- var SPECIALIZATION_KINDS3 = /* @__PURE__ */ new Set([":>", ":>>", "specializes", "subsets", "redefines"]);
60876
+ var SPECIALIZATION_KINDS4 = /* @__PURE__ */ new Set([":>", ":>>", "specializes", "subsets", "redefines"]);
59948
60877
  var CONSTRAINT_SIDE_EFFECT_TYPES = /* @__PURE__ */ new Set([
59949
60878
  "AssignNode",
59950
60879
  "SendNode",
@@ -60034,7 +60963,14 @@ var SysmlValidator = class _SysmlValidator {
60034
60963
  langiumDocuments;
60035
60964
  astNodeLocator;
60036
60965
  featurePaths;
60966
+ // REQ-396 — One SysmlValidator instance is registered against BOTH the SysML and
60967
+ // the KerML services (sysml-module.ts), so the parser used to read an embedded
60968
+ // representation is looked up from the document being validated rather than
60969
+ // captured here. The two share one grammar today; this keeps that from becoming
60970
+ // load-bearing.
60971
+ serviceRegistry;
60037
60972
  constructor(services) {
60973
+ this.serviceRegistry = services.shared.ServiceRegistry;
60038
60974
  this.indexManager = services.shared.workspace.IndexManager;
60039
60975
  this.langiumDocuments = services.shared.workspace.LangiumDocuments;
60040
60976
  this.astNodeLocator = services.workspace.AstNodeLocator;
@@ -60050,23 +60986,38 @@ var SysmlValidator = class _SysmlValidator {
60050
60986
  // Langium linker cannot diagnose a missing intermediate feature. Resolve the
60051
60987
  // chain here and underline only the first invalid segment.
60052
60988
  checkPathExpr(node, accept) {
60989
+ const fault = this.featurePathFault(node);
60990
+ if (!fault)
60991
+ return;
60992
+ accept(severity("RES001", "error"), DIAGNOSTIC_MESSAGES.RES001_FEATURE_PATH_SEGMENT(fault.segment, fault.owner), {
60993
+ node,
60994
+ range: fault.range,
60995
+ code: "RES001",
60996
+ data: { featurePathSegment: true }
60997
+ });
60998
+ }
60999
+ // REQ-317, REQ-396 — The one place that decides whether a written feature path
61000
+ // has a provably absent segment. Extracted so an embedded representation body is
61001
+ // judged by exactly this rule (issue #150 review): a body is grafted onto the
61002
+ // element it represents and is therefore unreachable from the document walk that
61003
+ // dispatches `checkPathExpr`, so without a shared decision the two would drift
61004
+ // and a body would quietly escape a diagnostic the surrounding model receives.
61005
+ featurePathFault(node) {
60053
61006
  let declaration = node.$container;
60054
61007
  while (declaration && !isPartDecl(declaration))
60055
61008
  declaration = declaration.$container;
60056
61009
  const modifiers2 = declaration?.modifiers ?? [];
60057
61010
  if (!declaration || !modifiers2.includes("ref"))
60058
- return;
61011
+ return void 0;
60059
61012
  const resolution = this.featurePaths.resolve(node);
60060
61013
  if (resolution.unresolvedIndex === void 0)
60061
- return;
61014
+ return void 0;
60062
61015
  const invalid = resolution.segments[resolution.unresolvedIndex];
60063
- const owner = resolution.unresolvedIndex > 0 ? resolution.segments[resolution.unresolvedIndex - 1].text : "the current scope";
60064
- accept(severity("RES001", "error"), DIAGNOSTIC_MESSAGES.RES001_FEATURE_PATH_SEGMENT(invalid.text, owner), {
60065
- node,
60066
- range: invalid.cst.range,
60067
- code: "RES001",
60068
- data: { featurePathSegment: true }
60069
- });
61016
+ return {
61017
+ segment: invalid.text,
61018
+ owner: resolution.unresolvedIndex > 0 ? resolution.segments[resolution.unresolvedIndex - 1].text : "the current scope",
61019
+ range: invalid.cst.range
61020
+ };
60070
61021
  }
60071
61022
  // REQ-389 — Namespace qualification versus feature chaining in every written path
60072
61023
  // issue #213 — RES019: `::` binds tighter than `.`. Each dot-separated link of
@@ -60254,10 +61205,13 @@ var SysmlValidator = class _SysmlValidator {
60254
61205
  if (!node.visibility) {
60255
61206
  accept(severity("SYN067", "error"), "Import visibility is required by the Release syntax; use 'private import' unless re-export is intended.", { node, code: "SYN067" });
60256
61207
  }
61208
+ if (node.visibility && node.visibility !== "private" && node.$container?.$type === "Document") {
61209
+ accept(severity("RES021", "error"), DIAGNOSTIC_MESSAGES.RES021_ROOT_IMPORT_VISIBILITY(node.visibility), { node, property: "visibility", code: "RES021" });
61210
+ }
60257
61211
  const headStr = node.head ?? "";
60258
61212
  const segsStr = node.segs.map((s) => {
60259
61213
  if (s.recursive)
60260
- return "::**";
61214
+ return s.star ? "::*::**" : "::**";
60261
61215
  if (s.star)
60262
61216
  return "::*";
60263
61217
  return `::${s.name ?? ""}`;
@@ -60297,6 +61251,7 @@ var SysmlValidator = class _SysmlValidator {
60297
61251
  this.checkConnectorForms(node, accept);
60298
61252
  this.checkActionStartSuccessions(node, accept);
60299
61253
  this.checkAnnotationForms(node, accept);
61254
+ this.checkEmbeddedRepresentations(node, accept);
60300
61255
  this.checkLanguageDisjointness(node, accept);
60301
61256
  this.checkKermlWellFormedness(node, accept);
60302
61257
  this.checkFilterExpressions(node, accept);
@@ -60637,6 +61592,132 @@ ${baseIndent}}`;
60637
61592
  }
60638
61593
  }
60639
61594
  }
61595
+ // REQ-396 — SYN076/SEM012 embedded textual representations (issue #150).
61596
+ // A `rep … language "sysml"` (or `"kerml"`, matched case-insensitively) is not
61597
+ // opaque content: OMG KerML §7.4.3 requires its body to be a legal representation
61598
+ // of the element it annotates. So the body is processed by the comment-body rules,
61599
+ // parsed, and compared against that element:
61600
+ // SYN076 — the body is not valid SysML, reported ON the offending character
61601
+ // inside the body rather than on the `rep` keyword.
61602
+ // SEM012 — the body parses but represents a different element (wrong kind, or
61603
+ // the right kind under a different name).
61604
+ // Every other language stays opaque and is never parsed — an `alf`, `ocl` or
61605
+ // `yaml` body is content, and the vendored OMG corpus holds only those.
61606
+ checkEmbeddedRepresentations(node, accept) {
61607
+ const doc = ast_utils_exports.getDocument(node);
61608
+ if (!doc?.textDocument)
61609
+ return;
61610
+ let parser;
61611
+ for (const child of ast_utils_exports.streamAllContents(node)) {
61612
+ if (child.$type !== "RepStmt")
61613
+ continue;
61614
+ if (!isEmbeddedLanguage(child.language))
61615
+ continue;
61616
+ parser ??= this.serviceRegistry.getServices(doc.uri).parser.LangiumParser;
61617
+ const evaluated = evaluateRepresentation(parser, child);
61618
+ if (!evaluated)
61619
+ continue;
61620
+ const { span, verdict } = evaluated;
61621
+ const language = String(child.language ?? "").replace(/^"|"$/gu, "");
61622
+ if (verdict.status === "unparsed") {
61623
+ const { line, character, message } = verdict.failure;
61624
+ const anchor = bodyOffsetAt(span, line, character);
61625
+ const after = bodyOffsetAt(span, line, character + 1);
61626
+ const from = after > anchor ? anchor : bodyOffsetAt(span, line, Math.max(0, character - 1));
61627
+ accept(severity("SYN076", "error"), DIAGNOSTIC_MESSAGES.SYN076_EMBEDDED_REPRESENTATION_SYNTAX(language, message), {
61628
+ node: child,
61629
+ range: {
61630
+ start: doc.textDocument.positionAt(from),
61631
+ end: doc.textDocument.positionAt(Math.max(after, anchor))
61632
+ },
61633
+ code: "SYN076"
61634
+ });
61635
+ continue;
61636
+ }
61637
+ for (const reference of evaluated.unresolved) {
61638
+ accept(severity("RES020", "warning"), DIAGNOSTIC_MESSAGES.RES020_REPRESENTATION_UNRESOLVED(reference.refText, language), {
61639
+ node: child,
61640
+ range: {
61641
+ start: doc.textDocument.positionAt(bodyOffsetAt(span, reference.line, reference.character)),
61642
+ end: doc.textDocument.positionAt(bodyOffsetAt(span, reference.line, reference.character + reference.length))
61643
+ },
61644
+ code: "RES020"
61645
+ });
61646
+ }
61647
+ if (evaluated.fragment) {
61648
+ this.checkEmbeddedDialect(child, evaluated.fragment, language, span, doc, accept);
61649
+ this.checkEmbeddedFeaturePaths(child, evaluated.fragment, language, span, doc, accept);
61650
+ }
61651
+ if (verdict.status === "ok")
61652
+ continue;
61653
+ const { reason, expected, actual } = verdict.mismatch;
61654
+ const owner = child.$container;
61655
+ accept(severity("SEM012", "warning"), reason === "kind" ? DIAGNOSTIC_MESSAGES.SEM012_REPRESENTATION_WRONG_KIND(expected, actual) : DIAGNOSTIC_MESSAGES.SEM012_REPRESENTATION_WRONG_NAME(expected, actual), {
61656
+ node: child,
61657
+ range: {
61658
+ start: doc.textDocument.positionAt(bodyOffsetAt(span, 0, 0)),
61659
+ end: doc.textDocument.positionAt(bodyOffsetAt(span, 0, span.lines[0]?.text.length ?? 0))
61660
+ },
61661
+ code: "SEM012",
61662
+ relatedInformation: owner ? [relatedInfo(owner, "The element this representation annotates.")].filter((info) => info !== void 0) : void 0
61663
+ });
61664
+ }
61665
+ }
61666
+ // REQ-396 — SYN100/SYN101 inside a representation body (issue #150 review).
61667
+ // The normative rule is that the body is legal in the language the representation
61668
+ // NAMES, which is not the language of the file it sits in: a `.sysml` file may
61669
+ // carry a `language "kerml"` representation, and its body may then use no
61670
+ // SysML-only construct. `checkLanguageDisjointness` answers a different question
61671
+ // — what may this FILE contain — from the host URI, so the same tables are read
61672
+ // here against the declared language instead.
61673
+ checkEmbeddedDialect(rep, fragment, language, span, doc, accept) {
61674
+ const dialect = language.trim().toLowerCase();
61675
+ const isKerml = dialect === "kerml";
61676
+ const forbidden = isKerml ? SYSML_ONLY_TYPES : KERML_ONLY_TYPES;
61677
+ const code = isKerml ? "SYN100" : "SYN101";
61678
+ for (const node of [fragment, ...ast_utils_exports.streamAllContents(fragment)]) {
61679
+ if (!forbidden.has(node.$type))
61680
+ continue;
61681
+ const range = node.$cstNode?.range;
61682
+ if (!range)
61683
+ continue;
61684
+ accept(severity(code, "error"), isKerml ? `'${declKeyword(node)}' is a SysML construct and is not available in a "${language}" representation.` : `'${declKeyword(node)}' is a KerML-only construct \u2014 use the SysML form in a "${language}" representation.`, {
61685
+ node: rep,
61686
+ range: this.bodyRange(span, doc, range),
61687
+ code
61688
+ });
61689
+ }
61690
+ }
61691
+ // REQ-396 — RES020 for a written feature path with a provably absent segment
61692
+ // (issue #150 review). `checkPathExpr` is registered as a node-level check, so
61693
+ // Langium dispatches it by walking the document AST and never reaches the grafted
61694
+ // fragment. The decision itself is shared with it through `featurePathFault`, so
61695
+ // a body is held to the same rule as the model around it rather than a parallel
61696
+ // one that could drift; only the code differs, keeping every fault found IN a
61697
+ // representation body under the one severity a team can tune.
61698
+ checkEmbeddedFeaturePaths(rep, fragment, language, span, doc, accept) {
61699
+ for (const node of [fragment, ...ast_utils_exports.streamAllContents(fragment)]) {
61700
+ if (!this.featurePaths.isPathExpr(node))
61701
+ continue;
61702
+ const fault = this.featurePathFault(node);
61703
+ if (!fault)
61704
+ continue;
61705
+ accept(severity("RES020", "warning"), DIAGNOSTIC_MESSAGES.RES020_REPRESENTATION_PATH_SEGMENT(fault.segment, fault.owner, language), {
61706
+ node: rep,
61707
+ range: this.bodyRange(span, doc, fault.range),
61708
+ code: "RES020"
61709
+ });
61710
+ }
61711
+ }
61712
+ // REQ-396 — A range inside a parsed body, expressed in document coordinates.
61713
+ // Fragment CST positions are line/character within the PROCESSED body, which is
61714
+ // exactly what the span's line table converts.
61715
+ bodyRange(span, doc, range) {
61716
+ return {
61717
+ start: doc.textDocument.positionAt(bodyOffsetAt(span, range.start.line, range.start.character)),
61718
+ end: doc.textDocument.positionAt(bodyOffsetAt(span, range.end.line, range.end.character))
61719
+ };
61720
+ }
60640
61721
  // REQ-311 — SYN050/051 connector syntax, with a specific message in place of
60641
61722
  // the grammar's generic parse error:
60642
61723
  // SYN050 — `connect a with b;` (use `connect a to b;`).
@@ -61146,6 +62227,7 @@ ${baseIndent}}`;
61146
62227
  const index = this.buildIndex();
61147
62228
  const imports = [];
61148
62229
  const exposePaths = [];
62230
+ const filterMembers = [];
61149
62231
  const decls = [];
61150
62232
  const verifyStmts = [];
61151
62233
  const satisfyStmts = [];
@@ -61159,6 +62241,8 @@ ${baseIndent}}`;
61159
62241
  aliasMap.set(alias, path10);
61160
62242
  } else if (isExposePath(child))
61161
62243
  exposePaths.push(child);
62244
+ else if (child.$type === "FilterMember")
62245
+ filterMembers.push(child);
61162
62246
  else if (isVerifyStmt(child))
61163
62247
  verifyStmts.push(child);
61164
62248
  else if (isSatisfyStmt(child))
@@ -61175,7 +62259,7 @@ ${baseIndent}}`;
61175
62259
  this.checkPrivateImports(imports, index, accept);
61176
62260
  this.checkPrivateWildcardReferences(node, imports, index, accept);
61177
62261
  this.checkImportCycles(imports, index, accept);
61178
- this.checkUnevaluatedFilters(imports, exposePaths, accept);
62262
+ this.checkUnevaluatedFilters(imports, exposePaths, filterMembers, index, accept);
61179
62263
  if (sysmlDiagnosticSettings.unusedImports !== "off") {
61180
62264
  this.checkUnusedImports(node, imports, index, sysmlDiagnosticSettings.unusedImports, accept);
61181
62265
  }
@@ -61603,6 +62687,10 @@ ${baseIndent}}`;
61603
62687
  if (condition && isDefinitelyNonBoolean(condition)) {
61604
62688
  accept(severity("KSM008", "error"), "A filter condition must be a Boolean expression.", { node: child, code: "KSM008" });
61605
62689
  }
62690
+ const owner = child.$container;
62691
+ if (owner && !isFilterHost(owner)) {
62692
+ accept(severity("KSM012", "error"), DIAGNOSTIC_MESSAGES.KSM012_FILTER_PLACEMENT(kindLabel(owner)), { node: child, code: "KSM012" });
62693
+ }
61606
62694
  }
61607
62695
  }
61608
62696
  // REQ-328 — KSM006: a type-composition `unions`/`intersects`/`differences`
@@ -61892,7 +62980,8 @@ ${baseIndent}}`;
61892
62980
  const node = this.resolveUnique(nsName, index);
61893
62981
  const ownsNamespace = node !== void 0 && (isPackage(node) || node.$type === "NamespaceDecl" || (node.members?.length ?? 0) > 0);
61894
62982
  if (node && !ownsNamespace) {
61895
- accept(severity("RES007", "error"), `Recursive import '${nsName}::*::**' requires '${nsName}' to be a package, namespace, or usage that owns nested members.`, { node: imp, code: "RES007" });
62983
+ const written = imp.segs.some((s) => s.recursive && s.star) ? `${nsName}::*::**` : `${nsName}::**`;
62984
+ accept(severity("RES007", "error"), `Recursive import '${written}' requires '${nsName}' to be a package, namespace, or usage that owns nested members.`, { node: imp, code: "RES007" });
61896
62985
  }
61897
62986
  }
61898
62987
  // REQ-323 — RES008: an `alias … for X` whose target `X` does not resolve.
@@ -62019,6 +63108,8 @@ ${baseIndent}}`;
62019
63108
  // REQ-320 — RES004 importing a private element from outside its namespace
62020
63109
  checkPrivateImports(imports, index, accept) {
62021
63110
  for (const imp of imports) {
63111
+ if (importForm(imp).importAll)
63112
+ continue;
62022
63113
  const path10 = importedPath(imp);
62023
63114
  if (!path10)
62024
63115
  continue;
@@ -62041,13 +63132,15 @@ ${baseIndent}}`;
62041
63132
  // reference so the user learns why a `Pkg::*` did not bring it in.
62042
63133
  checkPrivateWildcardReferences(node, imports, index, accept) {
62043
63134
  const wildcards = [];
63135
+ const importAllPaths = [];
62044
63136
  for (const imp of imports) {
62045
- const kind = importWildcard(imp);
62046
- if (kind === "none")
63137
+ const form = importForm(imp);
63138
+ if (form.wildcard === "none")
62047
63139
  continue;
62048
63140
  const path10 = importedPath(imp);
62049
- if (path10)
62050
- wildcards.push({ path: path10, recursive: kind === "recursive" });
63141
+ if (!path10)
63142
+ continue;
63143
+ (form.importAll ? importAllPaths : wildcards).push({ path: path10, recursive: form.wildcard === "recursive" });
62051
63144
  }
62052
63145
  if (wildcards.length === 0)
62053
63146
  return;
@@ -62068,8 +63161,10 @@ ${baseIndent}}`;
62068
63161
  const ownerQn = ownerPkg ? qualifiedNameOf(ownerPkg) : void 0;
62069
63162
  if (!ownerQn)
62070
63163
  continue;
62071
- const reachedByWildcard = wildcards.some((w) => w.recursive ? ownerQn === w.path || ownerQn.startsWith(w.path + "::") : ownerQn === w.path);
62072
- if (!reachedByWildcard)
63164
+ const reaches = (w) => w.recursive ? ownerQn === w.path || ownerQn.startsWith(w.path + "::") : ownerQn === w.path;
63165
+ if (!wildcards.some(reaches))
63166
+ continue;
63167
+ if (importAllPaths.some(reaches))
62073
63168
  continue;
62074
63169
  const refNode = ref.$refNode?.astNode;
62075
63170
  if (refNode && isWithinNamespaceOf(refNode, target))
@@ -62151,9 +63246,10 @@ ${baseIndent}}`;
62151
63246
  * unevaluated filter to break a build raise it per code through
62152
63247
  * `sysml.validation.severities` (REQ-240).
62153
63248
  */
62154
- checkUnevaluatedFilters(imports, exposePaths, accept) {
63249
+ checkUnevaluatedFilters(imports, exposePaths, filterMembers, index, accept) {
63250
+ const resolveName = (name) => this.resolveUnique(name, index);
62155
63251
  const report = (condition, subject) => {
62156
- const undecidable = undecidableFilterCondition(condition);
63252
+ const undecidable = undecidableFilterCondition(condition, resolveName);
62157
63253
  if (!undecidable)
62158
63254
  return;
62159
63255
  accept(severity("RES018", "info"), DIAGNOSTIC_MESSAGES.RES018_UNEVALUATED_FILTER(subject, undecidable.construct), { node: undecidable.node, code: "RES018" });
@@ -62163,6 +63259,11 @@ ${baseIndent}}`;
62163
63259
  report(filter3.condition, "Import");
62164
63260
  for (const path10 of exposePaths)
62165
63261
  report(path10.condition, "Expose");
63262
+ for (const member of filterMembers) {
63263
+ if (governsImportFilters(member.$container)) {
63264
+ report(member.condition, "Package");
63265
+ }
63266
+ }
62166
63267
  }
62167
63268
  // REQ-324 — RES009 unused import (configurable, OFF by default)
62168
63269
  checkUnusedImports(root3, imports, index, level, accept) {
@@ -62183,7 +63284,7 @@ ${baseIndent}}`;
62183
63284
  return;
62184
63285
  const visited = /* @__PURE__ */ new Set();
62185
63286
  const reachesSelf = (node) => {
62186
- for (const targetName of specializationTargets(node)) {
63287
+ for (const targetName of specializationTargets2(node)) {
62187
63288
  const target = this.resolve(targetName, index, node);
62188
63289
  if (!target)
62189
63290
  continue;
@@ -62570,14 +63671,14 @@ function shortNameOf(node) {
62570
63671
  function shortNameNodeOf(node) {
62571
63672
  return node.shortName;
62572
63673
  }
62573
- function specializationTargets(node) {
63674
+ function specializationTargets2(node) {
62574
63675
  const out = [];
62575
63676
  const rels = [
62576
63677
  ...node.preRelationships ?? [],
62577
63678
  ...node.relationships ?? []
62578
63679
  ];
62579
63680
  for (const rel of rels) {
62580
- if (rel.kind && SPECIALIZATION_KINDS3.has(rel.kind))
63681
+ if (rel.kind && SPECIALIZATION_KINDS4.has(rel.kind))
62581
63682
  out.push(...rel.targets);
62582
63683
  }
62583
63684
  return out;
@@ -62928,7 +64029,13 @@ function introducedNames(imp, index, nodeOf) {
62928
64029
  const protectedNamespaceKeys = protectedNamespaceKeysFor(imp.$container, globalDescs, nodeOf);
62929
64030
  return expandImportEntries(imp, globalDescs, {
62930
64031
  nodeOf,
62931
- protectedNamespaceKeys
64032
+ protectedNamespaceKeys,
64033
+ // issue #153 — filters may need a metadata definition's default value or
64034
+ // a specialization chain; both are index lookups, not cross-references.
64035
+ resolveName: (name) => {
64036
+ const description = globalDescs.firstNamed(name);
64037
+ return description ? nodeOf(description) : void 0;
64038
+ }
62932
64039
  }).map((entry) => ({
62933
64040
  simple: entry.name,
62934
64041
  targetQn: entry.targetName,
@@ -62949,13 +64056,13 @@ function protectedNamespaceKeysFor(context, globalDescs, nodeOf) {
62949
64056
  const node = nodeOf(desc);
62950
64057
  if (!node || !isDeclLike(node))
62951
64058
  return;
62952
- for (const inherited of specializationTargets(node))
64059
+ for (const inherited of specializationTargets2(node))
62953
64060
  collect(inherited);
62954
64061
  };
62955
64062
  let cur = context;
62956
64063
  while (cur) {
62957
64064
  if (isDeclLike(cur)) {
62958
- for (const target of specializationTargets(cur))
64065
+ for (const target of specializationTargets2(cur))
62959
64066
  collect(target);
62960
64067
  }
62961
64068
  cur = cur.$container;
@@ -63009,6 +64116,15 @@ function importIsUsed(imp, index, usedFull, usedFirst, nodeOf) {
63009
64116
  }
63010
64117
  return false;
63011
64118
  }
64119
+ var FILTER_HOST_TYPES = /* @__PURE__ */ new Set([
64120
+ "ViewDecl",
64121
+ "ViewpointDecl",
64122
+ "RenderingDecl",
64123
+ "Document"
64124
+ ]);
64125
+ function isFilterHost(owner) {
64126
+ return isPackage(owner) || FILTER_HOST_TYPES.has(owner.$type);
64127
+ }
63012
64128
  function kindLabel(node) {
63013
64129
  const m = /^([A-Z][a-z]+)Decl$/.exec(node.$type);
63014
64130
  return m ? m[1].toLowerCase() : node.$type;
@@ -63511,54 +64627,8 @@ function outlineGroupForType(astType) {
63511
64627
  return CATEGORY_TO_OUTLINE_GROUP[categoryForType(astType)] ?? "structure";
63512
64628
  }
63513
64629
 
63514
- // ../language-server/out/src/services/comment-body.js
63515
- function sourceOf(node) {
63516
- return node.$cstNode?.root.fullText;
63517
- }
63518
- function cleanBlockBody(inner) {
63519
- let body = inner.trim();
63520
- if (body.startsWith("/*"))
63521
- body = body.slice(2);
63522
- if (body.endsWith("*/"))
63523
- body = body.slice(0, -2);
63524
- const lines = body.split("\n").map((line) => line.replace(/^\s*\*+ ?/u, "").replace(/\s+$/u, ""));
63525
- while (lines.length > 0 && lines[0].trim() === "")
63526
- lines.shift();
63527
- while (lines.length > 0 && lines[lines.length - 1].trim() === "")
63528
- lines.pop();
63529
- return lines.join("\n").trim();
63530
- }
63531
- function docCommentBody(node) {
63532
- const raw = node.doc;
63533
- if (typeof raw !== "string")
63534
- return void 0;
63535
- const start = raw.indexOf("/*");
63536
- const end = raw.lastIndexOf("*/");
63537
- if (start < 0 || end < start)
63538
- return void 0;
63539
- const body = cleanBlockBody(raw.slice(start, end + 2));
63540
- return body.length > 0 ? body : void 0;
63541
- }
63542
- function trailingBlockBody(node) {
63543
- const cst = node.$cstNode;
63544
- const text = sourceOf(node);
63545
- if (!cst || text === void 0)
63546
- return void 0;
63547
- const rest = text.slice(cst.end);
63548
- const open = rest.indexOf("/*");
63549
- if (open < 0)
63550
- return void 0;
63551
- if (rest.slice(0, open).trim() !== "")
63552
- return void 0;
63553
- const close = rest.indexOf("*/", open + 2);
63554
- if (close < 0)
63555
- return void 0;
63556
- const body = cleanBlockBody(rest.slice(open, close + 2));
63557
- return body.length > 0 ? body : void 0;
63558
- }
63559
-
63560
64630
  // ../language-server/out/src/services/document-symbol-provider.js
63561
- var SPECIALIZATION_KINDS4 = /* @__PURE__ */ new Set([":>", "specializes"]);
64631
+ var SPECIALIZATION_KINDS5 = /* @__PURE__ */ new Set([":>", "specializes"]);
63562
64632
  var REDEFINITION_KINDS = /* @__PURE__ */ new Set([":>>", "redefines"]);
63563
64633
  var INHERITABLE_FEATURE_TYPES = /* @__PURE__ */ new Set([
63564
64634
  "ActionDecl",
@@ -63623,11 +64693,11 @@ function buildLocalSymbolIndex(root3) {
63623
64693
  }
63624
64694
  return symbols;
63625
64695
  }
63626
- function specializationTargets2(node) {
64696
+ function specializationTargets3(node) {
63627
64697
  const n = node;
63628
64698
  const out = [];
63629
64699
  for (const rel of [...n.preRelationships ?? [], ...n.relationships ?? []]) {
63630
- if (rel.kind && SPECIALIZATION_KINDS4.has(rel.kind))
64700
+ if (rel.kind && SPECIALIZATION_KINDS5.has(rel.kind))
63631
64701
  out.push(...rel.targets ?? []);
63632
64702
  }
63633
64703
  return out;
@@ -63746,7 +64816,7 @@ function inheritedFeatureSymbols(node, inheritedRange, context, seen = /* @__PUR
63746
64816
  return [];
63747
64817
  seen.add(node);
63748
64818
  const symbols = [];
63749
- for (const targetName of specializationTargets2(node)) {
64819
+ for (const targetName of specializationTargets3(node)) {
63750
64820
  const target = resolveLocalTarget(targetName, context);
63751
64821
  if (!target || seen.has(target))
63752
64822
  continue;
@@ -64351,7 +65421,7 @@ function nearestAncestor(node, types) {
64351
65421
  }
64352
65422
  return void 0;
64353
65423
  }
64354
- function exprText(node) {
65424
+ function exprText2(node) {
64355
65425
  return node?.$cstNode?.text?.trim().replace(/\s+/gu, " ") ?? "";
64356
65426
  }
64357
65427
  function conditionTypeLabel(node) {
@@ -64362,7 +65432,7 @@ function conditionTypeLabel(node) {
64362
65432
  if (["AndExpr", "OrExpr", "XorExpr", "NotExpr", "CompareExpr", "ClassifyOp"].includes(node.$type)) {
64363
65433
  return "Boolean";
64364
65434
  }
64365
- const text = exprText(node);
65435
+ const text = exprText2(node);
64366
65436
  return /\b(true|false)\b|[=!<>]=?|(?:\band\b|\bor\b|\bnot\b|\bxor\b)/u.test(text) ? "Boolean" : "Boolean (expected)";
64367
65437
  }
64368
65438
  function buildConditionalHover(node) {
@@ -64376,7 +65446,7 @@ function buildConditionalHover(node) {
64376
65446
  "",
64377
65447
  "Canonical form: `if condition ? thenExpression else elseExpression`",
64378
65448
  `Then marker: ${usesQuestion ? "canonical `?`" : "non-canonical `then`; use `?`"}`,
64379
- `Condition: \`${exprText(n.cond)}\``,
65449
+ `Condition: \`${exprText2(n.cond)}\``,
64380
65450
  `Condition type: ${conditionTypeLabel(n.cond)}`,
64381
65451
  "",
64382
65452
  sourceFooter(nodeSource(node))
@@ -66514,7 +67584,15 @@ var SysmlScopeProvider = class extends DefaultScopeProvider {
66514
67584
  // metadata `.ref` here re-enters the linker (cyclic reference error,
66515
67585
  // and the reference is poisoned with a cached failure). Match filters
66516
67586
  // by textual name only on this path; the validator resolves refs.
66517
- resolveReferences: false
67587
+ resolveReferences: false,
67588
+ // issue #153 — the index lookup a filter needs for a metadata
67589
+ // definition's default, a specialization chain or an enumeration
67590
+ // member. It reads the symbol table rather than a cross-reference,
67591
+ // so it is safe on this path where `.ref` is not.
67592
+ resolveName: (name) => {
67593
+ const description = globalDescs.firstNamed(name);
67594
+ return description ? this.nodeOf(description) : void 0;
67595
+ }
66518
67596
  };
66519
67597
  const result = [];
66520
67598
  for (const imp of this.visibleImportsFrom(contextNode)) {
@@ -66574,7 +67652,7 @@ var SysmlScopeProvider = class extends DefaultScopeProvider {
66574
67652
  const visitedTargets = /* @__PURE__ */ new Set();
66575
67653
  let cur = contextNode;
66576
67654
  while (cur) {
66577
- for (const target of specializationTargets3(cur)) {
67655
+ for (const target of specializationTargets4(cur)) {
66578
67656
  this.collectProtectedNamespace(target, globalDescs, keys3, nodes, visitedTargets);
66579
67657
  }
66580
67658
  cur = cur.$container;
@@ -66596,7 +67674,7 @@ var SysmlScopeProvider = class extends DefaultScopeProvider {
66596
67674
  keys3.add(key);
66597
67675
  nodes.push(node);
66598
67676
  }
66599
- for (const inherited of specializationTargets3(node)) {
67677
+ for (const inherited of specializationTargets4(node)) {
66600
67678
  this.collectProtectedNamespace(inherited, globalDescs, keys3, nodes, visitedTargets);
66601
67679
  }
66602
67680
  }
@@ -66615,16 +67693,7 @@ var SysmlScopeProvider = class extends DefaultScopeProvider {
66615
67693
  // every reference and re-expanded the whole standard library each time
66616
67694
  // (measured on a 1 500-line model: 226 misses over 349 references, 16 s).
66617
67695
  importContextKey(contextNode, protectedNamespaces) {
66618
- const parts = [];
66619
- let cur = contextNode;
66620
- while (cur) {
66621
- for (const member of namespaceMembers(cur)) {
66622
- if (isImport(member))
66623
- parts.push(importSignature(member));
66624
- }
66625
- cur = cur.$container;
66626
- }
66627
- const imports = parts.length > 0 ? parts.join(" ") : "root";
67696
+ const imports = importContextSignature(contextNode);
66628
67697
  return protectedNamespaces.key ? `${imports} ${protectedNamespaces.key}` : imports;
66629
67698
  }
66630
67699
  nodeOf(desc) {
@@ -66640,6 +67709,23 @@ var SysmlScopeProvider = class extends DefaultScopeProvider {
66640
67709
  function ownsProtectedImport(node) {
66641
67710
  return namespaceMembers(node).some((member) => isImport(member) && importVisibility(member) === "protected");
66642
67711
  }
67712
+ function importContextSignature(contextNode) {
67713
+ const parts = [];
67714
+ let cur = contextNode;
67715
+ while (cur) {
67716
+ for (const member of namespaceMembers(cur)) {
67717
+ if (isImport(member))
67718
+ parts.push(importSignature(member));
67719
+ else if (member.$type === "FilterMember")
67720
+ parts.push(filterSignature(member));
67721
+ }
67722
+ cur = cur.$container;
67723
+ }
67724
+ return parts.length > 0 ? parts.join(" ") : "root";
67725
+ }
67726
+ function filterSignature(member) {
67727
+ return `filter ${member.$cstNode?.text?.replace(/\s+/gu, " ").trim() ?? "?"}`;
67728
+ }
66643
67729
  function importSignature(imp) {
66644
67730
  const text = imp.$cstNode?.text;
66645
67731
  if (text)
@@ -66647,12 +67733,12 @@ function importSignature(imp) {
66647
67733
  const segments = imp.segs.map((seg) => `${seg.name ?? ""}${seg.star ? "*" : ""}${seg.recursive ? "**" : ""}`);
66648
67734
  return `${importVisibility(imp)} ${imp.head}::${segments.join("::")}${imp.alias ? ` as ${imp.alias}` : ""}`;
66649
67735
  }
66650
- var SPECIALIZATION_KINDS5 = /* @__PURE__ */ new Set([":>", ":>>", "specializes", "subsets", "redefines"]);
66651
- function specializationTargets3(node) {
67736
+ var SPECIALIZATION_KINDS6 = /* @__PURE__ */ new Set([":>", ":>>", "specializes", "subsets", "redefines"]);
67737
+ function specializationTargets4(node) {
66652
67738
  const n = node;
66653
67739
  const out = [];
66654
67740
  for (const rel of [...n.preRelationships ?? [], ...n.relationships ?? []]) {
66655
- if (rel.kind && SPECIALIZATION_KINDS5.has(rel.kind))
67741
+ if (rel.kind && SPECIALIZATION_KINDS6.has(rel.kind))
66656
67742
  out.push(...rel.targets ?? []);
66657
67743
  }
66658
67744
  return out;
@@ -66731,7 +67817,10 @@ var SysmlScopeComputation = class extends DefaultScopeComputation {
66731
67817
  const description = {
66732
67818
  ...entry.description,
66733
67819
  name: `${ownerAlias}::${entry.name}`,
66734
- isDerivedAlias: true
67820
+ isDerivedAlias: true,
67821
+ // issue #152 — a membership seen through a re-export,
67822
+ // not one this namespace owns.
67823
+ derivedKind: "reexport"
66735
67824
  };
66736
67825
  const key = exportAliasKey(description);
66737
67826
  if (seen.has(key))
@@ -66752,7 +67841,7 @@ var SysmlScopeComputation = class extends DefaultScopeComputation {
66752
67841
  // linker can resolve the qualified spelling without a full type evaluator.
66753
67842
  addInheritedQualifiedAliases(root3, exports2) {
66754
67843
  const seen = new Set(exports2.map(exportAliasKey));
66755
- const nodes = Array.from(ast_utils_exports.streamAllContents(root3)).filter((node) => specializationTargets4(node).length > 0);
67844
+ const nodes = Array.from(ast_utils_exports.streamAllContents(root3)).filter((node) => specializationTargets5(node).length > 0);
66756
67845
  if (nodes.length === 0)
66757
67846
  return;
66758
67847
  const ownerAliases = aliasesByNode(exports2);
@@ -66760,7 +67849,7 @@ var SysmlScopeComputation = class extends DefaultScopeComputation {
66760
67849
  const sourceDescriptions = new GlobalDescriptionIndex(exports2);
66761
67850
  const additions = [];
66762
67851
  for (const node of nodes) {
66763
- const targets = specializationTargets4(node);
67852
+ const targets = specializationTargets5(node);
66764
67853
  const aliases = ownerAliases.get(node) ?? [];
66765
67854
  if (aliases.length === 0)
66766
67855
  continue;
@@ -66773,7 +67862,9 @@ var SysmlScopeComputation = class extends DefaultScopeComputation {
66773
67862
  const description = {
66774
67863
  ...inherited,
66775
67864
  name: `${ownerAlias}::${suffix}`,
66776
- isDerivedAlias: true
67865
+ isDerivedAlias: true,
67866
+ // issue #152 — an implicit inherited membership.
67867
+ derivedKind: "inherited"
66777
67868
  };
66778
67869
  const key = exportAliasKey(description);
66779
67870
  if (seen.has(key))
@@ -66857,7 +67948,7 @@ var SysmlScopeComputation = class extends DefaultScopeComputation {
66857
67948
  ...base,
66858
67949
  ...visibility ? { visibility } : {},
66859
67950
  ...visibility === "private" ? { isPrivate: true } : {},
66860
- ...alias.derived ? { isDerivedAlias: true } : {},
67951
+ ...alias.derived ? { isDerivedAlias: true, derivedKind: "relative" } : {},
66861
67952
  // REQ-242 — issue #103 — mirrors what the precomputed library index
66862
67953
  // records, so consumers read def-ness the same way for workspace and
66863
67954
  // library symbols.
@@ -66906,39 +67997,26 @@ function directImportEntries(imp, descriptions) {
66906
67997
  const path10 = importedPath(imp);
66907
67998
  if (!path10)
66908
67999
  return [];
66909
- const wildcard = importWildcard(imp);
66910
- if (wildcard === "none") {
68000
+ const form = importForm(imp);
68001
+ const options = {
68002
+ resolveReferences: false,
68003
+ resolveName: (name) => descriptions.firstNamed(name)?.node
68004
+ };
68005
+ if (form.wildcard === "none") {
66911
68006
  const description = descriptions.firstNamed(path10);
66912
68007
  if (!description)
66913
68008
  return [];
66914
- return [{ name: imp.alias ?? path10.split("::").pop() ?? path10, description }];
66915
- }
66916
- const entries = [];
66917
- const seen = /* @__PURE__ */ new Set();
66918
- for (const description of descriptions.membersOf(path10, wildcard)) {
66919
- const visibility = description;
66920
- if (visibility.isPrivate || visibility.visibility === "private")
66921
- continue;
66922
- const rest = description.name.slice(path10.length + 2);
66923
- if (!rest)
66924
- continue;
66925
- const name = rest.split("::").pop();
66926
- if (!name)
66927
- continue;
66928
- const key = `${name}|${description.documentUri.toString()}|${description.path}`;
66929
- if (seen.has(key))
66930
- continue;
66931
- seen.add(key);
66932
- entries.push({ name, description });
68009
+ const name = imp.alias ?? path10.split("::").pop() ?? path10;
68010
+ return applyFilters(imp, [{ name, targetName: description.name, description }], options);
66933
68011
  }
66934
- return entries;
68012
+ return applyFilters(imp, selectMemberships(path10, form, descriptions), options);
66935
68013
  }
66936
- var SPECIALIZATION_KINDS6 = /* @__PURE__ */ new Set([":>", ":>>", "specializes", "subsets", "redefines"]);
66937
- function specializationTargets4(node) {
68014
+ var SPECIALIZATION_KINDS7 = /* @__PURE__ */ new Set([":>", ":>>", "specializes", "subsets", "redefines"]);
68015
+ function specializationTargets5(node) {
66938
68016
  const value = node;
66939
68017
  const targets = [];
66940
68018
  for (const relationship of [...value.preRelationships ?? [], ...value.relationships ?? []]) {
66941
- if (relationship.kind && SPECIALIZATION_KINDS6.has(relationship.kind)) {
68019
+ if (relationship.kind && SPECIALIZATION_KINDS7.has(relationship.kind)) {
66942
68020
  targets.push(...relationship.targets ?? []);
66943
68021
  }
66944
68022
  }
@@ -67251,6 +68329,15 @@ var SysmlCodeActionProvider = class {
67251
68329
  });
67252
68330
  }
67253
68331
  }
68332
+ if (code === "RES021") {
68333
+ actions.push({
68334
+ title: "Make this root import 'private'",
68335
+ kind: import_vscode_languageserver18.CodeActionKind.QuickFix,
68336
+ isPreferred: true,
68337
+ diagnostics: [diagnostic],
68338
+ edit: { changes: { [uri]: [import_vscode_languageserver18.TextEdit.replace(diagnostic.range, "private")] } }
68339
+ });
68340
+ }
67254
68341
  if (code === "RES015" && isImportFixData(diagnostic.data)) {
67255
68342
  const importPath = diagnostic.data.importPath;
67256
68343
  const pkg = nearestAncestor2(node, isPackage);
@@ -68781,341 +69868,6 @@ function effectiveNameHint(node) {
68781
69868
  };
68782
69869
  }
68783
69870
 
68784
- // ../language-server/out/src/services/requirement-eval.js
68785
- var UNRESOLVED = { kind: "unresolved" };
68786
- var INCONCLUSIVE = { kind: "inconclusive" };
68787
- var REDEFINE_KINDS = /* @__PURE__ */ new Set([":>>", ":>", "redefines", "subsets"]);
68788
- function declaresFeature(node, name) {
68789
- if (node.name === name)
68790
- return true;
68791
- for (const rel of [...node.preRelationships ?? [], ...node.relationships ?? []]) {
68792
- if (rel.kind && REDEFINE_KINDS.has(rel.kind) && (rel.targets ?? []).includes(name))
68793
- return true;
68794
- }
68795
- return false;
68796
- }
68797
- function evaluateExpr(node, scope) {
68798
- if (!node)
68799
- return INCONCLUSIVE;
68800
- const n = node;
68801
- switch (n.$type) {
68802
- case "NumericPrimary":
68803
- return typeof n.numVal === "number" ? { kind: "number", value: n.numVal } : INCONCLUSIVE;
68804
- case "LiteralBool":
68805
- return { kind: "boolean", value: n.value === "true" };
68806
- case "LiteralStr":
68807
- return { kind: "string", value: decodeStringLiteral(String(n.value ?? "")) };
68808
- case "LiteralNull":
68809
- return INCONCLUSIVE;
68810
- case "ParenExpr": {
68811
- const items = n.items ?? [];
68812
- return items.length === 1 ? evaluateExpr(items[0], scope) : INCONCLUSIVE;
68813
- }
68814
- case "UnaryMinusExpr": {
68815
- const v = evaluateExpr(n.operand, scope);
68816
- return v.kind === "number" ? { kind: "number", value: -v.value } : passThrough(v);
68817
- }
68818
- case "UnaryPlusExpr":
68819
- return evaluateExpr(n.operand, scope);
68820
- case "NotExpr": {
68821
- if (!n.operand)
68822
- return INCONCLUSIVE;
68823
- const v = evaluateExpr(n.operand, scope);
68824
- return v.kind === "boolean" ? { kind: "boolean", value: !v.value } : passThrough(v);
68825
- }
68826
- case "PathExpr":
68827
- return scope(String(n.path).split("."));
68828
- case "IfExpr": {
68829
- const cond = evaluateExpr(n.cond, scope);
68830
- if (cond.kind !== "boolean")
68831
- return passThrough(cond);
68832
- return cond.value ? evaluateExpr(n.thenExpr, scope) : evaluateExpr(n.elseExpr, scope);
68833
- }
68834
- case "PostfixOp": {
68835
- if (n.unit && n.unitValue)
68836
- return evaluateExpr(n.unitValue, scope);
68837
- if (n.operand)
68838
- return evaluateExpr(n.operand, scope);
68839
- return INCONCLUSIVE;
68840
- }
68841
- case "BinExpr":
68842
- return evaluateBin2(n, scope);
68843
- default:
68844
- return INCONCLUSIVE;
68845
- }
68846
- }
68847
- function passThrough(v) {
68848
- return v.kind === "unresolved" ? UNRESOLVED : INCONCLUSIVE;
68849
- }
68850
- function decodeStringLiteral(raw) {
68851
- let body = raw;
68852
- if (body.length >= 2 && body.startsWith('"') && body.endsWith('"')) {
68853
- body = body.slice(1, -1);
68854
- }
68855
- return body.replace(/\\(.)/gu, (_m, ch) => {
68856
- switch (ch) {
68857
- case "n":
68858
- return "\n";
68859
- case "t":
68860
- return " ";
68861
- case "b":
68862
- return "\b";
68863
- case "f":
68864
- return "\f";
68865
- default:
68866
- return ch;
68867
- }
68868
- });
68869
- }
68870
- function evaluateBin2(node, scope) {
68871
- const op = String(node.op);
68872
- const left = evaluateExpr(node.left, scope);
68873
- if (op === "and" || op === "&") {
68874
- if (left.kind === "boolean" && !left.value)
68875
- return { kind: "boolean", value: false };
68876
- } else if (op === "or" || op === "|") {
68877
- if (left.kind === "boolean" && left.value)
68878
- return { kind: "boolean", value: true };
68879
- } else if (op === "implies") {
68880
- if (left.kind === "boolean" && !left.value)
68881
- return { kind: "boolean", value: true };
68882
- }
68883
- const right = evaluateExpr(node.right, scope);
68884
- if (left.kind === "unresolved" || right.kind === "unresolved")
68885
- return UNRESOLVED;
68886
- if (left.kind === "inconclusive" || right.kind === "inconclusive")
68887
- return INCONCLUSIVE;
68888
- switch (op) {
68889
- case "+":
68890
- case "-":
68891
- case "*":
68892
- case "/":
68893
- case "%":
68894
- case "**":
68895
- case "^":
68896
- if (left.kind === "number" && right.kind === "number") {
68897
- return { kind: "number", value: arith(op, left.value, right.value) };
68898
- }
68899
- return INCONCLUSIVE;
68900
- case "<":
68901
- case ">":
68902
- case "<=":
68903
- case ">=":
68904
- if (left.kind === "number" && right.kind === "number") {
68905
- return { kind: "boolean", value: compare(op, left.value, right.value) };
68906
- }
68907
- return INCONCLUSIVE;
68908
- case "==":
68909
- case "!=":
68910
- case "===":
68911
- case "!==": {
68912
- const eq3 = valuesEqual(left, right);
68913
- if (eq3 === void 0)
68914
- return INCONCLUSIVE;
68915
- return { kind: "boolean", value: op.startsWith("!") ? !eq3 : eq3 };
68916
- }
68917
- case "and":
68918
- case "&":
68919
- return bothBool(left, right, (a2, b) => a2 && b);
68920
- case "or":
68921
- case "|":
68922
- return bothBool(left, right, (a2, b) => a2 || b);
68923
- case "xor":
68924
- return bothBool(left, right, (a2, b) => a2 !== b);
68925
- case "implies":
68926
- return bothBool(left, right, (a2, b) => !a2 || b);
68927
- default:
68928
- return INCONCLUSIVE;
68929
- }
68930
- }
68931
- function arith(op, a2, b) {
68932
- switch (op) {
68933
- case "+":
68934
- return a2 + b;
68935
- case "-":
68936
- return a2 - b;
68937
- case "*":
68938
- return a2 * b;
68939
- case "/":
68940
- return a2 / b;
68941
- case "%":
68942
- return a2 % b;
68943
- case "**":
68944
- case "^":
68945
- return a2 ** b;
68946
- default:
68947
- return NaN;
68948
- }
68949
- }
68950
- function compare(op, a2, b) {
68951
- switch (op) {
68952
- case "<":
68953
- return a2 < b;
68954
- case ">":
68955
- return a2 > b;
68956
- case "<=":
68957
- return a2 <= b;
68958
- case ">=":
68959
- return a2 >= b;
68960
- default:
68961
- return false;
68962
- }
68963
- }
68964
- function valuesEqual(a2, b) {
68965
- if (a2.kind === "number" && b.kind === "number")
68966
- return a2.value === b.value;
68967
- if (a2.kind === "boolean" && b.kind === "boolean")
68968
- return a2.value === b.value;
68969
- if (a2.kind === "string" && b.kind === "string")
68970
- return a2.value === b.value;
68971
- return void 0;
68972
- }
68973
- function bothBool(a2, b, f) {
68974
- if (a2.kind === "boolean" && b.kind === "boolean")
68975
- return { kind: "boolean", value: f(a2.value, b.value) };
68976
- return INCONCLUSIVE;
68977
- }
68978
- function memberNamed(node, name, seen = /* @__PURE__ */ new Set()) {
68979
- if (!node || seen.has(node))
68980
- return void 0;
68981
- seen.add(node);
68982
- for (const member of node.members ?? []) {
68983
- if (member.value !== void 0 && declaresFeature(member, name))
68984
- return member;
68985
- }
68986
- for (const member of node.members ?? []) {
68987
- if (declaresFeature(member, name))
68988
- return member;
68989
- }
68990
- const typeRef = node.typing?.type?.ref;
68991
- return typeRef ? memberNamed(typeRef, name, seen) : void 0;
68992
- }
68993
- function resolveFeatureValue(root3, segments) {
68994
- let cur = root3;
68995
- for (const seg of segments) {
68996
- cur = memberNamed(cur, seg);
68997
- if (!cur)
68998
- return UNRESOLVED;
68999
- }
69000
- if (cur.value)
69001
- return evaluateExpr(cur.value, () => INCONCLUSIVE);
69002
- return INCONCLUSIVE;
69003
- }
69004
- function subjectScope(subjectName, subjectBinding) {
69005
- const binding = subjectBinding;
69006
- return (segments) => {
69007
- if (!binding)
69008
- return INCONCLUSIVE;
69009
- if (subjectName && segments[0] === subjectName) {
69010
- const rest = segments.slice(1);
69011
- if (rest.length === 0)
69012
- return INCONCLUSIVE;
69013
- return resolveFeatureValue(binding, rest);
69014
- }
69015
- return resolveFeatureValue(binding, segments);
69016
- };
69017
- }
69018
- function subjectNameOf(req) {
69019
- const subject = (req.members ?? []).find((m) => m.$type === "SubjectDecl");
69020
- return subject?.name;
69021
- }
69022
- function gatherConstraints(req) {
69023
- const out = [];
69024
- for (const member of req.members ?? []) {
69025
- if (member.$type === "RequireConstraintStmt" && member.body) {
69026
- out.push({ kind: "require", body: member.body, text: exprText2(member.body) });
69027
- } else if (member.$type === "AssumeConstraintStmt" && member.body) {
69028
- out.push({ kind: "assume", body: member.body, text: exprText2(member.body) });
69029
- }
69030
- }
69031
- return out;
69032
- }
69033
- function exprText2(node) {
69034
- return node.$cstNode?.text?.trim() ?? "";
69035
- }
69036
- function evaluateRequirement(req, subjectBinding) {
69037
- const requirement = req;
69038
- const subjectName = subjectNameOf(requirement);
69039
- const scope = subjectScope(subjectName, subjectBinding);
69040
- const constraints = gatherConstraints(requirement);
69041
- const details = [];
69042
- let sawInconclusive = false;
69043
- let sawUnresolved = false;
69044
- let failed = false;
69045
- for (const c of constraints) {
69046
- const v = evaluateExpr(c.body, scope);
69047
- let status2;
69048
- if (v.kind === "unresolved") {
69049
- status2 = "unresolved";
69050
- sawUnresolved = true;
69051
- } else if (v.kind !== "boolean") {
69052
- status2 = "inconclusive";
69053
- sawInconclusive = true;
69054
- } else if (v.value) {
69055
- status2 = "pass";
69056
- } else if (c.kind === "require") {
69057
- status2 = "fail";
69058
- failed = true;
69059
- } else {
69060
- status2 = "inconclusive";
69061
- sawInconclusive = true;
69062
- }
69063
- details.push({ kind: c.kind, status: status2, text: c.text });
69064
- }
69065
- let status;
69066
- if (constraints.length === 0)
69067
- status = "inconclusive";
69068
- else if (failed)
69069
- status = "fail";
69070
- else if (sawUnresolved)
69071
- status = "unresolved";
69072
- else if (sawInconclusive)
69073
- status = "inconclusive";
69074
- else
69075
- status = "pass";
69076
- return { status, details };
69077
- }
69078
- function bindingName(by) {
69079
- const n = by;
69080
- if (n?.$type !== "PathExpr")
69081
- return void 0;
69082
- return n.path?.split(/::|\./).pop();
69083
- }
69084
- function evaluateVerificationCase(caseNode, resolveRequirement, resolvePart) {
69085
- const node = caseNode;
69086
- const subject = (node.members ?? []).find((m) => m.$type === "SubjectDecl");
69087
- const subjectBoundName = bindingName(subject?.value);
69088
- const subjectBinding = (subjectBoundName ? resolvePart(subjectBoundName) : void 0) ?? subject;
69089
- const verifies = [];
69090
- for (const member of node.members ?? []) {
69091
- if (member.$type !== "VerifyStmt")
69092
- continue;
69093
- const targetName = String(member.target ?? "").split(/::|\./).pop();
69094
- if (!targetName)
69095
- continue;
69096
- const req = resolveRequirement(targetName);
69097
- if (!req) {
69098
- verifies.push({ requirement: targetName, status: "unresolved" });
69099
- continue;
69100
- }
69101
- const boundName = bindingName(member.by);
69102
- const binding = (boundName ? resolvePart(boundName) : void 0) ?? subjectBinding;
69103
- verifies.push({ requirement: targetName, status: evaluateRequirement(req, binding).status });
69104
- }
69105
- let status = "inconclusive";
69106
- if (verifies.length === 0)
69107
- status = "inconclusive";
69108
- else if (verifies.some((v) => v.status === "fail"))
69109
- status = "fail";
69110
- else if (verifies.some((v) => v.status === "unresolved"))
69111
- status = "error";
69112
- else if (verifies.some((v) => v.status === "inconclusive"))
69113
- status = "inconclusive";
69114
- else
69115
- status = "pass";
69116
- return { status, verifies };
69117
- }
69118
-
69119
69871
  // ../language-server/out/src/services/codelens-provider.js
69120
69872
  function walkAst(node, fn) {
69121
69873
  fn(node);
@@ -71093,7 +71845,7 @@ async function runValidation(command) {
71093
71845
  }
71094
71846
 
71095
71847
  // src/main.ts
71096
- var VERSION2 = true ? "0.16.0" : "dev";
71848
+ var VERSION2 = true ? "0.18.0" : "dev";
71097
71849
  async function main(argv) {
71098
71850
  const command = parseArgs(argv);
71099
71851
  if (command.kind === "help") {