private function verifyReturnType(PhpType $type, \PHPParser_Node $node) { if (null === ($commentType = $this->parser->getTypeFromReturnAnnotation($node))) { if ($this->getSetting('ask_for_return_if_not_inferrable') && $type->isUnknownType()) { $this->phpFile->addComment($node->getLine(), Comment::warning('php_doc.return_type_not_inferrable', 'Please add a ``@return`` annotation.')); } return; } if (!$this->getSetting('return')) { return; } if (!$type->isSubtypeOf($commentType)) { if ($this->getSetting('suggest_more_specific_types') && $this->typeRegistry->getNativeType('array')->isSubtypeOf($type)) { $this->phpFile->addComment($this->getLineOfReturn($node), Comment::warning('php_doc.return_type_mismatch_with_generic_array', 'Should the return type not be ``%expected_type%``? Also, consider making the array more specific, something like ``array<String>``, or ``String[]``.', array('expected_type' => $type->getDocType($this->importedNamespaces)))); } else { $this->phpFile->addComment($this->getLineOfReturn($node), Comment::warning('php_doc.return_type_mismatch', 'Should the return type not be ``%expected_type%``?', array('expected_type' => $type->getDocType($this->importedNamespaces)))); } return; } if (!$this->getSetting('suggest_more_specific_types')) { return; } if (!$this->isMoreSpecificType($type, $commentType)) { if ($type->isAllType()) { $this->phpFile->addComment($this->getLineOfReturn($node), Comment::warning('php_doc.return_type_all_type_more_specific', 'Please define a more specific return type; maybe using a union like ``null|Object``, or ``string|array``.')); } else { if ($this->typeRegistry->getNativeType('array')->isSubtypeOf($type)) { $this->phpFile->addComment($this->getLineOfReturn($node), Comment::warning('php_doc.return_type_array_element_type', 'Please define the element type for the returned array (using ``array<SomeType>``, or ``SomeType[]``).')); } } return; } $this->phpFile->addComment($this->getLineOfReturn($node), Comment::warning('php_doc.return_type_more_specific', 'Consider making the return type a bit more specific; maybe use ``%actual_type%``.', array('actual_type' => $type->getDocType($this->importedNamespaces)))); }
private function traverseAssignList(\PHPParser_Node_Expr_AssignList $node, LinkedFlowScope $scope) { $scope = $this->traverse($node->expr, $scope); $exprType = $this->getType($node->expr); $isArray = $exprType->isArrayType(); $checkedUnknown = $this->typeRegistry->getNativeType('unknown_checked'); $castTypes = $this->commentParser->getTypesFromInlineComment($node->getDocComment()); foreach ($node->vars as $i => $var) { if (null === $var) { continue; } $newType = $isArray ? $exprType->getItemType($i)->getOrElse($checkedUnknown) : $checkedUnknown; $this->updateScopeForTypeChange($scope, $var, null, $newType, $castTypes); } return $scope; }
private function enterNode(\PHPParser_Node $node) { if (NodeUtil::isMethodContainer($node)) { $this->commentParser->setCurrentClassName(implode("\\", $node->namespacedName->parts)); $this->commentParser->setImportedNamespaces($this->importedNamespaces); $this->classParser->setImportedNamespaces($this->importedNamespaces); $class = $this->classParser->parse($node); $this->classFiles[$class] = $this->phpFile; if ($this->typeRegistry->hasClass($class->getName(), TypeRegistry::LOOKUP_NO_CACHE)) { $this->analyzer->logger->warning(sprintf('The class "%s" has been defined more than once (maybe as a fixture for code generation). Ignoring the second definition.', $class->getName())); return; } $this->typeRegistry->registerClass($class); } else { if ($node instanceof \PHPParser_Node_Stmt_Function) { $this->functionParser->setImportedNamespaces($this->importedNamespaces); $function = $this->functionParser->parse($node); if ($this->typeRegistry->hasFunction($functionName = $function->getName(), false)) { $this->analyzer->logger->warning(sprintf('The function "%s" has been defined more than once (probably conditionally). Ignoring the second definition.', $functionName)); return; } $this->typeRegistry->registerFunction($function); } else { if (NodeUtil::isConstantDefinition($node)) { assert($node instanceof \PHPParser_Node_Expr_FuncCall); if (!$node->args[0]->value instanceof \PHPParser_Node_Scalar_String) { return; } $constant = new GlobalConstant($node->args[0]->value->value); $constant->setAstNode($node); $constant->setPhpType($this->typeRegistry->getNativeType('unknown')); if (null !== ($type = $node->args[1]->value->getAttribute('type'))) { $constant->setPhpType($type); } if ($this->typeRegistry->hasConstant($constant->getName(), false)) { $this->analyzer->logger->warning(sprintf('The constant "%s" was defined more than once. Ignoring all but first definition.', $constant->getName())); return; } $this->typeRegistry->registerConstant($constant); } } } }