Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/1.5.x' into 2.0.x
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Nov 20, 2024
2 parents 90c4275 + f36b6d6 commit f0e0abb
Show file tree
Hide file tree
Showing 8 changed files with 268 additions and 225 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
],
"require": {
"php": "^7.4 || ^8.0",
"phpstan/phpstan": "^2.0"
"phpstan/phpstan": "^2.0.3"
},
"conflict": {
"doctrine/collections": "<1.0",
Expand Down
3 changes: 1 addition & 2 deletions src/Type/Doctrine/Descriptors/BigIntType.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
namespace PHPStan\Type\Doctrine\Descriptors;

use Composer\InstalledVersions;
use PHPStan\Type\Accessory\AccessoryNumericStringType;
use PHPStan\Type\IntegerType;
use PHPStan\Type\StringType;
use PHPStan\Type\Type;
Expand All @@ -25,7 +24,7 @@ public function getWritableToPropertyType(): Type
return new IntegerType();
}

return TypeCombinator::intersect(new StringType(), new AccessoryNumericStringType());
return (new IntegerType())->toString();
}

public function getWritableToDatabaseType(): Type
Expand Down
9 changes: 2 additions & 7 deletions src/Type/Doctrine/Descriptors/DecimalType.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@

use Doctrine\DBAL\Connection;
use PHPStan\Doctrine\Driver\DriverDetector;
use PHPStan\Type\Accessory\AccessoryNumericStringType;
use PHPStan\Type\FloatType;
use PHPStan\Type\IntegerType;
use PHPStan\Type\IntersectionType;
use PHPStan\Type\StringType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeCombinator;
Expand All @@ -30,7 +28,7 @@ public function getType(): string

public function getWritableToPropertyType(): Type
{
return TypeCombinator::intersect(new StringType(), new AccessoryNumericStringType());
return (new FloatType())->toString();
}

public function getWritableToDatabaseType(): Type
Expand All @@ -57,10 +55,7 @@ public function getDatabaseInternalTypeForDriver(Connection $connection): Type
DriverDetector::PGSQL,
DriverDetector::PDO_PGSQL,
], true)) {
return new IntersectionType([
new StringType(),
new AccessoryNumericStringType(),
]);
return (new FloatType())->toString();
}

// not yet supported driver, return the old implementation guess
Expand Down
8 changes: 1 addition & 7 deletions src/Type/Doctrine/Descriptors/FloatType.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@

use Doctrine\DBAL\Connection;
use PHPStan\Doctrine\Driver\DriverDetector;
use PHPStan\Type\Accessory\AccessoryNumericStringType;
use PHPStan\Type\IntegerType;
use PHPStan\Type\IntersectionType;
use PHPStan\Type\StringType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeCombinator;
use function in_array;
Expand Down Expand Up @@ -41,10 +38,7 @@ public function getDatabaseInternalType(): Type
{
return TypeCombinator::union(
new \PHPStan\Type\FloatType(),
new IntersectionType([
new StringType(),
new AccessoryNumericStringType(),
]),
(new \PHPStan\Type\FloatType())->toString(),
);
}

Expand Down
74 changes: 57 additions & 17 deletions src/Type/Doctrine/Query/QueryResultTypeWalker.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
use PHPStan\Php\PhpVersion;
use PHPStan\ShouldNotHappenException;
use PHPStan\TrinaryLogic;
use PHPStan\Type\Accessory\AccessoryLowercaseStringType;
use PHPStan\Type\Accessory\AccessoryNumericStringType;
use PHPStan\Type\Accessory\AccessoryUppercaseStringType;
use PHPStan\Type\ArrayType;
use PHPStan\Type\BooleanType;
use PHPStan\Type\Constant\ConstantBooleanType;
Expand Down Expand Up @@ -622,10 +624,10 @@ public function walkFunction($function): string
$type = $this->createFloat(false);

} elseif ($castedExprType->isNumericString()->yes()) {
$type = $this->createNumericString(false);
$type = $this->createNumericString(false, $castedExprType->isLowercaseString()->yes(), $castedExprType->isUppercaseString()->yes());

} else {
$type = TypeCombinator::union($this->createFloat(false), $this->createNumericString(false));
$type = TypeCombinator::union($this->createFloat(false), $this->createNumericString(false, false, true));
}

} else {
Expand Down Expand Up @@ -738,7 +740,7 @@ private function inferAvgFunction(AST\Functions\AvgFunction $function): Type

if ($this->driverType === DriverDetector::PDO_MYSQL || $this->driverType === DriverDetector::MYSQLI) {
if ($exprTypeNoNull->isInteger()->yes()) {
return $this->createNumericString($nullable);
return $this->createNumericString($nullable, true, true);
}

if ($exprTypeNoNull->isString()->yes() && !$exprTypeNoNull->isNumericString()->yes()) {
Expand All @@ -750,7 +752,7 @@ private function inferAvgFunction(AST\Functions\AvgFunction $function): Type

if ($this->driverType === DriverDetector::PGSQL || $this->driverType === DriverDetector::PDO_PGSQL) {
if ($exprTypeNoNull->isInteger()->yes()) {
return $this->createNumericString($nullable);
return $this->createNumericString($nullable, true, true);
}

return $this->generalizeConstantType($exprType, $nullable);
Expand Down Expand Up @@ -786,7 +788,7 @@ private function inferSumFunction(AST\Functions\SumFunction $function): Type

if ($this->driverType === DriverDetector::PDO_MYSQL || $this->driverType === DriverDetector::MYSQLI) {
if ($exprTypeNoNull->isInteger()->yes()) {
return $this->createNumericString($nullable);
return $this->createNumericString($nullable, true, true);
}

if ($exprTypeNoNull->isString()->yes() && !$exprTypeNoNull->isNumericString()->yes()) {
Expand All @@ -800,7 +802,7 @@ private function inferSumFunction(AST\Functions\SumFunction $function): Type
if ($exprTypeNoNull->isInteger()->yes()) {
return TypeCombinator::union(
$this->createInteger($nullable),
$this->createNumericString($nullable),
$this->createNumericString($nullable, true, true),
);
}

Expand Down Expand Up @@ -837,19 +839,41 @@ private function createNonNegativeInteger(bool $nullable): Type
return $nullable ? TypeCombinator::addNull($integer) : $integer;
}

private function createNumericString(bool $nullable): Type
private function createNumericString(bool $nullable, bool $lowercase = false, bool $uppercase = false): Type
{
$numericString = TypeCombinator::intersect(
$types = [
new StringType(),
new AccessoryNumericStringType(),
);
];
if ($lowercase) {
$types[] = new AccessoryLowercaseStringType();
}
if ($uppercase) {
$types[] = new AccessoryUppercaseStringType();
}

$numericString = new IntersectionType($types);

return $nullable ? TypeCombinator::addNull($numericString) : $numericString;
}

private function createString(bool $nullable): Type
private function createString(bool $nullable, bool $lowercase = false, bool $uppercase = false): Type
{
$string = new StringType();
if ($lowercase || $uppercase) {
$types = [
new StringType(),
];
if ($lowercase) {
$types[] = new AccessoryLowercaseStringType();
}
if ($uppercase) {
$types[] = new AccessoryUppercaseStringType();
}
$string = new IntersectionType($types);
} else {
$string = new StringType();
}

return $nullable ? TypeCombinator::addNull($string) : $string;
}

Expand Down Expand Up @@ -895,10 +919,18 @@ private function generalizeConstantType(Type $type, bool $makeNullable): Type
$result = $this->createFloat($containsNull);

} elseif ($typeNoNull->isNumericString()->yes()) {
$result = $this->createNumericString($containsNull);
$result = $this->createNumericString(
$containsNull,
$typeNoNull->isLowercaseString()->yes(),
$typeNoNull->isUppercaseString()->yes(),
);

} elseif ($typeNoNull->isString()->yes()) {
$result = $this->createString($containsNull);
$result = $this->createString(
$containsNull,
$typeNoNull->isLowercaseString()->yes(),
$typeNoNull->isUppercaseString()->yes(),
);

} else {
$result = $type;
Expand Down Expand Up @@ -1241,7 +1273,7 @@ public function walkSelectExpression($selectExpression): string

// e.g. 1.0 on sqlite results to '1' with pdo_stringify on PHP 8.1, but '1.0' on PHP 8.0 with no setup
// so we relax constant types and return just numeric-string to avoid those issues
$stringifiedFloat = $this->createNumericString(false);
$stringifiedFloat = $this->createNumericString(false, false, true);

if ($stringify->yes()) {
return $stringifiedFloat;
Expand Down Expand Up @@ -1773,7 +1805,11 @@ private function inferPlusMinusTimesType(array $termTypes): Type
}

if ($this->containsOnlyTypes($unionWithoutNull, [new IntegerType(), $this->createNumericString(false)])) {
return $this->createNumericString($nullable);
return $this->createNumericString(
$nullable,
$unionWithoutNull->toString()->isLowercaseString()->yes(),
$unionWithoutNull->toString()->isUppercaseString()->yes(),
);
}

if ($this->containsOnlyNumericTypes($unionWithoutNull)) {
Expand Down Expand Up @@ -1825,7 +1861,7 @@ private function inferDivisionType(array $termTypes): Type

if ($unionWithoutNull->isInteger()->yes()) {
if ($this->driverType === DriverDetector::MYSQLI || $this->driverType === DriverDetector::PDO_MYSQL) {
return $this->createNumericString($nullable);
return $this->createNumericString($nullable, true, true);
} elseif ($this->driverType === DriverDetector::PDO_PGSQL || $this->driverType === DriverDetector::PGSQL || $this->driverType === DriverDetector::SQLITE3 || $this->driverType === DriverDetector::PDO_SQLITE) {
return $this->createInteger($nullable);
}
Expand Down Expand Up @@ -1853,7 +1889,11 @@ private function inferDivisionType(array $termTypes): Type
}

if ($this->containsOnlyTypes($unionWithoutNull, [new IntegerType(), $this->createNumericString(false)])) {
return $this->createNumericString($nullable);
return $this->createNumericString(
$nullable,
$unionWithoutNull->toString()->isLowercaseString()->yes(),
$unionWithoutNull->toString()->isUppercaseString()->yes(),
);
}

if ($this->containsOnlyTypes($unionWithoutNull, [new FloatType(), $this->createNumericString(false)])) {
Expand Down
Loading

0 comments on commit f0e0abb

Please sign in to comment.