From f10fe2b33d164e6a2c3780231fe3591b0dac8ce1 Mon Sep 17 00:00:00 2001 From: dobryy Date: Fri, 3 Jul 2020 23:17:16 +0200 Subject: [PATCH 1/2] update rule to support multiple occurrences of the class in the string --- ...assKeywordForClassNameResolutionRector.php | 41 +++++++++++++------ .../mutiple_occurrences_in_one_string.php.inc | 27 ++++++++++++ 2 files changed, 56 insertions(+), 12 deletions(-) create mode 100644 rules/coding-style/tests/Rector/String_/UseClassKeywordForClassNameResolutionRector/Fixture/mutiple_occurrences_in_one_string.php.inc diff --git a/rules/coding-style/src/Rector/String_/UseClassKeywordForClassNameResolutionRector.php b/rules/coding-style/src/Rector/String_/UseClassKeywordForClassNameResolutionRector.php index ee26d3a7abb2..ddb21713c8d5 100644 --- a/rules/coding-style/src/Rector/String_/UseClassKeywordForClassNameResolutionRector.php +++ b/rules/coding-style/src/Rector/String_/UseClassKeywordForClassNameResolutionRector.php @@ -50,23 +50,40 @@ public function getNodeTypes(): array */ public function refactor(Node $node): ?Node { - if (substr_count($node->value, '::') !== 1) { - return null; - } - // a possible static call reference // @see https://regex101.com/r/Vv41Qr/1/ - [$before, $possibleClass, $after] = Strings::split($node->value, '#([\\\\a-zA-Z0-9_\\x80-\\xff]*)::#'); + $matches = Strings::matchAll($node->value, '#([\\\\a-zA-Z0-9_\\x80-\\xff]*)::#', PREG_PATTERN_ORDER); + + $classNames = array_filter($matches[1], function (string $className) { + return class_exists($className); + }); - if (! $possibleClass || ! class_exists($possibleClass)) { - return null; + if (empty($classNames)) { + return $node; } - $classConstFetch = new ClassConstFetch(new FullyQualified(ltrim($possibleClass, '\\')), 'class'); + $classNames = array_map(function (string $className) { + return preg_quote($className); + }, $classNames); + + // @see https://regex101.com/r/8nGS0F/1 + $splits = Strings::split($node->value, '#(' . implode('|', $classNames) . ')#'); + + foreach ($splits as $split) { + if (empty($split)) { + continue; + } + + if (class_exists($split)) { + $returnNode = new ClassConstFetch(new FullyQualified(ltrim($split, '\\')), 'class'); + } else { + $returnNode = new String_($split); + } + + $concat = ! isset($concat) ? $returnNode : new Concat($concat, $returnNode); + } - $concat = new Concat($classConstFetch, new String_('::' . $after)); - if (! empty($before)) { - $concat = new Concat(new String_($before), $classConstFetch); - $concat = new Concat($concat, new String_('::' . $after)); + if (! isset($concat)) { + return $node; } return $concat; diff --git a/rules/coding-style/tests/Rector/String_/UseClassKeywordForClassNameResolutionRector/Fixture/mutiple_occurrences_in_one_string.php.inc b/rules/coding-style/tests/Rector/String_/UseClassKeywordForClassNameResolutionRector/Fixture/mutiple_occurrences_in_one_string.php.inc new file mode 100644 index 000000000000..e393a4e7e074 --- /dev/null +++ b/rules/coding-style/tests/Rector/String_/UseClassKeywordForClassNameResolutionRector/Fixture/mutiple_occurrences_in_one_string.php.inc @@ -0,0 +1,27 @@ + +----- + From 0eb87f03e71f44c7c2cdb42db7551ab948c4ff4f Mon Sep 17 00:00:00 2001 From: dobryy Date: Sat, 4 Jul 2020 16:53:40 +0200 Subject: [PATCH 2/2] pull request comments related changes --- ...assKeywordForClassNameResolutionRector.php | 52 +++++++++++-------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/rules/coding-style/src/Rector/String_/UseClassKeywordForClassNameResolutionRector.php b/rules/coding-style/src/Rector/String_/UseClassKeywordForClassNameResolutionRector.php index ddb21713c8d5..368301e28515 100644 --- a/rules/coding-style/src/Rector/String_/UseClassKeywordForClassNameResolutionRector.php +++ b/rules/coding-style/src/Rector/String_/UseClassKeywordForClassNameResolutionRector.php @@ -50,33 +50,19 @@ public function getNodeTypes(): array */ public function refactor(Node $node): ?Node { - // @see https://regex101.com/r/Vv41Qr/1/ - $matches = Strings::matchAll($node->value, '#([\\\\a-zA-Z0-9_\\x80-\\xff]*)::#', PREG_PATTERN_ORDER); - - $classNames = array_filter($matches[1], function (string $className) { - return class_exists($className); - }); + $classNames = $this->getExistentClasses($node); - if (empty($classNames)) { + if ($classNames === []) { return $node; } - $classNames = array_map(function (string $className) { - return preg_quote($className); - }, $classNames); - - // @see https://regex101.com/r/8nGS0F/1 - $splits = Strings::split($node->value, '#(' . implode('|', $classNames) . ')#'); - - foreach ($splits as $split) { - if (empty($split)) { - continue; - } + $parts = $this->getParts($node, $classNames); - if (class_exists($split)) { - $returnNode = new ClassConstFetch(new FullyQualified(ltrim($split, '\\')), 'class'); + foreach ($parts as $part) { + if (class_exists($part)) { + $returnNode = new ClassConstFetch(new FullyQualified(ltrim($part, '\\')), 'class'); } else { - $returnNode = new String_($split); + $returnNode = new String_($part); } $concat = ! isset($concat) ? $returnNode : new Concat($concat, $returnNode); @@ -88,4 +74,28 @@ public function refactor(Node $node): ?Node return $concat; } + + public function getExistentClasses(String_ $string): array + { + // @see https://regex101.com/r/Vv41Qr/1/ + $matches = Strings::matchAll($string->value, '#([\\\\a-zA-Z0-9_\\x80-\\xff]*)::#', PREG_PATTERN_ORDER); + + return array_filter($matches[1], function (string $className) { + return class_exists($className); + }); + } + + public function getParts(String_ $string, array $classNames): array + { + $classNames = array_map(function (string $className) { + return preg_quote($className); + }, $classNames); + + // @see https://regex101.com/r/8nGS0F/1 + $parts = Strings::split($string->value, '#(' . implode('|', $classNames) . ')#'); + + return array_filter($parts, function (string $className) { + return $className !== ''; + }); + } }