From e4543fac3c249fe40dad5bbd8ca574ef16e499a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gytis=20=C5=A0k=C4=97ma?= Date: Thu, 23 May 2024 15:51:02 +0300 Subject: [PATCH] feat: add IteratorItemTypeSniff --- CHANGELOG.md | 4 +- README.md | 2 + .../CodeElement/IteratorItemTypeSniff.php | 74 +++++++++++++++++++ src/Sniffs/CompositeCodeElementSniff.php | 2 + .../Sniffs/CompositeCodeElementSniffTest.php | 12 +++ tests/Sniffs/fixtures/TestIterator0.php | 15 ++++ 6 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 src/Sniffs/CodeElement/IteratorItemTypeSniff.php create mode 100644 tests/Sniffs/fixtures/TestIterator0.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 09d8acf..2c2d4cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,11 @@ All notable changes to `phpcs-type-sniff` will be documented in this file. Updates should follow the [Keep a CHANGELOG](http://keepachangelog.com/) principles. -## Unreleased +## 81.6.0 - 2024-05-23 ### Changed - Min `phpcs` version to 3.10 +### Added +- `IteratorItemTypeSniff` - enabled by default ## 81.5.2 - 2024-04-05 ### Changed diff --git a/README.md b/README.md index 5b431a5..9cb76ea 100644 --- a/README.md +++ b/README.md @@ -331,6 +331,7 @@ String `true/false` values are automatically converted to booleans. + @@ -340,6 +341,7 @@ String `true/false` values are automatically converted to booleans. + diff --git a/src/Sniffs/CodeElement/IteratorItemTypeSniff.php b/src/Sniffs/CodeElement/IteratorItemTypeSniff.php new file mode 100644 index 0000000..1b43c21 --- /dev/null +++ b/src/Sniffs/CodeElement/IteratorItemTypeSniff.php @@ -0,0 +1,74 @@ +reportType = (string)($config['reportType'] ?? 'warning'); + $this->addViolationId = (bool)($config['addViolationId'] ?? true); + } + + /** + * @inheritDoc + */ + public function register(): array + { + return [ + ClassElement::class, + ]; + } + + /** + * @inheritDoc + * @param AbstractFqcnElement $element + */ + public function process(File $file, CodeElementInterface $element, CodeElementInterface $parentElement): void + { + try { + $ref = new ReflectionClass($element->getFqcn()); + } catch (Error | ReflectionException) { + return; // give up... + } + + if (!in_array(IteratorAggregate::class, $ref->getInterfaceNames())) { + return; + } + + if ($element->getDocBlock()->getTagsByName('template-implements')) { + return; + } elseif ($element->getDocBlock()->getTagsByName('template-extends')) { + return; + } else { + $originId = $this->addViolationId ? $element->getFqcn() : null; + SniffHelper::addViolation( + $file, + 'Classes which implement IteratorAggregate must have "@template-implements IteratorAggregate"' + . ' doc tag with a specified item type or template type', + $element->getLine(), + static::CODE, + $this->reportType, + $originId + ); + } + } +} diff --git a/src/Sniffs/CompositeCodeElementSniff.php b/src/Sniffs/CompositeCodeElementSniff.php index 7c9462c..0a97b12 100644 --- a/src/Sniffs/CompositeCodeElementSniff.php +++ b/src/Sniffs/CompositeCodeElementSniff.php @@ -6,6 +6,7 @@ use Gskema\TypeSniff\Core\CodeElement\Element\CodeElementInterface; use Gskema\TypeSniff\Core\CodeElement\Element\FileElement; use Gskema\TypeSniff\Sniffs\CodeElement\FqcnDescriptionSniff; +use Gskema\TypeSniff\Sniffs\CodeElement\IteratorItemTypeSniff; use PHP_CodeSniffer\Files\File; use Gskema\TypeSniff\Core\CodeElement\CodeElementDetector; use Gskema\TypeSniff\Sniffs\CodeElement\CodeElementSniffInterface; @@ -42,6 +43,7 @@ protected function configure(array $config): void $config['sniffs'][] = FqcnPropSniff::class; $config['sniffs'][] = FqcnConstSniff::class; $config['sniffs'][] = FqcnDescriptionSniff::class; + $config['sniffs'][] = IteratorItemTypeSniff::class; // CodeElementSniff(s) are saved by their short name, meaning you can't have 2 instances of same sniff. $rawSniffs = []; diff --git a/tests/Sniffs/CompositeCodeElementSniffTest.php b/tests/Sniffs/CompositeCodeElementSniffTest.php index ac8c3df..845b17a 100644 --- a/tests/Sniffs/CompositeCodeElementSniffTest.php +++ b/tests/Sniffs/CompositeCodeElementSniffTest.php @@ -566,6 +566,18 @@ public static function dataProcess(): array ], ]; + // #25 + $dataSets[] = [ + [ + 'addViolationId' => false, + 'useReflection' => false, + ], + __DIR__ . '/fixtures/TestIterator0.php', + [ + '009 Classes which implement IteratorAggregate must have "@template-implements IteratorAggregate" doc tag with a specified item type or template type' + ], + ]; + return $dataSets; } diff --git a/tests/Sniffs/fixtures/TestIterator0.php b/tests/Sniffs/fixtures/TestIterator0.php new file mode 100644 index 0000000..eb65800 --- /dev/null +++ b/tests/Sniffs/fixtures/TestIterator0.php @@ -0,0 +1,15 @@ +