Skip to content

Commit

Permalink
Compatibility with nikic/php-parser v5 (#36)
Browse files Browse the repository at this point in the history
* Compatibility with nikic/php-parser v5

* feat(deps): bump symfony property info version to make it work with readonly

---------

Co-authored-by: Joel Wurtz <[email protected]>
  • Loading branch information
Korbeil and joelwurtz authored Mar 11, 2024
1 parent b4d0741 commit 106eb30
Show file tree
Hide file tree
Showing 14 changed files with 131 additions and 39 deletions.
29 changes: 25 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
- name: checkout
uses: actions/checkout@master
- name: setup
uses: shivammathur/setup-php@2.9.0
uses: shivammathur/setup-php@2.29.0
with:
php-version: 8.2
coverage: none
Expand All @@ -28,7 +28,7 @@ jobs:
path: ~/.composer/cache/
key: composer-${{ github.sha }}
- name: setup
uses: shivammathur/setup-php@2.9.0
uses: shivammathur/setup-php@2.29.0
with:
php-version: 8.3
coverage: none
Expand Down Expand Up @@ -58,7 +58,7 @@ jobs:
path: ~/.composer/cache/
key: composer-${{ github.sha }}
- name: setup
uses: shivammathur/setup-php@2.9.0
uses: shivammathur/setup-php@2.29.0
with:
php-version: '${{ matrix.php-versions }}'
coverage: none
Expand All @@ -67,6 +67,27 @@ jobs:
run: composer update --prefer-stable
- name: tests
run: vendor/bin/phpunit
tests-lowest:
runs-on: ubuntu-latest
name: tests-lowest
steps:
- name: checkout
uses: actions/checkout@master
- name: cache-composer
uses: actions/cache@v2
with:
path: ~/.composer/cache/
key: composer-${{ github.sha }}
- name: setup
uses: shivammathur/[email protected]
with:
php-version: 8.2
coverage: none
extensions: mbstring, fileinfo, json, intl, dom
- name: composer install
run: composer update --prefer-stable --prefer-lowest
- name: tests
run: vendor/bin/phpunit
check-version:
runs-on: ubuntu-latest
steps:
Expand All @@ -78,7 +99,7 @@ jobs:
path: ~/.composer/cache/
key: composer-${{ github.sha }}
- name: setup
uses: shivammathur/setup-php@2.9.0
uses: shivammathur/setup-php@2.29.0
with:
php-version: 8.3
coverage: none
Expand Down
8 changes: 4 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,17 @@
"require": {
"php": "^8.2",
"doctrine/inflector": "^1.4 || ^2.0",
"nikic/php-parser": "^4.0",
"nikic/php-parser": "^4.18 || ^5.0",
"symfony/deprecation-contracts": "^2.2|^3.0",
"symfony/property-info": "^5.4 || ^6.0 || ^7.0",
"symfony/property-info": "^5.4.23 || ^6.2.10 || ^7.0",
"symfony/serializer": "^5.4 || ^6.0 || ^7.0"
},
"require-dev": {
"doctrine/annotations": "~1.0",
"moneyphp/money": "^3.0",
"moneyphp/money": "^3.3.2",
"phpdocumentor/type-resolver": "^1.7",
"phpstan/phpdoc-parser": "^1.24",
"phpunit/phpunit": "^8.0",
"phpunit/phpunit": "^9.0",
"symfony/filesystem": "^5.4 || ^6.0 || ^7.0",
"symfony/http-kernel": "^5.4 || ^6.0 || ^7.0",
"symfony/uid": "^5.4 || ^6.0 || ^7.0"
Expand Down
18 changes: 9 additions & 9 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>

<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/5.2/phpunit.xsd"
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/9.3/phpunit.xsd"
backupGlobals="false"
colors="true"
bootstrap="vendor/autoload.php"
Expand All @@ -19,13 +19,13 @@
</testsuite>
</testsuites>

<filter>
<whitelist>
<coverage>
<include>
<directory>./</directory>
<exclude>
<directory>./tests</directory>
<directory>./vendor</directory>
</exclude>
</whitelist>
</filter>
</include>
<exclude>
<directory>./tests</directory>
<directory>./vendor</directory>
</exclude>
</coverage>
</phpunit>
4 changes: 2 additions & 2 deletions src/Extractor/ClassMethodToCallbackExtractor.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

public function __construct(?Parser $parser = null)
{
$this->parser = $parser ?? (new ParserFactory())->create(ParserFactory::PREFER_PHP7);
$this->parser = $parser ?? (new ParserFactory())->createForHostVersion();
}

/**
Expand Down Expand Up @@ -77,7 +77,7 @@ public function extract(string $class, string $method, array $inputParameters):

return new Expr\FuncCall(
new Expr\Closure([
'stmts' => $classMethod->stmts,
'stmts' => $classMethod->stmts ?? [],
'params' => $closureParameters,
'returnType' => $classMethod->returnType,
]),
Expand Down
2 changes: 1 addition & 1 deletion src/Generator/CreateTargetStatementsGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public function __construct(
private CachedReflectionStatementsGenerator $cachedReflectionStatementsGenerator,
?Parser $parser = null,
) {
$this->parser = $parser ?? (new ParserFactory())->create(ParserFactory::PREFER_PHP7);
$this->parser = $parser ?? (new ParserFactory())->createForHostVersion();
}

/**
Expand Down
11 changes: 5 additions & 6 deletions src/Generator/MapperGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use AutoMapper\MapperGeneratorMetadataInterface;
use PhpParser\Builder;
use PhpParser\Node\Expr;
use PhpParser\Node\Name;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt;

Expand Down Expand Up @@ -103,7 +104,7 @@ private function mapMethod(MapperGeneratorMetadataInterface $mapperMetadata): St
->setReturnType('mixed')
->makeReturnByRef()
->addParam(new Param($variableRegistry->getSourceInput()))
->addParam(new Param($variableRegistry->getContext(), default: new Expr\Array_(), type: 'array'))
->addParam(new Param($variableRegistry->getContext(), default: new Expr\Array_(), type: new Name('array')))
->addStmts($this->mapMethodStatementsGenerator->getStatements($mapperMetadata))
->setDocComment(
sprintf(
Expand Down Expand Up @@ -133,11 +134,9 @@ private function injectMappersMethod(MapperGeneratorMetadataInterface $mapperMet
return (new Builder\Method('injectMappers'))
->makePublic()
->setReturnType('void')
->addParam(
new Param(
var: $param = new Expr\Variable('autoMapperRegistry'),
type: AutoMapperRegistryInterface::class
)
->addParam(new Param(
var: $param = new Expr\Variable('autoMapperRegistry'),
type: new Name(AutoMapperRegistryInterface::class))
)
->addStmts($this->injectMapperMethodStatementsGenerator->getStatements($param, $mapperMetadata))
->getNode();
Expand Down
24 changes: 20 additions & 4 deletions src/Generator/PropertyConditionsGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
use AutoMapper\Extractor\PropertyMapping;
use AutoMapper\MapperContext;
use PhpParser\Node\Arg;
use PhpParser\Node\ArrayItem as NewArrayItem;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\ArrayItem as OldArrayItem;
use PhpParser\Node\Name;
use PhpParser\Node\Scalar;

Expand Down Expand Up @@ -134,6 +136,13 @@ private function sourceGroupsCheck(PropertyMapping $propertyMapping): ?Expr

$variableRegistry = $propertyMapping->mapperMetadata->getVariableRegistry();

// compatibility with old versions of nikic/php-parser
if (class_exists(NewArrayItem::class)) {
$arrayItemClass = NewArrayItem::class;
} else {
$arrayItemClass = OldArrayItem::class;
}

return new Expr\BinaryOp\BooleanAnd(
new Expr\BinaryOp\NotIdentical(
new Expr\ConstFetch(new Name('null')),
Expand All @@ -149,8 +158,8 @@ private function sourceGroupsCheck(PropertyMapping $propertyMapping): ?Expr
new Expr\Array_()
)
),
new Arg(new Expr\Array_(array_map(function (string $group) {
return new Expr\ArrayItem(new Scalar\String_($group));
new Arg(new Expr\Array_(array_map(function (string $group) use ($arrayItemClass) {
return new $arrayItemClass(new Scalar\String_($group));
}, $propertyMapping->sourceGroups))),
])
);
Expand All @@ -171,6 +180,13 @@ private function targetGroupsCheck(PropertyMapping $propertyMapping): ?Expr

$variableRegistry = $propertyMapping->mapperMetadata->getVariableRegistry();

// compatibility with old versions of nikic/php-parser
if (class_exists(NewArrayItem::class)) {
$arrayItemClass = NewArrayItem::class;
} else {
$arrayItemClass = OldArrayItem::class;
}

return new Expr\BinaryOp\BooleanAnd(
new Expr\BinaryOp\NotIdentical(
new Expr\ConstFetch(new Name('null')),
Expand All @@ -186,8 +202,8 @@ private function targetGroupsCheck(PropertyMapping $propertyMapping): ?Expr
new Expr\Array_()
)
),
new Arg(new Expr\Array_(array_map(function (string $group) {
return new Expr\ArrayItem(new Scalar\String_($group));
new Arg(new Expr\Array_(array_map(function (string $group) use ($arrayItemClass) {
return new $arrayItemClass(new Scalar\String_($group));
}, $propertyMapping->targetGroups))),
])
);
Expand Down
11 changes: 10 additions & 1 deletion src/Transformer/BuiltinTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
use AutoMapper\Extractor\PropertyMapping;
use AutoMapper\Generator\UniqueVariableScope;
use PhpParser\Node\Arg;
use PhpParser\Node\ArrayItem as NewArrayItem;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\ArrayItem as OldArrayItem;
use PhpParser\Node\Expr\Cast;
use PhpParser\Node\Name;
use Symfony\Component\PropertyInfo\Type;
Expand Down Expand Up @@ -104,7 +106,14 @@ public function transform(Expr $input, Expr $target, PropertyMapping $propertyMa

private function toArray(Expr $input): Expr
{
return new Expr\Array_([new Expr\ArrayItem($input)]);
// compatibility with old versions of nikic/php-parser
if (class_exists(NewArrayItem::class)) {
$arrayItemClass = NewArrayItem::class;
} else {
$arrayItemClass = OldArrayItem::class;
}

return new Expr\Array_([new $arrayItemClass($input)]);
}

private function fromIteratorToArray(Expr $input): Expr
Expand Down
10 changes: 9 additions & 1 deletion tests/AutoMapperBaseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@
use AutoMapper\Generator\Shared\ClassDiscriminatorResolver;
use AutoMapper\Loader\ClassLoaderInterface;
use AutoMapper\Loader\FileLoader;
use Doctrine\Common\Annotations\AnnotationReader;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorFromClassMetadata;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
use Symfony\Component\Serializer\Mapping\Loader\AttributeLoader;

/**
Expand All @@ -33,7 +35,13 @@ protected function buildAutoMapper(bool $allowReadOnlyTargetToPopulate = false,
{
$fs = new Filesystem();
$fs->remove(__DIR__ . '/cache/');
$classMetadataFactory = new ClassMetadataFactory(new AttributeLoader());

if (class_exists(AttributeLoader::class)) {
$loaderClass = new AttributeLoader();
} else {
$loaderClass = new AnnotationLoader(new AnnotationReader());
}
$classMetadataFactory = new ClassMetadataFactory($loaderClass);

$this->loader = new FileLoader(new MapperGenerator(
new ClassDiscriminatorResolver(new ClassDiscriminatorFromClassMetadata($classMetadataFactory)),
Expand Down
16 changes: 12 additions & 4 deletions tests/Extractor/ClassMethodToCallbackExtractorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,18 @@ public function testExtractSimpleMethod(string $varName): void
$extractor = new ClassMethodToCallbackExtractor();
$extractedMethod = new Expression($extractor->extract(FooCustomMapper::class, 'transform', [new Arg(new Variable($varName))]));

// used for compatibility with older versions of nikic/php-parser
$generatedCode = (new Standard())->prettyPrint([$extractedMethod]);
$generatedCode = str_replace(') : mixed', '): mixed', $generatedCode);

$this->assertEquals(<<<PHP
(function (mixed \$object) : mixed {
(function (mixed \$object): mixed {
if (\$object instanceof \AutoMapper\Tests\Extractor\Fixtures\Foo) {
\$object->bar = 'Hello World!';
}
return \$object;
})(\${$varName});
PHP, $generatedCode = (new Standard())->prettyPrint([$extractedMethod]));
PHP, $generatedCode);

$this->assertGeneratedCodeIsRunnable($generatedCode, $varName);
}
Expand All @@ -51,15 +55,19 @@ public function testExtractMethodWithTwoVariables(): void
$extractor = new ClassMethodToCallbackExtractor();
$extractedMethod = new Expression($extractor->extract(FooCustomMapper::class, 'switch', [new Arg(new Variable('someVar')), new Arg(new Variable('context'))]));

// used for compatibility with older versions of nikic/php-parser
$generatedCode = (new Standard())->prettyPrint([$extractedMethod]);
$generatedCode = str_replace(') : mixed', '): mixed', $generatedCode);

$this->assertEquals(<<<PHP
(function (mixed \$object, string \$someString) : mixed {
(function (mixed \$object, string \$someString): mixed {
if (\$object instanceof \AutoMapper\Tests\Extractor\Fixtures\Foo) {
\$object->bar = 'Hello World!';
\$object->baz = \$someString;
}
return \$object;
})(\$someVar, \$context);
PHP, (new Standard())->prettyPrint([$extractedMethod]));
PHP, $generatedCode);
}

public function testCannotExtractCode(): void
Expand Down
10 changes: 9 additions & 1 deletion tests/Extractor/FromSourceMappingExtractorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@
use AutoMapper\Transformer\NullableTransformerFactory;
use AutoMapper\Transformer\ObjectTransformerFactory;
use AutoMapper\Transformer\UniqueTypeTransformerFactory;
use Doctrine\Common\Annotations\AnnotationReader;
use Symfony\Component\PropertyInfo\Extractor\PhpStanExtractor;
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
use Symfony\Component\PropertyInfo\PropertyInfoExtractor;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
use Symfony\Component\Serializer\Mapping\Loader\AttributeLoader;

/**
Expand All @@ -39,7 +41,13 @@ protected function setUp(): void

private function fromSourceMappingExtractorBootstrap(bool $private = true): void
{
$classMetadataFactory = new ClassMetadataFactory(new AttributeLoader());
if (class_exists(AttributeLoader::class)) {
$loaderClass = new AttributeLoader();
} else {
$loaderClass = new AnnotationLoader(new AnnotationReader());
}
$classMetadataFactory = new ClassMetadataFactory($loaderClass);

$flags = ReflectionExtractor::ALLOW_PUBLIC;

if ($private) {
Expand Down
9 changes: 8 additions & 1 deletion tests/Extractor/FromTargetMappingExtractorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@
use AutoMapper\Transformer\NullableTransformerFactory;
use AutoMapper\Transformer\ObjectTransformerFactory;
use AutoMapper\Transformer\UniqueTypeTransformerFactory;
use Doctrine\Common\Annotations\AnnotationReader;
use Symfony\Component\PropertyInfo\Extractor\PhpStanExtractor;
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
use Symfony\Component\PropertyInfo\PropertyInfoExtractor;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
use Symfony\Component\Serializer\Mapping\Loader\AttributeLoader;

/**
Expand All @@ -38,7 +40,12 @@ protected function setUp(): void

private function fromTargetMappingExtractorBootstrap(bool $private = true): void
{
$classMetadataFactory = new ClassMetadataFactory(new AttributeLoader());
if (class_exists(AttributeLoader::class)) {
$loaderClass = new AttributeLoader();
} else {
$loaderClass = new AnnotationLoader(new AnnotationReader());
}
$classMetadataFactory = new ClassMetadataFactory($loaderClass);
$flags = ReflectionExtractor::ALLOW_PUBLIC;

if ($private) {
Expand Down
Loading

0 comments on commit 106eb30

Please sign in to comment.