Conditions | 99 |
Paths | > 20000 |
Total Lines | 517 |
Lines | 0 |
Ratio | 0 % |
Changes | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.
There are several approaches to avoid long parameter lists:
1 | <?php |
||
82 | public static function expandAtomic( |
||
83 | Codebase $codebase, |
||
84 | Type\Atomic &$return_type, |
||
85 | ?string $self_class, |
||
86 | $static_class_type, |
||
87 | ?string $parent_class, |
||
88 | bool $evaluate_class_constants = true, |
||
89 | bool $evaluate_conditional_types = false, |
||
90 | bool $final = false |
||
91 | ) { |
||
92 | if ($return_type instanceof TNamedObject |
||
93 | || $return_type instanceof TTemplateParam |
||
94 | ) { |
||
95 | if ($return_type->extra_types) { |
||
96 | $new_intersection_types = []; |
||
97 | |||
98 | foreach ($return_type->extra_types as &$extra_type) { |
||
99 | self::expandAtomic( |
||
100 | $codebase, |
||
101 | $extra_type, |
||
102 | $self_class, |
||
103 | $static_class_type, |
||
104 | $parent_class, |
||
105 | $evaluate_class_constants, |
||
106 | $evaluate_conditional_types |
||
107 | ); |
||
108 | |||
109 | if ($extra_type instanceof TNamedObject && $extra_type->extra_types) { |
||
110 | $new_intersection_types = array_merge( |
||
111 | $new_intersection_types, |
||
112 | $extra_type->extra_types |
||
113 | ); |
||
114 | $extra_type->extra_types = []; |
||
115 | } |
||
116 | } |
||
117 | |||
118 | if ($new_intersection_types) { |
||
119 | $return_type->extra_types = array_merge($return_type->extra_types, $new_intersection_types); |
||
120 | } |
||
121 | } |
||
122 | |||
123 | if ($return_type instanceof TNamedObject) { |
||
124 | $return_type_lc = strtolower($return_type->value); |
||
125 | |||
126 | if ($static_class_type && ($return_type_lc === 'static' || $return_type_lc === '$this')) { |
||
127 | if (is_string($static_class_type)) { |
||
128 | $return_type->value = $static_class_type; |
||
129 | } else { |
||
130 | if ($return_type instanceof Type\Atomic\TGenericObject |
||
131 | && $static_class_type instanceof Type\Atomic\TGenericObject |
||
132 | ) { |
||
133 | $return_type->value = $static_class_type->value; |
||
134 | } else { |
||
135 | $return_type = clone $static_class_type; |
||
136 | } |
||
137 | } |
||
138 | |||
139 | if (!$final && $return_type instanceof TNamedObject) { |
||
140 | $return_type->was_static = true; |
||
141 | } |
||
142 | } elseif ($return_type->was_static |
||
143 | && ($static_class_type instanceof Type\Atomic\TNamedObject |
||
144 | || $static_class_type instanceof Type\Atomic\TTemplateParam) |
||
145 | ) { |
||
146 | $return_type = clone $return_type; |
||
147 | $cloned_static = clone $static_class_type; |
||
148 | $extra_static = $cloned_static->extra_types ?: []; |
||
149 | $cloned_static->extra_types = null; |
||
150 | |||
151 | if ($cloned_static->getKey(false) !== $return_type->getKey(false)) { |
||
152 | $return_type->extra_types[$static_class_type->getKey()] = clone $cloned_static; |
||
153 | } |
||
154 | |||
155 | foreach ($extra_static as $extra_static_type) { |
||
156 | if ($extra_static_type->getKey(false) !== $return_type->getKey(false)) { |
||
157 | $return_type->extra_types[$extra_static_type->getKey()] = clone $extra_static_type; |
||
158 | } |
||
159 | } |
||
160 | } elseif ($self_class && $return_type_lc === 'self') { |
||
161 | $return_type->value = $self_class; |
||
162 | } elseif ($parent_class && $return_type_lc === 'parent') { |
||
163 | $return_type->value = $parent_class; |
||
164 | } else { |
||
165 | $return_type->value = $codebase->classlikes->getUnAliasedName($return_type->value); |
||
166 | } |
||
167 | } |
||
168 | } |
||
169 | |||
170 | if ($return_type instanceof Type\Atomic\TClassString |
||
171 | && $return_type->as_type |
||
172 | ) { |
||
173 | $new_as_type = clone $return_type->as_type; |
||
174 | |||
175 | self::expandAtomic( |
||
176 | $codebase, |
||
177 | $new_as_type, |
||
178 | $self_class, |
||
179 | $static_class_type, |
||
180 | $parent_class, |
||
181 | $evaluate_class_constants, |
||
182 | $evaluate_conditional_types, |
||
183 | $final |
||
184 | ); |
||
185 | |||
186 | if ($new_as_type instanceof TNamedObject) { |
||
187 | $return_type->as_type = $new_as_type; |
||
188 | $return_type->as = $return_type->as_type->value; |
||
189 | } |
||
190 | } elseif ($return_type instanceof Type\Atomic\TTemplateParam) { |
||
191 | $new_as_type = self::expandUnion( |
||
192 | $codebase, |
||
193 | clone $return_type->as, |
||
194 | $self_class, |
||
195 | $static_class_type, |
||
196 | $parent_class, |
||
197 | $evaluate_class_constants, |
||
198 | $evaluate_conditional_types, |
||
199 | $final |
||
200 | ); |
||
201 | |||
202 | $return_type->as = $new_as_type; |
||
203 | } |
||
204 | |||
205 | if ($return_type instanceof Type\Atomic\TScalarClassConstant) { |
||
206 | if ($return_type->fq_classlike_name === 'self' && $self_class) { |
||
207 | $return_type->fq_classlike_name = $self_class; |
||
208 | } |
||
209 | |||
210 | if ($evaluate_class_constants && $codebase->classOrInterfaceExists($return_type->fq_classlike_name)) { |
||
211 | if (strtolower($return_type->const_name) === 'class') { |
||
212 | return new Type\Atomic\TLiteralClassString($return_type->fq_classlike_name); |
||
213 | } |
||
214 | |||
215 | if (strpos($return_type->const_name, '*') !== false) { |
||
216 | $class_storage = $codebase->classlike_storage_provider->get($return_type->fq_classlike_name); |
||
217 | |||
218 | $all_class_constants = $class_storage->public_class_constants |
||
219 | + $class_storage->protected_class_constants |
||
220 | + $class_storage->private_class_constants |
||
221 | + $class_storage->public_class_constant_nodes |
||
222 | + $class_storage->protected_class_constant_nodes |
||
223 | + $class_storage->private_class_constant_nodes; |
||
224 | |||
225 | $matching_constants = \array_keys($all_class_constants); |
||
226 | |||
227 | $const_name_part = \substr($return_type->const_name, 0, -1); |
||
228 | |||
229 | if ($const_name_part) { |
||
230 | $matching_constants = \array_filter( |
||
231 | $matching_constants, |
||
232 | function ($constant_name) use ($const_name_part) { |
||
233 | return $constant_name !== $const_name_part |
||
234 | && \strpos($constant_name, $const_name_part) === 0; |
||
235 | } |
||
236 | ); |
||
237 | } |
||
238 | } else { |
||
239 | $matching_constants = [$return_type->const_name]; |
||
240 | } |
||
241 | |||
242 | $matching_constant_types = []; |
||
243 | |||
244 | foreach ($matching_constants as $matching_constant) { |
||
245 | try { |
||
246 | $class_constant = $codebase->classlikes->getConstantForClass( |
||
247 | $return_type->fq_classlike_name, |
||
248 | $matching_constant, |
||
249 | \ReflectionProperty::IS_PRIVATE |
||
250 | ); |
||
251 | } catch (\Psalm\Exception\CircularReferenceException $e) { |
||
252 | $class_constant = null; |
||
253 | } |
||
254 | |||
255 | if ($class_constant) { |
||
256 | if ($class_constant->isSingle()) { |
||
257 | $class_constant = clone $class_constant; |
||
258 | |||
259 | $matching_constant_types = \array_merge( |
||
260 | \array_values($class_constant->getAtomicTypes()), |
||
261 | $matching_constant_types |
||
262 | ); |
||
263 | } |
||
264 | } |
||
265 | } |
||
266 | |||
267 | if ($matching_constant_types) { |
||
268 | return $matching_constant_types; |
||
269 | } |
||
270 | } |
||
271 | |||
272 | return $return_type; |
||
273 | } |
||
274 | |||
275 | if ($return_type instanceof Type\Atomic\TTypeAlias) { |
||
276 | $declaring_fq_classlike_name = $return_type->declaring_fq_classlike_name; |
||
277 | |||
278 | if ($declaring_fq_classlike_name === 'self' && $self_class) { |
||
279 | $declaring_fq_classlike_name = $self_class; |
||
280 | } |
||
281 | |||
282 | if ($evaluate_class_constants && $codebase->classOrInterfaceExists($declaring_fq_classlike_name)) { |
||
283 | $class_storage = $codebase->classlike_storage_provider->get($declaring_fq_classlike_name); |
||
284 | |||
285 | $type_alias_name = $return_type->alias_name; |
||
286 | |||
287 | if (isset($class_storage->type_aliases[$type_alias_name])) { |
||
288 | $resolved_type_alias = $class_storage->type_aliases[$type_alias_name]; |
||
289 | |||
290 | if ($resolved_type_alias->replacement_atomic_types) { |
||
291 | $replacement_atomic_types = $resolved_type_alias->replacement_atomic_types; |
||
292 | |||
293 | $recursively_fleshed_out_types = []; |
||
294 | |||
295 | foreach ($replacement_atomic_types as $replacement_atomic_type) { |
||
296 | $recursively_fleshed_out_type = self::expandAtomic( |
||
297 | $codebase, |
||
298 | $replacement_atomic_type, |
||
299 | $self_class, |
||
300 | $static_class_type, |
||
301 | $parent_class, |
||
302 | $evaluate_class_constants, |
||
303 | $evaluate_conditional_types |
||
304 | ); |
||
305 | |||
306 | if (is_array($recursively_fleshed_out_type)) { |
||
307 | $recursively_fleshed_out_types = array_merge( |
||
308 | $recursively_fleshed_out_type, |
||
309 | $recursively_fleshed_out_types |
||
310 | ); |
||
311 | } else { |
||
312 | $recursively_fleshed_out_types[] = $recursively_fleshed_out_type; |
||
313 | } |
||
314 | } |
||
315 | |||
316 | return $recursively_fleshed_out_types; |
||
317 | } |
||
318 | } |
||
319 | } |
||
320 | |||
321 | return $return_type; |
||
322 | } |
||
323 | |||
324 | if ($return_type instanceof Type\Atomic\TKeyOfClassConstant |
||
325 | || $return_type instanceof Type\Atomic\TValueOfClassConstant |
||
326 | ) { |
||
327 | if ($return_type->fq_classlike_name === 'self' && $self_class) { |
||
328 | $return_type->fq_classlike_name = $self_class; |
||
329 | } |
||
330 | |||
331 | if ($evaluate_class_constants && $codebase->classOrInterfaceExists($return_type->fq_classlike_name)) { |
||
332 | try { |
||
333 | $class_constant_type = $codebase->classlikes->getConstantForClass( |
||
334 | $return_type->fq_classlike_name, |
||
335 | $return_type->const_name, |
||
336 | \ReflectionProperty::IS_PRIVATE |
||
337 | ); |
||
338 | } catch (\Psalm\Exception\CircularReferenceException $e) { |
||
339 | $class_constant_type = null; |
||
340 | } |
||
341 | |||
342 | if ($class_constant_type) { |
||
343 | foreach ($class_constant_type->getAtomicTypes() as $const_type_atomic) { |
||
344 | if ($const_type_atomic instanceof Type\Atomic\ObjectLike |
||
345 | || $const_type_atomic instanceof Type\Atomic\TArray |
||
346 | ) { |
||
347 | if ($const_type_atomic instanceof Type\Atomic\ObjectLike) { |
||
348 | $const_type_atomic = $const_type_atomic->getGenericArrayType(); |
||
349 | } |
||
350 | |||
351 | if ($return_type instanceof Type\Atomic\TKeyOfClassConstant) { |
||
352 | return array_values($const_type_atomic->type_params[0]->getAtomicTypes()); |
||
353 | } |
||
354 | |||
355 | return array_values($const_type_atomic->type_params[1]->getAtomicTypes()); |
||
356 | } |
||
357 | } |
||
358 | } |
||
359 | } |
||
360 | |||
361 | return $return_type; |
||
362 | } |
||
363 | |||
364 | if ($return_type instanceof Type\Atomic\TArray |
||
365 | || $return_type instanceof Type\Atomic\TGenericObject |
||
366 | || $return_type instanceof Type\Atomic\TIterable |
||
367 | ) { |
||
368 | foreach ($return_type->type_params as $k => $type_param) { |
||
369 | /** @psalm-suppress PropertyTypeCoercion */ |
||
370 | $return_type->type_params[$k] = self::expandUnion( |
||
371 | $codebase, |
||
372 | $type_param, |
||
373 | $self_class, |
||
374 | $static_class_type, |
||
375 | $parent_class, |
||
376 | $evaluate_class_constants, |
||
377 | $evaluate_conditional_types, |
||
378 | $final |
||
379 | ); |
||
380 | } |
||
381 | } elseif ($return_type instanceof Type\Atomic\ObjectLike) { |
||
382 | foreach ($return_type->properties as &$property_type) { |
||
383 | $property_type = self::expandUnion( |
||
384 | $codebase, |
||
385 | $property_type, |
||
386 | $self_class, |
||
387 | $static_class_type, |
||
388 | $parent_class, |
||
389 | $evaluate_class_constants, |
||
390 | $evaluate_conditional_types, |
||
391 | $final |
||
392 | ); |
||
393 | } |
||
394 | } elseif ($return_type instanceof Type\Atomic\TList) { |
||
395 | $return_type->type_param = self::expandUnion( |
||
396 | $codebase, |
||
397 | $return_type->type_param, |
||
398 | $self_class, |
||
399 | $static_class_type, |
||
400 | $parent_class, |
||
401 | $evaluate_class_constants, |
||
402 | $evaluate_conditional_types, |
||
403 | $final |
||
404 | ); |
||
405 | } |
||
406 | |||
407 | if ($return_type instanceof Type\Atomic\TCallable |
||
408 | || $return_type instanceof Type\Atomic\TFn |
||
409 | ) { |
||
410 | if ($return_type->params) { |
||
411 | foreach ($return_type->params as $param) { |
||
412 | if ($param->type) { |
||
413 | $param->type = self::expandUnion( |
||
414 | $codebase, |
||
415 | $param->type, |
||
416 | $self_class, |
||
417 | $static_class_type, |
||
418 | $parent_class, |
||
419 | $evaluate_class_constants, |
||
420 | $evaluate_conditional_types, |
||
421 | $final |
||
422 | ); |
||
423 | } |
||
424 | } |
||
425 | } |
||
426 | if ($return_type->return_type) { |
||
427 | $return_type->return_type = self::expandUnion( |
||
428 | $codebase, |
||
429 | $return_type->return_type, |
||
430 | $self_class, |
||
431 | $static_class_type, |
||
432 | $parent_class, |
||
433 | $evaluate_class_constants, |
||
434 | $evaluate_conditional_types, |
||
435 | $final |
||
436 | ); |
||
437 | } |
||
438 | } |
||
439 | |||
440 | if ($return_type instanceof Type\Atomic\TConditional) { |
||
441 | if ($evaluate_conditional_types) { |
||
442 | $assertion = null; |
||
443 | |||
444 | if ($return_type->conditional_type->isSingle()) { |
||
445 | foreach ($return_type->conditional_type->getAtomicTypes() as $condition_atomic_type) { |
||
446 | $candidate = self::expandAtomic( |
||
447 | $codebase, |
||
448 | $condition_atomic_type, |
||
449 | $self_class, |
||
450 | $static_class_type, |
||
451 | $parent_class, |
||
452 | $evaluate_class_constants, |
||
453 | $evaluate_conditional_types, |
||
454 | $final |
||
455 | ); |
||
456 | |||
457 | if (!is_array($candidate)) { |
||
458 | $assertion = $candidate->getAssertionString(); |
||
459 | } |
||
460 | } |
||
461 | } |
||
462 | |||
463 | $if_conditional_return_types = []; |
||
464 | |||
465 | foreach ($return_type->if_type->getAtomicTypes() as $if_atomic_type) { |
||
466 | $candidate = self::expandAtomic( |
||
467 | $codebase, |
||
468 | $if_atomic_type, |
||
469 | $self_class, |
||
470 | $static_class_type, |
||
471 | $parent_class, |
||
472 | $evaluate_class_constants, |
||
473 | $evaluate_conditional_types, |
||
474 | $final |
||
475 | ); |
||
476 | |||
477 | $candidate_types = is_array($candidate) ? $candidate : [$candidate]; |
||
478 | |||
479 | $if_conditional_return_types = array_merge( |
||
480 | $if_conditional_return_types, |
||
481 | $candidate_types |
||
482 | ); |
||
483 | } |
||
484 | |||
485 | $else_conditional_return_types = []; |
||
486 | |||
487 | foreach ($return_type->else_type->getAtomicTypes() as $else_atomic_type) { |
||
488 | $candidate = self::expandAtomic( |
||
489 | $codebase, |
||
490 | $else_atomic_type, |
||
491 | $self_class, |
||
492 | $static_class_type, |
||
493 | $parent_class, |
||
494 | $evaluate_class_constants, |
||
495 | $evaluate_conditional_types, |
||
496 | $final |
||
497 | ); |
||
498 | |||
499 | $candidate_types = is_array($candidate) ? $candidate : [$candidate]; |
||
500 | |||
501 | $else_conditional_return_types = array_merge( |
||
502 | $else_conditional_return_types, |
||
503 | $candidate_types |
||
504 | ); |
||
505 | } |
||
506 | |||
507 | if ($assertion && $return_type->param_name === (string) $return_type->if_type) { |
||
508 | $if_conditional_return_type = TypeCombination::combineTypes( |
||
509 | $if_conditional_return_types, |
||
510 | $codebase |
||
511 | ); |
||
512 | |||
513 | $if_conditional_return_type = \Psalm\Internal\Type\SimpleAssertionReconciler::reconcile( |
||
514 | $assertion, |
||
515 | $codebase, |
||
516 | $if_conditional_return_type |
||
517 | ); |
||
518 | |||
519 | |||
520 | if ($if_conditional_return_type) { |
||
521 | $if_conditional_return_types = array_values($if_conditional_return_type->getAtomicTypes()); |
||
522 | } |
||
523 | } |
||
524 | |||
525 | if ($assertion && $return_type->param_name === (string) $return_type->else_type) { |
||
526 | $else_conditional_return_type = TypeCombination::combineTypes( |
||
527 | $else_conditional_return_types, |
||
528 | $codebase |
||
529 | ); |
||
530 | |||
531 | $else_conditional_return_type = \Psalm\Internal\Type\SimpleNegatedAssertionReconciler::reconcile( |
||
532 | $assertion, |
||
533 | $else_conditional_return_type |
||
534 | ); |
||
535 | |||
536 | if ($else_conditional_return_type) { |
||
537 | $else_conditional_return_types = array_values($else_conditional_return_type->getAtomicTypes()); |
||
538 | } |
||
539 | } |
||
540 | |||
541 | $all_conditional_return_types = array_merge( |
||
542 | $if_conditional_return_types, |
||
543 | $else_conditional_return_types |
||
544 | ); |
||
545 | |||
546 | foreach ($all_conditional_return_types as $i => $conditional_return_type) { |
||
547 | if ($conditional_return_type instanceof Type\Atomic\TVoid |
||
548 | && count($all_conditional_return_types) > 1 |
||
549 | ) { |
||
550 | $all_conditional_return_types[$i] = new Type\Atomic\TNull(); |
||
551 | $all_conditional_return_types[$i]->from_docblock = true; |
||
552 | } |
||
553 | } |
||
554 | |||
555 | $combined = TypeCombination::combineTypes( |
||
556 | array_values($all_conditional_return_types), |
||
557 | $codebase |
||
558 | ); |
||
559 | |||
560 | return array_values($combined->getAtomicTypes()); |
||
561 | } |
||
562 | |||
563 | $return_type->conditional_type = self::expandUnion( |
||
564 | $codebase, |
||
565 | $return_type->conditional_type, |
||
566 | $self_class, |
||
567 | $static_class_type, |
||
568 | $parent_class, |
||
569 | $evaluate_class_constants, |
||
570 | $evaluate_conditional_types, |
||
571 | $final |
||
572 | ); |
||
573 | |||
574 | $return_type->if_type = self::expandUnion( |
||
575 | $codebase, |
||
576 | $return_type->if_type, |
||
577 | $self_class, |
||
578 | $static_class_type, |
||
579 | $parent_class, |
||
580 | $evaluate_class_constants, |
||
581 | $evaluate_conditional_types, |
||
582 | $final |
||
583 | ); |
||
584 | |||
585 | $return_type->else_type = self::expandUnion( |
||
586 | $codebase, |
||
587 | $return_type->else_type, |
||
588 | $self_class, |
||
589 | $static_class_type, |
||
590 | $parent_class, |
||
591 | $evaluate_class_constants, |
||
592 | $evaluate_conditional_types, |
||
593 | $final |
||
594 | ); |
||
595 | } |
||
596 | |||
597 | return $return_type; |
||
598 | } |
||
599 | } |
||
600 |
This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.