public function parse(\PHPParser_Node_Stmt_Function $node) { $function = new GlobalFunction(implode("\\", $node->namespacedName->parts)); $function->setImportedNamespaces($this->importedNamespaces); $function->setAstNode($node); $function->setReturnByRef($node->byRef); $function->setVariableParameters(false !== strpos($node->getDocComment(), '@jms-variable-parameters')); foreach ($this->paramParser->parse($node->params, 'Scrutinizer\\PhpAnalyzer\\Model\\FunctionParameter') as $param) { $function->addParameter($param); } return $function; }
public function persist(GlobalFunction $function, $packageVersionId) { $this->insertStmt->bindValue(1, $this->phpType->convertToDatabaseValue($function->getReturnType(), $this->platform)); $this->insertStmt->bindValue(2, $function->getName()); $this->insertStmt->bindValue(3, $function->isReturnByRef() ? 1 : 0, \PDO::PARAM_INT); $this->insertStmt->bindValue(4, $packageVersionId, \PDO::PARAM_INT); $this->insertStmt->bindValue(5, $function->hasVariableParameters() ? 1 : 0, \PDO::PARAM_INT); $this->insertStmt->execute(); $functionId = $this->con->lastInsertId(); $this->functionIdRef->setValue($function, $functionId); foreach ($function->getParameters() as $param) { $this->paramPersister->persist($param, $function); } foreach ($function->getInCallSites() as $callSite) { $this->callSitePersister->persist($callSite); } foreach ($function->getOutCallSites() as $callSite) { $this->callSitePersister->persist($callSite); } }
public function registerFunction(GlobalFunction $function) { $this->functions[strtolower($function->getName())] = $function; }
/** * @group definingExpr */ public function testDefiningExprIsCheckedForVariables() { $this->registry->registerFunction($function = new GlobalFunction('is_array')); $function->setReturnType($this->registry->getNativeType('boolean')); $ast = $this->analyzeAst('TypeInference/defining_expr_for_variable.php'); $this->assertTypedAst($ast, 'defining_expr_for_variable'); }
public function addFunction(GlobalFunction $function) { $function->setPackageVersion($this); $this->functions->set($function->getName(), $function); }
private function createFunction($name, $returnType = 'all') { $func = new GlobalFunction($name); $func->setReturnType($this->registry->resolveType($returnType)); return $func; }
public function getPreciserFunctionReturnTypeKnowingArguments(GlobalFunction $function, array $argValues, array $argTypes) { switch ($function->getName()) { case 'array_change_key_case': return $this->casePreserveIncomingArray($argTypes, 'false'); case 'array_chunk': case 'array_combine': // TODO break; case 'array_diff_assoc': case 'array_diff_key': case 'array_diff_uassoc': case 'array_diff_ukey': case 'array_diff': return $this->casePreserveIncomingArray($argTypes); case 'array_fill_keys': case 'array_fill': case 'array_filter': case 'array_flip': // TODO break; case 'array_intersect_assoc': case 'array_intersect_key': case 'array_intersect_uassoc': case 'array_intersect_ukey': case 'array_intersect': return $this->casePreserveIncomingArray($argTypes); case 'array_keys': return $this->caseArrayKeys($argTypes); case 'array_merge_recursive': case 'array_replace_recursive': case 'array_merge': case 'array_replace': return $this->caseArrayMergeReplace($argTypes, $function->getName()); case 'array_pad': return $this->caseArrayPad($argTypes); case 'array_pop': return $this->caseArrayPop($argTypes); case 'array_rand': // TODO break; case 'array_reverse': return $this->casePreserveIncomingArray($argTypes); case 'array_search': return $this->caseArraySearch($argTypes); case 'array_shift': return $this->caseElementTypeOrElse($argTypes, 'null'); case 'array_slice': case 'array_splice': return $this->casePreserveIncomingArray($argTypes); case 'array_udiff_assoc': case 'array_udiff_uassoc': case 'array_udiff': case 'array_uintersect_assoc': case 'array_uintersect_uassoc': case 'array_uintersect': return $this->casePreserveIncomingArray($argTypes); case 'array_unique': return $this->casePreserveIncomingArray($argTypes); case 'array_values': return $this->caseArrayValues($argTypes); case 'compact': // TODO break; case 'current': case 'end': case 'next': case 'pos': case 'prev': case 'reset': return $this->caseElementTypeOrElse($argTypes, 'false'); case 'each': case 'extract': case 'key': case 'range': // TODO break; } return null; }
public function addFunction(GlobalFunction $function) { $this->functions[$function->getName()] = $function; }
public function getPreciserFunctionReturnTypeKnowingArguments(GlobalFunction $function, array $argValues, array $argTypes) { switch ($function->getName()) { case 'version_compare': switch (count($argTypes)) { case 2: return $this->registry->getNativeType('integer'); case 3: return $this->registry->getNativeType('boolean'); default: return $this->registry->resolveType('integer|boolean'); } case 'unserialize': return $this->registry->getNativeType('unknown_checked'); case 'var_export': if (count($argValues) !== 2) { return null; } if (\Scrutinizer\PhpAnalyzer\PhpParser\NodeUtil::isBoolean($argValues[1]) && \Scrutinizer\PhpAnalyzer\PhpParser\NodeUtil::getBooleanValue($argValues[1]) === true) { return $this->registry->getNativeType('string'); } return null; case 'min': case 'max': switch (count($argTypes)) { case 0: return null; case 1: if ($argTypes[0]->isArrayType()) { return $argTypes[0]->getElementType(); } return null; default: // TODO: We could make this a bit smarter as some types are always considered // greater/smaller than other types. // See http://de1.php.net/manual/en/language.operators.comparison.php return $this->registry->createUnionType($argTypes); } case 'str_replace': case 'preg_filter': case 'preg_replace': case 'preg_replace_callback': if (isset($argTypes[2])) { if ($argTypes[2]->isUnknownType()) { return $this->registry->getNativeType('unknown'); } if ($argTypes[2]->isArrayType()) { return $this->registry->resolveType('array<string>'); } $nullableScalar = $this->registry->createNullableType($this->registry->getNativeType('scalar')); if ($argTypes[2]->isSubtypeOf($nullableScalar)) { return $this->registry->getNativeType('string'); } } return null; // Use the non-restricted type if we don't know. // Use the non-restricted type if we don't know. default: return null; } }