fix(definitionresolver): infinite loop when indexing self referencing classes (#670)
parent
71390c9903
commit
c7d25c7b44
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
namespace RecursiveTest;
|
||||||
|
|
||||||
|
class A extends A {}
|
||||||
|
|
||||||
|
class B extends C {}
|
||||||
|
class C extends B {}
|
||||||
|
|
||||||
|
class D extends E {}
|
||||||
|
class E extends F {}
|
||||||
|
class F extends D {}
|
||||||
|
|
||||||
|
$a = new A;
|
||||||
|
$a->undef_prop = 1;
|
||||||
|
|
||||||
|
$b = new B;
|
||||||
|
$b->undef_prop = 1;
|
||||||
|
|
||||||
|
$d = new D;
|
||||||
|
$d->undef_prop = 1;
|
|
@ -438,6 +438,7 @@ class DefinitionResolver
|
||||||
|
|
||||||
// Find the right class that implements the member
|
// Find the right class that implements the member
|
||||||
$implementorFqns = [$classFqn];
|
$implementorFqns = [$classFqn];
|
||||||
|
$visitedFqns = [];
|
||||||
|
|
||||||
while ($implementorFqn = array_shift($implementorFqns)) {
|
while ($implementorFqn = array_shift($implementorFqns)) {
|
||||||
// If the member FQN exists, return it
|
// If the member FQN exists, return it
|
||||||
|
@ -450,13 +451,18 @@ class DefinitionResolver
|
||||||
if ($implementorDef === null) {
|
if ($implementorDef === null) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// Note the FQN as visited
|
||||||
|
$visitedFqns[] = $implementorFqn;
|
||||||
// Repeat for parent class
|
// Repeat for parent class
|
||||||
if ($implementorDef->extends) {
|
if ($implementorDef->extends) {
|
||||||
foreach ($implementorDef->extends as $extends) {
|
foreach ($implementorDef->extends as $extends) {
|
||||||
|
// Don't add the parent FQN if it's already been visited
|
||||||
|
if (!\in_array($extends, $visitedFqns)) {
|
||||||
$implementorFqns[] = $extends;
|
$implementorFqns[] = $extends;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return $classFqn . $memberSuffix;
|
return $classFqn . $memberSuffix;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue