Skip to content

Commit b45b598

Browse files
committed
Copy doc block types from accessors to properties
1 parent 5553715 commit b45b598

File tree

7 files changed

+46
-30
lines changed

7 files changed

+46
-30
lines changed

demo/auto/AutoValue_Address.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*/
77
final class AutoValue_Address extends Address
88
{
9-
/** @var array */
9+
/** @var string[] */
1010
private $lines;
1111
/** @var ?string */
1212
private $city;
@@ -64,13 +64,15 @@ public function toBuilder(): \AutoValue\Demo\AddressBuilder
6464
public function withLines(string ...$lines): \AutoValue\Demo\Address
6565
{
6666
$result = clone $this;
67+
unset($result->__memoized);
6768
$result->lines = $lines;
6869
return $result;
6970
}
7071

7172
public function withCountry(string $country): \AutoValue\Demo\Address
7273
{
7374
$result = clone $this;
75+
unset($result->__memoized);
7476
$result->country = $country;
7577
return $result;
7678
}

demo/src/Address.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ public static function builder(): AddressBuilder
1313

1414
public abstract function toBuilder(): AddressBuilder;
1515

16+
/**
17+
* @return string[]
18+
*/
1619
public abstract function lines(): array;
1720

1821
public abstract function withLines(string ...$lines): self;

src/Property.php

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
<?php
22
namespace AutoValue;
33

4+
use phpDocumentor\Reflection\Type;
5+
use Roave\BetterReflection\Reflection\ReflectionMethod;
6+
use Roave\BetterReflection\Reflection\ReflectionProperty;
47
use Roave\BetterReflection\Reflection\ReflectionType;
58

69
/**
710
* @author Josh Di Fabio <[email protected]>
811
*/
912
class Property
1013
{
11-
public static function named(string $name): self
14+
public static function fromAccessorMethod(string $propertyName, ReflectionMethod $accessorMethod): self
1215
{
1316
$property = new self;
14-
$property->name = $name;
17+
$property->name = $propertyName;
18+
$property->accessorMethod = $accessorMethod;
1519
return $property;
1620
}
1721

@@ -20,26 +24,38 @@ public function name(): string
2024
return $this->name;
2125
}
2226

23-
public function type(): ?ReflectionType
27+
public function phpType(): ?ReflectionType
2428
{
25-
return $this->type;
29+
if (!$this->phpType) {
30+
$this->phpType = $this->accessorMethod->getReturnType();
31+
}
32+
return $this->phpType;
2633
}
2734

28-
public function withType(?ReflectionType $type): self
35+
public function docBlockType(): string
2936
{
30-
$result = clone $this;
31-
$result->type = $type;
32-
return $result;
37+
if (!isset($this->docBlockType)) {
38+
$docBlockTypes = $this->accessorMethod->getDocBlockReturnTypes();
39+
$this->docBlockType = $docBlockTypes
40+
? \implode('|', $docBlockTypes)
41+
: ($this->phpType()
42+
? generateTypeHint($this->phpType(), $this->accessorMethod->getDeclaringClass())
43+
: 'mixed'
44+
);
45+
}
46+
return $this->docBlockType;
3347
}
3448

3549
public function isRequired(): bool
3650
{
37-
return $this->type && !$this->type->allowsNull();
51+
return $this->phpType() && !$this->phpType()->allowsNull();
3852
}
3953

4054
private $name;
55+
/** @var ReflectionMethod */
56+
private $accessorMethod;
4157
/** @var ReflectionType|null */
42-
private $type;
58+
private $phpType;
4359

4460
private function __construct()
4561
{

src/ValueClass/AccessorMethodProcessor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public function inferProperties(ReflectionMethodCollection $matchedMethods): Pro
2929
$templateUsesPrefixes = self::templateUsesPrefixes($matchedMethods);
3030
return $matchedMethods->reduce(PropertyCollection::create(), function (PropertyCollection $properties, ReflectionMethod $method) use ($templateUsesPrefixes) {
3131
$propertyName = self::getPropertyName($templateUsesPrefixes, $method);
32-
$property = Property::named($propertyName)->withType($method->getReturnType());
32+
$property = Property::fromAccessorMethod($propertyName, $method);
3333
return $properties->withProperty($property);
3434
});
3535
}

src/ValueClass/ValueClassGenerator.php

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,8 @@ public function generateClass(ReflectionClass $baseClass, PropertyCollection $pr
1818
{
1919
// todo include type in properties constant
2020
$propertyDeclarations = \implode("\n", $properties->map(function (Property $property) use ($baseClass) {
21-
if ($property->type()) {
22-
$type = generateTypeHint($property->type(), $baseClass);
23-
} else {
24-
$type = 'mixed';
25-
}
2621
return <<<THEPHP
27-
/** @var $type */
22+
/** @var {$property->docBlockType()} */
2823
private \${$property->name()};
2924
THEPHP;
3025
}));

src/ValueEquals/EqualsMethodProcessor.php

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -50,25 +50,25 @@ private function generateMethodBody(
5050
string $valueParam,
5151
PropertyCollection $properties
5252
): string {
53-
$typedProperties = $properties->filter(function (Property $property) { return $property->type() !== null; });
54-
$arrayProperties = $typedProperties->filter(function (Property $property) { return (string)$property->type() === 'array'; });
55-
$classProperties = $typedProperties->filter(function (Property $property) { return isClass($property->type()); });
53+
$typedProperties = $properties->filter(function (Property $property) { return $property->phpType() !== null; });
54+
$arrayProperties = $typedProperties->filter(function (Property $property) { return (string)$property->phpType() === 'array'; });
55+
$classProperties = $typedProperties->filter(function (Property $property) { return isClass($property->phpType()); });
5656
$valueObjectProperties = $classProperties->filter(function (Property $property) use ($templateClass) {
5757
return $this->isValueObject($templateClass, $property);
5858
});
5959
$mixedProperties = $properties->filter(function (Property $property) {
60-
return $property->type() === null
61-
|| (string)$property->type() === 'object'
62-
|| (string)$property->type() === 'iterable'
63-
|| (string)$property->type() === 'callable';
60+
return $property->phpType() === null
61+
|| (string)$property->phpType() === 'object'
62+
|| (string)$property->phpType() === 'iterable'
63+
|| (string)$property->phpType() === 'callable';
6464
});
6565

6666
$testsForTypedProperties = \array_merge(
6767
["\${$valueParam} instanceof self"],
6868

6969
$typedProperties
70-
->filter(function (Property $property) { return !isClass($property->type()); })
71-
->filter(function (Property $property) { return (string)$property->type() !== 'array'; })
70+
->filter(function (Property $property) { return !isClass($property->phpType()); })
71+
->filter(function (Property $property) { return (string)$property->phpType() !== 'array'; })
7272
->mapPropertyNames(function (string $propertyName) use ($valueParam) {
7373
return "\$this->$propertyName === \${$valueParam}->$propertyName";
7474
}),
@@ -137,7 +137,7 @@ private function generateMethodBody(
137137

138138
private function isValueObject(ReflectionClass $templateClass, Property $property): bool
139139
{
140-
$reflectionClass = getClass($templateClass, $property->type());
140+
$reflectionClass = getClass($templateClass, $property->phpType());
141141
return $reflectionClass->hasMethod('equals')
142142
&& $this->matchMethod($reflectionClass->getMethod('equals'));
143143
}

src/functions.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ function generateParameters(array $reflectionParameters): string
3535
}, $reflectionParameters));
3636
}
3737

38-
function generateReturnTypeHint(?ReflectionType $returnType, ?ReflectionClass $declaringClass): string
38+
function generateReturnTypeHint(?ReflectionType $returnType, ReflectionClass $declaringClass): string
3939
{
4040
return $returnType === null ? '' : ': ' . generateTypeHint($returnType, $declaringClass);
4141
}
4242

43-
function generateTypeHint(ReflectionType $type, ?ReflectionClass $declaringClass): string
43+
function generateTypeHint(ReflectionType $type, ReflectionClass $declaringClass): string
4444
{
4545
$prefix = $type->allowsNull() ? '?' : '';
4646
$normalizedType = (string)$type === 'self'

0 commit comments

Comments
 (0)