speedup autocomplete with ReadableIndex::getDefinitionsForNamespace
parent
1ec8d8d8e2
commit
2d91ee8eff
|
@ -201,21 +201,44 @@ class CompletionProvider
|
||||||
$this->definitionResolver->resolveExpressionNodeToType($node->dereferencableExpression)
|
$this->definitionResolver->resolveExpressionNodeToType($node->dereferencableExpression)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$checksCount = 0;
|
||||||
|
$start = microtime(true);
|
||||||
// Add the object access operator to only get members of all parents
|
// Add the object access operator to only get members of all parents
|
||||||
$prefixes = [];
|
$namespaces = [];
|
||||||
foreach ($this->expandParentFqns($fqns) as $prefix) {
|
foreach ($this->expandParentFqns($fqns) as $namespace) {
|
||||||
$prefixes[] = $prefix . '->';
|
$namespaces[] = $namespace;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect all definitions that match any of the prefixes
|
// Collect all definitions that match any of the prefixes
|
||||||
foreach ($this->index->getDefinitions() as $fqn => $def) {
|
foreach ($namespaces as $namespace) {
|
||||||
foreach ($prefixes as $prefix) {
|
foreach ($this->index->getDefinitionsForNamespace($namespace) as $fqn => $def) {
|
||||||
if (substr($fqn, 0, strlen($prefix)) === $prefix && $def->isMember) {
|
++$checksCount;
|
||||||
|
$prefix = $namespace . '->';
|
||||||
|
if (substr($fqn, 0, strlen($prefix)) === $prefix && !$def->isMember) {
|
||||||
$list->items[] = CompletionItem::fromDefinition($def);
|
$list->items[] = CompletionItem::fromDefinition($def);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// $prefixes = [];
|
||||||
|
// foreach ($this->expandParentFqns($fqns) as $prefix) {
|
||||||
|
// $prefixes[] = $prefix . '->';
|
||||||
|
// }
|
||||||
|
// foreach ($this->index->getDefinitions() as $fqn => $def) {
|
||||||
|
// foreach ($prefixes as $prefix) {
|
||||||
|
// ++$checksCount;
|
||||||
|
// if (substr($fqn, 0, strlen($prefix)) === $prefix && !$def->isGlobal) {
|
||||||
|
// $list->items[] = CompletionItem::fromDefinition($def);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
$duration = microtime(true) - $start;
|
||||||
|
file_put_contents(
|
||||||
|
'/home/nicolas/tmp/php_language-server.log',
|
||||||
|
sprintf("%d items found, %d checks, memory : %d bytes, %ss\n", sizeof($list->items), $checksCount, memory_get_usage(true), $duration),
|
||||||
|
FILE_APPEND
|
||||||
|
);
|
||||||
|
|
||||||
} elseif (
|
} elseif (
|
||||||
($scoped = $node->parent) instanceof Node\Expression\ScopedPropertyAccessExpression ||
|
($scoped = $node->parent) instanceof Node\Expression\ScopedPropertyAccessExpression ||
|
||||||
($scoped = $node) instanceof Node\Expression\ScopedPropertyAccessExpression
|
($scoped = $node) instanceof Node\Expression\ScopedPropertyAccessExpression
|
||||||
|
|
|
@ -115,6 +115,23 @@ abstract class AbstractAggregateIndex implements ReadableIndex
|
||||||
return $defs;
|
return $defs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Definitions that are in the given namespace
|
||||||
|
*
|
||||||
|
* @param string $namespace
|
||||||
|
* @return Definitions[]
|
||||||
|
*/
|
||||||
|
public function getDefinitionsForNamespace(string $namespace): array
|
||||||
|
{
|
||||||
|
$defs = [];
|
||||||
|
foreach ($this->getIndexes() as $index) {
|
||||||
|
foreach ($index->getDefinitionsForNamespace($namespace) as $fqn => $def) {
|
||||||
|
$defs[$fqn] = $def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $defs;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the Definition object by a specific FQN
|
* Returns the Definition object by a specific FQN
|
||||||
*
|
*
|
||||||
|
|
|
@ -21,6 +21,13 @@ class Index implements ReadableIndex, \Serializable
|
||||||
*/
|
*/
|
||||||
private $definitions = [];
|
private $definitions = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An associative array that maps namespaces to an associative array of FQN to Definitions
|
||||||
|
*
|
||||||
|
* @var Definition[]
|
||||||
|
*/
|
||||||
|
private $namespaceDefinitions = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An associative array that maps fully qualified symbol names to arrays of document URIs that reference the symbol
|
* An associative array that maps fully qualified symbol names to arrays of document URIs that reference the symbol
|
||||||
*
|
*
|
||||||
|
@ -94,6 +101,20 @@ class Index implements ReadableIndex, \Serializable
|
||||||
return $this->definitions;
|
return $this->definitions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Definitions that are in the given namespace
|
||||||
|
*
|
||||||
|
* @param string $namespace
|
||||||
|
* @return Definitions[]
|
||||||
|
*/
|
||||||
|
public function getDefinitionsForNamespace(string $namespace): array
|
||||||
|
{
|
||||||
|
return isset($this->namespaceDefinitions[$namespace])
|
||||||
|
? $this->namespaceDefinitions[$namespace]
|
||||||
|
: []
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the Definition object by a specific FQN
|
* Returns the Definition object by a specific FQN
|
||||||
*
|
*
|
||||||
|
@ -123,6 +144,7 @@ class Index implements ReadableIndex, \Serializable
|
||||||
public function setDefinition(string $fqn, Definition $definition)
|
public function setDefinition(string $fqn, Definition $definition)
|
||||||
{
|
{
|
||||||
$this->definitions[$fqn] = $definition;
|
$this->definitions[$fqn] = $definition;
|
||||||
|
$this->setNamespaceDefinition($fqn, $definition);
|
||||||
$this->emit('definition-added');
|
$this->emit('definition-added');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,6 +159,7 @@ class Index implements ReadableIndex, \Serializable
|
||||||
{
|
{
|
||||||
unset($this->definitions[$fqn]);
|
unset($this->definitions[$fqn]);
|
||||||
unset($this->references[$fqn]);
|
unset($this->references[$fqn]);
|
||||||
|
$this->removeNamespaceDefinition($fqn);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -207,6 +230,7 @@ class Index implements ReadableIndex, \Serializable
|
||||||
foreach ($data as $prop => $val) {
|
foreach ($data as $prop => $val) {
|
||||||
$this->$prop = $val;
|
$this->$prop = $val;
|
||||||
}
|
}
|
||||||
|
$this->buildNamespaceDefinitionsIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -222,4 +246,59 @@ class Index implements ReadableIndex, \Serializable
|
||||||
'staticComplete' => $this->staticComplete
|
'staticComplete' => $this->staticComplete
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function buildNamespaceDefinitionsIndex()
|
||||||
|
{
|
||||||
|
foreach ($this->definitions as $fqn => $definition) {
|
||||||
|
$this->setNamespaceDefinition($fqn, $definition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a definition to a namespace
|
||||||
|
*
|
||||||
|
* @param string $fqn The fully qualified name of the symbol
|
||||||
|
* @param Definition $definition The Definition object
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function setNamespaceDefinition(string $fqn, Definition $definition)
|
||||||
|
{
|
||||||
|
$namespace = $this->extractNamespace($fqn);
|
||||||
|
if (!isset($this->namespaceDefinitions[$namespace])) {
|
||||||
|
$this->namespaceDefinitions[$namespace] = [];
|
||||||
|
}
|
||||||
|
$this->namespaceDefinitions[$namespace][$fqn] = $definition;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a definition from a namespace
|
||||||
|
*
|
||||||
|
* @param string $fqn The fully qualified name of the symbol
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function removeNamespaceDefinition(string $fqn)
|
||||||
|
{
|
||||||
|
$namespace = $this->extractNamespace($fqn);
|
||||||
|
if (isset($this->namespaceDefinitions[$namespace])) {
|
||||||
|
unset($this->namespaceDefinitions[$namespace][$fqn]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $fqn
|
||||||
|
* @return string The namespace extracted from the given FQN
|
||||||
|
*/
|
||||||
|
private function extractNamespace(string $fqn): string
|
||||||
|
{
|
||||||
|
foreach (['::', '->'] as $operator) {
|
||||||
|
if (false !== ($pos = strpos($fqn, $operator))) {
|
||||||
|
return substr($fqn, 0, $pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $fqn;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,14 @@ interface ReadableIndex extends EmitterInterface
|
||||||
*/
|
*/
|
||||||
public function getDefinitions(): array;
|
public function getDefinitions(): array;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Definitions that are in the given namespace
|
||||||
|
*
|
||||||
|
* @param string $namespace
|
||||||
|
* @return Definitions[]
|
||||||
|
*/
|
||||||
|
public function getDefinitionsForNamespace(string $namespace): array;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the Definition object by a specific FQN
|
* Returns the Definition object by a specific FQN
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue