feat(migrate): write every SysML v1 diagram as a v2 view exposing what it shows - #524
Merged
Merged
Conversation
…records Co-Authored-By: jason.han <hanhuijun@gmail.com>
…member target Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…e/migrate-diagrams-to-views An «Expose» whose supplier is a diagram exposes the diagram's view, and a diagram's view takes a numbered name beside a same-named «View» usage. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ber references with :: An expose names a member by its qualified name, never a feature chain: memberRef writes Package::Def::feature where ref chains Def.feature for a subsetting. An anonymous association written as an actor of a use case is exposed as that actor, and is no connection def of its own. Co-Authored-By: jason.han <hanhuijun@gmail.com>
Contributor
Author
|
I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".
|
…one, and harden root and viewpoint edge cases - The diagram reader takes its kind from the first descendant carrying a plain type or umlType attribute, never from an xmi:type, and reads the shown elements beneath that object only; a diagram nested in another is left to its own record. - A «View» package at the document root is classified as a view; only a root Model, whose members are flattened to the top level, is not. - An InterfaceRealization at the document root is refused with a note instead of dereferencing its missing owner. - A «Viewpoint» concernList entry that is not a Comment frames no concern and downgrades the viewpoint, leaving the named element's verdict alone. Co-Authored-By: jason.han <hanhuijun@gmail.com>
… per client Co-Authored-By: jason.han <hanhuijun@gmail.com>
…xpressions' into feature/migrate-diagrams-to-views
devin-ai-integration
Bot
changed the base branch from
develop
to
feature/migrate-views-usecases-expressions
September 22, 2026 13:09
… method's diagram in its operation The representation object is selected by how it is held or tagged (a diagramRepresentation child or a DiagramRepresentationObject), or failing that by the umlType it states; a child with a plain type attribute is no longer taken for it, and only the representation's own usedElements are shown. A diagram owned by a behavior that is an operation's method is written in the operation's body, where the behavior itself is written, instead of beside the owning classifier under a numbered name. Co-Authored-By: jason.han <hanhuijun@gmail.com>
… diagram views Co-Authored-By: jason.han <hanhuijun@gmail.com>
…e ScalarValues is shadowed Co-Authored-By: jason.han <hanhuijun@gmail.com>
Merged
6 tasks
…s' into feature/migrate-diagrams-to-views
… diagram views Co-Authored-By: jason.han <hanhuijun@gmail.com>
…data def Co-Authored-By: jason.han <hanhuijun@gmail.com>
… diagram views Co-Authored-By: jason.han <hanhuijun@gmail.com>
Contributor
Author
|
On the "multi-operand powers associate backward" flag ( |
…y their written names A member of an operation's method behavior is written in the operation's body, so its qualified name — in an `expose` and in the report's target column — now runs through the operation, not the behavior. Association ends are named once, ahead of writing, so a declaration and every reference to a renamed end agree. An «Expose» whose supplier is a proxy with a local `href` fragment naming a diagram exposes that diagram's view. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…owers left An ElementValue a tool keeps in an xmi:Extension is adopted as an operand wherever the tool nests it — a direct child or under several wrappers — while a diagram's own content and reference extensions are still not read. A power tree over three or more operands is written `(a ** b) ** c`: the migrator folds every operator left to right, and v2 groups `**` to the right. Co-Authored-By: jason.han <hanhuijun@gmail.com>
Shown elements are read only from the diagram's representation object; when a tool serialized none, other content of the diagram (a legend, its history) is not scanned for usedElements, so the view is empty as its note says. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…e/migrate-diagrams-to-views Co-Authored-By: jason.han <hanhuijun@gmail.com>
…written as An action node is written as a usage inside its activity's action def (or the operation whose method the activity is), and that usage opens no body views could be members of. Planning a view under the node left the diagram unmapped and unwritten. The planner now resolves each candidate host to the element whose v2 body stands for it and refuses action nodes, so the walk falls back to the containing action def or operation, noted as approximated. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…xpressions' into feature/migrate-diagrams-to-views Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # internal/translate/migrate/expression.go # internal/translate/xmi/sysmlv1/xmi.go # internal/translate/xmi/sysmlv1/xmi_test.go
6 tasks
…xpressions' into feature/migrate-diagrams-to-views
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Base automatically changed from
feature/migrate-views-usecases-expressions
to
develop
September 22, 2026 17:54
A behavior's member whose role no behavior writer declares was taken as written, so a constraint of an opaque or function behavior, or a port of an activity or state machine, was dropped silently and a diagram could try to expose it. Every behavior body now names the roles it writes and reports the rest unmapped, once, with the kind of the member and of the body. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…members A method behavior's members are written in the operation's body beside the diagram's view, but the view's name was checked only against the operation's own children, so a diagram named like a method's attribute, nested definition or action node redeclared its name. Co-Authored-By: jason.han <hanhuijun@gmail.com>
… in a root package A diagram held directly under xmi:XMI names no owner and no holder, and its view was placed in the first root package that hosts views, making it that package's member. The top level is now a nil host of its own: the root model, whose members are written there, resolves to it, and top-level views are written after the roots. Top-level name reservation now sees the root model's members and the other roots' declarations. Co-Authored-By: jason.han <hanhuijun@gmail.com>
An association's connection def is declared under the name its references and report rows use, so a later sibling sharing a name gets its distinct name; anonymity is still judged from the source name, so an anonymous association something refers to is still written as its member ends. Co-Authored-By: jason.han <hanhuijun@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
What and why
Every diagram of a SysML v1 model was skipped by the migrator as "tool-private xmi:Extension content" (1,347 report rows in the proof model). A diagram is a v2
view: what it shows is itsexposelist and its kind selects arenderfrom the standardViewslibrary. This PR reads the diagrams a tool serializes and writes each as aviewusage.Reader (
internal/translate/xmi/sysmlv1/diagram.go). Auml:Diagram(local(xmi:type) == "Diagram", whatever the tool) becomes a tool-neutral recordKind/UMLKindcome from theDiagramRepresentationObject'stype/umlTypewhen one is serialized: the representation object is found by how it is held (diagramRepresentation) or tagged, else by aumlType, never by a plaintype(which names a UML type on other descendants), and the shown ids are read from that object's subtree only; a bare diagram keeps an empty kind. Recognized diagrams leave the skipped-extension bookkeeping (no double reporting) while every other typed element of the extension is still recorded as skipped;ElementValuenodes a diagram's extension holds are adopted as before. External hrefs and proxies resolve like any other reference.Migrator (
internal/translate/migrate/diagrams.go). Oneviewper diagram, in the body of the v2 element written forownerOfDiagram(a package, or a classifier's def — apart def,state def,metadata deffor a user stereotype…); a diagram whose owner has no v2 body (an enumeration, an opaque behavior, a property…) is written in the nearest ancestor that has one and reported approximated with the reason; a diagram owned by a behavior that is an operation's method is written in the operation's body, where that behavior is written. A diagram with no owner, or an owner id that resolves to nothing, is placed by the element whose extension holds it, or at the document's top level when the extension is held by the root model or by the document itself (the top level is a host of its own, never a root package); a holder under nothing written is unmapped with the reason. The view exposes every shown element the document writes through the existing qualified-name machinery (no new resolver); shown elements that are unwritten or dangling are dropped and counted in the note, and a diagram showing nothing writable is an empty view (which validates). Renderings are chosen by the diagram-type family the tooltypeand UMLumlTypename (first matching row wins):Views::asElementTableViews::asInterconnectionDiagramViews::asTreeDiagramViews::asTextualNotationrender Views::…is written$::Views::…when a member namedViewson the way out of scope would hide the library, and a shown primitive is exposed as$::ScalarValues::…when a member namedScalarValueswould.Names follow the existing quoting rules; a view whose name collides with another member of its host (a state, an action, a «View» usage with the same name as its diagram — Cameo's default) is suffixed with the existing sibling-name disambiguation (
'Overview 2') and the report says so. Anonymous diagrams are nameddiagram.«Expose» to a diagram. #514 wrote an «Expose» dependency whose supplier is a diagram as unmapped ("notation only"). The seam is closed: it now writes
expose <the diagram's view, qualified from the client>;. #514 has landed ondevelop, which this branch merges (ordinary merges), so the diff is the diagram work.Consequences in shared code.
exposeand view member references are written with::member qualification (memberRef), not the feature-chain.thatrefuses for expressions; the former mixed the two, which was a syntax error once a diagram exposed a nested feature.internal/syntax/parser/defusage.go): a view's reference members (render,satisfy,expose) accept a globally qualified target$::Views::asTreeDiagram, which the grammar allows and which the migrator writes when a member namedViewshides the library.behaviorWritesMember) andunwrittenMembersreports the rest once — a constraint, attribute, operation or nested behavior of an OpaqueBehavior, FunctionBehavior or Interaction, a port of an Activity or StateMachine (34 rows in the proof model that were absent before). A diagram showing such a member does not expose it.unnamedwithout a note).endNames), soexposenever spells a path that is not written. A diagram view hosted by an operation body is numbered past the method's members too (viewNamechecksbodyMethod(host)), since they are written beside it.uml:ElementValuea tool keeps in anxmi:Extensionis adopted as an operand at any nesting depth, not only one wrapper down; a serialized diagram's own content is never read as an operand.**tree over three or more operands is written(a ** b) ** c, since the v2 grammar groups**to the right while every operator tree is folded left.Specification basis
SysML v2 Language Specification, Views and Viewpoints: a
ViewUsagewhoseExposeimports name what it shows and whoseViewRenderingMembershipnames a rendering of the standardViewslibrary (asTreeDiagram,asInterconnectionDiagram,asElementTable,asTextualNotation,internal/workspace/libs/stdlib/Systems Library/Views.sysml). The$::global qualification is KerML'sGlobalQualifiedName. No row ofdocs/project/spec-compliance.mdmoves.How it was verified
tests/migrate/testdata/xmi/:diagrams.xmi(a BDD, an IBD, an activity diagram, a table, a state machine diagram; shown elements that are unwritten, dangling, imported from a library, owned by another package, nested features; diagrams owned by an activity and by an opaque behavior that are operation methods) andmalformed_diagrams.xmi(missing owner, unknown owner, dangling ids, empty contents, a bare diagram with no representation, an anonymous diagram, an owner with no v2 body, a profile-owned diagram with no writable host). Their notation and report goldens are pinned byTestGoldenConstructFixtures, which also asserts each notation validates with 0 errors.report_viewsgoldens regenerated for the «Expose»→diagram seam.diagram_test.go): valid diagram, no owner, no representation, kind from a type-only representation object, atypeon a non-representation descendant ignored, a diagram without a representation showing nothing, nested diagrams read separately, duplicate and dangling ids, diagrams in archive entries resolving across documents.diagrams_internal_test.go): package and classifier hosts, missing/unknown owner, dangling ids, empty diagram, host fallback to a written ancestor, unknown kind, collision with an existing member, duplicate diagram names, no representable host, method-owned diagrams hosted by the operation and numbered past the method's members, diagrams owned by action nodes and by a simulation configuration, a shown primitive under a member namedScalarValues— each reported exactly once.behavior_members_internal_test.go: a constraint or attribute of an opaque, function or interaction body, of an operation's opaque method, and a port of an activity or state machine are reported unmapped once and not exposed, while an activity's or state machine's constraints and attributes stay written.tests/parser/testdata/parse/view_members.sysmlgained a$::-qualified target;TestStdlibConformance,TestGolden,TestNegativepass.gofmt -l .empty,go build ./...,go vet ./...,go test ./...,make lint(staticcheck + gosec) all clean;python3 scripts/changelog.py check,python3 scripts/check-doc-ids.pyclean. Corpus gates with the corpora downloaded (OPENSYSML_REQUIRE_TRAINING_CORPUS=1 OPENSYSML_REQUIRE_PILOT_CORPORA=1 OPENSYSML_REQUIRE_PSSM_SUITE=1 go test -count=1 ./tests/corpus) pass with no ratchet movement and no baseline change.rg -n "TMT|APS\b|IRIS|WFOS|Time_Acq|M1CS|PEAS" internal docs/reference/sysml-v1-migration.md changes/unreleased/migrate-diagrams-to-views.added.mdon the added lines): no matches. The only tool names in production code are the provenance the reader already keyed on (thexmi:Extensionextender).Proof model (Cameo 2024x, 1,347 diagrams)
-validateerrors-validatewarningsReport rows moved between categories, develop → this branch:
All 1,347 diagrams are written as views (525
asTreeDiagram, 107asInterconnectionDiagram, 100asElementTable, 615asTextualNotation); none is unmapped. Of the 1,186 approximated: 1,024 drop unwritten shown elements (259 of them expose nothing because none is written), 241 have dangling shown ids, 178 are hosted by a written ancestor because their owner has no v2 body and 19 by the operation whose method owns them, 134 show nothing, 95 are renamed for a collision (several reasons can apply to one diagram). The 3 «Expose» rows still unmapped expose a model outside the document or come from a client that is not a view.Warnings. The 631 additional warnings are all
Duplicate of inherited member nameonview x :> Ysubsetting lines of «View» usages (1,404 → 2,035 in total; 828 → 1,107 of them on a single such line): a «View» usage exposing packages with::**now also inherits the diagram views those packages own and their exposed members, so same-named members reach the subsetting view by two paths. An anonymous «View»-typed property a diagram shows is now named so it can be exposed (view overview :> Overviewwhere develop writesview :> Overview), which moves those warnings onto the named line. Diagram views themselves expose specific elements, never::**, and none of the warnings is on a diagram view.Execution.
sysml out.sysml -compare-results out.migration-results.jsonon both outputs (the sidecar is byte-identical: 62 configurations): 17 configurations run and compare without a seed, 24 more with-seed 1— the same 41 on develop and here — and 21 are refused on both for the same reasons (no migrated behavior). The 41 result tables (242 rows) and the 6 execution errors are identical. The single textual difference is one error message that names an invoked action by its qualified name instead of its bare name: the enclosingstate defnow owns a view named after that action's diagram, so the existing shadowing rule qualifies the reference — the call resolves to the same action.Checklist
make testandmake lintpass locallychanges/unreleased/<slug>.<section>.md, not as an edit toCHANGELOG.mdmake docs-countsrun if a gate count moved (compliance rows need nothing: the census is counted at docs build) — no gate count movedF4,K5) in the body, docs, or changelog