Skip to content

Commit

Permalink
First collector rule: NotAnalysedTraitRule
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Jun 27, 2022
1 parent 199dee4 commit c4d0527
Show file tree
Hide file tree
Showing 8 changed files with 185 additions and 0 deletions.
1 change: 1 addition & 0 deletions conf/bleedingEdge.neon
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ parameters:
readOnlyByPhpDoc: true
phpDocParserRequireWhitespaceBeforeDescription: true
runtimeReflectionRules: true
notAnalysedTrait: true
15 changes: 15 additions & 0 deletions conf/config.level4.neon
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ rules:
conditionalTags:
PHPStan\Rules\Comparison\ConstantLooseComparisonRule:
phpstan.rules.rule: %featureToggles.looseComparison%
PHPStan\Rules\Traits\TraitDeclarationCollector:
phpstan.collector: %featureToggles.notAnalysedTrait%
PHPStan\Rules\Traits\TraitUseCollector:
phpstan.collector: %featureToggles.notAnalysedTrait%
PHPStan\Rules\Traits\NotAnalysedTraitRule:
phpstan.rules.rule: %featureToggles.notAnalysedTrait%

parameters:
checkAdvancedIsset: true
Expand Down Expand Up @@ -175,3 +181,12 @@ services:
class: PHPStan\Rules\Properties\NullsafePropertyFetchRule
tags:
- phpstan.rules.rule

-
class: PHPStan\Rules\Traits\TraitDeclarationCollector

-
class: PHPStan\Rules\Traits\TraitUseCollector

-
class: PHPStan\Rules\Traits\NotAnalysedTraitRule

This comment has been minimized.

Copy link
@staabm

staabm Sep 8, 2022

Contributor

does this class miss a - phpstan.rules.rule tag?

This comment has been minimized.

Copy link
@rvanvelzen

rvanvelzen Sep 8, 2022

Contributor

It has a conditional tag (see lime 29-30)

2 changes: 2 additions & 0 deletions conf/config.neon
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ parameters:
readOnlyByPhpDoc: false
phpDocParserRequireWhitespaceBeforeDescription: false
runtimeReflectionRules: false
notAnalysedTrait: false
fileExtensions:
- php
checkAdvancedIsset: false
Expand Down Expand Up @@ -251,6 +252,7 @@ parametersSchema:
readOnlyByPhpDoc: bool()
phpDocParserRequireWhitespaceBeforeDescription: bool()
runtimeReflectionRules: bool()
notAnalysedTrait: bool()
])
fileExtensions: listOf(string())
checkAdvancedIsset: bool()
Expand Down
55 changes: 55 additions & 0 deletions src/Rules/Traits/NotAnalysedTraitRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Traits;

use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Node\CollectedDataNode;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;
use function sprintf;
use function strtolower;

/**
* @implements Rule<CollectedDataNode>
*/
class NotAnalysedTraitRule implements Rule
{

public function getNodeType(): string
{
return CollectedDataNode::class;
}

public function processNode(Node $node, Scope $scope): array
{
$traitDeclarationData = $node->get(TraitDeclarationCollector::class);
$traitUseData = $node->get(TraitUseCollector::class);

$declaredTraits = [];
foreach ($traitDeclarationData as $file => $declaration) {
foreach ($declaration as [$name, $line]) {
$declaredTraits[strtolower($name)] = [$file, $name, $line];
}
}

foreach ($traitUseData as $usedNamesData) {
foreach ($usedNamesData as $usedNames) {
foreach ($usedNames as $usedName) {
unset($declaredTraits[strtolower($usedName)]);
}
}
}

$errors = [];
foreach ($declaredTraits as [$file, $name, $line]) {
$errors[] = RuleErrorBuilder::message(sprintf(
'Trait %s is used zero times and is not analysed.',
$name,
))->file($file)->line($line)->build();
}

return $errors;
}

}
29 changes: 29 additions & 0 deletions src/Rules/Traits/TraitDeclarationCollector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Traits;

use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Collectors\Collector;

/**
* @implements Collector<Node\Stmt\Trait_, array{string, int}>
*/
class TraitDeclarationCollector implements Collector
{

public function getNodeType(): string
{
return Node\Stmt\Trait_::class;
}

public function processNode(Node $node, Scope $scope)
{
if ($node->namespacedName === null) {
return null;
}

return [$node->namespacedName->toString(), $node->getLine()];
}

}
26 changes: 26 additions & 0 deletions src/Rules/Traits/TraitUseCollector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Traits;

use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Collectors\Collector;
use function array_map;

/**
* @implements Collector<Node\Stmt\TraitUse, list<int, string>>

This comment has been minimized.

Copy link
@stof

stof Jun 27, 2022

Contributor

should be list<string>. A list does not have a generic key type.

*/
class TraitUseCollector implements Collector
{

public function getNodeType(): string
{
return Node\Stmt\TraitUse::class;
}

public function processNode(Node $node, Scope $scope)
{
return array_map(static fn (Node\Name $traitName) => $traitName->toString(), $node->traits);
}

}
37 changes: 37 additions & 0 deletions tests/PHPStan/Rules/Traits/NotAnalysedTraitRuleTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Traits;

use PHPStan\Rules\Rule;
use PHPStan\Testing\RuleTestCase;

/**
* @extends RuleTestCase<NotAnalysedTraitRule>
*/
class NotAnalysedTraitRuleTest extends RuleTestCase
{

protected function getRule(): Rule
{
return new NotAnalysedTraitRule();
}

protected function getCollectors(): array
{
return [
new TraitDeclarationCollector(),
new TraitUseCollector(),
];
}

public function testRule(): void
{
$this->analyse([__DIR__ . '/data/not-analysed-trait.php'], [
[
'Trait NotAnalysedTrait\Bar is used zero times and is not analysed.',
10,
],
]);
}

}
20 changes: 20 additions & 0 deletions tests/PHPStan/Rules/Traits/data/not-analysed-trait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace NotAnalysedTrait;

trait Foo
{

}

trait Bar
{

}

class UsesFoo
{

use Foo;

}

0 comments on commit c4d0527

Please sign in to comment.