internalFunctionSignatureMapForFQSEN() public static method

A list of types for parameters associated with the given builtin function with the given name
See also: internal_varargs_check Formerly `function internal_varargs_check`
public static internalFunctionSignatureMapForFQSEN ( FullyQualifiedMethodName | FullyQualifiedFunctionName $function_fqsen ) : array
$function_fqsen Phan\Language\FQSEN\FullyQualifiedMethodName | Phan\Language\FQSEN\FullyQualifiedFunctionName
return array
Example #1
0
 /**
  * @param FunctionInterface $function
  * Get a list of methods hydrated with type information
  * for the given partial method
  *
  * @param CodeBase $code_base
  * The global code base holding all state
  *
  * @return Method[]
  * A list of typed methods based on the given method
  */
 private static function functionListFromFunction(FunctionInterface $function, CodeBase $code_base) : array
 {
     // See if we have any type information for this
     // internal function
     $map_list = UnionType::internalFunctionSignatureMapForFQSEN($function->getFQSEN());
     if (!$map_list) {
         return [$function];
     }
     $alternate_id = 0;
     return array_map(function ($map) use($function, &$alternate_id) : FunctionInterface {
         $alternate_function = clone $function;
         $alternate_function->setFQSEN($alternate_function->getFQSEN()->withAlternateId($alternate_id++));
         // Set the return type if one is defined
         if (!empty($map['return_type'])) {
             $alternate_function->setUnionType($map['return_type']);
         }
         // Load properties if defined
         foreach ($map['property_name_type_map'] ?? [] as $parameter_name => $parameter_type) {
             $flags = 0;
             $is_optional = false;
             // Check to see if its a pass-by-reference parameter
             if (strpos($parameter_name, '&') === 0) {
                 $flags |= \ast\flags\PARAM_REF;
                 $parameter_name = substr($parameter_name, 1);
             }
             // Check to see if its variadic
             if (strpos($parameter_name, '...') !== false) {
                 $flags |= \ast\flags\PARAM_VARIADIC;
                 $parameter_name = str_replace('...', '', $parameter_name);
             }
             // Check to see if its an optional parameter
             if (strpos($parameter_name, '=') !== false) {
                 $is_optional = true;
                 $parameter_name = str_replace('=', '', $parameter_name);
             }
             $parameter = new Parameter($function->getContext(), $parameter_name, $parameter_type, $flags);
             if ($is_optional) {
                 $parameter->setDefaultValueType(NullType::instance()->asUnionType());
             }
             // Add the parameter
             $alternate_function->appendParameter($parameter);
         }
         $alternate_function->setNumberOfRequiredParameters(array_reduce($alternate_function->getParameterList(), function (int $carry, Parameter $parameter) : int {
             return $carry + ($parameter->isOptional() ? 0 : 1);
         }, 0));
         $alternate_function->setNumberOfOptionalParameters(count($alternate_function->getParameterList()) - $alternate_function->getNumberOfRequiredParameters());
         if ($alternate_function instanceof Method) {
             if ($alternate_function->getIsMagicCall() || $alternate_function->getIsMagicCallStatic()) {
                 $alternate_function->setNumberOfOptionalParameters(999);
                 $alternate_function->setNumberOfRequiredParameters(0);
             }
         }
         return $alternate_function;
     }, $map_list);
 }
Example #2
0
 /**
  * @param Method $method
  * Get a list of methods hydrated with type information
  * for the given partial method
  *
  * @param CodeBase $code_base
  * The global code base holding all state
  *
  * @return Method[]
  * A list of typed methods based on the given method
  */
 private static function methodListFromMethod(Method $method, CodeBase $code_base) : array
 {
     // See if we have any type information for this
     // internal function
     $map_list = UnionType::internalFunctionSignatureMapForFQSEN($method->getFQSEN());
     if (!$map_list) {
         return [$method];
     }
     $alternate_id = 0;
     return array_map(function ($map) use($method, &$alternate_id) : Method {
         $alternate_method = clone $method;
         $alternate_method->setFQSEN($alternate_method->getFQSEN()->withAlternateId($alternate_id++));
         // Set the return type if one is defined
         if (!empty($map['return_type'])) {
             $alternate_method->setUnionType($map['return_type']);
         }
         // Load properties if defined
         foreach ($map['property_name_type_map'] ?? [] as $parameter_name => $parameter_type) {
             $flags = 0;
             $is_optional = false;
             // Check to see if its a pass-by-reference parameter
             if (strpos($parameter_name, '&') === 0) {
                 $flags |= \ast\flags\PARAM_REF;
                 $parameter_name = substr($parameter_name, 1);
             }
             // Check to see if its variadic
             if (strpos($parameter_name, '...') !== false) {
                 $flags |= \ast\flags\PARAM_VARIADIC;
                 $parameter_name = str_replace('...', '', $parameter_name);
             }
             // Check to see if its an optional parameter
             if (strpos($parameter_name, '=') !== false) {
                 $is_optional = true;
                 $parameter_name = str_replace('=', '', $parameter_name);
             }
             $parameter = new Parameter($method->getContext(), $parameter_name, $parameter_type, $flags);
             if ($is_optional) {
                 $parameter->setDefaultValue(null, NullType::instance()->asUnionType());
             }
             // Add the parameter
             $alternate_method->parameter_list[] = $parameter;
         }
         return $alternate_method;
     }, $map_list);
 }
