Skip to content

Commit 3093b89

Browse files
authored
Merge pull request #320 from webmozarts/feature/2-0
Start v2.0 preparation
2 parents 9be6926 + 80b7882 commit 3093b89

File tree

116 files changed

+4577
-5036
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

116 files changed

+4577
-5036
lines changed

.github/workflows/ci.yaml

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
- name: Install PHP
2525
uses: shivammathur/setup-php@v2
2626
with:
27-
php-version: '8.3'
27+
php-version: '8.4'
2828
coverage: none
2929
extensions: mbstring
3030

@@ -40,14 +40,15 @@ jobs:
4040
run: >-
4141
composer run cs-check
4242
43-
- name: Run backwards compatibility check
44-
run: >-
45-
composer run bc-check
46-
4743
- name: Run static analysis
4844
run: >-
4945
composer run static-analysis
5046
47+
# Disabled for version 2.0, since there is no BC promise at this time.
48+
# - name: Run backwards compatibility check
49+
# run: >-
50+
# composer run bc-check
51+
5152
tests:
5253
name: Tests
5354

@@ -56,11 +57,6 @@ jobs:
5657
strategy:
5758
matrix:
5859
php-version:
59-
- "7.2"
60-
- "7.3"
61-
- "7.4"
62-
- "8.0"
63-
- "8.1"
6460
- "8.2"
6561
- "8.3"
6662
- "8.4"
@@ -76,7 +72,7 @@ jobs:
7672
php-version: "${{ matrix.php-version }}"
7773
coverage: none
7874
extensions: mbstring
79-
tools: phpunit:8
75+
tools: phpunit:11
8076

8177
- name: Install dependencies
8278
run: composer install
@@ -92,7 +88,7 @@ jobs:
9288
strategy:
9389
matrix:
9490
php-version:
95-
- "7.4"
91+
- "8.2"
9692
- "8.3"
9793
- "8.4"
9894
- "8.5"
@@ -107,7 +103,7 @@ jobs:
107103
php-version: "${{ matrix.php-version }}"
108104
coverage: none
109105
extensions: mbstring
110-
tools: phpunit:8
106+
tools: phpunit:11
111107

112108
- name: Install dependencies
113109
run: composer install

CHANGELOG.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
Changelog
22
=========
33

4-
## UNRELEASED
4+
## 2.0.0 (UNRELEASED)
5+
6+
### Changed
7+
8+
- **BREAKING**: Minimum PHP version is now 8.2 (was 7.2).
9+
- Updated CI/CD test matrix to test PHP 8.2, 8.3, 8.4, and 8.5.
10+
- Updated development tools (PHPUnit, Psalm, PHP-CS-Fixer) to supported versions.
11+
- Added explicit return types and parameter types to all methods in both source code and tests.
12+
- Remove deprecated `isTraversable` (use `isIterable` or `isInstanceOf` instead).
513

614
## 1.12.1
715

README.md

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ Method | Description
9898
`resource($value, $type = null, $message = '')` | Check that a value is a resource
9999
`isCallable($value, $message = '')` | Check that a value is a callable
100100
`isArray($value, $message = '')` | Check that a value is an array
101-
`isTraversable($value, $message = '')` (deprecated) | Check that a value is an array or a `\Traversable`
102101
`isIterable($value, $message = '')` | Check that a value is an array or a `\Traversable`
103102
`isCountable($value, $message = '')` | Check that a value is an array or a `\Countable`
104103
`isInstanceOf($value, $class, $message = '')` | Check that a value is an `instanceof` a class
@@ -112,26 +111,28 @@ Method | Description
112111

113112
### Comparison Assertions
114113

