Skip to content

Commit 0881d5c

Browse files
committed
add fixture
1 parent b5f2638 commit 0881d5c

5 files changed

Lines changed: 133 additions & 13 deletions

File tree

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
3+
namespace Rector\Symfony\Tests\Symfony73\Rector\Class_\InvokableCommandInputAttributeRector\Fixture\DefaultValue;
4+
5+
use Symfony\Component\Console\Attribute\AsCommand;
6+
use Symfony\Component\Console\Command\Command;
7+
use Symfony\Component\Console\Input\InputArgument;
8+
use Symfony\Component\Console\Input\InputInterface;
9+
use Symfony\Component\Console\Input\InputOption;
10+
use Symfony\Component\Console\Output\OutputInterface;
11+
12+
#[AsCommand(
13+
name: 'app:hello',
14+
)]
15+
class MatchScalarType extends Command
16+
{
17+
protected function configure(): void
18+
{
19+
$this->addArgument('first', InputArgument::OPTIONAL, null, 100);
20+
$this->addArgument('second', InputArgument::REQUIRED, null, 200.5);
21+
22+
$this->addOption('third', '', null, null, 200);
23+
$this->addOption('fourth', '', null, null, 400.5);
24+
}
25+
protected function execute(InputInterface $input, OutputInterface $output): int
26+
{
27+
}
28+
}
29+
30+
?>
31+
-----
32+
<?php
33+
34+
namespace Rector\Symfony\Tests\Symfony73\Rector\Class_\InvokableCommandInputAttributeRector\Fixture\DefaultValue;
35+
36+
use Symfony\Component\Console\Attribute\AsCommand;
37+
use Symfony\Component\Console\Command\Command;
38+
use Symfony\Component\Console\Input\InputArgument;
39+
use Symfony\Component\Console\Input\InputInterface;
40+
use Symfony\Component\Console\Input\InputOption;
41+
use Symfony\Component\Console\Output\OutputInterface;
42+
43+
#[AsCommand(
44+
name: 'app:hello',
45+
)]
46+
class MatchScalarType
47+
{
48+
public function __invoke(
49+
#[\Symfony\Component\Console\Attribute\Argument(name: 'first')]
50+
?int $first = 100,
51+
#[\Symfony\Component\Console\Attribute\Argument(name: 'second')]
52+
float $second = 200.5,
53+
#[\Symfony\Component\Console\Attribute\Option(name: 'third')]
54+
?int $third = 200,
55+
#[\Symfony\Component\Console\Attribute\Option(name: 'fourth')]
56+
?float $fourth = 400.5
57+
): int
58+
{
59+
}
60+
}
61+
62+
?>

rules/Symfony73/NodeAnalyzer/CommandArgumentsResolver.php

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@
44

55
namespace Rector\Symfony\Symfony73\NodeAnalyzer;
66

7+
use PHPStan\Type\Type;
8+
use PhpParser\Node\Arg;
79
use PhpParser\Node\Expr;
810
use PhpParser\Node\Stmt\ClassMethod;
11+
use Rector\NodeTypeResolver\NodeTypeResolver;
912
use Rector\PhpParser\Node\Value\ValueResolver;
1013
use Rector\Symfony\Symfony73\NodeFinder\MethodCallFinder;
1114
use Rector\Symfony\Symfony73\ValueObject\CommandArgument;
@@ -14,7 +17,8 @@
1417
{
1518
public function __construct(
1619
private MethodCallFinder $methodCallFinder,
17-
private ValueResolver $valueResolver
20+
private ValueResolver $valueResolver,
21+
private NodeTypeResolver $nodeTypeResolver
1822
) {
1923
}
2024

@@ -31,25 +35,47 @@ public function resolve(ClassMethod $configureClassMethod): array
3135

3236
$argumentName = $this->valueResolver->getValue($addArgumentArgs[0]->value);
3337

34-
$modeExpr = $addArgumentArgs[1]->value ?? null;
35-
36-
$isArray = false;
37-
if ($modeExpr instanceof Expr) {
38-
$modeValue = $this->valueResolver->getValue($modeExpr);
39-
// binary check for InputArgument::IS_ARRAY
40-
$isArray = (bool) ($modeValue & 4);
41-
}
38+
$isArray = $this->isArrayMode($addArgumentArgs);
4239

4340
$commandArguments[] = new CommandArgument(
4441
$argumentName,
4542
$addArgumentArgs[0]->value,
4643
$addArgumentArgs[1]->value ?? null,
4744
$addArgumentArgs[2]->value ?? null,
4845
$addArgumentArgs[3]->value ?? null,
49-
$isArray
46+
$isArray,
47+
$this->resolveDefaultType($addArgumentArgs)
5048
);
5149
}
5250

