Add ReturnRemoval mutator#2296
Conversation
… feat/ReturnRemoval
|
looking at we need to find/tag |
|
Sadly NodeConnectingVisitor only sets the next attribute on nodes that share the same parent. I.e. these do not: if ($foo) {
return $bar;
}
return $baz;But it is a good starting point for our own connecting visitor. |
|
Yes, posted it for inspiration to implement a smaller/specific one for our use-case |
| $this->previous?->setAttribute(self::NEXT_ATTRIBUTE, $node); | ||
| $this->previous = $node; |
There was a problem hiding this comment.
I think we should set references between AstNodes very carefully.
at best this visitor would be very specific for the use-case and set a more specific attribute, like "isLastReturn" and if-possible only on Return_ nodes.
references between ast nodes can be very costly, as they hinder the garbage collector.
see e.g. https://phpstan.org/blog/preprocessing-ast-for-custom-rules which describes the cost of a parent/next/previous attribute the NodeConnectingVisitor incurs.
There was a problem hiding this comment.
If PHPStan has to keep the whole codebase in memory to do its thing, then it makes total sense for it. For us, it is a single file at a time. So it should not be a problem, and we already use the parent connecting visitor.
maks-rafalko
left a comment
There was a problem hiding this comment.
so I've went through my todo list and the only one item left is to analyze overlapping, which I will postpone as I don't have time yet for this time-consuming activity.
Also, I've read seggested topics by Markus regarding weak references, and they look very interesting. I will create an issue to have a separate discussion on this topic so we can check if and how weak references help us not only here for the new visitor but for parent connector as well.
I've also analyzed ~20 escaped mutants generated for Infection and they do make sense.
Let's try!
This PR:
ReturnRemovalmutator to fix Return removal mutator #2268NextConnectingVisitorto track statement execution orderNextConnectingVisitorAdded a new AST visitor that connects sequential statement nodes by adding a "next" attribute. This visitor:
Nop)ReturnRemovalmutator to detect if there are statements after a returnReturnRemovalMutatorThe mutator now intelligently removes return statements without causing language errors:
NextConnectingVisitor)return;orreturn null;at the end of functions without return types, as these are semantically equivalent to implicit null returnsSo we avoid both un-killable mutations and fatal errors.
Benefits
This implementation successfully avoids language errors while still exposing untested code paths. By preserving the last return statement in typed functions, we ensure the code remains syntactically valid while still being able to detect:
The approach provides maximum mutation coverage without breaking PHP's type system. Just what we wanted 🙂
Per-mutator report: