We will inject interface implementation.

@param $reflectionParam

@return array
545456
public function interfaceInjection($reflectionParam)
    {
        $constructorArgs = null;
        /*
         | Check if constructor dependency is Interface or not.
         | if interface we will check definition for the interface
         | and inject into controller constructor
         */
        if (!$reflectionParam->IsInstantiable() && $reflectionParam->isInterface()) {
            $aliases = $this->definition['definition.config']['register.alias'];
            $interface = Inflector::getClassName($reflectionParam->getName());

            if (array_key_exists($interface, $aliases)) {
                $constructorArgs = $this->container->makeInstance($aliases[$interface]);
            }
        }

        return $constructorArgs;
    }
810089
private function getBindParams(string $className, string $methodName, \Throwable $throwable)
    {
        $reflectClass  = new \ReflectionClass($className);
        $reflectMethod = $reflectClass->getMethod($methodName);
        $reflectParams = $reflectMethod->getParameters();
        $response      = RequestContext::getResponse();
        $request       = RequestContext::getRequest();

        // binding params
        $bindParams = [];
        foreach ($reflectParams as $key => $reflectParam) {
            $reflectType = $reflectParam->getType();

            // undefined type of the param
            if ($reflectType === null) {
                $bindParams[$key] = null;
                continue;
            }

            /**
             * defined type of the param
             * @notice \ReflectType::getName() is not supported in PHP 7.0, that is why use __toString()
             */
            $type = $reflectType->__toString();
            if ($type === Request::class) {
                $bindParams[$key] = $request;
            } elseif ($type == Response::class) {
                $bindParams[$key] = $response;
            } elseif ($type == \Throwable::class) {
                $bindParams[$key] = $throwable;
            } else {
                $bindParams[$key] = null;
            }
        }

        return $bindParams;
    }
355014
protected function paramDetails(\ReflectionParameter $param) {
        return ' ' . ($param->isOptional() ? '[' : '') . '--' . $param->getName() . ($param->isOptional() ? '=' . ($param->isDefaultValueConstant() ? $param->getDefaultValueConstantName() : '"' . $param->getDefaultValue() . '"') : '') . ($param->isOptional() ? ']' : '');
    }
865288
private function getReflectionParamData(\ReflectionParameter $param)
    {
        $param_type = self::getPsalmTypeFromReflectionType($param->getType());
        $param_name = (string)$param->getName();

        $is_optional = (bool)$param->isOptional();

        return new FunctionLikeParameter(
            $param_name,
            (bool)$param->isPassedByReference(),
            $param_type,
            null,
            null,
            $is_optional,
            $param_type->isNullable(),
            $param->isVariadic()
        );
    }
455198
public static function getReturnType($param)
    {
        $lexer = new Lexer($param);

        // A dummy parser is used for error reporting.
        $type = DataType::parse(new Parser(), $lexer->list);

        if ($type === null) {
            return [
                '',
                '',
                '',
                '',
                '',
            ];
        }

        $options = [];
        foreach ($type->options->options as $opt) {
            $options[] = is_string($opt) ? $opt : $opt['value'];
        }

        return [
            '',
            '',
            $type->name,
            implode(',', $type->parameters),
            implode(' ', $options),
        ];
    }
151463
protected function getParamType(\ReflectionClass $class, \ReflectionParameter $param): string
    {
        $this->assertType($class->getName(), $param->getName(), $param->getType());

        return $param->getType()->getName();
    }
517680
protected function matchArguments(
        array $reflectionParameters,
        array $providedArguments
    )/*# : array */ {
        // result
        $resolvedArguments = [];
        foreach ($reflectionParameters as $i => $param) {
            $class = $param->getClass();

            if ($this->isTypeMatched($class, $providedArguments)) {
                $resolvedArguments[$i] = array_shift($providedArguments);
            } elseif ($this->isRequiredClass($param, $providedArguments)) {
                $resolvedArguments[$i] = $this->getObjectByClass($class->getName());
            }
        }
        return array_merge($resolvedArguments, $providedArguments);
    }
1367886
private function getFunctionArguments(\ReflectionFunctionAbstract $reflection, $value, $fields)
    {
        $arguments = [];
        if ($reflection->getNumberOfParameters() == 1) {
            $arguments[] = $value;
        } elseif ($reflection->getNumberOfParameters() == 2) {
            $arguments[] = $value;
            $arguments[] = $fields;
        }
        return $arguments;
    }
255428
private function getDependencyInjectionParameter(\ReflectionParameter $reflectionParameter, array &$arguments, array $argumentsClass)
    {
        // Parameter name in arguments list?
        if (array_key_exists($reflectionParameter->getName(), $arguments)) {
            $parameter = $arguments[$reflectionParameter->getName()];

            // Remove argument to do not use again
            unset($arguments[$reflectionParameter->getName()]);

            return $parameter;
        }

        // Parameter is class?
        if ($reflectionParameter->hasType() && !$reflectionParameter->getType()->isBuiltin()) {
            // Parameter type is in arguments class?
            if (array_key_exists($reflectionParameter->getType()->getName(), $argumentsClass)) {
                $argumentsFound = $argumentsClass[$reflectionParameter->getType()->getName()];

                // Argument is already available?
                if (($argumentFound = reset($argumentsFound)) !== false && isset($arguments[$argumentFound])) {
                    $parameter = $arguments[$argumentFound];

                    // Remove argument to do not use again
                    unset($arguments[$argumentFound]);

                    return $parameter;
                }
            }

            if (!is_null($this->getContainer())) {
                // Service exists with the same name and same type?
                if ($this->getContainer()->has($reflectionParameter->getName())
                    && is_a($service = $this->getContainer()->get($reflectionParameter->getName()), $reflectionParameter->getType()->getName())) {
                    return $service;
                }

                // Service exists with same class?
                if ($this->getContainer()->has($reflectionParameter->getType()->getName())
                    && is_a($service = $this->getContainer()->get($reflectionParameter->getType()->getName()), $reflectionParameter->getType()->getName())) {
                    return $service;
                }
            }
        }

        if ($reflectionParameter->isDefaultValueAvailable()) {
            try {
                return $reflectionParameter->getDefaultValue();
            } catch (\Exception $e) {
                throw new InstantiatorException(sprintf('Unable to get default value of parameter "%s"', $reflectionParameter->getName()));
            }
        } else {
            if ($reflectionParameter->allowsNull()) {
                return null;
            } else {
                throw new InstantiatorException(sprintf('Missing parameter "%s"', $reflectionParameter->getName()));
            }
        }
    }
652022
public function call($param = null)
    {
        // get the class within the correct namespace
        // initiate object
        $object = $this->prepareObject(new $this->class());

        $return    = new \SplFixedArray(2);
        $return[1] = $object;

        if (!empty($this->method)) {
            if (!empty($param) && !empty($this->param)) {
                $return[0] = $object->{$this->method}(array_merge((array)$this->param, (array)$param));

                return $return;
            }
            $return[0] = $object->{$this->method}();

            return $return;
        }

        return $return;
    }
1019462
protected final function getArg(ReflectionParameter $param, CacheInterface $cache = null)
   {
       $match = [];
       $delimiter = "@param";
       $type = "string|int|bool|float|array|callable";
       preg_match(
           '/^.+' . $delimiter . '\s+(?!' . $type
         . ')([A-Za-z0-9\\\]{1,})\s+\$'
         . $param->name . '/m',
           $param->getDeclaringFunction()->getDocComment(),
           $match);
       if (array_key_exists(1, $match)) {
           return $this->resolve($match[1], $cache);
       }
   }
931622
final protected function throwIfArray(ReflectionParameter $param, ?string $type): void
    {
        if ($type === 'array') {
            throw new Exception('The parameter `$' . $param->getName() . '` on method ' . $this->getMethodFullName($param->getDeclaringFunction()) . ' is type hinted as `array` and is not overridden via `@API\Argument` annotation. Either change the type hint or specify the type with `@API\Argument` annotation.');
        }
    }
1280448
private function getArgumentByName(\ReflectionParameter $parameter, $parameters)
    {
        foreach ($parameters as $name => $item) {
            $paramName = $parameter->getName();
            if ($name === $paramName) {
                return $item;
            }
        }

        return null;
    }
543885
private function getInjector(\ReflectionClass $reflection): InjectorInterface
    {
        if (isset($this->injectors[$reflection->getName()])) {
            //Stated directly
            $injector = $this->get($this->injectors[$reflection->getName()]);
        } else {
            //Auto-injection!
            $injector = $this->get($reflection->getConstant('INJECTOR'));
        }

        if (!$injector instanceof InjectorInterface) {
            throw new InjectionException(sprintf(
                "Class '%s' must be an instance of InjectorInterface for '%s'",
                get_class($injector),
                $reflection->getName()
            ));
        }

        return $injector;
    }
898760
private function canInject(
        \ReflectionParameter $parameter,
        MapInterface $properties
    ): bool {
        if (
            !$parameter->allowsNull() &&
            !$properties->contains($parameter->name)
        ) {
            return false;
        } else if (
            $parameter->allowsNull() &&
            !$properties->contains($parameter->name)
        ) {
            return false;
        }

        $property = $properties->get($parameter->name);

        if ($parameter->hasType()) {
            $type = $parameter->getType();

            if ($type->isBuiltin()) {
                return (string) $type === gettype($property);
            } else if (!is_object($property)) {
                return false;
            }

            $refl = new \ReflectionObject($property);
            $wishedClass = (string) $type;

            return get_class($property) === $wishedClass ||
                $refl->isSubClassOf($wishedClass);
        }

        return true;
    }
972680
private function getParameterValue(\ReflectionParameter $parameter, $value)
    {
        $class = $parameter->getClass();

        if ($class) {
            $className = $class->getName();

            if ($parameter->isVariadic()) {
                $result = [];

                foreach ($value as $subValue) {
                    $result[] = $this->getObject($className, $subValue);
                }

                return $result;
            }

            return $this->getObject($className, $value);
        }

        return $value;
    }
912370
public function resolveMethodDependencies(array $parameters, ReflectionFunctionAbstract $reflector)
    {
        foreach ($reflector->getParameters() as $key => $parameter) {
            $instance = $this->transformDependency($parameter, $parameters);

            if (!is_null($instance)) {
                $this->spliceIntoParameters($parameters, $key, $instance);
            }
        }

        return $parameters;
    }