code: private function getInjectHint(\ReflectionMethod $method, \ReflectionParameter $parameter)
      {
          // find the first injection hint for the given parameter
          $hint = Psi::it($this->reader->getMethodAnnotations($method))
              ->filter(new IsInstanceOf(Di\DiInjectHintAnnotation::class))
              ->filter(function (Di\DiInjectHintAnnotation $i) use ($parameter) {
                  return $i->getParameter() === $parameter->getName();
              })
              ->getFirst();
  
          if ($hint !== null) {
              return $hint;
          }
  
          // No hint is given. We do the default injection strategy.
          try {
              if ($parameter->getClass() === null) {
                  throw new \InvalidArgumentException(
                      "Cannot inject constructor-param '{$parameter->getName()}' into {$method->getDeclaringClass()->getName()}. " .
                      'The parameter does not have a an @Inject hint and it has no type-hint.'
                  );
              }
          } catch (\ReflectionException $e) {
              // We ignore not existing class errors. But why?
              // Well, it is very likely that the service to be injected does not yet exist and will be created by a code-generator, e.g. the storage.
          }
  
          return Di\Inject\ByType::create($parameter->getName(), Util::normalizeFqcn((string) $parameter->getType()));
      }
docs: Looks into the injection hints on the method to figure out what is to be injected for which parameter.
  
  @param \ReflectionMethod    $method
  @param \ReflectionParameter $parameter
  
  @return Di\DiInjectHintAnnotation