Skip to content

Commit bd4bec1

Browse files
committed
feat: option to generate code with strict types
1 parent 2eb0671 commit bd4bec1

File tree

7 files changed

+64
-7
lines changed

7 files changed

+64
-7
lines changed

src/Configuration.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ public function __construct(
3636
* Does the mapper should throw an exception if the target is read-only.
3737
*/
3838
public bool $allowReadOnlyTargetToPopulate = false,
39+
/**
40+
* Add declare(strict_types=1) to generated code.
41+
*/
42+
public bool $strictTypes = false,
3943
) {
4044
}
4145
}

src/Generator/MapperGenerator.php

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
use PhpParser\Node\Stmt;
2121
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
2222

23+
use function AutoMapper\PhpParser\create_declare_item;
24+
use function AutoMapper\PhpParser\create_scalar_int;
25+
2326
/**
2427
* Generates code for a mapping class.
2528
*
@@ -32,6 +35,7 @@
3235
private MapperConstructorGenerator $mapperConstructorGenerator;
3336
private InjectMapperMethodStatementsGenerator $injectMapperMethodStatementsGenerator;
3437
private MapMethodStatementsGenerator $mapMethodStatementsGenerator;
38+
private bool $declareStrictTypes;
3539
private bool $disableGeneratedMapper;
3640

3741
public function __construct(
@@ -52,28 +56,38 @@ public function __construct(
5256

5357
$this->injectMapperMethodStatementsGenerator = new InjectMapperMethodStatementsGenerator();
5458

59+
$this->declareStrictTypes = $configuration->strictTypes;
5560
$this->disableGeneratedMapper = !$configuration->autoRegister;
5661
}
5762

5863
/**
5964
* Generate Class AST given metadata for a mapper.
6065
*
66+
* @return Stmt[]
67+
*
6168
* @throws CompileException
6269
* @throws InvalidMappingException
6370
*/
64-
public function generate(GeneratorMetadata $metadata): Stmt\Class_
71+
public function generate(GeneratorMetadata $metadata): array
6572
{
6673
if ($this->disableGeneratedMapper) {
6774
throw new InvalidMappingException('No mapper found for source ' . $metadata->mapperMetadata->source . ' and target ' . $metadata->mapperMetadata->target);
6875
}
6976

70-
return (new Builder\Class_($metadata->mapperMetadata->className))
77+
$statements = [];
78+
if ($this->declareStrictTypes) {
79+
// @phpstan-ignore argument.type
80+
$statements[] = new Stmt\Declare_([create_declare_item('strict_types', create_scalar_int(1))]);
81+
}
82+
$statements[] = (new Builder\Class_($metadata->mapperMetadata->className))
7183
->makeFinal()
7284
->extend(GeneratedMapper::class)
7385
->addStmt($this->constructorMethod($metadata))
7486
->addStmt($this->mapMethod($metadata))
7587
->addStmt($this->registerMappersMethod($metadata))
7688
->getNode();
89+
90+
return $statements;
7791
}
7892

7993
/**

src/Loader/EvalLoader.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ public function __construct(
3131

3232
public function loadClass(MapperMetadata $mapperMetadata): void
3333
{
34-
$class = $this->generator->generate($this->metadataFactory->getGeneratorMetadata($mapperMetadata->source, $mapperMetadata->target));
35-
36-
eval($this->printer->prettyPrint([$class]));
34+
eval($this->printer->prettyPrint($this->generator->generate(
35+
$this->metadataFactory->getGeneratorMetadata($mapperMetadata->source, $mapperMetadata->target)
36+
)));
3737
}
3838

3939
public function buildMappers(MetadataRegistry $registry): bool

src/Loader/FileLoader.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,9 @@ public function createGeneratedMapper(MapperMetadata $mapperMetadata): string
7878
$className = $mapperMetadata->className;
7979
$classPath = $this->directory . \DIRECTORY_SEPARATOR . $className . '.php';
8080

81-
$generatorMetadata = $this->metadataFactory->getGeneratorMetadata($mapperMetadata->source, $mapperMetadata->target);
82-
$classCode = $this->printer->prettyPrint([$this->generator->generate($generatorMetadata)]);
81+
$classCode = $this->printer->prettyPrint($this->generator->generate(
82+
$this->metadataFactory->getGeneratorMetadata($mapperMetadata->source, $mapperMetadata->target)
83+
));
8384

8485
$this->write($classPath, "<?php\n\n" . $classCode . "\n");
8586

src/php-parser.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,19 @@ function create_expr_array_item(Expr $value, Expr $key = null, bool $byRef = fal
4343

4444
return new $class($value, $key, $byRef, $attributes, $unpack);
4545
}
46+
47+
/**
48+
* Constructs a declare key=>value pair node.
49+
*
50+
* @param string|Node\Identifier $key Key
51+
* @param Expr $value Value
52+
* @param array<string, mixed> $attributes Additional attributes
53+
*
54+
* @internal
55+
*/
56+
function create_declare_item($key, Expr $value, array $attributes = []): Node\DeclareItem|Node\Stmt\DeclareDeclare
57+
{
58+
$class = class_exists(Node\DeclareItem::class) ? Node\DeclareItem::class : Node\Stmt\DeclareDeclare::class;
59+
60+
return new $class($key, $value, $attributes);
61+
}

tests/AutoMapperTest.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,15 @@ public function testNoAutoRegister(): void
785785
$automapper->getMapper(Fixtures\User::class, Fixtures\UserDTO::class);
786786
}
787787

788+
public function testStrictTypes(): void
789+
{
790+
$this->expectException(\TypeError::class);
791+
792+
$automapper = AutoMapper::create(new Configuration(strictTypes: true, classPrefix: 'StrictTypes_'));
793+
$data = ['foo' => 1.1];
794+
$automapper->map($data, Fixtures\IntDTO::class);
795+
}
796+
788797
public function testWithMixedArray(): void
789798
{
790799
$user = new Fixtures\User(1, 'yolo', '13');

tests/Fixtures/IntDTO.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace AutoMapper\Tests\Fixtures;
6+
7+
readonly class IntDTO
8+
{
9+
public function __construct(
10+
public int $foo,
11+
) {
12+
}
13+
}

0 commit comments

Comments
 (0)