Skip to content

Commit

Permalink
Add validation for subtypes during compilation
Browse files Browse the repository at this point in the history
  • Loading branch information
olsavmic committed Sep 9, 2024
1 parent 20e366d commit 25ba92c
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 0 deletions.
19 changes: 19 additions & 0 deletions src/Compiler/Exception/CannotCompileMapperException.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use LogicException;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use ShipMonk\InputMapper\Compiler\Mapper\MapperCompiler;
use ShipMonk\InputMapper\Compiler\Mapper\Object\MapDiscriminatedObject;
use ShipMonk\InputMapper\Compiler\Validator\ValidatorCompiler;
use Throwable;

Expand All @@ -24,6 +25,24 @@ public static function withIncompatibleMapper(
return new self("Cannot compile mapper {$mapperCompilerClass}, because {$reason}", 0, $previous);
}

/**
* @template T of object
* @param MapDiscriminatedObject<T> $mapperCompiler
*/
public static function withIncompatibleSubtypeMapper(
MapDiscriminatedObject $mapperCompiler,
MapperCompiler $subtypeMapperCompiler,
?Throwable $previous = null
): self
{
$mapperOutputType = $mapperCompiler->getOutputType();
$subtypeMapperCompilerClass = $subtypeMapperCompiler::class;
$subtypeMapperOutputType = $subtypeMapperCompiler->getOutputType();

$reason = "its output type '{$subtypeMapperOutputType}' is not super type of '{$mapperOutputType}'";
return new self("Cannot compile mapper {$subtypeMapperCompilerClass} as subtype (#[Discriminator]) mapper, because {$reason}", 0, $previous);
}

public static function withIncompatibleValidator(
ValidatorCompiler $validatorCompiler,
MapperCompiler $mapperCompiler,
Expand Down
8 changes: 8 additions & 0 deletions src/Compiler/Mapper/Object/MapDiscriminatedObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use ShipMonk\InputMapper\Compiler\CompiledExpr;
use ShipMonk\InputMapper\Compiler\Exception\CannotCompileMapperException;
use ShipMonk\InputMapper\Compiler\Mapper\GenericMapperCompiler;
use ShipMonk\InputMapper\Compiler\Mapper\MapperCompiler;
use ShipMonk\InputMapper\Compiler\Mapper\Scalar\MapString;
use ShipMonk\InputMapper\Compiler\Mapper\Wrapper\MapNullable;
use ShipMonk\InputMapper\Compiler\Php\PhpCodeBuilder;
use ShipMonk\InputMapper\Compiler\Type\GenericTypeParameter;
use ShipMonk\InputMapper\Compiler\Type\PhpDocTypeUtils;
use ShipMonk\InputMapper\Runtime\Exception\MappingFailedException;
use function array_keys;
use function count;
Expand Down Expand Up @@ -43,6 +45,12 @@ public function __construct(

public function compile(Expr $value, Expr $path, PhpCodeBuilder $builder): CompiledExpr
{
foreach ($this->subtypeCompilers as $subtypeCompiler) {
if (!PhpDocTypeUtils::isSubTypeOf($subtypeCompiler->getOutputType(), $this->getOutputType())) {
throw CannotCompileMapperException::withIncompatibleSubtypeMapper($this, $subtypeCompiler);
}
}

$statements = [
$builder->if($builder->not($builder->funcCall($builder->importFunction('is_array'), [$value])), [
$builder->throw(
Expand Down

0 comments on commit 25ba92c

Please sign in to comment.