How to reference actions in if/else blocks

Hello,

I have a question regarding action references inside if/else blocks in a use case usage flow.

For example:

use case useCaseUsage {

    action action1 { out data; }
    action action2 { in data; }
    action action3;
    action action4 { in data; }

    flow action1.data to action2.data;
    flow action1.data to action4.data;

    first start;
    then action1;
    then if condition {
        action2;
    } else {
        action3;
    }
    then action4;
    then done;
}

My question is specifically about how action2 and action3 should be referenced inside the if block.

Is it correct to simply write the action name as shown above (action2;, action3;)?

Or should I use something like perform action2 / perform action3 instead?

If perform is used, and the action has in/out parameters, do I need to explicitly provide or bind values for those parameters even if flows already exist?

Also, if there are multiple actions inside the same if or else block, should they be structured using first ... then ..., for example:

if condition {
    first action2;
    then action3;
}

Or is there another recommended way to structure multiple actions inside conditional branches?

I am trying to understand the recommended way to reference and invoke actions inside conditional flow structures.

Thank you.

Your instinct to reach for perform is the right one — use perform action2 and perform action3, not the bare action2;.

  1. Writing action2; inside the branch does not refer to your existing action2. It creates a brand-new reference named action2, local to the branch —
    not typed as an action, and resolving to nothing (SySIDE leaves its referenced_feature empty). So it neither performs your action2 nor receives the flow action1.data to action2.data;;
    that flow still targets the outer action2. perform action2 is a genuine reference — its performed action is the action2 you declared, so the flow’s target and the performed step are
    the same element. Both forms load without error, so the difference is silent, which is what makes the bare form easy to get wrong.

  2. No extra binding needed. Because perform action2 is the same action2 your flow targets, flow action1.data to action2.data; already supplies its in data. You’d
    only add an explicit binding if no flow carried that value.

  3. Write the first action directly and chain the rest with then — don’t open the branch with first:

if condition {
    perform action2;
    then perform action3;
}

first only marks the start step at the top of the body (your first start;); inside a branch it’s a parse error.

Checking what an action reference points at

Both action2; and perform action2; load without an error, so the editor
won’t tell you which one actually connects to your declared action2 (the one
your flow feeds). Here’s how to see what SySIDE really linked.

Note: this uses a small Python script. If you’re comfortable running
Python, it gives you a direct look at the resolved model.

The script

Save as show_model.py and run uv run show_model.py yourfile.sysml:

#!/usr/bin/env -S uv run --script
# /// script
# dependencies = ["syside"]
# ///
import sys, syside
model, _ = syside.try_load_model(sysml_source=open(sys.argv[1]).read())
with list(model.user_docs)[0].lock() as locked:
    print(syside.sexp(locked.root_node, include_implicit=False, print_references=True))

It prints the model as a nested tree. print_references=True adds a
... to <name> line under each reference, showing what it resolved to.

What it shows

With the bare name, the branch step has no to ... line:

(ActionUsage thenClause
  (FeatureMembership
    (ReferenceUsage action2)))          <-- resolves to nothing

With perform, it carries a ReferenceSubsetting to ...::action2:

(ActionUsage thenClause
  (FeatureMembership
    (PerformActionUsage action2
      (ReferenceSubsetting to Test::useCaseUsage::action2))))   <-- your action2

(For comparison, your flow’s target end always shows
ReferenceSubsetting to Test::useCaseUsage::action2 — so with perform the
flow target and the performed step are the same element; with the bare name
they are not.)

Thank you very much for the detailed explanation and for sharing the script.

This was very helpful and clarified exactly what I was confused about. I will definitely try the script and keep it in mind for future debugging and learning.

I really appreciate your help.