diff --git a/tests/Core/Ruleset/ExplainTest.php b/tests/Core/Ruleset/ExplainTest.php index 51bb9d3750..caf9f4b3ce 100644 --- a/tests/Core/Ruleset/ExplainTest.php +++ b/tests/Core/Ruleset/ExplainTest.php @@ -185,10 +185,10 @@ public function testExplainWithDeprecatedSniffs() $ruleset = new Ruleset($config); $expected = PHP_EOL; - $expected .= 'The ShowSniffDeprecationsTest standard contains 9 sniffs'.PHP_EOL.PHP_EOL; + $expected .= 'The ShowSniffDeprecationsTest standard contains 10 sniffs'.PHP_EOL.PHP_EOL; - $expected .= 'TestStandard (9 sniffs)'.PHP_EOL; - $expected .= '-----------------------'.PHP_EOL; + $expected .= 'TestStandard (10 sniffs)'.PHP_EOL; + $expected .= '------------------------'.PHP_EOL; $expected .= ' TestStandard.Deprecated.WithLongReplacement *'.PHP_EOL; $expected .= ' TestStandard.Deprecated.WithoutReplacement *'.PHP_EOL; $expected .= ' TestStandard.Deprecated.WithReplacement *'.PHP_EOL; @@ -197,7 +197,8 @@ public function testExplainWithDeprecatedSniffs() $expected .= ' TestStandard.SetProperty.AllowedAsDeclared'.PHP_EOL; $expected .= ' TestStandard.SetProperty.AllowedViaMagicMethod'.PHP_EOL; $expected .= ' TestStandard.SetProperty.AllowedViaStdClass'.PHP_EOL; - $expected .= ' TestStandard.SetProperty.NotAllowedViaAttribute'.PHP_EOL.PHP_EOL; + $expected .= ' TestStandard.SetProperty.NotAllowedViaAttribute'.PHP_EOL; + $expected .= ' TestStandard.SetProperty.PropertyTypeHandling'.PHP_EOL.PHP_EOL; $expected .= '* Sniffs marked with an asterix are deprecated.'.PHP_EOL; diff --git a/tests/Core/Ruleset/Fixtures/PropertyTypeHandlingInline.inc b/tests/Core/Ruleset/Fixtures/PropertyTypeHandlingInline.inc new file mode 100644 index 0000000000..984f8cd2c2 --- /dev/null +++ b/tests/Core/Ruleset/Fixtures/PropertyTypeHandlingInline.inc @@ -0,0 +1,26 @@ +string,10=>10,float=>1.5,null=>null,true=>true,false=>false + +// phpcs:set TestStandard.SetProperty.PropertyTypeHandling expectsOldSchoolArrayWithOnlyValues[] string, 10, 1.5, null, true, false +// phpcs:set TestStandard.SetProperty.PropertyTypeHandling expectsOldSchoolArrayWithKeysAndValues[] string=>string,10=>10,float=>1.5,null=>null,true=>true,false=>false + +echo 'hello!'; diff --git a/tests/Core/Ruleset/Fixtures/TestStandard/Sniffs/SetProperty/PropertyTypeHandlingSniff.php b/tests/Core/Ruleset/Fixtures/TestStandard/Sniffs/SetProperty/PropertyTypeHandlingSniff.php new file mode 100644 index 0000000000..be4c2147db --- /dev/null +++ b/tests/Core/Ruleset/Fixtures/TestStandard/Sniffs/SetProperty/PropertyTypeHandlingSniff.php @@ -0,0 +1,125 @@ + + */ + public $expectsArrayWithOnlyValues; + + /** + * Used to verify that array properties with keys get parsed to a proper array. + * + * @var array + */ + public $expectsArrayWithKeysAndValues; + + /** + * Used to verify that array properties passed as a string get parsed to a proper array. + * + * @var array + */ + public $expectsOldSchoolArrayWithOnlyValues; + + /** + * Used to verify that array properties passed as a string with keys get parsed to a proper array. + * + * @var array + */ + public $expectsOldSchoolArrayWithKeysAndValues; + + public function register() + { + return [T_ECHO]; + } + + public function process(File $phpcsFile, $stackPtr) + { + // Do something. + } +} diff --git a/tests/Core/Ruleset/PropertyTypeHandlingInlineTest.xml b/tests/Core/Ruleset/PropertyTypeHandlingInlineTest.xml new file mode 100644 index 0000000000..0bdadc7de0 --- /dev/null +++ b/tests/Core/Ruleset/PropertyTypeHandlingInlineTest.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/tests/Core/Ruleset/PropertyTypeHandlingTest.php b/tests/Core/Ruleset/PropertyTypeHandlingTest.php new file mode 100644 index 0000000000..0e11a4892d --- /dev/null +++ b/tests/Core/Ruleset/PropertyTypeHandlingTest.php @@ -0,0 +1,226 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Ruleset; + +use PHP_CodeSniffer\Files\LocalFile; +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Tests\ConfigDouble; +use PHPUnit\Framework\TestCase; + +/** + * Test the handling of property value types for properties set via the ruleset and inline. + * + * @covers \PHP_CodeSniffer\Ruleset::processRule + * @covers \PHP_CodeSniffer\Ruleset::setSniffProperty + */ +final class PropertyTypeHandlingTest extends TestCase +{ + + /** + * Sniff code for the sniff used in these tests. + * + * @var string + */ + const SNIFF_CODE = 'TestStandard.SetProperty.PropertyTypeHandling'; + + /** + * Class name of the sniff used in these tests. + * + * @var string + */ + const SNIFF_CLASS = 'Fixtures\\TestStandard\\Sniffs\\SetProperty\\PropertyTypeHandlingSniff'; + + + /** + * Test the value type handling for properties set via a ruleset. + * + * @param string $propertyName Property name. + * @param mixed $expected Expected property value. + * + * @dataProvider dataTypeHandling + * + * @return void + */ + public function testTypeHandlingWhenSetViaRuleset($propertyName, $expected) + { + $sniffObject = $this->getSniffObjectForRuleset(); + + $this->assertSame($expected, $sniffObject->$propertyName); + + }//end testTypeHandlingWhenSetViaRuleset() + + + /** + * Test the value type handling for properties set inline in a test case file. + * + * @param string $propertyName Property name. + * @param mixed $expected Expected property value. + * + * @dataProvider dataTypeHandling + * + * @return void + */ + public function testTypeHandlingWhenSetInline($propertyName, $expected) + { + $sniffObject = $this->getSniffObjectAfterProcessingFile(); + + $this->assertSame($expected, $sniffObject->$propertyName); + + }//end testTypeHandlingWhenSetInline() + + + /** + * Data provider. + * + * @see self::testTypeHandlingWhenSetViaRuleset() + * + * @return array> + */ + public static function dataTypeHandling() + { + $expectedArrayOnlyValues = [ + 'string', + '10', + '1.5', + 'null', + 'true', + 'false', + ]; + $expectedArrayKeysAndValues = [ + 'string' => 'string', + 10 => '10', + 'float' => '1.5', + 'null' => 'null', + 'true' => 'true', + 'false' => 'false', + ]; + + return [ + 'String value (default)' => [ + 'propertyName' => 'expectsString', + 'expected' => 'arbitraryvalue', + ], + 'String with whitespace only value becomes null' => [ + 'propertyName' => 'emptyStringBecomesNull', + 'expected' => null, + ], + 'Integer value gets set as string' => [ + 'propertyName' => 'expectsIntButAcceptsString', + 'expected' => '12345', + ], + 'Float value gets set as string' => [ + 'propertyName' => 'expectsFloatButAcceptsString', + 'expected' => '12.345', + ], + 'Null value gets set as string' => [ + 'propertyName' => 'expectsNull', + 'expected' => 'null', + ], + 'Null (uppercase) value gets set as string' => [ + 'propertyName' => 'expectsNullCase', + 'expected' => 'NULL', + ], + 'True value gets set as boolean' => [ + 'propertyName' => 'expectsBooleanTrue', + 'expected' => true, + ], + 'True (mixed case) value gets set as string' => [ + 'propertyName' => 'expectsBooleanTrueCase', + 'expected' => 'True', + ], + 'False value gets set as boolean' => [ + 'propertyName' => 'expectsBooleanFalse', + 'expected' => false, + ], + 'False (mixed case) value gets set as string' => [ + 'propertyName' => 'expectsBooleanFalseCase', + 'expected' => 'fALSe', + ], + 'Array with only values' => [ + 'propertyName' => 'expectsArrayWithOnlyValues', + 'expected' => $expectedArrayOnlyValues, + ], + 'Array with keys and values' => [ + 'propertyName' => 'expectsArrayWithKeysAndValues', + 'expected' => $expectedArrayKeysAndValues, + ], + ]; + + }//end dataTypeHandling() + + + /** + * Test Helper. + * + * @see self::testTypeHandlingWhenSetViaRuleset() + * + * @return \PHP_CodeSniffer\Sniffs\Sniff + */ + private function getSniffObjectForRuleset() + { + static $sniffObject; + + if (isset($sniffObject) === false) { + // Set up the ruleset. + $standard = __DIR__."/PropertyTypeHandlingTest.xml"; + $config = new ConfigDouble(["--standard=$standard"]); + $ruleset = new Ruleset($config); + + // Verify that our target sniff has been registered. + $this->assertArrayHasKey(self::SNIFF_CODE, $ruleset->sniffCodes, 'Target sniff not registered'); + $this->assertSame(self::SNIFF_CLASS, $ruleset->sniffCodes[self::SNIFF_CODE], 'Target sniff not registered with the correct class'); + $this->assertArrayHasKey(self::SNIFF_CLASS, $ruleset->sniffs, 'Sniff class not listed in registered sniffs'); + + $sniffObject = $ruleset->sniffs[self::SNIFF_CLASS]; + } + + return $sniffObject; + + }//end getSniffObjectForRuleset() + + + /** + * Test Helper + * + * @see self::testTypeHandlingWhenSetInline() + * + * @return \PHP_CodeSniffer\Sniffs\Sniff + */ + private function getSniffObjectAfterProcessingFile() + { + static $sniffObject; + + if (isset($sniffObject) === false) { + // Set up the ruleset. + $standard = __DIR__."/PropertyTypeHandlingInlineTest.xml"; + $config = new ConfigDouble(["--standard=$standard"]); + $ruleset = new Ruleset($config); + + // Verify that our target sniff has been registered. + $this->assertArrayHasKey(self::SNIFF_CODE, $ruleset->sniffCodes, 'Target sniff not registered'); + $this->assertSame(self::SNIFF_CLASS, $ruleset->sniffCodes[self::SNIFF_CODE], 'Target sniff not registered with the correct class'); + $this->assertArrayHasKey(self::SNIFF_CLASS, $ruleset->sniffs, 'Sniff class not listed in registered sniffs'); + + $sniffObject = $ruleset->sniffs[self::SNIFF_CLASS]; + + // Process the file with inline phpcs:set annotations. + $testFile = realpath(__DIR__.'/Fixtures/PropertyTypeHandlingInline.inc'); + $this->assertNotFalse($testFile); + + $phpcsFile = new LocalFile($testFile, $ruleset, $config); + $phpcsFile->process(); + } + + return $sniffObject; + + }//end getSniffObjectAfterProcessingFile() + + +}//end class diff --git a/tests/Core/Ruleset/PropertyTypeHandlingTest.xml b/tests/Core/Ruleset/PropertyTypeHandlingTest.xml new file mode 100644 index 0000000000..ff85ca1a0b --- /dev/null +++ b/tests/Core/Ruleset/PropertyTypeHandlingTest.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +