1
<?php
2

3
declare(strict_types=1);
4

5
namespace Carbon\PHPStan;
6

7
use Closure;
8
use PHPStan\Reflection\Php\BuiltinMethodReflection;
9
use PHPStan\TrinaryLogic;
10
use ReflectionClass;
11
use ReflectionFunction;
12
use ReflectionMethod;
13
use ReflectionParameter;
14
use ReflectionType;
15
use stdClass;
16
use Throwable;
17

18
final class Macro implements BuiltinMethodReflection
19
{
20
    /**
21
     * The class name.
22
     *
23
     * @var class-string
24
     */
25
    private $className;
26

27
    /**
28
     * The method name.
29
     *
30
     * @var string
31
     */
32
    private $methodName;
33

34
    /**
35
     * The reflection function/method.
36
     *
37
     * @var ReflectionFunction|ReflectionMethod
38
     */
39
    private $reflectionFunction;
40

41
    /**
42
     * The parameters.
43
     *
44
     * @var ReflectionParameter[]
45
     */
46
    private $parameters;
47

48
    /**
49
     * The is static.
50
     *
51
     * @var bool
52
     */
53
    private $static = false;
54

55
    /**
56
     * Macro constructor.
57
     *
58
     * @param string $className
59
     * @phpstan-param class-string $className
60
     *
61
     * @param string   $methodName
62
     * @param callable $macro
63
     */
64 1
    public function __construct(string $className, string $methodName, $macro)
65
    {
66 1
        $this->className = $className;
67 1
        $this->methodName = $methodName;
68 1
        $this->reflectionFunction = \is_array($macro)
69 1
            ? new ReflectionMethod($macro[0], $macro[1])
70 1
            : new ReflectionFunction($macro);
71 1
        $this->parameters = $this->reflectionFunction->getParameters();
72

73 1
        if ($this->reflectionFunction->isClosure()) {
74
            try {
75
                /** @var Closure $closure */
76 1
                $closure = $this->reflectionFunction->getClosure();
77 1
                $boundClosure = Closure::bind($closure, new stdClass);
78 1
                $this->static = (!$boundClosure || (new ReflectionFunction($boundClosure))->getClosureThis() === null);
79 1
            } catch (Throwable $e) {
80 1
                $this->static = true;
81
            }
82
        }
83
    }
84

85
    /**
86
     * {@inheritdoc}
87
     */
88 1
    public function getDeclaringClass(): ReflectionClass
89
    {
90 1
        return new ReflectionClass($this->className);
91
    }
92

93
    /**
94
     * {@inheritdoc}
95
     */
96 1
    public function isPrivate(): bool
97
    {
98 1
        return false;
99
    }
100

101
    /**
102
     * {@inheritdoc}
103
     */
104 1
    public function isPublic(): bool
105
    {
106 1
        return true;
107
    }
108

109
    /**
110
     * {@inheritdoc}
111
     */
112 1
    public function isFinal(): bool
113
    {
114 1
        return false;
115
    }
116

117
    /**
118
     * {@inheritdoc}
119
     */
120 1
    public function isInternal(): bool
121
    {
122 1
        return false;
123
    }
124

125
    /**
126
     * {@inheritdoc}
127
     */
128 1
    public function isAbstract(): bool
129
    {
130 1
        return false;
131
    }
132

133
    /**
134
     * {@inheritdoc}
135
     */
136 1
    public function isStatic(): bool
137
    {
138 1
        return $this->static;
139
    }
140

141
    /**
142
     * {@inheritdoc}
143
     */
144 1
    public function getDocComment(): ?string
145
    {
146 1
        return $this->reflectionFunction->getDocComment() ?: null;
147
    }
148

149
    /**
150
     * {@inheritdoc}
151
     */
152 1
    public function getFileName()
153
    {
154 1
        return $this->reflectionFunction->getFileName();
155
    }
156

157
    /**
158
     * {@inheritdoc}
159
     */
160 1
    public function getName(): string
161
    {
162 1
        return $this->methodName;
163
    }
164

165
    /**
166
     * {@inheritdoc}
167
     */
168 1
    public function getParameters(): array
169
    {
170 1
        return $this->parameters;
171
    }
172

173
    /**
174
     * {@inheritdoc}
175
     */
176 1
    public function getReturnType(): ?ReflectionType
177
    {
178 1
        return $this->reflectionFunction->getReturnType();
179
    }
180

181
    /**
182
     * {@inheritdoc}
183
     */
184 1
    public function getStartLine()
185
    {
186 1
        return $this->reflectionFunction->getStartLine();
187
    }
188

189
    /**
190
     * {@inheritdoc}
191
     */
192 1
    public function getEndLine()
193
    {
194 1
        return $this->reflectionFunction->getEndLine();
195
    }
196

197
    /**
198
     * {@inheritdoc}
199
     */
200 1
    public function isDeprecated(): TrinaryLogic
201
    {
202 1
        return TrinaryLogic::createFromBoolean(
203 1
            $this->reflectionFunction->isDeprecated() ||
204 1
            preg_match('/@deprecated/i', $this->getDocComment() ?: '')
205
        );
206
    }
207

208
    /**
209
     * {@inheritdoc}
210
     */
211 1
    public function isVariadic(): bool
212
    {
213 1
        return $this->reflectionFunction->isVariadic();
214
    }
215

216
    /**
217
     * {@inheritdoc}
218
     */
219 1
    public function getPrototype(): BuiltinMethodReflection
220
    {
221 1
        return $this;
222
    }
223

224
    /**
225
     * {@inheritdoc}
226
     */
227 1
    public function getReflection(): ?ReflectionMethod
228
    {
229 1
        return $this->reflectionFunction instanceof ReflectionMethod
230 1
            ? $this->reflectionFunction
231 1
            : null;
232
    }
233
}

Read our documentation on viewing source code .

Loading