Skip to content

Commit b48fd77

Browse files
committed
Read PHPDocs for built-in method even if the method has multiple variants
1 parent ce5f316 commit b48fd77

File tree

3 files changed

+53
-28
lines changed

3 files changed

+53
-28
lines changed

src/Reflection/Php/PhpClassReflectionExtension.php

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,7 @@ private function createMethod(
482482
$stubPhpDocParameterVariadicity = [];
483483
$phpDocParameterTypes = [];
484484
$phpDocReturnType = null;
485+
$stubPhpDocPair = null;
485486
if (count($variantNumbers) === 1) {
486487
$stubPhpDocPair = $this->findMethodPhpDocIncludingAncestors($declaringClass, $methodReflection->getName(), array_map(static function (ParameterSignature $parameterSignature): string {
487488
return $parameterSignature->getName();
@@ -505,36 +506,37 @@ private function createMethod(
505506
);
506507
$stubPhpDocParameterVariadicity[$name] = $paramTag->isVariadic();
507508
}
508-
} elseif ($reflectionMethod !== null && $reflectionMethod->getDocComment() !== false) {
509-
$filename = $reflectionMethod->getFileName();
510-
if ($filename !== false) {
511-
$phpDocBlock = $this->fileTypeMapper->getResolvedPhpDoc(
512-
$filename,
513-
$declaringClassName,
514-
null,
515-
$reflectionMethod->getName(),
516-
$reflectionMethod->getDocComment()
517-
);
518-
$throwsTag = $phpDocBlock->getThrowsTag();
519-
if ($throwsTag !== null) {
520-
$throwType = $throwsTag->getType();
521-
}
522-
$returnTag = $phpDocBlock->getReturnTag();
523-
if ($returnTag !== null) {
524-
$phpDocReturnType = $returnTag->getType();
525-
}
526-
foreach ($phpDocBlock->getParamTags() as $name => $paramTag) {
527-
$phpDocParameterTypes[$name] = $paramTag->getType();
528-
}
529-
530-
$signatureParameters = $methodSignature->getParameters();
531-
foreach ($reflectionMethod->getParameters() as $paramI => $reflectionParameter) {
532-
if (!array_key_exists($paramI, $signatureParameters)) {
533-
continue;
534-
}
509+
}
510+
}
511+
if ($stubPhpDocPair === null && $reflectionMethod !== null && $reflectionMethod->getDocComment() !== false) {
512+
$filename = $reflectionMethod->getFileName();
513+
if ($filename !== false) {
514+
$phpDocBlock = $this->fileTypeMapper->getResolvedPhpDoc(
515+
$filename,
516+
$declaringClassName,
517+
null,
518+
$reflectionMethod->getName(),
519+
$reflectionMethod->getDocComment()
520+
);
521+
$throwsTag = $phpDocBlock->getThrowsTag();
522+
if ($throwsTag !== null) {
523+
$throwType = $throwsTag->getType();
524+
}
525+
$returnTag = $phpDocBlock->getReturnTag();
526+
if ($returnTag !== null) {
527+
$phpDocReturnType = $returnTag->getType();
528+
}
529+
foreach ($phpDocBlock->getParamTags() as $name => $paramTag) {
530+
$phpDocParameterTypes[$name] = $paramTag->getType();
531+
}
535532

536-
$phpDocParameterNameMapping[$signatureParameters[$paramI]->getName()] = $reflectionParameter->getName();
533+
$signatureParameters = $methodSignature->getParameters();
534+
foreach ($reflectionMethod->getParameters() as $paramI => $reflectionParameter) {
535+
if (!array_key_exists($paramI, $signatureParameters)) {
536+
continue;
537537
}
538+
539+
$phpDocParameterNameMapping[$signatureParameters[$paramI]->getName()] = $reflectionParameter->getName();
538540
}
539541
}
540542
}

tests/PHPStan/Analyser/NodeScopeResolverTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@ public function dataFileAsserts(): iterable
383383
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-2906.php');
384384

385385
yield from $this->gatherAssertTypes(__DIR__ . '/data/DateTimeDynamicReturnTypes.php');
386+
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-4821.php');
386387
}
387388

388389
/**
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
namespace Bug4821;
4+
5+
use PHPStan\TrinaryLogic;
6+
use function PHPStan\Testing\assertVariableCertainty;
7+
8+
class HelloWorld
9+
{
10+
public function sayHello(): void
11+
{
12+
try {
13+
$object = new HelloWorld();
14+
$method = new \ReflectionMethod($object, 'nonExisting');
15+
$method->invoke($object);
16+
return;
17+
} catch (\ReflectionException $e) {
18+
assertVariableCertainty(TrinaryLogic::createYes(), $object);
19+
assertVariableCertainty(TrinaryLogic::createMaybe(), $method);
20+
}
21+
}
22+
}

0 commit comments

Comments
 (0)