marcosh/php-type-checker

View on GitHub
src/Check/Parameter.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php

declare(strict_types=1);

namespace Marcosh\PhpTypeChecker\Check;

use phpDocumentor\Reflection\Type;
use phpDocumentor\Reflection\Types\Array_;
use phpDocumentor\Reflection\Types\Mixed;
use phpDocumentor\Reflection\Types\Object_;
use phpDocumentor\Reflection\Types\Self_;
use Roave\BetterReflection\Reflection\ReflectionParameter;

final class Parameter
{
    /**
     * @var ReflectionParameter
     */
    private $parameter;

    public function __construct(ReflectionParameter $parameter)
    {
        $this->parameter = $parameter;
    }

    /**
     * @return Type[]
     */
    private function docBlockTypes(): array
    {
        $docBlockTypes = [];

        try {
            $docBlockTypes = $this->parameter->getDocBlockTypes();
        } catch (\InvalidArgumentException $e) {
            // we need this here to prevent reflection-bocblock errors on @see invalid Fqsen
        }

        return $docBlockTypes;
    }

    public function typeIsMissing(): bool
    {
        return null === $this->parameter->getTypeHint() &&
            empty($this->docBlockTypes());
    }

    public function typeIsMissingWithDocBlock(): bool
    {
        return null === $this->parameter->getTypeHint() &&
            !empty($this->docBlockTypes()) &&
            !$this->docBlockTypes()[0] instanceof Mixed &&
            !$this->docBlockTypes()[0] instanceof Object_;
    }

    public function typeDoesNotCoincideWithDocBlock(): bool
    {
        $docBlockTypes = $this->docBlockTypes();

        return !empty($docBlockTypes) &&
            $this->parameter->getTypeHint() instanceof Type &&
            !in_array($this->parameter->getTypeHint(), $docBlockTypes, false) &&
            !($this->parameter->getTypeHint() instanceof Array_ && $docBlockTypes[0] instanceof Array_) &&
            !($this->parameter->getTypeHint() instanceof Self_ &&
                $docBlockTypes[0] instanceof Object_ &&
                $this->parameter->getDeclaringClass()->getName() === ltrim((string) $docBlockTypes[0]->getFqsen(), '\\')
            ) &&
            !($this->parameter->getTypeHint() instanceof Object_ &&
                $docBlockTypes[0] instanceof Self_ &&
                $this->parameter->getDeclaringClass()->getName() === ltrim((string) $this->parameter->getTypeHint()->getFqsen(), '\\')
            );
    }
}