Skip to content

Display user friendly message instead of a fatal error when unable to change a sniff property #905

Open
@rodrigoprimo

Description

@rodrigoprimo

Is your feature request related to a problem?

PHPCS displays a fatal error when the user inadvertently tries to change a sniff property that can't be changed from outside the class. Consider the ruleset.xml file below:

<?xml version="1.0"?>
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="phpcs.xsd">
    <rule ref="Generic.PHP.ForbiddenFunctions">
        <properties>
            <property name="patternMatch" value="true"/>
        </properties>
    </rule>
</ruleset>

It results in the following PHP fatal error:

PHP Fatal error:  Uncaught Error: Cannot access protected property PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\ForbiddenFunctionsSniff::$patternMatch in src/Ruleset.php:1620
Stack trace:
#0 src/Ruleset.php(1449): PHP_CodeSniffer\Ruleset->setSniffProperty()
#1 src/Ruleset.php(250): PHP_CodeSniffer\Ruleset->populateTokenListeners()
#2 src/Runner.php(348): PHP_CodeSniffer\Ruleset->__construct()
#3 src/Runner.php(76): PHP_CodeSniffer\Runner->init()
#4 bin/phpcs(14): PHP_CodeSniffer\Runner->runPHPCS()
#5 {main}
  thrown in src/Ruleset.php on line 1620

Describe the solution you'd like

I want to suggest that instead of a fatal error, PHPCS display a user-friendly error message alerting that the property cannot be changed.

It needs to be determined in which cases PHPCS cannot change the sniff property. Here is a non-exhaustive list:

  • The property is not public and the __set() magic method does not exist in the sniff class.
  • The property is public but read-only (PHP >= 8.1).

Additional context

Here is the code that checks if the property exists and displays an error if it doesn't:

if (property_exists($sniffObject, $propertyName) === true
|| ($sniffObject instanceof stdClass) === true
|| method_exists($sniffObject, '__set') === true
) {
$isSettable = true;
}
if ($isSettable === false) {
if ($settings['scope'] === 'sniff') {
$notice = "Property \"$propertyName\" does not exist on sniff ";
$notice .= array_search($sniffClass, $this->sniffCodes, true).'.';
$this->msgCache->add($notice, MessageCollector::ERROR);
}
return;
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions