annotations icon indicating copy to clipboard operation
annotations copied to clipboard

Assumption about value type causes parsing error

Open rkeet opened this issue 7 years ago • 1 comments
trafficstars

https://github.com/doctrine/annotations/blob/9419fd5b220de184c9501a16ede49a029b94d482/lib/Doctrine/Common/Annotations/DocParser.php#L810

Line #810 is the elseif (...) line

        if ($type['type'] === 'array') {
            // handle the case of a single value
            if ( ! is_array($values[$property])) {
                $values[$property] = array($values[$property]);
            }
            // checks if the attribute has array type declaration, such as "array<string>"
            if (isset($type['array_type'])) {
                foreach ($values[$property] as $item) {
                    if (gettype($item) !== $type['array_type'] && !$item instanceof $type['array_type']) {
                        throw AnnotationException::attributeTypeError($property, $originalName, $this->context, 'either a(n) '.$type['array_type'].', or an array of '.$type['array_type'].'s', $item);
                    }
                }
            }
        } elseif (gettype($values[$property]) !== $type['type'] && !$values[$property] instanceof $type['type']) {
            throw AnnotationException::attributeTypeError($property, $originalName, $this->context, 'a(n) '.$type['value'], $values[$property]);
        }

Assumes type annotation of value to be done like so:

@var string

However, you could do something like

@var null|string

Because the elseif() only does string comparisons, using the latter notation will always fail.


Small use case

/**
 * @var string
 * @ORM\Column(name="api_pass", type="text", nullable=false)
 * @Encrypted(spices="credential")
 */
protected $apiPass;

Here the @Encrypted is custom Annotation. I'll leave all options out of the scope but it's defined like so:

/**
 * @Annotation
 * @Target("PROPERTY")
 */
class Encrypted
{
    /**
     * @var string
     */
    public $spices;
    
    // getters/setters + other options
}

However, I would like to define the property like so:

/**
 * @var null|string
 */
public $spices;

The first passes, the second fails because an assumption is done that the @var declaration always contains just one type.


P.s. - I've seen comments before about creating a test case, PR and PhpUnit tested code and such. If you have any docs on "how-to" all that, I'll give creating that a shot.

rkeet avatar Mar 21 '18 14:03 rkeet

Hi again @rkeet :) Thanks for participating and creating issues for us to look at. You can find information on contributing here http://www.doctrine-project.org/contribute.html

jwage avatar Mar 22 '18 02:03 jwage