From 8853465f5488a9003fab9c9a73933f2600b33adf Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 26 Apr 2023 12:55:09 +0200 Subject: [PATCH] Printer: attributes on parameters are placed on its own line --- src/PhpGenerator/Printer.php | 52 +++++--- tests/PhpGenerator/Printer.function.phpt | 121 +++++++++++++++++- .../expected/ClassType.attributes.expect | 3 +- .../expected/ClassType.from.expect | 3 +- .../expected/ClassType.promotion.expect | 3 +- .../expected/Extractor.classes.expect | 3 +- .../PhpGenerator/expected/PhpNamespace.expect | 3 +- .../expected/Printer.class-alt.expect | 6 +- .../expected/Printer.class.expect | 6 +- 9 files changed, 166 insertions(+), 34 deletions(-) diff --git a/src/PhpGenerator/Printer.php b/src/PhpGenerator/Printer.php index 4731fbe3..1b4fea73 100644 --- a/src/PhpGenerator/Printer.php +++ b/src/PhpGenerator/Printer.php @@ -326,37 +326,51 @@ protected function printUses(PhpNamespace $namespace, string $of = PhpNamespace: protected function printParameters(Closure|GlobalFunction|Method $function, int $column = 0): string { - $params = []; - $list = $function->getParameters(); - $multiline = false; - - foreach ($list as $param) { + $special = false; + foreach ($function->getParameters() as $param) { $param->validate(); - $variadic = $function->isVariadic() && $param === end($list); - $type = $param->getType(); + $special = $special || $param instanceof PromotedParameter || $param->getAttributes(); + } + + if (!$special) { + $line = $this->formatParameters($function, false); + if (!str_contains($line, "\n") && strlen($line) + $column <= $this->wrapLength) { + return $line; + } + } + + return $this->formatParameters($function, true); + } + + + private function formatParameters(Closure|GlobalFunction|Method $function, bool $multiline): string + { + $params = $function->getParameters(); + $res = ''; + + foreach ($params as $param) { + $variadic = $function->isVariadic() && $param === end($params); $promoted = $param instanceof PromotedParameter ? $param : null; - $params[] = + $attrs = $this->printAttributes($param->getAttributes(), inline: true); + $res .= ($promoted ? $this->printDocComment($promoted) : '') - . ($attrs = $this->printAttributes($param->getAttributes(), inline: true)) + . ($attrs ? ($multiline ? substr($attrs, 0, -1) . "\n" : $attrs) : '') . ($promoted ? ($promoted->getVisibility() ?: 'public') - . ($promoted->isReadOnly() && $type ? ' readonly' : '') + . ($promoted->isReadOnly() && $param->getType() ? ' readonly' : '') . ' ' : '') - . ltrim($this->printType($type, $param->isNullable()) . ' ') + . ltrim($this->printType($param->getType(), $param->isNullable()) . ' ') . ($param->isReference() ? '&' : '') . ($variadic ? '...' : '') . '$' . $param->getName() - . ($param->hasDefaultValue() && !$variadic ? ' = ' . $this->dump($param->getDefaultValue()) : ''); - - $multiline = $multiline || $promoted || $attrs; + . ($param->hasDefaultValue() && !$variadic ? ' = ' . $this->dump($param->getDefaultValue()) : '') + . ($multiline ? ",\n" : ', '); } - $line = implode(', ', $params); - $multiline = $multiline || count($params) > 1 && (strlen($line) + $column > $this->wrapLength); - return $multiline - ? "(\n" . $this->indent(implode(",\n", $params)) . ",\n)" - : "($line)"; + ? "(\n" . $this->indent($res) . ')' + : '(' . substr($res, 0, -2) . ')'; + } diff --git a/tests/PhpGenerator/Printer.function.phpt b/tests/PhpGenerator/Printer.function.phpt index f9ed7719..c75a6545 100644 --- a/tests/PhpGenerator/Printer.function.phpt +++ b/tests/PhpGenerator/Printer.function.phpt @@ -2,6 +2,7 @@ declare(strict_types=1); +use Nette\PhpGenerator\GlobalFunction; use Nette\PhpGenerator\Printer; use Tester\Assert; @@ -9,7 +10,7 @@ require __DIR__ . '/../bootstrap.php'; $printer = new Printer; -$function = new Nette\PhpGenerator\GlobalFunction('func'); +$function = new GlobalFunction('func'); $function ->setReturnType('stdClass') ->setBody("func(); \r\nreturn 123;") @@ -26,20 +27,20 @@ Assert::match(<<<'XX' XX, $printer->printFunction($function)); -$function = new Nette\PhpGenerator\GlobalFunction('multi'); +$function = new GlobalFunction('multi'); $function->addParameter('foo') ->addAttribute('Foo'); Assert::match(<<<'XX' function multi( - #[Foo] $foo, + #[Foo] + $foo, ) { } - XX, $printer->printFunction($function)); -$function = new Nette\PhpGenerator\GlobalFunction('multiType'); +$function = new GlobalFunction('multiType'); $function ->setReturnType('array') ->addParameter('foo') @@ -47,9 +48,117 @@ $function Assert::match(<<<'XX' function multiType( - #[Foo] $foo, + #[Foo] + $foo, ): array { } + XX, $printer->printFunction($function)); + + +$function = new GlobalFunction('func'); +$function->addAttribute('Foo', [1, 2, 3]); +$function->addAttribute('Bar'); + +same( + <<<'XX' + #[Foo(1, 2, 3)] + #[Bar] + function func() + { + } + + XX, + (string) $function, +); + + +// single +$function = new GlobalFunction('func'); +$function->addAttribute('Foo', [1, 2, 3]); + +Assert::match(<<<'XX' + #[Foo(1, 2, 3)] + function func() + { + } + XX, $printer->printFunction($function)); + + +// multiple +$function = new GlobalFunction('func'); +$function->addAttribute('Foo', [1, 2, 3]); +$function->addAttribute('Bar'); + +Assert::match(<<<'XX' + #[Foo(1, 2, 3)] + #[Bar] + function func() + { + } + XX, $printer->printFunction($function)); + + +// multiline +$function = new GlobalFunction('func'); +$function->addAttribute('Foo', ['a', str_repeat('x', 120)]); + +Assert::match(<<<'XX' + #[Foo( + 'a', + 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', + )] + function func() + { + } + XX, $printer->printFunction($function)); + + +// parameter: single +$function = new GlobalFunction('func'); +$param = $function->addParameter('foo'); +$param->addAttribute('Foo', [1, 2, 3]); + +Assert::match(<<<'XX' + function func( + #[Foo(1, 2, 3)] + $foo, + ) { + } + XX, $printer->printFunction($function)); + +// parameter: multiple +$function = new GlobalFunction('func'); +$param = $function->addParameter('foo'); +$param->addAttribute('Foo', [1, 2, 3]); +$param->addAttribute('Bar'); + +Assert::match(<<<'XX' + function func( + #[Foo(1, 2, 3), Bar] + $foo, + ) { + } + XX, $printer->printFunction($function)); + + +// parameter: multiline +$function = new GlobalFunction('func'); +$param = $function->addParameter('bar'); +$param->addAttribute('Foo'); +$param = $function->addParameter('foo'); +$param->addAttribute('Foo', ['a', str_repeat('x', 120)]); + +Assert::match(<<<'XX' + function func( + #[Foo] + $bar, + #[Foo( + 'a', + 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', + )] + $foo, + ) { + } XX, $printer->printFunction($function)); diff --git a/tests/PhpGenerator/expected/ClassType.attributes.expect b/tests/PhpGenerator/expected/ClassType.attributes.expect index 57d6307a..9ed82714 100644 --- a/tests/PhpGenerator/expected/ClassType.attributes.expect +++ b/tests/PhpGenerator/expected/ClassType.attributes.expect @@ -21,7 +21,8 @@ class Example */ #[ExampleAttribute] public function getHandle( - #[ExampleAttribute, WithArguments(123)] $mode, + #[ExampleAttribute, WithArguments(123)] + $mode, ) { } } diff --git a/tests/PhpGenerator/expected/ClassType.from.expect b/tests/PhpGenerator/expected/ClassType.from.expect index f66a53a9..a6f42d2a 100644 --- a/tests/PhpGenerator/expected/ClassType.from.expect +++ b/tests/PhpGenerator/expected/ClassType.from.expect @@ -139,7 +139,8 @@ class Class9 */ #[ExampleAttribute] public function getHandle( - #[WithArguments(123)] $mode, + #[WithArguments(123)] + $mode, ) { } } diff --git a/tests/PhpGenerator/expected/ClassType.promotion.expect b/tests/PhpGenerator/expected/ClassType.promotion.expect index 81dd351e..78700ad6 100644 --- a/tests/PhpGenerator/expected/ClassType.promotion.expect +++ b/tests/PhpGenerator/expected/ClassType.promotion.expect @@ -4,7 +4,8 @@ class Example $a, public $b, /** promo */ - #[Example] private string $c, + #[Example] + private string $c, public readonly Draft $d = new Draft(10), ) { } diff --git a/tests/PhpGenerator/expected/Extractor.classes.expect b/tests/PhpGenerator/expected/Extractor.classes.expect index 25d94e84..3397988c 100644 --- a/tests/PhpGenerator/expected/Extractor.classes.expect +++ b/tests/PhpGenerator/expected/Extractor.classes.expect @@ -149,7 +149,8 @@ class Class9 */ #[ExampleAttribute] public function getHandle( - #[WithArguments(123)] $mode, + #[WithArguments(123)] + $mode, ) { } } diff --git a/tests/PhpGenerator/expected/PhpNamespace.expect b/tests/PhpGenerator/expected/PhpNamespace.expect index 0577d9c4..0fd4adb9 100644 --- a/tests/PhpGenerator/expected/PhpNamespace.expect +++ b/tests/PhpGenerator/expected/PhpNamespace.expect @@ -12,7 +12,8 @@ class A implements A, C #[A] public function test( - #[\Bar\D] C $a, + #[\Bar\D] + C $a, self $b, parent $c, array $d, diff --git a/tests/PhpGenerator/expected/Printer.class-alt.expect b/tests/PhpGenerator/expected/Printer.class-alt.expect index 5fa5b6ff..bded1b70 100644 --- a/tests/PhpGenerator/expected/Printer.class-alt.expect +++ b/tests/PhpGenerator/expected/Printer.class-alt.expect @@ -64,14 +64,16 @@ final class Example extends ParentClass implements IExample public function multi( - #[Foo] $foo, + #[Foo] + $foo, ) { } public function multiType( - #[Foo] $foo, + #[Foo] + $foo, ): array { } } diff --git a/tests/PhpGenerator/expected/Printer.class.expect b/tests/PhpGenerator/expected/Printer.class.expect index c66082ba..810494c7 100644 --- a/tests/PhpGenerator/expected/Printer.class.expect +++ b/tests/PhpGenerator/expected/Printer.class.expect @@ -62,13 +62,15 @@ final class Example extends ParentClass implements IExample public function multi( - #[Foo] $foo, + #[Foo] + $foo, ) { } public function multiType( - #[Foo] $foo, + #[Foo] + $foo, ): array { }