From 6e6c31b6bb951d49c94343b5f5aec8191c9065b4 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 8 May 2019 20:24:07 +0100 Subject: [PATCH 1/3] StringClassReference sniff - better detection possible string classes In PHP string backslash can be escaped. Tokenizer returns content with escape character so we need to replace drop these escape characters. We can also reaturn early when name contains spaces as it cannot be a valid class name. --- .../Formatting/StringClassReferenceSniff.php | 17 ++++++++++++++--- .../Formatting/StringClassReferenceUnitTest.inc | 9 +++++++++ .../StringClassReferenceUnitTest.inc.fixed | 9 +++++++++ .../Formatting/StringClassReferenceUnitTest.php | 1 + 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/WebimpressCodingStandard/Sniffs/Formatting/StringClassReferenceSniff.php b/src/WebimpressCodingStandard/Sniffs/Formatting/StringClassReferenceSniff.php index 438fd70f..fcd9595a 100644 --- a/src/WebimpressCodingStandard/Sniffs/Formatting/StringClassReferenceSniff.php +++ b/src/WebimpressCodingStandard/Sniffs/Formatting/StringClassReferenceSniff.php @@ -10,10 +10,10 @@ use function class_exists; use function interface_exists; use function ltrim; -use function str_replace; +use function preg_match; use function strpos; +use function strtr; use function trait_exists; -use function trim; use const T_CONSTANT_ENCAPSED_STRING; @@ -37,7 +37,18 @@ public function process(File $phpcsFile, $stackPtr) return; } - $name = trim(str_replace(['"', "'"], '', $tokens[$stackPtr]['content'])); + $name = strtr($tokens[$stackPtr]['content'], [ + '"' => '', + "'" => '', + '\\\\' => '\\', + ]); + + if (strpos($name, '\\\\') !== false + || preg_match('/\s/', $name) + ) { + return; + } + if (class_exists($name) || interface_exists($name) || trait_exists($name)) { $error = 'String "%s" contains class reference, use ::class instead'; $data = [$name]; diff --git a/test/Sniffs/Formatting/StringClassReferenceUnitTest.inc b/test/Sniffs/Formatting/StringClassReferenceUnitTest.inc index 2352e41d..d3ca6d15 100644 --- a/test/Sniffs/Formatting/StringClassReferenceUnitTest.inc +++ b/test/Sniffs/Formatting/StringClassReferenceUnitTest.inc @@ -11,3 +11,12 @@ $trait = 'WebimpressCodingStandard\Helper\NamespacesTrait'; $nonExistingClass = 'MyNamespace\ClassDoesNotExist'; $nonSlash = 'DateTime'; + +$doubleNamespaceSeparator = 'WebimpressCodingStandardTest\\Ruleset'; +$fourBackslashes = 'WebimpressCodingStandardTest\\\\Ruleset'; +$spaceInTheName = 'WebimpressCodingStandardTest Ruleset'; +$newLineInTheName = 'WebimpressCodingStandardTest + Ruleset'; + +$spaceAtTheBeginning = ' WebimpressCodingStandardTest\\Ruleset'; +$spaceAtTheEnd = ' WebimpressCodingStandardTest\\Ruleset '; diff --git a/test/Sniffs/Formatting/StringClassReferenceUnitTest.inc.fixed b/test/Sniffs/Formatting/StringClassReferenceUnitTest.inc.fixed index 37a86606..8520de76 100644 --- a/test/Sniffs/Formatting/StringClassReferenceUnitTest.inc.fixed +++ b/test/Sniffs/Formatting/StringClassReferenceUnitTest.inc.fixed @@ -11,3 +11,12 @@ $trait = \WebimpressCodingStandard\Helper\NamespacesTrait::class; $nonExistingClass = 'MyNamespace\ClassDoesNotExist'; $nonSlash = 'DateTime'; + +$doubleNamespaceSeparator = \WebimpressCodingStandardTest\Ruleset::class; +$fourBackslashes = 'WebimpressCodingStandardTest\\\\Ruleset'; +$spaceInTheName = 'WebimpressCodingStandardTest Ruleset'; +$newLineInTheName = 'WebimpressCodingStandardTest + Ruleset'; + +$spaceAtTheBeginning = ' WebimpressCodingStandardTest\\Ruleset'; +$spaceAtTheEnd = ' WebimpressCodingStandardTest\\Ruleset '; diff --git a/test/Sniffs/Formatting/StringClassReferenceUnitTest.php b/test/Sniffs/Formatting/StringClassReferenceUnitTest.php index 12620979..5621e666 100644 --- a/test/Sniffs/Formatting/StringClassReferenceUnitTest.php +++ b/test/Sniffs/Formatting/StringClassReferenceUnitTest.php @@ -16,6 +16,7 @@ protected function getErrorList(string $testFile = '') : array 7 => 1, 8 => 1, 10 => 1, + 15 => 1, ]; } From 0657d3908e6e46e51f17aad7a5175e229ab48423 Mon Sep 17 00:00:00 2001 From: webimpress Date: Thu, 9 May 2019 21:42:54 +0100 Subject: [PATCH 2/3] StringClassReference sniff - better string checks --- .../Sniffs/Formatting/StringClassReferenceSniff.php | 5 ++++- test/Sniffs/Formatting/StringClassReferenceUnitTest.inc | 3 +++ .../Sniffs/Formatting/StringClassReferenceUnitTest.inc.fixed | 3 +++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/WebimpressCodingStandard/Sniffs/Formatting/StringClassReferenceSniff.php b/src/WebimpressCodingStandard/Sniffs/Formatting/StringClassReferenceSniff.php index fcd9595a..5186a5d4 100644 --- a/src/WebimpressCodingStandard/Sniffs/Formatting/StringClassReferenceSniff.php +++ b/src/WebimpressCodingStandard/Sniffs/Formatting/StringClassReferenceSniff.php @@ -13,6 +13,7 @@ use function preg_match; use function strpos; use function strtr; +use function substr; use function trait_exists; use const T_CONSTANT_ENCAPSED_STRING; @@ -44,7 +45,9 @@ public function process(File $phpcsFile, $stackPtr) ]); if (strpos($name, '\\\\') !== false - || preg_match('/\s/', $name) + || preg_match('/[^\\a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]/', $name) + || substr($name, -1) === '\\' + || ltrim($name, '\\') === '' ) { return; } diff --git a/test/Sniffs/Formatting/StringClassReferenceUnitTest.inc b/test/Sniffs/Formatting/StringClassReferenceUnitTest.inc index d3ca6d15..4309c667 100644 --- a/test/Sniffs/Formatting/StringClassReferenceUnitTest.inc +++ b/test/Sniffs/Formatting/StringClassReferenceUnitTest.inc @@ -20,3 +20,6 @@ $newLineInTheName = 'WebimpressCodingStandardTest $spaceAtTheBeginning = ' WebimpressCodingStandardTest\\Ruleset'; $spaceAtTheEnd = ' WebimpressCodingStandardTest\\Ruleset '; + +$namespaceSeparatorAtTheEnd = 'WebimpressCodingStandardTest\\Ruleset\\'; +$justNamespaceSeparator = '\\'; diff --git a/test/Sniffs/Formatting/StringClassReferenceUnitTest.inc.fixed b/test/Sniffs/Formatting/StringClassReferenceUnitTest.inc.fixed index 8520de76..63d387cf 100644 --- a/test/Sniffs/Formatting/StringClassReferenceUnitTest.inc.fixed +++ b/test/Sniffs/Formatting/StringClassReferenceUnitTest.inc.fixed @@ -20,3 +20,6 @@ $newLineInTheName = 'WebimpressCodingStandardTest $spaceAtTheBeginning = ' WebimpressCodingStandardTest\\Ruleset'; $spaceAtTheEnd = ' WebimpressCodingStandardTest\\Ruleset '; + +$namespaceSeparatorAtTheEnd = 'WebimpressCodingStandardTest\\Ruleset\\'; +$justNamespaceSeparator = '\\'; From 60a9b21a215e99f60934e73d3d086fa526e9175d Mon Sep 17 00:00:00 2001 From: webimpress Date: Fri, 10 May 2019 20:02:39 +0100 Subject: [PATCH 3/3] Adds CHANGELOG entry for #8 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5af8a926..7594564e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,8 @@ All notable changes to this project will be documented in this file, in reverse - [#7](https://github.com/webimpress/coding-standard/pull/7) `Commenting\DocComment` - fixes false-positive when new line was required before doc-block +- [#8](https://github.com/webimpress/coding-standard/pull/8) `Formatting\StringClassReference` - fixes checking if string is a valid class name before check if class/interface/trait exists + ## 1.0.0 - 2019-03-07 Initial release.