Skip to content

Commit

Permalink
Merge d0ddef1 into b2b8690
Browse files Browse the repository at this point in the history
  • Loading branch information
staabm committed Dec 19, 2021
2 parents b2b8690 + d0ddef1 commit 52f6365
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 3 deletions.
19 changes: 18 additions & 1 deletion src/Type/Php/PregSplitDynamicReturnTypeExtension.php
Expand Up @@ -3,6 +3,7 @@
namespace PHPStan\Type\Php;

use PhpParser\Node\Arg;
use PhpParser\Node\Expr\BinaryOp\BitwiseOr;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Name;
use PHPStan\Analyser\Scope;
Expand All @@ -15,6 +16,7 @@
use PHPStan\Type\Constant\ConstantBooleanType;
use PHPStan\Type\Constant\ConstantIntegerType;
use PHPStan\Type\DynamicFunctionReturnTypeExtension;
use PHPStan\Type\IntegerRangeType;
use PHPStan\Type\IntegerType;
use PHPStan\Type\StringType;
use PHPStan\Type\Type;
Expand Down Expand Up @@ -46,7 +48,7 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
if ($this->hasFlag($this->getConstant('PREG_SPLIT_OFFSET_CAPTURE'), $flagsArg, $scope)) {
$type = new ArrayType(
new IntegerType(),
new ConstantArrayType([new ConstantIntegerType(0), new ConstantIntegerType(1)], [new StringType(), new IntegerType()]),
new ConstantArrayType([new ConstantIntegerType(0), new ConstantIntegerType(1)], [new StringType(), IntegerRangeType::fromInterval(0, null)]),
);
return TypeCombinator::union($type, new ConstantBooleanType(false));
}
Expand All @@ -61,6 +63,21 @@ private function hasFlag(int $flag, ?Arg $expression, Scope $scope): bool
return false;
}

if ($expression->value instanceof BitwiseOr) {
$left = $expression->value->left;
$right = $expression->value->right;

$leftType = $scope->getType($left);
$rightType = $scope->getType($right);

if ($leftType instanceof ConstantIntegerType && ($leftType->getValue() & $flag) === $flag) {
return true;
}
if ($rightType instanceof ConstantIntegerType && ($rightType->getValue() & $flag) === $flag) {
return true;
}
}

$type = $scope->getType($expression->value);
return $type instanceof ConstantIntegerType && ($type->getValue() & $flag) === $flag;
}
Expand Down
21 changes: 19 additions & 2 deletions tests/PHPStan/Analyser/data/preg_split.php
Expand Up @@ -4,5 +4,22 @@

assertType('array<int, string>|false', preg_split('/-/', '1-2-3'));
assertType('array<int, string>|false', preg_split('/-/', '1-2-3', -1, PREG_SPLIT_NO_EMPTY));
assertType('array<int, array{string, int}>|false', preg_split('/-/', '1-2-3', -1, PREG_SPLIT_OFFSET_CAPTURE));
assertType('array<int, array{string, int}>|false', preg_split('/-/', '1-2-3', -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE));
assertType('array<int, array{string, int<0, max>}>|false', preg_split('/-/', '1-2-3', -1, PREG_SPLIT_OFFSET_CAPTURE));
assertType('array<int, array{string, int<0, max>}>|false', preg_split('/-/', '1-2-3', -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE));

class HelloWorld
{
/**
* @param string $pattern
* @param string $subject
* @param int $limit
* @param int $flags PREG_SPLIT_NO_EMPTY or PREG_SPLIT_DELIM_CAPTURE
* @return list<array{string, int}>
* @phpstan-return list<array{string, int<0, max>}>
*/
public static function splitWithOffset($pattern, $subject, $limit = -1, $flags = 0)
{
assertType('array<int, array{string, int<0, max>}>|false', preg_split($pattern, $subject, $limit, $flags | PREG_SPLIT_OFFSET_CAPTURE));
assertType('array<int, array{string, int<0, max>}>|false', preg_split($pattern, $subject, $limit, PREG_SPLIT_OFFSET_CAPTURE | $flags));
}
}

0 comments on commit 52f6365

Please sign in to comment.