Skip to content

Commit b41777b

Browse files
committed
add number, numeric, integerish, floatish
1 parent 19633f7 commit b41777b

File tree

12 files changed

+293
-100
lines changed

12 files changed

+293
-100
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
## Numbers
3+
4+
| type | accepts | returns |
5+
|------------|--------------------------------|------------------------------------|
6+
| floatish | 10, 15.5, '14', '14.1', '14.0' | all float |
7+
| integerish | 10, 15.5, '14', '14.1', '14.0' | all int |
8+
| numeric | 10, 15.5, '14', '14.1', '14.0' | int, float, string, string, string |
9+
| number | 10, 15.5, '14', '14.1', '14.0' | int, float, int, float, int |

bin/.gitignore

Lines changed: 0 additions & 3 deletions
This file was deleted.

bin/composer.json

Lines changed: 0 additions & 8 deletions
This file was deleted.

bin/generate.php

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?php declare(strict_types = 1);
22

3+
use Generator\TypeStruct;
34
use Nette\Neon\Neon;
45
use Nette\PhpGenerator\ClassType;
56
use Nette\PhpGenerator\Helpers;
@@ -12,9 +13,10 @@
1213
use Nette\Utils\Strings;
1314
use Nette\Utils\Type;
1415
use Utilitte\Asserts\Exceptions\AssertionFailedException;
16+
use Utilitte\Asserts\Helper\TypeHelper;
1517
use Utilitte\Asserts\TypeAssert;
1618

17-
require __DIR__ . '/vendor/autoload.php';
19+
require __DIR__ . '/../vendor/autoload.php';
1820

1921
class DefaultPrinter extends Printer
2022
{
@@ -64,14 +66,21 @@ public function printClass(ClassType $class, PhpNamespace $namespace = null): st
6466
class TypeAssertionGenerator
6567
{
6668

69+
/** @var TypeStruct[] */
70+
private array $types;
71+
6772
public function __construct(
6873
private string $arrayTypeAssertTraitName,
6974
private string $typeAssertTraitName,
7075
private string $typeAssertClassName,
7176
private string $typeAssertionException,
72-
private array $types,
77+
array $types,
7378
)
7479
{
80+
$this->types = array_map(
81+
fn (stdClass $type) => new TypeStruct($type->prolog, $type->epilog, $type->asserts, $type->returns, $type->arguments),
82+
$types
83+
);
7584
}
7685

7786
public function runArray(array $types): string
@@ -102,6 +111,7 @@ public function run(array $types): string
102111
$file->setStrictTypes();
103112
$namespace = $file->addNamespace(Helpers::extractNamespace($this->typeAssertTraitName));
104113
$namespace->addUse($this->typeAssertionException);
114+
$namespace->addUse(TypeHelper::class);
105115
$class = $namespace->addTrait(Helpers::extractShortName($this->typeAssertTraitName));
106116
$class->addComment('@internal');
107117

@@ -141,27 +151,28 @@ private function generate(Type $type, ClassType $class, PhpNamespace $namespace)
141151

142152
$expandedType = $this->typeToStringExpanded($type);
143153

144-
$assertions = [];
145-
$epilogs = [];
146-
$prologs = [];
154+
$structs = [];
147155
foreach ($type->getTypes() as $singleType) {
148-
$struct = $this->types[$singleType->getSingleName()];
149-
$assertions = array_merge($assertions, $struct->assertions);
150-
if ($struct->prolog) {
151-
$prologs[] = $struct->prolog;
152-
}
153-
if ($struct->epilog) {
154-
$epilogs[] = $struct->epilogs;
156+
$structs[] = $this->types[$singleType->getSingleName()];
157+
}
158+
$struct = TypeStruct::combine(...$structs);
159+
160+
foreach (TypeStruct::combine(...$structs)->arguments as $argument) {
161+
if ($argument->default !== PHP_INT_MAX - 42) {
162+
$parameter = $method->addParameter($argument->name, $argument->default);
163+
} else {
164+
$parameter = $method->addParameter($argument->name);
155165
}
166+
$parameter->setType($argument->type);
156167
}
157168

158-
if ($prologs) {
159-
$method->addBody(implode("\n", $prologs));
169+
if ($struct->prolog) {
170+
$method->addBody($struct->prolog);
160171
$method->addBody('');
161172
}
162173

163174
$method->addBody(
164-
sprintf('if (%s) {', $this->generateCondition($assertions))
175+
sprintf('if (%s) {', $struct->getAssertion())
165176
);
166177
$method->addBody(
167178
sprintf(
@@ -172,10 +183,10 @@ private function generate(Type $type, ClassType $class, PhpNamespace $namespace)
172183
);
173184
$method->addBody('}');
174185

175-
if ($epilogs) {
176-
$method->addBody('');
177-
$method->addBody(implode("\n", $epilogs));
178-
}
186+
// if ($epilogs) {
187+
// $method->addBody('');
188+
// $method->addBody(implode("\n", $epilogs));
189+
// }
179190

180191
$method->addBody('');
181192
$method->addBody('return $value;');
@@ -230,10 +241,15 @@ private function returnType(Type $type): string
230241

231242
$data = (new Processor())->process(Expect::structure([
232243
'types' => Expect::arrayOf(Expect::structure([
233-
'assertions' => Expect::anyOf(Expect::string(), Expect::arrayOf('string'))->castTo('array')->default([]),
234-
'returns' => Expect::anyOf(Expect::string(), Expect::arrayOf('string'))->castTo('array')->default([]),
244+
'asserts' => Expect::anyOf(Expect::string(), Expect::arrayOf('string'))->castTo('array')->required(),
245+
'returns' => Expect::anyOf(Expect::string(), Expect::arrayOf('string'))->castTo('array')->required(),
235246
'prolog' => Expect::string()->default(null),
236247
'epilog' => Expect::string()->default(null),
248+
'arguments' => Expect::listOf(Expect::structure([
249+
'name' => Expect::string()->required(),
250+
'type' => Expect::string()->required(),
251+
'default' => Expect::mixed(PHP_INT_MAX - 42),
252+
])),
237253
])),
238254
'generate' => Expect::structure([
239255
'builtIn' => Expect::arrayOf(Expect::string()),

bin/methods.neon

Lines changed: 45 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,58 @@
11
types:
22
int:
3-
assertions: '!is_int($value)'
3+
asserts: is_int
4+
returns: int
45
float:
5-
assertions: '!is_float($value)'
6+
asserts: is_float
7+
returns: float
68
array:
7-
assertions: '!is_array($value)'
9+
asserts: is_array
10+
returns: array
811
object:
9-
assertions: '!is_object($value)'
12+
asserts: is_object
13+
returns: object
1014
string:
11-
assertions: '!is_string($value)'
15+
asserts: is_string
16+
returns: string
1217
bool:
13-
assertions: '!is_bool($value)'
18+
asserts: is_bool
19+
returns: bool
1420
scalar:
1521
returns: [int, float, string, bool]
16-
assertions: '!is_scalar($value)'
22+
asserts: is_scalar
1723
callable:
18-
assertions: '!is_callable($value)'
24+
returns: callable
25+
asserts: is_callable
1926
iterable:
20-
assertions: '!is_iterable($value)'
27+
returns: iterable
28+
asserts: is_iterable
2129
null:
22-
assertions: '$value !== null'
30+
returns: null
31+
asserts: is_null
2332

24-
numeric:
25-
assertions: '!is_float($value) && !is_int($value)'
26-
returns: [float, int]
27-
prolog: """
28-
if (is_string($value) && is_numeric($value)) {
29-
$value = str_contains($value, '.') ? (float) $value : (int) $value;
30-
}
31-
"""
32-
numericFloat:
33-
assertions: '!is_float($value)'
33+
floatish:
34+
asserts: [is_float]
3435
returns: float
3536
prolog: """
36-
if (is_string($value) && is_numeric($value)) {
37-
$value = (float) preg_replace('#\\.0*$#D', '', $value);
38-
}
37+
$value = TypeHelper::tryToFloat($value);
3938
"""
40-
numericInt:
41-
assertions: '!is_int($value)'
39+
integerish:
40+
asserts: [is_int]
4241
returns: int
4342
prolog: """
44-
if (is_string($value) && is_numeric($value) && preg_match('#^[0-9]+$#D', $value)) {
45-
$value = (int) preg_replace('#\\.0*$#D', '', $value);
46-
}
43+
$value = TypeHelper::tryToInt($value);
44+
"""
45+
number:
46+
asserts: [is_int, is_float]
47+
returns: [float, int]
48+
prolog: """
49+
$value = TypeHelper::tryToNumber($value);
50+
"""
51+
numeric:
52+
asserts: [is_int, is_float, is_numeric]
53+
returns: [float, int, string]
54+
prolog: """
55+
$value = TypeHelper::tryToNumeric($value);
4756
"""
4857

4958
generate:
@@ -68,11 +77,15 @@ generate:
6877
- callable|null
6978
- iterable
7079
- iterable|null
80+
7181
special:
7282
- scalar
7383
- scalar|null
7484
- numeric
75-
- numericInt
76-
- numericInt|null
77-
- numericFloat
78-
- numericFloat|null
85+
- numeric|null
86+
- integerish
87+
- integerish|null
88+
- floatish
89+
- floatish|null
90+
- number
91+
- number|null

bin/src/TypeStruct.php

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Generator;
4+
5+
final class TypeStruct
6+
{
7+
8+
private const SUBS = [
9+
'is_null' => '$value !== null',
10+
];
11+
12+
/**
13+
* @param string[] $asserts
14+
* @param string[] $returns
15+
* @param mixed[] $arguments
16+
*/
17+
public function __construct(
18+
public ?string $prolog,
19+
public ?string $epilog,
20+
public array $asserts,
21+
public array $returns,
22+
public array $arguments,
23+
)
24+
{
25+
}
26+
27+
public static function combine(TypeStruct ... $structs): self
28+
{
29+
$prolog = '';
30+
$epilog = '';
31+
$asserts = [];
32+
$returns = [];
33+
$arguments = [];
34+
foreach ($structs as $struct) {
35+
$prolog .= $struct->prolog;
36+
if ($prolog) {
37+
$prolog .= "\n";
38+
}
39+
40+
$epilog .= $struct->epilog;
41+
if ($epilog) {
42+
$epilog .= "\n";
43+
}
44+
45+
$asserts = array_merge($asserts, $struct->asserts);
46+
$returns = array_merge($returns, $struct->returns);
47+
$arguments = array_merge($arguments, $struct->arguments);
48+
}
49+
50+
$prolog = trim($prolog);
51+
$epilog = trim($epilog);
52+
53+
return new self($prolog ?: null, $epilog ?: null, array_unique($asserts), array_unique($returns), $arguments);
54+
}
55+
56+
public function getAssertion(): string
57+
{
58+
$asserts = [];
59+
foreach ($this->asserts as $assert) {
60+
if (isset(self::SUBS[$assert])) {
61+
$asserts[] = self::SUBS[$assert];
62+
63+
continue;
64+
}
65+
if (!str_contains($assert, '$')) {
66+
$assert = $assert . '($value)';
67+
}
68+
69+
$asserts[] = '!' . $assert;
70+
}
71+
72+
return implode(' && ', $asserts);
73+
}
74+
75+
}

composer.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,19 @@
55
"Utilitte\\Asserts\\": "src"
66
}
77
},
8+
"autoload-dev": {
9+
"psr-4": {
10+
"Generator\\": "bin/src"
11+
}
12+
},
813
"require": {
914
"php": ">= 8.0",
1015
"nette/tester": "^2.4",
1116
"nette/utils": "^3.2"
1217
},
1318
"require-dev": {
14-
"nette/neon": "^3.3"
19+
"nette/neon": "^3.3",
20+
"nette/schema": "^1.2",
21+
"nette/php-generator": "^3.6"
1522
}
1623
}

src/Helper/TypeHelper.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Utilitte\Asserts\Helper;
4+
5+
final class TypeHelper
6+
{
7+
8+
public static function tryToNumeric(mixed $value): mixed
9+
{
10+
if (is_numeric($value)) {
11+
$value = trim($value);
12+
}
13+
14+
return $value;
15+
}
16+
17+
public static function tryToFloat(mixed $value): mixed
18+
{
19+
if (is_numeric($value)) {
20+
return (float) $value;
21+
}
22+
23+
return $value;
24+
}
25+
26+
public static function tryToInt(mixed $value): mixed
27+
{
28+
if (is_numeric($value)) {
29+
return (int) $value;
30+
}
31+
32+
return $value;
33+
}
34+
35+
public static function tryToNumber(mixed $value): mixed
36+
{
37+
if (is_string($value) && is_numeric($value)) {
38+
$value = preg_replace('#\\.0*$#D', '', $value);
39+
40+
return str_contains($value, '.') ? (float) $value : (int) $value;
41+
}
42+
43+
return $value;
44+
}
45+
46+
}

0 commit comments

Comments
 (0)