Phan\Language\Element\Func::fromNode PHP Méthode

fromNode() public static méthode

public static fromNode ( Context $context, CodeBase $code_base, ast\Node\Decl $node, FullyQualifiedFunctionName $fqsen ) : Func
$context Phan\Language\Context The context in which the node appears
$code_base Phan\CodeBase
$node ast\Node\Decl An AST node representing a function
$fqsen Phan\Language\FQSEN\FullyQualifiedFunctionName A fully qualified name for the function
Résultat Func A Func representing the AST node in the given context
    public static function fromNode(Context $context, CodeBase $code_base, Decl $node, FullyQualifiedFunctionName $fqsen) : Func
    {
        // Create the skeleton function object from what
        // we know so far
        $func = new Func($context, (string) $node->name, new UnionType(), $node->flags ?? 0, $fqsen);
        // Parse the comment above the function to get
        // extra meta information about the function.
        $comment = Comment::fromStringInContext($node->docComment ?? '', $context);
        // @var Parameter[]
        // The list of parameters specified on the
        // function
        $parameter_list = Parameter::listFromNode($context, $code_base, $node->children['params']);
        // Add each parameter to the scope of the function
        foreach ($parameter_list as $parameter) {
            $func->getInternalScope()->addVariable($parameter);
        }
        // If the function is Analyzable, set the node so that
        // we can come back to it whenever we like and
        // rescan it
        $func->setNode($node);
        // Set the parameter list on the function
        $func->setParameterList($parameter_list);
        $func->setNumberOfRequiredParameters(array_reduce($parameter_list, function (int $carry, Parameter $parameter) : int {
            return $carry + ($parameter->isRequired() ? 1 : 0);
        }, 0));
        $func->setNumberOfOptionalParameters(array_reduce($parameter_list, function (int $carry, Parameter $parameter) : int {
            return $carry + ($parameter->isOptional() ? 1 : 0);
        }, 0));
        // Check to see if the comment specifies that the
        // function is deprecated
        $func->setIsDeprecated($comment->isDeprecated());
        $func->setSuppressIssueList($comment->getSuppressIssueList());
        // Take a look at function return types
        if ($node->children['returnType'] !== null) {
            // Get the type of the parameter
            $union_type = UnionType::fromNode($context, $code_base, $node->children['returnType']);
            $func->getUnionType()->addUnionType($union_type);
        }
        if ($comment->hasReturnUnionType()) {
            // See if we have a return type specified in the comment
            $union_type = $comment->getReturnType();
            assert(!$union_type->hasSelfType(), "Function referencing self in {$context}");
            $func->getUnionType()->addUnionType($union_type);
        }
        // Add params to local scope for user functions
        if (!$func->isInternal()) {
            $parameter_offset = 0;
            foreach ($func->getParameterList() as $i => $parameter) {
                if ($parameter->getUnionType()->isEmpty()) {
                    // If there is no type specified in PHP, check
                    // for a docComment with @param declarations. We
                    // assume order in the docComment matches the
                    // parameter order in the code
                    if ($comment->hasParameterWithNameOrOffset($parameter->getName(), $parameter_offset)) {
                        $comment_type = $comment->getParameterWithNameOrOffset($parameter->getName(), $parameter_offset)->getUnionType();
                        $parameter->getUnionType()->addUnionType($comment_type);
                    }
                }
                // If there's a default value on the parameter, check to
                // see if the type of the default is cool with the
                // specified type.
                if ($parameter->hasDefaultValue()) {
                    $default_type = $parameter->getDefaultValueType();
                    if (!$default_type->isEqualTo(NullType::instance()->asUnionType())) {
                        if (!$default_type->isEqualTo(NullType::instance()->asUnionType()) && !$default_type->canCastToUnionType($parameter->getUnionType())) {
                            Issue::maybeEmit($code_base, $context, Issue::TypeMismatchDefault, $node->lineno ?? 0, (string) $parameter->getUnionType(), $parameter->getName(), (string) $default_type);
                        }
                    }
                    // If we have no other type info about a parameter,
                    // just because it has a default value of null
                    // doesn't mean that is its type. Any type can default
                    // to null
                    if ((string) $default_type === 'null' && !$parameter->getUnionType()->isEmpty()) {
                        $parameter->getUnionType()->addType(NullType::instance());
                    }
                }
                ++$parameter_offset;
            }
        }
        return $func;
    }

Usage Example

Exemple #1
0
 /**
  * Visit a node with kind `\ast\AST_FUNC_DECL`
  *
  * @param Node $node
  * A node to parse
  *
  * @return Context
  * A new or an unchanged context resulting from
  * parsing the node
  */
 public function visitFuncDecl(Decl $node) : Context
 {
     $function_name = (string) $node->name;
     // Hunt for an un-taken alternate ID
     $alternate_id = 0;
     $function_fqsen = null;
     do {
         $function_fqsen = FullyQualifiedFunctionName::fromStringInContext($function_name, $this->context)->withNamespace($this->context->getNamespace())->withAlternateId($alternate_id++);
     } while ($this->code_base->hasFunctionWithFQSEN($function_fqsen));
     $func = Func::fromNode($this->context->withLineNumberStart($node->lineno ?? 0)->withLineNumberEnd($node->endLineno ?? 0), $this->code_base, $node, $function_fqsen);
     $this->code_base->addFunction($func);
     // Send the context into the function and reset the scope
     $context = $this->context->withScope($func->getInternalScope());
     return $context;
 }
All Usage Examples Of Phan\Language\Element\Func::fromNode