Skip to content

Commit 48bbbb5

Browse files
committed
differenciate member and non member definitions
1 parent 97ec127 commit 48bbbb5

File tree

5 files changed

+105
-47
lines changed

5 files changed

+105
-47
lines changed

src/CompletionProvider.php

+6-8
Original file line numberDiff line numberDiff line change
@@ -221,10 +221,10 @@ public function provideCompletion(PhpDocument $doc, Position $pos, CompletionCon
221221
// The FQNs of the symbol and its parents (eg the implemented interfaces)
222222
foreach ($this->expandParentFqns($fqns) as $parentFqn) {
223223
// Collect fqn definitions
224-
foreach ($this->index->getDescendantDefinitionsForFqn($parentFqn) as $fqn => $def) {
224+
foreach ($this->index->getDescendantDefinitionsForFqn($parentFqn, true) as $fqn => $def) {
225225
// Add the object access operator to only get members of all parents
226226
$prefix = $parentFqn . '->';
227-
if (substr($fqn, 0, strlen($prefix)) === $prefix && $def->isMember) {
227+
if (substr($fqn, 0, strlen($prefix)) === $prefix) {
228228
$list->items[] = CompletionItem::fromDefinition($def);
229229
}
230230
}
@@ -251,10 +251,10 @@ public function provideCompletion(PhpDocument $doc, Position $pos, CompletionCon
251251
// The FQNs of the symbol and its parents (eg the implemented interfaces)
252252
foreach ($this->expandParentFqns($fqns) as $parentFqn) {
253253
// Collect fqn definitions
254-
foreach ($this->index->getDescendantDefinitionsForFqn($parentFqn) as $fqn => $def) {
254+
foreach ($this->index->getDescendantDefinitionsForFqn($parentFqn, true) as $fqn => $def) {
255255
// Append :: operator to only get static members of all parents
256256
$prefix = strtolower($parentFqn . '::');
257-
if (substr(strtolower($fqn), 0, strlen($prefix)) === $prefix && $def->isMember) {
257+
if (substr(strtolower($fqn), 0, strlen($prefix)) === $prefix) {
258258
$list->items[] = CompletionItem::fromDefinition($def);
259259
}
260260
}
@@ -321,14 +321,12 @@ public function provideCompletion(PhpDocument $doc, Position $pos, CompletionCon
321321
// Suggest global (ie non member) symbols that either
322322
// - start with the current namespace + prefix, if the Name node is not fully qualified
323323
// - start with just the prefix, if the Name node is fully qualified
324-
foreach ($this->index->getDefinitions() as $fqn => $def) {
324+
foreach ($this->index->getDefinitions(false) as $fqn => $def) {
325325

326326
$fqnStartsWithPrefix = substr($fqn, 0, $prefixLen) === $prefix;
327327

328328
if (
329-
// Exclude methods, properties etc.
330-
!$def->isMember
331-
&& (
329+
(
332330
!$prefix
333331
|| (
334332
// Either not qualified, but a matching prefix with global fallback

src/Index/AbstractAggregateIndex.php

+6-4
Original file line numberDiff line numberDiff line change
@@ -102,25 +102,27 @@ public function isStaticComplete(): bool
102102
* Returns a Generator providing an associative array [string => Definition]
103103
* that maps fully qualified symbol names to Definitions (global or not)
104104
*
105+
* @param boolean|null $member Indicates if we want member or non-member definitions (null for both, default null)
105106
* @return \Generator yields Definition
106107
*/
107-
public function getDefinitions(): \Generator
108+
public function getDefinitions(bool $member = null): \Generator
108109
{
109110
foreach ($this->getIndexes() as $index) {
110-
yield from $index->getDefinitions();
111+
yield from $index->getDefinitions($member);
111112
}
112113
}
113114

114115
/**
115116
* Returns a Generator that yields all the descendant Definitions of a given FQN
116117
*
117118
* @param string $fqn
119+
* @param boolean|null $member Indicates if we want member or non-member definitions (null for both, default null)
118120
* @return \Generator yields Definition
119121
*/
120-
public function getDescendantDefinitionsForFqn(string $fqn): \Generator
122+
public function getDescendantDefinitionsForFqn(string $fqn, bool $member = null): \Generator
121123
{
122124
foreach ($this->getIndexes() as $index) {
123-
yield from $index->getDescendantDefinitionsForFqn($fqn);
125+
yield from $index->getDescendantDefinitionsForFqn($fqn, $member);
124126
}
125127
}
126128

src/Index/Index.php

+74-17
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,37 @@ class Index implements ReadableIndex, \Serializable
1616

1717
/**
1818
* An associative array that maps splitted fully qualified symbol names
19-
* to definitions, eg :
19+
* to non-member definitions, eg :
2020
* [
2121
* 'Psr' => [
2222
* '\Log' => [
2323
* '\LoggerInterface' => [
24-
* '' => $def1, // definition for 'Psr\Log\LoggerInterface' which is non-member
25-
* '->log()' => $def2, // definition for 'Psr\Log\LoggerInterface->log()' which is a member definition
24+
* '' => $definition,
2625
* ],
2726
* ],
2827
* ],
2928
* ]
3029
*
3130
* @var array
3231
*/
33-
private $definitions = [];
32+
private $nonMemberDefinitions = [];
33+
34+
/**
35+
* An associative array that maps splitted fully qualified symbol names
36+
* to member definitions, eg :
37+
* [
38+
* 'Psr' => [
39+
* '\Log' => [
40+
* '\LoggerInterface' => [
41+
* '->log()' => $definition,
42+
* ],
43+
* ],
44+
* ],
45+
* ]
46+
*
47+
* @var array
48+
*/
49+
private $memberDefinitions = [];
3450

3551
/**
3652
* An associative array that maps fully qualified symbol names
@@ -99,20 +115,29 @@ public function isStaticComplete(): bool
99115
* Returns a Generator providing an associative array [string => Definition]
100116
* that maps fully qualified symbol names to Definitions (global or not)
101117
*
118+
* @param boolean|null $member Indicates if we want member or non-member definitions (null for both, default null)
102119
* @return \Generator yields Definition
103120
*/
104-
public function getDefinitions(): \Generator
121+
public function getDefinitions(bool $member = null): \Generator
105122
{
106-
yield from $this->yieldDefinitionsRecursively($this->definitions);
123+
if (true === $member) {
124+
yield from $this->yieldDefinitionsRecursively($this->memberDefinitions);
125+
} elseif (false === $member) {
126+
yield from $this->yieldDefinitionsRecursively($this->nonMemberDefinitions);
127+
} else {
128+
yield from $this->yieldDefinitionsRecursively($this->memberDefinitions);
129+
yield from $this->yieldDefinitionsRecursively($this->nonMemberDefinitions);
130+
}
107131
}
108132

109133
/**
110134
* Returns a Generator that yields all the descendant Definitions of a given FQN
111135
*
112136
* @param string $fqn
137+
* @param boolean|null $member Indicates if we want member or non-member definitions (null for both, default null)
113138
* @return \Generator yields Definition
114139
*/
115-
public function getDescendantDefinitionsForFqn(string $fqn): \Generator
140+
public function getDescendantDefinitionsForFqn(string $fqn, bool $member = null): \Generator
116141
{
117142
$parts = $this->splitFqn($fqn);
118143
if ('' === end($parts)) {
@@ -121,12 +146,13 @@ public function getDescendantDefinitionsForFqn(string $fqn): \Generator
121146
array_pop($parts);
122147
}
123148

124-
$result = $this->getIndexValue($parts, $this->definitions);
125-
126-
if ($result instanceof Definition) {
127-
yield $fqn => $result;
128-
} elseif (is_array($result)) {
129-
yield from $this->yieldDefinitionsRecursively($result, $fqn);
149+
if (true === $member) {
150+
yield from $this->doGetDescendantDefinitionsForFqn($fqn, $parts, $this->memberDefinitions);
151+
} elseif (false === $member) {
152+
yield from $this->doGetDescendantDefinitionsForFqn($fqn, $parts, $this->nonMemberDefinitions);
153+
} else {
154+
yield from $this->doGetDescendantDefinitionsForFqn($fqn, $parts, $this->memberDefinitions);
155+
yield from $this->doGetDescendantDefinitionsForFqn($fqn, $parts, $this->nonMemberDefinitions);
130156
}
131157
}
132158

@@ -140,8 +166,13 @@ public function getDescendantDefinitionsForFqn(string $fqn): \Generator
140166
public function getDefinition(string $fqn, bool $globalFallback = false)
141167
{
142168
$parts = $this->splitFqn($fqn);
143-
$result = $this->getIndexValue($parts, $this->definitions);
144169

170+
$result = $this->getIndexValue($parts, $this->memberDefinitions);
171+
if ($result instanceof Definition) {
172+
return $result;
173+
}
174+
175+
$result = $this->getIndexValue($parts, $this->nonMemberDefinitions);
145176
if ($result instanceof Definition) {
146177
return $result;
147178
}
@@ -164,7 +195,12 @@ public function getDefinition(string $fqn, bool $globalFallback = false)
164195
public function setDefinition(string $fqn, Definition $definition)
165196
{
166197
$parts = $this->splitFqn($fqn);
167-
$this->indexDefinition(0, $parts, $this->definitions, $definition);
198+
199+
if ($definition->isMember) {
200+
$this->indexDefinition(0, $parts, $this->memberDefinitions, $definition);
201+
} else {
202+
$this->indexDefinition(0, $parts, $this->nonMemberDefinitions, $definition);
203+
}
168204

169205
$this->emit('definition-added');
170206
}
@@ -179,7 +215,8 @@ public function setDefinition(string $fqn, Definition $definition)
179215
public function removeDefinition(string $fqn)
180216
{
181217
$parts = $this->splitFqn($fqn);
182-
$this->removeIndexedDefinition(0, $parts, $this->definitions, $this->definitions);
218+
$this->removeIndexedDefinition(0, $parts, $this->memberDefinitions, $this->memberDefinitions);
219+
$this->removeIndexedDefinition(0, $parts, $this->nonMemberDefinitions, $this->nonMemberDefinitions);
183220

184221
unset($this->references[$fqn]);
185222
}
@@ -279,6 +316,26 @@ public function serialize()
279316
]);
280317
}
281318

319+
/**
320+
* Returns a Generator that yields all the descendant Definitions of a given FQN
321+
* in the given definition index.
322+
*
323+
* @param string $fqn
324+
* @param string[] $parts The splitted FQN
325+
* @param array &$storage The definitions index to look into
326+
* @return \Generator yields Definition
327+
*/
328+
private function doGetDescendantDefinitionsForFqn(string $fqn, array $parts, array &$storage): \Generator
329+
{
330+
$result = $this->getIndexValue($parts, $storage);
331+
332+
if ($result instanceof Definition) {
333+
yield $fqn => $result;
334+
} elseif (is_array($result)) {
335+
yield from $this->yieldDefinitionsRecursively($result, $fqn);
336+
}
337+
}
338+
282339
/**
283340
* Returns a Generator that yields all the Definitions in the given $storage recursively.
284341
* The generator yields key => value pairs, e.g.
@@ -431,7 +488,7 @@ private function removeIndexedDefinition(int $level, array $parts, array &$stora
431488
$this->removeIndexedDefinition(0, array_slice($parts, 0, $level), $rootStorage, $rootStorage);
432489
}
433490
}
434-
} else {
491+
} elseif (isset($storage[$part])) {
435492
$this->removeIndexedDefinition($level + 1, $parts, $storage[$part], $rootStorage);
436493
}
437494
}

src/Index/ReadableIndex.php

+4-2
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,19 @@ public function isStaticComplete(): bool;
3333
* Returns a Generator providing an associative array [string => Definition]
3434
* that maps fully qualified symbol names to Definitions (global or not)
3535
*
36+
* @param boolean|null $member Indicates if we want member or non-member definitions (null for both, default null)
3637
* @return \Generator yields Definition
3738
*/
38-
public function getDefinitions(): \Generator;
39+
public function getDefinitions(bool $member = null): \Generator;
3940

4041
/**
4142
* Returns a Generator that yields all the descendant Definitions of a given FQN
4243
*
4344
* @param string $fqn
45+
* @param boolean|null $member Indicates if we want member or non-member definitions (null for both, default null)
4446
* @return \Generator yields Definition
4547
*/
46-
public function getDescendantDefinitionsForFqn(string $fqn): \Generator;
48+
public function getDescendantDefinitionsForFqn(string $fqn, bool $member = null): \Generator;
4749

4850
/**
4951
* Returns the Definition object by a specific FQN

0 commit comments

Comments
 (0)