Skip to content

Commit

Permalink
feat(exceptions): better exception naming, add interface to group all…
Browse files Browse the repository at this point in the history
… exceptions (#118)

This implement the following pattern : 

* All exceptions throw by the lib implement the `AutoMapperException`
interface
 * Split exceptions in 3 categories : 
   * MetadataException : happens when loading metadata
   * CompileException : happens when generating code
   * RuntimeException : happens when executing the mapping
  • Loading branch information
Korbeil authored May 6, 2024
2 parents 1b23ffc + aa758bf commit 10ed913
Show file tree
Hide file tree
Showing 20 changed files with 42 additions and 35 deletions.
4 changes: 2 additions & 2 deletions src/AutoMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace AutoMapper;

use AutoMapper\Exception\NoMappingFoundException;
use AutoMapper\Exception\InvalidMappingException;
use AutoMapper\Generator\MapperGenerator;
use AutoMapper\Generator\Shared\ClassDiscriminatorResolver;
use AutoMapper\Loader\ClassLoaderInterface;
Expand Down Expand Up @@ -109,7 +109,7 @@ public function map(array|object $source, string|array|object $target, array $co
}

if ('array' === $sourceType && 'array' === $targetType) {
throw new NoMappingFoundException('Cannot map this value, both source and target are array.');
throw new InvalidMappingException('Cannot map this value, both source and target are array.');
}

return $this->getMapper($sourceType, $targetType)->map($source, $context);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
/**
* @author Joel Wurtz <[email protected]>
*/
final class NoMappingFoundException extends RuntimeException
interface AutoMapperException
{
}
2 changes: 1 addition & 1 deletion src/Exception/BadMapDefinitionException.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
/**
* @author Joel Wurtz <[email protected]>
*/
final class BadMapDefinitionException extends RuntimeException
final class BadMapDefinitionException extends MetadataException
{
}
2 changes: 1 addition & 1 deletion src/Exception/CompileException.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
/**
* @author Joel Wurtz <[email protected]>
*/
final class CompileException extends RuntimeException
final class CompileException extends \LogicException implements AutoMapperException
{
}
2 changes: 1 addition & 1 deletion src/Exception/InvalidArgumentException.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
/**
* @author Baptiste Leduc <[email protected]>
*/
final class InvalidArgumentException extends \InvalidArgumentException
final class InvalidArgumentException extends \InvalidArgumentException implements AutoMapperException
{
}
2 changes: 1 addition & 1 deletion src/Exception/InvalidMappingException.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
/**
* @author Joel Wurtz <[email protected]>
*/
final class InvalidMappingException extends RuntimeException
final class InvalidMappingException extends MetadataException
{
}
2 changes: 1 addition & 1 deletion src/Exception/LogicException.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
/**
* @author Baptiste Leduc <[email protected]>
*/
final class LogicException extends \LogicException
final class LogicException extends \LogicException implements AutoMapperException
{
}
9 changes: 9 additions & 0 deletions src/Exception/MetadataException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

declare(strict_types=1);

namespace AutoMapper\Exception;

class MetadataException extends \RuntimeException implements AutoMapperException
{
}
2 changes: 1 addition & 1 deletion src/Exception/MissingConstructorArgumentsException.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace AutoMapper\Exception;

final class MissingConstructorArgumentsException extends \RuntimeException
final class MissingConstructorArgumentsException extends RuntimeException
{
/**
* @param string[] $missingArguments
Expand Down
5 changes: 1 addition & 4 deletions src/Exception/RuntimeException.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@

namespace AutoMapper\Exception;

/**
* @author Joel Wurtz <[email protected]>
*/
class RuntimeException extends \RuntimeException
class RuntimeException extends \RuntimeException implements AutoMapperException
{
}
4 changes: 2 additions & 2 deletions src/Extractor/ReadAccessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public function getExpression(Expr\Variable $input): Expr
/*
* Create method call argument to read value from context and throw exception if not found
*
* $context['map_to_accessor_parameter']['some_key'] ?? throw new \InvalidArgumentException('error message');
* $context['map_to_accessor_parameter']['some_key'] ?? throw new InvalidArgumentException('error message');
*/
$methodCallArguments[] = new Arg(
new Expr\BinaryOp\Coalesce(
Expand All @@ -75,7 +75,7 @@ public function getExpression(Expr\Variable $input): Expr
),
new Expr\Throw_(
new Expr\New_(
new Name\FullyQualified(\InvalidArgumentException::class),
new Name\FullyQualified(InvalidArgumentException::class),
[
new Arg(
new Scalar\String_(
Expand Down
4 changes: 2 additions & 2 deletions src/Generator/CreateTargetStatementsGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace AutoMapper\Generator;

use AutoMapper\Exception\LogicException;
use AutoMapper\Exception\CompileException;
use AutoMapper\Exception\MissingConstructorArgumentsException;
use AutoMapper\Generator\Shared\CachedReflectionStatementsGenerator;
use AutoMapper\Generator\Shared\DiscriminatorStatementsGenerator;
Expand Down Expand Up @@ -323,6 +323,6 @@ private function getValueAsExpr(mixed $value): Expr
return $expr->expr;
}

throw new LogicException('Cannot extract expr from ' . var_export($value, true));
throw new CompileException('Cannot extract expr from ' . var_export($value, true));
}
}
6 changes: 3 additions & 3 deletions src/Generator/MapperGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use AutoMapper\AutoMapperRegistryInterface;
use AutoMapper\Configuration;
use AutoMapper\Exception\CompileException;
use AutoMapper\Exception\NoMappingFoundException;
use AutoMapper\Exception\InvalidMappingException;
use AutoMapper\GeneratedMapper;
use AutoMapper\Generator\Shared\CachedReflectionStatementsGenerator;
use AutoMapper\Generator\Shared\ClassDiscriminatorResolver;
Expand Down Expand Up @@ -59,12 +59,12 @@ public function __construct(
* Generate Class AST given metadata for a mapper.
*
* @throws CompileException
* @throws NoMappingFoundException
* @throws InvalidMappingException
*/
public function generate(GeneratorMetadata $metadata): Stmt\Class_
{
if ($this->disableGeneratedMapper) {
throw new NoMappingFoundException('No mapper found for source ' . $metadata->mapperMetadata->source . ' and target ' . $metadata->mapperMetadata->target);
throw new InvalidMappingException('No mapper found for source ' . $metadata->mapperMetadata->source . ' and target ' . $metadata->mapperMetadata->target);
}

return (new Builder\Class_($metadata->mapperMetadata->className))
Expand Down
6 changes: 3 additions & 3 deletions src/Generator/PropertyConditionsGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace AutoMapper\Generator;

use AutoMapper\Exception\LogicException;
use AutoMapper\Exception\CompileException;
use AutoMapper\MapperContext;
use AutoMapper\Metadata\GeneratorMetadata;
use AutoMapper\Metadata\PropertyMetadata;
Expand Down Expand Up @@ -259,7 +259,7 @@ private function customCondition(GeneratorMetadata $metadata, PropertyMetadata $
}

if ($argumentsCount > 2) {
throw new LogicException('Callable condition must have 1 or 2 arguments required, but it has ' . $argumentsCount);
throw new CompileException('Callable condition must have 1 or 2 arguments required, but it has ' . $argumentsCount);
}
}

Expand Down Expand Up @@ -303,6 +303,6 @@ private function customCondition(GeneratorMetadata $metadata, PropertyMetadata $
return $expr->expr;
}

throw new LogicException('Cannot use callback or create expression language condition from expression "' . $propertyMetadata->if . "'");
throw new CompileException('Cannot use callback or create expression language condition from expression "' . $propertyMetadata->if . "'");
}
}
4 changes: 2 additions & 2 deletions src/Loader/FileLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace AutoMapper\Loader;

use AutoMapper\Exception\RuntimeException;
use AutoMapper\Exception\CompileException;
use AutoMapper\Generator\MapperGenerator;
use AutoMapper\Metadata\MapperMetadata;
use AutoMapper\Metadata\MetadataFactory;
Expand Down Expand Up @@ -129,7 +129,7 @@ private function write(string $file, string $contents): void
$fp = fopen($file, 'w');

if (false === $fp) {
throw new RuntimeException(sprintf('Could not open file "%s"', $file));
throw new CompileException(sprintf('Could not open file "%s"', $file));
}

if (flock($fp, LOCK_EX)) {
Expand Down
4 changes: 2 additions & 2 deletions src/MapperContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
namespace AutoMapper;

use AutoMapper\Exception\CircularReferenceException;
use AutoMapper\Exception\RuntimeException;
use AutoMapper\Exception\InvalidArgumentException;

/**
* Context for mapping.
Expand Down Expand Up @@ -327,7 +327,7 @@ public static function getForcedTimezone(array $context): ?\DateTimeZone
try {
return new \DateTimeZone($timezone);
} catch (\Exception $e) {
throw new RuntimeException("Invalid timezone \"$timezone\" passed to automapper context.", previous: $e);
throw new InvalidArgumentException("Invalid timezone \"$timezone\" passed to automapper context.", previous: $e);
}
}
}
4 changes: 2 additions & 2 deletions src/Transformer/ExpressionLanguageTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace AutoMapper\Transformer;

use AutoMapper\Exception\LogicException;
use AutoMapper\Exception\CompileException;
use AutoMapper\Generator\UniqueVariableScope;
use AutoMapper\Metadata\PropertyMetadata;
use PhpParser\Node\Expr;
Expand Down Expand Up @@ -34,6 +34,6 @@ public function transform(Expr $input, Expr $target, PropertyMetadata $propertyM
return [$expr->expr, []];
}

throw new LogicException('Cannot use callback or create expression language condition from expression "' . $this->expression . "'");
throw new CompileException('Cannot use callback or create expression language condition from expression "' . $this->expression . "'");
}
}
4 changes: 2 additions & 2 deletions src/Transformer/FixedValueTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace AutoMapper\Transformer;

use AutoMapper\Exception\LogicException;
use AutoMapper\Exception\CompileException;
use AutoMapper\Generator\UniqueVariableScope;
use AutoMapper\Metadata\PropertyMetadata;
use PhpParser\Node\Expr;
Expand Down Expand Up @@ -34,6 +34,6 @@ public function transform(Expr $input, Expr $target, PropertyMetadata $propertyM
return [$expr->expr, []];
}

throw new LogicException('Cannot create php code from value ' . json_encode($this->value));
throw new CompileException('Cannot create php code from value ' . json_encode($this->value));
}
}
6 changes: 3 additions & 3 deletions tests/AutoMapperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
use AutoMapper\ConstructorStrategy;
use AutoMapper\Event\PropertyMetadataEvent;
use AutoMapper\Exception\CircularReferenceException;
use AutoMapper\Exception\InvalidMappingException;
use AutoMapper\Exception\MissingConstructorArgumentsException;
use AutoMapper\Exception\NoMappingFoundException;
use AutoMapper\Exception\ReadOnlyTargetException;
use AutoMapper\MapperContext;
use AutoMapper\Provider\EarlyReturn;
Expand Down Expand Up @@ -769,15 +769,15 @@ public function testDiscriminator(): void

public function testInvalidMappingBothArray(): void
{
self::expectException(NoMappingFoundException::class);
$this->expectException(InvalidMappingException::class);

$data = ['test' => 'foo'];
$array = $this->autoMapper->map($data, 'array');
}

public function testNoAutoRegister(): void
{
self::expectException(NoMappingFoundException::class);
$this->expectException(InvalidMappingException::class);

$automapper = AutoMapper::create(new Configuration(autoRegister: false, classPrefix: 'NoAutoRegister_'));
$automapper->getMapper(Fixtures\User::class, Fixtures\UserDTO::class);
Expand Down
3 changes: 2 additions & 1 deletion tests/MapperContextTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace AutoMapper\Tests;

use AutoMapper\Exception\CircularReferenceException;
use AutoMapper\Exception\InvalidArgumentException;
use AutoMapper\MapperContext;
use PHPUnit\Framework\TestCase;

Expand Down Expand Up @@ -159,7 +160,7 @@ public static function forcedTimeZoneProvider(): iterable

public function testItThrowsExceptionWithInvalidTimeZone(): void
{
$this->expectException(\RuntimeException::class);
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Invalid timezone "foo" passed to automapper context.');

MapperContext::getForcedTimezone([MapperContext::DATETIME_FORCE_TIMEZONE => 'foo']);
Expand Down

0 comments on commit 10ed913

Please sign in to comment.