src/DefinitionResolver.php
public function resolveReferenceNodeToDefinition(Node $node)
    {
        $parent = $node->parent;
        // Variables are not indexed globally, as they stay in the file scope anyway.
        // Ignore variable nodes that are part of ScopedPropertyAccessExpression,
        // as the scoped property access expression node is handled separately.
        if ($node instanceof Node\Expression\Variable &&
            !($parent instanceof Node\Expression\ScopedPropertyAccessExpression)) {
            // Resolve $this to the containing class definition.
            if ($node->getName() === 'this' && $fqn = $this->getContainingClassFqn($node)) {
                return $this->index->getDefinition($fqn, false);
            }

            // Resolve the variable to a definition node (assignment, param or closure use)
            $defNode = $this->resolveVariableToNode($node);
            if ($defNode === null) {
                return null;
            }
            return $this->createDefinitionFromNode($defNode);
        }
        // Other references are references to a global symbol that have an FQN
        // Find out the FQN
        $fqn = $this->resolveReferenceNodeToFqn($node);
        if (!$fqn) {
            return null;
        }

        if ($fqn === 'self' || $fqn === 'static') {
            // Resolve self and static keywords to the containing class
            // (This is not 100% correct for static but better than nothing)
            $classNode = $node->getFirstAncestor(Node\Statement\ClassDeclaration::class);
            if (!$classNode) {
                return;
            }
            $fqn = (string)$classNode->getNamespacedName();
            if (!$fqn) {
                return;
            }
        } else if ($fqn === 'parent') {
            // Resolve parent keyword to the base class FQN
            $classNode = $node->getFirstAncestor(Node\Statement\ClassDeclaration::class);
            if (!$classNode || !$classNode->classBaseClause || !$classNode->classBaseClause->baseClass) {
                return;
            }
            $fqn = (string)$classNode->classBaseClause->baseClass->getResolvedName();
            if (!$fqn) {
                return;
            }
        }

        // If the node is a function or constant, it could be namespaced, but PHP falls back to global
        // http://php.net/manual/en/language.namespaces.fallback.php
        // TODO - verify that this is not a method
        $globalFallback = ParserHelpers\isConstantFetch($node) || $parent instanceof Node\Expression\CallExpression;

        // Return the Definition object from the index index
        return $this->index->getDefinition($fqn, $globalFallback);
    }
public function resolveReferenceNodeToDefinition(Node $node)
    {
        $parent = $node->parent;
        // Variables are not indexed globally, as they stay in the file scope anyway.
        // Ignore variable nodes that are part of ScopedPropertyAccessExpression,
        // as the scoped property access expression node is handled separately.
        if ($node instanceof Node\Expression\Variable &&
            !($parent instanceof Node\Expression\ScopedPropertyAccessExpression)) {
            // Resolve $this to the containing class definition.
            if ($node->getName() === 'this' && $fqn = $this->getContainingClassFqn($node)) {
                return $this->index->getDefinition($fqn, false);
            }

            // Resolve the variable to a definition node (assignment, param or closure use)
            $defNode = $this->resolveVariableToNode($node);
            if ($defNode === null) {
                return null;
            }
            return $this->createDefinitionFromNode($defNode);
        }
        // Other references are references to a global symbol that have an FQN
        // Find out the FQN
        $fqn = $this->resolveReferenceNodeToFqn($node);
        if (!$fqn) {
            return null;
        }

        if ($fqn === 'self' || $fqn === 'static') {
            // Resolve self and static keywords to the containing class
            // (This is not 100% correct for static but better than nothing)
            $classNode = $node->getFirstAncestor(Node\Statement\ClassDeclaration::class);
            if (!$classNode) {
                return;
            }
            $fqn = (string)$classNode->getNamespacedName();
            if (!$fqn) {
                return;
            }
        } else if ($fqn === 'parent') {
            // Resolve parent keyword to the base class FQN
            $classNode = $node->getFirstAncestor(Node\Statement\ClassDeclaration::class);
            if (!$classNode || !$classNode->classBaseClause || !$classNode->classBaseClause->baseClass) {
                return;
            }
            $fqn = (string)$classNode->classBaseClause->baseClass->getResolvedName();
            if (!$fqn) {
                return;
            }
        }

        // If the node is a function or constant, it could be namespaced, but PHP falls back to global
        // http://php.net/manual/en/language.namespaces.fallback.php
        // TODO - verify that this is not a method
        $globalFallback = ParserHelpers\isConstantFetch($node) || $parent instanceof Node\Expression\CallExpression;

        // Return the Definition object from the index index
        return $this->index->getDefinition($fqn, $globalFallback);
    }
public function resolveReferenceNodeToDefinition ( Node $ node ) { $ parent = $ node -> parent ; // Variables are not indexed globally, as they stay in the file scope anyway. // Ignore variable nodes that are part of ScopedPropertyAccessExpression, // as the scoped property access expression node is handled separately. if ( $ node instanceof Node \ Expression \ Variable && ! ( $ parent instanceof Node \ Expression \ ScopedPropertyAccessExpression ) ) { // Resolve $this to the containing class definition. if ( $ node -> getName ( ) === 'this' && $ fqn = $ this -> getContainingClassFqn ( $ node ) ) { return $ this -> index -> getDefinition ( $ fqn , false ) ; } // Resolve the variable to a definition node (assignment, param or closure use) $ defNode = $ this -> resolveVariableToNode ( $ node ) ; if ( $ defNode === null ) { return null ; } return $ this -> createDefinitionFromNode ( $ defNode ) ; } // Other references are references to a global symbol that have an FQN // Find out the FQN $ fqn = $ this -> resolveReferenceNodeToFqn ( $ node ) ; if ( ! $ fqn ) { return null ; } if ( $ fqn === 'self' || $ fqn === 'static' ) { // Resolve self and static keywords to the containing class // (This is not 100% correct for static but better than nothing) $ classNode = $ node -> getFirstAncestor ( Node \ Statement \ ClassDeclaration :: class ) ; if ( ! $ classNode ) { return ; } $ fqn = ( string ) $ classNode -> getNamespacedName ( ) ; if ( ! $ fqn ) { return ; } } else if ( $ fqn === 'parent' ) { // Resolve parent keyword to the base class FQN $ classNode = $ node -> getFirstAncestor ( Node \ Statement \ ClassDeclaration :: class ) ; if ( ! $ classNode || ! $ classNode -> classBaseClause || ! $ classNode -> classBaseClause -> baseClass ) { return ; } $ fqn = ( string ) $ classNode -> classBaseClause -> baseClass -> getResolvedName ( ) ; if ( ! $ fqn ) { return ; } } // If the node is a function or constant, it could be namespaced, but PHP falls back to global // http://php.net/manual/en/language.namespaces.fallback.php // TODO - verify that this is not a method $ globalFallback = ParserHelpers \ isConstantFetch ( $ node ) || $ parent instanceof Node \ Expression \ CallExpression ; // Return the Definition object from the index index return $ this -> index -> getDefinition ( $ fqn , $ globalFallback ) ; }
Given any node, returns the Definition object of the symbol that is referenced

@param Node $node Any reference node
@return Definition|null
Given any node returns the Definition object of the symbol that is referenced