115-
Method | Description
116-
----------------------------------------------- | ------------------------------------------------------------------
117-
`true($value, $message = '')` | Check that a value is `true`
118-
`false($value, $message = '')` | Check that a value is `false`
119-
`notFalse($value, $message = '')` | Check that a value is not `false`
120-
`null($value, $message = '')` | Check that a value is `null`
121-
`notNull($value, $message = '')` | Check that a value is not `null`
122-
`isEmpty($value, $message = '')` | Check that a value is `empty()`
123-
`notEmpty($value, $message = '')` | Check that a value is not `empty()`
124-
`eq($value, $value2, $message = '')` | Check that a value equals another (`==`)
125-
`notEq($value, $value2, $message = '')` | Check that a value does not equal another (`!=`)
126-
`same($value, $value2, $message = '')` | Check that a value is identical to another (`===`)
127-
`notSame($value, $value2, $message = '')` | Check that a value is not identical to another (`!==`)
128-
`greaterThan($value, $value2, $message = '')` | Check that a value is greater than another
129-
`greaterThanEq($value, $value2, $message = '')` | Check that a value is greater than or equal to another
130-
`lessThan($value, $value2, $message = '')` | Check that a value is less than another
131-
`lessThanEq($value, $value2, $message = '')` | Check that a value is less than or equal to another
132-
`range($value, $min, $max, $message = '')` | Check that a value is within a range
133-
`inArray($value, array $values, $message = '')` | Check that a value is one of a list of values
134-
`oneOf($value, array $values, $message = '')` | Check that a value is one of a list of values (alias of `inArray`)
114+
Method | Description
115+
----------------------------------------------------- | ------------------------------------------------------------------
116+
`true($value, $message = '')` | Check that a value is `true`
117+
`false($value, $message = '')` | Check that a value is `false`
118+
`notFalse($value, $message = '')` | Check that a value is not `false`
119+
`null($value, $message = '')` | Check that a value is `null`
120+
`notNull($value, $message = '')` | Check that a value is not `null`
121+
`isEmpty($value, $message = '')` | Check that a value is `empty()`
122+
`notEmpty($value, $message = '')` | Check that a value is not `empty()`
123+
`eq($value, $value2, $message = '')` | Check that a value equals another (`==`)
124+
`notEq($value, $value2, $message = '')` | Check that a value does not equal another (`!=`)
125+
`same($value, $value2, $message = '')` | Check that a value is identical to another (`===`)
126+
`notSame($value, $value2, $message = '')` | Check that a value is not identical to another (`!==`)
127+
`greaterThan($value, $value2, $message = '')` | Check that a value is greater than another
128+
`greaterThanEq($value, $value2, $message = '')` | Check that a value is greater than or equal to another
129+
`lessThan($value, $value2, $message = '')` | Check that a value is less than another
130+
`lessThanEq($value, $value2, $message = '')` | Check that a value is less than or equal to another
131+
`range($value, $min, $max, $message = '')` | Check that a value is within a range
132+
`inArray($value, array $values, $message = '')` | Check that a value is one of a list of values
133+
`notInArray($value, array $values, $message = '')` | Check that a value is not one of a list of values
134+
`oneOf($value, array $values, $message = '')` | Check that a value is one of a list of values (alias of `inArray`)
135+
`notOneOf($value, array $values, $message = '')` | Check that a value is not one of a list of values (alias of `notInArray`)
135136

136137
### String Assertions
137138

bin/src/MixinGenerator.php

Lines changed: 64 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,18 @@
55
namespace Webmozart\Assert\Bin;
66

77
use ArrayAccess;
8-
use Closure;
98
use Countable;
109
use ReflectionClass;
1110
use ReflectionException;
11+
use ReflectionIntersectionType;
1212
use ReflectionMethod;
13+
use ReflectionType;
14+
use ReflectionUnionType;
1315
use RuntimeException;
14-
use Throwable;
1516
use Webmozart\Assert\Assert;
17+
18+
use function array_map;
19+
use function implode;
1620
use function rtrim;
1721

1822
final class MixinGenerator
@@ -56,6 +60,8 @@ public function generate(): string
5660
<<<'PHP'
5761
<?php
5862
63+
declare(strict_types=1);
64+
5965
%s
6066
PHP
6167
,
@@ -69,9 +75,7 @@ private function namespace(): string
6975

7076
$namespace = sprintf("namespace %s;\n\n", $assert->getNamespaceName());
7177
$namespace .= sprintf("use %s;\n", ArrayAccess::class);
72-
$namespace .= sprintf("use %s;\n", Closure::class);
7378
$namespace .= sprintf("use %s;\n", Countable::class);
74-
$namespace .= sprintf("use %s;\n", Throwable::class);
7579
$namespace .= "\n";
7680

7781
$namespace .= $this->trait($assert);
@@ -200,6 +204,8 @@ private function assertion(ReflectionMethod $method, string $methodNameTemplate,
200204
$parameters = [];
201205
/** @psalm-var array<string, scalar|null> $parametersDefaults */
202206
$parametersDefaults = [];
207+
/** @var array<string, string> $parameterTypes */
208+
$parameterTypes = [];
203209
$parametersReflection = $method->getParameters();
204210

205211
foreach ($parametersReflection as $parameterReflection) {
@@ -212,6 +218,18 @@ private function assertion(ReflectionMethod $method, string $methodNameTemplate,
212218

213219
$parametersDefaults[$parameterReflection->name] = $defaultValue;
214220
}
221+
222+
if ($parameterReflection->hasType()) {
223+
if ($parameterReflection->name === 'value' && $typeTemplate) {
224+
$parameterTypes[$parameterReflection->name] = match ($typeTemplate) {
225+
'%s|null' => $this->reduceParameterType($parameterReflection->getType()),
226+
'iterable<%s>' => 'iterable',
227+
'iterable<%s|null>' => '?iterable',
228+
};
229+
} else {
230+
$parameterTypes[$parameterReflection->name] = $this->reduceParameterType($parameterReflection->getType());
231+
}
232+
}
215233
}
216234

217235
if (in_array($newMethodName, $this->skipMethods, true)) {
@@ -278,7 +296,7 @@ private function assertion(ReflectionMethod $method, string $methodNameTemplate,
278296
$phpdocLines[] = trim($comment);
279297
}
280298

281-
if ('deprecated' === $key || 'psalm-pure' === $key) {
299+
if ('deprecated' === $key || 'psalm-pure' === $key || 'psalm-assert' === $key || 'see' === $key) {
282300
$phpdocLines[] = '';
283301
}
284302
}
@@ -296,7 +314,24 @@ private function assertion(ReflectionMethod $method, string $methodNameTemplate,
296314
$phpdocLinesDeduplicatedEmptyLines[] = $line;
297315
}
298316

299-
return $this->staticMethod($newMethodName, $parameters, $parametersDefaults, $phpdocLinesDeduplicatedEmptyLines, $indent, $body);
317+
return $this->staticMethod($newMethodName, $parameters, $parameterTypes, $parametersDefaults, $phpdocLinesDeduplicatedEmptyLines, $indent, $body);
318+
}
319+
320+
private function reduceParameterType(ReflectionType $type): string
321+
{
322+
if ($type instanceof ReflectionIntersectionType) {
323+
return implode('&', array_map([$this, 'reduceParameterType'], $type->getTypes()));
324+
}
325+
326+
if ($type instanceof ReflectionUnionType) {
327+
return implode('|', array_map([$this, 'reduceParameterType'], $type->getTypes()));
328+
}
329+
330+
if ($type->getName() === 'mixed') {
331+
return $type->getName();
332+
}
333+
334+
return ($type->allowsNull() ? '?' : '') . $type->getName();
300335
}
301336

302337
private function applyTypeTemplate(string $type, string $typeTemplate): string
@@ -353,26 +388,27 @@ private function findLongestTypeAndName(array $values): array
353388
}
354389

