diff --git a/money/extension.neon b/money/extension.neon index eb50626..5920603 100644 --- a/money/extension.neon +++ b/money/extension.neon @@ -4,11 +4,6 @@ services: tags: - phpstan.dynamicStaticMethodThrowTypeExtension - - - class: Brick\Money\PHPStan\MoneyFactoryRoundingModeThrowTypeExtension - tags: - - phpstan.dynamicStaticMethodThrowTypeExtension - - class: Brick\Money\PHPStan\MoneyOperationThrowTypeExtension tags: diff --git a/money/src/MoneyFactoryRoundingModeThrowTypeExtension.php b/money/src/MoneyFactoryRoundingModeThrowTypeExtension.php deleted file mode 100644 index ec038d0..0000000 --- a/money/src/MoneyFactoryRoundingModeThrowTypeExtension.php +++ /dev/null @@ -1,63 +0,0 @@ - rounding mode arg index */ - private const array METHODS = [ - 'of' => 3, - 'ofMinor' => 3, - ]; - - public function isStaticMethodSupported(MethodReflection $methodReflection): bool - { - return $methodReflection->getDeclaringClass()->getName() === Money::class - && isset(self::METHODS[$methodReflection->getName()]); - } - - public function getThrowTypeFromStaticMethodCall( - MethodReflection $methodReflection, - StaticCall $methodCall, - Scope $scope, - ): Type|null { - $methodName = $methodReflection->getName(); - $roundingModeArgIndex = self::METHODS[$methodName]; - - $args = $methodCall->getArgs(); - - if (! isset($args[$roundingModeArgIndex])) { - return $methodReflection->getThrowType(); - } - - $roundingModeType = $scope->getType($args[$roundingModeArgIndex]->value); - - if (! SafeType::isSafeRoundingMode($roundingModeType)) { - return $methodReflection->getThrowType(); - } - - // Rounding mode is not Unnecessary — RoundingNecessaryException cannot occur. - return TypeCombinator::union( - new ObjectType(NumberFormatException::class), - new ObjectType(UnknownCurrencyException::class), - ); - } -} diff --git a/money/src/MoneyFactoryThrowTypeExtension.php b/money/src/MoneyFactoryThrowTypeExtension.php index 0614fe7..0d19915 100644 --- a/money/src/MoneyFactoryThrowTypeExtension.php +++ b/money/src/MoneyFactoryThrowTypeExtension.php @@ -92,7 +92,7 @@ public function getThrowTypeFromStaticMethodCall( // Money::of()/ofMinor() can still throw RoundingNecessaryException, // unless the amount cannot require rounding. - if ($className === Money::class && ! $this->isRoundingSafe($amountType, $methodName, $args)) { + if ($className === Money::class && ! $this->isRoundingSafe($amountType, $methodName, $args, $scope)) { $residualTypes[] = new ObjectType(RoundingNecessaryException::class); } @@ -114,8 +114,12 @@ public function getThrowTypeFromStaticMethodCall( * * @param Arg[] $args */ - private function isRoundingSafe(Type $amountType, string $methodName, array $args): bool + private function isRoundingSafe(Type $amountType, string $methodName, array $args, Scope $scope): bool { + if (isset($args[3]) && SafeType::isSafeRoundingMode($scope->getType($args[3]->value))) { + return true; + } + if (SafeType::isZero($amountType)) { return true; } diff --git a/money/tests/data/MoneyThrowTypes.php b/money/tests/data/MoneyThrowTypes.php index f0cbe74..1453063 100644 --- a/money/tests/data/MoneyThrowTypes.php +++ b/money/tests/data/MoneyThrowTypes.php @@ -163,6 +163,24 @@ public function ofStringWithCustomContext(string $amount): void } } + public function ofWithRoundingMode(BigDecimal $amount): void + { + try { + $result = Money::of($amount, 'USD', roundingMode: RoundingMode::HalfUp); + } finally { + assertVariableCertainty(TrinaryLogic::createYes(), $result); + } + } + + public function ofMinorWithRoundingMode(BigDecimal $amount): void + { + try { + $result = Money::ofMinor($amount, 'USD', roundingMode: RoundingMode::HalfUp); + } finally { + assertVariableCertainty(TrinaryLogic::createYes(), $result); + } + } + // --- Comparison methods --- public function compareToWithInt(Money $a): void