-
Notifications
You must be signed in to change notification settings - Fork 563
Expand file tree
/
Copy pathClassNameUsageLocation.php
More file actions
307 lines (267 loc) · 10.5 KB
/
ClassNameUsageLocation.php
File metadata and controls
307 lines (267 loc) · 10.5 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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
<?php declare(strict_types = 1);
namespace PHPStan\Rules;
use PHPStan\Reflection\ClassConstantReflection;
use PHPStan\Reflection\ExtendedMethodReflection;
use PHPStan\Reflection\ExtendedPropertyReflection;
use PHPStan\Reflection\FunctionReflection;
use function sprintf;
use function ucfirst;
/**
* @api
*/
final class ClassNameUsageLocation
{
public const TRAIT_USE = 'traitUse';
public const STATIC_PROPERTY_ACCESS = 'staticProperty';
public const PHPDOC_TAG_ASSERT = 'assert';
public const ATTRIBUTE = 'attribute';
public const EXCEPTION_CATCH = 'catch';
public const CLASS_CONSTANT_ACCESS = 'classConstant';
public const CLASS_IMPLEMENTS = 'classImplements';
public const ENUM_IMPLEMENTS = 'enumImplements';
public const INTERFACE_EXTENDS = 'interfaceExtends';
public const CLASS_EXTENDS = 'classExtends';
public const INSTANCEOF = 'instanceof';
public const PROPERTY_TYPE = 'property';
public const PARAMETER_TYPE = 'parameter';
public const RETURN_TYPE = 'return';
public const PHPDOC_TAG_SELF_OUT = 'selfOut';
public const PHPDOC_TAG_VAR = 'varTag';
public const INSTANTIATION = 'new';
public const TYPE_ALIAS = 'typeAlias';
public const PHPDOC_TAG_METHOD = 'methodTag';
public const PHPDOC_TAG_MIXIN = 'mixin';
public const PHPDOC_TAG_PROPERTY = 'propertyTag';
public const PHPDOC_TAG_REQUIRE_EXTENDS = 'requireExtends';
public const PHPDOC_TAG_REQUIRE_IMPLEMENTS = 'requireImplements';
public const PHPDOC_TAG_SEALED = 'sealed';
public const STATIC_METHOD_CALL = 'staticMethod';
public const PHPDOC_TAG_TEMPLATE_BOUND = 'templateBound';
public const PHPDOC_TAG_TEMPLATE_DEFAULT = 'templateDefault';
/**
* @param self::* $value
* @param mixed[] $data
*/
private function __construct(public readonly string $value, public readonly array $data)
{
}
/**
* @param self::* $value
* @param mixed[] $data
*/
public static function from(string $value, array $data = []): self
{
return new self($value, $data);
}
public function getMethod(): ?ExtendedMethodReflection
{
return $this->data['method'] ?? null;
}
public function getProperty(): ?ExtendedPropertyReflection
{
return $this->data['property'] ?? null;
}
public function getFunction(): ?FunctionReflection
{
return $this->data['function'] ?? null;
}
public function getPhpDocTagName(): ?string
{
return $this->data['phpDocTagName'] ?? null;
}
public function getAssertedExprString(): ?string
{
return $this->data['assertedExprString'] ?? null;
}
public function getClassConstant(): ?ClassConstantReflection
{
return $this->data['classConstant'] ?? null;
}
public function getCurrentClassName(): ?string
{
return $this->data['currentClassName'] ?? null;
}
public function getParameterName(): ?string
{
return $this->data['parameterName'] ?? null;
}
public function getTypeAliasName(): ?string
{
return $this->data['typeAliasName'] ?? null;
}
public function getMethodTagName(): ?string
{
return $this->data['methodTagName'] ?? null;
}
public function getPropertyTagName(): ?string
{
return $this->data['propertyTagName'] ?? null;
}
public function getTemplateTagName(): ?string
{
return $this->data['templateTagName'] ?? null;
}
public function isInAnomyousFunction(): bool
{
return $this->data['isInAnonymousFunction'] ?? false;
}
public function createMessage(string $part): string
{
switch ($this->value) {
case self::TRAIT_USE:
if ($this->getCurrentClassName() !== null) {
return sprintf('Usage of %s in class %s.', $part, $this->getCurrentClassName());
}
return sprintf('Usage of %s.', $part);
case self::STATIC_PROPERTY_ACCESS:
$property = $this->getProperty();
if ($property !== null) {
return sprintf('Access to static property $%s on %s.', $property->getName(), $part);
}
return sprintf('Access to static property on %s.', $part);
case self::PHPDOC_TAG_ASSERT:
$phpDocTagName = $this->getPhpDocTagName();
$assertExprString = $this->getAssertedExprString();
if ($phpDocTagName !== null && $assertExprString !== null) {
return sprintf('PHPDoc tag %s for %s references %s.', $phpDocTagName, $assertExprString, $part);
}
return sprintf('Assert tag references %s.', $part);
case self::ATTRIBUTE:
return sprintf('Attribute references %s.', $part);
case self::EXCEPTION_CATCH:
return sprintf('Catching %s.', $part);
case self::CLASS_CONSTANT_ACCESS:
if ($this->getClassConstant() !== null) {
return sprintf('Access to constant %s on %s.', $this->getClassConstant()->getName(), $part);
}
return sprintf('Access to constant on %s.', $part);
case self::CLASS_IMPLEMENTS:
if ($this->getCurrentClassName() !== null) {
return sprintf('Class %s implements %s.', $this->getCurrentClassName(), $part);
}
return sprintf('Anonymous class implements %s.', $part);
case self::ENUM_IMPLEMENTS:
if ($this->getCurrentClassName() !== null) {
return sprintf('Enum %s implements %s.', $this->getCurrentClassName(), $part);
}
return sprintf('Enum implements %s.', $part);
case self::INTERFACE_EXTENDS:
if ($this->getCurrentClassName() !== null) {
return sprintf('Interface %s extends %s.', $this->getCurrentClassName(), $part);
}
return sprintf('Interface extends %s.', $part);
case self::CLASS_EXTENDS:
if ($this->getCurrentClassName() !== null) {
return sprintf('Class %s extends %s.', $this->getCurrentClassName(), $part);
}
return sprintf('Anonymous class extends %s.', $part);
case self::INSTANCEOF:
return sprintf('Instanceof references %s.', $part);
case self::PROPERTY_TYPE:
$property = $this->getProperty();
if ($property !== null) {
return sprintf('Property $%s references %s in its type.', $property->getName(), $part);
}
return sprintf('Property references %s in its type.', $part);
case self::PARAMETER_TYPE:
$parameterName = $this->getParameterName();
if ($parameterName !== null) {
if ($this->isInAnomyousFunction()) {
return sprintf('Parameter $%s of anonymous function has typehint with %s.', $parameterName, $part);
}
if ($this->getMethod() !== null) {
if ($this->getCurrentClassName() !== null) {
return sprintf('Parameter $%s of method %s::%s() has typehint with %s.', $parameterName, $this->getCurrentClassName(), $this->getMethod()->getName(), $part);
}
return sprintf('Parameter $%s of method %s() in anonymous class has typehint with %s.', $parameterName, $this->getMethod()->getName(), $part);
}
if ($this->getFunction() !== null) {
return sprintf('Parameter $%s of function %s() has typehint with %s.', $parameterName, $this->getFunction()->getName(), $part);
}
return sprintf('Parameter $%s has typehint with %s.', $parameterName, $part);
}
return sprintf('Parameter has typehint with %s.', $part);
case self::RETURN_TYPE:
if ($this->isInAnomyousFunction()) {
return sprintf('Return type of anonymous function has typehint with %s.', $part);
}
if ($this->getMethod() !== null) {
if ($this->getCurrentClassName() !== null) {
return sprintf('Return type of method %s::%s() has typehint with %s.', $this->getCurrentClassName(), $this->getMethod()->getName(), $part);
}
return sprintf('Return type of method %s() in anonymous class has typehint with %s.', $this->getMethod()->getName(), $part);
}
if ($this->getFunction() !== null) {
return sprintf('Return type of function %s() has typehint with %s.', $this->getFunction()->getName(), $part);
}
return sprintf('Return type has typehint with %s.', $part);
case self::PHPDOC_TAG_SELF_OUT:
return sprintf('PHPDoc tag @phpstan-self-out references %s.', $part);
case self::PHPDOC_TAG_VAR:
return sprintf('PHPDoc tag @var references %s.', $part);
case self::INSTANTIATION:
return sprintf('Instantiation of %s.', $part);
case self::TYPE_ALIAS:
if ($this->getTypeAliasName() !== null) {
return sprintf('Type alias %s references %s.', $this->getTypeAliasName(), $part);
}
return sprintf('Type alias references %s.', $part);
case self::PHPDOC_TAG_METHOD:
if ($this->getMethodTagName() !== null) {
return sprintf('PHPDoc tag @method for %s() references %s.', $this->getMethodTagName(), $part);
}
return sprintf('PHPDoc tag @method references %s.', $part);
case self::PHPDOC_TAG_MIXIN:
return sprintf('PHPDoc tag @mixin references %s.', $part);
case self::PHPDOC_TAG_PROPERTY:
if ($this->getPropertyTagName() !== null) {
return sprintf('PHPDoc tag @property for $%s references %s.', $this->getPropertyTagName(), $part);
}
return sprintf('PHPDoc tag @property references %s.', $part);
case self::PHPDOC_TAG_REQUIRE_EXTENDS:
return sprintf('PHPDoc tag @phpstan-require-extends references %s.', $part);
case self::PHPDOC_TAG_REQUIRE_IMPLEMENTS:
return sprintf('PHPDoc tag @phpstan-require-implements references %s.', $part);
case self::PHPDOC_TAG_SEALED:
return sprintf('PHPDoc tag @phpstan-sealed references %s.', $part);
case self::STATIC_METHOD_CALL:
$method = $this->getMethod();
if ($method !== null) {
return sprintf('Call to static method %s() on %s.', $method->getName(), $part);
}
return sprintf('Call to static method on %s.', $part);
case self::PHPDOC_TAG_TEMPLATE_BOUND:
if ($this->getTemplateTagName() !== null) {
return sprintf('PHPDoc tag @template %s bound references %s.', $this->getTemplateTagName(), $part);
}
return sprintf('PHPDoc tag @template bound references %s.', $part);
case self::PHPDOC_TAG_TEMPLATE_DEFAULT:
if ($this->getTemplateTagName() !== null) {
return sprintf('PHPDoc tag @template %s default references %s.', $this->getTemplateTagName(), $part);
}
return sprintf('PHPDoc tag @template default references %s.', $part);
}
}
public function createIdentifier(string $secondPart): string
{
if ($this->value === self::CLASS_IMPLEMENTS) {
return sprintf('class.implements%s', ucfirst($secondPart));
}
if ($this->value === self::ENUM_IMPLEMENTS) {
return sprintf('enum.implements%s', ucfirst($secondPart));
}
if ($this->value === self::INTERFACE_EXTENDS) {
return sprintf('interface.extends%s', ucfirst($secondPart));
}
if ($this->value === self::CLASS_EXTENDS) {
return sprintf('class.extends%s', ucfirst($secondPart));
}
if ($this->value === self::PHPDOC_TAG_TEMPLATE_BOUND) {
return sprintf('generics.%sBound', $secondPart);
}
if ($this->value === self::PHPDOC_TAG_TEMPLATE_DEFAULT) {
return sprintf('generics.%sDefault', $secondPart);
}
return sprintf('%s.%s', $this->value, $secondPart);
}
}