Skip to content

Textual export emits then; for successions whose target is an anonymous control node (then decide;) #2528

Description

@HuiJun

SysON version: v2026.9.0 (eclipsesyson/syson:v2026.9.0 image)
Component: syson-sysml-metamodel-services / SysMLElementSerializer (caseSuccessionAsUsage, caseDecisionNode)

Summary

Exporting a project created from the bundled Batmobile template to SysML v2 text splits

then decide;

into two lines, the first of which has no target:

action def 'Drive Batmobile' {
    first start then startBatmobile;
    action startBatmobile;
    then scanEnvironment;
    action scanEnvironment {
        out status : StatusKind;
    }
    then;
    decide ;
    if scanEnvironment.status == StatusKind::safe then 'Switch to standard mode';
    if scanEnvironment.status == StatusKind::alert then 'Switch to alert mode';
    action 'Switch to standard mode';
    ...

then; is not valid SysML v2 text — a succession needs a target — so a conformant parser rejects the file (e.g. "expected a name" at the then; line). Everything before this point in the action body exports correctly.

The reference text next to the template (templates/Batmobile.sysml) has:

then decide;
    if scanEnvironment.status == StatusKind::safe then 'Switch to standard mode';
    if scanEnvironment.status == StatusKind::alert then 'Switch to alert mode';

Steps to reproduce

  1. Start SysON v2026.9.0 and create a new project from the Batmobile template.
  2. Export the project to SysML v2 text (download the .sysml document, or call SysMLv2DocumentExporter on the document).
  3. Look at action def 'Drive Batmobile', just after action scanEnvironment.

What the model looks like

In templates/Batmobile.json the decision node is a sysml:DecisionNode with no declaredName, owned by 'Drive Batmobile' through a FeatureMembership. The succession that leads to it is a SuccessionAsUsage whose target EndFeatureMembership owns a ReferenceUsage with no ReferenceSubsetting — the target is only bound implicitly (the "next member" semantics of then <node>), so there is no named feature for the serializer to print after then.

Expected

then decide;

i.e. when a succession's target is an unnamed control node that immediately follows it (the TargetSuccession + inline ActionNode grammar form), serialize the node inline after then and skip its standalone declaration.

Actual

then;
decide ;

Related

Notes

  • caseSuccessionAsUsage unconditionally appends then and then appendConnectorEndMember(second), which produces nothing when the end has no ReferenceSubsetting/name. Emitting then with no target should either inline the following anonymous node or be reported as an export error rather than written out.
  • decide ; (with the stray space from "decide " + an empty usage declaration) is legal on its own, but once the succession is inlined it should disappear as a separate statement.
  • The same code path is likely to affect then fork;, then join;, then merge; and then done; where the node is anonymous.

Related (smaller) issue in the same export, if you prefer to track it separately

caseSatisfyRequirementUsage appends by unconditionally, so a satisfy usage without a SubjectMembership exports as

part def 'Part list' {
    assert satisfy 'system components' by;
}

which is invalid text; the template source is satisfy 'system components';. The by keyword should only be written when a satisfaction subject exists.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions