Perform action referencing bug

Hi guys,

Consider the following model:

package Package {
    action def TheAction;
    part def ThePart {
        perform action theAction : TheAction;
    }

    part def TheSystem {

        action theAction : TheAction;
        part thePart : ThePart {
            perform action theActionPerformance references theAction redefines ThePart::theAction;
        }
    }
}

I’m expecting that theAction in the perform action should refer to TheSystem::theAction.
However, Automator is returning ThePart::theAction:

import syside

model, _ = syside.load_model(['model.sysml'])
with model.documents[-1].lock() as doc:
    root_node = doc.root_node
    package: syside.Package = root_node.children.elements[0]

    the_system = package.children.elements[2]
    assert the_system.name == 'TheSystem'

    the_local_action = the_system.children.elements[0]
    assert the_local_action.name == 'theAction'
    print(the_local_action.qualified_name)

    the_local_part = the_system.children.elements[1]
    assert the_local_part.name == 'thePart'

    local_action_performance = the_local_part.children.elements[0]
    assert isinstance(local_action_performance, syside.PerformActionUsage)

    print(local_action_performance.performed_action.qualified_name)
    assert local_action_performance.performed_action == the_local_action

Did I misinterpret the way local namespaces work in SysML v2, or is this a bug?

Greetings,
Jasper

Hi Jasper,

This is expected. Name resolution for referenced theAction starts in thePart which has an inherited theAction, and is selected.

Note that references are resolved in order, and the redefinition only comes into play later on. In contrast, Pilot implementation seems to resolve, or at least hide theAction, redefinition before resolving referencing which then resolves it to TheSystem::theAction instead. However, the specification makes no mention of this implied ordering.

Hi Daumantas,

All right, so it’s best to use the qualified name instead when specifying the reference in this case.

Unfortunately, when I would load a model and then print it, sometimes the reference is not printed with its fully qualified path anymore. I can’t reproduce it in a small example like this unfortunately…

Greetings,
Jasper

If you happen to make a reproduction case, I would be happy to look at.

I managed to reproduce the problem: it happens when creating the action performance.

Model:

package Package {
    action def TheAction;
    part def ThePart {
        perform action theAction : TheAction;
    }

    part def TheSystem {
        action theAction : TheAction;
        part thePart : ThePart {
            
        }
    }
}

Script:

import syside

model, _ = syside.load_model(['model2.sysml'])
with model.documents[-1].lock() as doc:
    root_node = doc.root_node
    package: syside.Package = root_node.children.elements[0]

    the_part_def = package.children.elements[1]
    assert the_part_def.name == 'ThePart'

    the_perform_action = the_part_def.children.elements[0]
    assert isinstance(the_perform_action, syside.PerformActionUsage)

    the_system = package.children.elements[2]
    assert the_system.name == 'TheSystem'

    the_local_action = the_system.children.elements[0]
    assert the_local_action.name == 'theAction'

    the_local_part = the_system.children.elements[1]
    assert the_local_part.name == 'thePart'

    _, local_action_performance = the_local_part.children.append(syside.OwningMembership, syside.PerformActionUsage)
    local_action_performance.declared_name = 'theActionPerformance'

    local_action_performance.heritage.append(syside.ReferenceSubsetting, the_local_action)

    local_action_performance.heritage.append(syside.Redefinition, the_perform_action)

    printer_config = syside.PrinterConfig(line_width=80, tab_width=4)
    printer = syside.ModelPrinter.sysml()
    output = syside.pprint(root_node, printer, printer_config)
    print(output)

Printer action performance: perform action theActionPerformance ::> theAction :>> ThePart::theAction;

So then when loading that, the referenced action is interpreted wrongly.
Hope this helps.

Thanks, the minimal synthetic reference printer does not currently take inherited names into account when selecting the initial reference segment. I have extended the printer for the next release to check base types as well. In the meantime, you can use ReferencePrinter to select reference segments manually.