Example #3
0
 /**
  * Visit a node with kind `\ast\AST_CALL`
  *
  * @param Node $node
  * A node of the type indicated by the method name that we'd
  * like to figure out the type that it produces.
  *
  * @return UnionType
  * The set of types that are possibly produced by the
  * given node
  */
 public function visitCall(Node $node) : UnionType
 {
     if ($node->children['expr']->kind !== \ast\AST_NAME) {
         // Things like `$func()`
         return new UnionType();
     }
     $function_name = $node->children['expr']->children['name'];
     try {
         $function = (new ContextNode($this->code_base, $this->context, $node->children['expr']))->getFunction($function_name);
     } catch (CodeBaseException $exception) {
         // If the function wasn't declared, it'll be caught
         // and reported elsewhere
         return new UnionType();
     }
     $function_fqsen = $function->getFQSEN();
     // TODO: I don't believe we need this any more
     // If this is an internal function, see if we can get
     // its types from the static dataset.
     if ($function->getContext()->isInternal() && $function->getUnionType()->isEmpty()) {
         $map = UnionType::internalFunctionSignatureMapForFQSEN($function->getFQSEN());
         return $map[$function_name] ?? new UnionType();
     }
     return $function->getUnionType();
 }
Example #4
0
 /**
  * Visit a node with kind `\ast\AST_CALL`
  *
  * @param Node $node
  * A node of the type indicated by the method name that we'd
  * like to figure out the type that it produces.
  *
  * @return UnionType
  * The set of types that are possibly produced by the
  * given node
  */
 public function visitCall(Node $node) : UnionType
 {
     if ($node->children['expr']->kind !== \ast\AST_NAME) {
         // Things like `$func()`
         return new UnionType();
     }
     $function_name = $node->children['expr']->children['name'];
     $function_fqsen = null;
     // If its not fully qualified
     if ($node->children['expr']->flags & \ast\flags\NAME_NOT_FQ) {
         // Check to see if we have a mapped name
         if ($this->context->hasNamespaceMapFor(T_FUNCTION, $function_name)) {
             $function_fqsen = $this->context->getNamespaceMapFor(T_FUNCTION, $function_name);
         } else {
             $function_fqsen = FullyQualifiedFunctionName::fromStringInContext($function_name, $this->context);
         }
         // If the name is fully qualified
     } else {
         $function_fqsen = FullyQualifiedFunctionName::fromFullyQualifiedString($function_name);
     }
     // If the function doesn't exist, check to see if its
     // a call to a builtin method
     if (!$this->code_base->hasMethod($function_fqsen)) {
         $function_fqsen = FullyQualifiedFunctionName::make('', $function_name);
     }
     if (!$this->code_base->hasMethod($function_fqsen)) {
         // Missing internal (bulitin) method.
         return new UnionType();
     }
     $function = $this->code_base->getMethod($function_fqsen);
     // If this is an internal function, see if we can get
     // its types from the static dataset.
     if ($function->getContext()->isInternal() && $function->getUnionType()->isEmpty()) {
         $map = UnionType::internalFunctionSignatureMapForFQSEN($function_fqsen);
         return $map[$function_name] ?? new UnionType();
     }
     return $function->getUnionType();
 }
Example #5
0
 /**
  * Visit a node with kind `\ast\AST_CALL`
  *
  * @param Node $node
  * A node of the type indicated by the method name that we'd
  * like to figure out the type that it produces.
  *
  * @return UnionType
  * The set of types that are possibly produced by the
  * given node
  */
 public function visitCall(Node $node) : UnionType
 {
     if ($node->children['expr']->kind !== \ast\AST_NAME) {
         // Things like `$func()`
         return new UnionType();
     }
     $function_name = $node->children['expr']->children['name'];
     $function = AST::functionFromNameInContext($function_name, $this->context, $this->code_base);
     $function_fqsen = $function->getFQSEN();
     // If this is an internal function, see if we can get
     // its types from the static dataset.
     if ($function->getContext()->isInternal() && $function->getUnionType()->isEmpty()) {
         $map = UnionType::internalFunctionSignatureMapForFQSEN($function->getFQSEN());
         return $map[$function_name] ?? new UnionType();
     }
     return $function->getUnionType();
 }