2016-10-11 23:45:15 +00:00
|
|
|
<?php
|
|
|
|
declare(strict_types = 1);
|
|
|
|
|
|
|
|
namespace LanguageServer\NodeVisitor;
|
|
|
|
|
|
|
|
use PhpParser\{NodeVisitorAbstract, Node};
|
2016-11-18 14:22:24 +00:00
|
|
|
use LanguageServer\DefinitionResolver;
|
2016-10-11 23:45:15 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Collects references to classes, interfaces, traits, methods, properties and constants
|
|
|
|
* Depends on ReferencesAdder and NameResolver
|
|
|
|
*/
|
|
|
|
class ReferencesCollector extends NodeVisitorAbstract
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* Map from fully qualified name (FQN) to array of nodes that reference the symbol
|
|
|
|
*
|
|
|
|
* @var Node[][]
|
|
|
|
*/
|
2016-11-18 14:22:24 +00:00
|
|
|
public $nodes = [];
|
|
|
|
|
2016-12-13 01:13:57 +00:00
|
|
|
/**
|
|
|
|
* @var DefinitionResolver
|
|
|
|
*/
|
|
|
|
private $definitionResolver;
|
|
|
|
|
2016-11-18 14:22:24 +00:00
|
|
|
/**
|
|
|
|
* @param DefinitionResolver $definitionResolver The DefinitionResolver to resolve reference nodes to definitions
|
|
|
|
*/
|
|
|
|
public function __construct(DefinitionResolver $definitionResolver)
|
|
|
|
{
|
|
|
|
$this->definitionResolver = $definitionResolver;
|
|
|
|
}
|
2016-10-11 23:45:15 +00:00
|
|
|
|
|
|
|
public function enterNode(Node $node)
|
|
|
|
{
|
|
|
|
// Check if the node references any global symbol
|
2016-11-18 14:22:24 +00:00
|
|
|
$fqn = $this->definitionResolver->resolveReferenceNodeToFqn($node);
|
2016-10-11 23:45:15 +00:00
|
|
|
if ($fqn) {
|
|
|
|
$this->addReference($fqn, $node);
|
|
|
|
// Namespaced constant access and function calls also need to register a reference
|
|
|
|
// to the global version because PHP falls back to global at runtime
|
|
|
|
// http://php.net/manual/en/language.namespaces.fallback.php
|
|
|
|
$parent = $node->getAttribute('parentNode');
|
|
|
|
if ($parent instanceof Node\Expr\ConstFetch || $parent instanceof Node\Expr\FuncCall) {
|
|
|
|
$parts = explode('\\', $fqn);
|
|
|
|
if (count($parts) > 1) {
|
|
|
|
$globalFqn = end($parts);
|
|
|
|
$this->addReference($globalFqn, $node);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private function addReference(string $fqn, Node $node)
|
|
|
|
{
|
2016-11-18 14:22:24 +00:00
|
|
|
if (!isset($this->nodes[$fqn])) {
|
|
|
|
$this->nodes[$fqn] = [];
|
2016-10-11 23:45:15 +00:00
|
|
|
}
|
2016-11-18 14:22:24 +00:00
|
|
|
$this->nodes[$fqn][] = $node;
|
2016-10-11 23:45:15 +00:00
|
|
|
}
|
|
|
|
}
|