CuyZ / Valinor

PHP library that helps to map any input into a strongly-typed value object structure.

Home Page:https://valinor.cuyz.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Valinor parser crash on @immutable annotation

alaerock opened this issue · comments

With the new released version 1.6.1, Valinor crash when a class contains the @immutable annotation, get error:

   AssertionError 

  assert(!$this->done())

  at vendor/cuyz/valinor/src/Type/Parser/Lexer/TokenStream.php:30
     26▕ 
     27▕     /** @phpstan-impure */
     28▕     public function read(): Type
     29▕     {
  ➜  30▕         assert(! $this->done());
     31▕ 
     32▕         $token = $this->forward();
     33▕ 
     34▕         assert($token instanceof TraversingToken);

  1   vendor/cuyz/valinor/src/Type/Parser/Lexer/TokenStream.php:30

  2   vendor/cuyz/valinor/src/Type/Parser/LexingParser.php:23
      CuyZ\Valinor\Type\Parser\Lexer\TokenStream::read()

  3   vendor/cuyz/valinor/src/Definition/Repository/Reflection/ReflectionClassDefinitionRepository.php:174
      CuyZ\Valinor\Type\Parser\LexingParser::parse("")

  4   vendor/cuyz/valinor/src/Definition/Repository/Reflection/ReflectionClassDefinitionRepository.php:129
      CuyZ\Valinor\Definition\Repository\Reflection\ReflectionClassDefinitionRepository::localTypeAliases(Object(CuyZ\Valinor\Type\Types\NativeClassType))

  5   vendor/cuyz/valinor/src/Definition/Repository/Reflection/ReflectionClassDefinitionRepository.php:81
      CuyZ\Valinor\Definition\Repository\Reflection\ReflectionClassDefinitionRepository::typeResolver(Object(CuyZ\Valinor\Type\Types\NativeClassType), Object(ReflectionClass))

  6   [internal]:0
      CuyZ\Valinor\Definition\Repository\Reflection\ReflectionClassDefinitionRepository::CuyZ\Valinor\Definition\Repository\Reflection\{closure}(Object(ReflectionProperty))
  7   vendor/cuyz/valinor/src/Definition/Repository/Reflection/ReflectionClassDefinitionRepository.php:79

  8   vendor/cuyz/valinor/src/Definition/Repository/Reflection/ReflectionClassDefinitionRepository.php:67
      CuyZ\Valinor\Definition\Repository\Reflection\ReflectionClassDefinitionRepository::properties(Object(CuyZ\Valinor\Type\Types\NativeClassType))

  9   vendor/cuyz/valinor/src/Definition/Repository/Cache/CacheClassDefinitionRepository.php:31
      CuyZ\Valinor\Definition\Repository\Reflection\ReflectionClassDefinitionRepository::for(Object(CuyZ\Valinor\Type\Types\NativeClassType))

  10  vendor/cuyz/valinor/src/Mapper/Tree/Builder/InterfaceNodeBuilder.php:47
      CuyZ\Valinor\Definition\Repository\Cache\CacheClassDefinitionRepository::for(Object(CuyZ\Valinor\Type\Types\NativeClassType))

  11  vendor/cuyz/valinor/src/Mapper/Tree/Builder/CasterProxyNodeBuilder.php:24
      CuyZ\Valinor\Mapper\Tree\Builder\InterfaceNodeBuilder::build(Object(CuyZ\Valinor\Mapper\Tree\Shell), Object(CuyZ\Valinor\Mapper\Tree\Builder\RootNodeBuilder))

  12  vendor/cuyz/valinor/src/Mapper/Tree/Builder/IterableNodeBuilder.php:26
      CuyZ\Valinor\Mapper\Tree\Builder\CasterProxyNodeBuilder::build(Object(CuyZ\Valinor\Mapper\Tree\Shell), Object(CuyZ\Valinor\Mapper\Tree\Builder\RootNodeBuilder))

  13  vendor/cuyz/valinor/src/Mapper/Tree/Builder/StrictNodeBuilder.php:36
      CuyZ\Valinor\Mapper\Tree\Builder\IterableNodeBuilder::build(Object(CuyZ\Valinor\Mapper\Tree\Shell), Object(CuyZ\Valinor\Mapper\Tree\Builder\RootNodeBuilder))

  14  vendor/cuyz/valinor/src/Mapper/Tree/Builder/ErrorCatcherNodeBuilder.php:33
      CuyZ\Valinor\Mapper\Tree\Builder\StrictNodeBuilder::build(Object(CuyZ\Valinor\Mapper\Tree\Shell), Object(CuyZ\Valinor\Mapper\Tree\Builder\RootNodeBuilder))

  15  vendor/cuyz/valinor/src/Mapper/Tree/Builder/RootNodeBuilder.php:16
      CuyZ\Valinor\Mapper\Tree\Builder\ErrorCatcherNodeBuilder::build(Object(CuyZ\Valinor\Mapper\Tree\Shell), Object(CuyZ\Valinor\Mapper\Tree\Builder\RootNodeBuilder))

  16  vendor/cuyz/valinor/src/Mapper/TypeTreeMapper.php:44
      CuyZ\Valinor\Mapper\Tree\Builder\RootNodeBuilder::build(Object(CuyZ\Valinor\Mapper\Tree\Shell))

That seems to be happend in /src/Definition/Repository/Reflection/ReflectionClassDefinitionRepository.php#L163-L183

    private function localTypeAliases(ClassType $type): array
    {
        $reflection = Reflection::class($type->className());
        $rawTypes = DocParser::localTypeAliases($reflection);

        $typeParser = $this->typeParser($type);

        $types = [];

        foreach ($rawTypes as $name => $raw) {
            try {
                $types[$name] = $typeParser->parse($raw);
            } catch (InvalidType $exception) {
                $raw = trim($raw);

                $types[$name] = UnresolvableType::forLocalAlias($raw, $name, $type, $exception);
            }
        }

        return $types;
    }

typeParser->parse($raw) get am empty string because $rawTypes for immutable is an array of empty string ['immutable' => ''] .

The only way actually is to remove @immutable from affected class/DTO

Hi @alaerock thanks for the report. I think this was fixed by #437, could you try on dev-master to see if the issue is gone?

Feel free to reopen the issue if the problem persists.

FYI I'll publish a new release soon so you can easily update the lib.

Thanks @romm, dev-master worked as expected, Perfect 👌

Version 1.7.0 has just been released! Enjoy. 😎