diff --git a/README.md b/README.md
index 58ffb918..5d99f15d 100644
--- a/README.md
+++ b/README.md
@@ -70,4 +70,1120 @@ services:
+## 3. Register Particular Rules
+
+[ruledoc-start]
+## AnnotateRegexClassConstWithRegexLinkRule
+
+Add regex101.com link to that shows the regex in practise, so it will be easier to maintain in case of bug/extension in the future
+
+- class: [`Symplify\PHPStanRules\Rules\AnnotateRegexClassConstWithRegexLinkRule`](../src/Rules/AnnotateRegexClassConstWithRegexLinkRule.php)
+
+```php
+class SomeClass
+{
+ private const COMPLICATED_REGEX = '#some_complicated_stu|ff#';
+}
+```
+
+:x:
+
+
+
+```php
+class SomeClass
+{
+ /**
+ * @see https://regex101.com/r/SZr0X5/12
+ */
+ private const COMPLICATED_REGEX = '#some_complicated_stu|ff#';
+}
+```
+
+:+1:
+
+
+
+## CheckClassNamespaceFollowPsr4Rule
+
+Class like namespace "%s" does not follow PSR-4 configuration in `composer.json`
+
+- class: [`Symplify\PHPStanRules\Rules\CheckClassNamespaceFollowPsr4Rule`](../src/Rules/CheckClassNamespaceFollowPsr4Rule.php)
+
+```php
+// defined "Foo\Bar" namespace in composer.json > autoload > psr-4
+namespace Foo;
+
+class Baz
+{
+}
+```
+
+:x:
+
+
+
+```php
+// defined "Foo\Bar" namespace in composer.json > autoload > psr-4
+namespace Foo\Bar;
+
+class Baz
+{
+}
+```
+
+:+1:
+
+
+
+## CheckRequiredInterfaceInContractNamespaceRule
+
+Interface must be located in "Contract" or "Contracts" namespace
+
+- class: [`Symplify\PHPStanRules\Rules\CheckRequiredInterfaceInContractNamespaceRule`](../src/Rules/CheckRequiredInterfaceInContractNamespaceRule.php)
+
+```php
+namespace App\Repository;
+
+interface ProductRepositoryInterface
+{
+}
+```
+
+:x:
+
+
+
+```php
+namespace App\Contract\Repository;
+
+interface ProductRepositoryInterface
+{
+}
+```
+
+:+1:
+
+
+
+## ClassNameRespectsParentSuffixRule
+
+Class should have suffix "%s" to respect parent type
+
+:wrench: **configure it!**
+
+- class: [`Symplify\PHPStanRules\Rules\ClassNameRespectsParentSuffixRule`](../src/Rules/ClassNameRespectsParentSuffixRule.php)
+
+```yaml
+services:
+ -
+ class: Symplify\PHPStanRules\Rules\ClassNameRespectsParentSuffixRule
+ tags: [phpstan.rules.rule]
+ arguments:
+ parentClasses:
+ - Symfony\Component\Console\Command\Command
+```
+
+↓
+
+```php
+class Some extends Command
+{
+}
+```
+
+:x:
+
+
+
+```php
+class SomeCommand extends Command
+{
+}
+```
+
+:+1:
+
+
+
+## ExplicitClassPrefixSuffixRule
+
+Interface have suffix of "Interface", trait have "Trait" suffix exclusively
+
+- class: [`Symplify\PHPStanRules\Rules\Explicit\ExplicitClassPrefixSuffixRule`](../src/Rules/Explicit/ExplicitClassPrefixSuffixRule.php)
+
+```php
+
+
+```php
+
+
+## ForbiddenArrayMethodCallRule
+
+Array method calls [$this, "method"] are not allowed. Use explicit method instead to help PhpStorm, PHPStan and Rector understand your code
+
+- class: [`Symplify\PHPStanRules\Rules\Complexity\ForbiddenArrayMethodCallRule`](../src/Rules/Complexity/ForbiddenArrayMethodCallRule.php)
+
+```php
+usort($items, [$this, "method"]);
+```
+
+:x:
+
+
+
+```php
+usort($items, function (array $apples) {
+ return $this->method($apples);
+};
+```
+
+:+1:
+
+
+
+## ForbiddenExtendOfNonAbstractClassRule
+
+Only abstract classes can be extended
+
+- class: [`Symplify\PHPStanRules\Rules\ForbiddenExtendOfNonAbstractClassRule`](../src/Rules/ForbiddenExtendOfNonAbstractClassRule.php)
+
+```php
+final class SomeClass extends ParentClass
+{
+}
+
+class ParentClass
+{
+}
+```
+
+:x:
+
+
+
+```php
+final class SomeClass extends ParentClass
+{
+}
+
+abstract class ParentClass
+{
+}
+```
+
+:+1:
+
+
+
+## ForbiddenFuncCallRule
+
+Function `"%s()"` cannot be used/left in the code
+
+:wrench: **configure it!**
+
+- class: [`Symplify\PHPStanRules\Rules\ForbiddenFuncCallRule`](../src/Rules/ForbiddenFuncCallRule.php)
+
+```yaml
+services:
+ -
+ class: Symplify\PHPStanRules\Rules\ForbiddenFuncCallRule
+ tags: [phpstan.rules.rule]
+ arguments:
+ forbiddenFunctions:
+ - eval
+```
+
+↓
+
+```php
+echo eval('...');
+```
+
+:x:
+
+
+
+```php
+echo '...';
+```
+
+:+1:
+
+
+
+```yaml
+services:
+ -
+ class: Symplify\PHPStanRules\Rules\ForbiddenFuncCallRule
+ tags: [phpstan.rules.rule]
+ arguments:
+ forbiddenFunctions:
+ dump: 'seems you missed some debugging function'
+```
+
+↓
+
+```php
+dump($value);
+echo $value;
+```
+
+:x:
+
+
+
+```php
+echo $value;
+```
+
+:+1:
+
+
+
+## ForbiddenMultipleClassLikeInOneFileRule
+
+Multiple class/interface/trait is not allowed in single file
+
+- class: [`Symplify\PHPStanRules\Rules\ForbiddenMultipleClassLikeInOneFileRule`](../src/Rules/ForbiddenMultipleClassLikeInOneFileRule.php)
+
+```php
+// src/SomeClass.php
+class SomeClass
+{
+}
+
+interface SomeInterface
+{
+}
+```
+
+:x:
+
+
+
+```php
+// src/SomeClass.php
+class SomeClass
+{
+}
+
+// src/SomeInterface.php
+interface SomeInterface
+{
+}
+```
+
+:+1:
+
+
+
+## ForbiddenNodeRule
+
+"%s" is forbidden to use
+
+:wrench: **configure it!**
+
+- class: [`Symplify\PHPStanRules\Rules\ForbiddenNodeRule`](../src/Rules/ForbiddenNodeRule.php)
+
+```yaml
+services:
+ -
+ class: Symplify\PHPStanRules\Rules\ForbiddenNodeRule
+ tags: [phpstan.rules.rule]
+ arguments:
+ forbiddenNodes:
+ - PhpParser\Node\Expr\ErrorSuppress
+```
+
+↓
+
+```php
+return @strlen('...');
+```
+
+:x:
+
+
+
+```php
+return strlen('...');
+```
+
+:+1:
+
+
+
+## ForbiddenStaticClassConstFetchRule
+
+Avoid static access of constants, as they can change value. Use interface and contract method instead
+
+- class: [`Symplify\PHPStanRules\Rules\ForbiddenStaticClassConstFetchRule`](../src/Rules/ForbiddenStaticClassConstFetchRule.php)
+
+```php
+class SomeClass
+{
+ public function run()
+ {
+ return static::SOME_CONST;
+ }
+}
+```
+
+:x:
+
+
+
+```php
+class SomeClass
+{
+ public function run()
+ {
+ return self::SOME_CONST;
+ }
+}
+```
+
+:+1:
+
+
+
+## NoDynamicNameRule
+
+Use explicit names over dynamic ones
+
+- class: [`Symplify\PHPStanRules\Rules\NoDynamicNameRule`](../src/Rules/NoDynamicNameRule.php)
+
+```php
+class SomeClass
+{
+ public function old(): bool
+ {
+ return $this->${variable};
+ }
+}
+```
+
+:x:
+
+
+
+```php
+class SomeClass
+{
+ public function old(): bool
+ {
+ return $this->specificMethodName();
+ }
+}
+```
+
+:+1:
+
+
+
+## NoEntityOutsideEntityNamespaceRule
+
+Class with #[Entity] attribute must be located in "Entity" namespace to be loaded by Doctrine
+
+- class: [`Symplify\PHPStanRules\Rules\NoEntityOutsideEntityNamespaceRule`](../src/Rules/NoEntityOutsideEntityNamespaceRule.php)
+
+```php
+namespace App\ValueObject;
+
+use Doctrine\ORM\Mapping as ORM;
+
+#[ORM\Entity]
+class Product
+{
+}
+```
+
+:x:
+
+
+
+```php
+namespace App\Entity;
+
+use Doctrine\ORM\Mapping as ORM;
+
+#[ORM\Entity]
+class Product
+{
+}
+```
+
+:+1:
+
+
+
+## NoGlobalConstRule
+
+Global constants are forbidden. Use enum-like class list instead
+
+- class: [`Symplify\PHPStanRules\Rules\NoGlobalConstRule`](../src/Rules/NoGlobalConstRule.php)
+
+```php
+const SOME_GLOBAL_CONST = 'value';
+```
+
+:x:
+
+
+
+```php
+class SomeClass
+{
+ public function run()
+ {
+ return self::SOME_CONST;
+ }
+}
+```
+
+:+1:
+
+
+
+## NoInlineStringRegexRule
+
+Use local named constant instead of inline string for regex to explain meaning by constant name
+
+- class: [`Symplify\PHPStanRules\Rules\NoInlineStringRegexRule`](../src/Rules/NoInlineStringRegexRule.php)
+
+```php
+class SomeClass
+{
+ public function run($value)
+ {
+ return preg_match('#some_stu|ff#', $value);
+ }
+}
+```
+
+:x:
+
+
+
+```php
+class SomeClass
+{
+ /**
+ * @var string
+ */
+ public const SOME_STUFF_REGEX = '#some_stu|ff#';
+
+ public function run($value)
+ {
+ return preg_match(self::SOME_STUFF_REGEX, $value);
+ }
+}
+```
+
+:+1:
+
+
+
+## NoReferenceRule
+
+Use explicit return value over magic &reference
+
+- class: [`Symplify\PHPStanRules\Rules\NoReferenceRule`](../src/Rules/NoReferenceRule.php)
+
+```php
+class SomeClass
+{
+ public function run(&$value)
+ {
+ }
+}
+```
+
+:x:
+
+
+
+```php
+class SomeClass
+{
+ public function run($value)
+ {
+ return $value;
+ }
+}
+```
+
+:+1:
+
+
+
+## NoReturnArrayVariableListRule
+
+Use value object over return of values
+
+- class: [`Symplify\PHPStanRules\Rules\NoReturnArrayVariableListRule`](../src/Rules/NoReturnArrayVariableListRule.php)
+
+```php
+class ReturnVariables
+{
+ public function run($value, $value2): array
+ {
+ return [$value, $value2];
+ }
+}
+```
+
+:x:
+
+
+
+```php
+final class ReturnVariables
+{
+ public function run($value, $value2): ValueObject
+ {
+ return new ValueObject($value, $value2);
+ }
+}
+```
+
+:+1:
+
+
+
+## NoReturnSetterMethodRule
+
+Setter method cannot return anything, only set value
+
+- class: [`Symplify\PHPStanRules\Rules\NoReturnSetterMethodRule`](../src/Rules/NoReturnSetterMethodRule.php)
+
+```php
+final class SomeClass
+{
+ private $name;
+
+ public function setName(string $name): int
+ {
+ return 1000;
+ }
+}
+```
+
+:x:
+
+
+
+```php
+final class SomeClass
+{
+ private $name;
+
+ public function setName(string $name): void
+ {
+ $this->name = $name;
+ }
+}
+```
+
+:+1:
+
+
+
+## NoSingleInterfaceImplementerRule
+
+Interface "%s" has only single implementer. Consider using the class directly as there is no point in using the interface.
+
+- class: [`Symplify\PHPStanRules\Rules\NoSingleInterfaceImplementerRule`](../src/Rules/NoSingleInterfaceImplementerRule.php)
+
+```php
+class SomeClass implements SomeInterface
+{
+}
+
+interface SomeInterface
+{
+}
+```
+
+:x:
+
+
+
+```php
+class SomeClass implements SomeInterface
+{
+}
+
+class AnotherClass implements SomeInterface
+{
+}
+
+interface SomeInterface
+{
+}
+```
+
+:+1:
+
+
+
+## NoTestMocksRule
+
+Mocking "%s" class is forbidden. Use direct/anonymous class instead for better static analysis
+
+- class: [`Symplify\PHPStanRules\Rules\PHPUnit\NoTestMocksRule`](../src/Rules/PHPUnit/NoTestMocksRule.php)
+
+```php
+use PHPUnit\Framework\TestCase;
+
+final class SkipApiMock extends TestCase
+{
+ public function test()
+ {
+ $someTypeMock = $this->createMock(SomeType::class);
+ }
+}
+```
+
+:x:
+
+
+
+```php
+use PHPUnit\Framework\TestCase;
+
+final class SkipApiMock extends TestCase
+{
+ public function test()
+ {
+ $someTypeMock = new class() implements SomeType {};
+ }
+}
+```
+
+:+1:
+
+
+
+## PreferredClassRule
+
+Instead of "%s" class/interface use "%s"
+
+:wrench: **configure it!**
+
+- class: [`Symplify\PHPStanRules\Rules\PreferredClassRule`](../src/Rules/PreferredClassRule.php)
+
+```yaml
+services:
+ -
+ class: Symplify\PHPStanRules\Rules\PreferredClassRule
+ tags: [phpstan.rules.rule]
+ arguments:
+ oldToPreferredClasses:
+ SplFileInfo: CustomFileInfo
+```
+
+↓
+
+```php
+class SomeClass
+{
+ public function run()
+ {
+ return new SplFileInfo('...');
+ }
+}
+```
+
+:x:
+
+
+
+```php
+class SomeClass
+{
+ public function run()
+ {
+ return new CustomFileInfo('...');
+ }
+}
+```
+
+:+1:
+
+
+
+## PreventParentMethodVisibilityOverrideRule
+
+Change `"%s()"` method visibility to "%s" to respect parent method visibility.
+
+- class: [`Symplify\PHPStanRules\Rules\PreventParentMethodVisibilityOverrideRule`](../src/Rules/PreventParentMethodVisibilityOverrideRule.php)
+
+```php
+class SomeParentClass
+{
+ public function run()
+ {
+ }
+}
+
+class SomeClass extends SomeParentClass
+{
+ protected function run()
+ {
+ }
+}
+```
+
+:x:
+
+
+
+```php
+class SomeParentClass
+{
+ public function run()
+ {
+ }
+}
+
+class SomeClass extends SomeParentClass
+{
+ public function run()
+ {
+ }
+}
+```
+
+:+1:
+
+
+
+## RegexSuffixInRegexConstantRule
+
+Name your constant with "_REGEX" suffix, instead of "%s"
+
+- class: [`Symplify\PHPStanRules\Rules\RegexSuffixInRegexConstantRule`](../src/Rules/RegexSuffixInRegexConstantRule.php)
+
+```php
+class SomeClass
+{
+ public const SOME_NAME = '#some\s+name#';
+
+ public function run($value)
+ {
+ $somePath = preg_match(self::SOME_NAME, $value);
+ }
+}
+```
+
+:x:
+
+
+
+```php
+class SomeClass
+{
+ public const SOME_NAME_REGEX = '#some\s+name#';
+
+ public function run($value)
+ {
+ $somePath = preg_match(self::SOME_NAME_REGEX, $value);
+ }
+}
+```
+
+:+1:
+
+
+
+## RequireAttributeNameRule
+
+Attribute must have all names explicitly defined
+
+- class: [`Symplify\PHPStanRules\Rules\RequireAttributeNameRule`](../src/Rules/RequireAttributeNameRule.php)
+
+```php
+use Symfony\Component\Routing\Annotation\Route;
+
+class SomeController
+{
+ #[Route("/path")]
+ public function someAction()
+ {
+ }
+}
+```
+
+:x:
+
+
+
+```php
+use Symfony\Component\Routing\Annotation\Route;
+
+class SomeController
+{
+ #[Route(path: "/path")]
+ public function someAction()
+ {
+ }
+}
+```
+
+:+1:
+
+
+
+## RequireAttributeNamespaceRule
+
+Attribute must be located in "Attribute" namespace
+
+- class: [`Symplify\PHPStanRules\Rules\Domain\RequireAttributeNamespaceRule`](../src/Rules/Domain/RequireAttributeNamespaceRule.php)
+
+```php
+// app/Entity/SomeAttribute.php
+namespace App\Controller;
+
+#[\Attribute]
+final class SomeAttribute
+{
+}
+```
+
+:x:
+
+
+
+```php
+// app/Attribute/SomeAttribute.php
+namespace App\Attribute;
+
+#[\Attribute]
+final class SomeAttribute
+{
+}
+```
+
+:+1:
+
+
+
+## RequireExceptionNamespaceRule
+
+`Exception` must be located in "Exception" namespace
+
+- class: [`Symplify\PHPStanRules\Rules\Domain\RequireExceptionNamespaceRule`](../src/Rules/Domain/RequireExceptionNamespaceRule.php)
+
+```php
+// app/Controller/SomeException.php
+namespace App\Controller;
+
+final class SomeException extends Exception
+{
+
+}
+```
+
+:x:
+
+
+
+```php
+// app/Exception/SomeException.php
+namespace App\Exception;
+
+final class SomeException extends Exception
+{
+}
+```
+
+:+1:
+
+
+
+## RequireInvokableControllerRule
+
+Use invokable controller with `__invoke()` method instead of named action method
+
+- class: [`Symplify\PHPStanRules\Symfony\Rules\RequireInvokableControllerRule`](../src/Symfony/Rules/RequireInvokableControllerRule.php)
+
+```php
+use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
+use Symfony\Component\Routing\Annotation\Route;
+
+final class SomeController extends AbstractController
+{
+ #[Route()]
+ public function someMethod()
+ {
+ }
+}
+```
+
+:x:
+
+
+
+```php
+use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
+use Symfony\Component\Routing\Annotation\Route;
+
+final class SomeController extends AbstractController
+{
+ #[Route()]
+ public function __invoke()
+ {
+ }
+}
+```
+
+:+1:
+
+
+
+## RequireUniqueEnumConstantRule
+
+Enum constants "%s" are duplicated. Make them unique instead
+
+- class: [`Symplify\PHPStanRules\Rules\Enum\RequireUniqueEnumConstantRule`](../src/Rules/Enum/RequireUniqueEnumConstantRule.php)
+
+```php
+use MyCLabs\Enum\Enum;
+
+class SomeClass extends Enum
+{
+ private const YES = 'yes';
+
+ private const NO = 'yes';
+}
+```
+
+:x:
+
+
+
+```php
+use MyCLabs\Enum\Enum;
+
+class SomeClass extends Enum
+{
+ private const YES = 'yes';
+
+ private const NO = 'no';
+}
+```
+
+:+1:
+
+
+
+## SeeAnnotationToTestRule
+
+Class "%s" is missing `@see` annotation with test case class reference
+
+:wrench: **configure it!**
+
+- class: [`Symplify\PHPStanRules\Rules\SeeAnnotationToTestRule`](../src/Rules/SeeAnnotationToTestRule.php)
+
+```yaml
+services:
+ -
+ class: Symplify\PHPStanRules\Rules\SeeAnnotationToTestRule
+ tags: [phpstan.rules.rule]
+ arguments:
+ requiredSeeTypes:
+ - Rule
+```
+
+↓
+
+```php
+class SomeClass extends Rule
+{
+}
+```
+
+:x:
+
+
+
+```php
+/**
+ * @see SomeClassTest
+ */
+class SomeClass extends Rule
+{
+}
+```
+
+:+1:
+
+
+
+## UppercaseConstantRule
+
+Constant "%s" must be uppercase
+
+- class: [`Symplify\PHPStanRules\Rules\UppercaseConstantRule`](../src/Rules/UppercaseConstantRule.php)
+
+```php
+final class SomeClass
+{
+ public const some = 'value';
+}
+```
+
+:x:
+
+
+
+```php
+final class SomeClass
+{
+ public const SOME = 'value';
+}
+```
+
+:+1:
+
+
+
+[ruledoc-end]
+
Happy coding!
diff --git a/composer.json b/composer.json
index a795ef2c..5bdd9af7 100644
--- a/composer.json
+++ b/composer.json
@@ -8,16 +8,16 @@
"nette/utils": "^3.2.9 || ^4.0",
"webmozart/assert": "^1.11",
"phpstan/phpstan": "^1.11",
- "symplify/rule-doc-generator-contracts": "^11.1.26"
+ "symplify/rule-doc-generator-contracts": "^11.2"
},
"require-dev": {
"nikic/php-parser": "^4.19",
"symplify/phpstan-extensions": "^11.4",
- "symplify/rule-doc-generator": "^12.0",
+ "symplify/rule-doc-generator": "^12.1",
"phpunit/phpunit": "^10.5",
"symfony/framework-bundle": "6.1.*",
"rector/rector": "^1.1",
- "symplify/easy-coding-standard": "^12.1",
+ "symplify/easy-coding-standard": "^12.2",
"phpstan/extension-installer": "^1.3",
"tomasvotruba/class-leak": "^0.2"
},