sysml-diagram 0.36.0 → 0.38.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 +1267 -74
- package/out/main.js.map +4 -4
- package/package.json +1 -1
- package/resources/sysml.dimension-table.json +1 -1
package/out/main.js
CHANGED
|
@@ -161054,6 +161054,125 @@ var ANCHOR_KEYWORD = {
|
|
|
161054
161054
|
bv: "package"
|
|
161055
161055
|
};
|
|
161056
161056
|
|
|
161057
|
+
// ../language-server/out/src/services/constraint-reference.js
|
|
161058
|
+
var REFERENCE_KEYWORDS = {
|
|
161059
|
+
AssertConstraintStmt: "assert",
|
|
161060
|
+
RequireConstraintStmt: "require",
|
|
161061
|
+
AssumeConstraintStmt: "assume"
|
|
161062
|
+
};
|
|
161063
|
+
function constraintReferenceOf(node) {
|
|
161064
|
+
const kind = REFERENCE_KEYWORDS[node.$type];
|
|
161065
|
+
if (!kind)
|
|
161066
|
+
return void 0;
|
|
161067
|
+
const shape = node;
|
|
161068
|
+
if (shape.constraintKw)
|
|
161069
|
+
return void 0;
|
|
161070
|
+
const negated = shape.isNegated === true;
|
|
161071
|
+
if (kind === "assert") {
|
|
161072
|
+
if (!shape.name)
|
|
161073
|
+
return void 0;
|
|
161074
|
+
const links = [shape.name, ...shape.chainSegs ?? []];
|
|
161075
|
+
return { kind, negated, path: links.join("::"), simpleName: links[links.length - 1] };
|
|
161076
|
+
}
|
|
161077
|
+
const target = shape.target;
|
|
161078
|
+
if (typeof target !== "string" || target.length === 0)
|
|
161079
|
+
return void 0;
|
|
161080
|
+
return {
|
|
161081
|
+
kind,
|
|
161082
|
+
negated,
|
|
161083
|
+
property: "target",
|
|
161084
|
+
path: target,
|
|
161085
|
+
simpleName: lastLink(target)
|
|
161086
|
+
};
|
|
161087
|
+
}
|
|
161088
|
+
function lastLink(path10) {
|
|
161089
|
+
return path10.split(/::|\./u).filter(Boolean).pop() ?? path10;
|
|
161090
|
+
}
|
|
161091
|
+
var NON_CONSTRAINT_DECL_TYPES = /* @__PURE__ */ new Set([
|
|
161092
|
+
"Package",
|
|
161093
|
+
"NamespaceDecl",
|
|
161094
|
+
"Document",
|
|
161095
|
+
"Import",
|
|
161096
|
+
"PartDecl",
|
|
161097
|
+
"ItemDecl",
|
|
161098
|
+
"AttributeDecl",
|
|
161099
|
+
"PortDecl",
|
|
161100
|
+
"OccurrenceDecl",
|
|
161101
|
+
"InterfaceDecl",
|
|
161102
|
+
"ConnectionDecl",
|
|
161103
|
+
"AllocationDecl",
|
|
161104
|
+
"ConnectorDecl",
|
|
161105
|
+
"EnumDecl",
|
|
161106
|
+
"EnumValueDecl",
|
|
161107
|
+
"MetadataDecl",
|
|
161108
|
+
"MultiplicityDecl",
|
|
161109
|
+
"ActionDecl",
|
|
161110
|
+
"StateDecl",
|
|
161111
|
+
"CalcDecl",
|
|
161112
|
+
"CaseDecl",
|
|
161113
|
+
"UseCaseDecl",
|
|
161114
|
+
"AnalysisCaseDecl",
|
|
161115
|
+
"VerificationCaseDecl",
|
|
161116
|
+
"ViewDecl",
|
|
161117
|
+
"ViewpointDecl",
|
|
161118
|
+
"RenderingDecl",
|
|
161119
|
+
"ActorDecl",
|
|
161120
|
+
"StakeholderDecl",
|
|
161121
|
+
"StructDecl",
|
|
161122
|
+
"ClassDecl",
|
|
161123
|
+
"DatatypeDecl",
|
|
161124
|
+
"AssociationDecl",
|
|
161125
|
+
"MetaclassDecl",
|
|
161126
|
+
"BehaviorDecl",
|
|
161127
|
+
"FunctionDecl",
|
|
161128
|
+
"InteractionDecl"
|
|
161129
|
+
]);
|
|
161130
|
+
var NON_CONSTRAINT_LABELS = {
|
|
161131
|
+
Package: "a package",
|
|
161132
|
+
NamespaceDecl: "a namespace",
|
|
161133
|
+
Document: "a file root namespace",
|
|
161134
|
+
Import: "an import",
|
|
161135
|
+
PartDecl: "a part",
|
|
161136
|
+
ItemDecl: "an item",
|
|
161137
|
+
AttributeDecl: "an attribute",
|
|
161138
|
+
PortDecl: "a port",
|
|
161139
|
+
OccurrenceDecl: "an occurrence",
|
|
161140
|
+
InterfaceDecl: "an interface",
|
|
161141
|
+
ConnectionDecl: "a connection",
|
|
161142
|
+
AllocationDecl: "an allocation",
|
|
161143
|
+
ConnectorDecl: "a connector",
|
|
161144
|
+
EnumDecl: "an enumeration",
|
|
161145
|
+
EnumValueDecl: "an enumeration value",
|
|
161146
|
+
MetadataDecl: "a metadata usage",
|
|
161147
|
+
MultiplicityDecl: "a multiplicity",
|
|
161148
|
+
ActionDecl: "an action",
|
|
161149
|
+
StateDecl: "a state",
|
|
161150
|
+
CalcDecl: "a calculation",
|
|
161151
|
+
CaseDecl: "a case",
|
|
161152
|
+
UseCaseDecl: "a use case",
|
|
161153
|
+
AnalysisCaseDecl: "an analysis case",
|
|
161154
|
+
VerificationCaseDecl: "a verification case",
|
|
161155
|
+
ViewDecl: "a view",
|
|
161156
|
+
ViewpointDecl: "a viewpoint",
|
|
161157
|
+
RenderingDecl: "a rendering",
|
|
161158
|
+
ActorDecl: "an actor",
|
|
161159
|
+
StakeholderDecl: "a stakeholder",
|
|
161160
|
+
StructDecl: "a structure",
|
|
161161
|
+
ClassDecl: "a class",
|
|
161162
|
+
DatatypeDecl: "a datatype",
|
|
161163
|
+
AssociationDecl: "an association",
|
|
161164
|
+
MetaclassDecl: "a metaclass",
|
|
161165
|
+
BehaviorDecl: "a behavior",
|
|
161166
|
+
FunctionDecl: "a function",
|
|
161167
|
+
InteractionDecl: "an interaction"
|
|
161168
|
+
};
|
|
161169
|
+
function isWrongKindConstraintTarget(node) {
|
|
161170
|
+
return NON_CONSTRAINT_DECL_TYPES.has(node.$type);
|
|
161171
|
+
}
|
|
161172
|
+
function wrongKindLabel(node) {
|
|
161173
|
+
return NON_CONSTRAINT_LABELS[node.$type] ?? "not a constraint";
|
|
161174
|
+
}
|
|
161175
|
+
|
|
161057
161176
|
// ../language-server/out/src/services/requirement-semantics.js
|
|
161058
161177
|
var DEFAULT_SUBJECT_TYPE = "Anything";
|
|
161059
161178
|
var MAX_INHERITANCE_DEPTH = 16;
|
|
@@ -161071,6 +161190,16 @@ var REQUIREMENT_SHAPED = /* @__PURE__ */ new Set([
|
|
|
161071
161190
|
"ObjectiveDecl",
|
|
161072
161191
|
"ViewpointDecl"
|
|
161073
161192
|
]);
|
|
161193
|
+
var CASE_SHAPED = /* @__PURE__ */ new Set([
|
|
161194
|
+
"CaseDecl",
|
|
161195
|
+
"AnalysisCaseDecl",
|
|
161196
|
+
"VerificationCaseDecl",
|
|
161197
|
+
"UseCaseDecl"
|
|
161198
|
+
]);
|
|
161199
|
+
var SUBJECT_SHAPED = /* @__PURE__ */ new Set([
|
|
161200
|
+
...REQUIREMENT_SHAPED,
|
|
161201
|
+
...CASE_SHAPED
|
|
161202
|
+
]);
|
|
161074
161203
|
var CONSTRAINT_SHAPED = /* @__PURE__ */ new Set([
|
|
161075
161204
|
"ConstraintDecl",
|
|
161076
161205
|
"InvShorthand",
|
|
@@ -161178,9 +161307,10 @@ function referencePathOf(member) {
|
|
|
161178
161307
|
return target.trim() || void 0;
|
|
161179
161308
|
if (target && typeof target === "object") {
|
|
161180
161309
|
const text = target.$refText?.trim();
|
|
161181
|
-
|
|
161310
|
+
if (text)
|
|
161311
|
+
return text;
|
|
161182
161312
|
}
|
|
161183
|
-
return
|
|
161313
|
+
return constraintReferenceOf(member)?.path;
|
|
161184
161314
|
}
|
|
161185
161315
|
function referenceTargetOf(member, resolve8) {
|
|
161186
161316
|
const target = member.target;
|
|
@@ -161361,7 +161491,7 @@ function inheritedSubject(node, resolve8, depth, seen) {
|
|
|
161361
161491
|
return void 0;
|
|
161362
161492
|
seen.add(node);
|
|
161363
161493
|
for (const supertype of supertypesOf(node, resolve8)) {
|
|
161364
|
-
if (!
|
|
161494
|
+
if (!SUBJECT_SHAPED.has(supertype.$type))
|
|
161365
161495
|
continue;
|
|
161366
161496
|
const own = ownSubject(supertype);
|
|
161367
161497
|
if (own)
|
|
@@ -161685,7 +161815,7 @@ function memberNamed(node, name, seen = /* @__PURE__ */ new Set()) {
|
|
|
161685
161815
|
const typeRef = node.typing?.type?.ref;
|
|
161686
161816
|
return typeRef ? memberNamed(typeRef, name, seen) : void 0;
|
|
161687
161817
|
}
|
|
161688
|
-
function resolveFeatureValue(root4, segments) {
|
|
161818
|
+
function resolveFeatureValue(root4, segments, ext) {
|
|
161689
161819
|
let cur = root4;
|
|
161690
161820
|
for (const seg of segments) {
|
|
161691
161821
|
cur = memberNamed(cur, seg);
|
|
@@ -161693,7 +161823,7 @@ function resolveFeatureValue(root4, segments) {
|
|
|
161693
161823
|
return UNRESOLVED;
|
|
161694
161824
|
}
|
|
161695
161825
|
if (cur.value)
|
|
161696
|
-
return evaluateExpr(cur.value, () => INCONCLUSIVE);
|
|
161826
|
+
return evaluateExpr(cur.value, () => INCONCLUSIVE, ext);
|
|
161697
161827
|
return INCONCLUSIVE;
|
|
161698
161828
|
}
|
|
161699
161829
|
function subjectScope(subjectName, subjectBinding) {
|
|
@@ -161788,6 +161918,83 @@ function evaluateSatisfy(stmt, resolveRequirement, resolvePart, resolve8) {
|
|
|
161788
161918
|
const status = result.status === "pass" ? "fail" : result.status === "fail" ? "pass" : result.status;
|
|
161789
161919
|
return { status, requirement, satisfier };
|
|
161790
161920
|
}
|
|
161921
|
+
var CONSTRAINT_SHAPED_TYPES = /* @__PURE__ */ new Set([
|
|
161922
|
+
"ConstraintDecl",
|
|
161923
|
+
"InvShorthand",
|
|
161924
|
+
"RequirementDecl",
|
|
161925
|
+
"ConcernDecl",
|
|
161926
|
+
"PredicateDecl",
|
|
161927
|
+
"AssertConstraintStmt",
|
|
161928
|
+
"RequireConstraintStmt",
|
|
161929
|
+
"AssumeConstraintStmt"
|
|
161930
|
+
]);
|
|
161931
|
+
function exprText2(node) {
|
|
161932
|
+
return node?.$cstNode?.text?.trim() ?? "";
|
|
161933
|
+
}
|
|
161934
|
+
function rootOf2(node) {
|
|
161935
|
+
let current2 = node;
|
|
161936
|
+
while (current2.$container)
|
|
161937
|
+
current2 = current2.$container;
|
|
161938
|
+
return current2;
|
|
161939
|
+
}
|
|
161940
|
+
function* walkMembers(node) {
|
|
161941
|
+
for (const member of [...node.elements ?? [], ...node.members ?? []]) {
|
|
161942
|
+
yield member;
|
|
161943
|
+
yield* walkMembers(member);
|
|
161944
|
+
}
|
|
161945
|
+
}
|
|
161946
|
+
function documentConstraintResolver() {
|
|
161947
|
+
return (reference, member) => {
|
|
161948
|
+
for (const candidate of walkMembers(rootOf2(member))) {
|
|
161949
|
+
if (candidate.name === reference.simpleName && CONSTRAINT_SHAPED_TYPES.has(candidate.$type)) {
|
|
161950
|
+
return candidate;
|
|
161951
|
+
}
|
|
161952
|
+
}
|
|
161953
|
+
return void 0;
|
|
161954
|
+
};
|
|
161955
|
+
}
|
|
161956
|
+
var assertionExpression = (node) => {
|
|
161957
|
+
const expr = node;
|
|
161958
|
+
return (expr.$type === "NumericPrimary" || expr.$type === "PostfixOp") && expr.unit ? INCONCLUSIVE : void 0;
|
|
161959
|
+
};
|
|
161960
|
+
function evaluateAssertion(node, resolveConstraint = documentConstraintResolver()) {
|
|
161961
|
+
const member = node;
|
|
161962
|
+
if (member.$type !== "AssertConstraintStmt")
|
|
161963
|
+
return void 0;
|
|
161964
|
+
const reference = constraintReferenceOf(member);
|
|
161965
|
+
const negated = reference?.negated ?? member.isNegated === true;
|
|
161966
|
+
let body;
|
|
161967
|
+
let text;
|
|
161968
|
+
let target;
|
|
161969
|
+
if (reference) {
|
|
161970
|
+
text = `${reference.kind}${reference.negated ? " not" : ""} ${reference.path}`;
|
|
161971
|
+
target = resolveConstraint(reference, member);
|
|
161972
|
+
if (!target)
|
|
161973
|
+
return { status: "unresolved", text };
|
|
161974
|
+
body = member.body ?? constraintBodyOf(target, documentResolver(member));
|
|
161975
|
+
} else {
|
|
161976
|
+
body = member.body;
|
|
161977
|
+
text = exprText2(member.body);
|
|
161978
|
+
}
|
|
161979
|
+
if (!body)
|
|
161980
|
+
return { status: "inconclusive", text };
|
|
161981
|
+
const scope = (segments) => {
|
|
161982
|
+
for (const owner of [member, target]) {
|
|
161983
|
+
if (!owner)
|
|
161984
|
+
continue;
|
|
161985
|
+
if (memberNamed(owner, segments[0])) {
|
|
161986
|
+
return resolveFeatureValue(owner, segments, assertionExpression);
|
|
161987
|
+
}
|
|
161988
|
+
}
|
|
161989
|
+
return INCONCLUSIVE;
|
|
161990
|
+
};
|
|
161991
|
+
const value = negate2(evaluateExpr(body, scope, assertionExpression), negated);
|
|
161992
|
+
if (value.kind === "unresolved")
|
|
161993
|
+
return { status: "unresolved", text };
|
|
161994
|
+
if (value.kind !== "boolean")
|
|
161995
|
+
return { status: "inconclusive", text };
|
|
161996
|
+
return { status: value.value ? "pass" : "fail", text };
|
|
161997
|
+
}
|
|
161791
161998
|
function bindingName(by) {
|
|
161792
161999
|
const n2 = by;
|
|
161793
162000
|
if (n2?.$type !== "PathExpr")
|
|
@@ -163036,6 +163243,21 @@ function unwrap(node) {
|
|
|
163036
163243
|
}
|
|
163037
163244
|
var namedChildrenByNode = /* @__PURE__ */ new WeakMap();
|
|
163038
163245
|
var childrenByName = /* @__PURE__ */ new WeakMap();
|
|
163246
|
+
var REFERENCE_FORM_DECLARATIONS = {
|
|
163247
|
+
PerformStmt: "actionKw",
|
|
163248
|
+
EntryAction: "actionKw",
|
|
163249
|
+
DoAction: "actionKw",
|
|
163250
|
+
ExitAction: "actionKw",
|
|
163251
|
+
ExhibitStateDecl: "stateKw",
|
|
163252
|
+
AssertConstraintStmt: "constraintKw",
|
|
163253
|
+
EventDecl: "isOccurrence"
|
|
163254
|
+
};
|
|
163255
|
+
function isReferenceFormDeclaration(node) {
|
|
163256
|
+
const keyword = REFERENCE_FORM_DECLARATIONS[node.$type];
|
|
163257
|
+
if (!keyword)
|
|
163258
|
+
return false;
|
|
163259
|
+
return node[keyword] !== true;
|
|
163260
|
+
}
|
|
163039
163261
|
function directNamedChildren(node) {
|
|
163040
163262
|
const cached = namedChildrenByNode.get(node);
|
|
163041
163263
|
if (cached)
|
|
@@ -163044,6 +163266,8 @@ function directNamedChildren(node) {
|
|
|
163044
163266
|
const seen = /* @__PURE__ */ new Set();
|
|
163045
163267
|
for (const raw of ast_utils_exports.streamContents(node)) {
|
|
163046
163268
|
const child = unwrap(raw);
|
|
163269
|
+
if (isReferenceFormDeclaration(child))
|
|
163270
|
+
continue;
|
|
163047
163271
|
if (!nameOf(child) || seen.has(child))
|
|
163048
163272
|
continue;
|
|
163049
163273
|
seen.add(child);
|
|
@@ -163525,7 +163749,7 @@ var FeaturePathResolver = class {
|
|
|
163525
163749
|
}
|
|
163526
163750
|
for (let owner = node.$container; owner; owner = owner.$container) {
|
|
163527
163751
|
const declaredName3 = owner.name;
|
|
163528
|
-
if (typeof declaredName3 === "string" && canonicalEscapedName(declaredName3) === name && !isSelfReference(owner, node)) {
|
|
163752
|
+
if (typeof declaredName3 === "string" && canonicalEscapedName(declaredName3) === name && !isReferenceFormDeclaration(owner) && !isSelfReference(owner, node)) {
|
|
163529
163753
|
return this.targetForNode(owner, this.memberInventoryKnown(owner, snapshot));
|
|
163530
163754
|
}
|
|
163531
163755
|
if (boundVariableName(owner) === name) {
|
|
@@ -166341,6 +166565,16 @@ var directionOf = (node) => {
|
|
|
166341
166565
|
return void 0;
|
|
166342
166566
|
return mods.find((m) => m === "in" || m === "out" || m === "inout");
|
|
166343
166567
|
};
|
|
166568
|
+
function parameterKeyword(node) {
|
|
166569
|
+
const direction = directionOf(node);
|
|
166570
|
+
if (!direction)
|
|
166571
|
+
return void 0;
|
|
166572
|
+
let owner = node.$container;
|
|
166573
|
+
while (owner?.$type === "PrefixMetadataMember" || owner?.$type === "MemberPrefixDecl") {
|
|
166574
|
+
owner = owner.$container;
|
|
166575
|
+
}
|
|
166576
|
+
return owner && (isConstraintDecl(owner) || isCalcDecl(owner)) ? `${direction} parameter` : void 0;
|
|
166577
|
+
}
|
|
166344
166578
|
function keywordFor(node) {
|
|
166345
166579
|
const n2 = node;
|
|
166346
166580
|
if (node.$type === "VariantReference")
|
|
@@ -166402,6 +166636,9 @@ function keywordFor(node) {
|
|
|
166402
166636
|
DoAction: "do action",
|
|
166403
166637
|
ExitAction: "exit action"
|
|
166404
166638
|
};
|
|
166639
|
+
const parameter = parameterKeyword(node);
|
|
166640
|
+
if (parameter)
|
|
166641
|
+
return parameter;
|
|
166405
166642
|
if (t === "ActionDecl" && n2.inlineBody?.$type === "AcceptNode") {
|
|
166406
166643
|
return "accept action";
|
|
166407
166644
|
}
|
|
@@ -167879,6 +168116,19 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
167879
168116
|
const all = [...ast_utils_exports.streamAllContents(scope)];
|
|
167880
168117
|
const annotationNodes = all.filter(isGvAnnotationNode);
|
|
167881
168118
|
const annotationNodeSet = new Set(annotationNodes);
|
|
168119
|
+
const declaredOwnerOf = (node) => {
|
|
168120
|
+
let owner = node.$container;
|
|
168121
|
+
while (owner?.$type === "PrefixMetadataMember" || owner?.$type === "MemberPrefixDecl") {
|
|
168122
|
+
owner = owner.$container;
|
|
168123
|
+
}
|
|
168124
|
+
return owner;
|
|
168125
|
+
};
|
|
168126
|
+
const isDefinitionParameter = (node) => {
|
|
168127
|
+
if (directionOf(node) === void 0)
|
|
168128
|
+
return false;
|
|
168129
|
+
const owner = declaredOwnerOf(node);
|
|
168130
|
+
return !!owner && owner.isDef === true && (isConstraintDecl(owner) || isCalcDecl(owner));
|
|
168131
|
+
};
|
|
167882
168132
|
const usageNodes = all.filter(isGvExplicitUsage);
|
|
167883
168133
|
const usageNodeSet = new Set(usageNodes);
|
|
167884
168134
|
const usageDefinitions = new Map(usageNodes.map((node) => [
|
|
@@ -167917,7 +168167,20 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
167917
168167
|
semanticOwners.set(member, found);
|
|
167918
168168
|
return found;
|
|
167919
168169
|
};
|
|
168170
|
+
const readsAsAttribute = (node) => isAttributeDecl(node) || isAttributeDecl(this.resolveType(node, index2));
|
|
168171
|
+
const implicitlyRedefined = (node) => {
|
|
168172
|
+
const name = nameOf2(node);
|
|
168173
|
+
const owner = semanticOwner(node);
|
|
168174
|
+
if (!name || !owner || owner.isDef === true)
|
|
168175
|
+
return void 0;
|
|
168176
|
+
const definition = usageDefinitions.get(owner);
|
|
168177
|
+
if (!definition)
|
|
168178
|
+
return void 0;
|
|
168179
|
+
return membersOf(definition).find((member) => nameOf2(member) === name);
|
|
168180
|
+
};
|
|
167920
168181
|
const attributeUsages = new Set(usageNodes.filter((node) => {
|
|
168182
|
+
if (isDefinitionParameter(node))
|
|
168183
|
+
return false;
|
|
167921
168184
|
if (isAttributeDecl(node))
|
|
167922
168185
|
return true;
|
|
167923
168186
|
const owner = semanticOwner(node);
|
|
@@ -167928,12 +168191,23 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
167928
168191
|
const definition = usageDefinitions.get(node);
|
|
167929
168192
|
if (definition && isAttributeDecl(definition))
|
|
167930
168193
|
return true;
|
|
167931
|
-
|
|
168194
|
+
if (redefinitionTargetsOf(node).some((target) => {
|
|
167932
168195
|
const inherited = this.resolveFeatureInheritanceTarget(node, target, index2, /* @__PURE__ */ new Set());
|
|
167933
168196
|
return inherited && isAttributeDecl(inherited);
|
|
167934
|
-
})
|
|
168197
|
+
}))
|
|
168198
|
+
return true;
|
|
168199
|
+
const implicit = implicitlyRedefined(node);
|
|
168200
|
+
return !!implicit && readsAsAttribute(implicit);
|
|
167935
168201
|
}));
|
|
167936
168202
|
const attributeValue = (node) => valueTextOf(node) ?? node.default?.value?.$cstNode?.text ?? "";
|
|
168203
|
+
const returnMemberOf = (node) => membersOf(node).find((m) => m.$type === "ReturnDecl");
|
|
168204
|
+
const expressionBody = (node) => {
|
|
168205
|
+
const ret = isCalcDecl(node) ? returnMemberOf(node) : void 0;
|
|
168206
|
+
const text = ret ? valueTextOf(ret) ?? "" : node.body?.$cstNode?.text ?? "";
|
|
168207
|
+
return text.replace(/\s+/g, " ").trim();
|
|
168208
|
+
};
|
|
168209
|
+
const declaresExpression = (node) => node.body !== void 0 || isCalcDecl(node) && valueTextOf(returnMemberOf(node)) !== void 0;
|
|
168210
|
+
const showsExpressionField = (node) => (isConstraintDecl(node) || isCalcDecl(node)) && (node.isDef === true || declaresExpression(node));
|
|
167937
168211
|
const ids = /* @__PURE__ */ new Map();
|
|
167938
168212
|
const unnamedOrdinals = /* @__PURE__ */ new Map();
|
|
167939
168213
|
const semanticId = (node) => {
|
|
@@ -167989,6 +168263,8 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
167989
168263
|
multiplicity: this.multText(n2),
|
|
167990
168264
|
type: typeText(n2) ?? (usageDefinitions.get(n2) ? nameOf2(usageDefinitions.get(n2)) : void 0),
|
|
167991
168265
|
...attributeUsages.has(n2) ? { value: attributeValue(n2) } : {},
|
|
168266
|
+
// REQ-208/209 — the constraint or calculation expression field.
|
|
168267
|
+
...showsExpressionField(n2) ? { value: expressionBody(n2) } : {},
|
|
167992
168268
|
compartments: extra?.compartments ?? this.compartmentsFor(n2, uri, index2, shape === "box"),
|
|
167993
168269
|
...packageOf2(n2),
|
|
167994
168270
|
source: sourceOf2(n2, uri),
|
|
@@ -168003,9 +168279,60 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
168003
168279
|
for (const usage of usageNodes) {
|
|
168004
168280
|
pushNode(usage, "box", false, {
|
|
168005
168281
|
compartments: this.compartmentsFor(usage, uri, index2, true, false),
|
|
168006
|
-
|
|
168282
|
+
// REQ-376 — a parameter keeps its own banner; only an ordinary
|
|
168283
|
+
// attribute usage is relabelled by its value-carrying role.
|
|
168284
|
+
...attributeUsages.has(usage) && !parameterKeyword(usage) ? { keyword: "attribute" } : {}
|
|
168007
168285
|
});
|
|
168008
168286
|
}
|
|
168287
|
+
for (const usage of usageNodes) {
|
|
168288
|
+
if (!isConstraintDecl(usage) || usage.isDef === true)
|
|
168289
|
+
continue;
|
|
168290
|
+
const definition = usageDefinitions.get(usage);
|
|
168291
|
+
if (!definition || !isConstraintDecl(definition))
|
|
168292
|
+
continue;
|
|
168293
|
+
const usageId = semanticId(usage);
|
|
168294
|
+
const local = new Set(membersOf(usage).flatMap((member) => [nameOf2(member), ...redefinitionTargetsOf(member)]).filter((name) => !!name));
|
|
168295
|
+
for (const member of membersOf(definition)) {
|
|
168296
|
+
const name = nameOf2(member);
|
|
168297
|
+
if (!name || local.has(name))
|
|
168298
|
+
continue;
|
|
168299
|
+
if (directionOf(member) === void 0 && !isAttributeDecl(member))
|
|
168300
|
+
continue;
|
|
168301
|
+
const id2 = `${usageId}::${name}`;
|
|
168302
|
+
if (nodes.some((existing) => existing.id === id2))
|
|
168303
|
+
continue;
|
|
168304
|
+
nodes.push({
|
|
168305
|
+
id: id2,
|
|
168306
|
+
name: effectiveNameOf(member) ?? name,
|
|
168307
|
+
keyword: "attribute",
|
|
168308
|
+
isDef: false,
|
|
168309
|
+
shape: "box",
|
|
168310
|
+
multiplicity: this.multText(member),
|
|
168311
|
+
type: typeText(member),
|
|
168312
|
+
value: attributeValue(member),
|
|
168313
|
+
compartments: [],
|
|
168314
|
+
parent: usageId,
|
|
168315
|
+
// Navigation lands on the declaration the member comes from.
|
|
168316
|
+
source: sourceOf2(member, uri),
|
|
168317
|
+
meta: {
|
|
168318
|
+
gvUsage: true,
|
|
168319
|
+
gvOwnerId: usageId,
|
|
168320
|
+
gvExplicit: true,
|
|
168321
|
+
gvDeclaredName: name,
|
|
168322
|
+
gvDeclaredType: typeText(member) ?? "",
|
|
168323
|
+
// REQ-364 — the concrete usage that owns a local edit, plus
|
|
168324
|
+
// the relative redefinition path to write inside it.
|
|
168325
|
+
localUsageId: usageId,
|
|
168326
|
+
localUsageName: nameOf2(usage),
|
|
168327
|
+
localUsageSource: sourceOf2(usage, uri),
|
|
168328
|
+
localUsagePath: [name],
|
|
168329
|
+
expandedFromDefinition: true,
|
|
168330
|
+
declarationId: qnameOf(member),
|
|
168331
|
+
declarationSource: sourceOf2(member, uri)
|
|
168332
|
+
}
|
|
168333
|
+
});
|
|
168334
|
+
}
|
|
168335
|
+
}
|
|
168009
168336
|
for (const p of packageNodes) {
|
|
168010
168337
|
const pn = p;
|
|
168011
168338
|
pushNode(p, "package", false, {
|
|
@@ -168322,6 +168649,28 @@ var SysmlDiagramModelProvider = class _SysmlDiagramModelProvider {
|
|
|
168322
168649
|
}
|
|
168323
168650
|
}
|
|
168324
168651
|
}
|
|
168652
|
+
const CLAIM_EDGE_KINDS = {
|
|
168653
|
+
AssertConstraintStmt: "assert",
|
|
168654
|
+
AssumeConstraintStmt: "assume",
|
|
168655
|
+
RequireConstraintStmt: "require"
|
|
168656
|
+
};
|
|
168657
|
+
for (const owner of [...defNodes, ...usageNodes]) {
|
|
168658
|
+
for (const m of membersOf(owner)) {
|
|
168659
|
+
const claim = CLAIM_EDGE_KINDS[m.$type];
|
|
168660
|
+
if (!claim)
|
|
168661
|
+
continue;
|
|
168662
|
+
const negated = m.isNegated === true;
|
|
168663
|
+
const label = `\xAB${claim}${negated ? " not" : ""}\xBB`;
|
|
168664
|
+
const reference = constraintReferenceOf(m);
|
|
168665
|
+
if (reference) {
|
|
168666
|
+
linkByName(claim, owner, reference.path, label, m);
|
|
168667
|
+
continue;
|
|
168668
|
+
}
|
|
168669
|
+
const typed = typeText(m);
|
|
168670
|
+
if (typed)
|
|
168671
|
+
linkByName(claim, owner, typed, label, m);
|
|
168672
|
+
}
|
|
168673
|
+
}
|
|
168325
168674
|
const allocPairs = [
|
|
168326
168675
|
...all.filter((m) => m.$type === "AllocateStmt").map((a2) => ({
|
|
168327
168676
|
from: String(a2.source ?? ""),
|
|
@@ -172388,7 +172737,12 @@ ${node.id}`;
|
|
|
172388
172737
|
idOf.set(n2, id2);
|
|
172389
172738
|
nodes.push({
|
|
172390
172739
|
id: id2,
|
|
172391
|
-
|
|
172740
|
+
// REQ-404 — a redeclaration (`actor :>> driver = …`) writes no name
|
|
172741
|
+
// of its own; the name it is KNOWN BY is the one it redefines, which
|
|
172742
|
+
// is the same derivation the rest of the model is labelled by. The
|
|
172743
|
+
// last-resort fallback is the SHAPE, never the literal 'subject':
|
|
172744
|
+
// that string labelled every unnamed actor "subject" on the card.
|
|
172745
|
+
name: effectiveNameOf(n2) ?? lastSeg(typeText(n2) ?? shape),
|
|
172392
172746
|
keyword: keywordFor(n2),
|
|
172393
172747
|
isDef: n2.isDef === true,
|
|
172394
172748
|
shape,
|
|
@@ -172432,14 +172786,15 @@ ${node.id}`;
|
|
|
172432
172786
|
const declarationKey = (subject) => {
|
|
172433
172787
|
const type = this.resolveType(subject, index2);
|
|
172434
172788
|
const typeKey = (type ? qnameOf(type) : void 0) || typeText(subject) || "";
|
|
172435
|
-
const name =
|
|
172789
|
+
const name = effectiveNameOf(subject) ?? "";
|
|
172436
172790
|
return name || typeKey ? `subject:${name}|${typeKey}` : "";
|
|
172437
172791
|
};
|
|
172438
172792
|
const declarationText = (subject) => {
|
|
172439
172793
|
const value = subjectValuePath(subject);
|
|
172440
172794
|
const type = typeText(subject);
|
|
172441
|
-
return [
|
|
172795
|
+
return [effectiveNameOf(subject), type ? `: ${type}` : void 0, value ? `= ${value}` : void 0].filter((part) => !!part).join(" ");
|
|
172442
172796
|
};
|
|
172797
|
+
const boundKeysOfDeclaration = /* @__PURE__ */ new Map();
|
|
172443
172798
|
const subjectKey = (subject, seen = /* @__PURE__ */ new Set()) => {
|
|
172444
172799
|
const canonical = canonicalSubjectTarget(subject);
|
|
172445
172800
|
if (canonical && isSubjectDecl(canonical) && canonical !== subject && !seen.has(canonical)) {
|
|
@@ -172448,7 +172803,14 @@ ${node.id}`;
|
|
|
172448
172803
|
}
|
|
172449
172804
|
const canonicalQName = canonical && !isSubjectDecl(canonical) ? qnameOf(canonical) : "";
|
|
172450
172805
|
const value = subjectValuePath(subject);
|
|
172451
|
-
|
|
172806
|
+
if (canonicalQName)
|
|
172807
|
+
return `target:${canonicalQName}`;
|
|
172808
|
+
if (value)
|
|
172809
|
+
return `value:${value}`;
|
|
172810
|
+
const adopted = boundKeysOfDeclaration.get(subject);
|
|
172811
|
+
if (adopted?.size === 1)
|
|
172812
|
+
return [...adopted][0];
|
|
172813
|
+
return declarationKey(subject) || `decl:${qnameOf(subject) || `${subject.$cstNode?.offset ?? 0}:subject`}`;
|
|
172452
172814
|
};
|
|
172453
172815
|
const subjectIdByKey = /* @__PURE__ */ new Map();
|
|
172454
172816
|
const subjectOfCase = /* @__PURE__ */ new Map();
|
|
@@ -172459,7 +172821,7 @@ ${node.id}`;
|
|
|
172459
172821
|
const key2 = subjectKey(subject);
|
|
172460
172822
|
let sid = subjectIdByKey.get(key2);
|
|
172461
172823
|
if (!sid) {
|
|
172462
|
-
const label =
|
|
172824
|
+
const label = effectiveNameOf(identity6) ?? lastSeg(value || typeText(identity6) || "subject");
|
|
172463
172825
|
add(identity6, "subject", {
|
|
172464
172826
|
id: `${scopeId}::__cv_subject__::${key2}`,
|
|
172465
172827
|
name: label,
|
|
@@ -172471,6 +172833,26 @@ ${node.id}`;
|
|
|
172471
172833
|
idOf.set(subject, sid);
|
|
172472
172834
|
return sid;
|
|
172473
172835
|
};
|
|
172836
|
+
for (const c of displayedCases) {
|
|
172837
|
+
const declared = declaredMembers(c).filter(isSubjectDecl);
|
|
172838
|
+
for (const bound of declared) {
|
|
172839
|
+
if (!subjectValuePath(bound))
|
|
172840
|
+
continue;
|
|
172841
|
+
const name = effectiveNameOf(bound);
|
|
172842
|
+
if (!name)
|
|
172843
|
+
continue;
|
|
172844
|
+
for (const target of declared) {
|
|
172845
|
+
if (target === bound || subjectValuePath(target))
|
|
172846
|
+
continue;
|
|
172847
|
+
if (effectiveNameOf(target) !== name)
|
|
172848
|
+
continue;
|
|
172849
|
+
let keys3 = boundKeysOfDeclaration.get(target);
|
|
172850
|
+
if (!keys3)
|
|
172851
|
+
boundKeysOfDeclaration.set(target, keys3 = /* @__PURE__ */ new Set());
|
|
172852
|
+
keys3.add(subjectKey(bound));
|
|
172853
|
+
}
|
|
172854
|
+
}
|
|
172855
|
+
}
|
|
172474
172856
|
const denotesSubject = (s) => !!(nameOf2(s) || typeText(s) || subjectValuePath(s));
|
|
172475
172857
|
for (const c of displayedCases) {
|
|
172476
172858
|
const declared = declaredMembers(c).filter(isSubjectDecl);
|
|
@@ -172513,16 +172895,47 @@ ${node.id}`;
|
|
|
172513
172895
|
};
|
|
172514
172896
|
const actorOfCase = [];
|
|
172515
172897
|
const actorCasePairs = /* @__PURE__ */ new Set();
|
|
172516
|
-
const
|
|
172898
|
+
const actorTypeKey = (actor) => {
|
|
172899
|
+
const type = this.resolveType(actor, index2);
|
|
172900
|
+
return (type ? qnameOf(type) : void 0) || typeText(actor) || "";
|
|
172901
|
+
};
|
|
172902
|
+
const actorTypeSource = (actor, siblings) => {
|
|
172903
|
+
if (actorTypeKey(actor))
|
|
172904
|
+
return actor;
|
|
172905
|
+
const name = effectiveNameOf(actor);
|
|
172906
|
+
if (!name)
|
|
172907
|
+
return void 0;
|
|
172908
|
+
return siblings.find((sibling) => sibling !== actor && effectiveNameOf(sibling) === name && !!actorTypeKey(sibling));
|
|
172909
|
+
};
|
|
172910
|
+
const actorDeclarationKey = (actor, siblings) => {
|
|
172911
|
+
const name = effectiveNameOf(actor) ?? "";
|
|
172912
|
+
const typeKey = actorTypeKey(actorTypeSource(actor, siblings) ?? actor);
|
|
172913
|
+
return name || typeKey ? `actor:${name}|${typeKey}` : "";
|
|
172914
|
+
};
|
|
172915
|
+
const actorKey = (actor, siblings) => actorDeclarationKey(actor, siblings) || `decl:${qnameOf(actor) || ""}:${actor.$cstNode?.offset ?? 0}`;
|
|
172916
|
+
const actorIdByKey = /* @__PURE__ */ new Map();
|
|
172917
|
+
const addActor = (actor, siblings) => {
|
|
172918
|
+
const canonical = actorCanonical(actor);
|
|
172919
|
+
const key2 = actorKey(canonical, siblings);
|
|
172920
|
+
let aid = actorIdByKey.get(key2);
|
|
172921
|
+
if (aid === void 0) {
|
|
172922
|
+
const typeSource = actorTypeSource(canonical, siblings);
|
|
172923
|
+
add(canonical, "actor", {
|
|
172924
|
+
id: `${scopeId}::__cv_actor__::${key2}`,
|
|
172925
|
+
...typeSource && typeSource !== canonical ? { type: typeText(typeSource) } : {},
|
|
172926
|
+
meta: { cvAuxiliary: true }
|
|
172927
|
+
});
|
|
172928
|
+
aid = idOf.get(canonical);
|
|
172929
|
+
actorIdByKey.set(key2, aid);
|
|
172930
|
+
}
|
|
172931
|
+
idOf.set(actor, aid);
|
|
172932
|
+
return aid;
|
|
172933
|
+
};
|
|
172517
172934
|
for (const c of displayedCases) {
|
|
172518
|
-
|
|
172519
|
-
|
|
172520
|
-
|
|
172521
|
-
const
|
|
172522
|
-
if (!idOf.has(canonical))
|
|
172523
|
-
add(canonical, "actor", { id: anonymousActorId(canonical), meta: { cvAuxiliary: true } });
|
|
172524
|
-
const actorId = idOf.get(canonical);
|
|
172525
|
-
idOf.set(a2, actorId);
|
|
172935
|
+
const siblings = declaredMembers(c).filter(isActorDecl);
|
|
172936
|
+
const typeSources = siblings.some((a2) => !actorTypeKey(a2)) ? [...siblings, ...this.inheritedTypesOf(c, index2).flatMap((t) => membersOf(t).filter(isActorDecl))] : siblings;
|
|
172937
|
+
for (const a2 of siblings) {
|
|
172938
|
+
const actorId = addActor(a2, typeSources);
|
|
172526
172939
|
const pair = `${actorId}\0${qnameOf(c) ?? nameOf2(c) ?? ""}`;
|
|
172527
172940
|
if (!actorCasePairs.has(pair)) {
|
|
172528
172941
|
actorCasePairs.add(pair);
|
|
@@ -174271,7 +174684,7 @@ ${node.id}`;
|
|
|
174271
174684
|
const inherited = includeInherited ? this.inheritedItems(node, index2, uri) : [];
|
|
174272
174685
|
const inheritedRows = (predicate, text = (member) => this.featureText(member)) => inherited.filter(({ member }) => predicate(member)).map(({ member, source }) => ({ text: `^${text(member)}`, source }));
|
|
174273
174686
|
const usages = (guard) => members.filter((m) => guard(m) && m.isDef !== true && nameOf2(m) && isOrdinaryMember(m));
|
|
174274
|
-
const
|
|
174687
|
+
const exprText4 = (m) => (m.body?.$cstNode?.text ?? "").replace(/\s+/g, " ").trim();
|
|
174275
174688
|
const statementText = (m) => (m.$cstNode?.text ?? this.featureText(m)).replace(/\s+/g, " ").replace(/;$/, "").trim();
|
|
174276
174689
|
const canonicalFeatureText = (m) => m.$type === "FeatureShorthand" || m.$type === "FeatureRedefinitionShorthand" ? statementText(m) : this.featureText(m);
|
|
174277
174690
|
const out = [];
|
|
@@ -174323,8 +174736,8 @@ ${node.id}`;
|
|
|
174323
174736
|
add("occurrences", members.map((m) => this.thenActionMemberNode(m) ?? m).filter(isNonVariantMember).filter((m) => isEventDecl(m) && m.isOccurrence === true && nameOf2(m)).map((m) => item(m)));
|
|
174324
174737
|
add("calcs", undirected(isCalcDecl).map((m) => item(m)));
|
|
174325
174738
|
add("constraints", undirected(isConstraintDecl).map((m) => item(m)));
|
|
174326
|
-
add("assume constraints", members.filter((m) => m.$type === "AssumeConstraintStmt").map((m) => item(m,
|
|
174327
|
-
add("require constraints", members.filter((m) => m.$type === "RequireConstraintStmt").map((m) => item(m,
|
|
174739
|
+
add("assume constraints", members.filter((m) => m.$type === "AssumeConstraintStmt").map((m) => item(m, exprText4(m) || "assume constraint")));
|
|
174740
|
+
add("require constraints", members.filter((m) => m.$type === "RequireConstraintStmt").map((m) => item(m, exprText4(m) || `require ${this.featurePath(m.target) ?? ""}`.trim())));
|
|
174328
174741
|
add("actors", members.filter(isActorDecl).filter(isNonVariantMember).map((m) => item(m)));
|
|
174329
174742
|
add("stakeholders", members.filter(isStakeholderDecl).filter(isNonVariantMember).map((m) => item(m)));
|
|
174330
174743
|
add("frames", members.filter((m) => m.$type === "FrameMember").map((m) => item(m, this.refText(m.target) ?? "concern")));
|
|
@@ -174353,7 +174766,7 @@ ${node.id}`;
|
|
|
174353
174766
|
]);
|
|
174354
174767
|
add("result", members.filter((m) => m.$type === "ReturnDecl").map((m) => item(m, `return${nameOf2(m) ? ` ${nameOf2(m)}` : ""}${typeText(m) ? ` : ${typeText(m)}` : ""}`)));
|
|
174355
174768
|
if (isConstraintDecl(node))
|
|
174356
|
-
add("expression",
|
|
174769
|
+
add("expression", exprText4(node) ? [{ text: exprText4(node), source: sourceOf2(node, uri) }] : []);
|
|
174357
174770
|
const enumValueMembers = isEnumDecl(node) ? members.filter(isOwnedEnumerationValue) : members.filter((m) => isNonVariantMember(m) && m.$type === "EnumValueDecl" && !m.typing);
|
|
174358
174771
|
add("enums", enumValueMembers.map((m) => {
|
|
174359
174772
|
const nm = nameOf2(m);
|
|
@@ -174382,11 +174795,11 @@ ${node.id}`;
|
|
|
174382
174795
|
add("state transition", members.filter((m) => m.$type === "TransitionDecl").map((m) => item(m, `${m.from ?? ""} \u2192 ${m.to ?? ""}`)));
|
|
174383
174796
|
const successionText = (m) => (m.$cstNode?.text ?? "").replace(/\s+/g, " ").replace(/;$/, "").trim();
|
|
174384
174797
|
add("successions", members.filter((m) => m.$type === "FirstThenChain" || m.$type === "SuccessionStmt" || m.$type === "ThenActionMember" && typeof m.target === "string" || m.$type === "ElseSuccessionMember" || (m.$type === "AcceptNode" || m.$type === "IfActionNode") && typeof m.thenTarget === "string").map((m) => item(m, successionText(m))).filter((row) => !!row.text));
|
|
174385
|
-
add("assert constraints", members.filter((m) => m.$type === "AssertConstraintStmt").map((m) => item(m,
|
|
174798
|
+
add("assert constraints", members.filter((m) => m.$type === "AssertConstraintStmt").map((m) => item(m, exprText4(m) || nameOf2(m) || "assert constraint")));
|
|
174386
174799
|
add("invariants", members.filter((m) => m.$type === "InvShorthand").map((m) => {
|
|
174387
174800
|
const inv = m;
|
|
174388
174801
|
const head2 = `inv${inv.isNegated ? " false" : ""}${nameOf2(m) ? ` ${nameOf2(m)}` : ""}`;
|
|
174389
|
-
const expr =
|
|
174802
|
+
const expr = exprText4(m);
|
|
174390
174803
|
return item(m, `${head2} { ${expr} }`.replace(/\s+/g, " ").trim());
|
|
174391
174804
|
}));
|
|
174392
174805
|
add("actions", usages(isActionDecl).map((m) => item(m)));
|
|
@@ -174643,8 +175056,12 @@ function projectGvCompartments(input) {
|
|
|
174643
175056
|
continue;
|
|
174644
175057
|
visible.add(node.id);
|
|
174645
175058
|
const key2 = gvElementKey(node);
|
|
174646
|
-
const
|
|
174647
|
-
|
|
175059
|
+
const children2 = (index2.children.get(node.id) ?? []).filter(
|
|
175060
|
+
(child) => child.meta?.gvDerived !== true && child.meta?.connectionDefinitionHub !== true
|
|
175061
|
+
);
|
|
175062
|
+
const canExpand = children2.length > 0;
|
|
175063
|
+
const open = canExpand && gvElementIsExpanded(node, expanded2);
|
|
175064
|
+
if (canExpand) expandable.add(key2);
|
|
174648
175065
|
nodes.push({
|
|
174649
175066
|
...node,
|
|
174650
175067
|
parent,
|
|
@@ -174663,7 +175080,7 @@ function projectGvCompartments(input) {
|
|
|
174663
175080
|
...node.meta,
|
|
174664
175081
|
gvMode: "group",
|
|
174665
175082
|
gvExpansionKey: key2,
|
|
174666
|
-
gvCanExpand:
|
|
175083
|
+
gvCanExpand: canExpand,
|
|
174667
175084
|
gvExpanded: open,
|
|
174668
175085
|
gvOpenContainer: open,
|
|
174669
175086
|
internalsHidden: !open,
|
|
@@ -174671,7 +175088,7 @@ function projectGvCompartments(input) {
|
|
|
174671
175088
|
}
|
|
174672
175089
|
});
|
|
174673
175090
|
if (open) {
|
|
174674
|
-
for (const child of
|
|
175091
|
+
for (const child of children2) {
|
|
174675
175092
|
queue.push({ node: child, parent: node.id });
|
|
174676
175093
|
}
|
|
174677
175094
|
}
|
|
@@ -174707,10 +175124,10 @@ function projectGvTree(input) {
|
|
|
174707
175124
|
visible.add(node.id);
|
|
174708
175125
|
const isPackage2 = node.shape === "package";
|
|
174709
175126
|
const children2 = (index2.children.get(node.id) ?? []).filter(
|
|
174710
|
-
(child) => isPackage2 || isGvPartUsage(child)
|
|
175127
|
+
(child) => child.meta?.gvTreeExcluded !== true && !isDerivedHub(child) && (isPackage2 || isGvPartUsage(child))
|
|
174711
175128
|
);
|
|
174712
175129
|
const key2 = gvElementKey(node);
|
|
174713
|
-
const canExpand =
|
|
175130
|
+
const canExpand = children2.length > 0;
|
|
174714
175131
|
const open = canExpand && gvElementIsExpanded(node, expanded2, true);
|
|
174715
175132
|
if (canExpand) expandable.add(key2);
|
|
174716
175133
|
nodes.push({
|
|
@@ -175761,6 +176178,283 @@ function resolveEffectiveSubject(node) {
|
|
|
175761
176178
|
return void 0;
|
|
175762
176179
|
}
|
|
175763
176180
|
|
|
176181
|
+
// ../language-server/out/src/services/case-semantics.js
|
|
176182
|
+
var CASE_KIND_BY_TYPE = /* @__PURE__ */ new Map([
|
|
176183
|
+
["CaseDecl", "case"],
|
|
176184
|
+
["AnalysisCaseDecl", "analysis"],
|
|
176185
|
+
["VerificationCaseDecl", "verification"],
|
|
176186
|
+
["UseCaseDecl", "use-case"]
|
|
176187
|
+
]);
|
|
176188
|
+
var MAX_INHERITANCE_DEPTH2 = 16;
|
|
176189
|
+
function caseKindOf(node) {
|
|
176190
|
+
return node ? CASE_KIND_BY_TYPE.get(node.$type) : void 0;
|
|
176191
|
+
}
|
|
176192
|
+
function enclosingCase(node) {
|
|
176193
|
+
let current2 = node;
|
|
176194
|
+
while (current2) {
|
|
176195
|
+
if (CASE_SHAPED.has(current2.$type))
|
|
176196
|
+
return current2;
|
|
176197
|
+
current2 = current2.$container;
|
|
176198
|
+
}
|
|
176199
|
+
return void 0;
|
|
176200
|
+
}
|
|
176201
|
+
function writtenTypes(node, resolve8) {
|
|
176202
|
+
const out = [];
|
|
176203
|
+
for (const typing of [node.typing, ...node.moreTypings ?? []]) {
|
|
176204
|
+
if (!typing)
|
|
176205
|
+
continue;
|
|
176206
|
+
for (const ref of [typing.type, ...typing.moreTypes ?? []]) {
|
|
176207
|
+
if (!ref)
|
|
176208
|
+
continue;
|
|
176209
|
+
const name = ref.$refText?.trim() ?? ref.ref?.name;
|
|
176210
|
+
if (!name)
|
|
176211
|
+
continue;
|
|
176212
|
+
out.push({ name, node: ref.ref ?? resolve8(name) });
|
|
176213
|
+
}
|
|
176214
|
+
}
|
|
176215
|
+
return out;
|
|
176216
|
+
}
|
|
176217
|
+
function effectiveCaseDefinition(node, resolve8) {
|
|
176218
|
+
const kind = caseKindOf(node);
|
|
176219
|
+
if (!kind)
|
|
176220
|
+
return void 0;
|
|
176221
|
+
const decl = node;
|
|
176222
|
+
const resolver = resolve8 ?? documentResolver(node);
|
|
176223
|
+
const definitions = writtenTypes(decl, resolver).filter((type) => type.node === void 0 || CASE_SHAPED.has(type.node.$type));
|
|
176224
|
+
return {
|
|
176225
|
+
kind,
|
|
176226
|
+
isDefinition: decl.isDef === true,
|
|
176227
|
+
definitions,
|
|
176228
|
+
sole: definitions.length === 1 ? definitions[0] : void 0
|
|
176229
|
+
};
|
|
176230
|
+
}
|
|
176231
|
+
function hasAmbiguousDefinition(node, resolve8) {
|
|
176232
|
+
const effective = effectiveCaseDefinition(node, resolve8);
|
|
176233
|
+
if (!effective || effective.isDefinition)
|
|
176234
|
+
return false;
|
|
176235
|
+
return effective.definitions.filter((type) => type.node !== void 0).length > 1;
|
|
176236
|
+
}
|
|
176237
|
+
function isDecidedSubject(subject) {
|
|
176238
|
+
if (!subject)
|
|
176239
|
+
return false;
|
|
176240
|
+
return subject.origin !== "default" && subject.origin !== "ambiguous" && subject.typeName !== DEFAULT_SUBJECT_TYPE;
|
|
176241
|
+
}
|
|
176242
|
+
function effectiveCaseSubject(node, resolve8) {
|
|
176243
|
+
const resolver = resolve8 ?? documentResolver(node);
|
|
176244
|
+
if (hasAmbiguousDefinition(node, resolver)) {
|
|
176245
|
+
const own = ownSubject(node);
|
|
176246
|
+
return own ? subjectInfo(own, node, "own") : { typeName: DEFAULT_SUBJECT_TYPE, origin: "ambiguous" };
|
|
176247
|
+
}
|
|
176248
|
+
return effectiveSubject(node, resolver);
|
|
176249
|
+
}
|
|
176250
|
+
function ownActors(node) {
|
|
176251
|
+
return (node.members ?? []).filter((member) => member.$type === "ActorDecl");
|
|
176252
|
+
}
|
|
176253
|
+
function effectiveActors(node, resolve8) {
|
|
176254
|
+
const resolver = resolve8 ?? documentResolver(node);
|
|
176255
|
+
const ambiguous = hasAmbiguousDefinition(node, resolver);
|
|
176256
|
+
const out = [];
|
|
176257
|
+
const seenNodes = /* @__PURE__ */ new Set();
|
|
176258
|
+
const seenNames = /* @__PURE__ */ new Set();
|
|
176259
|
+
const walk = (current2, origin, depth) => {
|
|
176260
|
+
if (depth > MAX_INHERITANCE_DEPTH2 || seenNodes.has(current2))
|
|
176261
|
+
return;
|
|
176262
|
+
seenNodes.add(current2);
|
|
176263
|
+
for (const actor of ownActors(current2)) {
|
|
176264
|
+
if (actor.name && seenNames.has(actor.name))
|
|
176265
|
+
continue;
|
|
176266
|
+
if (actor.name)
|
|
176267
|
+
seenNames.add(actor.name);
|
|
176268
|
+
out.push({
|
|
176269
|
+
declaration: actor,
|
|
176270
|
+
name: actor.name,
|
|
176271
|
+
typeName: subjectTypeName(actor),
|
|
176272
|
+
origin,
|
|
176273
|
+
owner: current2
|
|
176274
|
+
});
|
|
176275
|
+
}
|
|
176276
|
+
if (ambiguous)
|
|
176277
|
+
return;
|
|
176278
|
+
for (const supertype of supertypesOf(current2, resolver)) {
|
|
176279
|
+
if (!CASE_SHAPED.has(supertype.$type))
|
|
176280
|
+
continue;
|
|
176281
|
+
walk(supertype, "inherited", depth + 1);
|
|
176282
|
+
}
|
|
176283
|
+
};
|
|
176284
|
+
walk(node, "own", 0);
|
|
176285
|
+
return out;
|
|
176286
|
+
}
|
|
176287
|
+
function caseResult(node, resolve8) {
|
|
176288
|
+
const resolver = resolve8 ?? documentResolver(node);
|
|
176289
|
+
const ambiguous = hasAmbiguousDefinition(node, resolver);
|
|
176290
|
+
const seen = /* @__PURE__ */ new Set();
|
|
176291
|
+
const walk = (current2, origin, depth) => {
|
|
176292
|
+
if (depth > MAX_INHERITANCE_DEPTH2 || seen.has(current2))
|
|
176293
|
+
return void 0;
|
|
176294
|
+
seen.add(current2);
|
|
176295
|
+
const own = (current2.members ?? []).find((member) => member.$type === "ReturnDecl");
|
|
176296
|
+
if (own) {
|
|
176297
|
+
return {
|
|
176298
|
+
declaration: own,
|
|
176299
|
+
name: own.name,
|
|
176300
|
+
typeName: subjectTypeName(own),
|
|
176301
|
+
origin,
|
|
176302
|
+
owner: current2
|
|
176303
|
+
};
|
|
176304
|
+
}
|
|
176305
|
+
if (ambiguous)
|
|
176306
|
+
return void 0;
|
|
176307
|
+
for (const supertype of supertypesOf(current2, resolver)) {
|
|
176308
|
+
if (!CASE_SHAPED.has(supertype.$type))
|
|
176309
|
+
continue;
|
|
176310
|
+
const inherited = walk(supertype, "inherited", depth + 1);
|
|
176311
|
+
if (inherited)
|
|
176312
|
+
return inherited;
|
|
176313
|
+
}
|
|
176314
|
+
return void 0;
|
|
176315
|
+
};
|
|
176316
|
+
return walk(node, "own", 0);
|
|
176317
|
+
}
|
|
176318
|
+
function objectiveBindingOf(objective, resolve8) {
|
|
176319
|
+
if (objective.$type !== "ObjectiveDecl")
|
|
176320
|
+
return void 0;
|
|
176321
|
+
const caseNode = enclosingCase(objective.$container);
|
|
176322
|
+
const caseKind = caseKindOf(caseNode);
|
|
176323
|
+
if (!caseNode || !caseKind)
|
|
176324
|
+
return void 0;
|
|
176325
|
+
const resolver = resolve8 ?? documentResolver(objective);
|
|
176326
|
+
const own = ownSubject(objective);
|
|
176327
|
+
const bindsSubject = caseKind === "verification" || caseKind === "use-case";
|
|
176328
|
+
if (bindsSubject) {
|
|
176329
|
+
const subject = effectiveCaseSubject(caseNode, resolver);
|
|
176330
|
+
return {
|
|
176331
|
+
objective,
|
|
176332
|
+
caseNode,
|
|
176333
|
+
caseKind,
|
|
176334
|
+
target: "case-subject",
|
|
176335
|
+
strength: "bind",
|
|
176336
|
+
boundTo: subject.declaration,
|
|
176337
|
+
// An undecided subject names no type: the case still binds its
|
|
176338
|
+
// objective to whatever its subject is, but neither hover nor
|
|
176339
|
+
// `SSM046` may say what that is.
|
|
176340
|
+
typeName: isDecidedSubject(subject) ? subject.typeName : void 0,
|
|
176341
|
+
own
|
|
176342
|
+
};
|
|
176343
|
+
}
|
|
176344
|
+
const result = caseResult(caseNode, resolver);
|
|
176345
|
+
return {
|
|
176346
|
+
objective,
|
|
176347
|
+
caseNode,
|
|
176348
|
+
caseKind,
|
|
176349
|
+
target: "case-result",
|
|
176350
|
+
strength: "default",
|
|
176351
|
+
boundTo: result?.declaration,
|
|
176352
|
+
typeName: result?.typeName,
|
|
176353
|
+
own
|
|
176354
|
+
};
|
|
176355
|
+
}
|
|
176356
|
+
function effectiveObjectiveSubject(objective, resolve8) {
|
|
176357
|
+
const resolver = resolve8 ?? documentResolver(objective);
|
|
176358
|
+
const binding = objectiveBindingOf(objective, resolver);
|
|
176359
|
+
const own = ownSubject(objective);
|
|
176360
|
+
if (!binding) {
|
|
176361
|
+
return own ? { declaration: own, name: own.name, typeName: subjectTypeName(own) ?? DEFAULT_SUBJECT_TYPE, origin: "own", owner: objective } : { typeName: DEFAULT_SUBJECT_TYPE, origin: "default" };
|
|
176362
|
+
}
|
|
176363
|
+
if (own && binding.strength === "default") {
|
|
176364
|
+
return {
|
|
176365
|
+
declaration: own,
|
|
176366
|
+
name: own.name,
|
|
176367
|
+
typeName: subjectTypeName(own) ?? DEFAULT_SUBJECT_TYPE,
|
|
176368
|
+
origin: "own",
|
|
176369
|
+
owner: objective
|
|
176370
|
+
};
|
|
176371
|
+
}
|
|
176372
|
+
return {
|
|
176373
|
+
declaration: binding.boundTo,
|
|
176374
|
+
typeName: binding.typeName ?? DEFAULT_SUBJECT_TYPE,
|
|
176375
|
+
origin: "enclosing",
|
|
176376
|
+
owner: binding.caseNode
|
|
176377
|
+
};
|
|
176378
|
+
}
|
|
176379
|
+
function objectiveSubrequirements(objective, resolve8) {
|
|
176380
|
+
if (objective.$type !== "ObjectiveDecl")
|
|
176381
|
+
return [];
|
|
176382
|
+
const resolver = resolve8 ?? documentResolver(objective);
|
|
176383
|
+
const subjectTypeName2 = effectiveObjectiveSubject(objective, resolver).typeName;
|
|
176384
|
+
const out = [];
|
|
176385
|
+
for (const member of objective.members ?? []) {
|
|
176386
|
+
if (member.$type === "VerifyStmt") {
|
|
176387
|
+
const path10 = referencePathOf(member);
|
|
176388
|
+
out.push({
|
|
176389
|
+
declaration: member,
|
|
176390
|
+
kind: "verify",
|
|
176391
|
+
path: path10,
|
|
176392
|
+
target: referenceTargetOf(member, resolver),
|
|
176393
|
+
subjectTypeName: subjectTypeName2
|
|
176394
|
+
});
|
|
176395
|
+
} else if (member.$type === "RequirementDecl") {
|
|
176396
|
+
out.push({ declaration: member, kind: "requirement", subjectTypeName: subjectTypeName2 });
|
|
176397
|
+
}
|
|
176398
|
+
}
|
|
176399
|
+
return out;
|
|
176400
|
+
}
|
|
176401
|
+
function valueSimpleName(value) {
|
|
176402
|
+
const node = value;
|
|
176403
|
+
if (!node)
|
|
176404
|
+
return void 0;
|
|
176405
|
+
if (node.$type === "ParenExpr") {
|
|
176406
|
+
const items = node.items ?? [];
|
|
176407
|
+
return items.length === 1 ? valueSimpleName(items[0]) : void 0;
|
|
176408
|
+
}
|
|
176409
|
+
if (node.$type !== "PathExpr")
|
|
176410
|
+
return void 0;
|
|
176411
|
+
return node.path ? simpleName(node.path) : void 0;
|
|
176412
|
+
}
|
|
176413
|
+
function includeBindingOf(stmt, resolve8) {
|
|
176414
|
+
if (stmt.$type !== "IncludeStmt")
|
|
176415
|
+
return void 0;
|
|
176416
|
+
const node = stmt;
|
|
176417
|
+
const resolver = resolve8 ?? documentResolver(stmt);
|
|
176418
|
+
const isUseCase = (candidate) => candidate !== void 0 && candidate.$type === "UseCaseDecl";
|
|
176419
|
+
const typed = writtenTypes(node, resolver).find((type) => type.node === void 0 || isUseCase(type.node));
|
|
176420
|
+
const path10 = referencePathOf(node);
|
|
176421
|
+
const named2 = typed?.node ?? (typed ? void 0 : referenceTargetOf(node, resolver));
|
|
176422
|
+
const target = isUseCase(named2) ? named2 : void 0;
|
|
176423
|
+
const form = node.useCaseKw === true || typed !== void 0 ? "declaration" : "reference";
|
|
176424
|
+
const containing = enclosingCase(node.$container);
|
|
176425
|
+
const parameters = target ? effectiveActors(target, resolver) : [];
|
|
176426
|
+
const actors = [];
|
|
176427
|
+
for (const member of node.members ?? []) {
|
|
176428
|
+
if (member.$type !== "ActorDecl")
|
|
176429
|
+
continue;
|
|
176430
|
+
const name = member.name;
|
|
176431
|
+
actors.push({
|
|
176432
|
+
declaration: member,
|
|
176433
|
+
name,
|
|
176434
|
+
valueName: valueSimpleName(member.value),
|
|
176435
|
+
typeName: subjectTypeName(member),
|
|
176436
|
+
parameter: name ? parameters.find((parameter) => parameter.name === name) : void 0
|
|
176437
|
+
});
|
|
176438
|
+
}
|
|
176439
|
+
const containingSubject = containing ? effectiveCaseSubject(containing, resolver) : void 0;
|
|
176440
|
+
const includedSubject = target ? effectiveCaseSubject(target, resolver) : void 0;
|
|
176441
|
+
const subjectOrigin = isDecidedSubject(includedSubject) ? "included" : isDecidedSubject(containingSubject) ? "containing" : "default";
|
|
176442
|
+
const subjectTypeName2 = subjectOrigin === "included" ? includedSubject.typeName : subjectOrigin === "containing" ? containingSubject.typeName : DEFAULT_SUBJECT_TYPE;
|
|
176443
|
+
return {
|
|
176444
|
+
statement: stmt,
|
|
176445
|
+
form,
|
|
176446
|
+
path: typed ? typed.name : path10,
|
|
176447
|
+
target,
|
|
176448
|
+
containing,
|
|
176449
|
+
containingSubject,
|
|
176450
|
+
includedSubject,
|
|
176451
|
+
subjectOrigin,
|
|
176452
|
+
subjectTypeName: subjectTypeName2,
|
|
176453
|
+
parameters,
|
|
176454
|
+
actors
|
|
176455
|
+
};
|
|
176456
|
+
}
|
|
176457
|
+
|
|
175764
176458
|
// ../language-server/out/src/services/implicit-specialization.js
|
|
175765
176459
|
var EXPLICIT_SPECIALIZATION_KINDS = /* @__PURE__ */ new Set([
|
|
175766
176460
|
":>",
|
|
@@ -176530,11 +177224,64 @@ var DIAGNOSTIC_MESSAGES = {
|
|
|
176530
177224
|
SSM040_INDIVIDUAL_NOT_OCCURRENCE: (name, kind) => `'individual' names one occurrence with an identity of its own, and ${name} is ${kind}, which has no life to identify. Remove 'individual', or move it to the occurrence this belongs to.`,
|
|
176531
177225
|
SSM041_INDIVIDUAL_MULTIPLE_DEFINITIONS: (name, first2, second) => `${name} is typed by two individual definitions, '${first2}' and '${second}'. An individual usage names ONE life, so at most one of its types may be an 'individual def'.`,
|
|
176532
177226
|
SSM042_INDIVIDUAL_WITHOUT_DEFINITION: (name) => `${name} is declared 'individual' but names no individual definition. An individual usage is typed by exactly one 'individual def' - the definition that carries the identity it names.`,
|
|
177227
|
+
// REQ-415 — issue #164. `assert c`, `require c` and `assume c` all reach their
|
|
177228
|
+
// constraint through the same OwnedReferenceSubsetting, so one message covers
|
|
177229
|
+
// the three. The kind is named because the fix depends on it: a part or an
|
|
177230
|
+
// action is not something that can be true or false.
|
|
177231
|
+
SSM043_CONSTRAINT_REFERENCE_KIND: (keyword, path10, kind) => `'${keyword} ${path10}' must name a constraint, but '${path10}' is ${kind}. The '${keyword}' shorthand asserts the referenced constraint's Boolean body, so write 'assert constraint { \u2026 }' to state a condition here instead.`,
|
|
177232
|
+
// REQ-415 — the reference resolves and its constraint evaluates to a definite
|
|
177233
|
+
// false, so the model states something against itself. A warning, never an
|
|
177234
|
+
// error: the text is well formed, and only a closed constant expression is
|
|
177235
|
+
// decided at all - anything that depends on a binding stays silent.
|
|
177236
|
+
SEM014_ASSERTION_VIOLATED: (text) => `Asserted constraint '${text}' evaluates to false, so this model is inconsistent as written.`,
|
|
177237
|
+
// REQ-131 — a constraint is a predicate: `BooleanEvaluation` returns
|
|
177238
|
+
// `Boolean[1]` (Kernel Semantic Library, `Performances.kerml`). A body that is
|
|
177239
|
+
// demonstrably some other type can never be true or false. Only a body the
|
|
177240
|
+
// checker can PROVE is not Boolean is reported, so an expression whose type it
|
|
177241
|
+
// cannot settle stays silent.
|
|
177242
|
+
SEM015_CONSTRAINT_BODY_NOT_BOOLEAN: (text, kind) => `A constraint body must be a Boolean expression, but '${text}' is ${kind}. A constraint is a predicate, so its body has to be able to come out true or false.`,
|
|
177243
|
+
// REQ-209 — a usage inherits its definition's expression. Replacing it hides
|
|
177244
|
+
// what the definition says while every other usage still reads the original.
|
|
177245
|
+
// Advisory: the language permits the redefinition, the modelling idiom does not
|
|
177246
|
+
// use it, and no model in the OMG corpus does.
|
|
177247
|
+
STYL012_CONSTRAINT_BODY_OVERRIDES_DEFINITION: (usage, definition) => `'${usage}' replaces the expression it inherits from '${definition}', so the definition's expression no longer applies here. Bind the parameters instead, or give this usage its own constraint definition.`,
|
|
177248
|
+
/* REQ-376 — a parameter of a constraint or a calculation is an INPUT.
|
|
177249
|
+
*
|
|
177250
|
+
* A constraint is a predicate: its one output is its Boolean result, which
|
|
177251
|
+
* comes from the body, never from a parameter. A calculation produces its
|
|
177252
|
+
* value through `return`. Neither has anything to send back out through a
|
|
177253
|
+
* parameter, and the OMG corpus bears that out: 40 `in` parameters on
|
|
177254
|
+
* constraints and 44 on calculations, and not one `out` or `inout` on either.
|
|
177255
|
+
*
|
|
177256
|
+
* A constraint is also ACAUSAL — `StraightLineDynamicsEquations` declares even
|
|
177257
|
+
* the quantities it would be solved for (`x_f`, `v_f`, `a`) as `in`, because
|
|
177258
|
+
* which parameter is the unknown is the binding's business, not the
|
|
177259
|
+
* constraint's. Fixing a direction would bake in one solving order. */
|
|
177260
|
+
STYL014_PARAMETER_DIRECTION: (parameter, direction, kind, owner) => kind === "constraint" ? `Parameter '${parameter}' is '${direction}' on constraint '${owner}'. A constraint's only output is true or false, so everything it relates is an input: declare the parameter 'in'. Which parameter is the unknown is decided where the constraint is bound.` : `Parameter '${parameter}' is '${direction}' on calculation '${owner}'. A calculation produces its value through 'return', so declare the parameter 'in' and return the result.`,
|
|
177261
|
+
// REQ-376 — a directed parameter is an input to be bound by a usage, not a
|
|
177262
|
+
// value slot. OMG declares parameters bare on a definition and puts values on
|
|
177263
|
+
// `attribute` members (`StraightLineDynamicsEquations`).
|
|
177264
|
+
STYL013_PARAMETER_DEFAULT_ON_DEFINITION: (parameter, owner) => `Parameter '${parameter}' carries a value on the definition '${owner}'. A parameter is an input a usage binds, so declare it without a value and put the value on an attribute, or bind it where the definition is used.`,
|
|
176533
177265
|
// issue #165 — a satisfaction binds a thing to the subject a requirement
|
|
176534
177266
|
// constrains, so the thing has to BE one of those (OMG SysML v2 Part 1
|
|
176535
177267
|
// §7.21.2). The message names both types because the fix is either to bind a
|
|
176536
177268
|
// different satisfier or to widen the requirement's subject.
|
|
176537
177269
|
SSM044_SATISFIER_SUBJECT_TYPE: (satisfier, satisfierType, requirement, subjectType) => `'${satisfier}' is a '${satisfierType}', but '${requirement}' constrains a subject of type '${subjectType}'. A satisfying element must conform to the requirement's subject.`,
|
|
177270
|
+
// issue #166 — a case usage performs ONE case (OMG SysML v2 Part 1 §7.22.2),
|
|
177271
|
+
// and every effective binding this extension derives reads through that one:
|
|
177272
|
+
// the subject, the actor parameters and the objective. Two definitions leave
|
|
177273
|
+
// all three undecided, so the message names them and asks for one.
|
|
177274
|
+
SSM045_CASE_MULTIPLE_DEFINITIONS: (name, first2, second) => `Case '${name}' names more than one case definition ('${first2}' and '${second}'). A case usage performs exactly one case, so keep one and subset the other.`,
|
|
177275
|
+
// issue #166 — an `objective` written inside a verification case or a use
|
|
177276
|
+
// case has its subject BOUND to the case's subject, so a `subject` of an
|
|
177277
|
+
// unrelated type on the objective states something the case has already
|
|
177278
|
+
// decided otherwise.
|
|
177279
|
+
SSM046_OBJECTIVE_SUBJECT_TYPE: (caseName, objectiveType, subjectType) => `This objective declares a subject of type '${objectiveType}', but '${caseName}' binds its objective's subject to its own subject of type '${subjectType}'. Remove the subject or widen the case's.`,
|
|
177280
|
+
// issue #166 — an `include` investigates the included use case on the
|
|
177281
|
+
// including case's subject (§7.25), and an `actor` written inside the
|
|
177282
|
+
// include binds one of the included use case's actor parameters.
|
|
177283
|
+
SSM047_INCLUDE_SUBJECT_TYPE: (included, includedType, containerType) => `Included use case '${included}' has a subject of type '${includedType}', which does not conform to the including case's subject of type '${containerType}'. An included use case is investigated on the same subject.`,
|
|
177284
|
+
SSM048_INCLUDE_ACTOR_BINDING: (actor, included, known2) => `'${actor}' is not an actor parameter of the included use case '${included}'. It declares ${known2}.`,
|
|
176538
177285
|
// REQ-392 — a `sysml-format` comment the formatter cannot act on. Advisory:
|
|
176539
177286
|
// the directive is inert, and saying so beats leaving the author to wonder
|
|
176540
177287
|
// why their layout was reformatted anyway.
|
|
@@ -176997,7 +177744,7 @@ function nearestAncestor(node, types) {
|
|
|
176997
177744
|
}
|
|
176998
177745
|
return void 0;
|
|
176999
177746
|
}
|
|
177000
|
-
function
|
|
177747
|
+
function exprText3(node) {
|
|
177001
177748
|
return node?.$cstNode?.text?.trim().replace(/\s+/gu, " ") ?? "";
|
|
177002
177749
|
}
|
|
177003
177750
|
function conditionTypeLabel(node) {
|
|
@@ -177008,7 +177755,7 @@ function conditionTypeLabel(node) {
|
|
|
177008
177755
|
if (["AndExpr", "OrExpr", "XorExpr", "NotExpr", "CompareExpr", "ClassifyOp"].includes(node.$type)) {
|
|
177009
177756
|
return "Boolean";
|
|
177010
177757
|
}
|
|
177011
|
-
const text =
|
|
177758
|
+
const text = exprText3(node);
|
|
177012
177759
|
return /\b(true|false)\b|[=!<>]=?|(?:\band\b|\bor\b|\bnot\b|\bxor\b)/u.test(text) ? "Boolean" : "Boolean (expected)";
|
|
177013
177760
|
}
|
|
177014
177761
|
function buildConditionalHover(node) {
|
|
@@ -177022,7 +177769,7 @@ function buildConditionalHover(node) {
|
|
|
177022
177769
|
"",
|
|
177023
177770
|
"Canonical form: `if condition ? thenExpression else elseExpression`",
|
|
177024
177771
|
`Then marker: ${usesQuestion ? "canonical `?`" : "non-canonical `then`; use `?`"}`,
|
|
177025
|
-
`Condition: \`${
|
|
177772
|
+
`Condition: \`${exprText3(n2.cond)}\``,
|
|
177026
177773
|
`Condition type: ${conditionTypeLabel(n2.cond)}`,
|
|
177027
177774
|
"",
|
|
177028
177775
|
sourceFooter(nodeSource(node))
|
|
@@ -177194,6 +177941,8 @@ ${headerLines.join("\n")}
|
|
|
177194
177941
|
const subject = subjectInheritanceSection(node);
|
|
177195
177942
|
if (subject)
|
|
177196
177943
|
parts.push(subject);
|
|
177944
|
+
for (const section of caseBindingSections(node))
|
|
177945
|
+
parts.push(section);
|
|
177197
177946
|
if (relationshipDetails)
|
|
177198
177947
|
parts.push(relationshipDetails);
|
|
177199
177948
|
const flip = conjugationFlipSection(node);
|
|
@@ -177230,6 +177979,62 @@ function subjectInheritanceSection(node) {
|
|
|
177230
177979
|
const ownerName = effective.owner.name ?? "(anonymous requirement)";
|
|
177231
177980
|
return `*Subject inherited from \`${ownerName}\`:* \`${subjectText}\``;
|
|
177232
177981
|
}
|
|
177982
|
+
var CASE_KIND_LABELS = {
|
|
177983
|
+
"case": "Case",
|
|
177984
|
+
"analysis": "Analysis case",
|
|
177985
|
+
"verification": "Verification case",
|
|
177986
|
+
"use-case": "Use case"
|
|
177987
|
+
};
|
|
177988
|
+
function caseBindingSections(node) {
|
|
177989
|
+
const out = [];
|
|
177990
|
+
const kind = caseKindOf(node);
|
|
177991
|
+
if (kind) {
|
|
177992
|
+
const effective = effectiveCaseDefinition(node);
|
|
177993
|
+
if (effective && !effective.isDefinition && effective.sole) {
|
|
177994
|
+
out.push(`*${CASE_KIND_LABELS[kind]} performs:* \`${effective.sole.name}\``);
|
|
177995
|
+
}
|
|
177996
|
+
const subject = effectiveCaseSubject(node);
|
|
177997
|
+
if (subject.origin === "inherited") {
|
|
177998
|
+
const owner = subject.owner?.name;
|
|
177999
|
+
out.push(`*Subject inherited${owner ? ` from \`${owner}\`` : ""}:* \`${subject.name ?? "subject"} : ${subject.typeName}\``);
|
|
178000
|
+
} else if (subject.origin === "default") {
|
|
178001
|
+
out.push("*Subject:* none declared, so this case investigates `Anything`.");
|
|
178002
|
+
}
|
|
178003
|
+
const inherited = effectiveActors(node).filter((actor) => actor.origin === "inherited");
|
|
178004
|
+
if (inherited.length > 0) {
|
|
178005
|
+
const list = inherited.map((actor) => `\`${actor.name ?? "actor"}${actor.typeName ? ` : ${actor.typeName}` : ""}\``).join(", ");
|
|
178006
|
+
out.push(`*Actors inherited:* ${list}`);
|
|
178007
|
+
}
|
|
178008
|
+
}
|
|
178009
|
+
if (node.$type === "ObjectiveDecl") {
|
|
178010
|
+
const binding = objectiveBindingOf(node);
|
|
178011
|
+
if (binding) {
|
|
178012
|
+
const what = binding.target === "case-subject" ? "subject" : "result";
|
|
178013
|
+
const verb = binding.strength === "bind" ? "is bound to" : "defaults to";
|
|
178014
|
+
const type = binding.typeName ? ` (\`${binding.typeName}\`)` : "";
|
|
178015
|
+
const caseName = binding.caseNode.name;
|
|
178016
|
+
out.push(`*Objective subject ${verb}* the ${what} of ${caseName ? `\`${caseName}\`` : "the enclosing case"}${type}.`);
|
|
178017
|
+
}
|
|
178018
|
+
const subrequirements = objectiveSubrequirements(node);
|
|
178019
|
+
if (subrequirements.length > 0) {
|
|
178020
|
+
const list = subrequirements.map((sub) => `\`${sub.path ?? sub.declaration.name ?? "requirement"}\``).join(", ");
|
|
178021
|
+
out.push(`*Required subrequirements:* ${list} \u2014 each is checked on this objective's subject.`);
|
|
178022
|
+
}
|
|
178023
|
+
}
|
|
178024
|
+
if (node.$type === "IncludeStmt") {
|
|
178025
|
+
const binding = includeBindingOf(node);
|
|
178026
|
+
if (binding?.target) {
|
|
178027
|
+
const name = binding.path ? `\`${binding.path}\`` : "the included use case";
|
|
178028
|
+
out.push(`*Includes:* ${name}, a reference to a use case performed elsewhere. It keeps its own identity and is not copied here.`);
|
|
178029
|
+
if (binding.subjectOrigin === "containing") {
|
|
178030
|
+
out.push(`*Investigated on:* the including case's subject (\`${binding.subjectTypeName}\`).`);
|
|
178031
|
+
} else if (binding.subjectOrigin === "included") {
|
|
178032
|
+
out.push(`*Investigated on:* its own subject (\`${binding.subjectTypeName}\`).`);
|
|
178033
|
+
}
|
|
178034
|
+
}
|
|
178035
|
+
}
|
|
178036
|
+
return out;
|
|
178037
|
+
}
|
|
177233
178038
|
function flipDirection(direction) {
|
|
177234
178039
|
return direction === "in" ? "out" : direction === "out" ? "in" : direction;
|
|
177235
178040
|
}
|
|
@@ -178204,6 +179009,13 @@ var TYPE_CONTEXTS = {
|
|
|
178204
179009
|
calc: ["CalcDecl", "FunctionDecl"],
|
|
178205
179010
|
constraint: ["ConstraintDecl", "PredicateDecl"]
|
|
178206
179011
|
};
|
|
179012
|
+
var CONSTRAINT_REFERENCE_TYPES = [
|
|
179013
|
+
"ConstraintDecl",
|
|
179014
|
+
"InvShorthand",
|
|
179015
|
+
"PredicateDecl",
|
|
179016
|
+
"RequirementDecl",
|
|
179017
|
+
"ConcernDecl"
|
|
179018
|
+
];
|
|
178207
179019
|
var ALL_DEFINITION_TYPES = [
|
|
178208
179020
|
"PartDecl",
|
|
178209
179021
|
"PortDecl",
|
|
@@ -178389,6 +179201,10 @@ var SysmlCompletionProvider = class extends DefaultCompletionProvider {
|
|
|
178389
179201
|
allowedLabels.add("requirement");
|
|
178390
179202
|
allowedLabels.add("by");
|
|
178391
179203
|
}
|
|
179204
|
+
if (context.kind === "constraint-reference") {
|
|
179205
|
+
allowedLabels.add("constraint");
|
|
179206
|
+
allowedLabels.add("not");
|
|
179207
|
+
}
|
|
178392
179208
|
if (context.kind === "specialization") {
|
|
178393
179209
|
allowedLabels.add("specializes");
|
|
178394
179210
|
allowedLabels.add("subsets");
|
|
@@ -178463,6 +179279,14 @@ var SysmlCompletionProvider = class extends DefaultCompletionProvider {
|
|
|
178463
179279
|
addUnique(items, this.visibleSymbolItems(["RequirementDecl"], { document: document2, offset: offset2 }));
|
|
178464
179280
|
return;
|
|
178465
179281
|
}
|
|
179282
|
+
// REQ-415 — a reference shorthand names a CONSTRAINT, so the slot
|
|
179283
|
+
// offers constraint usages and definitions rather than every symbol.
|
|
179284
|
+
// A requirement and a concern are constraints too (OMG SysML v2
|
|
179285
|
+
// Part 1 §7.20.2, §7.21.2), so both belong in the list.
|
|
179286
|
+
case "constraint-reference": {
|
|
179287
|
+
addUnique(items, this.visibleSymbolItems(CONSTRAINT_REFERENCE_TYPES, { document: document2, offset: offset2 }));
|
|
179288
|
+
return;
|
|
179289
|
+
}
|
|
178466
179290
|
case "connect": {
|
|
178467
179291
|
addUnique(items, this.connectPortItems(document2, offset2));
|
|
178468
179292
|
return;
|
|
@@ -178484,6 +179308,8 @@ var SysmlCompletionProvider = class extends DefaultCompletionProvider {
|
|
|
178484
179308
|
symbolTypesForContext(context) {
|
|
178485
179309
|
if (context.kind === "verify" || context.kind === "satisfy")
|
|
178486
179310
|
return ["RequirementDecl"];
|
|
179311
|
+
if (context.kind === "constraint-reference")
|
|
179312
|
+
return CONSTRAINT_REFERENCE_TYPES;
|
|
178487
179313
|
const keyword = context.typingKeyword;
|
|
178488
179314
|
if (!keyword)
|
|
178489
179315
|
return ALL_DEFINITION_TYPES;
|
|
@@ -178687,6 +179513,9 @@ function detectCompletionContext(text, offset2) {
|
|
|
178687
179513
|
if (/\bconnect\s+(?:[\p{L}_:'.]+(?:\.[\p{L}_:']+)*\s+to\s*)?[\p{L}_:'.]*$/u.test(statement)) {
|
|
178688
179514
|
return { kind: "connect", statement };
|
|
178689
179515
|
}
|
|
179516
|
+
if (/\b(?:assert|require|assume)\s+(?:not\s+)?[\p{L}_:'.]*$/u.test(statement)) {
|
|
179517
|
+
return { kind: "constraint-reference", statement };
|
|
179518
|
+
}
|
|
178690
179519
|
if (/(?:^|[^\w:])(?::>|:>>|specializes|subsets|redefines)\s*~?[\p{L}_:'.]*$/u.test(statement)) {
|
|
178691
179520
|
return { kind: "specialization", statement, typingKeyword: keyword };
|
|
178692
179521
|
}
|
|
@@ -180197,6 +181026,60 @@ var CONSTRAINT_SIDE_EFFECT_TYPES = /* @__PURE__ */ new Set([
|
|
|
180197
181026
|
"DoAction",
|
|
180198
181027
|
"ExitAction"
|
|
180199
181028
|
]);
|
|
181029
|
+
var BOOLEAN_OPERATORS = /* @__PURE__ */ new Set([
|
|
181030
|
+
"or",
|
|
181031
|
+
"|",
|
|
181032
|
+
"implies",
|
|
181033
|
+
"xor",
|
|
181034
|
+
"and",
|
|
181035
|
+
"&",
|
|
181036
|
+
">=",
|
|
181037
|
+
"<=",
|
|
181038
|
+
"===",
|
|
181039
|
+
"!==",
|
|
181040
|
+
"==",
|
|
181041
|
+
"!=",
|
|
181042
|
+
">",
|
|
181043
|
+
"<",
|
|
181044
|
+
"hastype",
|
|
181045
|
+
"istype",
|
|
181046
|
+
"@",
|
|
181047
|
+
"@@"
|
|
181048
|
+
]);
|
|
181049
|
+
var ARITHMETIC_OPERATORS = /* @__PURE__ */ new Set(["+", "-", "*", "/", "%", "**", "^", ".."]);
|
|
181050
|
+
function nonBooleanExpressionKind(expr) {
|
|
181051
|
+
const node = expr;
|
|
181052
|
+
switch (expr.$type) {
|
|
181053
|
+
case "NumericPrimary":
|
|
181054
|
+
return node.unit ? "a quantity" : "a number";
|
|
181055
|
+
case "LiteralStr":
|
|
181056
|
+
return "a string";
|
|
181057
|
+
case "UnaryMinusExpr":
|
|
181058
|
+
case "UnaryPlusExpr":
|
|
181059
|
+
return "a number";
|
|
181060
|
+
case "ParenExpr": {
|
|
181061
|
+
const items = Array.isArray(node.items) ? node.items : [];
|
|
181062
|
+
return items.length === 1 ? nonBooleanExpressionKind(items[0]) : void 0;
|
|
181063
|
+
}
|
|
181064
|
+
case "BinExpr": {
|
|
181065
|
+
const op = typeof node.op === "string" ? node.op : void 0;
|
|
181066
|
+
if (op && BOOLEAN_OPERATORS.has(op))
|
|
181067
|
+
return void 0;
|
|
181068
|
+
if (op && ARITHMETIC_OPERATORS.has(op)) {
|
|
181069
|
+
return op === ".." ? "a range" : "an arithmetic expression";
|
|
181070
|
+
}
|
|
181071
|
+
return void 0;
|
|
181072
|
+
}
|
|
181073
|
+
default:
|
|
181074
|
+
return void 0;
|
|
181075
|
+
}
|
|
181076
|
+
}
|
|
181077
|
+
function directionOfModifiers(node) {
|
|
181078
|
+
const modifiers2 = node.modifiers;
|
|
181079
|
+
if (!Array.isArray(modifiers2))
|
|
181080
|
+
return void 0;
|
|
181081
|
+
return modifiers2.find((modifier) => modifier === "in" || modifier === "out" || modifier === "inout");
|
|
181082
|
+
}
|
|
180200
181083
|
var ACTION_BODY_TYPES = /* @__PURE__ */ new Set([
|
|
180201
181084
|
"ActionDecl",
|
|
180202
181085
|
"PerformStmt",
|
|
@@ -180497,7 +181380,122 @@ var SysmlValidator = class _SysmlValidator {
|
|
|
180497
181380
|
accept(severity("SEM010", "warning"), `Constraint '${node.name ?? "(anonymous)"}' must be a pure Boolean expression - '${member.$type}' is a statement with side effects and is not allowed in a constraint body.`, { node: member, code: "SEM010" });
|
|
180498
181381
|
}
|
|
180499
181382
|
}
|
|
181383
|
+
const notBoolean = node.body ? nonBooleanExpressionKind(node.body) : void 0;
|
|
181384
|
+
if (node.body?.$cstNode && notBoolean) {
|
|
181385
|
+
accept(severity("SEM015", "error"), DIAGNOSTIC_MESSAGES.SEM015_CONSTRAINT_BODY_NOT_BOOLEAN(node.body.$cstNode.text.replace(/\s+/g, " ").trim(), notBoolean), { node, property: "body", code: "SEM015" });
|
|
181386
|
+
}
|
|
181387
|
+
if (!node.isDef && node.body) {
|
|
181388
|
+
const definition = this.constraintTypeOf(node);
|
|
181389
|
+
if (definition?.body && definition.name) {
|
|
181390
|
+
accept(severity("STYL012", "hint"), DIAGNOSTIC_MESSAGES.STYL012_CONSTRAINT_BODY_OVERRIDES_DEFINITION(node.name ?? "(anonymous)", definition.name), { node, property: "body", code: "STYL012" });
|
|
181391
|
+
}
|
|
181392
|
+
}
|
|
181393
|
+
}
|
|
181394
|
+
/** REQ-209 — the constraint definition a usage is typed by, when the link
|
|
181395
|
+
* resolved. Only a direct typing is followed: a deeper specialization chain
|
|
181396
|
+
* is not what "replaces its definition's expression" is about. */
|
|
181397
|
+
constraintTypeOf(node) {
|
|
181398
|
+
const target = node.typing?.type?.ref;
|
|
181399
|
+
return target?.$type === "ConstraintDecl" ? target : void 0;
|
|
181400
|
+
}
|
|
181401
|
+
/* REQ-376 (user direction 2026-09-07) — STYL014: a parameter of a constraint
|
|
181402
|
+
* or a calculation is an INPUT. A constraint's one output is its Boolean
|
|
181403
|
+
* result and a calculation's is its `return`; neither sends anything back
|
|
181404
|
+
* through a parameter, and no model in the OMG corpus declares one `out` or
|
|
181405
|
+
* `inout`.
|
|
181406
|
+
*
|
|
181407
|
+
* Reported where the parameter is DECLARED: on a definition, and on a usage
|
|
181408
|
+
* that declares its own (an untyped `constraint c { out x : T; … }`). A TYPED
|
|
181409
|
+
* usage inherits its parameters, so a direction written there is a
|
|
181410
|
+
* redefinition of one, and `SSM025` already reports that as an error - saying
|
|
181411
|
+
* it twice, once as an error and once as an advisory, helps nobody. */
|
|
181412
|
+
checkParameterDirection(node, accept) {
|
|
181413
|
+
const decl = node;
|
|
181414
|
+
const typed = node.typing?.type?.ref;
|
|
181415
|
+
if (decl.isDef !== true && typed)
|
|
181416
|
+
return;
|
|
181417
|
+
const kind = node.$type === "ConstraintDecl" ? "constraint" : "calculation";
|
|
181418
|
+
const owner = typeof decl.name === "string" && decl.name ? decl.name : "(anonymous)";
|
|
181419
|
+
for (const member of decl.members ?? []) {
|
|
181420
|
+
const direction = directionOfModifiers(member);
|
|
181421
|
+
if (direction !== "out" && direction !== "inout")
|
|
181422
|
+
continue;
|
|
181423
|
+
const name = member.name;
|
|
181424
|
+
if (typeof name !== "string" || !name)
|
|
181425
|
+
continue;
|
|
181426
|
+
accept(severity("STYL014", "hint"), DIAGNOSTIC_MESSAGES.STYL014_PARAMETER_DIRECTION(name, direction, kind, owner), { node: member, code: "STYL014" });
|
|
181427
|
+
}
|
|
180500
181428
|
}
|
|
181429
|
+
// REQ-376 — STYL013: a directed parameter is an input a usage binds, not a
|
|
181430
|
+
// value slot. OMG declares them bare on a definition and puts values on
|
|
181431
|
+
// `attribute` members. Only a DEFINITION is flagged: `in x = expr;` on a usage
|
|
181432
|
+
// is the canonical binding form.
|
|
181433
|
+
checkParameterDefaultOnDefinition(node, accept) {
|
|
181434
|
+
const decl = node;
|
|
181435
|
+
if (decl.isDef !== true || typeof decl.name !== "string" || !decl.name)
|
|
181436
|
+
return;
|
|
181437
|
+
for (const member of decl.members ?? []) {
|
|
181438
|
+
const name = member.name;
|
|
181439
|
+
const value = member.value;
|
|
181440
|
+
if (!value || typeof name !== "string" || !name)
|
|
181441
|
+
continue;
|
|
181442
|
+
if (directionOfModifiers(member) === void 0)
|
|
181443
|
+
continue;
|
|
181444
|
+
accept(severity("STYL013", "hint"), DIAGNOSTIC_MESSAGES.STYL013_PARAMETER_DEFAULT_ON_DEFINITION(name, decl.name), { node: member, code: "STYL013" });
|
|
181445
|
+
}
|
|
181446
|
+
}
|
|
181447
|
+
// REQ-415 — issue #164. `assert c;`, `assert not c;`, `require c;` and
|
|
181448
|
+
// `assume c;` name a constraint declared elsewhere (OMG SysML v2 Part 1
|
|
181449
|
+
// §7.20.3, §7.21.2). Three things can go wrong with that name, and all three
|
|
181450
|
+
// were silent: it may resolve to nothing, it may resolve to something that is
|
|
181451
|
+
// not a constraint, and the constraint it resolves to may be decidably false.
|
|
181452
|
+
//
|
|
181453
|
+
// The ROOT link is judged here rather than in `checkWrittenPaths`, which
|
|
181454
|
+
// deliberately leaves a root alone: a root is reported absent only when the
|
|
181455
|
+
// resolver could enumerate the whole surrounding inventory, and that is
|
|
181456
|
+
// exactly the guarantee `unresolvedIndex === 0` carries. It is the same rule
|
|
181457
|
+
// `checkRelationshipTargets` applies to a redefinition target.
|
|
181458
|
+
checkConstraintReference(node, accept) {
|
|
181459
|
+
const reference = constraintReferenceOf(node);
|
|
181460
|
+
if (!reference)
|
|
181461
|
+
return;
|
|
181462
|
+
const resolution = reference.property ? this.featurePaths.resolvePropertyPath(node, reference.property) : this.featurePaths.resolveDeclarationPath(node);
|
|
181463
|
+
if (resolution.segments.length === 0)
|
|
181464
|
+
return;
|
|
181465
|
+
if (resolution.unresolvedIndex === 0) {
|
|
181466
|
+
const invalid = resolution.segments[0];
|
|
181467
|
+
accept(severity("RES001", "error"), DIAGNOSTIC_MESSAGES.RES001_FEATURE_PATH_SEGMENT(invalid.text, "the current scope"), { node, range: invalid.cst.range, code: "RES001", data: { featurePathSegment: true } });
|
|
181468
|
+
return;
|
|
181469
|
+
}
|
|
181470
|
+
if (resolution.unresolvedIndex !== void 0 || resolution.indeterminateIndex !== void 0)
|
|
181471
|
+
return;
|
|
181472
|
+
const last2 = resolution.segments[resolution.segments.length - 1];
|
|
181473
|
+
const target = last2.target;
|
|
181474
|
+
if (target && isWrongKindConstraintTarget(target)) {
|
|
181475
|
+
accept(severity("SSM043", "error"), DIAGNOSTIC_MESSAGES.SSM043_CONSTRAINT_REFERENCE_KIND(reference.kind, reference.path, wrongKindLabel(target)), { node, range: last2.cst.range, code: "SSM043" });
|
|
181476
|
+
}
|
|
181477
|
+
}
|
|
181478
|
+
// REQ-415 — SEM014. An assertion the model can DECIDE and that comes out
|
|
181479
|
+
// false is an inconsistency the author wrote against themselves. Only a
|
|
181480
|
+
// closed constant expression is decided: every feature reference is
|
|
181481
|
+
// inconclusive here, so an assertion that depends on a binding, on time, or
|
|
181482
|
+
// on anything this evaluator does not model stays silent rather than passing
|
|
181483
|
+
// quietly or being reported on a guess.
|
|
181484
|
+
checkAssertionConsistency(node, accept) {
|
|
181485
|
+
if (node.$type !== "AssertConstraintStmt")
|
|
181486
|
+
return;
|
|
181487
|
+
const result = evaluateAssertion(node, this.constraintResolver);
|
|
181488
|
+
if (result?.status !== "fail")
|
|
181489
|
+
return;
|
|
181490
|
+
accept(severity("SEM014", "warning"), DIAGNOSTIC_MESSAGES.SEM014_ASSERTION_VIOLATED(result.text), { node, code: "SEM014" });
|
|
181491
|
+
}
|
|
181492
|
+
// REQ-415 — Resolve a reference shorthand through the shared path resolver,
|
|
181493
|
+
// so a target in another file or in the standard library is evaluated exactly
|
|
181494
|
+
// as a same-file one is.
|
|
181495
|
+
constraintResolver = (reference, member) => {
|
|
181496
|
+
const resolution = reference.property ? this.featurePaths.resolvePropertyPath(member, reference.property) : this.featurePaths.resolveDeclarationPath(member);
|
|
181497
|
+
return resolution.segments[resolution.segments.length - 1]?.target;
|
|
181498
|
+
};
|
|
180501
181499
|
// REQ-410 — SEM013. A `ref` feature is NON-composite: it names a feature that
|
|
180502
181500
|
// is owned somewhere else. An unbound one therefore names nothing at all, and
|
|
180503
181501
|
// the General View cannot draw it as anything: a box would claim the owner
|
|
@@ -181996,6 +182994,7 @@ ${baseIndent}}`;
|
|
|
181996
182994
|
const decls = [];
|
|
181997
182995
|
const verifyStmts = [];
|
|
181998
182996
|
const satisfyStmts = [];
|
|
182997
|
+
const includeStmts = [];
|
|
181999
182998
|
const aliasMap = /* @__PURE__ */ new Map();
|
|
182000
182999
|
for (const child of ast_utils_exports.streamAllContents(node)) {
|
|
182001
183000
|
if (isImport(child)) {
|
|
@@ -182019,6 +183018,8 @@ ${baseIndent}}`;
|
|
|
182019
183018
|
if (a2.name && a2.target)
|
|
182020
183019
|
aliasMap.set(a2.name, a2.target);
|
|
182021
183020
|
}
|
|
183021
|
+
if (child.$type === "IncludeStmt")
|
|
183022
|
+
includeStmts.push(child);
|
|
182022
183023
|
}
|
|
182023
183024
|
this.checkAmbiguousReferences(node, imports, index2, accept);
|
|
182024
183025
|
this.checkPrivateImports(imports, index2, accept);
|
|
@@ -182054,7 +183055,7 @@ ${baseIndent}}`;
|
|
|
182054
183055
|
this.checkInverseOfTargets(decl, index2, accept);
|
|
182055
183056
|
this.checkTypeComposition(decl, index2, accept);
|
|
182056
183057
|
}
|
|
182057
|
-
this.checkTypeConformance(decls, satisfyStmts, index2, accept);
|
|
183058
|
+
this.checkTypeConformance(decls, satisfyStmts, includeStmts, index2, accept);
|
|
182058
183059
|
}
|
|
182059
183060
|
// ══════════════════════════════════════════════════════════════════════
|
|
182060
183061
|
// REQ-390 — SSM017-SSM021: whole-model type conformance (issue #104)
|
|
@@ -182064,7 +183065,7 @@ ${baseIndent}}`;
|
|
|
182064
183065
|
// the walk, so a type rooted in the unparsed standard library yields
|
|
182065
183066
|
// `unknown` and no diagnostic. That is what keeps the OMG corpus clean while
|
|
182066
183067
|
// still catching the workspace-local mistakes these codes exist for.
|
|
182067
|
-
checkTypeConformance(decls, satisfyStmts, index2, accept) {
|
|
183068
|
+
checkTypeConformance(decls, satisfyStmts, includeStmts, index2, accept) {
|
|
182068
183069
|
const model = new ConformanceModel((name) => this.resolveUnique(name, index2), (node) => this.implicit?.closureOf(node) ?? { names: /* @__PURE__ */ new Set(), complete: true });
|
|
182069
183070
|
for (const decl of decls) {
|
|
182070
183071
|
this.checkRedefinitionTypeConformance(decl, model, index2, accept);
|
|
@@ -182079,9 +183080,78 @@ ${baseIndent}}`;
|
|
|
182079
183080
|
this.checkRedefinitionDirection(decl, index2, accept);
|
|
182080
183081
|
this.checkInterfaceEndTypes(decl, model, index2, accept);
|
|
182081
183082
|
this.checkIndividualDefinitions(decl, model, accept);
|
|
183083
|
+
this.checkCaseDefinitionCount(decl, index2, accept);
|
|
183084
|
+
this.checkObjectiveSubject(decl, model, index2, accept);
|
|
182082
183085
|
}
|
|
182083
183086
|
for (const stmt of satisfyStmts)
|
|
182084
183087
|
this.checkSatisfierSubjectType(stmt, model, index2, accept);
|
|
183088
|
+
for (const stmt of includeStmts)
|
|
183089
|
+
this.checkIncludeBindings(stmt, model, index2, accept);
|
|
183090
|
+
}
|
|
183091
|
+
// ══════════════════════════════════════════════════════════════════════
|
|
183092
|
+
// REQ-417 — SSM045-SSM048: the bindings a case makes (issue #166)
|
|
183093
|
+
// ══════════════════════════════════════════════════════════════════════
|
|
183094
|
+
// SSM045 — OMG SysML v2 Part 1 §7.22.2: a CaseUsage has exactly one
|
|
183095
|
+
// CaseDefinition. Everything this extension derives about a case usage reads
|
|
183096
|
+
// through that one — its subject, its actor parameters, its objective — so
|
|
183097
|
+
// two leave all three undecided rather than merged. A type this validator
|
|
183098
|
+
// could not read is NOT counted: an unread type is not a wrong one, the same
|
|
183099
|
+
// three-valued rule the rest of this family follows.
|
|
183100
|
+
checkCaseDefinitionCount(decl, index2, accept) {
|
|
183101
|
+
const effective = effectiveCaseDefinition(decl, (name) => this.resolveUnique(name, index2));
|
|
183102
|
+
if (!effective || effective.isDefinition)
|
|
183103
|
+
return;
|
|
183104
|
+
const read = effective.definitions.filter((type) => type.node !== void 0);
|
|
183105
|
+
if (read.length < 2)
|
|
183106
|
+
return;
|
|
183107
|
+
accept(severity("SSM045", "error"), DIAGNOSTIC_MESSAGES.SSM045_CASE_MULTIPLE_DEFINITIONS(decl.name ?? "this case", read[0].name, read[1].name), { node: decl, code: "SSM045" });
|
|
183108
|
+
}
|
|
183109
|
+
// SSM046 — a `verification case` and a `use case` BIND their objective's
|
|
183110
|
+
// subject to their own (`objective obj { subject subj = VerificationCase::subj; }`
|
|
183111
|
+
// in `VerificationCases.sysml`), so a `subject` written on the objective with
|
|
183112
|
+
// an unrelated type states something the case has already decided otherwise.
|
|
183113
|
+
// A generic `case` and an `analysis case` only DEFAULT the objective's subject
|
|
183114
|
+
// to their result, which the model may override, so neither is judged here.
|
|
183115
|
+
checkObjectiveSubject(decl, model, index2, accept) {
|
|
183116
|
+
if (decl.$type !== "ObjectiveDecl")
|
|
183117
|
+
return;
|
|
183118
|
+
const binding = objectiveBindingOf(decl, (name) => this.resolveUnique(name, index2));
|
|
183119
|
+
if (!binding || binding.strength !== "bind" || !binding.own)
|
|
183120
|
+
return;
|
|
183121
|
+
const written = binding.own.typing?.type?.$refText?.trim();
|
|
183122
|
+
if (!written)
|
|
183123
|
+
return;
|
|
183124
|
+
const bound = binding.typeName;
|
|
183125
|
+
if (!bound || bound === DEFAULT_SUBJECT_TYPE)
|
|
183126
|
+
return;
|
|
183127
|
+
if (model.compatible(written, bound) !== "unrelated")
|
|
183128
|
+
return;
|
|
183129
|
+
const caseName = binding.caseNode.name ?? "this case";
|
|
183130
|
+
accept(severity("SSM046", "warning"), DIAGNOSTIC_MESSAGES.SSM046_OBJECTIVE_SUBJECT_TYPE(caseName, written, bound), { node: binding.own, code: "SSM046" });
|
|
183131
|
+
}
|
|
183132
|
+
// SSM047 / SSM048 — OMG SysML v2 Part 1 §7.25 / §8.2.2.25 IncludeUseCaseUsage.
|
|
183133
|
+
// An include is a REFERENCE to a use case performed elsewhere: it keeps that
|
|
183134
|
+
// use case's identity, is investigated on the including case's subject, and
|
|
183135
|
+
// binds that use case's own actor parameters. Both checks stay silent unless
|
|
183136
|
+
// the included use case was actually read.
|
|
183137
|
+
checkIncludeBindings(stmt, model, index2, accept) {
|
|
183138
|
+
const binding = includeBindingOf(stmt, (name) => this.resolveUnique(name, index2));
|
|
183139
|
+
if (!binding?.target)
|
|
183140
|
+
return;
|
|
183141
|
+
const included = binding.path ?? "the included use case";
|
|
183142
|
+
const includedSubject = binding.includedSubject;
|
|
183143
|
+
const containingSubject = binding.containingSubject;
|
|
183144
|
+
if (isDecidedSubject(includedSubject) && isDecidedSubject(containingSubject) && model.compatible(includedSubject.typeName, containingSubject.typeName) === "unrelated") {
|
|
183145
|
+
accept(severity("SSM047", "warning"), DIAGNOSTIC_MESSAGES.SSM047_INCLUDE_SUBJECT_TYPE(included, includedSubject.typeName, containingSubject.typeName), { node: stmt, code: "SSM047" });
|
|
183146
|
+
}
|
|
183147
|
+
if (binding.parameters.length === 0)
|
|
183148
|
+
return;
|
|
183149
|
+
const known2 = binding.parameters.map((parameter) => `'${parameter.name ?? "(anonymous)"}'`).join(", ");
|
|
183150
|
+
for (const actor of binding.actors) {
|
|
183151
|
+
if (!actor.name || actor.parameter)
|
|
183152
|
+
continue;
|
|
183153
|
+
accept(severity("SSM048", "warning"), DIAGNOSTIC_MESSAGES.SSM048_INCLUDE_ACTOR_BINDING(actor.name, included, known2), { node: actor.declaration, code: "SSM048" });
|
|
183154
|
+
}
|
|
182085
183155
|
}
|
|
182086
183156
|
// REQ-416 — SSM044: `satisfy MassReq by engine;` claims that `engine` is one
|
|
182087
183157
|
// of the things `MassReq` constrains, so `engine`'s type has to conform to
|
|
@@ -183346,7 +184416,16 @@ ${baseIndent}}`;
|
|
|
183346
184416
|
// issue #215 — the rest of the reference-form declarations. They share
|
|
183347
184417
|
// `ReferenceFormPath` with `perform`/`exhibit`, so they can spell the
|
|
183348
184418
|
// same defect and are judged by the same rule.
|
|
183349
|
-
|
|
184419
|
+
// REQ-415 — issue #164: the constraint reference shorthands. `assert`
|
|
184420
|
+
// shares its `ReferenceFormPath` with the other reference forms, so it
|
|
184421
|
+
// also carries the RES019 separator rule above.
|
|
184422
|
+
AssertConstraintStmt: [
|
|
184423
|
+
this.checkChainSeparators.bind(this),
|
|
184424
|
+
this.checkConstraintReference.bind(this),
|
|
184425
|
+
this.checkAssertionConsistency.bind(this)
|
|
184426
|
+
],
|
|
184427
|
+
RequireConstraintStmt: this.checkConstraintReference.bind(this),
|
|
184428
|
+
AssumeConstraintStmt: this.checkConstraintReference.bind(this),
|
|
183350
184429
|
EntryAction: this.checkChainSeparators.bind(this),
|
|
183351
184430
|
DoAction: this.checkChainSeparators.bind(this),
|
|
183352
184431
|
ExitAction: this.checkChainSeparators.bind(this),
|
|
@@ -183354,7 +184433,17 @@ ${baseIndent}}`;
|
|
|
183354
184433
|
ConnectorEnd: this.checkConnectorEndSeparators.bind(this),
|
|
183355
184434
|
RequirementDecl: this.checkRequirementDecl.bind(this),
|
|
183356
184435
|
AttributeDecl: this.checkAttributeDecl.bind(this),
|
|
183357
|
-
|
|
184436
|
+
// REQ-376 — STYL013 applies to both behavioral definitions that take
|
|
184437
|
+
// parameters, so the constraint check runs beside it here.
|
|
184438
|
+
ConstraintDecl: [
|
|
184439
|
+
this.checkConstraintDecl.bind(this),
|
|
184440
|
+
this.checkParameterDefaultOnDefinition.bind(this),
|
|
184441
|
+
this.checkParameterDirection.bind(this)
|
|
184442
|
+
],
|
|
184443
|
+
CalcDecl: [
|
|
184444
|
+
this.checkParameterDefaultOnDefinition.bind(this),
|
|
184445
|
+
this.checkParameterDirection.bind(this)
|
|
184446
|
+
],
|
|
183358
184447
|
VerificationCaseDecl: this.checkVerificationCaseDecl.bind(this),
|
|
183359
184448
|
AnalysisCaseDecl: this.checkAnalysisCaseDecl.bind(this),
|
|
183360
184449
|
ViewDecl: this.checkViewDecl.bind(this),
|
|
@@ -184077,6 +185166,9 @@ var STYLE_ADVISORY_CODES = /* @__PURE__ */ new Set([
|
|
|
184077
185166
|
"STYL009",
|
|
184078
185167
|
"STYL010",
|
|
184079
185168
|
"STYL011",
|
|
185169
|
+
"STYL012",
|
|
185170
|
+
"STYL013",
|
|
185171
|
+
"STYL014",
|
|
184080
185172
|
"LEX009",
|
|
184081
185173
|
// trailing whitespace
|
|
184082
185174
|
"SYN024",
|
|
@@ -184399,6 +185491,8 @@ var SysmlScopeComputation = class extends DefaultScopeComputation {
|
|
|
184399
185491
|
break;
|
|
184400
185492
|
if (node.$type === "ShortName" || node.$type === "ImportSeg")
|
|
184401
185493
|
continue;
|
|
185494
|
+
if (isReferenceFormDeclaration(node))
|
|
185495
|
+
continue;
|
|
184402
185496
|
const aliases = this.nameAliasesOf(node);
|
|
184403
185497
|
if (aliases.length === 0)
|
|
184404
185498
|
continue;
|
|
@@ -190059,7 +191153,9 @@ function nodeSize(node, direction) {
|
|
|
190059
191153
|
const portRunHeight = connectionUsage ? portRows ? portRows * 18 + 6 : 0 : portRows ? compactContainer ? portRows * 24 + 8 : 40 + portRows * 24 + 8 : 0;
|
|
190060
191154
|
const bodyH = Math.max(
|
|
190061
191155
|
connectionUsage ? 42 : BOX_H,
|
|
190062
|
-
|
|
191156
|
+
// REQ-209/375 - The value field sits at the bottom of the card, under
|
|
191157
|
+
// whatever compartments it carries, so both have to fit.
|
|
191158
|
+
node.value !== void 0 ? Math.max(88, NODE_COMPARTMENT_TOP + compartmentHeight(node) + 36) : 0,
|
|
190063
191159
|
featureH === 0 ? NODE_COMPARTMENT_TOP + compartmentHeight(node) : 0,
|
|
190064
191160
|
portRunHeight,
|
|
190065
191161
|
portedSideLength(ph, "left"),
|
|
@@ -190730,7 +191826,7 @@ function collapseIvModel(model, hiddenInternals) {
|
|
|
190730
191826
|
const frames = model.frames ?? [];
|
|
190731
191827
|
if (!frames.length) return model;
|
|
190732
191828
|
const frameById = new Map(frames.map((f) => [f.id, f]));
|
|
190733
|
-
const requested = new Set(frames.filter((frame2) => framePresentationEnabled(hiddenInternals, frame2, true) && isCollapsibleFrame("iv", frame2)).map((frame2) => frame2.id));
|
|
191829
|
+
const requested = new Set(frames.filter((frame2) => (frame2.meta?.internalsExpandable === false || framePresentationEnabled(hiddenInternals, frame2, true)) && isCollapsibleFrame("iv", frame2)).map((frame2) => frame2.id));
|
|
190734
191830
|
if (requested.size === 0) return model;
|
|
190735
191831
|
const hasRequestedAncestor = (id2) => {
|
|
190736
191832
|
let p = frameById.get(id2)?.parent;
|
|
@@ -190793,12 +191889,11 @@ function collapseIvModel(model, hiddenInternals) {
|
|
|
190793
191889
|
const toRoot = containerRootOf(e.to);
|
|
190794
191890
|
if (fromRoot !== void 0 && fromRoot === toRoot) return false;
|
|
190795
191891
|
return !(hidden.has(e.from) && fromRoot === void 0) && !(hidden.has(e.to) && toRoot === void 0);
|
|
190796
|
-
}).map((e) => {
|
|
191892
|
+
}).filter((e) => e.from === e.to || (bodyDock.get(e.from) ?? e.from) !== (bodyDock.get(e.to) ?? e.to)).map((e) => {
|
|
190797
191893
|
const from = bodyDock.get(e.from) ?? e.from;
|
|
190798
191894
|
const to = bodyDock.get(e.to) ?? e.to;
|
|
190799
191895
|
return from === e.from && to === e.to ? e : { ...e, from, to };
|
|
190800
191896
|
}).filter((e) => {
|
|
190801
|
-
if (e.from === e.to) return false;
|
|
190802
191897
|
const key2 = `${e.from}\0${e.to}\0${e.kind}\0${e.label ?? ""}`;
|
|
190803
191898
|
if (seenEdge.has(`${key2}:${e.id}`)) return false;
|
|
190804
191899
|
seenEdge.add(`${key2}:${e.id}`);
|
|
@@ -190876,17 +191971,30 @@ function isFeatureCompartmentNode(kind, node) {
|
|
|
190876
191971
|
if (kind === "stv") return node.shape === "state";
|
|
190877
191972
|
return false;
|
|
190878
191973
|
}
|
|
191974
|
+
function graphicalChildOwners(model) {
|
|
191975
|
+
const owners = /* @__PURE__ */ new Set();
|
|
191976
|
+
for (const node of model.nodes) {
|
|
191977
|
+
const owner = node.frame ?? node.parent;
|
|
191978
|
+
if (owner && owner !== node.id) owners.add(owner);
|
|
191979
|
+
}
|
|
191980
|
+
for (const frame2 of model.frames ?? []) {
|
|
191981
|
+
if (frame2.parent && frame2.parent !== frame2.id) owners.add(frame2.parent);
|
|
191982
|
+
}
|
|
191983
|
+
return owners;
|
|
191984
|
+
}
|
|
190879
191985
|
function applyFeatureCompartmentVisibility(model, visibleFeatureCompartments, hiddenInternals = {}) {
|
|
190880
191986
|
if (!CONTAINER_PRESENTATION_KINDS.has(model.kind)) return model;
|
|
190881
191987
|
const legacy = model.kind === "iv";
|
|
191988
|
+
const owners = graphicalChildOwners(model);
|
|
190882
191989
|
let changed = false;
|
|
190883
191990
|
const project = (host, leaf) => {
|
|
191991
|
+
const internalsExpandable = owners.has(host.id);
|
|
190884
191992
|
const alwaysVisible = host.meta?.alwaysVisibleCompartments === true;
|
|
190885
191993
|
const defaultVisible = leaf || model.kind === "afv" && !leaf;
|
|
190886
191994
|
const visible = alwaysVisible || framePresentationEnabled(visibleFeatureCompartments, host, legacy, defaultVisible);
|
|
190887
191995
|
const compartments = visible ? host.compartments : void 0;
|
|
190888
191996
|
const internalsHidden = leaf ? framePresentationEnabled(hiddenInternals, host, legacy) : host.meta?.internalsHidden === true;
|
|
190889
|
-
if (compartments === host.compartments && host.meta?.containerControls === true && host.meta?.featureCompartmentsVisible === visible && (!leaf || host.meta?.internalsHidden === internalsHidden)) return host;
|
|
191997
|
+
if (compartments === host.compartments && host.meta?.containerControls === true && host.meta?.internalsExpandable === internalsExpandable && host.meta?.featureCompartmentsVisible === visible && (!leaf || host.meta?.internalsHidden === internalsHidden)) return host;
|
|
190890
191998
|
changed = true;
|
|
190891
191999
|
return {
|
|
190892
192000
|
...host,
|
|
@@ -190894,6 +192002,7 @@ function applyFeatureCompartmentVisibility(model, visibleFeatureCompartments, hi
|
|
|
190894
192002
|
meta: {
|
|
190895
192003
|
...host.meta,
|
|
190896
192004
|
containerControls: true,
|
|
192005
|
+
internalsExpandable,
|
|
190897
192006
|
featureCompartmentsVisible: visible,
|
|
190898
192007
|
...leaf ? { internalsHidden } : {}
|
|
190899
192008
|
}
|
|
@@ -190909,10 +192018,10 @@ function collapseActionFrames(model, hiddenInternals, isHost = isCollapsibleActi
|
|
|
190909
192018
|
if (!frames.length) return model;
|
|
190910
192019
|
const frameById = new Map(frames.map((f) => [f.id, f]));
|
|
190911
192020
|
const requested = new Set(
|
|
190912
|
-
frames.filter((f) => framePresentationEnabled(hiddenInternals, f) && isHost(f)).map((f) => f.id)
|
|
192021
|
+
frames.filter((f) => (f.meta?.internalsExpandable === false || framePresentationEnabled(hiddenInternals, f)) && isHost(f)).map((f) => f.id)
|
|
190913
192022
|
);
|
|
190914
192023
|
if (requested.size === 0) return model;
|
|
190915
|
-
const
|
|
192024
|
+
const rootOf3 = (id2) => {
|
|
190916
192025
|
let root4;
|
|
190917
192026
|
const seen = /* @__PURE__ */ new Set();
|
|
190918
192027
|
for (let cur = id2; cur !== void 0 && !seen.has(cur); cur = frameById.get(cur)?.parent) {
|
|
@@ -190921,13 +192030,13 @@ function collapseActionFrames(model, hiddenInternals, isHost = isCollapsibleActi
|
|
|
190921
192030
|
}
|
|
190922
192031
|
return root4;
|
|
190923
192032
|
};
|
|
190924
|
-
const roots = new Set([...requested].filter((id2) =>
|
|
192033
|
+
const roots = new Set([...requested].filter((id2) => rootOf3(frameById.get(id2)?.parent) === void 0));
|
|
190925
192034
|
const dockOf = /* @__PURE__ */ new Map();
|
|
190926
192035
|
const proxyHost = /* @__PURE__ */ new Map();
|
|
190927
192036
|
const ownerOfHiddenPort = /* @__PURE__ */ new Map();
|
|
190928
192037
|
const hiddenFrameIds = /* @__PURE__ */ new Set();
|
|
190929
192038
|
for (const f of frames) {
|
|
190930
|
-
const root4 = roots.has(f.id) ?
|
|
192039
|
+
const root4 = roots.has(f.id) ? rootOf3(f.parent) : rootOf3(f.id);
|
|
190931
192040
|
if (root4 === void 0) continue;
|
|
190932
192041
|
hiddenFrameIds.add(f.id);
|
|
190933
192042
|
dockOf.set(f.id, root4);
|
|
@@ -190938,7 +192047,7 @@ function collapseActionFrames(model, hiddenInternals, isHost = isCollapsibleActi
|
|
|
190938
192047
|
}
|
|
190939
192048
|
const hiddenNodeIds = /* @__PURE__ */ new Set();
|
|
190940
192049
|
for (const n2 of model.nodes) {
|
|
190941
|
-
const root4 =
|
|
192050
|
+
const root4 = rootOf3(n2.frame);
|
|
190942
192051
|
if (root4 === void 0) continue;
|
|
190943
192052
|
hiddenNodeIds.add(n2.id);
|
|
190944
192053
|
dockOf.set(n2.id, root4);
|
|
@@ -190967,12 +192076,11 @@ function collapseActionFrames(model, hiddenInternals, isHost = isCollapsibleActi
|
|
|
190967
192076
|
const edges = model.edges.filter((e) => {
|
|
190968
192077
|
const fromRoot = containerRootOf(e.from);
|
|
190969
192078
|
return fromRoot === void 0 || fromRoot !== containerRootOf(e.to);
|
|
190970
|
-
}).map((e) => {
|
|
192079
|
+
}).filter((e) => e.from === e.to || (dockOf.get(e.from) ?? e.from) !== (dockOf.get(e.to) ?? e.to)).map((e) => {
|
|
190971
192080
|
const from = dockOf.get(e.from) ?? e.from;
|
|
190972
192081
|
const to = dockOf.get(e.to) ?? e.to;
|
|
190973
192082
|
return from === e.from && to === e.to ? e : { ...e, from, to };
|
|
190974
192083
|
}).filter((e) => {
|
|
190975
|
-
if (e.from === e.to) return false;
|
|
190976
192084
|
const key2 = `${e.from}\0${e.to}\0${e.kind}\0${e.label ?? ""}`;
|
|
190977
192085
|
if (seenEdge.has(`${key2}:${e.id}`)) return false;
|
|
190978
192086
|
seenEdge.add(`${key2}:${e.id}`);
|
|
@@ -205385,6 +206493,10 @@ function markersFor(kind) {
|
|
|
205385
206493
|
// REQ-199
|
|
205386
206494
|
case "derive":
|
|
205387
206495
|
// REQ-188
|
|
206496
|
+
case "assert":
|
|
206497
|
+
// REQ-131/REQ-415 — the constraint claims
|
|
206498
|
+
case "assume":
|
|
206499
|
+
case "require":
|
|
205388
206500
|
case "causation":
|
|
205389
206501
|
// REQ-189
|
|
205390
206502
|
case "import":
|
|
@@ -205761,7 +206873,7 @@ var KIN_MARKER_DEFS_SVG = [
|
|
|
205761
206873
|
|
|
205762
206874
|
// ../extension/src/webview/diagram/element-colors.ts
|
|
205763
206875
|
var ELEMENT_CLOSED_OPACITY = 1;
|
|
205764
|
-
var ELEMENT_OPEN_OPACITY = 0.
|
|
206876
|
+
var ELEMENT_OPEN_OPACITY = 0.3;
|
|
205765
206877
|
var DIAGRAM_ELEMENT_COLORS = {
|
|
205766
206878
|
default: {
|
|
205767
206879
|
outline: { light: "#3a3a3a", dark: "#a1a1a1" },
|
|
@@ -205894,7 +207006,22 @@ var DIAGRAM_LINE_COLORS = {
|
|
|
205894
207006
|
},
|
|
205895
207007
|
dependency: {
|
|
205896
207008
|
color: { light: "#6b46c1", dark: "#b08cf0" },
|
|
205897
|
-
kinds: [
|
|
207009
|
+
kinds: [
|
|
207010
|
+
"satisfy",
|
|
207011
|
+
"verify",
|
|
207012
|
+
"include",
|
|
207013
|
+
"dependency",
|
|
207014
|
+
"allocate",
|
|
207015
|
+
"frame",
|
|
207016
|
+
"derive",
|
|
207017
|
+
"causation",
|
|
207018
|
+
"import",
|
|
207019
|
+
"expose",
|
|
207020
|
+
// REQ-131/REQ-415 — the constraint claims read as the same family.
|
|
207021
|
+
"assert",
|
|
207022
|
+
"assume",
|
|
207023
|
+
"require"
|
|
207024
|
+
],
|
|
205898
207025
|
colorLabels: true
|
|
205899
207026
|
},
|
|
205900
207027
|
binding: {
|
|
@@ -206321,6 +207448,8 @@ body {
|
|
|
206321
207448
|
.dlink.satisfy, .dlink.verify, .dlink.include, .dlink.dependency { stroke-dasharray: 4 3; }
|
|
206322
207449
|
/* REQ-186/188/189/199/206/210 \u2014 the dashed labelled families */
|
|
206323
207450
|
.dlink.allocate, .dlink.frame, .dlink.derive, .dlink.causation, .dlink.import, .dlink.expose { stroke-dasharray: 4 3; }
|
|
207451
|
+
/* REQ-131/REQ-415 \u2014 the three constraint claims */
|
|
207452
|
+
.dlink.assert, .dlink.assume, .dlink.require { stroke-dasharray: 4 3; }
|
|
206324
207453
|
.dlink.annotation { stroke-dasharray: 2 3; }
|
|
206325
207454
|
.dlink.elaboration { stroke-dasharray: 2 3; pointer-events: none; }
|
|
206326
207455
|
.dlink.reply { stroke-dasharray: 4 3; } /* REQ-202 \u2014 sequence reply arrows */
|
|
@@ -207812,7 +208941,15 @@ var TOOLBOX = {
|
|
|
207812
208941
|
rel("verify", "verify", "\u2713", "click the verification case, then the requirement"),
|
|
207813
208942
|
rel("frame", "frame", "\u274F", "click the requirement/view, then the framed concern"),
|
|
207814
208943
|
rel("exhibit", "exhibit", "\u25C9", "click the part, then the exhibited state"),
|
|
207815
|
-
rel("perform", "perform", "\u25B7", "click the part, then the performed action")
|
|
208944
|
+
rel("perform", "perform", "\u25B7", "click the part, then the performed action"),
|
|
208945
|
+
// REQ-131/REQ-415 (user direction 2026-09-08 — "how do we add assert
|
|
208946
|
+
// constraint from the diagram") — the three constraint CLAIMS. The
|
|
208947
|
+
// diagram drew them in its compartments but could not create one, so
|
|
208948
|
+
// `assert constraint …` could only be typed. Each writes into the
|
|
208949
|
+
// claiming element, exactly as satisfy/verify/frame do.
|
|
208950
|
+
rel("assert", "assert", "\u22A8", "click the element that asserts, then the constraint"),
|
|
208951
|
+
rel("assume", "assume", "\u2283", "click the requirement/concern, then the assumed constraint"),
|
|
208952
|
+
rel("require", "require", "\u22A2", "click the requirement/concern, then the required constraint")
|
|
207816
208953
|
]
|
|
207817
208954
|
},
|
|
207818
208955
|
// The Interconnection View depicts parts, ports, and the compartment rows of
|
|
@@ -207843,7 +208980,12 @@ var TOOLBOX = {
|
|
|
207843
208980
|
rel("flow", "flow", "\u2192", "click the source port/feature, then the target"),
|
|
207844
208981
|
// issue #115 — an item flow that also sequences its ends.
|
|
207845
208982
|
rel("successionFlow", "succession flow", "\u21C9", "click the source port/feature, then the target"),
|
|
207846
|
-
rel("allocate", "allocate", "\u290F", "click the source part/feature, then the target")
|
|
208983
|
+
rel("allocate", "allocate", "\u290F", "click the source part/feature, then the target"),
|
|
208984
|
+
// REQ-131 — the view draws a part's constraints, and OMG's own
|
|
208985
|
+
// parametric picture is a part asserting one and binding its
|
|
208986
|
+
// parameters (ConstraintTest.sysml). `bind` was already here; the
|
|
208987
|
+
// claim that gives it something to bind was not.
|
|
208988
|
+
rel("assert", "assert", "\u22A8", "click the part, then the constraint it asserts")
|
|
207847
208989
|
]
|
|
207848
208990
|
},
|
|
207849
208991
|
// Action Flow depicts actions (a new `action def` becomes its own tile in a
|
|
@@ -208025,7 +209167,10 @@ var CHILD_KINDS = {
|
|
|
208025
209167
|
"event occurrence": [],
|
|
208026
209168
|
requirement: ["requirement", "constraint", "attribute", "part", "actor"],
|
|
208027
209169
|
concern: ["requirement", "constraint", "attribute", "actor"],
|
|
208028
|
-
constraint
|
|
209170
|
+
// REQ-376 — a constraint and a calculation take INPUTS, and there was no way
|
|
209171
|
+
// to add one from the diagram. Only `in`: an `out` or `inout` parameter on
|
|
209172
|
+
// either is STYL014, so offering one would contradict the check.
|
|
209173
|
+
constraint: ["in parameter", "attribute", "constraint"],
|
|
208029
209174
|
"use case": CASE_CHILDREN,
|
|
208030
209175
|
"analysis case": CASE_CHILDREN,
|
|
208031
209176
|
"verification case": CASE_CHILDREN,
|
|
@@ -208037,7 +209182,7 @@ var CHILD_KINDS = {
|
|
|
208037
209182
|
// issue (GRV on enum def): an enum def owns enumeration VALUES — nested enum
|
|
208038
209183
|
// usages — never requirements/parts; the old fallback offered the view list.
|
|
208039
209184
|
enum: ["enum"],
|
|
208040
|
-
calc: ["attribute", "calc"],
|
|
209185
|
+
calc: ["in parameter", "attribute", "calc"],
|
|
208041
209186
|
connection: ["attribute", "item", "part"],
|
|
208042
209187
|
connector: ["attribute", "item", "part"],
|
|
208043
209188
|
interface: ["port", "attribute", "item"],
|
|
@@ -208052,6 +209197,10 @@ var CHILD_KINDS = {
|
|
|
208052
209197
|
control: [],
|
|
208053
209198
|
terminate: [],
|
|
208054
209199
|
pin: [],
|
|
209200
|
+
// REQ-376 — the banner of a constraint/calc parameter card.
|
|
209201
|
+
"in parameter": [],
|
|
209202
|
+
"out parameter": [],
|
|
209203
|
+
"inout parameter": [],
|
|
208055
209204
|
// REQ-196 — a «performer» swimlane (OMG SysML v2 Part 1 §8.2.3.17, p.90). Its
|
|
208056
209205
|
// members are the actions that part performs; the edit writes the action into
|
|
208057
209206
|
// the OWNING action's body and a `perform` for it into the part.
|
|
@@ -208164,12 +209313,33 @@ function relationToolsForNode(keyword, viewKind, shape) {
|
|
|
208164
209313
|
case "exhibit":
|
|
208165
209314
|
case "perform":
|
|
208166
209315
|
return base === "part";
|
|
209316
|
+
// REQ-131 — the OMG corpus asserts inside a part or a package
|
|
209317
|
+
// (ConstraintTest.sysml, MassConstraintExample.sysml); a case and
|
|
209318
|
+
// a requirement own constraints of their own.
|
|
209319
|
+
case "assert":
|
|
209320
|
+
return [
|
|
209321
|
+
"part",
|
|
209322
|
+
"item",
|
|
209323
|
+
"package",
|
|
209324
|
+
"requirement",
|
|
209325
|
+
"concern",
|
|
209326
|
+
"use case",
|
|
209327
|
+
"analysis case",
|
|
209328
|
+
"verification case",
|
|
209329
|
+
"case"
|
|
209330
|
+
].includes(base);
|
|
209331
|
+
// REQ-131 — OMG SysML 8.2.2.21.1: a RequirementConstraintMembership
|
|
209332
|
+
// belongs to a requirement or a concern.
|
|
209333
|
+
case "assume":
|
|
209334
|
+
case "require":
|
|
209335
|
+
return ["requirement", "concern"].includes(base);
|
|
208167
209336
|
default:
|
|
208168
209337
|
return true;
|
|
208169
209338
|
}
|
|
208170
209339
|
}
|
|
208171
209340
|
if (viewKind === "iv") {
|
|
208172
209341
|
if (!["part", "port", "attribute", "item", "connection"].includes(base)) return false;
|
|
209342
|
+
if (tool.kind === "assert") return base === "part" || base === "item";
|
|
208173
209343
|
return tool.kind === "interface" ? base === "port" : true;
|
|
208174
209344
|
}
|
|
208175
209345
|
if (viewKind === "afv") {
|
|
@@ -208604,7 +209774,7 @@ function GvDisclosure({ element, svgWidth }) {
|
|
|
208604
209774
|
}
|
|
208605
209775
|
);
|
|
208606
209776
|
}
|
|
208607
|
-
function AttributeValueEditor({ id: id2, name, value, top }) {
|
|
209777
|
+
function AttributeValueEditor({ id: id2, name, value, top, label = "Value", placeholder = "Add value" }) {
|
|
208608
209778
|
const { onSetElementValue } = useDiagram();
|
|
208609
209779
|
const [draft, setDraft] = (0, import_react9.useState)(value);
|
|
208610
209780
|
if (!onSetElementValue) return null;
|
|
@@ -208614,8 +209784,8 @@ function AttributeValueEditor({ id: id2, name, value, top }) {
|
|
|
208614
209784
|
type: "text",
|
|
208615
209785
|
className: "dattribute-value nodrag nopan nowheel",
|
|
208616
209786
|
style: { top },
|
|
208617
|
-
"aria-label": "
|
|
208618
|
-
placeholder
|
|
209787
|
+
"aria-label": label + " of " + name,
|
|
209788
|
+
placeholder,
|
|
208619
209789
|
value: draft,
|
|
208620
209790
|
onPointerDown: (event) => event.stopPropagation(),
|
|
208621
209791
|
onClick: (event) => event.stopPropagation(),
|
|
@@ -209026,12 +210196,17 @@ function titleNameLine(name, type, mult, alias, availPx) {
|
|
|
209026
210196
|
const shown = fitText(full, availPx, 11);
|
|
209027
210197
|
return { full, shown, clipped: shown !== full };
|
|
209028
210198
|
}
|
|
209029
|
-
function
|
|
209030
|
-
|
|
210199
|
+
function valueFieldRole(keyword) {
|
|
210200
|
+
if (keyword.startsWith("constraint")) return { label: "Constraint", placeholder: "Add constraint" };
|
|
210201
|
+
if (keyword.startsWith("calc")) return { label: "Expression", placeholder: "Add expression" };
|
|
210202
|
+
return { label: "Value", placeholder: "Add value" };
|
|
210203
|
+
}
|
|
210204
|
+
function AttributeValueShape({ value, w, top, placeholder = "Add value" }) {
|
|
210205
|
+
const shown = fitText(value || placeholder, Math.max(16, w - 32), 11);
|
|
209031
210206
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("g", { className: "dattribute-value-shape", children: [
|
|
209032
210207
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("rect", { x: 8, y: top, width: Math.max(1, w - 16), height: 28, rx: 3 }),
|
|
209033
210208
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("text", { x: 15, y: top + 18, className: "dnode-label", children: [
|
|
209034
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("title", { children: value ||
|
|
210209
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("title", { children: value || placeholder }),
|
|
209035
210210
|
shown
|
|
209036
210211
|
] })
|
|
209037
210212
|
] });
|
|
@@ -209078,7 +210253,15 @@ function BoxBody({ node, w, h, showMult }) {
|
|
|
209078
210253
|
] })
|
|
209079
210254
|
] }),
|
|
209080
210255
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Compartments, { node, w, ruleClass }),
|
|
209081
|
-
node.value !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
210256
|
+
node.value !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
210257
|
+
AttributeValueShape,
|
|
210258
|
+
{
|
|
210259
|
+
value: node.value,
|
|
210260
|
+
w,
|
|
210261
|
+
top: h - 36,
|
|
210262
|
+
placeholder: valueFieldRole(node.keyword).placeholder
|
|
210263
|
+
}
|
|
210264
|
+
) : null
|
|
209082
210265
|
] });
|
|
209083
210266
|
}
|
|
209084
210267
|
function RoundedBody({ node, w, h, cls, showMult }) {
|
|
@@ -209262,7 +210445,7 @@ function SendAcceptBody({ node, w, h, accept }) {
|
|
|
209262
210445
|
}
|
|
209263
210446
|
function PackageBody({ node, w, h }) {
|
|
209264
210447
|
if (node.meta?.gvMode !== void 0) {
|
|
209265
|
-
const title = fitText(node.name, Math.max(24, w - 42), 11);
|
|
210448
|
+
const title = fitText(node.name, Math.max(24, w - (node.meta?.gvCanExpand === true ? 42 : 20)), 11);
|
|
209266
210449
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("g", { children: [
|
|
209267
210450
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { className: "dnode-rect package", d: packageFramePath(w, h) }),
|
|
209268
210451
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("text", { className: "dnode-kind", x: 10, y: 12, children: "\xABpackage\xBB" }),
|
|
@@ -210032,7 +211215,7 @@ function SysmlNode({ id: id2, data, draggable, selected: selected2, width, heigh
|
|
|
210032
211215
|
internalsVisible: !hiddenContainer,
|
|
210033
211216
|
featureCompartmentsVisible,
|
|
210034
211217
|
cornerRadius: nodeCornerRadius(node.shape, node.isDef, h, (node.compartments?.length ?? 0) > 0),
|
|
210035
|
-
onToggleInternals: ctx.onToggleInternals,
|
|
211218
|
+
onToggleInternals: node.meta?.internalsExpandable === true ? ctx.onToggleInternals : void 0,
|
|
210036
211219
|
onToggleFeatureCompartments: ctx.onToggleFeatureCompartments
|
|
210037
211220
|
}
|
|
210038
211221
|
) : null,
|
|
@@ -210042,7 +211225,8 @@ function SysmlNode({ id: id2, data, draggable, selected: selected2, width, heigh
|
|
|
210042
211225
|
id: id2,
|
|
210043
211226
|
name: node.name,
|
|
210044
211227
|
value: node.value,
|
|
210045
|
-
top: h - 36
|
|
211228
|
+
top: h - 36,
|
|
211229
|
+
...valueFieldRole(node.keyword)
|
|
210046
211230
|
},
|
|
210047
211231
|
id2 + ":" + node.value
|
|
210048
211232
|
) : null,
|
|
@@ -210289,7 +211473,15 @@ function FrameNode({ id: id2, data, selected: selected2, width, height }) {
|
|
|
210289
211473
|
strokeWidth: 0.8
|
|
210290
211474
|
}
|
|
210291
211475
|
) : null,
|
|
210292
|
-
frame2.value !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
211476
|
+
frame2.value !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
211477
|
+
AttributeValueShape,
|
|
211478
|
+
{
|
|
211479
|
+
value: frame2.value,
|
|
211480
|
+
w,
|
|
211481
|
+
top: frameHeaderHeight - 34,
|
|
211482
|
+
placeholder: valueFieldRole(frame2.keyword).placeholder
|
|
211483
|
+
}
|
|
211484
|
+
) : null,
|
|
210293
211485
|
isStructuredControl ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("g", { className: "dstructured-condition-compartment", children: [
|
|
210294
211486
|
isNamedStructuredAction ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
210295
211487
|
"line",
|
|
@@ -210555,7 +211747,7 @@ function FrameNode({ id: id2, data, selected: selected2, width, height }) {
|
|
|
210555
211747
|
internalsVisible: true,
|
|
210556
211748
|
featureCompartmentsVisible,
|
|
210557
211749
|
cornerRadius: frame2.isDef === true ? 0 : FRAME_USAGE_CORNER_RADIUS,
|
|
210558
|
-
onToggleInternals: ctx.onToggleInternals,
|
|
211750
|
+
onToggleInternals: frame2.meta?.internalsExpandable === true ? ctx.onToggleInternals : void 0,
|
|
210559
211751
|
onToggleFeatureCompartments: ctx.onToggleFeatureCompartments
|
|
210560
211752
|
}
|
|
210561
211753
|
) : null,
|
|
@@ -210565,7 +211757,8 @@ function FrameNode({ id: id2, data, selected: selected2, width, height }) {
|
|
|
210565
211757
|
id: id2,
|
|
210566
211758
|
name: frame2.label,
|
|
210567
211759
|
value: frame2.value,
|
|
210568
|
-
top: frameHeaderHeight - 34
|
|
211760
|
+
top: frameHeaderHeight - 34,
|
|
211761
|
+
...valueFieldRole(frame2.keyword)
|
|
210569
211762
|
},
|
|
210570
211763
|
id2 + ":" + frame2.value
|
|
210571
211764
|
) : null,
|
|
@@ -211260,7 +212453,7 @@ async function runExport(command) {
|
|
|
211260
212453
|
}
|
|
211261
212454
|
|
|
211262
212455
|
// src/main.ts
|
|
211263
|
-
var VERSION2 = true ? "0.
|
|
212456
|
+
var VERSION2 = true ? "0.38.0" : "dev";
|
|
211264
212457
|
function display(file) {
|
|
211265
212458
|
const rel2 = path9.relative(process.cwd(), file);
|
|
211266
212459
|
return rel2 && !rel2.startsWith("..") ? rel2.split(path9.sep).join("/") : file;
|