in gen_stub.php [1082:1213]
function parseFunctionLike(
PrettyPrinterAbstract $prettyPrinter,
FunctionOrMethodName $name,
int $classFlags,
int $flags,
Node\FunctionLike $func,
?string $cond
): FuncInfo {
$comment = $func->getDocComment();
$paramMeta = [];
$aliasType = null;
$alias = null;
$isDeprecated = false;
$verify = true;
$docReturnType = null;
$docParamTypes = [];
if ($comment) {
$tags = parseDocComment($comment);
foreach ($tags as $tag) {
if ($tag->name === 'prefer-ref') {
$varName = $tag->getVariableName();
if (!isset($paramMeta[$varName])) {
$paramMeta[$varName] = [];
}
$paramMeta[$varName]['preferRef'] = true;
} else if ($tag->name === 'alias' || $tag->name === 'implementation-alias') {
$aliasType = $tag->name;
$aliasParts = explode("::", $tag->getValue());
if (count($aliasParts) === 1) {
$alias = new FunctionName(new Name($aliasParts[0]));
} else {
$alias = new MethodName(new Name($aliasParts[0]), $aliasParts[1]);
}
} else if ($tag->name === 'deprecated') {
$isDeprecated = true;
} else if ($tag->name === 'no-verify') {
$verify = false;
} else if ($tag->name === 'return') {
$docReturnType = $tag->getType();
} else if ($tag->name === 'param') {
$docParamTypes[$tag->getVariableName()] = $tag->getType();
}
}
}
$varNameSet = [];
$args = [];
$numRequiredArgs = 0;
$foundVariadic = false;
foreach ($func->getParams() as $i => $param) {
$varName = $param->var->name;
$preferRef = !empty($paramMeta[$varName]['preferRef']);
unset($paramMeta[$varName]);
if (isset($varNameSet[$varName])) {
throw new Exception("Duplicate parameter name $varName for function $name");
}
$varNameSet[$varName] = true;
if ($preferRef) {
$sendBy = ArgInfo::SEND_PREFER_REF;
} else if ($param->byRef) {
$sendBy = ArgInfo::SEND_BY_REF;
} else {
$sendBy = ArgInfo::SEND_BY_VAL;
}
if ($foundVariadic) {
throw new Exception("Error in function $name: only the last parameter can be variadic");
}
$type = $param->type ? Type::fromNode($param->type) : null;
if ($type === null && !isset($docParamTypes[$varName])) {
throw new Exception("Missing parameter type for function $name()");
}
if ($param->default instanceof Expr\ConstFetch &&
$param->default->name->toLowerString() === "null" &&
$type && !$type->isNullable()
) {
$simpleType = $type->tryToSimpleType();
if ($simpleType === null) {
throw new Exception(
"Parameter $varName of function $name has null default, but is not nullable");
}
}
$foundVariadic = $param->variadic;
$args[] = new ArgInfo(
$varName,
$sendBy,
$param->variadic,
$type,
isset($docParamTypes[$varName]) ? Type::fromPhpDoc($docParamTypes[$varName]) : null,
$param->default ? $prettyPrinter->prettyPrintExpr($param->default) : null
);
if (!$param->default && !$param->variadic) {
$numRequiredArgs = $i + 1;
}
}
foreach (array_keys($paramMeta) as $var) {
throw new Exception("Found metadata for invalid param $var of function $name");
}
$returnType = $func->getReturnType();
if ($returnType === null && $docReturnType === null && !$name->isConstructor() && !$name->isDestructor()) {
throw new Exception("Missing return type for function $name()");
}
$return = new ReturnInfo(
$func->returnsByRef(),
$returnType ? Type::fromNode($returnType) : null,
$docReturnType ? Type::fromPhpDoc($docReturnType) : null
);
return new FuncInfo(
$name,
$classFlags,
$flags,
$aliasType,
$alias,
$isDeprecated,
$verify,
$args,
$return,
$numRequiredArgs,
$cond
);
}