pestphp / pest-plugin-mutate
Mutates your code to find untested cases
Fund package maintenance!
gehrisandro
Installs: 16 070
Dependents: 0
Suggesters: 0
Security: 0
Stars: 26
Watchers: 4
Forks: 1
Open Issues: 0
Requires
- php: ^8.1
- nikic/php-parser: ^4.19.1|^v5.0.2
- pestphp/pest-plugin: ^v2.1.1
- psr/simple-cache: ^3.0
Requires (Dev)
- pestphp/pest: ^v2.34.8
- pestphp/pest-dev-tools: ^2.16
- pestphp/pest-plugin-type-coverage: ^2.8.1
- rector/rector: 1.1.0 as 0.16.0
This package is auto-updated.
Last update: 2024-09-06 20:02:41 UTC
README
This repository contains the Pest Plugin Mutate.
This plugin is currently under development.
But you can still use it safely, as it does not affect your application, when not explicitly activated.
Roadmap
We are going to release new beta versions on a regular basis.
A stable version will be released at Laracon US by the end of August 2024.
To stay but to date, star the repository and follow it closely.
Another option is to follow Sandro Gehri on Twitter/X or LinkedIn, where I will post tips and tricks, and updates about the ongoing development.
If you have any question not covered in the docs or need help. Checkout the discussions section on GitHub.
Mutation Testing
Note: Before you can start using mutation testing, you need to have a successfully running test suite.
Source code: Pest Plugin Mutate
To start using Pest's Mutation plugin, you need to require the plugin via Composer.
composer require pestphp/pest-plugin-mutate --dev
Run mutation testing
Run from CLI
You can run the mutation testing from the CLI providing the --mutate
option.
vendor/bin/pest --mutate
When you are working with a larger codebase, checkout the performance section first, otherwise you will not have satisfying experience.
By default, it uses the default configuration (if available) or you can use a different configuration by providing its name.
vendor/bin/pest --mutate="arithmetic only"
You can set or overwrite all options available.
vendor/bin/pest --mutate --path=src
Additionally, you can make use of most of the options available in Pest.
For example this would only run mutation tests for code covered by tests in the "unit" group.
vendor/bin/pest --mutate --covered-only --group=unit
mutate()
Another powerful technique is to call the mutate()
function directly in your test file. This automatically start mutation testing ones you run vendor/bin/pest
. Additionally it limits the test run, to the tests in this file.
This function is intended to be used in your daily development workflow to establish a mutation testing practice right when you are implementing or modifying a feature.
By default, it inherits the default configuration. You can change this by providing an alternative configuration name.
In conjunction with the next release of Pest, it will be possible to append the
mutate()
function direct to an individual test case or a describe block.
mutate(); test('sum', function () { $result = sum(1, 2); expect($result)->toBe(3); })
Executing the ./vendor/bin/pest
command will now automatically run mutation testing. It is not necessary to provide the --mutate
option.
You can append options after calling mutate()
.
->mutate() ->path('src/functions.php') test('sum', function () { $result = sum(1, 2); expect($result)->toBe(3); });
Configuration
You can globally configure mutation testing in you Pest.php file.
mutate() ->paths('src');
For all the available options see Options section.
Alternative configurations
You can create multiple mutation testing configurations.
use Pest\Mutate\Mutators; mutate('arithmetic only') // 'default' if not provided ->paths('src') ->mutators(Mutators::SET_ARITHMETIC);
And you can inherit from another configuration.
WIP: Configuration inheritance is not implemented yet!
use Pest\Mutate\Mutators; mutate('arithmetic only') ->extends('default') ->mutators(Mutators::SET_ARITHMETIC);
Options
The following options are available.
path()
ignore()
class()
mutator()
except()
coveredOnly()
uncommittedOnly()
changedOnly()
stopOnEscaped()
stopOnNotCovered()
bail()
retry()
min()
ignoreMinScoreOnZeroMutations()
--id
--no-cache
--clear-cache
path()
CLI: --path
Limit the directories or files to mutate by providing one or more paths to a directory or file to test.
If no paths are provided, it defaults to the source directories configured in your phpunit.xml
file.
mutate() ->path('src');
ignore()
CLI: --ignore
Ignore one or more directory or file paths.
mutate() ->ignore('src/Contracts');
class()
CLI: --class
Limit the mutations to one or more classes by providing one or more class names.
mutate() ->class(MyClass::class, OtherClass::class);
mutator()
CLI: --mutator
Choose the mutators you want to use. Choose from various sets or provide individual mutators. If not set, Mutators::SET_DEFAULT
is used.
A list of all available mutators can be found in the Mutator Reference.
use Pest\Mutate\Mutators; mutate() ->mutator(Mutators::SET_ARITHMETIC); // or mutate() ->mutator(Mutators::ARITHMETIC_PLUS_TO_MINUS, Mutators::ARITHMETIC_MINUS_TO_PLUS);
On the CLI you can provide a comma separated list of mutator names.
vendor/bin/pest --mutate --mutator=ArithmeticPlusToMinus,ArithmeticMinusToPlus
except()
CLI: --except
Exclude specific mutators from being used. Especially useful if you want to use a set of mutators but want to exclude some of them.
use Pest\Mutate\Mutators; mutate() ->mutators(Mutators::SET_ARITHMETIC); ->except(Mutators::ARITHMETIC_PLUS_TO_MINUS);
coveredOnly()
CLI: --covered-only
Limit mutations to code that is covered by tests. This is especially helpful if you are running only a subset of your test suite. See Only run parts of your test suite.
mutate() ->coveredOnly();
uncommittedOnly()
CLI: --uncommitted-only
Limit mutations to code that has uncommitted changes.
mutate() ->uncommittedOnly();
changedOnly()
CLI: --changed-only
Limit mutations to code that has changed relative to a common ancestor of the given branch (defaults to main
).
mutate() ->changedOnly(); // or ->changedOnly('add-xyz');
stopOnEscaped()
CLI: --stop-on-escaped
Stop execution upon first escaped mutant.
mutate() ->stopOnEscaped();
stopOnNotCovered()
CLI: --stop-on-not-covered
Stop execution upon first not covered mutant.
mutate() ->stopOnNotCovered();
bail()
CLI: --bail
Stop execution upon first not covered or escaped mutant.
mutate() ->bail();
retry()
CLI: --retry
If a mutation previously escaped, you typically want to run them first. In such cases, you can use the --retry
option.
The --retry
flag reorders your mutations by prioritizing the previously escaped mutations. If there were no past escaped mutations, the suite runs as usual.
Additionally, it will stop execution upon first escaped mutant.
mutate() ->retry();
min()
CLI: --min
Enforce a minimum mutation score threshold. For more information see Minimum Score Threshold Enforcement.
mutate() ->min(100);
You can pass an optional second parameter to ignore the minimum score threshold if zero mutations are generated. In this case Pest will exit with code 0.
mutate() ->min(100, failOnZeroMutations: false);
ignoreMinScoreOnZeroMutations()
CLI: --ignore-min-score-on-zero-mutations
Ignores the minimum score threshold if zero mutations are generated. In this case Pest will exit with code 0.
mutate() ->ignoreMinScoreOnZeroMutations();
--id
Run only the mutation with the given ID. You can find the ID of a mutation in the console output of a previous run.
vendor/bin/pest --mutate --id=fa6913f68aa87747
--no-cache
Disables the cache (This option is only available on the cli).
vendor/bin/pest --mutate --no-cache
--clear-cache
Clears the cache (This option is only available on the cli).
vendor/bin/pest --mutate --clear-cache
Performance
Mutation testing is potentially very time-consuming and resource intensive because of the sheer amount of possible mutations and tests to run them against.
Therefore, Pest Mutation Testing is optimized to limit the amount of mutations and tests to run against as much as possible. To achieve this, it uses the following strategies:
- Limit the amount of possible mutations by having a carefully chosen set of mutators
- Run only tests that covers the mutated code
- It tries to reuse cached mutations
- Run mutations in a reasonable order
- Provide options to stop on first escaped or not covered mutation
But there is much more you can do to improve performance. Especially if you have a larger code base and/or you are using mutations testing while developing locally.
Use a code coverage driver
If you have a code coverage driver available, Pest will use it to only run tests that cover the mutated code.
Supports XDebug 3.0+ or PCOV.
Reduce the number of files to mutate
Reduce the number of mutations by only mutating a subset of your code base.
vendor/bin/pest --mutate --path=src/path/file.php
Reduce the number of classes to mutate
Reduce the number of mutations by only mutating a subset of your classes.
vendor/bin/pest --mutate --class="App\\MyClass,App\\OtherClass"
Only run parts of your test suite
Reduce the number of mutations and tests to execute by only running a subset of your test suite.
vendor/bin/pest --mutate --filter=SumTest
For more filter options see Filtering.
Only create mutations for covered files / lines
Reduce the number of mutations by only mutating code that is covered by tests. This is especially helpful if you are running only a subset of your test suite. See Only run parts of your test suite.
vendor/bin/pest --mutate --covered-only
Attention: Code not covered by tests will not be mutated. Ensure your test suite covers all code you want to mutate.
Run tests in parallel
Run tests against multiple mutations in parallel. This can significantly reduce the time it takes to run mutation tests.
Against a single mutation the tests are not run in parallel, regardless of the parallel option.
vendor/bin/pest --mutate --parallel
Reduce the number of mutators
Reduce the number of mutations by choosing a smaller set of mutators.
vendor/bin/pest --mutate --mutator=ArithmeticPlusToMinus
Profiling
You can profile the performance of the mutations by using the --profile
option.
It outputs a list of the ten slowest mutations.
vendor/bin/pest --mutate --profile
Ignoring Mutations
Ignore for a single line
Sometimes, you may want to prevent a line from being mutated. To do so, you may use the @pest-mutate-ignore
annotation:
if($age >= 18) // @pest-mutate-ignore // ... ];
If you want to ignore only a specific mutator, you can add a comma separated list of mutator names:
if($age >= 18) // @pest-mutate-ignore: GreaterOrEqualToGreater // ... ];
Ignore for multiple lines
To ignore mutations on large parts of the code you can add the annotation to a class, method or statement to ignore all mutations within the elements scope.
To ignore only specific mutators, you can add a comma separated list of mutator names: @pest-mutate-ignore: GreaterOrEqualToGreater,IfNegated
Class level
/** * @pest-mutate-ignore */ class Test { // ... }
Method or function level
/** * @pest-mutate-ignore */ public function test() { // ... }
Statement level
/** @pest-mutate-ignore */ for($i = 0; $i < 10; $i++) { // ... }
Minimum Score Threshold Enforcement
Just like code coverage, mutation coverage can also be enforced. You can use the --mutate
and --min
options to define the minimum threshold value for the mutation score. If the specified threshold is not met, Pest will report a failure.
./vendor/bin/pest --mutate --min=100
If zero mutations are generated, the score is considered to be 0 and Pest will report a failure. You can use the --ignore-min-score-on-zero-mutations
option to ignore the minimum score threshold if zero mutations are generated. In this case Pest will exit with code 0.
./vendor/bin/pest --mutate --min=100 --ignore-min-score-on-zero-mutations
Custom Mutators
WIP: Custom mutators are not implemented yet!
You may want to create your own custom mutators. You can do so by creating a class that implements the Mutator
interface.
This example will remove use
statements.
namespace App\Mutators; use Pest\Mutate\Contracts\Mutator; use PhpParser\Node; use PhpParser\NodeTraverser; class RemoveUseStatement implements Mutator { public static function can(Node $node): bool { return $node instanceof Node\Stmt\Use_; } public static function mutate(Node $node): int { return NodeTraverser::REMOVE_NODE; } }
Afterward you can use your mutator.
use App\Mutators\RemoveUseStatement; mutate() ->mutators(RemoveUseStatement::class);
In the CLI you must provide the full class name.
vendor/bin/pest --mutate --mutators="App\\Mutators\\RemoveUseStatement"
Mutator Reference
A comprehensive list of all mutators available.
Sets
The mutators are grouped in sets.
Default
A set of mutators that are enabled by default. Which keeps a good balance between performance and mutation coverage.
This set consists of various mutators from different sets. Mutators included are indicated with a asterisk (*).
ArithmeticSet
- BitwiseAndToBitwiseOr (*)
- BitwiseOrToBitwiseAnd (*)
- BitwiseXorToBitwiseAnd (*)
- PlusToMinus (*)
- MinusToPlus (*)
- DivisionToMultiplication (*)
- MultiplicationToDivision (*)
- ModulusToMultiplication (*)
- PowerToMultiplication (*)
- ShiftLeftToShiftRight (*)
- ShiftRightToShiftLeft (*)
- PostDecrementToPostIncrement (*)
- PostIncrementToPostDecrement (*)
- PreDecrementToPreIncrement (*)
- PreIncrementToPreDecrement (*)
ArraySet
- ArrayKeyFirstToArrayKeyLast (*)
- ArrayKeyLastToArrayKeyFirst (*)
- ArrayPopToArrayShift (*)
- ArrayShiftToArrayPop (*)
- UnwrapArrayChangeKeyCase (*)
- UnwrapArrayChunk (*)
- UnwrapArrayColumn (*)
- UnwrapArrayCombine (*)
- UnwrapArrayCountValues (*)
- UnwrapArrayDiffAssoc (*)
- UnwrapArrayDiffKey (*)
- UnwrapArrayDiffUassoc (*)
- UnwrapArrayDiffUkey (*)
- UnwrapArrayDiff (*)
- UnwrapArrayFilter (*)
- UnwrapArrayFlip (*)
- UnwrapArrayIntersectAssoc (*)
- UnwrapArrayIntersectKey (*)
- UnwrapArrayIntersectUassoc (*)
- UnwrapArrayIntersectUkey (*)
- UnwrapArrayIntersect (*)
- UnwrapArrayKeys (*)
- UnwrapArrayMap (*)
- UnwrapArrayMergeRecursive (*)
- UnwrapArrayMerge (*)
- UnwrapArrayPad (*)
- UnwrapArrayReduce (*)
- UnwrapArrayReplaceRecursive (*)
- UnwrapArrayReplace (*)
- UnwrapArrayReverse (*)
- UnwrapArraySlice (*)
- UnwrapArraySplice (*)
- UnwrapArrayUdiffAssoc (*)
- UnwrapArrayUdiffUassoc (*)
- UnwrapArrayUdiff (*)
- UnwrapArrayUintersectAssoc (*)
- UnwrapArrayUintersectUassoc (*)
- UnwrapArrayUintersect (*)
- UnwrapArrayUnique (*)
- UnwrapArrayValues (*)
AssignmentSet
- BitwiseAndToBitwiseOr (*)
- BitwiseOrToBitwiseAnd (*)
- BitwiseXorToBitwiseAnd (*)
- CoalesceEqualToEqual (*)
- ConcatEqualToEqual (*)
- DivideEqualToMultiplyEqual (*)
- MinusEqualToPlusEqual (*)
- ModulusEqualToMultiplyEqual (*)
- MultiplyEqualToDivideEqual (*)
- PlusEqualToMinusEqual (*)
- PowerEqualToMultiplyEqual (*)
- ShiftLeftToShiftRight (*)
- ShiftRightToShiftLeft (*)
CastingSet
- RemoveArrayCast (*)
- RemoveBooleanCast (*)
- RemoveDoubleCast (*)
- RemoveIntegerCast (*)
- RemoveObjectCast (*)
- RemoveStringCast (*)
ControlStructuresSet
- IfNegated (*)
- ElseIfNegated (*)
- TernaryNegated (*)
- ForAlwaysFalse (*)
- ForeachEmptyIterable (*)
- DoWhileAlwaysFalse (*)
- WhileAlwaysFalse (*)
- BreakToContinue (*)
- ContinueToBreak (*)
EqualitySet
- EqualToNotEqual (*)
- NotEqualToEqual (*)
- IdenticalToNotIdentical (*)
- NotIdenticalToIdentical (*)
- GreaterToGreaterOrEqual (*)
- GreaterToSmallerOrEqual (*)
- GreaterOrEqualToGreater (*)
- GreaterOrEqualToSmaller (*)
- SmallerToGreaterOrEqual (*)
- SmallerToSmallerOrEqual (*)
- SmallerOrEqualToGreater (*)
- SmallerOrEqualToSmaller (*)
- EqualToIdentical (*)
- NotEqualToNotIdentical (*)
- SpaceshipSwitchSides (*)
- IdenticalToEqual
- NotIdenticalToNotEqual
LogicalSet
- BooleanAndToBooleanOr (*)
- BooleanOrToBooleanAnd (*)
- CoalesceRemoveLeft (*)
- LogicalAndToLogicalOr (*)
- LogicalOrToLogicalAnd (*)
- LogicalXorToLogicalAnd (*)
- FalseToTrue (*)
- TrueToFalse (*)
- InstanceOfToTrue (*)
- InstanceOfToFalse (*)
- RemoveNot (*)
MathSet
- MinToMax (*)
- MaxToMin (*)
- RoundToFloor (*)
- RoundToCeil (*)
- FloorToRound (*)
- FloorToCiel (*)
- CeilToFloor (*)
- CeilToRound (*)
NumberSet
- DecrementFloat (*)
- IncrementFloat (*)
- DecrementInteger (*)
- IncrementInteger (*)
RemovalSet
- RemoveArrayItem (*)
- RemoveEarlyReturn (*)
- RemoveFunctionCall (*)
- RemoveMethodCall (*)
- RemoveNullSafeOperator (*)
ReturnSet
StringSet
- ConcatRemoveLeft (*)
- ConcatRemoveRight (*)
- ConcatSwitchSides (*)
- EmptyStringToNotEmpty (*)
- NotEmptyStringToEmpty (*)
- StrStartsWithToStrEndsWith (*)
- StrEndsWithToStrStartsWith (*)
- UnwrapChop (*)
- UnwrapChunkSplit (*)
- UnwrapHtmlentities (*)
- UnwrapHtmlEntityDecode (*)
- UnwrapHtmlspecialchars (*)
- UnwrapHtmlspecialcharsDecode (*)
- UnwrapLcfirst (*)
- UnwrapLtrim (*)
- UnwrapMd5 (*)
- UnwrapNl2br (*)
- UnwrapRtrim (*)
- UnwrapStripTags (*)
- UnwrapStrIreplace (*)
- UnwrapStrPad (*)
- UnwrapStrRepeat (*)
- UnwrapStrReplace (*)
- UnwrapStrrev (*)
- UnwrapStrShuffle (*)
- UnwrapStrtolower (*)
- UnwrapStrtoupper (*)
- UnwrapSubstr (*)
- UnwrapTrim (*)
- UnwrapUcfirst (*)
- UnwrapUcwords (*)
- UnwrapWordwrap (*)
VisibilitySet
- ConstantPublicToProtected
- ConstantProtectedToPrivate
- FunctionPublicToProtected (*)
- FunctionProtectedToPrivate
- PropertyPublicToProtected
- PropertyProtectedToPrivate
LaravelSet
Mutators
An alphabetical list of all mutators.
AlwaysReturnEmptyArray (*)
Set: Return
Mutates a return statement to an empty array
return [1]; // [tl! remove] return []; // [tl! add]
AlwaysReturnNull (*)
Set: Return
Mutates a return statement to null if it is not null
return $a; // [tl! remove] return null; // [tl! add]
ArrayKeyFirstToArrayKeyLast (*)
Set: Array
Replaces array_key_first
with array_key_last
.
$a = array_key_first([1, 2, 3]); // [tl! remove] $a = array_key_last([1, 2, 3]); // [tl! add]
ArrayKeyLastToArrayKeyFirst (*)
Set: Array
Replaces array_key_last
with array_key_first
.
$a = array_key_last([1, 2, 3]); // [tl! remove] $a = array_key_first([1, 2, 3]); // [tl! add]
ArrayPopToArrayShift (*)
Set: Array
Replaces array_pop
with array_shift
.
$a = array_pop([1, 2, 3]); // [tl! remove] $a = array_shift([1, 2, 3]); // [tl! add]
ArrayShiftToArrayPop (*)
Set: Array
Replaces array_shift
with array_pop
.
$a = array_shift([1, 2, 3]); // [tl! remove] $a = array_pop([1, 2, 3]); // [tl! add]
BitwiseAndToBitwiseOr (*)
Set: Arithmetic
Replaces &
with |
.
$c = $a & $b; // [tl! remove] $c = $a | $b; // [tl! add]
BitwiseAndToBitwiseOr (*)
Set: Assignment
Replaces &=
with |=
.
$a &= $b; // [tl! remove] $a |= $b; // [tl! add]
BitwiseOrToBitwiseAnd (*)
Set: Arithmetic
Replaces |
with &
.
$c = $a | $b; // [tl! remove] $c = $a & $b; // [tl! add]
BitwiseOrToBitwiseAnd (*)
Set: Assignment
Replaces |=
with &=
.
$a |= $b; // [tl! remove] $a &= $b; // [tl! add]
BitwiseXorToBitwiseAnd (*)
Set: Arithmetic
Replaces ^
with &
.
$c = $a ^ $b; // [tl! remove] $c = $a & $b; // [tl! add]
BitwiseXorToBitwiseAnd (*)
Set: Assignment
Replaces ^=
with &=
.
$a ^= $b; // [tl! remove] $a &= $b; // [tl! add]
BooleanAndToBooleanOr (*)
Set: Logical
Converts the boolean and operator to the boolean or operator.
if ($a && $b) { // [tl! remove] if ($a || $b) { // [tl! add] // ... }
BooleanOrToBooleanAnd (*)
Set: Logical
Converts the boolean or operator to the boolean and operator.
if ($a || $b) { // [tl! remove] if ($a && $b) { // [tl! add] // ... }
BreakToContinue (*)
Set: ControlStructures
Replaces break
with continue
.
foreach ($items as $item) { if ($item === 'foo') { break; // [tl! remove] continue; // [tl! add] } }
CeilToFloor (*)
Set: Math
Replaces ceil
function with floor
function.
$a = ceil(1.2); // [tl! remove] $a = floor(1.2); // [tl! add]
CeilToRound (*)
Set: Math
Replaces ceil
function with round
function.
$a = ceil(1.2); // [tl! remove] $a = round(1.2); // [tl! add]
CoalesceEqualToEqual (*)
Set: Assignment
Replaces ??=
with =
.
$a ??= $b; // [tl! remove] $a = $b; // [tl! add]
CoalesceRemoveLeft (*)
Set: Logical
Removes the left side of the coalesce operator.
return $a ?? $b; // [tl! remove] return $b; // [tl! add]
ConcatEqualToEqual (*)
Set: Assignment
Replaces .=
with =
.
$a .= $b; // [tl! remove] $a = $b; // [tl! add]
ConcatRemoveLeft (*)
Set: String
Removes the left part of a concat expression.
$a = 'Hello' . ' World'; // [tl! remove] $a = ' World'; // [tl! add]
ConcatRemoveRight (*)
Set: String
Removes the right part of a concat expression.
$a = 'Hello' . ' World'; // [tl! remove] $a = 'Hello'; // [tl! add]
ConcatSwitchSides (*)
Set: String
Switches the sides of a concat expression.
$a = 'Hello' . ' World'; // [tl! remove] $a = ' World' . 'Hello'; // [tl! add]
ConstantProtectedToPrivate
Set: Visibility
Mutates a protected constant to a private constant
protected const FOO = true; // [tl! remove] private const FOO = true; // [tl! add]
ConstantPublicToProtected
Set: Visibility
Mutates a public constant to a protected constant
public const FOO = true; // [tl! remove] protected const FOO = true; // [tl! add]
ContinueToBreak (*)
Set: ControlStructures
Replaces continue
with break
.
foreach ($items as $item) { if ($item === 'foo') { continue; // [tl! remove] break; // [tl! add] } }
DecrementFloat (*)
Set: Number
Decrements a float number by 1.
$a = 1.2; // [tl! remove] $a = 0.2; // [tl! add]
DecrementInteger (*)
Set: Number
Decrements an integer number by 1.
$a = 1; // [tl! remove] $a = 0; // [tl! add]
DivideEqualToMultiplyEqual (*)
Set: Assignment
Replaces /=
with *=
.
$a /= $b; // [tl! remove] $a *= $b; // [tl! add]
DivisionToMultiplication (*)
Set: Arithmetic
Replaces /
with *
.
$c = $a / $b; // [tl! remove] $c = $a * $b; // [tl! add]
DoWhileAlwaysFalse (*)
Set: ControlStructures
Makes the condition in a do-while loop always false.
do { // ... } while ($a < 100); // [tl! remove] } while (false); // [tl! add]
ElseIfNegated (*)
Set: ControlStructures
Negates the condition in an elseif statement.
if ($a === 1) { // ... } elseif ($a === 2) { // [tl! remove] } elseif (!($a === 2)) { // [tl! add] // ... }
EmptyStringToNotEmpty (*)
Set: String
Changes an empty string to a non-empty string.
$a = ''; // [tl! remove] $a = 'PEST Mutator was here!'; // [tl! add]
EqualToIdentical (*)
Set: Equality
Converts the equality operator to the identical operator.
if ($a == $b) { // [tl! remove] if ($a === $b) { // [tl! add] // ... }
EqualToNotEqual (*)
Set: Equality
Converts the equality operator to the not equal operator.
if ($a == $b) { // [tl! remove] if ($a != $b) { // [tl! add] // ... }
FalseToTrue (*)
Set: Logical
Converts false
to true
.
if (false) { // [tl! remove] if (true) { // [tl! add] // ... }
FloorToCiel (*)
Set: Math
Replaces floor
function with ceil
function.
$a = floor(1.2); // [tl! remove] $a = ceil(1.2); // [tl! add]
FloorToRound (*)
Set: Math
Replaces floor
function with round
function.
$a = floor(1.2); // [tl! remove] $a = round(1.2); // [tl! add]
ForAlwaysFalse (*)
Set: ControlStructures
Makes the condition in a for loop always false.
for ($i = 0; $i < 10; $i++) { // [tl! remove] for ($i = 0; false; $i++) { // [tl! add] // ... }
ForeachEmptyIterable (*)
Set: ControlStructures
Replaces the iterable in a foreach loop with an empty array.
foreach ($items as $item) { // [tl! remove] foreach ([] as $item) { // [tl! add] // ... }
FunctionProtectedToPrivate
Set: Visibility
Mutates a protected function to a private function
protected function foo(): bool // [tl! remove] private function foo(): bool // [tl! add] { return true; }
FunctionPublicToProtected (*)
Set: Visibility
Mutates a public function to a protected function
public function foo(): bool // [tl! remove] protected function foo(): bool // [tl! add] { return true; }
GreaterOrEqualToGreater (*)
Set: Equality
Converts the greater or equal operator to the greater operator.
if ($a >= $b) { // [tl! remove] if ($a > $b) { // [tl! add] // ... }
GreaterOrEqualToSmaller (*)
Set: Equality
Converts the greater or equal operator to the smaller operator.
if ($a >= $b) { // [tl! remove] if ($a < $b) { // [tl! add] // ... }
GreaterToGreaterOrEqual (*)
Set: Equality
Converts the greater operator to the greater or equal operator.
if ($a > $b) { // [tl! remove] if ($a >= $b) { // [tl! add] // ... }
GreaterToSmallerOrEqual (*)
Set: Equality
Converts the greater operator to the smaller or equal operator.
if ($a > $b) { // [tl! remove] if ($a <= $b) { // [tl! add] // ... }
IdenticalToEqual
Set: Equality
Converts the identical operator to the equality operator.
if ($a === $b) { // [tl! remove] if ($a == $b) { // [tl! add] // ... }
IdenticalToNotIdentical (*)
Set: Equality
Converts the identical operator to the not identical operator.
if ($a === $b) { // [tl! remove] if ($a !== $b) { // [tl! add] // ... }
IfNegated (*)
Set: ControlStructures
Negates the condition in an if statement.
if ($a === 1) { // [tl! remove] if (!($a === 1)) { // [tl! add] // ... }
IncrementFloat (*)
Set: Number
Increments a float number by 1.
$a = 1.2; // [tl! remove] $a = 2.2; // [tl! add]
IncrementInteger (*)
Set: Number
Increments an integer number by 1.
$a = 1; // [tl! remove] $a = 2; // [tl! add]
InstanceOfToFalse (*)
Set: Logical
Converts instanceof
to false
.
if ($a instanceof $b) { // [tl! remove] if (false) { // [tl! add] // ... }
InstanceOfToTrue (*)
Set: Logical
Converts instanceof
to true
.
if ($a instanceof $b) { // [tl! remove] if (true) { // [tl! add] // ... }
LaravelRemoveStringableUpper
Set: Laravel
Removes the upper method call from a stringable object.
Str::of('hello')->upper(); // [tl! remove] Str::of('hello'); // [tl! add]
LaravelUnwrapStrUpper
Set: Laravel
Unwraps the string upper method call.
$a = Illuminate\Support\Str::upper('foo'); // [tl! remove] $a = 'foo'; // [tl! add]
LogicalAndToLogicalOr (*)
Set: Logical
Converts the logical and operator to the logical or operator.
if ($a && $b) { // [tl! remove] if ($a || $b) { // [tl! add] // ... }
LogicalOrToLogicalAnd (*)
Set: Logical
Converts the logical or operator to the logical and operator.
if ($a || $b) { // [tl! remove] if ($a && $b) { // [tl! add] // ... }
LogicalXorToLogicalAnd (*)
Set: Logical
Converts the logical xor operator to the logical and operator.
if ($a xor $b) { // [tl! remove] if ($a && $b) { // [tl! add] // ... }
MaxToMin (*)
Set: Math
Replaces max
function with min
function.
$a = max(1, 2); // [tl! remove] $a = min(1, 2); // [tl! add]
MinToMax (*)
Set: Math
Replaces min
function with max
function.
$a = min(1, 2); // [tl! remove] $a = max(1, 2); // [tl! add]
MinusEqualToPlusEqual (*)
Set: Assignment
Replaces -=
with +=
.
$a -= $b; // [tl! remove] $a += $b; // [tl! add]
MinusToPlus (*)
Set: Arithmetic
Replaces -
with +
.
$c = $a - $b; // [tl! remove] $c = $a + $b; // [tl! add]
ModulusEqualToMultiplyEqual (*)
Set: Assignment
Replaces %=
with *=
.
$a %= $b; // [tl! remove] $a *= $b; // [tl! add]
ModulusToMultiplication (*)
Set: Arithmetic
Replaces %
with *
.
$c = $a % $b; // [tl! remove] $c = $a * $b; // [tl! add]
MultiplicationToDivision (*)
Set: Arithmetic
Replaces *
with /
.
$c = $a * $b; // [tl! remove] $c = $a / $b; // [tl! add]
MultiplyEqualToDivideEqual (*)
Set: Assignment
Replaces *=
with /=
.
$a *= $b; // [tl! remove] $a /= $b; // [tl! add]
NotEmptyStringToEmpty (*)
Set: String
Changes a non-empty string to an empty string.
$a = 'Hello World'; // [tl! remove] $a = ''; // [tl! add]
NotEqualToEqual (*)
Set: Equality
Converts the not equal operator to the equal operator.
if ($a != $b) { // [tl! remove] if ($a == $b) { // [tl! add] // ... }
NotEqualToNotIdentical (*)
Set: Equality
Converts the not equal operator to the not identical operator.
if ($a != $b) { // [tl! remove] if ($a !== $b) { // [tl! add] // ... }
NotIdenticalToIdentical (*)
Set: Equality
Converts the not identical operator to the identical operator.
if ($a !== $b) { // [tl! remove] if ($a === $b) { // [tl! add] // ... }
NotIdenticalToNotEqual
Set: Equality
Converts the not identical operator to the not equal operator.
if ($a !== $b) { // [tl! remove] if ($a != $b) { // [tl! add] // ... }
PlusEqualToMinusEqual (*)
Set: Assignment
Replaces +=
with -=
.
$a += $b; // [tl! remove] $a -= $b; // [tl! add]
PlusToMinus (*)
Set: Arithmetic
Replaces +
with -
.
$c = $a + $b; // [tl! remove] $c = $a - $b; // [tl! add]
PostDecrementToPostIncrement (*)
Set: Arithmetic
Replaces --
with ++
.
$b = $a--; // [tl! remove] $b = $a++; // [tl! add]
PostIncrementToPostDecrement (*)
Set: Arithmetic
Replaces ++
with --
.
$b = $a++; // [tl! remove] $b = $a--; // [tl! add]
PowerEqualToMultiplyEqual (*)
Set: Assignment
Replaces **=
with *=
.
$a **= $b; // [tl! remove] $a *= $b; // [tl! add]
PowerToMultiplication (*)
Set: Arithmetic
Replaces **
with *
.
$c = $a ** $b; // [tl! remove] $c = $a * $b; // [tl! add]
PreDecrementToPreIncrement (*)
Set: Arithmetic
Replaces --
with ++
.
$b = --$a; // [tl! remove] $b = ++$a; // [tl! add]
PreIncrementToPreDecrement (*)
Set: Arithmetic
Replaces ++
with --
.
$b = ++$a; // [tl! remove] $b = --$a; // [tl! add]
PropertyProtectedToPrivate
Set: Visibility
Mutates a protected property to a private property
protected bool $foo = true; // [tl! remove] private bool $foo = true; // [tl! add]
PropertyPublicToProtected
Set: Visibility
Mutates a public property to a protected property
public bool $foo = true; // [tl! remove] protected bool $foo = true; // [tl! add]
RemoveArrayCast (*)
Set: Casting
Removes array cast.
$a = (array) $b; // [tl! remove] $a = $b; // [tl! add]
RemoveArrayItem (*)
Set: Removal
Removes an item from an array
return [ 'foo' => 1, // [tl! remove] 'bar' => 2, ];
RemoveBooleanCast (*)
Set: Casting
Removes boolean cast.
$a = (bool) $b; // [tl! remove] $a = $b; // [tl! add]
RemoveDoubleCast (*)
Set: Casting
Removes double cast.
$a = (double) $b; // [tl! remove] $a = $b; // [tl! add]
RemoveEarlyReturn (*)
Set: Removal
Removes an early return statement
if ($a > $b) { return true // [tl! remove] } return false;
RemoveFunctionCall (*)
Set: Removal
Removes a function call
foo(); // [tl! remove]
RemoveIntegerCast (*)
Set: Casting
Removes integer cast.
$a = (int) $b; // [tl! remove] $a = $b; // [tl! add]
RemoveMethodCall (*)
Set: Removal
Removes a method call
$this->foo(); // [tl! remove]
RemoveNot (*)
Set: Logical
Removes the not operator.
if (!$a) { // [tl! remove] if ($a) { // [tl! add] // ... }
RemoveNullSafeOperator (*)
Set: Removal
Converts nullsafe method and property calls to regular calls.
$a?->b(); // [tl! remove] $a->b(); // [tl! add]
RemoveObjectCast (*)
Set: Casting
Removes object cast.
$a = (object) $b; // [tl! remove] $a = $b; // [tl! add]
RemoveStringCast (*)
Set: Casting
Removes string cast.
$a = (string) $b; // [tl! remove] $a = $b; // [tl! add]
RoundToCeil (*)
Set: Math
Replaces round
function with ceil
function.
$a = round(1.2); // [tl! remove] $a = ceil(1.2); // [tl! add]
RoundToFloor (*)
Set: Math
Replaces round
function with floor
function.
$a = round(1.2); // [tl! remove] $a = floor(1.2); // [tl! add]
ShiftLeftToShiftRight (*)
Set: Arithmetic
Replaces <<
with >>
.
$b = $a << 1; // [tl! remove] $b = $a >> 1; // [tl! add]
ShiftLeftToShiftRight (*)
Set: Assignment
Replaces <<=
with >>=
.
$a <<= $b; // [tl! remove] $a >>= $b; // [tl! add]
ShiftRightToShiftLeft (*)
Set: Arithmetic
Replaces >>
with <<
.
$b = $a >> 1; // [tl! remove] $b = $a << 1; // [tl! add]
ShiftRightToShiftLeft (*)
Set: Assignment
Replaces >>=
with <<=
.
$a >>= $b; // [tl! remove] $a <<= $b; // [tl! add]
SmallerOrEqualToGreater (*)
Set: Equality
Converts the smaller or equal operator to the greater operator.
if ($a <= $b) { // [tl! remove] if ($a > $b) { // [tl! add] // ... }
SmallerOrEqualToSmaller (*)
Set: Equality
Converts the smaller or equal operator to the smaller operator.
if ($a <= $b) { // [tl! remove] if ($a < $b) { // [tl! add] // ... }
SmallerToGreaterOrEqual (*)
Set: Equality
Converts the smaller operator to the greater or equal operator.
if ($a < $b) { // [tl! remove] if ($a >= $b) { // [tl! add] // ... }
SmallerToSmallerOrEqual (*)
Set: Equality
Converts the smaller operator to the smaller or equal operator.
if ($a < $b) { // [tl! remove] if ($a <= $b) { // [tl! add] // ... }
SpaceshipSwitchSides (*)
Set: Equality
Switches the sides of the spaceship operator.
return $a <=> $b; // [tl! remove] return $b <=> $a; // [tl! add]
StrEndsWithToStrStartsWith (*)
Set: String
Replaces str_ends_with
with str_starts_with
.
$a = str_ends_with('Hello World', 'World'); // [tl! remove] $a = str_starts_with('Hello World', 'World'); // [tl! add]
StrStartsWithToStrEndsWith (*)
Set: String
Replaces str_starts_with
with str_ends_with
.
$a = str_starts_with('Hello World', 'World'); // [tl! remove] $a = str_ends_with('Hello World', 'World'); // [tl! add]
TernaryNegated (*)
Set: ControlStructures
Negates the condition in a ternary statement.
$a = $b ? 1 : 2; // [tl! remove] $a = !$b ? 1 : 2; // [tl! add]
TrueToFalse (*)
Set: Logical
Converts true
to false
.
if (true) { // [tl! remove] if (false) { // [tl! add] // ... }
UnwrapArrayChangeKeyCase (*)
Set: Array
Unwraps array_change_key_case
calls.
$a = array_change_key_case(['foo' => 'bar'], CASE_UPPER); // [tl! remove] $a = ['foo' => 'bar']; // [tl! add]
UnwrapArrayChunk (*)
Set: Array
Unwraps array_chunk
calls.
$a = array_chunk([1, 2, 3], 2); // [tl! remove] $a = [1, 2, 3]; // [tl! add]
UnwrapArrayColumn (*)
Set: Array
Unwraps array_column
calls.
$a = array_column([['id' => 1], ['id' => 2]], 'id'); // [tl! remove] $a = [['id' => 1], ['id' => 2]]; // [tl! add]
UnwrapArrayCombine (*)
Set: Array
Unwraps array_combine
calls.
$a = array_combine([1, 2, 3], [3, 4]); // [tl! remove] $a = [1, 2, 3] // [tl! add]
UnwrapArrayCountValues (*)
Set: Array
Unwraps array_count_values
calls.
$a = array_count_values([1, 2, 3]); // [tl! remove] $a = [1, 2, 3]; // [tl! add]
UnwrapArrayDiff (*)
Set: Array
Unwraps array_diff
calls.
$a = array_diff([1, 2, 3], [1, 2]); // [tl! remove] $a = [1, 2, 3]; // [tl! add]
UnwrapArrayDiffAssoc (*)
Set: Array
Unwraps array_diff_assoc
calls.
$a = array_diff_assoc(['foo' => 1, 'bar' => 2], ['foo' => 1]) // [tl! remove] $a = ['foo' => 1, 'bar' => 2]; // [tl! add]
UnwrapArrayDiffKey (*)
Set: Array
Unwraps array_diff_key
calls.
$a = array_diff_key(['foo' => 1, 'bar' => 2], ['foo' => 1]); // [tl! remove] $a = ['foo' => 1, 'bar' => 2]; // [tl! add]
UnwrapArrayDiffUassoc (*)
Set: Array
Unwraps array_diff_uassoc
calls.
$a = array_diff_uassoc([1, 2, 3], [1, 2], 'strcmp'); // [tl! remove] $a = [1, 2, 3]; // [tl! add]
UnwrapArrayDiffUkey (*)
Set: Array
Unwraps array_diff_ukey
calls.
$a = array_diff_ukey(['foo' => 1, 'bar' => 2], ['foo' => 1], 'strcmp'); // [tl! remove] $a = ['foo' => 1, 'bar' => 2]; // [tl! add]
UnwrapArrayFilter (*)
Set: Array
Unwraps array_filter
calls.
$a = array_filter([1, 2, 3], fn($value) => $value > 2); // [tl! remove] $a = [1, 2, 3]; // [tl! add]
UnwrapArrayFlip (*)
Set: Array
Unwraps array_flip
calls.
$a = array_flip(['foo' => 1, 'bar' => 2]); // [tl! remove] $a = ['foo' => 1, 'bar' => 2]; // [tl! add]
UnwrapArrayIntersect (*)
Set: Array
Unwraps array_intersect
calls.
$a = array_intersect([1, 2, 3], [1, 2]); // [tl! remove] $a = [1, 2, 3]; // [tl! add]
UnwrapArrayIntersectAssoc (*)
Set: Array
Unwraps array_intersect_assoc
calls.
$a = array_intersect_assoc(['foo' => 1, 'bar' => 2], ['foo' => 1]); // [tl! remove] $a = ['foo' => 1, 'bar' => 2]; // [tl! add]
UnwrapArrayIntersectKey (*)
Set: Array
Unwraps array_intersect_key
calls.
$a = array_intersect_key(['foo' => 1, 'bar' => 2], ['foo' => 1]); // [tl! remove] $a = ['foo' => 1, 'bar' => 2]; // [tl! add]
UnwrapArrayIntersectUassoc (*)
Set: Array
Unwraps array_intersect_uassoc
calls.
$a = array_intersect_uassoc([1, 2, 3], [1, 2], 'strcmp'); // [tl! remove] $a = [1, 2, 3]; // [tl! add]
UnwrapArrayIntersectUkey (*)
Set: Array
Unwraps array_intersect_ukey
calls.
$a = array_intersect_ukey(['foo' => 1, 'bar' => 2], ['foo' => 1], 'strcmp'); // [tl! remove] $a = ['foo' => 1, 'bar' => 2]; // [tl! add]
UnwrapArrayKeys (*)
Set: Array
Unwraps array_keys
calls.
$a = array_keys(['foo' => 1, 'bar' => 2]); // [tl! remove] $a = ['foo' => 1, 'bar' => 2]; // [tl! add]
UnwrapArrayMap (*)
Set: Array
Unwraps array_map
calls.
$a = array_map(fn ($value) => $value + 1, [1, 2, 3]); // [tl! remove] $a = [1, 2, 3]; // [tl! add]
UnwrapArrayMerge (*)
Set: Array
Unwraps array_merge
calls.
$a = array_merge([1, 2, 3], [4, 5, 6]); // [tl! remove] $a = [1, 2, 3]; // [tl! add]
UnwrapArrayMergeRecursive (*)
Set: Array
Unwraps array_merge_recursive
calls.
$a = array_merge_recursive([1, 2, 3], [4, 5, 6]); // [tl! remove] $a = [1, 2, 3]; // [tl! add]
UnwrapArrayPad (*)
Set: Array
Unwraps array_pad
calls.
$a = array_pad([1, 2, 3], 5, 0); // [tl! remove] $a = [1, 2, 3]; // [tl! add]
UnwrapArrayReduce (*)
Set: Array
Unwraps array_reduce
calls.
$a = array_reduce([1, 2, 3], fn ($carry, $item) => $carry + $item, 0); // [tl! remove] $a = [1, 2, 3]; // [tl! add]
UnwrapArrayReplace (*)
Set: Array
Unwraps array_replace
calls.
$a = array_replace([1, 2, 3], ['a', 'b', 'c']); // [tl! remove] $a = [1, 2, 3]; // [tl! add]
UnwrapArrayReplaceRecursive (*)
Set: Array
Unwraps array_replace_recursive
calls.
$a = array_replace_recursive([1, 2, 3], ['a', 'b', 'c']); // [tl! remove] $a = [1, 2, 3]; // [tl! add]
UnwrapArrayReverse (*)
Set: Array
Unwraps array_reverse
calls.
$a = array_reverse([1, 2, 3]); // [tl! remove] $a = [1, 2, 3]; // [tl! add]
UnwrapArraySlice (*)
Set: Array
Unwraps array_slice
calls.
$a = array_slice([1, 2, 3], 1, 2); // [tl! remove] $a = [1, 2, 3]; // [tl! add]
UnwrapArraySplice (*)
Set: Array
Unwraps array_splice
calls.
$a = array_splice([1, 2, 3], 0, 2, ['a', 'b']); // [tl! remove] $a = [1, 2, 3]; // [tl! add]
UnwrapArrayUdiff (*)
Set: Array
Unwraps array_udiff
calls.
$a = array_udiff([1, 2, 3], [1, 2, 4], fn($a, $b) => $a <=> $b); // [tl! remove] $a = [1, 2, 3]; // [tl! add]
UnwrapArrayUdiffAssoc (*)
Set: Array
Unwraps array_udiff_assoc
calls.
$a = array_udiff_assoc([1, 2, 3], [1, 2, 4], fn ($a, $b) => $a <=> $b); // [tl! remove] $a = [1, 2, 3]; // [tl! add]
UnwrapArrayUdiffUassoc (*)
Set: Array
Unwraps array_udiff_uassoc
calls.
$a = array_udiff_uassoc([1, 2, 3], [1, 2, 4], fn ($a, $b) => $a <=> $b, fn ($a, $b) => $a <=> $b); // [tl! remove] $a = [1, 2, 3]; // [tl! add]
UnwrapArrayUintersect (*)
Set: Array
Unwraps array_uintersect
calls.
$a = array_uintersect([1, 2, 3], [1, 2, 4], fn ($a, $b) => $a <=> $b); // [tl! remove] $a = [1, 2, 3]; // [tl! add]
UnwrapArrayUintersectAssoc (*)
Set: Array
Unwraps array_uintersect_assoc
calls.
$a = array_uintersect_assoc([1, 2, 3], [1, 2, 4], fn ($a, $b) => $a <=> $b); // [tl! remove] $a = [1, 2, 3]; // [tl! add]
UnwrapArrayUintersectUassoc (*)
Set: Array
Unwraps array_uintersect_uassoc
calls.
$a = array_uintersect_uassoc([1, 2, 3], [1, 2, 4], fn ($a, $b) => $a <=> $b, fn ($a, $b) => $a <=> $b); // [tl! remove] $a = [1, 2, 3]; // [tl! add]
UnwrapArrayUnique (*)
Set: Array
Unwraps array_unique
calls.
$a = array_unique([1, 2, 3]); // [tl! remove] $a = [1, 2, 3]; // [tl! add]
UnwrapArrayValues (*)
Set: Array
Unwraps array_values
calls.
$a = array_values(['a' => 1, 'b' => 2, 'c' => 3]); // [tl! remove] $a = ['a' => 1, 'b' => 2, 'c' => 3]; // [tl! add]
UnwrapChop (*)
Set: String
Unwraps chop
calls.
$a = chop('Hello World ', ' '); // [tl! remove] $a = 'Hello World '; // [tl! add]
UnwrapChunkSplit (*)
Set: String
Unwraps chunk_split
calls.
$a = chunk_split('Hello World', 1, ' '); // [tl! remove] $a = 'Hello World'; // [tl! add]
UnwrapHtmlEntityDecode (*)
Set: String
Unwraps html_entity_decode
calls.
$a = html_entity_decode('<h1>Hello World</h1>'); // [tl! remove] $a = '<h1>Hello World</h1>'; // [tl! add]
UnwrapHtmlentities (*)
Set: String
Unwraps htmlentities
calls.
$a = htmlentities('<h1>Hello World</h1>'); // [tl! remove] $a = '<h1>Hello World</h1>'; // [tl! add]
UnwrapHtmlspecialchars (*)
Set: String
Unwraps htmlspecialchars
calls.
$a = htmlspecialchars('<h1>Hello World</h1>'); // [tl! remove] $a = '<h1>Hello World</h1>'; // [tl! add]
UnwrapHtmlspecialcharsDecode (*)
Set: String
Unwraps htmlspecialchars_decode
calls.
$a = htmlspecialchars_decode('<h1>Hello World</h1>'); // [tl! remove] $a = '<h1>Hello World</h1>'; // [tl! add]
UnwrapLcfirst (*)
Set: String
Unwraps lcfirst
calls.
$a = lcfirst('Hello World'); // [tl! remove] $a = 'Hello World'; // [tl! add]
UnwrapLtrim (*)
Set: String
Unwraps ltrim
calls.
$a = ltrim(' Hello World'); // [tl! remove] $a = ' Hello World'; // [tl! add]
UnwrapMd5 (*)
Set: String
Unwraps md5
calls.
$a = md5('Hello World'); // [tl! remove] $a = 'Hello World'; // [tl! add]
UnwrapNl2br (*)
Set: String
Unwraps nl2br
calls.
$a = nl2br('Hello World'); // [tl! remove] $a = 'Hello World'; // [tl! add]
UnwrapRtrim (*)
Set: String
Unwraps rtrim
calls.
$a = rtrim('Hello World '); // [tl! remove] $a = 'Hello World '; // [tl! add]
UnwrapStrIreplace (*)
Set: String
Unwraps str_ireplace
calls.
$a = str_ireplace('Hello', 'Hi', 'Hello World'); // [tl! remove] $a = 'Hello World'; // [tl! add]
UnwrapStrPad (*)
Set: String
Unwraps str_pad
calls.
$a = str_pad('Hello World', 20, '-'); // [tl! remove] $a = 'Hello World'; // [tl! add]
UnwrapStrRepeat (*)
Set: String
Unwraps str_repeat
calls.
$a = str_repeat('Hello World', 2); // [tl! remove] $a = 'Hello World'; // [tl! add]
UnwrapStrReplace (*)
Set: String
Unwraps str_replace
calls.
$a = str_replace('Hello', 'Hi', 'Hello World'); // [tl! remove] $a = 'Hello World'; // [tl! add]
UnwrapStrShuffle (*)
Set: String
Unwraps str_shuffle
calls.
$a = str_shuffle('Hello World'); // [tl! remove] $a = 'Hello World'; // [tl! add]
UnwrapStripTags (*)
Set: String
Unwraps strip_tags
calls.
$a = strip_tags('Hello World'); // [tl! remove] $a = 'Hello World'; // [tl! add]
UnwrapStrrev (*)
Set: String
Unwraps strrev
calls.
$a = strrev('Hello World'); // [tl! remove] $a = 'Hello World'; // [tl! add]
UnwrapStrtolower (*)
Set: String
Unwraps strtolower
calls.
$a = strtolower('Hello World'); // [tl! remove] $a = 'Hello World'; // [tl! add]
UnwrapStrtoupper (*)
Set: String
Unwraps strtoupper
calls.
$a = strtoupper('Hello World'); // [tl! remove] $a = 'Hello World'; // [tl! add]
UnwrapSubstr (*)
Set: String
Unwraps substr
calls.
$a = substr('Hello World', 0, 5); // [tl! remove] $a = 'Hello World'; // [tl! add]
UnwrapTrim (*)
Set: String
Unwraps trim
calls.
$a = trim(' Hello World '); // [tl! remove] $a = ' Hello World '; // [tl! add]
UnwrapUcfirst (*)
Set: String
Unwraps ucfirst
calls.
$a = ucfirst('hello world'); // [tl! remove] $a = 'hello world'; // [tl! add]
UnwrapUcwords (*)
Set: String
Unwraps ucwords
calls.
$a = ucwords('hello world'); // [tl! remove] $a = 'hello world'; // [tl! add]
UnwrapWordwrap (*)
Set: String
Unwraps wordwrap
calls.
$a = wordwrap('Hello World', 5); // [tl! remove] $a = 'Hello World'; // [tl! add]
WhileAlwaysFalse (*)
Set: ControlStructures
Makes the condition in a while loop always false.
while ($a < 100) { // [tl! remove] while (false) { // [tl! add] // ... }