Skip to content
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

Do not mutate * to / and vice versa if one of the operands is numeric ±1.0 #673

Merged
merged 1 commit into from Mar 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
27 changes: 26 additions & 1 deletion src/Mutator/Arithmetic/Division.php
Expand Up @@ -56,6 +56,31 @@ public function mutate(Node $node)

protected function mutatesNode(Node $node): bool
{
return $node instanceof Node\Expr\BinaryOp\Div;
if (!$node instanceof Node\Expr\BinaryOp\Div) {
return false;
}

if ($this->isNumericOne($node->left) || $this->isNumericOne($node->right)) {
return false;
}

if ($node->left instanceof Node\Expr\UnaryMinus && $this->isNumericOne($node->left->expr)) {
return false;
}

if ($node->right instanceof Node\Expr\UnaryMinus && $this->isNumericOne($node->right->expr)) {
return false;
}

return true;
}

private function isNumericOne(Node $node): bool
{
if ($node instanceof Node\Scalar\LNumber && $node->value === 1) {
return true;
}

return $node instanceof Node\Scalar\DNumber && $node->value === 1.0;
}
}
27 changes: 26 additions & 1 deletion src/Mutator/Arithmetic/Multiplication.php
Expand Up @@ -56,6 +56,31 @@ public function mutate(Node $node)

protected function mutatesNode(Node $node): bool
{
return $node instanceof Node\Expr\BinaryOp\Mul;
if (!$node instanceof Node\Expr\BinaryOp\Mul) {
return false;
}

if ($this->isNumericOne($node->left) || $this->isNumericOne($node->right)) {
return false;
}

if ($node->left instanceof Node\Expr\UnaryMinus && $this->isNumericOne($node->left->expr)) {
return false;
}

if ($node->right instanceof Node\Expr\UnaryMinus && $this->isNumericOne($node->right->expr)) {
return false;
}

return true;
}

private function isNumericOne(Node $node): bool
{
if ($node instanceof Node\Scalar\LNumber && $node->value === 1) {
return true;
}

return $node instanceof Node\Scalar\DNumber && $node->value === 1.0;
}
}
81 changes: 64 additions & 17 deletions tests/Mutator/Arithmetic/DivisionTest.php
Expand Up @@ -50,10 +50,9 @@ public function test_mutator($input, $expected = null): void
$this->doTest($input, $expected);
}

public function provideMutationCases(): array
public function provideMutationCases(): \Generator
{
return [
'It changes regular divison' => [
yield 'It changes regular divison' => [
<<<'PHP'
<?php

Expand All @@ -65,31 +64,79 @@ public function provideMutationCases(): array

$a = 10 * 2;
PHP
,
],
'It does not change division equals' => [
];

yield 'It does not change division equals' => [
<<<'PHP'
<?php

$a = 10;
$a /= 5;
PHP
,
],
];
}

public function test_replaces_division_with_multiplication(): void
{
$code = '<?php 1 / 2;';
$mutations = $this->mutate($code);
yield 'It does not mutate when the left side is 1 to avoid an equivalent mutation' => [
<<<'PHP'
<?php

$expectedMutatedCode = <<<'PHP'
$a = 1 / $b;
PHP
];

yield 'It does not mutate when the right side is 1 to avoid an equivalent mutation' => [
<<<'PHP'
<?php

1 * 2;
PHP;
$a = $b / 1;
PHP
];

yield 'It does not mutate when the left side is -1 to avoid an equivalent mutation' => [
<<<'PHP'
<?php

$a = -1 / $b;
PHP
];

yield 'It does not mutate when the right side is -1 to avoid an equivalent mutation' => [
<<<'PHP'
<?php

$this->assertSame($expectedMutatedCode, $mutations[0]);
$a = $b / -1;
PHP
];

yield 'It does not mutate when the left side is 1.0 to avoid an equivalent mutation' => [
<<<'PHP'
<?php

$a = 1.0 / $b;
PHP
];

yield 'It does not mutate when the right side is 1.0 to avoid an equivalent mutation' => [
<<<'PHP'
<?php

$a = $b / 1.0;
PHP
];

yield 'It does not mutate when the left side is -1.0 to avoid an equivalent mutation' => [
<<<'PHP'
<?php

$a = -1.0 / $b;
PHP
];

yield 'It does not mutate when the right side is -1.0 to avoid an equivalent mutation' => [
<<<'PHP'
<?php

$a = $b / -1.0;
PHP
];
}
}
77 changes: 69 additions & 8 deletions tests/Mutator/Arithmetic/MultiplicationTest.php
Expand Up @@ -50,10 +50,9 @@ public function test_mutator($input, $expected = null): void
$this->doTest($input, $expected);
}

public function provideMutationCases(): array
public function provideMutationCases(): \Generator
{
return [
'It mutates normal multiplication' => [
yield 'It mutates normal multiplication' => [
<<<'PHP'
<?php

Expand All @@ -65,17 +64,79 @@ public function provideMutationCases(): array

$a = 10 / 3;
PHP
,
],
'It does not mutate multiplication equals' => [
];

yield 'It does not mutate multiplication equals' => [
<<<'PHP'
<?php

$a = 1;
$a *= 2;
PHP
,
],
];

yield 'It does not mutate when the left side is 1 to avoid an equivalent mutation' => [
<<<'PHP'
<?php

$a = 1 * $b;
PHP
];

yield 'It does not mutate when the right side is 1 to avoid an equivalent mutation' => [
<<<'PHP'
<?php

$a = $b * 1;
PHP
];

yield 'It does not mutate when the left side is -1 to avoid an equivalent mutation' => [
<<<'PHP'
<?php

$a = -1 * $b;
PHP
];

yield 'It does not mutate when the right side is -1 to avoid an equivalent mutation' => [
<<<'PHP'
<?php

$a = $b * -1;
PHP
];

yield 'It does not mutate when the left side is 1.0 to avoid an equivalent mutation' => [
<<<'PHP'
<?php

$a = 1.0 * $b;
PHP
];

yield 'It does not mutate when the right side is 1.0 to avoid an equivalent mutation' => [
<<<'PHP'
<?php

$a = $b * 1.0;
PHP
];

yield 'It does not mutate when the left side is -1.0 to avoid an equivalent mutation' => [
<<<'PHP'
<?php

$a = -1.0 * $b;
PHP
];

yield 'It does not mutate when the right side is -1.0 to avoid an equivalent mutation' => [
<<<'PHP'
<?php

$a = $b * -1.0;
PHP
];
}
}