Skip to content

Commit 188a5df

Browse files
committed
fix definitions storage collision (member / non member)
1 parent d1f85f1 commit 188a5df

File tree

1 file changed

+78
-20
lines changed

1 file changed

+78
-20
lines changed

src/Index/Index.php

Lines changed: 78 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class Index implements ReadableIndex, \Serializable
1616

1717
/**
1818
* An associative array that maps splitted fully qualified symbol names
19-
* to definitions, eg :
19+
* to member definitions, eg :
2020
* [
2121
* 'Psr' => [
2222
* '\Log' => [
@@ -29,7 +29,23 @@ class Index implements ReadableIndex, \Serializable
2929
*
3030
* @var array
3131
*/
32-
private $definitions = [];
32+
private $memberDefinitions = [];
33+
34+
/**
35+
* An associative array that maps splitted fully qualified symbol names
36+
* to non member definitions, eg :
37+
* [
38+
* 'Psr' => [
39+
* '\Log' => [
40+
* '\LoggerInterface' => $definition,
41+
* ],
42+
* ],
43+
* ]
44+
*
45+
* @var array
46+
*/
47+
private $nonMemberDefinitions = [];
48+
3349

3450
/**
3551
* An associative array that maps fully qualified symbol names
@@ -108,7 +124,8 @@ public function getDefinitions(): \Generator
108124
// }
109125
// }
110126

111-
yield from $this->generateDefinitionsRecursively($this->definitions);
127+
yield from $this->yieldDefinitionsRecursively($this->memberDefinitions);
128+
yield from $this->yieldDefinitionsRecursively($this->nonMemberDefinitions);
112129
}
113130

114131
/**
@@ -124,12 +141,20 @@ public function getDefinitionsForFqn(string $fqn): \Generator
124141
// }
125142

126143
$parts = $this->splitFqn($fqn);
127-
$result = $this->getIndexValue($parts, $this->definitions);
144+
$result = $this->getIndexValue($parts, $this->memberDefinitions);
128145

129146
if ($result instanceof Definition) {
130-
yield $fqn => $definition;
147+
yield $fqn => $result;
131148
} elseif (is_array($result)) {
132-
yield from $this->generateDefinitionsRecursively($result, $fqn);
149+
yield from $this->yieldDefinitionsRecursively($result, $fqn);
150+
} else {
151+
$result = $this->getIndexValue($parts, $this->nonMemberDefinitions);
152+
153+
if ($result instanceof Definition) {
154+
yield $fqn => $result;
155+
} elseif (is_array($result)) {
156+
yield from $this->yieldDefinitionsRecursively($result, $fqn);
157+
}
133158
}
134159
}
135160

@@ -156,9 +181,18 @@ public function getDefinition(string $fqn, bool $globalFallback = false)
156181
// }
157182

158183
$parts = $this->splitFqn($fqn);
159-
$result = $this->getIndexValue($parts, $this->definitions);
184+
$result = $this->getIndexValue($parts, $this->memberDefinitions);
160185

161-
return $result instanceof Definition ?? null;
186+
if ($result instanceof Definition) {
187+
return $result;
188+
}
189+
190+
$result = $this->getIndexValue($parts, $this->nonMemberDefinitions);
191+
192+
return $result instanceof Definition
193+
? $result
194+
: null
195+
;
162196
}
163197

164198
/**
@@ -178,7 +212,12 @@ public function setDefinition(string $fqn, Definition $definition)
178212
// $this->fqnDefinitions[$namespacedFqn][$fqn] = $definition;
179213

180214
$parts = $this->splitFqn($fqn);
181-
$this->indexDefinition(0, $parts, $this->definitions, $definition);
215+
216+
if ($definition->isMember) {
217+
$this->indexDefinition(0, $parts, $this->memberDefinitions, $definition);
218+
} else {
219+
$this->indexDefinition(0, $parts, $this->nonMemberDefinitions, $definition);
220+
}
182221

183222
$this->emit('definition-added');
184223
}
@@ -202,7 +241,10 @@ public function removeDefinition(string $fqn)
202241
// }
203242

204243
$parts = $this->splitFqn($fqn);
205-
$this->removeIndexedDefinition(0, $parts, $this->definitions);
244+
245+
if (true !== $this->removeIndexedDefinition(0, $parts, $this->memberDefinitions)) {
246+
$this->removeIndexedDefinition(0, $parts, $this->nonMemberDefinitions);
247+
}
206248

207249
unset($this->references[$fqn]);
208250
}
@@ -287,7 +329,8 @@ public function unserialize($serialized)
287329
public function serialize()
288330
{
289331
return serialize([
290-
'definitions' => $this->definitions,
332+
'memberDefinitions' => $this->memberDefinitions,
333+
'nonMemberDefinitions' => $this->nonMemberDefinitions,
291334
'references' => $this->references,
292335
'complete' => $this->complete,
293336
'staticComplete' => $this->staticComplete
@@ -318,14 +361,13 @@ public function serialize()
318361
* @param string $prefix (optional)
319362
* @return \Generator
320363
*/
321-
private function generateDefinitionsRecursively(array &$storage, string $prefix = ''): \Generator
364+
private function yieldDefinitionsRecursively(array &$storage, string $prefix = ''): \Generator
322365
{
323366
foreach ($storage as $key => $value) {
324-
$prefix .= $key;
325367
if (!is_array($value)) {
326-
yield $prefix => $value;
368+
yield sprintf('%s%s', $prefix, $key) => $value;
327369
} else {
328-
yield from generateDefinitionsRecursively($value, $prefix);
370+
yield from $this->yieldDefinitionsRecursively($value, sprintf('%s%s', $prefix, $key));
329371
}
330372
}
331373
}
@@ -346,7 +388,10 @@ private function splitFqn(string $fqn): array
346388

