-
Notifications
You must be signed in to change notification settings - Fork 428
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Closes phpstan/phpstan#7511 Closes phpstan/phpstan#7224 Closes phpstan/phpstan#6997 Closes phpstan/phpstan#6556 Closes phpstan/phpstan#6181 Closes phpstan/phpstan#5743 Closes phpstan/phpstan#4708 Closes phpstan/phpstan#3821 Closes phpstan/phpstan#2911 Closes phpstan/phpstan#7156 Closes phpstan/phpstan#6728 Closes phpstan/phpstan#6364 Closes phpstan/phpstan#5758
- Loading branch information
1 parent
c968ca1
commit 5d7a1a5
Showing
25 changed files
with
898 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
<?php declare(strict_types=1); | ||
|
||
namespace Bug2911; | ||
|
||
use Exception; | ||
use function PHPStan\Testing\assertType; | ||
|
||
class MutatorConfig | ||
{ | ||
/** | ||
* @return array<mixed> | ||
*/ | ||
public function getMutatorSettings(): array | ||
{ | ||
return []; | ||
} | ||
} | ||
|
||
final class ArrayItemRemoval | ||
{ | ||
private const DEFAULT_SETTINGS = [ | ||
'remove' => 'first', | ||
'limit' => PHP_INT_MAX, | ||
]; | ||
|
||
/** | ||
* @var string first|last|all | ||
*/ | ||
private $remove; | ||
|
||
/** | ||
* @var int | ||
*/ | ||
private $limit; | ||
|
||
public function __construct(MutatorConfig $config) | ||
{ | ||
$settings = $this->getResultSettings($config->getMutatorSettings()); | ||
|
||
$this->remove = $settings['remove']; | ||
$this->limit = $settings['limit']; | ||
} | ||
|
||
/** | ||
* @param array<string, mixed> $settings | ||
* | ||
* @return array{remove: string, limit: int} | ||
*/ | ||
private function getResultSettings(array $settings): array | ||
{ | ||
$settings = array_merge(self::DEFAULT_SETTINGS, $settings); | ||
assertType('non-empty-array<string, mixed>', $settings); | ||
|
||
if (!is_string($settings['remove'])) { | ||
throw $this->configException($settings, 'remove'); | ||
} | ||
|
||
assertType("non-empty-array<string, mixed>&hasOffsetValue('remove', string)", $settings); | ||
|
||
$settings['remove'] = strtolower($settings['remove']); | ||
|
||
assertType("non-empty-array<string, mixed>&hasOffsetValue('remove', string)", $settings); | ||
|
||
if (!in_array($settings['remove'], ['first', 'last', 'all'], true)) { | ||
throw $this->configException($settings, 'remove'); | ||
} | ||
|
||
assertType("non-empty-array<string, mixed>&hasOffsetValue('remove', 'all'|'first'|'last')", $settings); | ||
|
||
if (!is_numeric($settings['limit']) || $settings['limit'] < 1) { | ||
throw $this->configException($settings, 'limit'); | ||
} | ||
assertType("non-empty-array<string, mixed>&hasOffsetValue('limit', float|int<1, max>|numeric-string)&hasOffsetValue('remove', 'all'|'first'|'last')", $settings); | ||
|
||
$settings['limit'] = (int) $settings['limit']; | ||
|
||
assertType("non-empty-array<string, mixed>&hasOffsetValue('limit', float|int<1, max>|numeric-string)&hasOffsetValue('limit', int)&hasOffsetValue('remove', 'all'|'first'|'last')", $settings); | ||
|
||
return $settings; | ||
} | ||
|
||
/** | ||
* @param array<string, mixed> $settings | ||
*/ | ||
private function configException(array $settings, string $property): Exception | ||
{ | ||
$value = $settings[$property]; | ||
|
||
return new Exception(sprintf( | ||
'Invalid configuration of ArrayItemRemoval mutator. Setting `%s` is invalid (%s)', | ||
$property, | ||
is_scalar($value) ? $value : '<' . strtoupper(gettype($value)) . '>' | ||
)); | ||
} | ||
} | ||
|
||
final class ArrayItemRemoval2 | ||
{ | ||
private const DEFAULT_SETTINGS = [ | ||
'remove' => 'first', | ||
'limit' => PHP_INT_MAX, | ||
]; | ||
|
||
/** | ||
* @param array<string, mixed> $settings | ||
* | ||
* @return array{remove: string, limit: int} | ||
*/ | ||
private function getResultSettings(array $settings): array | ||
{ | ||
$settings = array_merge(self::DEFAULT_SETTINGS, $settings); | ||
|
||
assertType('non-empty-array<string, mixed>', $settings); | ||
|
||
if (!is_string($settings['remove'])) { | ||
throw new Exception(); | ||
} | ||
|
||
assertType("non-empty-array<string, mixed>&hasOffsetValue('remove', string)", $settings); | ||
|
||
if (!is_int($settings['limit'])) { | ||
throw new Exception(); | ||
} | ||
|
||
assertType("non-empty-array<string, mixed>&hasOffsetValue('limit', int)&hasOffsetValue('remove', string)", $settings); | ||
|
||
return $settings; | ||
} | ||
|
||
|
||
/** | ||
* @param array<mixed> $array | ||
*/ | ||
function foo(array $array): void { | ||
$array['bar'] = 'string'; | ||
|
||
assertType("hasOffsetValue('bar', 'string')&non-empty-array", $array); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
<?php | ||
|
||
namespace Bug4708Two; | ||
|
||
use function PHPStan\Testing\assertType; | ||
|
||
/** | ||
* @param string[] $columns | ||
* | ||
* @return string[]|false | ||
*/ | ||
|
||
function GenerateData($columns) | ||
{ | ||
$res = []; | ||
|
||
if (!empty($columns)) | ||
{ | ||
foreach ($columns as $col) | ||
{ | ||
$res[$col] = $col; | ||
} | ||
} | ||
else | ||
{ | ||
$res = false; | ||
} | ||
|
||
return $res; | ||
} | ||
|
||
/** | ||
* Get a bunch of configurational fields about an ASC. | ||
* | ||
* @return array | ||
*/ | ||
|
||
function GetASCConfig() | ||
{ | ||
$columns = ['bsw', 'bew', 'utc', 'ssi']; | ||
|
||
$result = GenerateData($columns); | ||
|
||
if ($result === FALSE) | ||
{ | ||
$result = ['result' => FALSE, | ||
'dberror' => 'xyz']; | ||
} | ||
else | ||
{ | ||
assertType('array<string>', $result); | ||
if (!isset($result['bsw'])) | ||
{ | ||
assertType('array<string>', $result); | ||
$result['bsw'] = 1; | ||
assertType("non-empty-array<1|string>&hasOffsetValue('bsw', 1)", $result); | ||
} | ||
else | ||
{ | ||
assertType("array<string>&hasOffsetValue('bsw', string)", $result); | ||
$result['bsw'] = (int) $result['bsw']; | ||
assertType('*NEVER*', $result); // should be non-empty-array<string|int>&hasOffsetValue('bsw', int) | ||
} | ||
|
||
assertType("non-empty-array<1|string>&hasOffsetValue('bsw', 1)", $result); // should be non-empty-array<1|string>&hasOffsetValue('bsw', int) | ||
|
||
if (!isset($result['bew'])) | ||
{ | ||
$result['bew'] = 5; | ||
} | ||
else | ||
{ | ||
$result['bew'] = (int) $result['bew']; | ||
} | ||
|
||
assertType("non-empty-array<int|string>&hasOffsetValue('bsw', 1)", $result); // should be non-empty-array<int|string>&hasOffsetValue('bsw', int)&hasOffsetValue('bew', int) | ||
|
||
foreach (['utc', 'ssi'] as $field) | ||
{ | ||
if (array_key_exists($field, $result)) | ||
{ | ||
$result[$field] = (int) $result[$field]; | ||
} | ||
} | ||
|
||
assertType("non-empty-array<int|string>&hasOffsetValue('bsw', 1)", $result); // should be non-empty-array<int|string>&hasOffsetValue('bsw', int)&hasOffsetValue('bew', int) | ||
} | ||
|
||
assertType('non-empty-array<int|string|false>', $result); | ||
|
||
return $result; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
<?php declare(strict_types = 1); | ||
|
||
namespace Bug6556; | ||
|
||
use function PHPStan\Testing\assertType; | ||
|
||
/** | ||
* @phpstan-type Test array{ | ||
* test1?: string, | ||
* test2?: string, | ||
* test3?: array{title: string, details: string} | ||
* } | ||
*/ | ||
class TestClass { | ||
/** | ||
* @param Test $testArg | ||
*/ | ||
function testFunc(array $testArg): void { | ||
assertType('array{test1?: string, test2?: string, test3?: array{title: string, details: string}}', $testArg); | ||
$testKeys = [ | ||
'test1', | ||
'test2' | ||
]; | ||
|
||
$result = ''; | ||
|
||
foreach ($testKeys as $option) { | ||
if (\array_key_exists($option, $testArg)) { | ||
$result .= '<p>' . $testArg[$option] . '</p>'; | ||
} | ||
} | ||
|
||
assertType('array{test1?: string, test2?: string, test3?: array{title: string, details: string}}', $testArg); | ||
|
||
if (\array_key_exists('test3', $testArg)) { | ||
$result .= '<p>'; | ||
$result .= '<b>' . $testArg['test3']['title'] . '</b><br>'; | ||
$result .= $testArg['test3']['details']; | ||
$result .= '</p>'; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<?php | ||
|
||
namespace Bug6728; | ||
|
||
use function PHPStan\Testing\assertType; | ||
|
||
class HelloWorld | ||
{ | ||
/** @return array{success: false, errorReason: string}|array{success: true, id: int} */ | ||
public function sayHello(): array | ||
{ | ||
if (date('d') === '01') { | ||
return ['success' => false, 'errorReason' => 'Test']; | ||
} | ||
|
||
return ['success' => true, 'id' => 1]; | ||
} | ||
|
||
public function test(): void | ||
{ | ||
$retArr = $this->sayHello(); | ||
assertType('array{success: false, errorReason: string}|array{success: true, id: int}', $retArr); | ||
if ($retArr['success'] === true) { | ||
assertType('array{success: true, id: int}', $retArr); | ||
assertType('true', isset($retArr['id'])); | ||
assertType('int', $retArr['id']); | ||
} else { | ||
assertType('array{success: false, errorReason: string}', $retArr); | ||
assertType('string', $retArr['errorReason']); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
<?php | ||
|
||
namespace Bug7224; | ||
|
||
|
||
use function PHPStan\Testing\assertType; | ||
|
||
/** | ||
* @param array{id: string, name?: string, team_name?: string|null} $roleUpdates | ||
*/ | ||
function processUpdates(array $roleUpdates): void { | ||
assertType('array{id: string, name?: string, team_name?: string|null}', $roleUpdates); | ||
if (!isset($roleUpdates['team_name']) && !isset($roleUpdates['name'])) { | ||
return; | ||
} | ||
|
||
assertType('array{id: string, name?: string, team_name?: string|null}', $roleUpdates); | ||
|
||
$fieldUpdates = ['updated_at' => new \DateTime()]; | ||
|
||
if (\array_key_exists('team_name', $roleUpdates)) { | ||
$fieldUpdates['team_name'] = $roleUpdates['team_name']; | ||
} | ||
|
||
if (isset($roleUpdates['name'])) { | ||
$fieldUpdates['name'] = $roleUpdates['name']; | ||
} | ||
|
||
saveUpdates($roleUpdates['id'], $fieldUpdates); | ||
} | ||
|
||
/** | ||
* @param array{id: string, name?: string, team_name?: string|null} $roleUpdates | ||
*/ | ||
function processUpdates2(array $roleUpdates): void { | ||
assertType('array{id: string, name?: string, team_name?: string|null}', $roleUpdates); | ||
if (!isset($roleUpdates['team_name'])) { | ||
|
||
} | ||
|
||
assertType('array{id: string, name?: string, team_name?: string|null}', $roleUpdates); | ||
|
||
$fieldUpdates = ['updated_at' => new \DateTime()]; | ||
|
||
if (\array_key_exists('team_name', $roleUpdates)) { | ||
$fieldUpdates['team_name'] = $roleUpdates['team_name']; | ||
} | ||
|
||
if (isset($roleUpdates['name'])) { | ||
$fieldUpdates['name'] = $roleUpdates['name']; | ||
} | ||
|
||
saveUpdates($roleUpdates['id'], $fieldUpdates); | ||
} | ||
|
||
/** | ||
* @param array<string, mixed> $updatedFields | ||
*/ | ||
function saveUpdates(string $id, array $updatedFields): void { | ||
// ... | ||
} |
Oops, something went wrong.