Detector: TypeSwitchDetector
Report (why the flagged code is CORRECT and the detector is wrong):
ClientRun is a translator between two protocols, and dispatching on the SOURCE type is what a translator is. The usual fix — move the behaviour onto the type — is unavailable in both directions: Scene's primitives must not know about the Client domain (Client is a new root-level domain that Scene will be deleted in favour of, so a toClient() on each Scene primitive would make the dying side depend on the living one), and Client's natives must not know about Scene's. A visitor would require Scene's primitives to accept a visitor, which is the same dependency wearing a pattern. The class is scaffolding with a defined death: when the pipes emit Client instructions directly it is deleted whole, and the match goes with it.
Cleanest design the reporter can conceive:
A single match(true) over instanceof in one private method, each arm delegating to a small typed method (mount(Mount), animate(Play), listen(Listen)) so the concrete type is known inside each. The dispatch is stated once, in one place, and every arm is a named method that reads its source primitive's typed fields — no string keys, no reflection, no registry indirection that hides which source type maps to which target.
⚖️ Maintainer litmus: a valid detector-report needs the flagged code to ALREADY BE the
cleanest design. If the design above differs from the flagged code at all, THAT design is
the owed fix — close this report; the fix is still owed.
Where: src/Scene/Pipeline/ClientRun.php:67
Code (src/Scene/Pipeline/ClientRun.php:67):
64
65 private function translated(Primitive | Sequence $step): TranslatedRun
66 {
→ 67 if ($step instanceof Sequence)
68 {
69 $steps = $this->allOf($step->steps());
70
71 return self::emit($steps->run, $steps);
72 }
73
74 return match (true)
75 {
76 $step instanceof Navigate => new TranslatedRun([new ClientNavigate($step->url)], []),
77 $step instanceof Mount => $this->mount($step),
78 $step instanceof Listen => $this->listener($step),
79 $step instanceof Toggle => $this->branch($step),
80 $step instanceof Play => $this->animate($step),
81 $step instanceof Unmount => new TranslatedRun([new ClientUnmount($step->node)], []),
82 $step instanceof Anchor => new TranslatedRun([self::anchor($step)], []),
83 $step instanceof Hotkey => $this->hotkey($step),
84 $step instanceof Mark => new TranslatedRun([self::modify($step)], []),
85 $step instanceof Send => self::raise($step),
86 default => new TranslatedRun([], [$step->command()->value], isWhole: false),
87 };
88 }
89
90 private function mount(Mount $mount): TranslatedRun
91 {
Filed via commandments report from a consumer project.
Detector:
TypeSwitchDetectorReport (why the flagged code is CORRECT and the detector is wrong):
ClientRun is a translator between two protocols, and dispatching on the SOURCE type is what a translator is. The usual fix — move the behaviour onto the type — is unavailable in both directions: Scene's primitives must not know about the Client domain (Client is a new root-level domain that Scene will be deleted in favour of, so a toClient() on each Scene primitive would make the dying side depend on the living one), and Client's natives must not know about Scene's. A visitor would require Scene's primitives to accept a visitor, which is the same dependency wearing a pattern. The class is scaffolding with a defined death: when the pipes emit Client instructions directly it is deleted whole, and the match goes with it.
Cleanest design the reporter can conceive:
A single match(true) over instanceof in one private method, each arm delegating to a small typed method (mount(Mount), animate(Play), listen(Listen)) so the concrete type is known inside each. The dispatch is stated once, in one place, and every arm is a named method that reads its source primitive's typed fields — no string keys, no reflection, no registry indirection that hides which source type maps to which target.
Where:
src/Scene/Pipeline/ClientRun.php:67Code (
src/Scene/Pipeline/ClientRun.php:67):Filed via
commandments reportfrom a consumer project.