Skip to content

[CodeQuality] Skip non-constant constraint args in LoadValidatorMetadataToAttributeRector - #1000

Merged
TomasVotruba merged 3 commits into
mainfrom
skip-closure-constraint-attribute
Aug 3, 2026
Merged

[CodeQuality] Skip non-constant constraint args in LoadValidatorMetadataToAttributeRector#1000
TomasVotruba merged 3 commits into
mainfrom
skip-closure-constraint-attribute

Conversation

@TomasVotruba

@TomasVotruba TomasVotruba commented Aug 3, 2026

Copy link
Copy Markdown
Member

An attribute argument must be a constant expression. When a constraint carried something evaluated at runtime — a closure, a method call, a variable — moving it to an attribute produced a file PHP cannot even parse.

Before:

public static function loadValidatorMetadata(ClassMetadata $metadata): void
{
    $metadata->addConstraint(new Callback(
        function (self $self, ExecutionContextInterface $context): void {
            $context->buildViolation('nope')
                ->atPath('slotName')
                ->addViolation();
        },
    ));

    $metadata->addPropertyConstraint('type', new Choice(choices: (new TypeList())->getChoices()));
}

Broken output, now fixed:

+#[\Symfony\Component\Validator\Constraints\Callback(function (self $self, ExecutionContextInterface $context): void {
+    $context->buildViolation('nope')
+        ->atPath('slotName')
+        ->addViolation();
+})]
 final class SomeClass
 {
+    #[\Symfony\Component\Validator\Constraints\Choice(choices: (new TypeList())->getChoices())]
     private $type;
-
-    public static function loadValidatorMetadata(ClassMetadata $metadata): void
-    {
-        ...
-    }
 }

Such constraints are now left in loadValidatorMetadata().

A new ConstantExpressionAnalyzer decides what may become an attribute argument. It whitelists what PHP accepts — scalars, constants, class constants, arrays, new (allowed in an attribute argument since PHP 8.1, so nested constraints like new Assert\All(new Assert\NotBlank()) keep working), unary and binary operations, ternary, array dim fetch — and rejects everything else.

@TomasVotruba TomasVotruba changed the title [CodeQuality] Skip closure constraint in LoadValidatorMetadataToAttributeRector [CodeQuality] Skip non-constant constraint args in LoadValidatorMetadataToAttributeRector Aug 3, 2026
@TomasVotruba
TomasVotruba enabled auto-merge (squash) August 3, 2026 20:47
@TomasVotruba
TomasVotruba merged commit d2f220d into main Aug 3, 2026
7 checks passed
@TomasVotruba
TomasVotruba deleted the skip-closure-constraint-attribute branch August 3, 2026 20:48
@TomasVotruba TomasVotruba changed the title [CodeQuality] Skip non-constant constraint args in LoadValidatorMetadataToAttributeRector [CodeQuality] Skip constraints that cannot become an attribute in LoadValidatorMetadataToAttributeRector Aug 3, 2026
@TomasVotruba TomasVotruba changed the title [CodeQuality] Skip constraints that cannot become an attribute in LoadValidatorMetadataToAttributeRector [CodeQuality] Skip non-constant constraint args in LoadValidatorMetadataToAttributeRector Aug 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants