private function inferTypesForParameter(Parameter $param, AbstractFunction $function, Clazz $clazz = null) { if (($type = $param->getPhpType()) && !$type->isUnknownType() && !$type->isNullType() && !$type->isFalse() && !$type->isAllType()) { return; } $allowsNull = $type && $type->isNullType(); if (null !== ($node = $param->getAstNode())) { $type = $this->parser->getTypeFromParamAnnotation($node, $param->getName()); // Check whether we can use the type of a overridden method. // We only do this if we find a parent method that has been defined // on an interface (I), or if we find an abstract method (II). if (null === $type && $function instanceof Method && null !== $clazz) { foreach ($this->findOverriddenMethodsForDocInheritance($function->getName(), $clazz) as $parentMethod) { if (null !== ($docType = $parentMethod->getParamDocType($param->getIndex()))) { $type = $this->parser->getType($docType); break; } } } } if (null === $type) { $type = $this->registry->getNativeType('unknown'); } else { if ($allowsNull) { $type = $this->registry->createNullableType($type); } } $param->setPhpType($type); if ($node) { $node->setAttribute('type', $type); } }
private function inferTypeForParameter(AbstractFunction $function, \Scrutinizer\PhpAnalyzer\Model\Parameter $param) { $index = $param->getIndex(); $types = array(); foreach ($function->getInCallSites() as $site) { $args = $site->getArgs(); if (!isset($args[$index])) { continue; } $argType = $args[$index]->getPhpType(); if ($argType->isUnknownType() || $argType->isNoType()) { continue; } $types[] = $argType; } if (null !== ($astNode = $param->getAstNode()) && null !== $astNode->default) { $defaultType = $astNode->default->getAttribute('type'); // The default type might be null for example if a constant is assigned // as a default value, and we could not determine the value of that constant. if (null !== $defaultType) { $types[] = $defaultType; } } return $this->refineTypeForAnnotation($this->registry->createUnionType($types)); }