-
Notifications
You must be signed in to change notification settings - Fork 22
Expand file tree
/
Copy pathMacroMethodExtension.php
More file actions
126 lines (109 loc) · 4.11 KB
/
MacroMethodExtension.php
File metadata and controls
126 lines (109 loc) · 4.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
<?php declare(strict_types = 1);
namespace Webparking\PHPStan\Lumen;
use Illuminate\Support\Traits\Macroable;
use PHPStan\Broker\Broker;
use PHPStan\PhpDoc\Tag\ParamTag;
use PHPStan\Reflection\BrokerAwareExtension;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\MethodsClassReflectionExtension;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\Php\PhpMethodReflectionFactory;
use PHPStan\Type\FileTypeMapper;
use PHPStan\Type\Type;
final class MacroMethodExtension implements MethodsClassReflectionExtension, BrokerAwareExtension
{
/**
* @var \PHPStan\Broker\Broker
*/
private $broker;
/**
* @var \PHPStan\Reflection\MethodReflection[]
*/
private $methods = [];
/**
* @var \PHPStan\Reflection\Php\PhpMethodReflectionFactory
*/
private $methodReflectionFactory;
/**
* @var \PHPStan\Type\FileTypeMapper
*/
private $fileTypeMapper;
/**
* MacroMethodExtension constructor.
*
* @param \PHPStan\Reflection\Php\PhpMethodReflectionFactory $methodReflectionFactory
* @param \PHPStan\Type\FileTypeMapper $fileTypeMapper
*/
public function __construct(PhpMethodReflectionFactory $methodReflectionFactory, FileTypeMapper $fileTypeMapper)
{
$this->methodReflectionFactory = $methodReflectionFactory;
$this->fileTypeMapper = $fileTypeMapper;
}
/**
* @inheritdoc
*/
public function setBroker(Broker $broker): void
{
$this->broker = $broker;
}
/**
* @inheritdoc
*/
public function hasMethod(ClassReflection $classReflection, string $methodName): bool
{
if ($classReflection->hasTraitUse(Macroable::class)) {
/** @var \Illuminate\Support\Traits\Macroable $macroable */
$macroable = $classReflection->getName();
if ($macroable::hasMacro($methodName) && !isset($this->methods[$classReflection->getName()])) {
$refObject = new \ReflectionClass($macroable);
$refProperty = $refObject->getProperty('macros');
$refProperty->setAccessible(true);
foreach ($refProperty->getValue() as $macro => $callable) {
$this->methods[$classReflection->getName()][$macro] = $this->createMethod(
$classReflection,
new \ReflectionFunction($callable),
$macro
);
}
}
}
return isset($this->methods[$classReflection->getName()][$methodName]);
}
/**
* @inheritdoc
*/
public function getMethod(ClassReflection $classReflection, string $methodName): MethodReflection
{
return $this->methods[$classReflection->getName()][$methodName];
}
/**
* @param \PHPStan\Reflection\ClassReflection $classReflection
* @param \ReflectionFunction $functionReflection
* @param string $methodName
*
* @return \PHPStan\Reflection\MethodReflection
*/
private function createMethod(ClassReflection $classReflection, \ReflectionFunction $functionReflection, string $methodName): MethodReflection
{
$phpDocParameterTypes = [];
$phpDocReturnType = null;
if ($functionReflection->getFileName() !== false && $functionReflection->getDocComment() !== false) {
$resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc(
$functionReflection->getFileName(),
null,
null,
$functionReflection->getDocComment()
);
$phpDocParameterTypes = array_map(function (ParamTag $tag): Type {
return $tag->getType();
}, $resolvedPhpDoc->getParamTags());
$phpDocReturnType = $resolvedPhpDoc->getReturnTag() !== null ? $resolvedPhpDoc->getReturnTag()->getType() : null;
}
return $this->methodReflectionFactory->create(
$classReflection,
new ReflectionMethodFunctionProxy($classReflection->getName(), $methodName, $functionReflection),
$phpDocParameterTypes,
$phpDocReturnType
);
}
}