-
-
Notifications
You must be signed in to change notification settings - Fork 166
Custom mutator generator #1969
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Custom mutator generator #1969
Conversation
spend the day in some docker shit, will wait tomorrow / after tomorrow for a review 😅 |
ping @theofidry @sanmai it would be nice if you can do review, cause I'm going to move forward. Basically, everything is done to go live (from my tests and understanding) |
bb67c37
to
0e2d370
Compare
It would be also nice if you can go through the docs and try to do it yourself :) just to check if it's clear for you what to do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had a brief look, couldn't get to try it or check it out locally. It's actually a lot less changes than I expected (from the diff)
@@ -189,7 +195,7 @@ private function assertSyntaxIsValid(string $realMutatedCode): void | |||
$returnCode, | |||
sprintf( | |||
'Mutator %s produces invalid code', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'Mutator %s produces invalid code', | |
'The mutator "%s" produced invalid PHP code.', |
Might be worth tweaking it to print for which output this is the case?
@theofidry please review again |
New thing: https://infection-php.dev/ast - this will help custom mutator developers to better/easier understand what to use in |
thank you @theofidry and @sidz @sanmai feel free to add comments, will address in separate PR |
[](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [infection/infection](https://togithub.com/infection/infection) | `^0.28.1` -> `^0.29.0` | [](https://docs.renovatebot.com/merge-confidence/) | [](https://docs.renovatebot.com/merge-confidence/) | [](https://docs.renovatebot.com/merge-confidence/) | [](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes <details> <summary>infection/infection (infection/infection)</summary> ### [`v0.29.0`](https://togithub.com/infection/infection/blob/HEAD/CHANGELOG.md#0290-2024-05-28) [Compare Source](https://togithub.com/infection/infection/compare/0.28.1...0.29.0) [Full Changelog](https://togithub.com/infection/infection/compare/0.28.1...0.29.0) **Added:** - Support custom mutators by [@​vss414](https://togithub.com/vss414) in [https://github.com/infection/infection/pull/1686](https://togithub.com/infection/infection/pull/1686) - Custom mutator generator by [@​maks-rafalko](https://togithub.com/maks-rafalko) in [https://github.com/infection/infection/pull/1969](https://togithub.com/infection/infection/pull/1969) Read about how to create custom mutators: https://infection.github.io/guide/custom-mutators.html **Changed:** - Move `Infection\Mutator\Mutator` to a separate package by [@​maks-rafalko](https://togithub.com/maks-rafalko) in [https://github.com/infection/infection/pull/1963](https://togithub.com/infection/infection/pull/1963) - Make `Mutator::getDefinition` return type non-nullable by [@​maks-rafalko](https://togithub.com/maks-rafalko) in [https://github.com/infection/infection/pull/1958](https://togithub.com/infection/infection/pull/1958) - Enable Rector's `AddCoversClassAttributeRector` rule by [@​maks-rafalko](https://togithub.com/maks-rafalko) in [https://github.com/infection/infection/pull/1962](https://togithub.com/infection/infection/pull/1962) - Mention Discord instead of Slack in issue github template by [@​staabm](https://togithub.com/staabm) in [https://github.com/infection/infection/pull/1951](https://togithub.com/infection/infection/pull/1951) - test: Force mutators to include remedies by [@​theofidry](https://togithub.com/theofidry) in [https://github.com/infection/infection/pull/1954](https://togithub.com/infection/infection/pull/1954) - Use the latest composer 2 to prevent issue with incompatibility for Box and composer 2.1 by [@​maks-rafalko](https://togithub.com/maks-rafalko) in [https://github.com/infection/infection/pull/1957](https://togithub.com/infection/infection/pull/1957) - Use the latest v1 test checker action by [@​maks-rafalko](https://togithub.com/maks-rafalko) in [https://github.com/infection/infection/pull/1960](https://togithub.com/infection/infection/pull/1960) - Upgrade Rector and fix new issues by [@​maks-rafalko](https://togithub.com/maks-rafalko) in [https://github.com/infection/infection/pull/1961](https://togithub.com/infection/infection/pull/1961) - Use new PHP-CS-Fixer with parallelization by [@​maks-rafalko](https://togithub.com/maks-rafalko) in [https://github.com/infection/infection/pull/1964](https://togithub.com/infection/infection/pull/1964) - Remove our own custom FQCN visitor as we already use php-parser's `NameResolver` visitor by [@​maks-rafalko](https://togithub.com/maks-rafalko) in [https://github.com/infection/infection/pull/1967](https://togithub.com/infection/infection/pull/1967) - Replace deprecated constant `NodeTraverser::DONT_TRAVERSE_CURRENT_AND_CHILDREN` with `NodeVisitor::DONT_TRAVERSE_CURRENT_AND_CHILDREN` by [@​maks-rafalko](https://togithub.com/maks-rafalko) in [https://github.com/infection/infection/pull/1968](https://togithub.com/infection/infection/pull/1968) - Remove our own `ParentConnectorVisitor` and use `nikic-phpparser`'s one by [@​maks-rafalko](https://togithub.com/maks-rafalko) in [https://github.com/infection/infection/pull/1970](https://togithub.com/infection/infection/pull/1970) </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/Lendable/json-serializer). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4zNzcuOCIsInVwZGF0ZWRJblZlciI6IjM3LjM3Ny44IiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbXX0=--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This is a follow up for #1686, docs: infection/site#262
Short description
This PR adds new CLI command to generate custom mutator in a target project, as well as a test for convenient development / testing of brand new mutators.
Details
A lot of things needs to be explained here. After hours of thinking / experimenting how it should be, I came up with this solution that helps developers to generate a "skeleton" of new mutator and a test to for convenient development.
Things to note:
This PR adds a couple of things:
bin/infection make:mutator
CLI command to generate skeleton for new custom mutator - mutator itself and test fileBaseMutatorTestCase.php
(and other related classes) tosrc
fromtests
, so that developers can test their mutators in "Infection runtime". By this, I mean that developers will not blindly create new mutator class, but they will mutate the code in tests and see which mutants (new versions of the source code) are produced. Exactly the same as we do it in out unit testsbin/infection make:mutator
This idea is taken from Rector's
custom-rule
command, see https://getrector.com/documentation/custom-rule (implementation).What it does is basically generates 2 files - mutator and test for it. See
__Name__.php
and__Name__Test.php
files in the diff to understand how it works.__Name__
is replaced with the real name of the new mutator during creation of the files.Moving
BaseMutatorTestCase.php
fromtests
tosrc
- why?This is needed to allow users to write the following tests:
infection/tests/phpunit/Mutator/Arithmetic/PlusTest.php
Lines 58 to 73 in 80a1579
But to achieve it, we need to do really a lot of things:
Without our base class provided for the end developers, it will be very difficult to write all of this logic themselves. So we basically say for them: "look here, we have Infection runtime which you can use to test your new custom mutator - if you want - you can use it."
In order to use "Infection runtime" in custom mutator's tests, developers will need to require
infection/infection
. You can ask: "wait, but we extractedinfection/mutator
exactly to not depend oninfection/infection
?". And this is still the case!The project that will implement a custom mutator still needs to depend on
infection/mutator
inrequire
section. But if they want to use ourcustom-mutator
CLI generator and our base test class, they can requireinfection/infection
to therequire-dev
section. From dependencies POV, they still depend only oninfection/mutator
andinfection/infection
is a dev dependency only for test. So no problem here.Actually, Rector does the same thing. They have their base test class in
src
and package it with the source code:I've already created documentation for writing Custom Mutators - infection/site#261 - and after this PR it will be greatly simplified from developer's point of view, improving DX. Docs PR supporting this change: infection/site#262
Example of usage:
Generated files: