src/SignatureHelpProvider.php
private function getCallingInfo(Node $node)
    {
        return coroutine(function () use ($node) {
            $fqn = null;
            $callingNode = null;
            if ($node instanceof Node\DelimitedList\ArgumentExpressionList) {
                // Cursor is already inside a (
                $argumentExpressionList = $node;
                if ($node->parent instanceof Node\Expression\ObjectCreationExpression) {
                    // Constructing something
                    $callingNode = $node->parent->classTypeDesignator;
                    if (!$callingNode instanceof Node\QualifiedName) {
                        // We only support constructing from a QualifiedName
                        return null;
                    }
                    $fqn = $this->definitionResolver->resolveReferenceNodeToFqn($callingNode);
                    $fqn = "{$fqn}->__construct()";
                } else {
                    $callingNode = $node->parent->getFirstChildNode(
                        Node\Expression\MemberAccessExpression::class,
                        Node\Expression\ScopedPropertyAccessExpression::class,
                        Node\QualifiedName::class
                    );
                }
            } elseif ($node instanceof Node\Expression\CallExpression) {
                $argumentExpressionList = $node->getFirstChildNode(Node\DelimitedList\ArgumentExpressionList::class);
                $callingNode = $node->getFirstChildNode(
                    Node\Expression\MemberAccessExpression::class,
                    Node\Expression\ScopedPropertyAccessExpression::class,
                    Node\QualifiedName::class
                );
            } elseif ($node instanceof Node\Expression\ObjectCreationExpression) {
                $argumentExpressionList = $node->getFirstChildNode(Node\DelimitedList\ArgumentExpressionList::class);
                $callingNode = $node->classTypeDesignator;
                if (!$callingNode instanceof Node\QualifiedName) {
                    // We only support constructing from a QualifiedName
                    return null;
                }
                // Manually build the __construct fqn
                $fqn = $this->definitionResolver->resolveReferenceNodeToFqn($callingNode);
                $fqn = "{$fqn}->__construct()";
            }

            if (!$callingNode) {
                return null;
            }

            // Now find the definition of the call
            $fqn = $fqn ?: DefinitionResolver::getDefinedFqn($callingNode);
            while (true) {
                if ($fqn) {
                    $def = $this->index->getDefinition($fqn);
                } else {
                    $def = $this->definitionResolver->resolveReferenceNodeToDefinition($callingNode);
                }
                if ($def !== null || $this->index->isComplete()) {
                    break;
                }
                yield waitForEvent($this->index, 'definition-added');
            }

            if (!$def) {
                return null;
            }

            return [$def, $argumentExpressionList];
        });
    }
private function getCallingInfo(Node $node)
    {
        return coroutine(function () use ($node) {
            $fqn = null;
            $callingNode = null;
            if ($node instanceof Node\DelimitedList\ArgumentExpressionList) {
                // Cursor is already inside a (
                $argumentExpressionList = $node;
                if ($node->parent instanceof Node\Expression\ObjectCreationExpression) {
                    // Constructing something
                    $callingNode = $node->parent->classTypeDesignator;
                    if (!$callingNode instanceof Node\QualifiedName) {
                        // We only support constructing from a QualifiedName
                        return null;
                    }
                    $fqn = $this->definitionResolver->resolveReferenceNodeToFqn($callingNode);
                    $fqn = "{$fqn}->__construct()";
                } else {
                    $callingNode = $node->parent->getFirstChildNode(
                        Node\Expression\MemberAccessExpression::class,
                        Node\Expression\ScopedPropertyAccessExpression::class,
                        Node\QualifiedName::class
                    );
                }
            } elseif ($node instanceof Node\Expression\CallExpression) {
                $argumentExpressionList = $node->getFirstChildNode(Node\DelimitedList\ArgumentExpressionList::class);
                $callingNode = $node->getFirstChildNode(
                    Node\Expression\MemberAccessExpression::class,
                    Node\Expression\ScopedPropertyAccessExpression::class,
                    Node\QualifiedName::class
                );
            } elseif ($node instanceof Node\Expression\ObjectCreationExpression) {
                $argumentExpressionList = $node->getFirstChildNode(Node\DelimitedList\ArgumentExpressionList::class);
                $callingNode = $node->classTypeDesignator;
                if (!$callingNode instanceof Node\QualifiedName) {
                    // We only support constructing from a QualifiedName
                    return null;
                }
                // Manually build the __construct fqn
                $fqn = $this->definitionResolver->resolveReferenceNodeToFqn($callingNode);
                $fqn = "{$fqn}->__construct()";
            }

            if (!$callingNode) {
                return null;
            }

            // Now find the definition of the call
            $fqn = $fqn ?: DefinitionResolver::getDefinedFqn($callingNode);
            while (true) {
                if ($fqn) {
                    $def = $this->index->getDefinition($fqn);
                } else {
                    $def = $this->definitionResolver->resolveReferenceNodeToDefinition($callingNode);
                }
                if ($def !== null || $this->index->isComplete()) {
                    break;
                }
                yield waitForEvent($this->index, 'definition-added');
            }

            if (!$def) {
                return null;
            }

            return [$def, $argumentExpressionList];
        });
    }
private function getCallingInfo ( Node $ node ) { return coroutine ( function ( ) use ( $ node ) { $ fqn = null ; $ callingNode = null ; if ( $ node instanceof Node \ DelimitedList \ ArgumentExpressionList ) { // Cursor is already inside a ( $ argumentExpressionList = $ node ; if ( $ node -> parent instanceof Node \ Expression \ ObjectCreationExpression ) { // Constructing something $ callingNode = $ node -> parent -> classTypeDesignator ; if ( ! $ callingNode instanceof Node \ QualifiedName ) { // We only support constructing from a QualifiedName return null ; } $ fqn = $ this -> definitionResolver -> resolveReferenceNodeToFqn ( $ callingNode ) ; $ fqn = "{$fqn}->__construct()" ; } else { $ callingNode = $ node -> parent -> getFirstChildNode ( Node \ Expression \ MemberAccessExpression :: class , Node \ Expression \ ScopedPropertyAccessExpression :: class , Node \ QualifiedName :: class ) ; } } elseif ( $ node instanceof Node \ Expression \ CallExpression ) { $ argumentExpressionList = $ node -> getFirstChildNode ( Node \ DelimitedList \ ArgumentExpressionList :: class ) ; $ callingNode = $ node -> getFirstChildNode ( Node \ Expression \ MemberAccessExpression :: class , Node \ Expression \ ScopedPropertyAccessExpression :: class , Node \ QualifiedName :: class ) ; } elseif ( $ node instanceof Node \ Expression \ ObjectCreationExpression ) { $ argumentExpressionList = $ node -> getFirstChildNode ( Node \ DelimitedList \ ArgumentExpressionList :: class ) ; $ callingNode = $ node -> classTypeDesignator ; if ( ! $ callingNode instanceof Node \ QualifiedName ) { // We only support constructing from a QualifiedName return null ; } // Manually build the __construct fqn $ fqn = $ this -> definitionResolver -> resolveReferenceNodeToFqn ( $ callingNode ) ; $ fqn = "{$fqn}->__construct()" ; } if ( ! $ callingNode ) { return null ; } // Now find the definition of the call $ fqn = $ fqn ? : DefinitionResolver :: getDefinedFqn ( $ callingNode ) ; while ( true ) { if ( $ fqn ) { $ def = $ this -> index -> getDefinition ( $ fqn ) ; } else { $ def = $ this -> definitionResolver -> resolveReferenceNodeToDefinition ( $ callingNode ) ; } if ( $ def !== null || $ this -> index -> isComplete ( ) ) { break ; } yield waitForEvent ( $ this -> index , 'definition-added' ) ; } if ( ! $ def ) { return null ; } return [ $ def , $ argumentExpressionList ] ; } ) ; }
Given a node that could be a callable, finds the definition of the call and the argument expression list of
the node

@param Node $node The node to find calling information from

@return Promise <array|null>
Given a node that could be a callable finds the definition of the call and the argument expression list of the node