Skip to content

Commit

Permalink
ExtendedMethodReflection
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Jun 7, 2022
1 parent 6fe8a46 commit 778308d
Show file tree
Hide file tree
Showing 10 changed files with 142 additions and 21 deletions.
4 changes: 2 additions & 2 deletions src/Reflection/Annotations/AnnotationMethodReflection.php
Expand Up @@ -4,14 +4,14 @@

use PHPStan\Reflection\ClassMemberReflection;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\ExtendedMethodReflection;
use PHPStan\Reflection\FunctionVariant;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\ParametersAcceptor;
use PHPStan\TrinaryLogic;
use PHPStan\Type\Generic\TemplateTypeMap;
use PHPStan\Type\Type;

class AnnotationMethodReflection implements MethodReflection
class AnnotationMethodReflection implements ExtendedMethodReflection
{

/** @var FunctionVariant[]|null */
Expand Down
Expand Up @@ -3,6 +3,7 @@
namespace PHPStan\Reflection\Annotations;

use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\ExtendedMethodReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\MethodsClassReflectionExtension;
use PHPStan\Type\Generic\TemplateTypeHelper;
Expand All @@ -11,7 +12,7 @@
class AnnotationsMethodsClassReflectionExtension implements MethodsClassReflectionExtension
{

/** @var MethodReflection[][] */
/** @var ExtendedMethodReflection[][] */
private array $methods = [];

public function hasMethod(ClassReflection $classReflection, string $methodName): bool
Expand All @@ -27,6 +28,9 @@ public function hasMethod(ClassReflection $classReflection, string $methodName):
return isset($this->methods[$classReflection->getCacheKey()][$methodName]);
}

/**
* @return ExtendedMethodReflection
*/
public function getMethod(ClassReflection $classReflection, string $methodName): MethodReflection
{
return $this->methods[$classReflection->getCacheKey()][$methodName];
Expand All @@ -36,7 +40,7 @@ private function findClassReflectionWithMethod(
ClassReflection $classReflection,
ClassReflection $declaringClass,
string $methodName,
): ?MethodReflection
): ?ExtendedMethodReflection
{
$methodTags = $classReflection->getMethodTags();
if (isset($methodTags[$methodName])) {
Expand Down
19 changes: 14 additions & 5 deletions src/Reflection/ClassReflection.php
Expand Up @@ -63,7 +63,7 @@
class ClassReflection
{

/** @var MethodReflection[] */
/** @var ExtendedMethodReflection[] */
private array $methods = [];

/** @var PropertyReflection[] */
Expand Down Expand Up @@ -365,7 +365,7 @@ public function hasMethod(string $methodName): bool
return false;
}

public function getMethod(string $methodName, ClassMemberAccessAnswerer $scope): MethodReflection
public function getMethod(string $methodName, ClassMemberAccessAnswerer $scope): ExtendedMethodReflection
{
$key = $methodName;
if ($scope->isInClass()) {
Expand All @@ -377,7 +377,7 @@ public function getMethod(string $methodName, ClassMemberAccessAnswerer $scope):
continue;
}

$method = $extension->getMethod($this, $methodName);
$method = $this->wrapExtendedMethod($extension->getMethod($this, $methodName));
if ($scope->canCallMethod($method)) {
return $this->methods[$key] = $method;
}
Expand All @@ -392,12 +392,21 @@ public function getMethod(string $methodName, ClassMemberAccessAnswerer $scope):
return $this->methods[$key];
}

private function wrapExtendedMethod(MethodReflection $method): ExtendedMethodReflection
{
if ($method instanceof ExtendedMethodReflection) {
return $method;
}

return new WrappedExtendedMethodReflection($method);
}

public function hasNativeMethod(string $methodName): bool
{
return $this->getPhpExtension()->hasNativeMethod($this, $methodName);
}

public function getNativeMethod(string $methodName): MethodReflection
public function getNativeMethod(string $methodName): ExtendedMethodReflection
{
if (!$this->hasNativeMethod($methodName)) {
throw new MissingMethodFromReflectionException($this->getName(), $methodName);
Expand All @@ -410,7 +419,7 @@ public function hasConstructor(): bool
return $this->findConstructor() !== null;
}

public function getConstructor(): MethodReflection
public function getConstructor(): ExtendedMethodReflection
{
$constructor = $this->findConstructor();
if ($constructor === null) {
Expand Down
19 changes: 19 additions & 0 deletions src/Reflection/ExtendedMethodReflection.php
@@ -0,0 +1,19 @@
<?php declare(strict_types = 1);

namespace PHPStan\Reflection;

/**
* The purpose of this interface is to be able to
* answer more questions about methods
* without breaking backward compatibility
* with existing MethodsClassReflectionExtension.
*
* Developers are meant to only use the MethodReflection
* and its methods in their code.
*
* Methods on ExtendedMethodReflection are subject to change.
*/
interface ExtendedMethodReflection extends MethodReflection
{

}
4 changes: 2 additions & 2 deletions src/Reflection/Native/NativeMethodReflection.php
Expand Up @@ -4,8 +4,8 @@

use PHPStan\Reflection\ClassMemberReflection;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\ExtendedMethodReflection;
use PHPStan\Reflection\MethodPrototypeReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\ParametersAcceptorWithPhpDocs;
use PHPStan\Reflection\Php\BuiltinMethodReflection;
use PHPStan\Reflection\ReflectionProvider;
Expand All @@ -16,7 +16,7 @@
use ReflectionException;
use function strtolower;

class NativeMethodReflection implements MethodReflection
class NativeMethodReflection implements ExtendedMethodReflection
{

/**
Expand Down
4 changes: 2 additions & 2 deletions src/Reflection/Php/EnumCasesMethodReflection.php
Expand Up @@ -4,15 +4,15 @@

use PHPStan\Reflection\ClassMemberReflection;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\ExtendedMethodReflection;
use PHPStan\Reflection\FunctionVariant;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\ParametersAcceptor;
use PHPStan\ShouldNotHappenException;
use PHPStan\TrinaryLogic;
use PHPStan\Type\Generic\TemplateTypeMap;
use PHPStan\Type\Type;

class EnumCasesMethodReflection implements MethodReflection
class EnumCasesMethodReflection implements ExtendedMethodReflection
{

public function __construct(private ClassReflection $declaringClass, private Type $returnType)
Expand Down
12 changes: 8 additions & 4 deletions src/Reflection/Php/PhpClassReflectionExtension.php
Expand Up @@ -19,6 +19,7 @@
use PHPStan\Reflection\Annotations\AnnotationsMethodsClassReflectionExtension;
use PHPStan\Reflection\Annotations\AnnotationsPropertiesClassReflectionExtension;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\ExtendedMethodReflection;
use PHPStan\Reflection\FunctionVariantWithPhpDocs;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\MethodsClassReflectionExtension;
Expand Down Expand Up @@ -68,10 +69,10 @@ class PhpClassReflectionExtension
/** @var PhpPropertyReflection[][] */
private array $nativeProperties = [];

/** @var MethodReflection[][] */
/** @var ExtendedMethodReflection[][] */
private array $methodsIncludingAnnotations = [];

/** @var MethodReflection[][] */
/** @var ExtendedMethodReflection[][] */
private array $nativeMethods = [];

/** @var array<string, array<string, Type>> */
Expand Down Expand Up @@ -375,6 +376,9 @@ public function hasMethod(ClassReflection $classReflection, string $methodName):
return $classReflection->getNativeReflection()->hasMethod($methodName);
}

/**
* @return ExtendedMethodReflection
*/
public function getMethod(ClassReflection $classReflection, string $methodName): MethodReflection
{
if (isset($this->methodsIncludingAnnotations[$classReflection->getCacheKey()][$methodName])) {
Expand Down Expand Up @@ -411,7 +415,7 @@ public function hasNativeMethod(ClassReflection $classReflection, string $method
return false;
}

public function getNativeMethod(ClassReflection $classReflection, string $methodName): MethodReflection
public function getNativeMethod(ClassReflection $classReflection, string $methodName): ExtendedMethodReflection
{
if (isset($this->nativeMethods[$classReflection->getCacheKey()][$methodName])) {
return $this->nativeMethods[$classReflection->getCacheKey()][$methodName];
Expand Down Expand Up @@ -450,7 +454,7 @@ private function createMethod(
ClassReflection $classReflection,
BuiltinMethodReflection $methodReflection,
bool $includingAnnotations,
): MethodReflection
): ExtendedMethodReflection
{
if ($includingAnnotations && $this->annotationsMethodsClassReflectionExtension->hasMethod($classReflection, $methodReflection->getName())) {
$hierarchyDistances = $classReflection->getClassHierarchyDistances();
Expand Down
4 changes: 2 additions & 2 deletions src/Reflection/Php/PhpMethodReflection.php
Expand Up @@ -13,10 +13,10 @@
use PHPStan\Parser\Parser;
use PHPStan\Reflection\ClassMemberReflection;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\ExtendedMethodReflection;
use PHPStan\Reflection\FunctionVariantWithPhpDocs;
use PHPStan\Reflection\InitializerExprTypeResolver;
use PHPStan\Reflection\MethodPrototypeReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\ParameterReflectionWithPhpDocs;
use PHPStan\Reflection\ParametersAcceptor;
use PHPStan\Reflection\ParametersAcceptorWithPhpDocs;
Expand Down Expand Up @@ -44,7 +44,7 @@
use const PHP_VERSION_ID;

/** @api */
class PhpMethodReflection implements MethodReflection
class PhpMethodReflection implements ExtendedMethodReflection
{

/** @var PhpParameterReflection[]|null */
Expand Down
85 changes: 85 additions & 0 deletions src/Reflection/WrappedExtendedMethodReflection.php
@@ -0,0 +1,85 @@
<?php declare(strict_types = 1);

namespace PHPStan\Reflection;

use PHPStan\TrinaryLogic;
use PHPStan\Type\Type;

class WrappedExtendedMethodReflection implements ExtendedMethodReflection
{

public function __construct(private MethodReflection $method)
{
}

public function getDeclaringClass(): ClassReflection
{
return $this->method->getDeclaringClass();
}

public function isStatic(): bool
{
return $this->method->isStatic();
}

public function isPrivate(): bool
{
return $this->method->isPrivate();
}

public function isPublic(): bool
{
return $this->method->isPublic();
}

public function getDocComment(): ?string
{
return $this->method->getDocComment();
}

public function getName(): string
{
return $this->method->getName();
}

public function getPrototype(): ClassMemberReflection
{
return $this->method->getPrototype();
}

public function getVariants(): array
{
return $this->method->getVariants();
}

public function isDeprecated(): TrinaryLogic
{
return $this->method->isDeprecated();
}

public function getDeprecatedDescription(): ?string
{
return $this->method->getDeprecatedDescription();
}

public function isFinal(): TrinaryLogic
{
return $this->method->isFinal();
}

public function isInternal(): TrinaryLogic
{
return $this->method->isInternal();
}

public function getThrowType(): ?Type
{
return $this->method->getThrowType();
}

public function hasSideEffects(): TrinaryLogic
{
return $this->method->hasSideEffects();
}

}
4 changes: 2 additions & 2 deletions src/Rules/Methods/MethodSignatureRule.php
Expand Up @@ -6,7 +6,7 @@
use PHPStan\Analyser\Scope;
use PHPStan\Node\InClassMethodNode;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\ExtendedMethodReflection;
use PHPStan\Reflection\ParameterReflectionWithPhpDocs;
use PHPStan\Reflection\ParametersAcceptorSelector;
use PHPStan\Reflection\ParametersAcceptorWithPhpDocs;
Expand Down Expand Up @@ -120,7 +120,7 @@ public function processNode(Node $node, Scope $scope): array
}

/**
* @return MethodReflection[]
* @return ExtendedMethodReflection[]
*/
private function collectParentMethods(string $methodName, ClassReflection $class): array
{
Expand Down

0 comments on commit 778308d

Please sign in to comment.