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

Add stringable access check to ClassConstantRule #3910

Draft
wants to merge 1 commit into
base: 2.1.x
Choose a base branch
from

Conversation

zonuexe
Copy link
Contributor

@zonuexe zonuexe commented Mar 29, 2025

@@ -39,6 +39,7 @@ public function __construct(
private RuleLevelHelper $ruleLevelHelper,
private ClassNameCheck $classCheck,
private PhpVersion $phpVersion,
private bool $checkNonStringableDynamicAccess = true,
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 understand that we shouldn't use the default value, but I was getting the following error, probably due to a missing DI configuration, so I temporarily added = true to test.

% make phpstan
php bin/phpstan clear-result-cache -q && php -d memory_limit=448M bin/phpstan

In Resolver.php line 677:

  Service 'rules.26' (type of PHPStan\Rules\Classes\ClassConstantRule): Parameter $checkNonStringableDynamicAccess in ClassConstantRule::__construct() has no class type or default value, so its value must be
  specified.

Copy link
Member

Choose a reason for hiding this comment

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

My suggestion above will help you get rid of this error.

@zonuexe zonuexe force-pushed the feature/class-const-dynamic-access-stringable-rule branch from 25dfd4f to 4e57718 Compare March 29, 2025 21:13
@@ -60,6 +61,24 @@ public function processNode(Node $node, Scope $scope): array
$name = $constantString->getValue();
$constantNameScopes[$name] = $scope->filterByTruthyValue(new Identical($node->name, new String_($name)));
}

if ($this->checkNonStringableDynamicAccess) {
$accepts = $this->ruleLevelHelper->accepts(new StringType(), $nameType, true);
Copy link
Member

Choose a reason for hiding this comment

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

Delete this line, it's not used anywhere.

$node->name,
'',
static fn (Type $type) => $type->toString()->isString()->yes()
);
Copy link
Member

Choose a reason for hiding this comment

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

After this call there should be:

		$type = $typeResult->getType();
		if ($type instanceof ErrorType) {
			return [];
		}

Some rules return "unknown class errors" but that's irrelevant here.

@@ -19,6 +19,8 @@ class ClassConstantRuleTest extends RuleTestCase

private int $phpVersion;

private bool $checkNonStringableDynamicAccess;
Copy link
Member

Choose a reason for hiding this comment

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

If all the test cases use true then this property isn't needed at all. Just use true in the new expression in getRule.

$typeResult->getType()->toString()->isNumericString()->yes()
) {
$errors[] = RuleErrorBuilder::message(sprintf('Cannot fetch class constant with a non-stringable type %s.', $nameType->describe(VerbosityLevel::typeOnly())))
->identifier('classConstant.fetchInvalidExpression')
Copy link
Member

Choose a reason for hiding this comment

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

The error message and the identifier should reflect we're trying to access a class constant by non-stringable name. That's not obvious.

Copy link
Member

Choose a reason for hiding this comment

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

Also it might be nice to mention the class name here.

-
class: PHPStan\Rules\Classes\ClassConstantRule
arguments:
checkNonStringableDynamicAccess: %featureToggles.checkNonStringableDynamicAccess%
Copy link
Member

Choose a reason for hiding this comment

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

Why are you adding the service here in this file? Remove it please.

Copy link
Member

Choose a reason for hiding this comment

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

Instead, config.level0.neon should be modified:

  1. Remove the rule from rules section.
  2. Add the service same way you did here.
  3. But also add tags section with the corresponding tag.

@@ -39,6 +39,7 @@ public function __construct(
private RuleLevelHelper $ruleLevelHelper,
private ClassNameCheck $classCheck,
private PhpVersion $phpVersion,
private bool $checkNonStringableDynamicAccess = true,
Copy link
Member

Choose a reason for hiding this comment

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

My suggestion above will help you get rid of this error.

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.

2 participants