Skip to content

Commit

Permalink
Add PHP-Parser 5 support (#1909)
Browse files Browse the repository at this point in the history
* Add PHP-Parser 5 support

* fix PHP-Parser 5 breaking changes and deprecations

* Change Throw mutator due to internal changes in PHP-Parser

* Change PregQuite mutator due to internal changes in PHP-Parser and AST

* Change Finally_ mutator due to internal changes in PhpParser\Node\Stmt\TryCatch constructor

* Fix failed MutantCodeFactoryTest due to renamed nodes

* Fix failed MatchArmRemoval due to changes in PHP-Parser

* apply cs fixer

* fix invalid AbstractValueToNullReturnValue test case. Identifier->name ca not be null

* revert Configuration changes

* Fix integration tests due to AST changes

* Add BackwardCompatible pretty printer

* Fix tests

* Fix issues after merging master into current branch

* Fix tests, add missed DataProvider and fixed indentation in heredocs

* Removed previously added BackwardCompatibleStandard.php

* Fix more tests

* Remove `nikic/php-parser`:4 compatibility tests

* Fix other tests

* Fix issues after merging master

* Revert "Conflict with `nikic/php-parser` in e2e tests unless #1909 is merged"

This reverts commit 873cd33.

* Remove usage if old classes, fir phpstan/psalm errors

---------

Co-authored-by: maks-rafalko <b0rn@list.ru>
  • Loading branch information
sidz and maks-rafalko committed Mar 23, 2024
1 parent bde0f4a commit 7375c55
Show file tree
Hide file tree
Showing 80 changed files with 181 additions and 382 deletions.
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"infection/extension-installer": "^0.1.0",
"infection/include-interceptor": "^0.2.5",
"justinrainbow/json-schema": "^5.2.10",
"nikic/php-parser": "^4.15.1",
"nikic/php-parser": "^5.0",
"ondram/ci-detector": "^4.1.0",
"sanmai/later": "^0.1.1",
"sanmai/pipeline": "^5.1 || ^6",
Expand Down Expand Up @@ -85,7 +85,7 @@
"phpstan/phpstan-webmozart-assert": "^1.0.2",
"phpunit/phpunit": "^10.5",
"rector/rector": "^1.0",
"sidz/phpstan-rules": "^0.4.0",
"sidz/phpstan-rules": "^0.4",
"symfony/yaml": "^5.4 || ^6.0 || ^7.0",
"thecodingmachine/phpstan-safe-rule": "^1.2.0"
},
Expand Down
36 changes: 19 additions & 17 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 13 additions & 3 deletions devTools/phpstan-src-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,11 @@ parameters:
count: 1
path: ../src/Mutator/Operator/SpreadOneItem.php

-
message: "#^Parameter \\#1 \\$items of class PhpParser\\\\Node\\\\Expr\\\\Array_ constructor expects array\\<PhpParser\\\\Node\\\\ArrayItem\\>, array\\<int, PhpParser\\\\Node\\\\Expr\\\\ArrayItem\\> given\\.$#"
count: 1
path: ../src/Mutator/Operator/SpreadOneItem.php

-
message: "#^Method Infection\\\\Mutator\\\\Operator\\\\SpreadRemoval\\:\\:getDefinition\\(\\) never returns null so it can be removed from the return type\\.$#"
count: 1
Expand Down Expand Up @@ -841,12 +846,12 @@ parameters:
path: ../src/Mutator/Unwrap/UnwrapUcWords.php

-
message: "#^Method Infection\\\\PhpParser\\\\Visitor\\\\MutatorVisitor\\:\\:leaveNode\\(\\) never returns int so it can be removed from the return type\\.$#"
message: "#^Method Infection\\\\PhpParser\\\\Visitor\\\\NonMutableNodesIgnorerVisitor\\:\\:enterNode\\(\\) never returns PhpParser\\\\Node so it can be removed from the return type\\.$#"
count: 1
path: ../src/PhpParser/Visitor/MutatorVisitor.php
path: ../src/PhpParser/Visitor/NonMutableNodesIgnorerVisitor.php

-
message: "#^Method Infection\\\\PhpParser\\\\Visitor\\\\NonMutableNodesIgnorerVisitor\\:\\:enterNode\\(\\) never returns PhpParser\\\\Node so it can be removed from the return type\\.$#"
message: "#^Method Infection\\\\PhpParser\\\\Visitor\\\\NonMutableNodesIgnorerVisitor\\:\\:enterNode\\(\\) never returns array\\<PhpParser\\\\Node\\> so it can be removed from the return type\\.$#"
count: 1
path: ../src/PhpParser/Visitor/NonMutableNodesIgnorerVisitor.php

Expand All @@ -855,6 +860,11 @@ parameters:
count: 1
path: ../src/PhpParser/Visitor/ReflectionVisitor.php

-
message: "#^Method Infection\\\\PhpParser\\\\Visitor\\\\ReflectionVisitor\\:\\:enterNode\\(\\) never returns array\\<PhpParser\\\\Node\\> so it can be removed from the return type\\.$#"
count: 1
path: ../src/PhpParser/Visitor/ReflectionVisitor.php

-
message: "#^Parameter \\#2 \\$paths of method Composer\\\\Autoload\\\\ClassLoader\\:\\:setPsr4\\(\\) expects list\\<string\\>\\|string, array\\<string\\> given\\.$#"
count: 1
Expand Down
19 changes: 1 addition & 18 deletions src/Container.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@
use Infection\Mutant\MutantExecutionResultFactory;
use Infection\Mutant\MutantFactory;
use Infection\Mutation\FileMutationGenerator;
use Infection\Mutation\MutationAttributeKeys;
use Infection\Mutation\MutationGenerator;
use Infection\Mutator\MutatorFactory;
use Infection\Mutator\MutatorParser;
Expand Down Expand Up @@ -139,7 +138,6 @@
use InvalidArgumentException;
use OndraM\CiDetector\CiDetector;
use function php_ini_loaded_file;
use PhpParser\Lexer;
use PhpParser\Parser;
use PhpParser\ParserFactory;
use PhpParser\PrettyPrinter\Standard;
Expand Down Expand Up @@ -298,17 +296,7 @@ public static function create(): self
MemoizedTestFileDataProvider::class => static fn (self $container): TestFileDataProvider => new MemoizedTestFileDataProvider(
new JUnitTestFileDataProvider($container->getJUnitReportLocator()),
),
Lexer::class => static function (): Lexer {
$attributes = MutationAttributeKeys::ALL;
$attributes[] = 'comments';

return new Lexer\Emulative(['usedAttributes' => $attributes]);
},
Parser::class => static function (self $container): Parser {
$lexer = $container->getLexer();

return (new ParserFactory())->create(ParserFactory::PREFER_PHP7, $lexer);
},
Parser::class => static fn (): Parser => (new ParserFactory())->createForHostVersion(),
FileParser::class => static fn (self $container): FileParser => new FileParser($container->getParser()),
PrettyPrinterAbstract::class => static fn (): Standard => new Standard(),
MetricsCalculator::class => static fn (self $container): MetricsCalculator => new MetricsCalculator($container->getConfiguration()->getMsiPrecision()),
Expand Down Expand Up @@ -844,11 +832,6 @@ public function getMemoizedTestFileDataProvider(): MemoizedTestFileDataProvider
return $this->get(MemoizedTestFileDataProvider::class);
}

public function getLexer(): Lexer
{
return $this->get(Lexer::class);
}

public function getParser(): Parser
{
return $this->get(Parser::class);
Expand Down
4 changes: 2 additions & 2 deletions src/Mutation/Mutation.php
Original file line number Diff line number Diff line change
Expand Up @@ -162,12 +162,12 @@ public function getAllTests(): array
public function getNominalTestExecutionTime(): float
{
// TestLocator returns non-unique tests, and JUnitTestCaseSorter works around that; we have to do that too.
return $this->nominalTimeToTest ?? $this->nominalTimeToTest = (new JUnitTestCaseTimeAdder($this->tests))->getTotalTestTime();
return $this->nominalTimeToTest ??= (new JUnitTestCaseTimeAdder($this->tests))->getTotalTestTime();
}

public function getHash(): string
{
return $this->hash ?? $this->hash = $this->createHash();
return $this->hash ??= $this->createHash();
}

private function createHash(): string
Expand Down
4 changes: 2 additions & 2 deletions src/Mutator/IgnoreMutator.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,14 @@ public function canMutate(Node $node): bool
return !$this->config->isIgnored(
$reflectionClass->getName(),
$node->getAttribute(ReflectionVisitor::FUNCTION_NAME, ''),
$node->getLine(),
$node->getStartLine(),
);
}

/**
* @psalm-mutation-free
*
* @return iterable<Node|Node[]>
* @return iterable<int|Node|Node[]>
*/
public function mutate(Node $node): iterable
{
Expand Down
2 changes: 1 addition & 1 deletion src/Mutator/Mutator.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public function canMutate(Node $node): bool;
*
* @param TNode $node
*
* @return iterable<Node|Node[]>
* @return iterable<int|Node|Node[]>
*/
public function mutate(Node $node): iterable;
}
5 changes: 3 additions & 2 deletions src/Mutator/Operator/Finally_.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
use Infection\Mutator\MutatorCategory;
use Infection\PhpParser\Visitor\ParentConnector;
use PhpParser\Node;
use PhpParser\NodeVisitor;
use Webmozart\Assert\Assert;

/**
Expand Down Expand Up @@ -73,11 +74,11 @@ public static function getDefinition(): ?Definition
/**
* @psalm-mutation-free
*
* @return iterable<Node\Stmt\Nop>
* @return iterable<int|Node\Stmt\Nop>
*/
public function mutate(Node $node): iterable
{
yield new Node\Stmt\Nop();
yield NodeVisitor::REPLACE_WITH_NULL;
}

public function canMutate(Node $node): bool
Expand Down
8 changes: 4 additions & 4 deletions src/Mutator/Operator/Throw_.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
/**
* @internal
*
* @implements Mutator<Node\Stmt\Throw_>
* @implements Mutator<Node\Expr\Throw_>
*/
final class Throw_ implements Mutator
{
Expand Down Expand Up @@ -82,15 +82,15 @@ public static function getDefinition(): ?Definition
*
* Replaces "throw new Exception();" with "new Exception();"
*
* @return iterable<Node\Stmt\Expression>
* @return iterable<Node\Stmt\Expression|Node\Expr>
*/
public function mutate(Node $node): iterable
{
yield new Node\Stmt\Expression($node->expr);
yield $node->expr;
}

public function canMutate(Node $node): bool
{
return $node instanceof Node\Stmt\Throw_;
return $node instanceof Node\Expr\Throw_;
}
}
4 changes: 2 additions & 2 deletions src/Mutator/Regex/PregQuote.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,15 @@ public static function getDefinition(): ?Definition
/**
* @psalm-mutation-free
*
* @return iterable<Node\Arg>
* @return iterable<Node\Expr>
*/
public function mutate(Node $node): iterable
{
if ($node->args[0] instanceof Node\VariadicPlaceholder) {
return [];
}

yield $node->args[0];
yield $node->args[0]->value;
}

public function canMutate(Node $node): bool
Expand Down
2 changes: 1 addition & 1 deletion src/Mutator/Removal/ArrayItemRemoval.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
use Infection\PhpParser\Visitor\ParentConnector;
use function min;
use PhpParser\Node;
use PhpParser\Node\Expr\ArrayItem;
use PhpParser\Node\ArrayItem;
use function range;

/**
Expand Down
11 changes: 7 additions & 4 deletions src/Mutator/Removal/MatchArmRemoval.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

namespace Infection\Mutator\Removal;

use function array_values;
use function count;
use Infection\Mutator\Definition;
use Infection\Mutator\GetMutatorName;
Expand Down Expand Up @@ -116,13 +117,15 @@ public function mutate(Node $node): iterable
foreach ($node->arms as $i => $arm) {
$arms = $node->arms;

if ($arm->conds !== null && count((array) $arm->conds) > 1) {
foreach ($arm->conds as $j => $cond) {
$conds = $arm->conds;
$armConds = $arm->conds ?? [];

if (count($armConds) > 1) {
foreach ($armConds as $j => $cond) {
$conds = $armConds;

unset($conds[$j]);

$arms[$i] = new Node\MatchArm($conds, $arm->body, $node->getAttributes());
$arms[$i] = new Node\MatchArm(array_values($conds), $arm->body, $node->getAttributes());

yield new Node\Expr\Match_($node->cond, $arms, $node->getAttributes());
}
Expand Down
2 changes: 1 addition & 1 deletion src/Mutator/Util/AbstractValueToNullReturnValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ protected function isNullReturnValueAllowed(Node $node): bool
$returnType = $functionScope->getReturnType();

if ($returnType instanceof Node\Identifier) {
$returnType = $returnType->name;
$returnType = $returnType->toString();
}

// no return value specified
Expand Down

0 comments on commit 7375c55

Please sign in to comment.