diff --git a/README.md b/README.md
index c5e349f..6bbd7fe 100644
--- a/README.md
+++ b/README.md
@@ -346,14 +346,14 @@ final class Alert
-### PublicPropertiesShouldBeCamelCaseRule
+### PostMountMethodSignatureRule
-Enforces that all public properties in Twig Components follow camelCase naming convention.
-This ensures consistency and better integration with Twig templates where properties are passed and accessed using camelCase.
+Enforces that methods with the `#[PostMount]` attribute have the correct signature: they must be public with an optional parameter of type `array`, and a return type of `array`, `void`, or `array|void`.
+This ensures proper integration with the Symfony UX TwigComponent lifecycle hooks.
```yaml
rules:
- - Kocal\PHPStanSymfonyUX\Rules\TwigComponent\PublicPropertiesShouldBeCamelCaseRule
+ - Kocal\PHPStanSymfonyUX\Rules\TwigComponent\PostMountMethodSignatureRule
```
```php
@@ -361,12 +361,15 @@ rules:
namespace App\Twig\Components;
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
+use Symfony\UX\TwigComponent\Attribute\PostMount;
#[AsTwigComponent]
final class Alert
{
- public string $user_name;
- public bool $is_active;
+ #[PostMount]
+ protected function postMount(): void
+ {
+ }
}
```
@@ -375,11 +378,33 @@ final class Alert
namespace App\Twig\Components;
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
+use Symfony\UX\TwigComponent\Attribute\PostMount;
#[AsTwigComponent]
final class Alert
{
- public string $UserName;
+ #[PostMount]
+ public function postMount(array $data): string
+ {
+ return 'invalid';
+ }
+}
+```
+
+```php
+// src/Twig/Components/Alert.php
+namespace App\Twig\Components;
+
+use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
+use Symfony\UX\TwigComponent\Attribute\PostMount;
+
+#[AsTwigComponent]
+final class Alert
+{
+ #[PostMount]
+ public function postMount(string $data): void
+ {
+ }
}
```
@@ -392,12 +417,33 @@ final class Alert
namespace App\Twig\Components;
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
+use Symfony\UX\TwigComponent\Attribute\PostMount;
#[AsTwigComponent]
final class Alert
{
- public string $userName;
- public bool $isActive;
+ #[PostMount]
+ public function postMount(): void
+ {
+ }
+}
+```
+
+```php
+// src/Twig/Components/Alert.php
+namespace App\Twig\Components;
+
+use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
+use Symfony\UX\TwigComponent\Attribute\PostMount;
+
+#[AsTwigComponent]
+final class Alert
+{
+ #[PostMount]
+ public function postMount(array $data): array
+ {
+ return $data;
+ }
}
```
@@ -407,7 +453,7 @@ final class Alert
### PreMountMethodSignatureRule
-Enforces that methods with the `#[PreMount]` attribute have the correct signature: they must be public and have exactly one parameter of type `array`, with a return type of `array`.
+Enforces that methods with the `#[PreMount]` attribute have the correct signature: they must be public and have exactly one parameter of type `array`, with a return type of `array`, `void`, or `array|void` .
This ensures proper integration with the Symfony UX TwigComponent lifecycle hooks.
```yaml
@@ -444,12 +490,17 @@ use Symfony\UX\TwigComponent\Attribute\PreMount;
final class Alert
{
#[PreMount]
- public function preMount(array $data): void
+ public function preMount(string $data): array
{
+ return [];
}
}
```
+:x:
+
+
+
```php
// src/Twig/Components/Alert.php
namespace App\Twig\Components;
@@ -461,34 +512,71 @@ use Symfony\UX\TwigComponent\Attribute\PreMount;
final class Alert
{
#[PreMount]
- public function preMount(string $data): array
+ public function preMount(array $data): array
{
- return [];
+ $data['timestamp'] = time();
+
+ return $data;
}
}
```
-:x:
+:+1:
+### PublicPropertiesShouldBeCamelCaseRule
+
+Enforces that all public properties in Twig Components follow camelCase naming convention.
+This ensures consistency and better integration with Twig templates where properties are passed and accessed using camelCase.
+
+```yaml
+rules:
+ - Kocal\PHPStanSymfonyUX\Rules\TwigComponent\PublicPropertiesShouldBeCamelCaseRule
+```
+
```php
// src/Twig/Components/Alert.php
namespace App\Twig\Components;
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
-use Symfony\UX\TwigComponent\Attribute\PreMount;
#[AsTwigComponent]
final class Alert
{
- #[PreMount]
- public function preMount(array $data): array
- {
- $data['timestamp'] = time();
+ public string $user_name;
+ public bool $is_active;
+}
+```
- return $data;
- }
+```php
+// src/Twig/Components/Alert.php
+namespace App\Twig\Components;
+
+use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
+
+#[AsTwigComponent]
+final class Alert
+{
+ public string $UserName;
+}
+```
+
+:x:
+
+
+
+```php
+// src/Twig/Components/Alert.php
+namespace App\Twig\Components;
+
+use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
+
+#[AsTwigComponent]
+final class Alert
+{
+ public string $userName;
+ public bool $isActive;
}
```
diff --git a/ecs.php b/ecs.php
index 7f24063..09033eb 100644
--- a/ecs.php
+++ b/ecs.php
@@ -14,7 +14,7 @@
->withPreparedSets(psr12: true, common: true)
->withSkip([
ProtectedToPrivateFixer::class => [
- __DIR__ . '/tests/Rules/TwigComponent/MethodsShouldBePublicOrPrivateRule/Fixture/*',
+ __DIR__ . '/tests/Rules/**/Fixture/*',
],
])
;
diff --git a/phpstan.dist.neon b/phpstan.dist.neon
index e786f4c..053d645 100644
--- a/phpstan.dist.neon
+++ b/phpstan.dist.neon
@@ -12,6 +12,4 @@ parameters:
identifiers:
- method.unused
- missingType.iterableValue
- - missingType.return
- property.unused
- - return.unusedType
\ No newline at end of file
diff --git a/src/Rules/TwigComponent/PostMountMethodSignatureRule.php b/src/Rules/TwigComponent/PostMountMethodSignatureRule.php
new file mode 100644
index 0000000..7623153
--- /dev/null
+++ b/src/Rules/TwigComponent/PostMountMethodSignatureRule.php
@@ -0,0 +1,114 @@
+
+ */
+final class PostMountMethodSignatureRule implements Rule
+{
+ public function __construct(
+ private ReflectionProvider $reflectionProvider,
+ ) {
+ }
+
+ public function getNodeType(): string
+ {
+ return Class_::class;
+ }
+
+ public function processNode(Node $node, Scope $scope): array
+ {
+ if (! AttributeFinder::findAnyAttribute($node, [AsTwigComponent::class, AsLiveComponent::class])) {
+ return [];
+ }
+
+ if ($node->namespacedName === null) {
+ return [];
+ }
+
+ $errors = [];
+ $reflClass = $this->reflectionProvider->getClass($node->namespacedName->toString());
+
+ foreach ($node->getMethods() as $method) {
+ if (! AttributeFinder::findAttribute($method, PostMount::class)) {
+ continue;
+ }
+
+ $errors[] = $this->validatePostMountMethod(
+ $method,
+ $reflClass->getMethod($method->name->name, $scope),
+ );
+ }
+
+ return array_merge(...$errors);
+ }
+
+ /**
+ * @return list<\PHPStan\Rules\IdentifierRuleError>
+ */
+ private function validatePostMountMethod(Node\Stmt\ClassMethod $method, ExtendedMethodReflection $reflMethod): array
+ {
+ $errors = [];
+
+ $methodName = $reflMethod->getName();
+ $methodParams = $reflMethod->getOnlyVariant()->getParameters();
+ $methodReturnType = $reflMethod->getOnlyVariant()->getReturnType();
+
+ // Check if method is public
+ if (! $reflMethod->isPublic()) {
+ $errors[] = RuleErrorBuilder::message(sprintf('Method "%s" with #[PostMount] attribute must be public.', $methodName))
+ ->identifier('symfonyUX.twigComponent.postMountPublic')
+ ->line($method->getLine())
+ ->tip('Change the method visibility to public.')
+ ->build();
+ }
+
+ // Check parameter count and type (0 or 1 parameter allowed)
+ if (count($methodParams) > 1) {
+ $errors[] = RuleErrorBuilder::message(sprintf('Method "%s" with #[PostMount] attribute must have at most one parameter of type "array".', $methodName))
+ ->identifier('symfonyUX.twigComponent.postMountParameterCount')
+ ->line($method->getLine())
+ ->tip('The method should have zero or one parameter: "array $data" (optional).')
+ ->build();
+ } elseif (count($methodParams) === 1) {
+ // If there is a parameter, it must be of type array
+ if (! $methodParams[0]->getType()->isArray()->yes()) {
+ $errors[] = RuleErrorBuilder::message(sprintf('Method "%s" with #[PostMount] attribute must have a parameter of type "array".', $methodName))
+ ->identifier('symfonyUX.twigComponent.postMountParameterType')
+ ->line($method->getLine())
+ ->tip('Change the parameter type to "array".')
+ ->build();
+ }
+ }
+
+ // Check return type (must be array, void, or array|void)
+ $isValidReturnType = $methodReturnType->isVoid()->yes()
+ || $methodReturnType->isArray()->yes()
+ || ($methodReturnType->isArray()->maybe() && $methodReturnType->isVoid()->maybe());
+
+ if (! $isValidReturnType) {
+ $errors[] = RuleErrorBuilder::message(sprintf('Method "%s" with #[PostMount] attribute must have a return type of "array", "void", or "array|void".', $methodName))
+ ->identifier('symfonyUX.twigComponent.postMountReturnType')
+ ->line($method->getLine())
+ ->tip('Change the return type to ": array", ": void", or ": array|void".')
+ ->build();
+ }
+
+ return $errors;
+ }
+}
diff --git a/src/Rules/TwigComponent/PreMountMethodSignatureRule.php b/src/Rules/TwigComponent/PreMountMethodSignatureRule.php
index 4543c34..2223865 100644
--- a/src/Rules/TwigComponent/PreMountMethodSignatureRule.php
+++ b/src/Rules/TwigComponent/PreMountMethodSignatureRule.php
@@ -8,6 +8,8 @@
use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
use PHPStan\Analyser\Scope;
+use PHPStan\Reflection\ExtendedMethodReflection;
+use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
@@ -19,6 +21,11 @@
*/
final class PreMountMethodSignatureRule implements Rule
{
+ public function __construct(
+ private ReflectionProvider $reflectionProvider,
+ ) {
+ }
+
public function getNodeType(): string
{
return Class_::class;
@@ -30,84 +37,76 @@ public function processNode(Node $node, Scope $scope): array
return [];
}
+ if ($node->namespacedName === null) {
+ return [];
+ }
+
$errors = [];
+ $reflClass = $this->reflectionProvider->getClass($node->namespacedName->toString());
foreach ($node->getMethods() as $method) {
- // Check if the method has the PreMount attribute
if (! AttributeFinder::findAttribute($method, PreMount::class)) {
continue;
}
- $errors = array_merge($errors, $this->validatePreMountMethod($method));
+ $errors[] = $this->validatePreMountMethod(
+ $method,
+ $reflClass->getMethod($method->name->name, $scope),
+ );
}
- return $errors;
+ return array_merge(...$errors);
}
/**
* @return list<\PHPStan\Rules\IdentifierRuleError>
*/
- private function validatePreMountMethod(Node\Stmt\ClassMethod $node): array
+ private function validatePreMountMethod(Node\Stmt\ClassMethod $method, ExtendedMethodReflection $reflMethod): array
{
$errors = [];
- // Check if the method is public
- if (! $node->isPublic()) {
- $errors[] = RuleErrorBuilder::message(
- sprintf('Method "%s" with #[PreMount] attribute must be public.', $node->name->toString())
- )
- ->identifier('symfonyUX.twigComponent.preMountMethodMustBePublic')
- ->line($node->getLine())
+ $methodName = $reflMethod->getName();
+ $methodParams = $reflMethod->getOnlyVariant()->getParameters();
+ $methodReturnType = $reflMethod->getOnlyVariant()->getReturnType();
+
+ // Check if method is public
+ if (! $reflMethod->isPublic()) {
+ $errors[] = RuleErrorBuilder::message(sprintf('Method "%s" with #[PreMount] attribute must be public.', $methodName))
+ ->identifier('symfonyUX.twigComponent.preMountPublic')
+ ->line($method->getLine())
->tip('Change the method visibility to public.')
->build();
}
- // Check the return type
- $returnType = $node->getReturnType();
- if ($returnType === null) {
- $errors[] = RuleErrorBuilder::message(
- sprintf('Method "%s" with #[PreMount] attribute must have a return type of "array".', $node->name->toString())
- )
- ->identifier('symfonyUX.twigComponent.preMountMethodMissingReturnType')
- ->line($node->getLine())
- ->tip('Add ": array" return type to the method.')
+ // Check parameter count and type (0 or 1 parameter allowed)
+ if (count($methodParams) > 1) {
+ $errors[] = RuleErrorBuilder::message(sprintf('Method "%s" with #[PreMount] attribute must have at most one parameter of type "array".', $methodName))
+ ->identifier('symfonyUX.twigComponent.preMountParameterCount')
+ ->line($method->getLine())
+ ->tip('The method should have zero or one parameter: "array $data" (optional).')
->build();
- } else {
- $isValidReturnType = $returnType instanceof Node\Identifier && $returnType->toString() === 'array';
-
- if (! $isValidReturnType) {
- $errors[] = RuleErrorBuilder::message(
- sprintf('Method "%s" with #[PreMount] attribute must have a return type of "array".', $node->name->toString())
- )
- ->identifier('symfonyUX.twigComponent.preMountMethodInvalidReturnType')
- ->line($returnType->getLine())
- ->tip('Change the return type to ": array".')
+ } elseif (count($methodParams) === 1) {
+ // If there is a parameter, it must be of type array
+ if (! $methodParams[0]->getType()->isArray()->yes()) {
+ $errors[] = RuleErrorBuilder::message(sprintf('Method "%s" with #[PreMount] attribute must have a parameter of type "array".', $methodName))
+ ->identifier('symfonyUX.twigComponent.preMountParameterType')
+ ->line($method->getLine())
+ ->tip('Change the parameter type to "array".')
->build();
}
}
- // Check that there is exactly one parameter of type array
- if (count($node->params) !== 1) {
- $errors[] = RuleErrorBuilder::message(
- sprintf('Method "%s" with #[PreMount] attribute must have exactly one parameter of type "array".', $node->name->toString())
- )
- ->identifier('symfonyUX.twigComponent.preMountMethodInvalidParameterCount')
- ->line($node->getLine())
- ->tip('The method should have exactly one parameter: "array $data".')
+ // Check return type (must be array, void, or array|void)
+ $isValidReturnType = $methodReturnType->isVoid()->yes()
+ || $methodReturnType->isArray()->yes()
+ || ($methodReturnType->isArray()->maybe() && $methodReturnType->isVoid()->maybe());
+
+ if (! $isValidReturnType) {
+ $errors[] = RuleErrorBuilder::message(sprintf('Method "%s" with #[PreMount] attribute must have a return type of "array", "void", or "array|void".', $methodName))
+ ->identifier('symfonyUX.twigComponent.preMountReturnType')
+ ->line($method->getLine())
+ ->tip('Change the return type to ": array", ": void", or ": array|void".')
->build();
- } else {
- $param = $node->params[0];
- $paramType = $param->type;
-
- if (! $paramType instanceof Node\Identifier || $paramType->toString() !== 'array') {
- $errors[] = RuleErrorBuilder::message(
- sprintf('Method "%s" with #[PreMount] attribute must have a parameter of type "array".', $node->name->toString())
- )
- ->identifier('symfonyUX.twigComponent.preMountMethodInvalidParameterType')
- ->line($param->getLine())
- ->tip('Change the parameter type to "array".')
- ->build();
- }
}
return $errors;
diff --git a/tests/Rules/TwigComponent/ClassNameShouldNotEndWithComponentRule/ClassNameShouldNotEndWithComponentRuleTest.php b/tests/Rules/TwigComponent/ClassNameShouldNotEndWithComponentRule/ClassNameShouldNotEndWithComponentRuleTest.php
index 52200fd..249fee2 100644
--- a/tests/Rules/TwigComponent/ClassNameShouldNotEndWithComponentRule/ClassNameShouldNotEndWithComponentRuleTest.php
+++ b/tests/Rules/TwigComponent/ClassNameShouldNotEndWithComponentRule/ClassNameShouldNotEndWithComponentRuleTest.php
@@ -16,7 +16,7 @@ final class ClassNameShouldNotEndWithComponentRuleTest extends RuleTestCase
public function testViolations(): void
{
$this->analyse(
- [__DIR__ . '/Fixture/InvalidComponentName.php'],
+ [__DIR__ . '/Fixture/AlertComponent.php'],
[
[
'Twig component class "AlertComponent" should not end with "Component".',
@@ -27,7 +27,7 @@ public function testViolations(): void
);
$this->analyse(
- [__DIR__ . '/Fixture/InvalidLiveComponentName.php'],
+ [__DIR__ . '/Fixture/CounterComponent.php'],
[
[
'Twig component class "CounterComponent" should not end with "Component".',
diff --git a/tests/Rules/TwigComponent/ClassNameShouldNotEndWithComponentRule/Fixture/InvalidComponentName.php b/tests/Rules/TwigComponent/ClassNameShouldNotEndWithComponentRule/Fixture/AlertComponent.php
similarity index 100%
rename from tests/Rules/TwigComponent/ClassNameShouldNotEndWithComponentRule/Fixture/InvalidComponentName.php
rename to tests/Rules/TwigComponent/ClassNameShouldNotEndWithComponentRule/Fixture/AlertComponent.php
diff --git a/tests/Rules/TwigComponent/ClassNameShouldNotEndWithComponentRule/Fixture/InvalidLiveComponentName.php b/tests/Rules/TwigComponent/ClassNameShouldNotEndWithComponentRule/Fixture/CounterComponent.php
similarity index 100%
rename from tests/Rules/TwigComponent/ClassNameShouldNotEndWithComponentRule/Fixture/InvalidLiveComponentName.php
rename to tests/Rules/TwigComponent/ClassNameShouldNotEndWithComponentRule/Fixture/CounterComponent.php
diff --git a/tests/Rules/TwigComponent/ClassNameShouldNotEndWithComponentRule/Fixture/ValidComponentName.php b/tests/Rules/TwigComponent/ClassNameShouldNotEndWithComponentRule/Fixture/ValidComponentName.php
index 15428a5..f654774 100644
--- a/tests/Rules/TwigComponent/ClassNameShouldNotEndWithComponentRule/Fixture/ValidComponentName.php
+++ b/tests/Rules/TwigComponent/ClassNameShouldNotEndWithComponentRule/Fixture/ValidComponentName.php
@@ -7,6 +7,6 @@
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
#[AsTwigComponent]
-final class Alert
+final class ValidComponentName
{
}
diff --git a/tests/Rules/TwigComponent/ClassNameShouldNotEndWithComponentRule/Fixture/ValidLiveComponentName.php b/tests/Rules/TwigComponent/ClassNameShouldNotEndWithComponentRule/Fixture/ValidLiveComponentName.php
index ec1a72f..d871198 100644
--- a/tests/Rules/TwigComponent/ClassNameShouldNotEndWithComponentRule/Fixture/ValidLiveComponentName.php
+++ b/tests/Rules/TwigComponent/ClassNameShouldNotEndWithComponentRule/Fixture/ValidLiveComponentName.php
@@ -7,6 +7,6 @@
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
#[AsLiveComponent]
-final class Counter
+final class ValidLiveComponentName
{
}
diff --git a/tests/Rules/TwigComponent/ForbiddenAttributesPropertyRule/Fixture/ComponentWithCustomAttributesProperty.php b/tests/Rules/TwigComponent/ForbiddenAttributesPropertyRule/Fixture/ComponentWithCustomAttributesProperty.php
index 8fc7fea..14b5665 100644
--- a/tests/Rules/TwigComponent/ForbiddenAttributesPropertyRule/Fixture/ComponentWithCustomAttributesProperty.php
+++ b/tests/Rules/TwigComponent/ForbiddenAttributesPropertyRule/Fixture/ComponentWithCustomAttributesProperty.php
@@ -7,7 +7,7 @@
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
#[AsTwigComponent(attributesVar: 'customAttributes')]
-final class ComponentWithAttributesProperty
+final class ComponentWithCustomAttributesProperty
{
public string $customAttributes;
}
diff --git a/tests/Rules/TwigComponent/PostMountMethodSignatureRule/Fixture/InvalidLiveComponent.php b/tests/Rules/TwigComponent/PostMountMethodSignatureRule/Fixture/InvalidLiveComponent.php
new file mode 100644
index 0000000..bf1f56b
--- /dev/null
+++ b/tests/Rules/TwigComponent/PostMountMethodSignatureRule/Fixture/InvalidLiveComponent.php
@@ -0,0 +1,28 @@
+
+ */
+final class PostMountMethodSignatureRuleTest extends RuleTestCase
+{
+ public function testInvalidVisibility(): void
+ {
+ $this->analyse(
+ [__DIR__ . '/Fixture/InvalidVisibility.php'],
+ [
+ [
+ 'Method "postMountProtected" with #[PostMount] attribute must be public.',
+ 13,
+ 'Change the method visibility to public.',
+ ],
+ [
+ 'Method "postMountPrivate" with #[PostMount] attribute must be public.',
+ 18,
+ 'Change the method visibility to public.',
+ ],
+ ]
+ );
+ }
+
+ public function testInvalidParameterCount(): void
+ {
+ $this->analyse(
+ [__DIR__ . '/Fixture/InvalidParameterCount.php'],
+ [
+ [
+ 'Method "postMountTooManyParams" with #[PostMount] attribute must have at most one parameter of type "array".',
+ 13,
+ 'The method should have zero or one parameter: "array $data" (optional).',
+ ],
+ ]
+ );
+ }
+
+ public function testInvalidParameterType(): void
+ {
+ $this->analyse(
+ [__DIR__ . '/Fixture/InvalidParameterType.php'],
+ [
+ [
+ 'Method "postMountWrongType" with #[PostMount] attribute must have a parameter of type "array".',
+ 13,
+ 'Change the parameter type to "array".',
+ ],
+ [
+ 'Method "postMountIntType" with #[PostMount] attribute must have a parameter of type "array".',
+ 18,
+ 'Change the parameter type to "array".',
+ ],
+ ]
+ );
+ }
+
+ public function testInvalidReturnType(): void
+ {
+ $this->analyse(
+ [__DIR__ . '/Fixture/InvalidReturnType.php'],
+ [
+ [
+ 'Method "postMountStringReturn" with #[PostMount] attribute must have a return type of "array", "void", or "array|void".',
+ 13,
+ 'Change the return type to ": array", ": void", or ": array|void".',
+ ],
+ [
+ 'Method "postMountIntReturn" with #[PostMount] attribute must have a return type of "array", "void", or "array|void".',
+ 19,
+ 'Change the return type to ": array", ": void", or ": array|void".',
+ ],
+ [
+ 'Method "postMountBoolReturn" with #[PostMount] attribute must have a return type of "array", "void", or "array|void".',
+ 25,
+ 'Change the return type to ": array", ": void", or ": array|void".',
+ ],
+ ]
+ );
+ }
+
+ public function testInvalidLiveComponent(): void
+ {
+ $this->analyse(
+ [__DIR__ . '/Fixture/InvalidLiveComponent.php'],
+ [
+ [
+ 'Method "postMountWrongType" with #[PostMount] attribute must have a parameter of type "array".',
+ 13,
+ 'Change the parameter type to "array".',
+ ],
+ [
+ 'Method "postMountWrongReturn" with #[PostMount] attribute must have a return type of "array", "void", or "array|void".',
+ 18,
+ 'Change the return type to ": array", ": void", or ": array|void".',
+ ],
+ [
+ 'Method "postMountPrivate" with #[PostMount] attribute must be public.',
+ 24,
+ 'Change the method visibility to public.',
+ ],
+ ]
+ );
+ }
+
+ public function testNoViolations(): void
+ {
+ $this->analyse(
+ [__DIR__ . '/Fixture/NotAComponent.php'],
+ []
+ );
+
+ $this->analyse(
+ [__DIR__ . '/Fixture/ValidTwigComponent.php'],
+ []
+ );
+
+ $this->analyse(
+ [__DIR__ . '/Fixture/ValidLiveComponent.php'],
+ []
+ );
+ }
+
+ public static function getAdditionalConfigFiles(): array
+ {
+ return [__DIR__ . '/config/configured_rule.neon'];
+ }
+
+ protected function getRule(): Rule
+ {
+ return self::getContainer()->getByType(PostMountMethodSignatureRule::class);
+ }
+}
diff --git a/tests/Rules/TwigComponent/PostMountMethodSignatureRule/config/configured_rule.neon b/tests/Rules/TwigComponent/PostMountMethodSignatureRule/config/configured_rule.neon
new file mode 100644
index 0000000..620095f
--- /dev/null
+++ b/tests/Rules/TwigComponent/PostMountMethodSignatureRule/config/configured_rule.neon
@@ -0,0 +1,2 @@
+rules:
+ - Kocal\PHPStanSymfonyUX\Rules\TwigComponent\PostMountMethodSignatureRule
diff --git a/tests/Rules/TwigComponent/PreMountMethodSignatureRule/Fixture/InvalidLiveComponent.php b/tests/Rules/TwigComponent/PreMountMethodSignatureRule/Fixture/InvalidLiveComponent.php
new file mode 100644
index 0000000..8576b7f
--- /dev/null
+++ b/tests/Rules/TwigComponent/PreMountMethodSignatureRule/Fixture/InvalidLiveComponent.php
@@ -0,0 +1,28 @@
+analyse(
- [__DIR__ . '/Fixture/InvalidNotPublic.php'],
+ [__DIR__ . '/Fixture/InvalidVisibility.php'],
[
[
- 'Method "preMount" with #[PreMount] attribute must be public.',
+ 'Method "preMountProtected" with #[PreMount] attribute must be public.',
13,
'Change the method visibility to public.',
],
- ]
- );
-
- $this->analyse(
- [__DIR__ . '/Fixture/InvalidNoReturnType.php'],
- [
[
- 'Method "preMount" with #[PreMount] attribute must have a return type of "array".',
- 13,
- 'Add ": array" return type to the method.',
+ 'Method "preMountPrivate" with #[PreMount] attribute must be public.',
+ 18,
+ 'Change the method visibility to public.',
],
]
);
+ }
+ public function testInvalidParameterCount(): void
+ {
$this->analyse(
- [__DIR__ . '/Fixture/InvalidWrongReturnType.php'],
+ [__DIR__ . '/Fixture/InvalidParameterCount.php'],
[
[
- 'Method "preMount" with #[PreMount] attribute must have a return type of "array".',
- 14,
- 'Change the return type to ": array".',
+ 'Method "preMountTooManyParams" with #[PreMount] attribute must have at most one parameter of type "array".',
+ 13,
+ 'The method should have zero or one parameter: "array $data" (optional).',
],
]
);
+ }
+ public function testInvalidParameterType(): void
+ {
$this->analyse(
- [__DIR__ . '/Fixture/InvalidNoParameter.php'],
+ [__DIR__ . '/Fixture/InvalidParameterType.php'],
[
[
- 'Method "preMount" with #[PreMount] attribute must have exactly one parameter of type "array".',
+ 'Method "preMountWrongType" with #[PreMount] attribute must have a parameter of type "array".',
13,
- 'The method should have exactly one parameter: "array $data".',
+ 'Change the parameter type to "array".',
+ ],
+ [
+ 'Method "preMountIntType" with #[PreMount] attribute must have a parameter of type "array".',
+ 18,
+ 'Change the parameter type to "array".',
],
]
);
+ }
+ public function testInvalidReturnType(): void
+ {
$this->analyse(
- [__DIR__ . '/Fixture/InvalidTooManyParameters.php'],
+ [__DIR__ . '/Fixture/InvalidReturnType.php'],
[
[
- 'Method "preMount" with #[PreMount] attribute must have exactly one parameter of type "array".',
+ 'Method "preMountStringReturn" with #[PreMount] attribute must have a return type of "array", "void", or "array|void".',
13,
- 'The method should have exactly one parameter: "array $data".',
+ 'Change the return type to ": array", ": void", or ": array|void".',
+ ],
+ [
+ 'Method "preMountIntReturn" with #[PreMount] attribute must have a return type of "array", "void", or "array|void".',
+ 19,
+ 'Change the return type to ": array", ": void", or ": array|void".',
],
- ]
- );
-
- $this->analyse(
- [__DIR__ . '/Fixture/InvalidWithNullableReturnType.php'],
- [
[
- 'Method "preMount" with #[PreMount] attribute must have a return type of "array".',
- 14,
- 'Change the return type to ": array".',
+ 'Method "preMountBoolReturn" with #[PreMount] attribute must have a return type of "array", "void", or "array|void".',
+ 25,
+ 'Change the return type to ": array", ": void", or ": array|void".',
],
]
);
+ }
+ public function testInvalidLiveComponent(): void
+ {
$this->analyse(
- [__DIR__ . '/Fixture/InvalidWrongParameterType.php'],
+ [__DIR__ . '/Fixture/InvalidLiveComponent.php'],
[
[
- 'Method "preMount" with #[PreMount] attribute must have a parameter of type "array".',
- 14,
+ 'Method "preMountWrongType" with #[PreMount] attribute must have a parameter of type "array".',
+ 13,
'Change the parameter type to "array".',
],
+ [
+ 'Method "preMountWrongReturn" with #[PreMount] attribute must have a return type of "array", "void", or "array|void".',
+ 18,
+ 'Change the return type to ": array", ": void", or ": array|void".',
+ ],
+ [
+ 'Method "preMountPrivate" with #[PreMount] attribute must be public.',
+ 24,
+ 'Change the method visibility to public.',
+ ],
]
);
}