Skip to content

Commit 4108441

Browse files
committed
added support for PHP 7.4 typed properties
1 parent 173dd9d commit 4108441

File tree

9 files changed

+130
-5
lines changed

9 files changed

+130
-5
lines changed

readme.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,14 +124,19 @@ If the property, constant, method or parameter already exist, it will be overwri
124124

125125
Members can be removed using `removeProperty()`, `removeConstant()`, `removeMethod()` or `removeParameter()`.
126126

127-
PHP Generator supports all new PHP 7.3 features:
127+
PHP Generator supports all new PHP 7.3 and 7.4 features:
128128

129129
```php
130130
$class = new Nette\PhpGenerator\ClassType('Demo');
131131

132132
$class->addConstant('ID', 123)
133133
->setVisibility('private'); // constant visiblity
134134

135+
$class->addProperty('items')
136+
->setType('array') // typed properites
137+
->setNullable()
138+
->setInitialized();
139+
135140
$method = $class->addMethod('getValue')
136141
->setReturnType('int') // method return type
137142
->setReturnNullable() // nullable return type
@@ -151,6 +156,8 @@ class Demo
151156
{
152157
private const ID = 123;
153158

159+
public ?array $items = null;
160+
154161
public function getValue(?int $id): ?int
155162
{
156163
return count($this->items);

src/PhpGenerator/Factory.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,13 +121,19 @@ public function fromParameterReflection(\ReflectionParameter $from): Parameter
121121

122122
public function fromPropertyReflection(\ReflectionProperty $from): Property
123123
{
124+
$defaults = $from->getDeclaringClass()->getDefaultProperties();
124125
$prop = new Property($from->getName());
125-
$prop->setValue($from->getDeclaringClass()->getDefaultProperties()[$prop->getName()] ?? null);
126+
$prop->setValue($defaults[$prop->getName()] ?? null);
126127
$prop->setStatic($from->isStatic());
127128
$prop->setVisibility($from->isPrivate()
128129
? ClassType::VISIBILITY_PRIVATE
129130
: ($from->isProtected() ? ClassType::VISIBILITY_PROTECTED : ClassType::VISIBILITY_PUBLIC)
130131
);
132+
if (PHP_VERSION_ID >= 70400 && ($type = $from->getType())) {
133+
$prop->setType($type->getName());
134+
$prop->setNullable($type->allowsNull());
135+
$prop->setInitialized(array_key_exists($prop->getName(), $defaults));
136+
}
131137
$prop->setComment(Helpers::unformatDocComment((string) $from->getDocComment()));
132138
return $prop;
133139
}

src/PhpGenerator/Printer.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,12 @@ public function printClass(ClassType $class, PhpNamespace $namespace = null): st
103103

104104
$properties = [];
105105
foreach ($class->getProperties() as $property) {
106+
$type = $property->getType();
106107
$properties[] = Helpers::formatDocComment((string) $property->getComment())
107-
. ($property->getVisibility() ?: 'public') . ($property->isStatic() ? ' static' : '') . ' $' . $property->getName()
108-
. ($property->getValue() === null ? '' : ' = ' . $this->dump($property->getValue()))
108+
. ($property->getVisibility() ?: 'public') . ($property->isStatic() ? ' static' : '') . ' '
109+
. ($type ? ($property->isNullable() ? '?' : '') . ($this->resolveTypes && $namespace ? $namespace->unresolveName($type) : $type) . ' ' : '')
110+
. '$' . $property->getName()
111+
. ($property->getValue() === null && !$property->isInitialized() ? '' : ' = ' . $this->dump($property->getValue()))
109112
. ";\n";
110113
}
111114

src/PhpGenerator/Property.php

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,15 @@ final class Property
3030
/** @var bool */
3131
private $static = false;
3232

33+
/** @var string|null */
34+
private $type;
35+
36+
/** @var bool */
37+
private $nullable = false;
38+
39+
/** @var bool */
40+
private $initialized = false;
41+
3342

3443
/**
3544
* @return static
@@ -61,4 +70,52 @@ public function isStatic(): bool
6170
{
6271
return $this->static;
6372
}
73+
74+
75+
/**
76+
* @return static
77+
*/
78+
public function setType(?string $val): self
79+
{
80+
$this->type = $val;
81+
return $this;
82+
}
83+
84+
85+
public function getType(): ?string
86+
{
87+
return $this->type;
88+
}
89+
90+
91+
/**
92+
* @return static
93+
*/
94+
public function setNullable(bool $state = true): self
95+
{
96+
$this->nullable = $state;
97+
return $this;
98+
}
99+
100+
101+
public function isNullable(): bool
102+
{
103+
return $this->nullable;
104+
}
105+
106+
107+
/**
108+
* @return static
109+
*/
110+
public function setInitialized(bool $state = true): self
111+
{
112+
$this->initialized = $state;
113+
return $this;
114+
}
115+
116+
117+
public function isInitialized(): bool
118+
{
119+
return $this->initialized;
120+
}
64121
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
/**
4+
* @phpVersion 7.4
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
use Nette\PhpGenerator\ClassType;
10+
11+
12+
require __DIR__ . '/../bootstrap.php';
13+
require __DIR__ . '/fixtures/classes.php74';
14+
15+
$res[] = ClassType::from(new Abc\Class7);
16+
17+
sameFile(__DIR__ . '/expected/ClassType.from.74.expect', implode("\n", $res));

tests/PhpGenerator/ClassType.phpt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@ $class->addProperty('handle')
5353
$class->addProperty('order')
5454
->setValue(new PhpLiteral('RecursiveIteratorIterator::SELF_FIRST'));
5555

56+
$class->addProperty('typed1')
57+
->setType('array');
58+
59+
$class->addProperty('typed2')
60+
->setType('array')
61+
->setNullable()
62+
->setInitialized();
63+
5664
$p = $class->addProperty('sections', ['first' => true])
5765
->setStatic(true);
5866

@@ -115,7 +123,7 @@ $class->setMethods(array_values($methods));
115123
Assert::same($methods, $class->getMethods());
116124

117125
$properties = $class->getProperties();
118-
Assert::count(3, $properties);
126+
Assert::count(5, $properties);
119127
$class->setProperties(array_values($properties));
120128
Assert::same($properties, $class->getProperties());
121129

tests/PhpGenerator/expected/ClassType.expect

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ abstract class Example extends ParentClass implements IExample, IOne
2121

2222
public $order = RecursiveIteratorIterator::SELF_FIRST;
2323

24+
public array $typed1;
25+
26+
public ?array $typed2 = null;
27+
2428
public static $sections = ['first' => true];
2529

2630

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
class Class7
2+
{
3+
public \A $a;
4+
5+
public ?\B $b;
6+
7+
public ?\C $c = null;
8+
9+
public ?int $i = 1;
10+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Abc;
6+
7+
class Class7
8+
{
9+
public \A $a;
10+
public ?\B $b;
11+
public ?\C $c = null;
12+
public ?int $i = 1;
13+
}

0 commit comments

Comments
 (0)