Skip to content

Commit

Permalink
Use constructor parameters as source of definitions
Browse files Browse the repository at this point in the history
Constructor promoted properties provide better flexibility. However,
it's not possible to get their default value as it is part of the
constructor parameter (which assigns the property).

I decided that all inputs need to define a constructor with list of
parameters. Those don't need to be promoted properties, but all
parameters with #[Argument], or #[Option] will be used to create the
definitions.
  • Loading branch information
radmen committed Nov 23, 2024
1 parent 29eadb3 commit 2bc708d
Show file tree
Hide file tree
Showing 9 changed files with 167 additions and 106 deletions.
2 changes: 1 addition & 1 deletion src/Attributes/Argument.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use Attribute;

#[Attribute(Attribute::TARGET_PROPERTY)]
#[Attribute(Attribute::TARGET_PARAMETER)]
final class Argument
{
public function __construct()
Expand Down
2 changes: 1 addition & 1 deletion src/Attributes/Description.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use Attribute;

#[Attribute(Attribute::TARGET_PROPERTY)]
#[Attribute(Attribute::TARGET_PARAMETER)]
final class Description
{
public function __construct(
Expand Down
2 changes: 1 addition & 1 deletion src/Attributes/Name.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use Attribute;

#[Attribute(Attribute::TARGET_PROPERTY)]
#[Attribute(Attribute::TARGET_PARAMETER)]
final class Name
{
public function __construct(public readonly string $name)
Expand Down
2 changes: 1 addition & 1 deletion src/Attributes/Option.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use Attribute;

#[Attribute(Attribute::TARGET_PROPERTY)]
#[Attribute(Attribute::TARGET_PARAMETER)]
final class Option
{
public function __construct()
Expand Down
2 changes: 1 addition & 1 deletion src/Attributes/Shortcut.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use Attribute;

#[Attribute(Attribute::TARGET_PROPERTY)]
#[Attribute(Attribute::TARGET_PARAMETER)]
final class Shortcut
{
public function __construct(public readonly string $shortcut)
Expand Down
11 changes: 7 additions & 4 deletions src/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use Baethon\Symfony\Console\Input\Attributes\Argument;
use Baethon\Symfony\Console\Input\Attributes\Option;
use ReflectionClass;
use ReflectionProperty;
use ReflectionParameter;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;

Expand Down Expand Up @@ -80,13 +80,16 @@ function (ParameterDefinition $parameter) {
*/
private function collectByType(ReflectionClass $reflection, string $attribute): array
{
$constructor = $reflection->getConstructor()
?? throw new \InvalidArgumentException('Unable to finc constructor of '.$reflection->getName());

$properties = array_filter(
$reflection->getProperties(ReflectionProperty::IS_PUBLIC),
fn (ReflectionProperty $item) => $item->getAttributes($attribute) !== [],
$constructor->getParameters(),
fn (ReflectionParameter $item) => $item->getAttributes($attribute) !== [],
);

return array_map(
ParameterDefinition::fromReflectionProperty(...),
ParameterDefinition::fromReflectionParameter(...),
$properties,
);
}
Expand Down
20 changes: 11 additions & 9 deletions src/ParameterDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use Baethon\Symfony\Console\Input\Attributes\Description;
use Baethon\Symfony\Console\Input\Attributes\Name;
use Baethon\Symfony\Console\Input\Attributes\Shortcut;
use ReflectionProperty;
use ReflectionParameter;
use ReflectionType;

final class ParameterDefinition
Expand All @@ -22,22 +22,24 @@ public function __construct(
//
}

public static function fromReflectionProperty(ReflectionProperty $property): ParameterDefinition
public static function fromReflectionParameter(ReflectionParameter $parameter): ParameterDefinition
{
$type = $property->getType();
$defaultValue = $property->getDefaultValue();
$type = $parameter->getType();
$defaultValue = $parameter->isOptional()
? $parameter->getDefaultValue()
: null;

return new self(
name: self::findAttribute($property, Name::class)
?->name ?? $property->getName(),
name: self::findAttribute($parameter, Name::class)
?->name ?? $parameter->getName(),
required: match (true) {
! is_null($defaultValue) => false,
$type?->allowsNull() => false,
default => true,
},
description: self::findAttribute($property, Description::class)
description: self::findAttribute($parameter, Description::class)
?->description,
shortcut: self::findAttribute($property, Shortcut::class)
shortcut: self::findAttribute($parameter, Shortcut::class)
?->shortcut,
list: ($type instanceof ReflectionType && $type->getName() === 'array'),
option: ($type instanceof ReflectionType && $type->getName() === 'bool'),
Expand All @@ -51,7 +53,7 @@ public static function fromReflectionProperty(ReflectionProperty $property): Par
* @param class-string<T> $attribute
* @return ?T
*/
private static function findAttribute(ReflectionProperty $property, string $attribute)
private static function findAttribute(ReflectionParameter $property, string $attribute)
{
$attributes = $property->getAttributes($attribute);

Expand Down
Loading

0 comments on commit 2bc708d

Please sign in to comment.