Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Readonly classes cannot be combined with #[AllowDynamicProperties] #3738

Merged
merged 7 commits into from
Dec 20, 2024

Conversation

staabm
Copy link
Contributor

@staabm staabm commented Dec 17, 2024

@staabm staabm marked this pull request as ready for review December 17, 2024 10:57
@phpstan-bot
Copy link
Collaborator

This pull request has been marked as ready for review.

Copy link
Member

@ondrejmirtes ondrejmirtes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also need to error when this attribute is used above interfaces. Also please check what happens above enums and traits (I'm not sure).

src/Rules/Classes/ClassAttributesRule.php Outdated Show resolved Hide resolved
src/Rules/Classes/ClassAttributesRule.php Show resolved Hide resolved
@staabm
Copy link
Contributor Author

staabm commented Dec 17, 2024

We also need to error when this attribute is used above interfaces. Also please check what happens above enums and traits (I'm not sure).

I have tested this cases and linked the 3v4l.org examples in phpstan/phpstan#12281 (comment)

TL;DR:

  • enums not allowed
  • interfaces not allowed
  • traits not allowed

what do you think about adding a separate AllowDynamicPropertiesAttributeRule which targets ClassLike instead of adding this error to the existing rule?
(atm we don't have a rule which covers attributes on traits)

Copy link
Member

@ondrejmirtes ondrejmirtes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also:

  1. Please do new TraitAttributesRule similar to ClassAttributesRule that will call AttributesCheck. We need the rule to hook onto Trait_ and fetch the reflection ourselves from ReflectionProvider.
  2. Add AllowDynamicProperties check there too.

src/Rules/Classes/ClassAttributesRule.php Outdated Show resolved Hide resolved
src/Rules/Classes/ClassAttributesRule.php Outdated Show resolved Hide resolved
src/Rules/Classes/ClassAttributesRule.php Outdated Show resolved Hide resolved
src/Rules/Classes/ClassAttributesRule.php Outdated Show resolved Hide resolved
src/Rules/Classes/ClassAttributesRule.php Outdated Show resolved Hide resolved
src/Rules/Traits/TraitAttributesRule.php Outdated Show resolved Hide resolved
}

$errors = $this->attributesCheck->check(
$scope,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to do something with $scope here. Please recreate this problem 3447391 but with a trait.

We probably need to do $scope->enterTrait() here before calling the check. Just do if !$scope instanceof MutatingScope then throw ShouldNotHappen.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have adjusted the PR. I think I have reproduced the problem you are after.

adding $scope->enterTrait($classReflection) didn't work and throws:

2) PHPStan\Rules\Traits\TraitAttributesRuleTest::testBug12011
PHPStan\ShouldNotHappenException: Internal error.

C:\dvl\Workspace\phpstan-src-staabm\src\Analyser\ScopeContext.php:44
C:\dvl\Workspace\phpstan-src-staabm\src\Analyser\MutatingScope.php:2935
C:\dvl\Workspace\phpstan-src-staabm\src\Rules\Traits\TraitAttributesRule.php:49
C:\dvl\Workspace\phpstan-src-staabm\src\Analyser\FileAnalyser.php:111
C:\dvl\Workspace\phpstan-src-staabm\src\Analyser\NodeScopeResolver.php:482
C:\dvl\Workspace\phpstan-src-staabm\src\Analyser\NodeScopeResolver.php:354
C:\dvl\Workspace\phpstan-src-staabm\src\Analyser\NodeScopeResolver.php:842
C:\dvl\Workspace\phpstan-src-staabm\src\Analyser\NodeScopeResolver.php:307
C:\dvl\Workspace\phpstan-src-staabm\src\Analyser\FileAnalyser.php:212
C:\dvl\Workspace\phpstan-src-staabm\src\Analyser\Analyser.php:75
C:\dvl\Workspace\phpstan-src-staabm\src\Testing\RuleTestCase.php:177
C:\dvl\Workspace\phpstan-src-staabm\src\Testing\RuleTestCase.php:138
C:\dvl\Workspace\phpstan-src-staabm\tests\PHPStan\Rules\Traits\TraitAttributesRuleTest.php:78

at this point I have no idea what todo. could you fix the remaining thing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let me fix the build real quick

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Push the code that's crashing like that please, I will take a look

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here you are

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh right, we need to be in a class first before we can enter a trait.

I'd try two things: try to put the trait reflection into enterClass (but a different ShouldNotHappen might be thrown, not sure).

If that fails, we need to come up with some fake class to put into enterClass before we can enterTrait. It might be okay to simulate some anonymous Class_ node to use.

If it's too much work, don't worry and I'll merge the original code that doesn't use MutatingScope at all.

Copy link
Contributor Author

@staabm staabm Dec 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have class-faking without a thrown exception working. the test-case is still failling though

Will have another look after sleeping over it

@ondrejmirtes
Copy link
Member

Please keep this on 2.0.x. We don't need to be adding new features to 1.12.x anymore.

@clxmstaab clxmstaab force-pushed the readonly-dynm branch 2 times, most recently from 05dfb04 to 4fc9574 Compare December 19, 2024 17:00
@staabm staabm changed the base branch from 1.12.x to 2.0.x December 19, 2024 17:00
@ondrejmirtes
Copy link
Member

I changed my mind, I'm going to adjust it myself, thanks!

Some attribute arguments actually depend on using class instead of the trait

So we have to analyse the attributes in context of each class that uses the trait
@ondrejmirtes
Copy link
Member

See my commit and reasoning in description: b1cebc2

@ondrejmirtes
Copy link
Member

Please stop force-pushing here, I said I'm taking over. Thanks.

@ondrejmirtes ondrejmirtes force-pushed the readonly-dynm branch 2 times, most recently from b85805f to b2b833c Compare December 20, 2024 08:52
@staabm
Copy link
Contributor Author

staabm commented Dec 20, 2024

Please stop force-pushing here, I said I'm taking over. Thanks.

oh sorry, did not see your comments. I got it working just a moment ago ;)

@ondrejmirtes ondrejmirtes merged commit 202dd81 into phpstan:2.0.x Dec 20, 2024
425 of 426 checks passed
@ondrejmirtes
Copy link
Member

Thank you!

@staabm staabm deleted the readonly-dynm branch December 20, 2024 09:00
@staabm
Copy link
Contributor Author

staabm commented Dec 20, 2024

thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

readonly classes cannot be combined with #[AllowDynamicProperties]
3 participants