From 1e562244a5bbe2aeab4da3459505ca865d76fc73 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sun, 14 Jun 2026 19:16:52 +0200 Subject: [PATCH 1/5] misc --- composer.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/composer.json b/composer.json index b79fad78..4679691c 100644 --- a/composer.json +++ b/composer.json @@ -5,17 +5,17 @@ "license": "MIT", "require": { "php": "^8.4", - "webmozart/assert": "^2.0", + "webmozart/assert": "^2.4", "phpstan/phpstan": "^2.2", "nette/utils": "^4.1", "phpstan/phpdoc-parser": "^2.3" }, "require-dev": { "nikic/php-parser": "^5.7", - "phpunit/phpunit": "^13.0", - "symfony/framework-bundle": "^6.2", - "illuminate/container": "^11.0", - "symplify/easy-coding-standard": "^13.1", + "phpunit/phpunit": "^13.2", + "symfony/framework-bundle": "^6.4", + "illuminate/container": "^11.51", + "symplify/easy-coding-standard": "^13.2", "tomasvotruba/class-leak": "^2.1", "rector/rector": "^2.4", "phpstan/extension-installer": "^1.4", From 10bc4c015bf8ef1a852e7fea811953ab0c726764 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sun, 14 Jun 2026 19:21:18 +0200 Subject: [PATCH 2/5] nest parameters under symplify vendor, as convention --- config/ctor-rules.neon | 8 +++++++- config/mock-rules.neon | 6 ++++-- config/phpstan-extensions.neon | 14 ++++++++------ config/services/services.neon | 30 +++++++++++++++++++++++++++++- 4 files changed, 48 insertions(+), 10 deletions(-) diff --git a/config/ctor-rules.neon b/config/ctor-rules.neon index e5bb8715..3b67881a 100644 --- a/config/ctor-rules.neon +++ b/config/ctor-rules.neon @@ -1,6 +1,12 @@ parameters: # enables NewOverSettersRule, disabled by default - ctor: false + # + # parameters: + # symplify: + # ctor: true + # + # kept flat for backward compatibility, defaults to %symplify.ctor% + ctor: %symplify.ctor% parametersSchema: ctor: bool() diff --git a/config/mock-rules.neon b/config/mock-rules.neon index 6e3db73d..f96f3df9 100644 --- a/config/mock-rules.neon +++ b/config/mock-rules.neon @@ -1,10 +1,12 @@ # PHPUnit mocking rules, enable in your phpstan.neon with: # # parameters: -# mocks: true +# symplify: +# mocks: true parameters: - mocks: false + # kept flat for backward compatibility, defaults to %symplify.mocks% + mocks: %symplify.mocks% parametersSchema: mocks: bool() diff --git a/config/phpstan-extensions.neon b/config/phpstan-extensions.neon index 5a9deab4..de1e14a0 100644 --- a/config/phpstan-extensions.neon +++ b/config/phpstan-extensions.neon @@ -1,14 +1,16 @@ # return type extensions are disabled by default; enable in your phpstan.neon with: # # parameters: -# symfonyReturnType: true -# laravelReturnType: true -# pathStrings: true +# symplify: +# symfonyReturnType: true +# laravelReturnType: true +# pathStrings: true parameters: - symfonyReturnType: false - laravelReturnType: false - pathStrings: false + # kept flat for backward compatibility, default to the %symplify.*% nested values + symfonyReturnType: %symplify.symfonyReturnType% + laravelReturnType: %symplify.laravelReturnType% + pathStrings: %symplify.pathStrings% parametersSchema: symfonyReturnType: bool() diff --git a/config/services/services.neon b/config/services/services.neon index 504f113a..9e5bd5f4 100644 --- a/config/services/services.neon +++ b/config/services/services.neon @@ -1,8 +1,36 @@ parameters: + # nested configuration, the clear and preferred way to configure these rules: + # + # parameters: + # symplify: + # mocks: true + # ctor: true + # symfonyReturnType: true + # laravelReturnType: true + # pathStrings: true + # maximumIgnoredErrorCount: 0 + symplify: + mocks: false + ctor: false + symfonyReturnType: false + laravelReturnType: false + pathStrings: false + maximumIgnoredErrorCount: 0 + # related to MaximumIgnoredErrorCountRule - maximumIgnoredErrorCount: 0 + # kept flat for backward compatibility, defaults to the nested value above + maximumIgnoredErrorCount: %symplify.maximumIgnoredErrorCount% parametersSchema: + symplify: structure([ + mocks: bool() + ctor: bool() + symfonyReturnType: bool() + laravelReturnType: bool() + pathStrings: bool() + maximumIgnoredErrorCount: int() + ]) + # related to MaximumIgnoredErrorCountRule maximumIgnoredErrorCount: int() From 0f8b94749e11275042c18492c8c0c98919aaaee9 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sun, 14 Jun 2026 19:26:49 +0200 Subject: [PATCH 3/5] next --- README.md | 19 +++++++----- config/ctor-rules.neon | 1 + config/mock-rules.neon | 1 + config/phpstan-extensions.neon | 25 +++++++++++++++- config/phpunit-rules.neon | 3 +- config/services/services.neon | 29 +------------------ .../SymplifyErrorFormatterTest.php | 4 ++- .../config/configured_rule.neon | 4 ++- .../config/configured_rule.neon | 1 + .../config/configured_rule.neon | 1 + tests/config/included_services.neon | 1 + 11 files changed, 50 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index 2eb65cdb..dc6bdb23 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,8 @@ Do you use mocks in your PHPUnit tests? Enable mocking rules with single paramet ```yaml parameters: - mocks: true + symplify: + mocks: true ```
@@ -62,9 +63,10 @@ Want sharper type inference? The return type extensions are **disabled by defaul ```yaml parameters: - symfonyReturnType: true - laravelReturnType: true - pathStrings: true + symplify: + symfonyReturnType: true + laravelReturnType: true + pathStrings: true ``` `symfonyReturnType` resolves `$container->get(SomeService::class)` to `SomeService` and Symfony Finder's `$splFileInfo->getRealPath()` to `string`. `laravelReturnType` does the same for Laravel's `$container->make(SomeService::class)`. `pathStrings` narrows `getcwd()`, `dirname()` and `realpath()` to `string`: @@ -90,7 +92,8 @@ Tired of ever growing ignored error count in your `phpstan.neon`? Set hard limit ```yaml parameters: - maximumIgnoredErrorCount: 50 + symplify: + maximumIgnoredErrorCount: 50 ```
@@ -123,7 +126,8 @@ This rule is disabled by default. Enable it with the `ctor` parameter: ```yaml parameters: - ctor: true + symplify: + ctor: true ```
@@ -2706,7 +2710,8 @@ This set is for you! Enable all mocking rules with single parameter in your `php ```yaml parameters: - mocks: true + symplify: + mocks: true ```
diff --git a/config/ctor-rules.neon b/config/ctor-rules.neon index 3b67881a..fece644c 100644 --- a/config/ctor-rules.neon +++ b/config/ctor-rules.neon @@ -2,6 +2,7 @@ parameters: # enables NewOverSettersRule, disabled by default # # parameters: + # ctor: true # symplify: # ctor: true # diff --git a/config/mock-rules.neon b/config/mock-rules.neon index f96f3df9..c61257a6 100644 --- a/config/mock-rules.neon +++ b/config/mock-rules.neon @@ -1,6 +1,7 @@ # PHPUnit mocking rules, enable in your phpstan.neon with: # # parameters: +# mocks: true # symplify: # mocks: true diff --git a/config/phpstan-extensions.neon b/config/phpstan-extensions.neon index de1e14a0..426528cc 100644 --- a/config/phpstan-extensions.neon +++ b/config/phpstan-extensions.neon @@ -1,18 +1,41 @@ -# return type extensions are disabled by default; enable in your phpstan.neon with: +# Nested configuration, the clear and preferred way to configure these rules: # # parameters: # symplify: +# mocks: true +# ctor: true # symfonyReturnType: true # laravelReturnType: true # pathStrings: true +# maximumIgnoredErrorCount: 0 +# +# The flat parameters (e.g. "mocks: true") are kept for backward compatibility +# and default to their nested "symplify.*" counterpart. parameters: + symplify: + mocks: false + ctor: false + symfonyReturnType: false + laravelReturnType: false + pathStrings: false + maximumIgnoredErrorCount: 0 + # kept flat for backward compatibility, default to the %symplify.*% nested values symfonyReturnType: %symplify.symfonyReturnType% laravelReturnType: %symplify.laravelReturnType% pathStrings: %symplify.pathStrings% parametersSchema: + symplify: structure([ + mocks: bool() + ctor: bool() + symfonyReturnType: bool() + laravelReturnType: bool() + pathStrings: bool() + maximumIgnoredErrorCount: int() + ]) + symfonyReturnType: bool() laravelReturnType: bool() pathStrings: bool() diff --git a/config/phpunit-rules.neon b/config/phpunit-rules.neon index 78da5b9e..260f1116 100644 --- a/config/phpunit-rules.neon +++ b/config/phpunit-rules.neon @@ -5,4 +5,5 @@ rules: # mocking rules moved to mock-rules.neon, enable them with: # # parameters: -# mocks: true +# symplify: +# mocks: true diff --git a/config/services/services.neon b/config/services/services.neon index 9e5bd5f4..3856d435 100644 --- a/config/services/services.neon +++ b/config/services/services.neon @@ -1,36 +1,9 @@ parameters: - # nested configuration, the clear and preferred way to configure these rules: - # - # parameters: - # symplify: - # mocks: true - # ctor: true - # symfonyReturnType: true - # laravelReturnType: true - # pathStrings: true - # maximumIgnoredErrorCount: 0 - symplify: - mocks: false - ctor: false - symfonyReturnType: false - laravelReturnType: false - pathStrings: false - maximumIgnoredErrorCount: 0 - # related to MaximumIgnoredErrorCountRule - # kept flat for backward compatibility, defaults to the nested value above + # kept flat for backward compatibility, defaults to %symplify.maximumIgnoredErrorCount% maximumIgnoredErrorCount: %symplify.maximumIgnoredErrorCount% parametersSchema: - symplify: structure([ - mocks: bool() - ctor: bool() - symfonyReturnType: bool() - laravelReturnType: bool() - pathStrings: bool() - maximumIgnoredErrorCount: int() - ]) - # related to MaximumIgnoredErrorCountRule maximumIgnoredErrorCount: int() diff --git a/tests/ErrorFormatter/SymplifyErrorFormatterTest.php b/tests/ErrorFormatter/SymplifyErrorFormatterTest.php index 07fd440f..fd13a66b 100644 --- a/tests/ErrorFormatter/SymplifyErrorFormatterTest.php +++ b/tests/ErrorFormatter/SymplifyErrorFormatterTest.php @@ -47,6 +47,8 @@ public static function provideData(): Iterator #[Override] public static function getAdditionalConfigFiles(): array { - return [__DIR__ . '/../../config/phpstan-extensions.neon']; + return [ + __DIR__ . '/../../config/phpstan-extensions.neon', + ]; } } diff --git a/tests/Rules/NewOverSettersRule/config/configured_rule.neon b/tests/Rules/NewOverSettersRule/config/configured_rule.neon index 58a9d47d..9c61ad4b 100644 --- a/tests/Rules/NewOverSettersRule/config/configured_rule.neon +++ b/tests/Rules/NewOverSettersRule/config/configured_rule.neon @@ -1,5 +1,7 @@ includes: + - ../../../../config/phpstan-extensions.neon - ../../../../config/ctor-rules.neon parameters: - ctor: true + symplify: + ctor: true diff --git a/tests/Rules/Symfony/ConfigClosure/NoDuplicateArgAutowireByTypeRule/config/configured_rule.neon b/tests/Rules/Symfony/ConfigClosure/NoDuplicateArgAutowireByTypeRule/config/configured_rule.neon index ea8e56ed..7ec8916f 100644 --- a/tests/Rules/Symfony/ConfigClosure/NoDuplicateArgAutowireByTypeRule/config/configured_rule.neon +++ b/tests/Rules/Symfony/ConfigClosure/NoDuplicateArgAutowireByTypeRule/config/configured_rule.neon @@ -1,4 +1,5 @@ includes: + - ../../../../../../config/phpstan-extensions.neon - ../../../../../../config/services/services.neon rules: diff --git a/tests/Rules/Symfony/ConfigClosure/NoDuplicateArgsAutowireByTypeRule/config/configured_rule.neon b/tests/Rules/Symfony/ConfigClosure/NoDuplicateArgsAutowireByTypeRule/config/configured_rule.neon index f8eba2f3..c961e061 100644 --- a/tests/Rules/Symfony/ConfigClosure/NoDuplicateArgsAutowireByTypeRule/config/configured_rule.neon +++ b/tests/Rules/Symfony/ConfigClosure/NoDuplicateArgsAutowireByTypeRule/config/configured_rule.neon @@ -1,4 +1,5 @@ includes: + - ../../../../../../config/phpstan-extensions.neon - ../../../../../../config/services/services.neon rules: diff --git a/tests/config/included_services.neon b/tests/config/included_services.neon index bdcc782c..641dd767 100644 --- a/tests/config/included_services.neon +++ b/tests/config/included_services.neon @@ -1,2 +1,3 @@ includes: + - ../../config/phpstan-extensions.neon - ../../config/services/services.neon From d23d931a1be6bf01d22dcb2031ec0fc47e7605f0 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Mon, 15 Jun 2026 10:14:27 +0200 Subject: [PATCH 4/5] Tidy up --- config/ctor-rules.neon | 18 ++---------------- config/mock-rules.neon | 32 +++++++++----------------------- config/phpstan-extensions.neon | 25 +++++++------------------ config/phpunit-rules.neon | 7 +------ 4 files changed, 19 insertions(+), 63 deletions(-) diff --git a/config/ctor-rules.neon b/config/ctor-rules.neon index fece644c..d5aecd08 100644 --- a/config/ctor-rules.neon +++ b/config/ctor-rules.neon @@ -1,28 +1,14 @@ -parameters: - # enables NewOverSettersRule, disabled by default - # - # parameters: - # ctor: true - # symplify: - # ctor: true - # - # kept flat for backward compatibility, defaults to %symplify.ctor% - ctor: %symplify.ctor% - -parametersSchema: - ctor: bool() - services: - class: Symplify\PHPStanRules\Collector\NewWithFollowingSettersCollector tags: - phpstan.collector arguments: - isEnabled: %ctor% + isEnabled: %symplify.ctor% - class: Symplify\PHPStanRules\Rules\NewOverSettersRule tags: - phpstan.rules.rule arguments: - isEnabled: %ctor% + isEnabled: %symplify.ctor% diff --git a/config/mock-rules.neon b/config/mock-rules.neon index c61257a6..bb1b502f 100644 --- a/config/mock-rules.neon +++ b/config/mock-rules.neon @@ -1,43 +1,29 @@ -# PHPUnit mocking rules, enable in your phpstan.neon with: -# -# parameters: -# mocks: true -# symplify: -# mocks: true - -parameters: - # kept flat for backward compatibility, defaults to %symplify.mocks% - mocks: %symplify.mocks% - -parametersSchema: - mocks: bool() - conditionalTags: # mocking Symplify\PHPStanRules\Rules\PHPUnit\NoMockOnlyTestRule: - phpstan.rules.rule: %mocks% + phpstan.rules.rule: %symplify.mocks% Symplify\PHPStanRules\Rules\PHPUnit\NoMockObjectAndRealObjectPropertyRule: - phpstan.rules.rule: %mocks% + phpstan.rules.rule: %symplify.mocks% # overly complicated Symplify\PHPStanRules\Rules\PHPUnit\NoDoubleConsecutiveTestMockRule: - phpstan.rules.rule: %mocks% + phpstan.rules.rule: %symplify.mocks% # explicit expects() Symplify\PHPStanRules\Rules\PHPUnit\ExplicitExpectsMockMethodRule: - phpstan.rules.rule: %mocks% + phpstan.rules.rule: %symplify.mocks% Symplify\PHPStanRules\Rules\PHPUnit\AvoidAnyExpectsRule: - phpstan.rules.rule: %mocks% + phpstan.rules.rule: %symplify.mocks% Symplify\PHPStanRules\Rules\PHPUnit\NoWithOnStubRule: - phpstan.rules.rule: %mocks% + phpstan.rules.rule: %symplify.mocks% Symplify\PHPStanRules\Rules\PHPUnit\RequireAtLeastOneRule: - phpstan.rules.rule: %mocks% + phpstan.rules.rule: %symplify.mocks% # better alternative than mocks Symplify\PHPStanRules\Rules\Doctrine\NoDocumentMockingRule: - phpstan.rules.rule: %mocks% + phpstan.rules.rule: %symplify.mocks% Symplify\PHPStanRules\Rules\Doctrine\NoEntityMockingRule: - phpstan.rules.rule: %mocks% + phpstan.rules.rule: %symplify.mocks% services: - Symplify\PHPStanRules\Rules\PHPUnit\NoMockOnlyTestRule diff --git a/config/phpstan-extensions.neon b/config/phpstan-extensions.neon index 426528cc..1aa8de1e 100644 --- a/config/phpstan-extensions.neon +++ b/config/phpstan-extensions.neon @@ -1,17 +1,3 @@ -# Nested configuration, the clear and preferred way to configure these rules: -# -# parameters: -# symplify: -# mocks: true -# ctor: true -# symfonyReturnType: true -# laravelReturnType: true -# pathStrings: true -# maximumIgnoredErrorCount: 0 -# -# The flat parameters (e.g. "mocks: true") are kept for backward compatibility -# and default to their nested "symplify.*" counterpart. - parameters: symplify: mocks: false @@ -43,16 +29,19 @@ parametersSchema: conditionalTags: # Symfony Container::get($1) => $1 type Symplify\PHPStanRules\ReturnTypeExtension\Symfony\ContainerGetReturnTypeExtension: - phpstan.broker.dynamicMethodReturnTypeExtension: %symfonyReturnType% + phpstan.broker.dynamicMethodReturnTypeExtension: %symplify.symfonyReturnType% + # Symfony Finder SplFileInfo::getRealPath() => string type Symplify\PHPStanRules\ReturnTypeExtension\Symfony\SplFileInfoTolerantReturnTypeExtension: - phpstan.broker.dynamicMethodReturnTypeExtension: %symfonyReturnType% + phpstan.broker.dynamicMethodReturnTypeExtension: %symplify.symfonyReturnType% + # Laravel Container::make($1) => $1 type Symplify\PHPStanRules\ReturnTypeExtension\Laravel\LaravelContainerMakeTypeExtension: - phpstan.broker.dynamicMethodReturnTypeExtension: %laravelReturnType% + phpstan.broker.dynamicMethodReturnTypeExtension: %symplify.laravelReturnType% + # getcwd()/dirname()/realpath() => always "string" Symplify\PHPStanRules\ReturnTypeExtension\NativeFunctionReturnTypeExtension: - phpstan.broker.dynamicFunctionReturnTypeExtension: %pathStrings% + phpstan.broker.dynamicFunctionReturnTypeExtension: %symplify.pathStrings% services: # use with "errorFormat: symplify" in CLI/config diff --git a/config/phpunit-rules.neon b/config/phpunit-rules.neon index 260f1116..997de3d8 100644 --- a/config/phpunit-rules.neon +++ b/config/phpunit-rules.neon @@ -1,9 +1,4 @@ rules: - Symplify\PHPStanRules\Rules\PHPUnit\PublicStaticDataProviderRule - Symplify\PHPStanRules\Rules\PHPUnit\NoAssertFuncCallInTestsRule - -# mocking rules moved to mock-rules.neon, enable them with: -# -# parameters: -# symplify: -# mocks: true +ě From 8307c756f2ab4089529e335ea54ee548b0ca4419 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Mon, 15 Jun 2026 10:18:43 +0200 Subject: [PATCH 5/5] bump --- README.md | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index dc6bdb23..a27da36c 100644 --- a/README.md +++ b/README.md @@ -49,15 +49,7 @@ includes:
-Do you use mocks in your PHPUnit tests? Enable mocking rules with single parameter: - -```yaml -parameters: - symplify: - mocks: true -``` - -
+### Symfony/Laravel container `->get()`/`->make()` return type extensions Want sharper type inference? The return type extensions are **disabled by default** — enable the ones that fit your stack: @@ -69,13 +61,18 @@ parameters: pathStrings: true ``` -`symfonyReturnType` resolves `$container->get(SomeService::class)` to `SomeService` and Symfony Finder's `$splFileInfo->getRealPath()` to `string`. `laravelReturnType` does the same for Laravel's `$container->make(SomeService::class)`. `pathStrings` narrows `getcwd()`, `dirname()` and `realpath()` to `string`: +* `symfonyReturnType` resolves + * `$container->get(SomeService::class)` to `SomeService` and + * Symfony Finder's `$splFileInfo->getRealPath()` to `string` ```php $service = $container->get(SomeService::class); // $service is now known as SomeService, instead of plain object ``` +* `laravelReturnType` does the same for Laravel's `$container->make(SomeService::class)` +* `pathStrings` narrows `getcwd()`, `dirname()` and `realpath()` to `string`: +
But at start, make baby steps with one rule at a time: