Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[PropertyInfo] Incorrect handling of pseudo-types #44455

Closed
@EmilMassey

Description

@EmilMassey

Symfony version(s) affected

4.x, 5.x, 6.0

Description

Since static-analysis tools like PHPStan or Psalm became more popular, it is not uncommon to see usage of pseudo-type like:

/** @var non-empty-string */
public $foo;

Some pseudo-types are currently supported (see #43916 introducing list type) but others are not. We can add support for popular custom types used by PHPStan or phpDocumentor (see #44451) but there will always be less common pseudo-types which we are not aware of.

Handling of these cases is inconsistent between extractors and PhpDocExtractor has a bug where the first character of the pseudo-type is trimmed. That one bug is quite easy to fix, but I believe handling of custom, unknown types is overall broken and we should decide how we want to handle them.

How to reproduce

Tested on v6.0.0 tag:

class TestClass {
    /** @var non-empty-string */
    public $foo;

    /** @var some-other-custom-type */
    public $bar;
}

$extractor = new \Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor();
$fooType = $extractor->getTypes(TestClass::class, 'foo'); // $builtinType: object, $class: on-empty-string (first character trimmed)
$barType = $extractor->getTypes(TestClass::class, 'bar'); // NULL

$extractor = new \Symfony\Component\PropertyInfo\Extractor\PhpStanExtractor();
$fooType = $extractor->getTypes(TestClass::class, 'foo'); // $builtinType: object, $class: \non-empty-string (backslash prepended)
$barType = $extractor->getTypes(TestClass::class, 'bar'); // $builtinType: object, $class: \some-other-custom-type

Possible Solution

Expected result

  • pseudo-types shouldn't be automatically treated as objects
  • if the type cannot be correctly mapped to built-in type, getType() should return null or throw an exception
  • or the developer should be informed it is a pseudo-type and decide what to do with doctype
  • the doctype shouldn't be modified and returned as-is (i.e. some-other-custom-type and not \some-other-custom-type)
  • it would be perfect if the results were consistent between both extractors

Additional Context

The first character is trimmed due to bug in \Symfony\Component\PropertyInfo\Util\PhpDocTypeHelper. I believe there's assumption that the $docType is FQCN with backslash prefix but in case of /** @var non-empty-string */ it is passed as-is to the function.

// src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php

  // $docType: non-empty-string

    private function getPhpTypeAndClass(string $docType): array
    {
        // ...

        return ['object', substr($docType, 1)]; // substr to strip the namespace's `\`-prefix
    }

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions