Skip to content
Permalink
Browse files

Fix #1860 - be less restrictive about class_exists checks

  • Loading branch information...
muglug committed Jun 28, 2019
1 parent 6a95aeb commit 6514f2084c6c0a2ff8e8839eade2edf602003ccc
@@ -645,6 +645,26 @@ function (Assertion $assertion) use ($generic_params) : Assertion {
if (!$codebase->classlikes->classExists($resolved_name)) {
$context->phantom_classes[strtolower($resolved_name)] = true;
} elseif ($context->inside_negation) {
return false;
}
}
}
} elseif ($function->parts === ['interface_exists']) {
if ($first_arg) {
if ($first_arg->value instanceof PhpParser\Node\Scalar\String_) {
$context->phantom_classes[strtolower($first_arg->value->value)] = true;
} elseif ($first_arg->value instanceof PhpParser\Node\Expr\ClassConstFetch
&& $first_arg->value->class instanceof PhpParser\Node\Name
&& $first_arg->value->name instanceof PhpParser\Node\Identifier
&& $first_arg->value->name->name === 'class'
) {
$resolved_name = (string) $first_arg->value->class->getAttribute('resolvedName');
if (!$codebase->classlikes->interfaceExists($resolved_name)) {
$context->phantom_classes[strtolower($resolved_name)] = true;
} elseif ($context->inside_negation) {
return false;
}
}
}
@@ -158,14 +158,6 @@ public function __construct(
*/
public function enterNode(PhpParser\Node $node)
{
if ($this->skip_if_descendants
&& !$node instanceof PhpParser\Node\Stmt\If_
&& !$node instanceof PhpParser\Node\Stmt\Else_
&& !$node instanceof PhpParser\Node\Stmt\ElseIf_
) {
return;
}
foreach ($node->getComments() as $comment) {
if ($comment instanceof PhpParser\Comment\Doc) {
try {
@@ -265,6 +257,10 @@ public function enterNode(PhpParser\Node $node)
}
}
} elseif ($node instanceof PhpParser\Node\Stmt\ClassLike) {
if ($this->skip_if_descendants) {
return;
}
if ($this->registerClassLike($node) === false) {
return PhpParser\NodeTraverser::STOP_TRAVERSAL;
}
@@ -300,6 +296,14 @@ public function enterNode(PhpParser\Node $node)
}
}
} elseif ($node instanceof PhpParser\Node\FunctionLike) {
if ($node instanceof PhpParser\Node\Stmt\Function_
|| $node instanceof PhpParser\Node\Stmt\ClassMethod
) {
if ($this->skip_if_descendants) {
return;
}
}
$this->registerFunctionLike($node);
if ($node instanceof PhpParser\Node\Expr\Closure) {
@@ -515,14 +519,6 @@ public function enterNode(PhpParser\Node $node)
*/
public function leaveNode(PhpParser\Node $node)
{
if ($this->skip_if_descendants
&& !$node instanceof PhpParser\Node\Stmt\If_
&& !$node instanceof PhpParser\Node\Stmt\Else_
&& !$node instanceof PhpParser\Node\Stmt\ElseIf_
) {
return;
}
if ($node instanceof PhpParser\Node\Stmt\Namespace_) {
$this->aliases = $this->file_aliases;
@@ -542,6 +538,10 @@ public function leaveNode(PhpParser\Node $node)
}
}
} elseif ($node instanceof PhpParser\Node\Stmt\ClassLike) {
if ($this->skip_if_descendants) {
return;
}
if (!$this->fq_classlike_names) {
throw new \LogicException('$this->fq_classlike_names should not be empty');
}
@@ -614,6 +614,10 @@ public function leaveNode(PhpParser\Node $node)
) {
$this->function_template_types = [];
} elseif ($node instanceof PhpParser\Node\FunctionLike) {
if ($this->skip_if_descendants) {
return;
}
if (!$this->functionlike_storages) {
throw new \UnexpectedValueException('There should be function storages');
}
@@ -603,6 +603,14 @@ function foo(): bool {
class B extends A {}'
],
'noCrashWhenClassExists' => [
'<?php
class A {}
if (class_exists(A::class)) {
new \RuntimeException();
}'
],
];
}
@@ -706,6 +706,14 @@ function foo(I5 $d) : void {
function bar(I6 $d) : void {
$d->getMessage();
}
function bat(I7 $d) : void {
$d->getMessage();
}
function baz(I8 $d) : void {
$d->getMessage();
}'
);
@@ -23,15 +23,27 @@ interface I4 {}
interface I4 extends Bar {}
}
if (interface_exists(Throwable::class)) {
if (interface_exists('Throwable')) {
interface I5 extends Throwable {}
} else {
interface I5 {}
}
if (!interface_exists(Throwable::class)) {
if (!interface_exists('Throwable')) {
interface I6 {}
} else {
interface I6 extends Throwable {}
}
if (interface_exists(Throwable::class)) {
interface I7 extends Throwable {}
} else {
interface I7 {}
}
if (!interface_exists(Throwable::class)) {
interface I8 {}
} else {
interface I8 extends Throwable {}
}

0 comments on commit 6514f20

Please sign in to comment.
You can’t perform that action at this time.