Conditions | 130 |
Paths | 724 |
Total Lines | 396 |
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 |
||
267 | private static function analyzeNonDivOperands( |
||
268 | ?StatementsSource $statements_source, |
||
269 | ?\Psalm\Codebase $codebase, |
||
270 | Config $config, |
||
271 | ?Context $context, |
||
272 | PhpParser\Node\Expr $left, |
||
273 | PhpParser\Node\Expr $right, |
||
274 | PhpParser\Node $parent, |
||
275 | Type\Atomic $left_type_part, |
||
276 | Type\Atomic $right_type_part, |
||
277 | array &$invalid_left_messages, |
||
278 | array &$invalid_right_messages, |
||
279 | bool &$has_valid_left_operand, |
||
280 | bool &$has_valid_right_operand, |
||
281 | bool &$has_string_increment, |
||
282 | Type\Union &$result_type = null |
||
283 | ) { |
||
284 | if ($left_type_part instanceof TNull || $right_type_part instanceof TNull) { |
||
285 | // null case is handled above |
||
286 | return; |
||
287 | } |
||
288 | |||
289 | if ($left_type_part instanceof TFalse || $right_type_part instanceof TFalse) { |
||
290 | // null case is handled above |
||
291 | return; |
||
292 | } |
||
293 | |||
294 | if ($left_type_part instanceof Type\Atomic\TString |
||
295 | && $right_type_part instanceof TInt |
||
296 | && $parent instanceof PhpParser\Node\Expr\PostInc |
||
297 | ) { |
||
298 | $has_string_increment = true; |
||
299 | |||
300 | if (!$result_type) { |
||
301 | $result_type = Type::getString(); |
||
302 | } else { |
||
303 | $result_type = Type::combineUnionTypes(Type::getString(), $result_type); |
||
304 | } |
||
305 | |||
306 | $has_valid_left_operand = true; |
||
307 | $has_valid_right_operand = true; |
||
308 | |||
309 | return; |
||
310 | } |
||
311 | |||
312 | if ($left_type_part instanceof TTemplateParam |
||
313 | && $right_type_part instanceof TTemplateParam |
||
314 | ) { |
||
315 | $combined_type = Type::combineUnionTypes( |
||
316 | $left_type_part->as, |
||
317 | $right_type_part->as |
||
318 | ); |
||
319 | |||
320 | $combined_atomic_types = array_values($combined_type->getAtomicTypes()); |
||
321 | |||
322 | if (\count($combined_atomic_types) <= 2) { |
||
323 | $left_type_part = $combined_atomic_types[0]; |
||
324 | $right_type_part = $combined_atomic_types[1] ?? $combined_atomic_types[0]; |
||
325 | } |
||
326 | } |
||
327 | |||
328 | if ($left_type_part instanceof TMixed |
||
329 | || $right_type_part instanceof TMixed |
||
330 | || $left_type_part instanceof TTemplateParam |
||
331 | || $right_type_part instanceof TTemplateParam |
||
332 | ) { |
||
333 | if ($statements_source && $codebase && $context) { |
||
334 | if (!$context->collect_initializations |
||
335 | && !$context->collect_mutations |
||
336 | && $statements_source->getFilePath() === $statements_source->getRootFilePath() |
||
337 | && (!(($source = $statements_source->getSource()) |
||
338 | instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer) |
||
339 | || !$source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer) |
||
340 | ) { |
||
341 | $codebase->analyzer->incrementMixedCount($statements_source->getFilePath()); |
||
342 | } |
||
343 | } |
||
344 | |||
345 | if ($left_type_part instanceof TMixed || $left_type_part instanceof TTemplateParam) { |
||
346 | if ($statements_source && IssueBuffer::accepts( |
||
347 | new MixedOperand( |
||
348 | 'Left operand cannot be mixed', |
||
349 | new CodeLocation($statements_source, $left) |
||
350 | ), |
||
351 | $statements_source->getSuppressedIssues() |
||
352 | )) { |
||
353 | // fall through |
||
354 | } |
||
355 | } else { |
||
356 | if ($statements_source && IssueBuffer::accepts( |
||
357 | new MixedOperand( |
||
358 | 'Right operand cannot be mixed', |
||
359 | new CodeLocation($statements_source, $right) |
||
360 | ), |
||
361 | $statements_source->getSuppressedIssues() |
||
362 | )) { |
||
363 | // fall through |
||
364 | } |
||
365 | } |
||
366 | |||
367 | if ($left_type_part instanceof TMixed |
||
368 | && $left_type_part->from_loop_isset |
||
369 | && $parent instanceof PhpParser\Node\Expr\AssignOp\Plus |
||
370 | && !$right_type_part instanceof TMixed |
||
371 | ) { |
||
372 | $result_type_member = new Type\Union([$right_type_part]); |
||
373 | |||
374 | if (!$result_type) { |
||
375 | $result_type = $result_type_member; |
||
376 | } else { |
||
377 | $result_type = Type::combineUnionTypes($result_type_member, $result_type); |
||
378 | } |
||
379 | |||
380 | return; |
||
381 | } |
||
382 | |||
383 | $from_loop_isset = (!($left_type_part instanceof TMixed) || $left_type_part->from_loop_isset) |
||
384 | && (!($right_type_part instanceof TMixed) || $right_type_part->from_loop_isset); |
||
385 | |||
386 | $result_type = Type::getMixed($from_loop_isset); |
||
387 | |||
388 | return $result_type; |
||
389 | } |
||
390 | |||
391 | if ($statements_source && $codebase && $context) { |
||
392 | if (!$context->collect_initializations |
||
393 | && !$context->collect_mutations |
||
394 | && $statements_source->getFilePath() === $statements_source->getRootFilePath() |
||
395 | && (!(($parent_source = $statements_source->getSource()) |
||
396 | instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer) |
||
397 | || !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer) |
||
398 | ) { |
||
399 | $codebase->analyzer->incrementNonMixedCount($statements_source->getFilePath()); |
||
400 | } |
||
401 | } |
||
402 | |||
403 | if ($left_type_part instanceof TArray |
||
404 | || $right_type_part instanceof TArray |
||
405 | || $left_type_part instanceof ObjectLike |
||
406 | || $right_type_part instanceof ObjectLike |
||
407 | || $left_type_part instanceof TList |
||
408 | || $right_type_part instanceof TList |
||
409 | ) { |
||
410 | if ((!$right_type_part instanceof TArray |
||
411 | && !$right_type_part instanceof ObjectLike |
||
412 | && !$right_type_part instanceof TList) |
||
413 | || (!$left_type_part instanceof TArray |
||
414 | && !$left_type_part instanceof ObjectLike |
||
415 | && !$left_type_part instanceof TList) |
||
416 | ) { |
||
417 | if (!$left_type_part instanceof TArray |
||
418 | && !$left_type_part instanceof ObjectLike |
||
419 | && !$left_type_part instanceof TList |
||
420 | ) { |
||
421 | $invalid_left_messages[] = 'Cannot add an array to a non-array ' . $left_type_part; |
||
422 | } else { |
||
423 | $invalid_right_messages[] = 'Cannot add an array to a non-array ' . $right_type_part; |
||
424 | } |
||
425 | |||
426 | if ($left_type_part instanceof TArray |
||
427 | || $left_type_part instanceof ObjectLike |
||
428 | || $left_type_part instanceof TList |
||
429 | ) { |
||
430 | $has_valid_left_operand = true; |
||
431 | } elseif ($right_type_part instanceof TArray |
||
432 | || $right_type_part instanceof ObjectLike |
||
433 | || $right_type_part instanceof TList |
||
434 | ) { |
||
435 | $has_valid_right_operand = true; |
||
436 | } |
||
437 | |||
438 | $result_type = Type::getArray(); |
||
439 | |||
440 | return; |
||
441 | } |
||
442 | |||
443 | $has_valid_right_operand = true; |
||
444 | $has_valid_left_operand = true; |
||
445 | |||
446 | if ($left_type_part instanceof ObjectLike |
||
447 | && $right_type_part instanceof ObjectLike |
||
448 | ) { |
||
449 | $definitely_existing_mixed_right_properties = array_diff_key( |
||
450 | $right_type_part->properties, |
||
451 | $left_type_part->properties |
||
452 | ); |
||
453 | |||
454 | $properties = $left_type_part->properties; |
||
455 | |||
456 | foreach ($right_type_part->properties as $key => $type) { |
||
457 | if (!isset($properties[$key])) { |
||
458 | $properties[$key] = $type; |
||
459 | } elseif ($properties[$key]->possibly_undefined) { |
||
460 | $properties[$key] = Type::combineUnionTypes( |
||
461 | $properties[$key], |
||
462 | $type, |
||
463 | $codebase |
||
464 | ); |
||
465 | |||
466 | $properties[$key]->possibly_undefined = $type->possibly_undefined; |
||
467 | } |
||
468 | } |
||
469 | |||
470 | if (!$left_type_part->sealed) { |
||
471 | foreach ($definitely_existing_mixed_right_properties as $key => $type) { |
||
472 | $properties[$key] = Type::combineUnionTypes(Type::getMixed(), $type); |
||
473 | } |
||
474 | } |
||
475 | |||
476 | $result_type_member = new Type\Union([new ObjectLike($properties)]); |
||
477 | } else { |
||
478 | $result_type_member = TypeCombination::combineTypes( |
||
479 | [$left_type_part, $right_type_part], |
||
480 | $codebase, |
||
481 | true |
||
482 | ); |
||
483 | } |
||
484 | |||
485 | if (!$result_type) { |
||
486 | $result_type = $result_type_member; |
||
487 | } else { |
||
488 | $result_type = Type::combineUnionTypes($result_type_member, $result_type, $codebase, true); |
||
489 | } |
||
490 | |||
491 | if ($left instanceof PhpParser\Node\Expr\ArrayDimFetch |
||
492 | && $context |
||
493 | && $statements_source instanceof StatementsAnalyzer |
||
494 | ) { |
||
495 | ArrayAssignmentAnalyzer::updateArrayType( |
||
496 | $statements_source, |
||
497 | $left, |
||
498 | $right, |
||
499 | $result_type, |
||
500 | $context |
||
501 | ); |
||
502 | } |
||
503 | |||
504 | return; |
||
505 | } |
||
506 | |||
507 | if (($left_type_part instanceof TNamedObject && strtolower($left_type_part->value) === 'gmp') |
||
508 | || ($right_type_part instanceof TNamedObject && strtolower($right_type_part->value) === 'gmp') |
||
509 | ) { |
||
510 | if ((($left_type_part instanceof TNamedObject |
||
511 | && strtolower($left_type_part->value) === 'gmp') |
||
512 | && (($right_type_part instanceof TNamedObject |
||
513 | && strtolower($right_type_part->value) === 'gmp') |
||
514 | || ($right_type_part->isNumericType() || $right_type_part instanceof TMixed))) |
||
515 | || (($right_type_part instanceof TNamedObject |
||
516 | && strtolower($right_type_part->value) === 'gmp') |
||
517 | && (($left_type_part instanceof TNamedObject |
||
518 | && strtolower($left_type_part->value) === 'gmp') |
||
519 | || ($left_type_part->isNumericType() || $left_type_part instanceof TMixed))) |
||
520 | ) { |
||
521 | if (!$result_type) { |
||
522 | $result_type = new Type\Union([new TNamedObject('GMP')]); |
||
523 | } else { |
||
524 | $result_type = Type::combineUnionTypes( |
||
525 | new Type\Union([new TNamedObject('GMP')]), |
||
526 | $result_type |
||
527 | ); |
||
528 | } |
||
529 | } else { |
||
530 | if ($statements_source && IssueBuffer::accepts( |
||
531 | new InvalidOperand( |
||
532 | 'Cannot add GMP to non-numeric type', |
||
533 | new CodeLocation($statements_source, $parent) |
||
534 | ), |
||
535 | $statements_source->getSuppressedIssues() |
||
536 | )) { |
||
537 | // fall through |
||
538 | } |
||
539 | } |
||
540 | |||
541 | return; |
||
542 | } |
||
543 | |||
544 | if ($left_type_part->isNumericType() || $right_type_part->isNumericType()) { |
||
545 | if (($left_type_part instanceof TNumeric || $right_type_part instanceof TNumeric) |
||
546 | && ($left_type_part->isNumericType() && $right_type_part->isNumericType()) |
||
547 | ) { |
||
548 | if ($parent instanceof PhpParser\Node\Expr\BinaryOp\Mod) { |
||
549 | $result_type = Type::getInt(); |
||
550 | } elseif (!$result_type) { |
||
551 | $result_type = Type::getNumeric(); |
||
552 | } else { |
||
553 | $result_type = Type::combineUnionTypes(Type::getNumeric(), $result_type); |
||
554 | } |
||
555 | |||
556 | $has_valid_right_operand = true; |
||
557 | $has_valid_left_operand = true; |
||
558 | |||
559 | return; |
||
560 | } |
||
561 | |||
562 | if ($left_type_part instanceof TInt && $right_type_part instanceof TInt) { |
||
563 | if ($parent instanceof PhpParser\Node\Expr\BinaryOp\Mod) { |
||
564 | $result_type = Type::getInt(); |
||
565 | } elseif (!$result_type) { |
||
566 | $result_type = Type::getInt(true); |
||
567 | } else { |
||
568 | $result_type = Type::combineUnionTypes(Type::getInt(true), $result_type); |
||
569 | } |
||
570 | |||
571 | $has_valid_right_operand = true; |
||
572 | $has_valid_left_operand = true; |
||
573 | |||
574 | return; |
||
575 | } |
||
576 | |||
577 | if ($left_type_part instanceof TFloat && $right_type_part instanceof TFloat) { |
||
578 | if ($parent instanceof PhpParser\Node\Expr\BinaryOp\Mod) { |
||
579 | $result_type = Type::getInt(); |
||
580 | } elseif (!$result_type) { |
||
581 | $result_type = Type::getFloat(); |
||
582 | } else { |
||
583 | $result_type = Type::combineUnionTypes(Type::getFloat(), $result_type); |
||
584 | } |
||
585 | |||
586 | $has_valid_right_operand = true; |
||
587 | $has_valid_left_operand = true; |
||
588 | |||
589 | return; |
||
590 | } |
||
591 | |||
592 | if (($left_type_part instanceof TFloat && $right_type_part instanceof TInt) |
||
593 | || ($left_type_part instanceof TInt && $right_type_part instanceof TFloat) |
||
594 | ) { |
||
595 | if ($config->strict_binary_operands) { |
||
596 | if ($statements_source && IssueBuffer::accepts( |
||
597 | new InvalidOperand( |
||
598 | 'Cannot add ints to floats', |
||
599 | new CodeLocation($statements_source, $parent) |
||
600 | ), |
||
601 | $statements_source->getSuppressedIssues() |
||
602 | )) { |
||
603 | // fall through |
||
604 | } |
||
605 | } |
||
606 | |||
607 | if ($parent instanceof PhpParser\Node\Expr\BinaryOp\Mod) { |
||
608 | $result_type = Type::getInt(); |
||
609 | } elseif (!$result_type) { |
||
610 | $result_type = Type::getFloat(); |
||
611 | } else { |
||
612 | $result_type = Type::combineUnionTypes(Type::getFloat(), $result_type); |
||
613 | } |
||
614 | |||
615 | $has_valid_right_operand = true; |
||
616 | $has_valid_left_operand = true; |
||
617 | |||
618 | return; |
||
619 | } |
||
620 | |||
621 | if ($left_type_part->isNumericType() && $right_type_part->isNumericType()) { |
||
622 | if ($config->strict_binary_operands) { |
||
623 | if ($statements_source && IssueBuffer::accepts( |
||
624 | new InvalidOperand( |
||
625 | 'Cannot add numeric types together, please cast explicitly', |
||
626 | new CodeLocation($statements_source, $parent) |
||
627 | ), |
||
628 | $statements_source->getSuppressedIssues() |
||
629 | )) { |
||
630 | // fall through |
||
631 | } |
||
632 | } |
||
633 | |||
634 | if ($parent instanceof PhpParser\Node\Expr\BinaryOp\Mod) { |
||
635 | $result_type = Type::getInt(); |
||
636 | } elseif (!$result_type) { |
||
637 | $result_type = Type::getFloat(); |
||
638 | } else { |
||
639 | $result_type = Type::combineUnionTypes(Type::getFloat(), $result_type); |
||
640 | } |
||
641 | |||
642 | $has_valid_right_operand = true; |
||
643 | $has_valid_left_operand = true; |
||
644 | |||
645 | return; |
||
646 | } |
||
647 | |||
648 | if (!$left_type_part->isNumericType()) { |
||
649 | $invalid_left_messages[] = 'Cannot perform a numeric operation with a non-numeric type ' |
||
650 | . $left_type_part; |
||
651 | $has_valid_right_operand = true; |
||
652 | } else { |
||
653 | $invalid_right_messages[] = 'Cannot perform a numeric operation with a non-numeric type ' |
||
654 | . $right_type_part; |
||
655 | $has_valid_left_operand = true; |
||
656 | } |
||
657 | } else { |
||
658 | $invalid_left_messages[] = |
||
659 | 'Cannot perform a numeric operation with non-numeric types ' . $left_type_part |
||
660 | . ' and ' . $right_type_part; |
||
661 | } |
||
662 | } |
||
663 | } |
||
664 |