355390
/**
356-
* @psalm-param list<string> $parameters
357-
* @psalm-param array<string, scalar|null> $defaultValues
358-
* @psalm-param list<string> $phpdocLines
391+
* @psalm-param list<string> $parameters
392+
* @psalm-param array<string, scalar|null> $defaults
393+
* @psalm-param list<string> $phpdocLines
359394
* @psalm-param callable(string,string):string $body
360395
*
361-
* @param string $name
362-
* @param string[] $parameters
363-
* @param string[] $defaultValues
364-
* @param array $phpdocLines
365-
* @param int $indent
366-
* @param callable $body
396+
* @param string $name
397+
* @param string[] $parameters
398+
* @param array<string, string> $types
399+
* @param string[] $defaults
400+
* @param array $phpdocLines
401+
* @param int $indent
402+
* @param callable $body
367403
*
368404
* @return string
369405
*/
370-
private function staticMethod(string $name, array $parameters, array $defaultValues, array $phpdocLines, int $indent, callable $body): string
406+
private function staticMethod(string $name, array $parameters, array $types, array $defaults, array $phpdocLines, int $indent, callable $body): string
371407
{
372408
$indentation = str_repeat(' ', $indent);
373409

374410
$staticFunction = $this->phpdoc($phpdocLines, $indent)."\n";
375-
$staticFunction .= $indentation.'public static function '.$name.$this->functionParameters($parameters, $defaultValues)."\n"
411+
$staticFunction .= $indentation.'public static function '.$name.$this->functionParameters($parameters, $types, $defaults).": void\n"
376412
.$indentation."{\n";
377413

378414
$firstParameter = '$'.array_shift($parameters);
@@ -387,15 +423,16 @@ private function staticMethod(string $name, array $parameters, array $defaultVal
387423
}
388424

389425
/**
390-
* @psalm-param list<string> $parameters
391-
* @psalm-param array<string, scalar|null> $defaultValues
426+
* @psalm-param list<string> $parameters
427+
* @psalm-param array<string, scalar|null> $defaults
392428
*
393-
* @param string[] $parameters
394-
* @param string[] $defaultValues
429+
* @param string[] $parameters
430+
* @param array<string, string> $types
431+
* @param string[] $defaults
395432
*
396433
* @return string
397434
*/
398-
private function functionParameters(array $parameters, array $defaultValues): string
435+
private function functionParameters(array $parameters, array $types, array $defaults): string
399436
{
400437
$result = '';
401438

@@ -404,10 +441,12 @@ private function functionParameters(array $parameters, array $defaultValues): st
404441
$result .= ', ';
405442
}
406443

407-
$result .= '$'.$parameter;
444+
Assert::keyExists($types, $parameter);
445+
446+
$result .= $types[$parameter].' $'.$parameter;
408447

409-
if (array_key_exists($parameter, $defaultValues)) {
410-
$defaultValue = null === $defaultValues[$parameter] ? 'null' : var_export($defaultValues[$parameter], true);
448+
if (array_key_exists($parameter, $defaults)) {
449+
$defaultValue = null === $defaults[$parameter] ? 'null' : var_export($defaults[$parameter], true);
411450

412451
$result .= ' = '.$defaultValue;
413452
}

composer.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,14 @@
1111
{
1212
"name": "Bernhard Schussek",
1313
"email": "[email protected]"
14+
},
15+
{
16+
"name": "Woody Gilk",
17+
"email": "[email protected]"
1418
}
1519
],
1620
"require": {
17-
"php": "^7.2 || ^8.0",
21+
"php": "^8.2",
1822
"ext-ctype": "*",
1923
"ext-date": "*",
2024
"ext-filter": "*"
@@ -37,7 +41,7 @@
3741
},
3842
"extra": {
3943
"branch-alias": {
40-
"dev-master": "1.10-dev"
44+
"dev-feature/2-0": "2.0-dev"
4145
}
4246
},
4347
"scripts": {

phpunit.xml.dist

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,17 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
32
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4-
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
5-
bootstrap="vendor/autoload.php"
6-
colors="true"
7-
verbose="true"
8-
>
9-
<testsuites>
10-
<testsuite name="Webmozart Assert Test Suite">
11-
<directory>./tests/</directory>
12-
<exclude>./tests/static-analysis</exclude>
13-
</testsuite>
14-
</testsuites>
15-
16-
<!-- Whitelist for code coverage -->
17-
<filter>
18-
<whitelist>
19-
<directory suffix=".php">./src/</directory>
20-
</whitelist>
21-
</filter>
3+
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
4+
bootstrap="vendor/autoload.php"
5+
colors="true">
6+
<testsuites>
7+
<testsuite name="Webmozart Assert Test Suite">
8+
<directory>./tests/</directory>
9+
<exclude>./tests/static-analysis</exclude>
10+
</testsuite>
11+
</testsuites>
12+
<source>
13+
<include>
14+
<directory suffix=".php">./src/</directory>
15+
</include>
16+
</source>
2217
</phpunit>

0 commit comments

Comments
 (0)