|
45 | 45 | use PHPStan\ShouldNotHappenException; |
46 | 46 | use PHPStan\TrinaryLogic; |
47 | 47 | use PHPStan\Type\Accessory\AccessoryArrayListType; |
| 48 | +use PHPStan\Type\Accessory\AccessoryDecimalIntegerStringType; |
48 | 49 | use PHPStan\Type\Accessory\AccessoryLiteralStringType; |
49 | 50 | use PHPStan\Type\Accessory\AccessoryLowercaseStringType; |
50 | 51 | use PHPStan\Type\Accessory\AccessoryNonEmptyStringType; |
@@ -591,33 +592,41 @@ public function resolveConcatType(Type $left, Type $right): Type |
591 | 592 | $accessoryTypes[] = new AccessoryUppercaseStringType(); |
592 | 593 | } |
593 | 594 |
|
594 | | - $leftNumericStringNonEmpty = TypeCombinator::remove($leftStringType, new ConstantStringType('')); |
595 | | - if ($leftNumericStringNonEmpty->isNumericString()->yes()) { |
596 | | - $validationCallback = $left->isInteger()->yes() |
597 | | - ? static fn (string $value): bool => !str_starts_with($value, '-') |
598 | | - : static fn (string $value): bool => Strings::match($value, '#^\d+$#') !== null; |
| 595 | + $leftStringNonEmpty = TypeCombinator::remove($leftStringType, new ConstantStringType('')); |
| 596 | + $rightStringNonEmpty = TypeCombinator::remove($leftStringType, new ConstantStringType('')); |
| 597 | + if ( |
| 598 | + $leftStringNonEmpty->isDecimalIntegerString()->and($rightStringNonEmpty->isDecimalIntegerString())->yes() |
| 599 | + && $leftStringNonEmpty->isSuperTypeOf(new ConstantStringType('0'))->no() |
| 600 | + ) { |
| 601 | + $accessoryTypes[] = new AccessoryDecimalIntegerStringType(); |
| 602 | + } else { |
| 603 | + if ($leftStringNonEmpty->isNumericString()->yes()) { |
| 604 | + $validationCallback = $left->isInteger()->yes() |
| 605 | + ? static fn (string $value): bool => !str_starts_with($value, '-') |
| 606 | + : static fn (string $value): bool => Strings::match($value, '#^\d+$#') !== null; |
599 | 607 |
|
600 | | - $allRightConstantsZeroOrMore = false; |
601 | | - foreach ($rightConstantStrings as $rightConstantString) { |
602 | | - if ($rightConstantString->getValue() === '') { |
603 | | - continue; |
604 | | - } |
| 608 | + $allRightConstantsZeroOrMore = false; |
| 609 | + foreach ($rightConstantStrings as $rightConstantString) { |
| 610 | + if ($rightConstantString->getValue() === '') { |
| 611 | + continue; |
| 612 | + } |
605 | 613 |
|
606 | | - if ( |
607 | | - !is_numeric($rightConstantString->getValue()) |
608 | | - || !$validationCallback($rightConstantString->getValue()) |
609 | | - ) { |
610 | | - $allRightConstantsZeroOrMore = false; |
611 | | - break; |
612 | | - } |
| 614 | + if ( |
| 615 | + !is_numeric($rightConstantString->getValue()) |
| 616 | + || !$validationCallback($rightConstantString->getValue()) |
| 617 | + ) { |
| 618 | + $allRightConstantsZeroOrMore = false; |
| 619 | + break; |
| 620 | + } |
613 | 621 |
|
614 | | - $allRightConstantsZeroOrMore = true; |
615 | | - } |
| 622 | + $allRightConstantsZeroOrMore = true; |
| 623 | + } |
616 | 624 |
|
617 | | - $zeroOrMoreInteger = IntegerRangeType::fromInterval(0, null); |
618 | | - $nonNegativeRight = $allRightConstantsZeroOrMore || $zeroOrMoreInteger->isSuperTypeOf($right)->yes(); |
619 | | - if ($nonNegativeRight) { |
620 | | - $accessoryTypes[] = new AccessoryNumericStringType(); |
| 625 | + $zeroOrMoreInteger = IntegerRangeType::fromInterval(0, null); |
| 626 | + $nonNegativeRight = $allRightConstantsZeroOrMore || $zeroOrMoreInteger->isSuperTypeOf($right)->yes(); |
| 627 | + if ($nonNegativeRight) { |
| 628 | + $accessoryTypes[] = new AccessoryNumericStringType(); |
| 629 | + } |
621 | 630 | } |
622 | 631 | } |
623 | 632 |
|
|
0 commit comments