Skip to content

Commit

Permalink
use rule identifiers
Browse files Browse the repository at this point in the history
  • Loading branch information
TomasVotruba committed Dec 18, 2024
1 parent bd8de9e commit af1d927
Show file tree
Hide file tree
Showing 17 changed files with 101 additions and 46 deletions.
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1065,6 +1065,28 @@ final class SomeClass

<br>

## Doctrine-specific Rules

### NoGetRepositoryOutsideServiceRule

Instead of getting repository from EntityManager, use constructor injection and service pattern to keep code clean

```yaml
rules:
- Symplify\PHPStanRules\Rules\Doctrine\NoGetRepositoryOutsideServiceRule
```
```php
class SomeClass
{
public function run(EntityManagerInterface $entityManager)
{
return $entityManager->getRepository(SomeEntity::class);
}
}
```


<!-- ruledoc-end -->

<br>
Expand Down
22 changes: 22 additions & 0 deletions src/Enum/RuleIdentifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -182,4 +182,26 @@ final class RuleIdentifier
public const NO_DYNAMIC_NAME = 'symplify.noDynamicName';

public const NO_REFERENCE = 'symplify.noReference';

public const PHPUNIT_NO_MOCK_ONLY = 'phpunit.noMockOnly';

public const SINGLE_ARG_EVENT_DISPATCH = 'symfony.singleArgEventDispatch';

public const NO_ENTITY_MOCKING = 'doctrine.noEntityMocking';

public const NO_STRING_IN_GET_SUBSCRIBED_EVENTS = 'symfony.noStringInGetSubscribedEvents';

public const NO_LISTENER_WITHOUT_CONTRACT = 'symfony.noListenerWithoutContract';

public const DOCTRINE_NO_PARENT_REPOSITORY = 'doctrine.noParentRepository';

public const DOCTRINE_NO_GET_REPOSITORY_OUTSIDE_SERVICE = 'doctrine.noGetRepositoryOutsideService';

public const SYMFONY_NO_REQUIRED_OUTSIDE_CLASS = 'symfony.noRequiredOutsideClass';

public const NO_CONSTRUCTOR_OVERRIDE = 'symplify.noConstructorOverride';

public const SYMFONY_NO_ABSTRACT_CONTROLLER_CONSTRUCTOR = 'symfony.noAbstractControllerConstructor';

public const PHPUNIT_PUBLIC_STATIC_DATA_PROVIDER = 'phpunit.publicStaticDataProvider';
}
18 changes: 10 additions & 8 deletions src/PHPStan/Rules/Doctrine/NoGetRepositoryOutsideServiceRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,11 @@
use PhpParser\Node\Identifier;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleError;
use PHPStan\Rules\RuleErrorBuilder;
use Symplify\PHPStanRules\Enum\RuleIdentifier;

/**
* Check if abstract controller has constructor, as it should use
* #[Require] instead to avoid parent constructor override
*
* @see \Symplify\PHPStanRules\Tests\PHPStan\Rule\NoGetRepositoryOutsideServiceRule\NoGetRepositoryOutsideServiceRuleTest
* @see \Symplify\PHPStanRules\Tests\Rules\Doctrine\NoGetRepositoryOutsideServiceRule\NoGetRepositoryOutsideServiceRuleTest
*
* @implements Rule<MethodCall>
*/
Expand All @@ -34,7 +31,6 @@ public function getNodeType(): string

/**
* @param MethodCall $node
* @return RuleError[]
*/
public function processNode(Node $node, Scope $scope): array
{
Expand All @@ -47,7 +43,10 @@ public function processNode(Node $node, Scope $scope): array
}

if (! $scope->isInClass()) {
$ruleError = RuleErrorBuilder::message(self::ERROR_MESSAGE)->build();
$ruleError = RuleErrorBuilder::message(self::ERROR_MESSAGE)
->identifier(RuleIdentifier::DOCTRINE_NO_GET_REPOSITORY_OUTSIDE_SERVICE)
->build();

return [$ruleError];
}

Expand All @@ -57,7 +56,10 @@ public function processNode(Node $node, Scope $scope): array
return [];
}

$ruleError = RuleErrorBuilder::message(self::ERROR_MESSAGE)->build();
$ruleError = RuleErrorBuilder::message(self::ERROR_MESSAGE)
->identifier(RuleIdentifier::DOCTRINE_NO_GET_REPOSITORY_OUTSIDE_SERVICE)
->build();

return [$ruleError];
}
}
4 changes: 2 additions & 2 deletions src/PHPStan/Rules/Doctrine/NoParentRepositoryRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
use PhpParser\Node\Stmt\Class_;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleError;
use PHPStan\Rules\RuleErrorBuilder;
use Symplify\PHPStanRules\Enum\RuleIdentifier;

/**
* Check if class extends repository class,
Expand Down Expand Up @@ -39,7 +39,6 @@ public function getNodeType(): string

/**
* @param Class_ $node
* @return RuleError[]
*/
public function processNode(Node $node, Scope $scope): array
{
Expand All @@ -53,6 +52,7 @@ public function processNode(Node $node, Scope $scope): array
}

$ruleError = RuleErrorBuilder::message(self::ERROR_MESSAGE)
->identifier(RuleIdentifier::DOCTRINE_NO_PARENT_REPOSITORY)
->build();

return [$ruleError];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Symplify\PHPStanRules\PHPStan;
namespace Symplify\PHPStanRules\PHPUnit;

use PhpParser\Comment\Doc;
use PhpParser\Node\Stmt\ClassMethod;
Expand Down
8 changes: 5 additions & 3 deletions src/Rules/Complexity/NoConstructorOverrideRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
use PhpParser\NodeFinder;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleError;
use PHPStan\Rules\RuleErrorBuilder;
use Symplify\PHPStanRules\Enum\RuleIdentifier;

/**
* @implements Rule<ClassMethod>
Expand All @@ -35,7 +35,6 @@ public function getNodeType(): string

/**
* @param ClassMethod $node
* @return RuleError[]
*/
public function processNode(Node $node, Scope $scope): array
{
Expand Down Expand Up @@ -69,7 +68,10 @@ public function processNode(Node $node, Scope $scope): array
return [];
}

$ruleError = RuleErrorBuilder::message(self::ERROR_MESSAGE)->build();
$ruleError = RuleErrorBuilder::message(self::ERROR_MESSAGE)
->identifier(RuleIdentifier::NO_CONSTRUCTOR_OVERRIDE)
->build();

return [$ruleError];
}
}
4 changes: 2 additions & 2 deletions src/Rules/Doctrine/NoEntityMockingRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleError;
use PHPStan\Rules\RuleErrorBuilder;
use Symplify\PHPStanRules\Enum\RuleIdentifier;
use Symplify\PHPStanRules\PHPStan\DoctrineEntityDocumentAnalyser;

/**
Expand Down Expand Up @@ -40,7 +40,6 @@ public function getNodeType(): string

/**
* @param MethodCall $node
* @return RuleError[]
*/
public function processNode(Node $node, Scope $scope): array
{
Expand All @@ -62,6 +61,7 @@ public function processNode(Node $node, Scope $scope): array
}

$ruleError = RuleErrorBuilder::message(self::ERROR_MESSAGE)
->identifier(RuleIdentifier::NO_ENTITY_MOCKING)
->build();

return [$ruleError];
Expand Down
12 changes: 6 additions & 6 deletions src/Rules/PHPUnit/NoMockOnlyTestRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,19 @@

declare(strict_types=1);

namespace Symplify\PHPStanRules\PHPStan\Rule;
namespace Symplify\PHPStanRules\Rules\PHPUnit;

use PhpParser\Node;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt\Class_;
use PHPStan\Analyser\Scope;
use PHPStan\Node\InClassNode;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleError;
use PHPStan\Rules\RuleErrorBuilder;
use Symplify\PHPStanRules\PHPStan\PHPUnitTestAnalyser;
use Symplify\PHPStanRules\Enum\RuleIdentifier;

/**
* @see \Symplify\PHPStanRules\Tests\PHPStan\Rule\NoMockOnlyTestRule\NoMockOnlyTestRuleTest
* @see \Symplify\PHPStanRules\Tests\Rules\PHPUnit\NoMockOnlyTestRule\NoMockOnlyTestRuleTest
*
* @implements Rule<InClassNode>
*/
Expand All @@ -38,11 +37,10 @@ public function getNodeType(): string

/**
* @param InClassNode $node
* @return RuleError[]
*/
public function processNode(Node $node, Scope $scope): array
{
if (! PHPUnitTestAnalyser::isTestClass($scope)) {
if (! \Symplify\PHPStanRules\Testing\PHPUnitTestAnalyser::isTestClass($scope)) {
return [];
}

Expand Down Expand Up @@ -74,7 +72,9 @@ public function processNode(Node $node, Scope $scope): array
}

$ruleError = RuleErrorBuilder::message(self::ERROR_MESSAGE)
->identifier(RuleIdentifier::PHPUNIT_NO_MOCK_ONLY)
->build();

return [$ruleError];
}
}
12 changes: 6 additions & 6 deletions src/Rules/PHPUnit/PublicStaticDataProviderRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@

declare(strict_types=1);

namespace Symplify\PHPStanRules\PHPStan\Rule;
namespace Symplify\PHPStanRules\Rules\PHPUnit;

use PhpParser\Node;
use PhpParser\Node\Stmt\ClassMethod;
use PHPStan\Analyser\Scope;
use PHPStan\Node\InClassNode;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;
use Symplify\PHPStanRules\PHPStan\DataProviderMethodResolver;
use Symplify\PHPStanRules\PHPStan\PHPUnitTestAnalyser;
use Symplify\PHPStanRules\Enum\RuleIdentifier;
use Symplify\PHPStanRules\PHPUnit\DataProviderMethodResolver;

/**
* PHPUnit data provider have to be public and static
Expand Down Expand Up @@ -42,15 +42,15 @@ public function getNodeType(): string
*/
public function processNode(Node $node, Scope $scope): array
{
if (! PHPUnitTestAnalyser::isTestClass($scope)) {
if (! \Symplify\PHPStanRules\Testing\PHPUnitTestAnalyser::isTestClass($scope)) {
return [];
}

$ruleErrors = [];

$classLike = $node->getOriginalNode();
foreach ($classLike->getMethods() as $classMethod) {
if (! PHPUnitTestAnalyser::isTestClassMethod($classMethod)) {
if (! \Symplify\PHPStanRules\Testing\PHPUnitTestAnalyser::class::isTestClassMethod($classMethod)) {
continue;
}

Expand All @@ -75,7 +75,7 @@ public function processNode(Node $node, Scope $scope): array
if (! $dataProviderClassMethod->isStatic()) {
$errorMessage = sprintf(self::PUBLIC_ERROR_MESSAGE, $dataProviderMethodName);
$ruleErrors[] = RuleErrorBuilder::message($errorMessage)
->identifier('phpunit.publicDataProvider')
->identifier(RuleIdentifier::PHPUNIT_PUBLIC_STATIC_DATA_PROVIDER)
->line($dataProviderClassMethod->getLine())
->build();
}
Expand Down
8 changes: 5 additions & 3 deletions src/Rules/Symfony/NoAbstractControllerConstructorRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
use PhpParser\Node\Stmt\Class_;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleError;
use PHPStan\Rules\RuleErrorBuilder;
use Symplify\PHPStanRules\Enum\RuleIdentifier;

/**
* Check if abstract controller has constructor, as it should use
Expand All @@ -34,7 +34,6 @@ public function getNodeType(): string

/**
* @param Class_ $node
* @return RuleError[]
*/
public function processNode(Node $node, Scope $scope): array
{
Expand All @@ -55,7 +54,10 @@ public function processNode(Node $node, Scope $scope): array
return [];
}

$ruleError = RuleErrorBuilder::message(self::ERROR_MESSAGE)->build();
$ruleError = RuleErrorBuilder::message(self::ERROR_MESSAGE)
->identifier(RuleIdentifier::SYMFONY_NO_ABSTRACT_CONTROLLER_CONSTRUCTOR)
->build();

return [$ruleError];
}
}
9 changes: 5 additions & 4 deletions src/Rules/Symfony/NoListenerWithoutContractRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
use PHPStan\Analyser\Scope;
use PHPStan\Node\InClassNode;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleError;
use PHPStan\Rules\RuleErrorBuilder;
use Symplify\PHPStanRules\Enum\RuleIdentifier;

/**
* Based on https://tomasvotruba.com/blog/2019/07/22/how-to-convert-listeners-to-subscribers-and-reduce-your-configs
Expand All @@ -23,7 +23,7 @@ final class NoListenerWithoutContractRule implements Rule
/**
* @var string
*/
public const ERROR_MESSAGE = 'There should be no listeners defined in yaml config, use contract + PHP instead';
public const ERROR_MESSAGE = 'There should be no listeners modified in config. Use EventSubscriberInterface contract and PHP instead';

public function getNodeType(): string
{
Expand All @@ -32,7 +32,6 @@ public function getNodeType(): string

/**
* @param InClassNode $node
* @return RuleError[]
*/
public function processNode(Node $node, Scope $scope): array
{
Expand All @@ -54,7 +53,9 @@ public function processNode(Node $node, Scope $scope): array
return [];
}

$ruleError = RuleErrorBuilder::message(self::ERROR_MESSAGE)->build();
$ruleError = RuleErrorBuilder::message(self::ERROR_MESSAGE)
->identifier(RuleIdentifier::NO_LISTENER_WITHOUT_CONTRACT)
->build();

return [$ruleError];
}
Expand Down
4 changes: 2 additions & 2 deletions src/Rules/Symfony/NoRequiredOutsideClassRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
use PhpParser\Node\Stmt\Trait_;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleError;
use PHPStan\Rules\RuleErrorBuilder;
use Symplify\PHPStanRules\Enum\RuleIdentifier;

/**
* @see \Symplify\PHPStanRules\Tests\PHPStan\Rule\NoRequiredOutsideClassRule\NoRequiredOutsideClassRuleTest
Expand All @@ -37,7 +37,6 @@ public function getNodeType(): string

/**
* @param Trait_ $node
* @return RuleError[]
*/
public function processNode(Node $node, Scope $scope): array
{
Expand All @@ -47,6 +46,7 @@ public function processNode(Node $node, Scope $scope): array
if ($this->isAutowiredClassMethod($classMethod)) {
$ruleErrors[] = RuleErrorBuilder::message(self::ERROR_MESSAGE)
->file($scope->getFile())
->identifier(RuleIdentifier::SYMFONY_NO_REQUIRED_OUTSIDE_CLASS)
->line($classMethod->getLine())
->build();
}
Expand Down
Loading

0 comments on commit af1d927

Please sign in to comment.