347389
// write back the backslach prefix to the first part if it was present
348390
if ('' === $parts[0]) {
349-
$parts = array_slice($parts, 1);
391+
if (count($parts) > 1) {
392+
$parts = array_slice($parts, 1);
393+
}
394+
350395
$parts[0] = sprintf('\\%s', $parts[0]);
351396
}
352397

@@ -394,7 +439,13 @@ private function getIndexValue(array $parts, array &$storage)
394439
return $storage[$part];
395440
}
396441

397-
return getIndexValue($parts, $storage[$part]);
442+
if (!is_array($storage[$part]) && count($parts) > 0) {
443+
// we're looking for a member definition in the non member index,
444+
// no matches can be found.
445+
return null;
446+
}
447+
448+
return $this->getIndexValue($parts, $storage[$part]);
398449
}
399450

400451
/**
@@ -420,6 +471,12 @@ private function indexDefinition(int $level, array $parts, array &$storage, Defi
420471
$storage[$part] = [];
421472
}
422473

474+
if (!is_array($storage[$part])) {
475+
// it's a non member definition, we can't add it to the member
476+
// definitions index
477+
return;
478+
}
479+
423480
$this->indexDefinition($level + 1, $parts, $storage[$part], $definition);
424481
}
425482

@@ -434,6 +491,7 @@ private function indexDefinition(int $level, array $parts, array &$storage, Defi
434491
* @param array $parts The splitted FQN
435492
* @param array &$storage The current array in which to remove data
436493
* @param array &$rootStorage The root storage array
494+
* @return boolean|null True when the definition has been found and removed, null otherwise.
437495
*/
438496
private function removeIndexedDefinition(int $level, array $parts, array &$storage, &$rootStorage)
439497
{
@@ -446,16 +504,16 @@ private function removeIndexedDefinition(int $level, array $parts, array &$stora
446504
if (0 === $level) {
447505
// we're at root level, no need to check for parents
448506
// w/o children
449-
return;
507+
return true;
450508
}
451509

452510
array_pop($parts);
453511
// parse again the definition tree to see if the parent
454512
// can be removed too if it has no more children
455-
removeIndexedDefinition(0, $parts, $rootStorage, $rootStorage);
513+
return $this->removeIndexedDefinition(0, $parts, $rootStorage, $rootStorage);
456514
}
457515
} else {
458-
removeIndexedDefinition($level + 1, $parts, $storage[$part], $rootStorage);
516+
return $this->removeIndexedDefinition($level + 1, $parts, $storage[$part], $rootStorage);
459517
}
460518
}
461519
}

0 commit comments

Comments
 (0)