5351
return $commandArguments;
5452
}
53+
54+
/**
55+
* @param Arg[] $args
56+
*/
57+
private function resolveDefaultType(array $args): ?Type
58+
{
59+
$defaultArg = $args[3] ?? null;
60+
if (! $defaultArg instanceof Arg) {
61+
return null;
62+
}
63+
64+
return $this->nodeTypeResolver->getType($defaultArg->value);
65+
}
66+
67+
/**
68+
* @param Arg[] $args
69+
*/
70+
private function isArrayMode(array $args): bool
71+
{
72+
$modeExpr = $args[1]->value ?? null;
73+
if (! $modeExpr instanceof Expr) {
74+
return false;
75+
}
76+
77+
$modeValue = $this->valueResolver->getValue($modeExpr);
78+
// binary check for InputArgument::IS_ARRAY
79+
return (bool) ($modeValue & 4);
80+
}
5581
}

rules/Symfony73/NodeAnalyzer/CommandOptionsResolver.php

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44

55
namespace Rector\Symfony\Symfony73\NodeAnalyzer;
66

7+
use PHPStan\Type\Type;
8+
use PhpParser\Node\Arg;
79
use PhpParser\Node\Stmt\ClassMethod;
10+
use Rector\NodeTypeResolver\NodeTypeResolver;
811
use Rector\PhpParser\Node\Value\ValueResolver;
912
use Rector\Symfony\Symfony73\NodeFinder\MethodCallFinder;
1013
use Rector\Symfony\Symfony73\ValueObject\CommandOption;
@@ -13,7 +16,8 @@
1316
{
1417
public function __construct(
1518
private MethodCallFinder $methodCallFinder,
16-
private ValueResolver $valueResolver
19+
private ValueResolver $valueResolver,
20+
private NodeTypeResolver $nodeTypeResolver
1721
) {
1822
}
1923

@@ -37,10 +41,24 @@ public function resolve(ClassMethod $configureClassMethod): array
3741
$addOptionArgs[1]->value ?? null,
3842
$addOptionArgs[2]->value ?? null,
3943
$addOptionArgs[3]->value ?? null,
40-
$addOptionArgs[4]->value ?? null
44+
$addOptionArgs[4]->value ?? null,
45+
$this->resolveDefaultType($addOptionArgs)
4146
);
4247
}
4348

4449
return $commandOptions;
4550
}
51+
52+
/**
53+
* @param Arg[] $args
54+
*/
55+
private function resolveDefaultType(array $args): ?Type
56+
{
57+
$defaultArg = $args[4] ?? null;
58+
if (! $defaultArg instanceof Arg) {
59+
return null;
60+
}
61+
62+
return $this->nodeTypeResolver->getType($defaultArg->value);
63+
}
4664
}

rules/Symfony73/ValueObject/CommandArgument.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Rector\Symfony\Symfony73\ValueObject;
66

7+
use PHPStan\Type\Type;
78
use PhpParser\Node\Expr;
89

910
final readonly class CommandArgument
@@ -14,7 +15,8 @@ public function __construct(
1415
private ?Expr $mode,
1516
private ?Expr $description,
1617
private ?Expr $default,
17-
private bool $isArray
18+
private bool $isArray,
19+
private ?Type $defaultType
1820
) {
1921
}
2022

@@ -47,4 +49,9 @@ public function isArray(): bool
4749
{
4850
return $this->isArray;
4951
}
52+
53+
public function getDefaultType(): ?Type
54+
{
55+
return $this->defaultType;
56+
}
5057
}

rules/Symfony73/ValueObject/CommandOption.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Rector\Symfony\Symfony73\ValueObject;
66

7+
use PHPStan\Type\Type;
78
use PhpParser\Node\Expr;
89

910
final readonly class CommandOption
@@ -15,6 +16,7 @@ public function __construct(
1516
private ?Expr $mode,
1617
private ?Expr $description,
1718
private ?Expr $default,
19+
private ?Type $defaultType
1820
) {
1921
}
2022

@@ -47,4 +49,9 @@ public function getDefault(): ?Expr
4749
{
4850
return $this->default;
4951
}
52+
53+
public function getDefaultType(): ?Type
54+
{
55+
return $this->defaultType;
56+
}
5057
}

0 commit comments

Comments
 (0)