diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..bec95c44 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = space +indent_size = 4 diff --git a/.gitattributes b/.gitattributes index c802f7ae..84821a86 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,7 +1,7 @@ +/.github export-ignore /tests export-ignore .gitattributes export-ignore .gitignore export-ignore .travis.yml export- phpunit.xml export-ignore *.md export-ignore -/packages-tests export-ignore diff --git a/.github/workflows/auto_closer.yaml b/.github/workflows/auto_closer.yaml deleted file mode 100644 index de9fca80..00000000 --- a/.github/workflows/auto_closer.yaml +++ /dev/null @@ -1,23 +0,0 @@ -name: Auto Closer PR - -on: - pull_request_target: - types: [opened] - -jobs: - run: - runs-on: ubuntu-latest - steps: - - uses: superbrothers/close-pull-request@v3 - with: - # Optional. Post a issue comment just before closing a pull request. - comment: | - Hi, thank you for your contribution. - - Unfortunately, this repository is read-only. It's a split from our main monorepo repository. - - We'd like to kindly ask you to move the contribution there - https://github.com/symplify/symplify. - - We'll check it, review it and give you feed back right way. - - Thank you. diff --git a/.github/workflows/bare_run.yaml b/.github/workflows/bare_run.yaml new file mode 100644 index 00000000..68837f9a --- /dev/null +++ b/.github/workflows/bare_run.yaml @@ -0,0 +1,29 @@ +name: Bare Run on various PHP versions + +on: + push: + branches: + - main + +jobs: + bare_run: + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + php_version: ['7.2', '7.4', '8.0', '8.2'] + + steps: + - uses: actions/checkout@v3 + + - + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php_version }} + coverage: none + + - run: mkdir nested-dir + + - run: composer require symplify/phpstan-rules --dev --ansi + working-directory: nested-dir diff --git a/.github/workflows/code_analysis.yaml b/.github/workflows/code_analysis.yaml new file mode 100644 index 00000000..06f4c047 --- /dev/null +++ b/.github/workflows/code_analysis.yaml @@ -0,0 +1,53 @@ +name: Code Analysis + +on: + pull_request: null + push: + branches: + - main + +jobs: + code_analysis: + strategy: + fail-fast: false + matrix: + actions: + - + name: 'PHPStan' + run: composer phpstan --ansi + + - + name: 'Composer Validate' + run: composer validate --ansi + + - + name: 'Rector' + run: composer rector --ansi + + - + name: 'Coding Standard' + run: composer fix-cs --ansi + + - + name: 'Tests' + run: vendor/bin/phpunit + + - + name: 'Check Active Classes' + run: vendor/bin/class-leak check src --ansi + + name: ${{ matrix.actions.name }} + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + # see https://github.com/shivammathur/setup-php + - uses: shivammathur/setup-php@v2 + with: + php-version: 8.1 + coverage: none + + # composer install cache - https://github.com/ramsey/composer-install + - uses: "ramsey/composer-install@v2" + + - run: ${{ matrix.actions.run }} diff --git a/.github/workflows/downgraded_release.yaml b/.github/workflows/downgraded_release.yaml new file mode 100644 index 00000000..e9f6b266 --- /dev/null +++ b/.github/workflows/downgraded_release.yaml @@ -0,0 +1,64 @@ +name: Downgraded Release + +on: + push: + tags: + # avoid infinite looping, skip tags that ends with ".72" + # see https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#example-including-and-excluding-branches + - '*' + - '!**.72' + +jobs: + downgrade_release: + runs-on: ubuntu-latest + + steps: + - uses: "actions/checkout@v3" + with: + token: ${{ secrets.WORKFLOWS_TOKEN }} + + - + uses: "shivammathur/setup-php@v2" + with: + php-version: 8.1 + coverage: none + + # invoke patches + - run: composer install --ansi + + # but no dev packages + - run: composer update --no-dev --ansi + + # get rector to "rector-local" directory, to avoid downgrading itself in the /vendor + - run: mkdir rector-local + - run: composer require rector/rector:^0.17.1 --working-dir rector-local --ansi + + # downgrade to PHP 7.2 + - run: rector-local/vendor/bin/rector process src config --config build/rector-downgrade-php-72.php --ansi + + # clear the dev files + - run: rm -rf tests rector-local ecs.php phpstan.neon phpunit.xml .editorconfig + + # copy PHP 7.2 composer + workflows + - run: cp -r build/target-repository/. . + + # clear the dev files + - run: rm -rf build monorepo-builder.php full-tool-build.sh rector.php phpstan-for-tests.neon tests + + # setup git user + - + run: | + git config user.email "action@github.com" + git config user.name "GitHub Action" + # publish to the same repository with a new tag + # see https://tomasvotruba.com/blog/how-to-release-php-81-and-72-package-in-the-same-repository/ + - + name: "Tag Downgraded Code" + run: | + # separate a "git add" to add untracked (new) files too + git add --all + git commit -m "release PHP 7.2 downgraded" + + # force push tag, so there is only 1 version + git tag "${GITHUB_REF#refs/tags/}" --force + git push origin "${GITHUB_REF#refs/tags/}" --force diff --git a/.gitignore b/.gitignore index 8b7ef350..382f83c8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ /vendor composer.lock + +.phpunit.cache diff --git a/README.md b/README.md index 76032d39..1b22b18a 100644 --- a/README.md +++ b/README.md @@ -1,113 +1,28 @@ -# PHPStan Rules +# Type Perfect -[![Downloads](https://img.shields.io/packagist/dt/symplify/phpstan-rules.svg?style=flat-square)](https://packagist.org/packages/symplify/phpstan-rules/stats) +[![Downloads](https://img.shields.io/packagist/dt/tomasvotruba/type-perfect.svg?style=flat-square)](https://packagist.org/packages/tomasvotruba/type-perfect/stats) Set of rules for PHPStan used by Symplify projects - See [Rules Overview](docs/rules_overview.md) +
+ ## Install ```bash -composer require symplify/phpstan-rules --dev +composer requiretomasvotruba/type-perfect --dev ``` -## 1. Add Static Rules to `phpstan.neon` - -Some of rules here require configuration, some not. We recommend to start with rules that do not require any configuration, because there is just one way to use them: - -```yaml -# phpstan.neon -includes: - - vendor/symplify/phpstan-rules/config/static-rules.neon -``` - -Give it couple of days, before extending. +*Note: Make sure you use [`phpstan/extension-installer`](https://github.com/phpstan/extension-installer#usage) to load necessary service configs.*
-Some rules require extra services. To avoid service duplications, they're in the separate config that you can easily include: - -```yaml -includes: - - vendor/symplify/phpstan-rules/config/services/services.neon -``` - -*Note:* [Rules in subpackages](https://github.com/symplify/symplify/tree/main/packages/phpstan-rules/packages) contain additional service definitions which need to be included, in case you configure these rules: - -```yaml -includes: - - vendor/symplify/phpstan-rules/config/packages/cognitive-complexity/cognitive-complexity-services.neon - -services: - - - - class: Symplify\PHPStanRules\CognitiveComplexity\Rules\ClassLikeCognitiveComplexityRule - tags: [phpstan.rules.rule] - arguments: - maxClassCognitiveComplexity: 10 - -``` - -## 2. Pick from Prepared Sets - -Do you know prepared sets from ECS or Rector? Bunch of rules in single set. We use the same approach here: - -```yaml -includes: - - vendor/symplify/phpstan-rules/config/array-rules.neon - - vendor/symplify/phpstan-rules/config/code-complexity-rules.neon - - vendor/symplify/phpstan-rules/config/doctrine-rules.neon - - vendor/symplify/phpstan-rules/config/naming-rules.neon - - vendor/symplify/phpstan-rules/config/regex-rules.neon - - vendor/symplify/phpstan-rules/config/forbidden-static-rules.neon - - vendor/symplify/phpstan-rules/config/test-rules.neon -``` +@todo enable by configuration +one at a time :) levels? -Pick what you need, drop the rest. - -## 3. How we use Configurable Rules - -Last but not least, configurable rules with *saints defaults*. That's just polite wording for *opinionated*, like [`AllowedExclusiveDependencyRule`](https://github.com/symplify/phpstan-rules/blob/main/docs/rules_overview.md#allowedexclusivedependencyrule). - -You might not like them, but maybe you do: - -```yaml -# phpstan.neon -includes: - - vendor/symplify/phpstan-rules/config/configurable-rules.neon -``` - -Give it a trial run... so many erros and unclear feedback.... Would you like to **configure them yourself?** -That's good! We use one rule by another in other projects too, instead of one big import. - -- **Pick one and put it to your `phpstan.neon` manually**. -- Configure it to your specific needs and re-run PHPStan. It's easier to be responsible, when you're in control. - -E.g. `ForbiddenNodeRule`: - -```yaml -services: - - - class: Symplify\PHPStanRules\Rules\ForbiddenNodeRule - tags: [phpstan.rules.rule] - arguments: - forbiddenNodes: - - PhpParser\Node\Expr\Empty_ - - PhpParser\Node\Stmt\Switch_ - - PhpParser\Node\Expr\ErrorSuppress -``` - -You'll find them all in [rules overview](docs/rules_overview.md). - -Happy coding! +Add sets one by one, fix what you find useful and ignore the rest.
-## Report Issues - -In case you are experiencing a bug or want to request a new feature head over to the [Symplify monorepo issue tracker](https://github.com/symplify/symplify/issues) - -## Contribute - -The sources of this package are contained in the Symplify monorepo. We welcome contributions for this package on [symplify/symplify](https://github.com/symplify/symplify). +Happy coding! diff --git a/build/rector-downgrade-php-72.php b/build/rector-downgrade-php-72.php new file mode 100644 index 00000000..34d0c266 --- /dev/null +++ b/build/rector-downgrade-php-72.php @@ -0,0 +1,23 @@ +parallel(); + + $rectorConfig->sets([DowngradeLevelSetList::DOWN_TO_PHP_72]); + + $rectorConfig->ruleWithConfiguration(RemoveInterfacesRector::class, [ + DocumentedRuleInterface::class, + ConfigurableRuleInterface::class, + ]); + + $rectorConfig->skip(['*/Tests/*', '*/tests/*', __DIR__ . '/../../tests']); +}; + diff --git a/build/target-repository/.github/FUNDING.yml b/build/target-repository/.github/FUNDING.yml new file mode 100644 index 00000000..f797866a --- /dev/null +++ b/build/target-repository/.github/FUNDING.yml @@ -0,0 +1,3 @@ +# These are supported funding model platforms +github: tomasvotruba +custom: https://www.paypal.me/rectorphp diff --git a/.github/workflows/tests.yaml b/build/target-repository/.github/workflows/standalone_install.yaml similarity index 51% rename from .github/workflows/tests.yaml rename to build/target-repository/.github/workflows/standalone_install.yaml index 35cdcbf9..71846bb7 100644 --- a/.github/workflows/tests.yaml +++ b/build/target-repository/.github/workflows/standalone_install.yaml @@ -1,9 +1,9 @@ -name: Tests +name: Standalone Install on: [pull_request, push] jobs: - tests: + standalone_install: runs-on: ubuntu-latest strategy: @@ -17,15 +17,6 @@ jobs: - run: composer config --no-plugins allow-plugins.phpstan/extension-installer true - run: composer require phpstan/phpstan phpstan/extension-installer --dev - - # get current dev-main version - - run: composer require symplify/phpstan-rules:@dev --dev - - # prepare local files - - run: wget https://raw.githubusercontent.com/symplify/phpstan-rules/main/phpstan-for-tests.neon - - run: wget https://raw.githubusercontent.com/symplify/phpstan-rules/main/tests/SomeClass.php.inc - - - run: vendor/bin/phpstan analyze SomeClass.php.inc --configuration phpstan-for-tests.neon - + - run: composer require tomasvotruba/type-perfect:dev-main --dev diff --git a/build/target-repository/composer.json b/build/target-repository/composer.json new file mode 100644 index 00000000..a311a570 --- /dev/null +++ b/build/target-repository/composer.json @@ -0,0 +1,24 @@ +{ + "name": "tomasvotruba/type-perfect", + "type": "phpstan-extension", + "description": "Next level type declaration checks", + "license": "MIT", + "require": { + "php": "^7.2|^8.0", + "phpstan/phpstan": "^1.11", + "webmozart/assert": "^1.11" + }, + "autoload": { + "psr-4": { + "Rector\\TypePerfect\\": "src" + } + }, + "extra": { + "phpstan": { + "includes": [ + "config/services.neon", + "config/rules.neon" + ] + } + } +} diff --git a/phpstan-for-tests.neon b/build/target-repository/phpstan-for-tests.neon similarity index 74% rename from phpstan-for-tests.neon rename to build/target-repository/phpstan-for-tests.neon index 0d1b2a61..ead3abb6 100644 --- a/phpstan-for-tests.neon +++ b/build/target-repository/phpstan-for-tests.neon @@ -1,6 +1,6 @@ # this config is only for tests, it verifies all the rules are runnable includes: - - vendor/symplify/phpstan-rules/config/symplify-rules.neon + - vendor/tomasvotruba/type-perfect/config/rules.neon parameters: level: 4 diff --git a/composer.json b/composer.json index 8ac47da9..3361d481 100644 --- a/composer.json +++ b/composer.json @@ -1,36 +1,51 @@ { - "name": "symplify/phpstan-rules", + "name": "tomasvotruba/type-perfect", "type": "phpstan-extension", - "description": "Set of Symplify rules for PHPStan", + "description": "Next level type declaration checks", "license": "MIT", "require": { "php": "^7.2|^8.0", - "nikic/php-parser": "^4.14.0", - "nette/utils": "^3.2", - "phpstan/phpdoc-parser": "^1.6.3", - "phpstan/phpstan": "^1.8.1", - "webmozart/assert": "^1.10" + "phpstan/phpstan": "^1.11", + "webmozart/assert": "^1.11" + }, + "require-dev": { + "nikic/php-parser": "^4.19", + "symplify/phpstan-extensions": "^11.4", + "symplify/rule-doc-generator": "^12.1", + "phpunit/phpunit": "^10.5", + "rector/rector": "^1.1", + "symplify/easy-coding-standard": "^12.1", + "phpstan/extension-installer": "^1.3", + "tomasvotruba/class-leak": "^0.2" }, "autoload": { "psr-4": { - "Symplify\\PHPStanRules\\": [ - "src", - "packages" - ] + "Rector\\TypePerfect\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "Rector\\TypePerfect\\Tests\\": "tests" } }, "extra": { - "branch-alias": { - "dev-main": "11.1-dev" - }, "phpstan": { "includes": [ - "config/services/services.neon", - "config/packages/cognitive-complexity/cognitive-complexity-services.neon", - "config/packages/symfony/services.neon" + "config/services.neon", + "config/rules.neon" ] } }, - "minimum-stability": "dev", - "prefer-stable": true + "config": { + "platform-check": false, + "allow-plugins": { + "phpstan/extension-installer": true + } + }, + "scripts": { + "check-cs": "vendor/bin/ecs check --ansi", + "fix-cs": "vendor/bin/ecs check --fix --ansi", + "phpstan": "vendor/bin/phpstan analyse --ansi --error-format symplify", + "rector": "vendor/bin/rector process --dry-run --ansi" + } } diff --git a/config/array-rules.neon b/config/array-rules.neon deleted file mode 100644 index 1a227ae6..00000000 --- a/config/array-rules.neon +++ /dev/null @@ -1,6 +0,0 @@ -rules: - - Symplify\PHPStanRules\Rules\NoArrayStringObjectReturnRule - - Symplify\PHPStanRules\Rules\NoMultiArrayAssignRule - - Symplify\PHPStanRules\Rules\NoReturnArrayVariableListRule - - Symplify\PHPStanRules\Rules\ForbiddenArrayDestructRule - - Symplify\PHPStanRules\Rules\ForbiddenArrayWithStringKeysRule diff --git a/config/code-complexity-rules.neon b/config/code-complexity-rules.neon deleted file mode 100644 index b7d57ad9..00000000 --- a/config/code-complexity-rules.neon +++ /dev/null @@ -1,22 +0,0 @@ -rules: - - Symplify\PHPStanRules\Rules\Explicit\NoMixedArrayDimFetchRule - - Symplify\PHPStanRules\Rules\Explicit\NoMissingArrayShapeReturnArrayRule - - Symplify\PHPStanRules\Rules\Explicit\NoMixedCallableRule - - Symplify\PHPStanRules\Rules\Explicit\NoMixedPropertyFetcherRule - - Symplify\PHPStanRules\Rules\Explicit\NoMixedMethodCallerRule - - Symplify\PHPStanRules\Rules\Complexity\ForbiddenNamedArgumentsRule - - Symplify\PHPStanRules\Rules\Explicit\NoGetterAndPropertyRule - - Symplify\PHPStanRules\Rules\Explicit\ExplicitMethodCallOverMagicGetSetRule - - Symplify\PHPStanRules\Rules\Complexity\NoMirrorAssertRule - - Symplify\PHPStanRules\Rules\PHPUnit\NoRightPHPUnitAssertScalarRule - - Symplify\PHPStanRules\Rules\Complexity\NoDuplicatedArgumentRule - - Symplify\PHPStanRules\Rules\Complexity\NoAbstractRule - - Symplify\PHPStanRules\Rules\Complexity\ForbiddenInlineClassMethodRule - - Symplify\PHPStanRules\Rules\Enum\NoConstantInterfaceRule - - Symplify\PHPStanRules\Rules\Enum\RequireEnumDocBlockOnConstantListPassRule - - Symplify\PHPStanRules\Rules\NoFuncCallInMethodCallRule - - Symplify\PHPStanRules\Rules\NoDynamicNameRule - - Symplify\PHPStanRules\ObjectCalisthenics\Rules\NoChainMethodCallRule - - Symplify\PHPStanRules\Rules\ForbiddenNestedCallInAssertMethodCallRule - - Symplify\PHPStanRules\Rules\Explicit\NoRelativeFilePathRule - - Symplify\PHPStanRules\Rules\Explicit\NoMissingAssingNoVoidMethodCallRule diff --git a/config/collector-rules.neon b/config/collector-rules.neon deleted file mode 100644 index 54d80d02..00000000 --- a/config/collector-rules.neon +++ /dev/null @@ -1,44 +0,0 @@ -includes: - - type-coverage-rules.neon - -# these rule focus on the whole-project analysis, see https://phpstan.org/developing-extensions/collectors -rules: - - Symplify\PHPStanRules\Rules\NarrowType\NarrowPublicClassMethodParamTypeByCallerTypeRule - - Symplify\PHPStanRules\Rules\Explicit\NoDuplicatedVariableCasingNameRule - - Symplify\PHPStanRules\Rules\Domain\NoDuplicatedRegexRule - - Symplify\PHPStanRules\Rules\Complexity\NoDuplicatedTraitMethodNameRule - - Symplify\PHPStanRules\Rules\Domain\ForbiddenAlwaysSetterCallRule - -services: - # for ForbiddenAlwaysSetterCallRule - - - class: Symplify\PHPStanRules\Collector\ClassMethod\FormTypeClassCollector - tags: [phpstan.collector] - - - - class: Symplify\PHPStanRules\Collector\ClassMethod\NewAndSetterCallsCollector - tags: [phpstan.collector] - - # for NoDuplicatedRegexRule - - - class: Symplify\PHPStanRules\Collector\ClassConst\RegexClassConstCollector - tags: [phpstan.collector] - - # for NoDuplicatedVariableCasingNameRule - - - class: Symplify\PHPStanRules\Collector\Variable\VariableNameCollector - tags: [phpstan.collector] - - - # for NarrowPublicClassMethodParamTypeByCallerTypeRule - - - class: Symplify\PHPStanRules\Collector\ClassMethod\PublicClassMethodParamTypesCollector - tags: [phpstan.collector] - - - - class: Symplify\PHPStanRules\Collector\MethodCall\MethodCallArgTypesCollector - tags: [phpstan.collector] - - - - class: Symplify\PHPStanRules\Collector\ClassLike\TraitMethodNameCollector - tags: [phpstan.collector] diff --git a/config/configurable-rules.neon b/config/configurable-rules.neon deleted file mode 100644 index cbd03c26..00000000 --- a/config/configurable-rules.neon +++ /dev/null @@ -1,92 +0,0 @@ -services: - - - class: Symplify\PHPStanRules\Rules\NoDuplicatedShortClassNameRule - tags: [phpstan.rules.rule] - arguments: - toleratedNestingLevel: 2 - - - - class: Symplify\PHPStanRules\Rules\PreventDuplicateClassMethodRule - tags: [phpstan.rules.rule] - arguments: - minimumLineCount: 4 - - # required for "PreventDuplicateClassMethodRule" - - - class: Symplify\PHPStanRules\Collector\ClassMethod\ClassMethodContentCollector - tags: [phpstan.collector] - - - - class: Symplify\PHPStanRules\ObjectCalisthenics\Rules\NoShortNameRule - tags: [phpstan.rules.rule] - arguments: - minNameLength: 2 - - - - class: Symplify\PHPStanRules\Rules\ForbiddenNodeRule - tags: [phpstan.rules.rule] - arguments: - forbiddenNodes: - - PhpParser\Node\Stmt\Trait_ - - PhpParser\Node\Expr\Empty_ - - PhpParser\Node\Stmt\Switch_ - - PhpParser\Node\Expr\ErrorSuppress - - PhpParser\Node\Scalar\Encapsed - - PhpParser\Node\Scalar\EncapsedStringPart - # use pre* nodes instead - - PhpParser\Node\Expr\PostInc - - PhpParser\Node\Expr\PostDec - - - - class: Symplify\PHPStanRules\Rules\PreferredClassRule - tags: [phpstan.rules.rule] - arguments: - oldToPreferredClasses: - PHPStan\Node\ClassMethod: 'PhpParser\Node\Stmt\ClassMethod' - DateTime: 'Nette\Utils\DateTime' - 'PhpCsFixer\Finder': 'Symfony\Component\Finder\Finder' - # smart file system - 'Symfony\Component\Finder\SplFileInfo': 'Symplify\SmartFileSystem\SmartFileInfo' - - - - class: Symplify\PHPStanRules\Rules\ForbiddenFuncCallRule - tags: [phpstan.rules.rule] - arguments: - forbiddenFunctions: - - 'd' - - 'dd' - - 'dump' - - 'var_dump' - - 'extract' - - 'curl_*' - - 'compact' - - 'method_exists' - - 'property_exists' - - 'spl_autoload_register' - - 'spl_autoload_unregister' - - array_walk - preg_match: "Use Nette\\Utils\\Strings::match() instead" - preg_match_all: "Use Nette\\Utils\\Strings::matchAll() instead" - preg_replace: "Use Nette\\Utils\\Strings::replace() instead" - preg_replace_callback: "Use Nette\\Utils\\Strings::replace() instead" - preg_split: "Use Nette\\Utils\\Strings::split() instead" - file_get_contents: "Use Symplify\\SmartFileSystem\\SmartFileSystem::readFile() instead" - file_put_contents: "Use Symplify\\SmartFileSystem\\SmartFileSystem::dumpFile() instead" - json_encode: "Use Nette\\Utils\\Json::encode() instead" - json_decode: "Use Nette\\Utils\\Json::decode() instead" - - - - class: Symplify\PHPStanRules\Rules\SeeAnnotationToTestRule - tags: [phpstan.rules.rule] - arguments: - requiredSeeTypes: - - PHPStan\Rules\Rule - - PHP_CodeSniffer\Sniffs\Sniff - - PHP_CodeSniffer\Fixer - - - - class: Symplify\PHPStanRules\Rules\Enum\RequireNewArgumentConstantRule - tags: [phpstan.rules.rule] - arguments: - constantArgByNewByType: - Symfony\Component\Console\Input\InputOption: [0, 2] diff --git a/config/doctrine-rules.neon b/config/doctrine-rules.neon deleted file mode 100644 index f9d27a60..00000000 --- a/config/doctrine-rules.neon +++ /dev/null @@ -1,13 +0,0 @@ -services: - - - class: Symplify\PHPStanRules\Rules\ExclusiveDependencyRule - tags: [phpstan.rules.rule] - arguments: - allowedExclusiveDependencyInTypes: - # "EntityManager" dependency can be used only in "*Repository" class - 'Doctrine\ORM\EntityManager': - - '*Repository' - - 'Doctrine\Bundle\DoctrineBundle\EventSubscriber\EventSubscriberInterface' - 'Doctrine\ORM\EntityManagerInterface': - - '*Repository' - - 'Doctrine\Bundle\DoctrineBundle\EventSubscriber\EventSubscriberInterface' diff --git a/config/forbidden-static-rules.neon b/config/forbidden-static-rules.neon deleted file mode 100644 index 0f19b90c..00000000 --- a/config/forbidden-static-rules.neon +++ /dev/null @@ -1,4 +0,0 @@ -rules: - - Symplify\PHPStanRules\Rules\NoStaticPropertyRule - - Symplify\PHPStanRules\Rules\NoClassWithStaticMethodWithoutStaticNameRule - diff --git a/config/naming-rules.neon b/config/naming-rules.neon deleted file mode 100644 index 9318158f..00000000 --- a/config/naming-rules.neon +++ /dev/null @@ -1,11 +0,0 @@ -rules: - - Symplify\PHPStanRules\Rules\NoReturnSetterMethodRule - - Symplify\PHPStanRules\Rules\RequiredAbstractClassKeywordRule - - Symplify\PHPStanRules\Rules\NoVoidGetterMethodRule - - Symplify\PHPStanRules\Rules\SuffixInterfaceRule - - Symplify\PHPStanRules\Rules\SuffixTraitRule - - Symplify\PHPStanRules\Rules\PrefixAbstractClassRule - - Symplify\PHPStanRules\Rules\UppercaseConstantRule - - Symplify\PHPStanRules\Rules\ClassNameRespectsParentSuffixRule - - Symplify\PHPStanRules\Rules\CheckTypehintCallerTypeRule - - Symplify\PHPStanRules\Rules\CheckClassNamespaceFollowPsr4Rule diff --git a/config/packages/cognitive-complexity/cognitive-complexity-rules.neon b/config/packages/cognitive-complexity/cognitive-complexity-rules.neon deleted file mode 100644 index 3459da9d..00000000 --- a/config/packages/cognitive-complexity/cognitive-complexity-rules.neon +++ /dev/null @@ -1,12 +0,0 @@ -services: - - - class: Symplify\PHPStanRules\CognitiveComplexity\Rules\FunctionLikeCognitiveComplexityRule - tags: [phpstan.rules.rule] - arguments: - maxMethodCognitiveComplexity: 8 - - - - class: Symplify\PHPStanRules\CognitiveComplexity\Rules\ClassLikeCognitiveComplexityRule - tags: [phpstan.rules.rule] - arguments: - maxClassCognitiveComplexity: 50 diff --git a/config/packages/cognitive-complexity/cognitive-complexity-services.neon b/config/packages/cognitive-complexity/cognitive-complexity-services.neon deleted file mode 100644 index c1d55686..00000000 --- a/config/packages/cognitive-complexity/cognitive-complexity-services.neon +++ /dev/null @@ -1,8 +0,0 @@ -services: - - Symplify\PHPStanRules\CognitiveComplexity\AstCognitiveComplexityAnalyzer - - Symplify\PHPStanRules\CognitiveComplexity\CompositionOverInheritanceAnalyzer - - Symplify\PHPStanRules\CognitiveComplexity\DataCollector\CognitiveComplexityDataCollector - - Symplify\PHPStanRules\CognitiveComplexity\NodeVisitor\NestingNodeVisitor - - Symplify\PHPStanRules\CognitiveComplexity\NodeVisitor\ComplexityNodeVisitor - - Symplify\PHPStanRules\CognitiveComplexity\NodeAnalyzer\ComplexityAffectingNodeFinder - - Symplify\PHPStanRules\CognitiveComplexity\NodeTraverser\ComplexityNodeTraverserFactory diff --git a/config/packages/object-calisthenics-rules/object-calisthenics-rules.neon b/config/packages/object-calisthenics-rules/object-calisthenics-rules.neon deleted file mode 100644 index e445bfb0..00000000 --- a/config/packages/object-calisthenics-rules/object-calisthenics-rules.neon +++ /dev/null @@ -1,10 +0,0 @@ -services: - - - class: Symplify\PHPStanRules\ObjectCalisthenics\Rules\NoShortNameRule - tags: [phpstan.rules.rule] - arguments: - minNameLength: 3 - allowedShortNames: ['id', 'to', 'up'] - -rules: - - Symplify\PHPStanRules\ObjectCalisthenics\Rules\NoChainMethodCallRule diff --git a/config/packages/symfony/services.neon b/config/packages/symfony/services.neon deleted file mode 100644 index fc409d6a..00000000 --- a/config/packages/symfony/services.neon +++ /dev/null @@ -1,3 +0,0 @@ -services: - - Symplify\PHPStanRules\Symfony\NodeAnalyzer\SymfonyPhpConfigClosureAnalyzer - - Symplify\PHPStanRules\Symfony\NodeAnalyzer\SymfonyControllerAnalyzer diff --git a/config/packages/symfony/symfony-rules.neon b/config/packages/symfony/symfony-rules.neon deleted file mode 100644 index 8c1b36f4..00000000 --- a/config/packages/symfony/symfony-rules.neon +++ /dev/null @@ -1,75 +0,0 @@ -rules: - - Symplify\PHPStanRules\Symfony\Rules\RequireNamedCommandRule - - Symplify\PHPStanRules\Symfony\Rules\RequireNativeArraySymfonyRenderCallRule - - Symplify\PHPStanRules\Symfony\Rules\RequireInvokableControllerRule - - Symplify\PHPStanRules\Symfony\Rules\TwigPublicCallableExistsRule - -services: - - - class: Symplify\PHPStanRules\Rules\PreferredAttributeOverAnnotationRule - tags: [phpstan.rules.rule] - arguments: - annotations: - - Symfony\Component\Routing\Annotation\Route - # symfony\validation - @see https://github.com/symfony/symfony/pull/38309/files - - Symfony\Component\Validator\Constraints\Bic - - Symfony\Component\Validator\Constraints\Blank - - Symfony\Component\Validator\Constraints\Callback - - Symfony\Component\Validator\Constraints\CardScheme - - Symfony\Component\Validator\Constraints\Cascade - - Symfony\Component\Validator\Constraints\Choice - - Symfony\Component\Validator\Constraints\Count - - Symfony\Component\Validator\Constraints\Country - - Symfony\Component\Validator\Constraints\Currency - - Symfony\Component\Validator\Constraints\Date - - Symfony\Component\Validator\Constraints\DateTime - - Symfony\Component\Validator\Constraints\DisableAutoMapping - - Symfony\Component\Validator\Constraints\DivisibleBy - - Symfony\Component\Validator\Constraints\Email - - Symfony\Component\Validator\Constraints\EnableAutoMapping - - Symfony\Component\Validator\Constraints\EqualTo - - Symfony\Component\Validator\Constraints\Expression - - Symfony\Component\Validator\Constraints\ExpressionLanguageSyntax - - Symfony\Component\Validator\Constraints\File - - Symfony\Component\Validator\Constraints\GreaterThan - - Symfony\Component\Validator\Constraints\GreaterThanOrEqual - - Symfony\Component\Validator\Constraints\GroupSequence - - Symfony\Component\Validator\Constraints\GroupSequenceProvider - - Symfony\Component\Validator\Constraints\Hostname - - Symfony\Component\Validator\Constraints\Iban - - Symfony\Component\Validator\Constraints\IdenticalTo - - Symfony\Component\Validator\Constraints\Image - - Symfony\Component\Validator\Constraints\Ip - - Symfony\Component\Validator\Constraints\Isbn - - Symfony\Component\Validator\Constraints\IsFalse - - Symfony\Component\Validator\Constraints\Isin - - Symfony\Component\Validator\Constraints\IsNull - - Symfony\Component\Validator\Constraints\Issn - - Symfony\Component\Validator\Constraints\IsTrue - - Symfony\Component\Validator\Constraints\Json - - Symfony\Component\Validator\Constraints\Language - - Symfony\Component\Validator\Constraints\Length - - Symfony\Component\Validator\Constraints\LessThan - - Symfony\Component\Validator\Constraints\LessThanOrEqual - - Symfony\Component\Validator\Constraints\Locale - - Symfony\Component\Validator\Constraints\Luhn - - Symfony\Component\Validator\Constraints\Negative - - Symfony\Component\Validator\Constraints\NegativeOrZero - - Symfony\Component\Validator\Constraints\NotBlank - - Symfony\Component\Validator\Constraints\NotCompromisedPassword - - Symfony\Component\Validator\Constraints\NotEqualTo - - Symfony\Component\Validator\Constraints\NotIdenticalTo - - Symfony\Component\Validator\Constraints\NotNull - - Symfony\Component\Validator\Constraints\Positive - - Symfony\Component\Validator\Constraints\PositiveOrZero - - Symfony\Component\Validator\Constraints\Range - - Symfony\Component\Validator\Constraints\Regex - - Symfony\Component\Validator\Constraints\Time - - Symfony\Component\Validator\Constraints\Timezone - - Symfony\Component\Validator\Constraints\Traverse - - Symfony\Component\Validator\Constraints\Type - - Symfony\Component\Validator\Constraints\Ulid - - Symfony\Component\Validator\Constraints\Unique - - Symfony\Component\Validator\Constraints\Url - - Symfony\Component\Validator\Constraints\Uuid - - Symfony\Component\Validator\Constraints\Valid diff --git a/config/regex-rules.neon b/config/regex-rules.neon deleted file mode 100644 index ec0420d3..00000000 --- a/config/regex-rules.neon +++ /dev/null @@ -1,4 +0,0 @@ -rules: - - Symplify\PHPStanRules\Rules\AnnotateRegexClassConstWithRegexLinkRule - - Symplify\PHPStanRules\Rules\NoInlineStringRegexRule - - Symplify\PHPStanRules\Rules\RegexSuffixInRegexConstantRule diff --git a/config/rules.neon b/config/rules.neon new file mode 100644 index 00000000..225c448d --- /dev/null +++ b/config/rules.neon @@ -0,0 +1,31 @@ +# these rule focus on the whole-project analysis, see https://phpstan.org/developing-extensions/collectors +rules: + # narrow types - toggleables + - Rector\TypePerfect\Rules\NoReturnFalseInNonBoolClassMethodRule + - Rector\TypePerfect\Rules\NarrowPublicClassMethodParamTypeRule + - Rector\TypePerfect\Rules\NarrowPrivateClassMethodParamTypeRule + + # no mixed - toggleables + - Rector\TypePerfect\Rules\NoMixedPropertyFetcherRule + - Rector\TypePerfect\Rules\NoMixedMethodCallerRule + + # simple - always enable these + - Rector\TypePerfect\Rules\ForbiddenParamTypeRemovalRule + - Rector\TypePerfect\Rules\NoArrayAccessOnObjectRule + - Rector\TypePerfect\Rules\NoIssetOnObjectRule + + +services: + # for NarrowPublicClassMethodParamTypeByCallerTypeRule + - + class: Rector\TypePerfect\Collector\ClassMethod\PublicClassMethodParamTypesCollector + tags: [phpstan.collector] + + - + class: Rector\TypePerfect\Collector\MethodCall\MethodCallArgTypesCollector + tags: [phpstan.collector] + + - + class: Rector\TypePerfect\Collector\MethodCallableNode\MethodCallableCollector + tags: + - phpstan.collector diff --git a/config/services.neon b/config/services.neon new file mode 100644 index 00000000..90029634 --- /dev/null +++ b/config/services.neon @@ -0,0 +1,12 @@ +services: + - Rector\TypePerfect\NodeTraverser\SimpleCallableNodeTraverser + - Rector\TypePerfect\NodeFinder\ClassMethodNodeFinder + - Rector\TypePerfect\NodeFinder\MethodCallNodeFinder + - Rector\TypePerfect\NodeFinder\ReturnNodeFinder + - Rector\TypePerfect\PhpDoc\ApiDocStmtAnalyzer + - Rector\TypePerfect\Printer\NodeComparator + - Rector\TypePerfect\Reflection\ReflectionParser + - Rector\TypePerfect\Reflection\MethodNodeAnalyser + - Rector\TypePerfect\Matcher\Collector\PublicClassMethodMatcher + - Rector\TypePerfect\Matcher\ClassMethodCallReferenceResolver + - Rector\TypePerfect\Printer\CollectorMetadataPrinter diff --git a/config/services/services.neon b/config/services/services.neon deleted file mode 100644 index bcf82de8..00000000 --- a/config/services/services.neon +++ /dev/null @@ -1,88 +0,0 @@ -parameters: - featureToggles: - # disable node connecting visitor, see https://github.com/phpstan/phpstan-src/pull/1175 - nodeConnectingVisitorCompatibility: false - -services: - - PhpParser\NodeFinder - - - Symplify\PHPStanRules\Symfony\PropertyMetadataResolver - - Symplify\PHPStanRules\Symfony\Finder\ArrayKeyFinder - - Symplify\PHPStanRules\NodeTraverser\SimpleCallableNodeTraverser - - Symplify\PHPStanRules\PhpDocParser\PhpDocNodeTraverser - - Symplify\PHPStanRules\PhpDocParser\SimplePhpDocParser - - Symplify\PHPStanRules\Reflection\ReflectionParser - - Symplify\PHPStanRules\Matcher\ArrayStringAndFnMatcher - - Symplify\PHPStanRules\TypeResolver\ClassMethodReturnTypeResolver - - Symplify\PHPStanRules\NodeFinder\TypeAwareNodeFinder - - Symplify\PHPStanRules\PhpDoc\SeePhpDocTagNodesFinder - - Symplify\PHPStanRules\TypeAnalyzer\ContainsTypeAnalyser - - Symplify\PHPStanRules\Composer\ClassNamespaceMatcher - - Symplify\PHPStanRules\Composer\ComposerAutoloadResolver - - Symplify\PHPStanRules\Composer\ComposerVendorAutoloadResolver - - Symplify\PHPStanRules\Composer\Psr4PathValidator - - Symplify\PHPStanRules\Enum\EnumConstantAnalyzer - - Symplify\PHPStanRules\NodeFinder\ClassLikeNameFinder - - Symplify\PHPStanRules\Formatter\RequiredWithMessageFormatter - - Symplify\PHPStanRules\Location\DirectoryChecker - - Symplify\PHPStanRules\Matcher\ClassLikeNameMatcher - - Symplify\PHPStanRules\Matcher\ObjectTypeMatcher - - Symplify\PHPStanRules\Matcher\PositionMatcher - - Symplify\PHPStanRules\Matcher\SharedNamePrefixMatcher - - Symplify\PHPStanRules\Naming\BoolishNameAnalyser - - Symplify\PHPStanRules\Naming\ClassToSuffixResolver - - Symplify\PHPStanRules\NodeAnalyzer\ArrayAnalyzer - - Symplify\PHPStanRules\NodeAnalyzer\AttributeFinder - - Symplify\PHPStanRules\NodeAnalyzer\AutowiredMethodPropertyAnalyzer - - Symplify\PHPStanRules\NodeAnalyzer\CacheIfAnalyzer - - Symplify\PHPStanRules\NodeAnalyzer\ClassAnalyzer - - Symplify\PHPStanRules\NodeAnalyzer\DependencyNodeAnalyzer - - Symplify\PHPStanRules\NodeAnalyzer\EnumAnalyzer - - Symplify\PHPStanRules\NodeAnalyzer\IfElseBranchAnalyzer - - Symplify\PHPStanRules\NodeAnalyzer\IfResemblingMatchAnalyzer - - Symplify\PHPStanRules\NodeAnalyzer\MethodCall\MethodCallClassConstFetchPositionResolver - - Symplify\PHPStanRules\NodeAnalyzer\ProtectedAnalyzer - - Symplify\PHPStanRules\NodeAnalyzer\RegexFuncCallAnalyzer - - Symplify\PHPStanRules\NodeAnalyzer\RegexStaticCallAnalyzer - - Symplify\PHPStanRules\NodeAnalyzer\ScalarValueResolver - - Symplify\PHPStanRules\NodeAnalyzer\SprintfSpecifierTypeResolver - - Symplify\PHPStanRules\NodeAnalyzer\TypeNodeAnalyzer - - Symplify\PHPStanRules\NodeFinder\ClassMethodNodeFinder - - Symplify\PHPStanRules\NodeFinder\MethodCallNodeFinder - - Symplify\PHPStanRules\NodeFinder\ReturnNodeFinder - - Symplify\PHPStanRules\ParentClassMethodNodeResolver - - Symplify\PHPStanRules\ParentGuard\ParentClassMethodGuard - - Symplify\PHPStanRules\ParentGuard\ParentElementResolver\ParentMethodResolver - - Symplify\PHPStanRules\ParentGuard\ParentElementResolver\ParentMethodReturnTypeResolver - - Symplify\PHPStanRules\ParentGuard\ParentPropertyGuard - - Symplify\PHPStanRules\PhpDoc\ApiDocStmtAnalyzer - - Symplify\PHPStanRules\PhpDoc\BarePhpDocParser - - Symplify\PHPStanRules\PhpDoc\ClassAnnotationResolver - - Symplify\PHPStanRules\PhpDoc\ClassReferencePhpDocNodeVisitor - - Symplify\PHPStanRules\PhpDoc\PhpDocNodeTraverser\ClassReferencePhpDocNodeTraverser - - Symplify\PHPStanRules\PhpDoc\PhpDocResolver - - Symplify\PHPStanRules\Printer\DuplicatedClassMethodPrinter - - Symplify\PHPStanRules\Printer\NodeComparator - - Symplify\PHPStanRules\Reflection\MethodCallNodeAnalyzer - - Symplify\PHPStanRules\Reflection\MethodNodeAnalyser - - Symplify\PHPStanRules\Reflection\PublicClassReflectionAnalyzer - - Symplify\PHPStanRules\Reflection\StaticCallNodeAnalyzer - - Symplify\PHPStanRules\TypeAnalyzer\ArrayShapeDetector - - Symplify\PHPStanRules\TypeAnalyzer\CallableTypeAnalyzer - - Symplify\PHPStanRules\TypeAnalyzer\MatchingTypeAnalyzer - - Symplify\PHPStanRules\TypeResolver\ArgTypeResolver - - Symplify\PHPStanRules\Matcher\Collector\PublicClassMethodMatcher - - Symplify\PHPStanRules\Matcher\ClassMethodCallReferenceResolver - - Symplify\PHPStanRules\Printer\CollectorMetadataPrinter - - Symplify\PHPStanRules\NodeAnalyzer\MethodCall\AllowedChainCallSkipper - - Symplify\PHPStanRules\Formatter\SeaLevelRuleErrorFormatter - - - - - class: Symplify\PHPStanRules\NodeVisitor\AssignedToPropertyNodeVisitor - tags: - - phpstan.parser.richParserNodeVisitor - - - class: Symplify\PHPStanRules\ObjectCalisthenics\NodeVisitor\NullsafeCheckedNodeVisitor - tags: - - phpstan.parser.richParserNodeVisitor diff --git a/config/static-rules.neon b/config/static-rules.neon deleted file mode 100644 index abeac98d..00000000 --- a/config/static-rules.neon +++ /dev/null @@ -1,55 +0,0 @@ -rules: - - Symplify\PHPStanRules\Rules\NoProtectedElementInFinalClassRule - - - Symplify\PHPStanRules\Rules\Spotter\IfElseToMatchSpotterRule - - Symplify\PHPStanRules\Rules\Missing\CheckSprintfMatchingTypesRule - - Symplify\PHPStanRules\Rules\Explicit\ValueObjectOverArrayShapeRule - - Symplify\PHPStanRules\Rules\ForbiddenExtendOfNonAbstractClassRule - - # domain - - Symplify\PHPStanRules\Rules\Domain\RequireExceptionNamespaceRule - - Symplify\PHPStanRules\Rules\Domain\RequireAttributeNamespaceRule - - Symplify\PHPStanRules\Rules\CheckAttributteArgumentClassExistsRule - - Symplify\PHPStanRules\Rules\Enum\RequireUniqueEnumConstantRule - - Symplify\PHPStanRules\Rules\ForbiddenParamTypeRemovalRule - - Symplify\PHPStanRules\Rules\NoNestedFuncCallRule - - Symplify\PHPStanRules\Rules\RequireStringRegexMatchKeyRule - - Symplify\PHPStanRules\Rules\PreventParentMethodVisibilityOverrideRule - - # paths - - Symplify\PHPStanRules\Rules\NoMissingDirPathRule - - Symplify\PHPStanRules\Rules\NoAbstractMethodRule - - Symplify\PHPStanRules\Rules\NoReferenceRule - - Symplify\PHPStanRules\Rules\NoArrayAccessOnObjectRule - - - Symplify\PHPStanRules\Rules\NoNullableArrayPropertyRule - - Symplify\PHPStanRules\Rules\BoolishClassMethodPrefixRule - - # dead-code - - Symplify\PHPStanRules\Rules\NoIssetOnObjectRule - - # explicit naming - - Symplify\PHPStanRules\Rules\NoDefaultExceptionRule - - Symplify\PHPStanRules\Rules\NoDynamicPropertyOnStaticCallRule - - Symplify\PHPStanRules\Rules\NoParentMethodCallOnNoOverrideProcessRule - - Symplify\PHPStanRules\Rules\PreferredRawDataInTestDataProviderRule - - Symplify\PHPStanRules\Rules\RequireThisOnParentMethodCallRule - - Symplify\PHPStanRules\Rules\RequireThisCallOnLocalMethodRule - - Symplify\PHPStanRules\Rules\ForbiddenMultipleClassLikeInOneFileRule - - Symplify\PHPStanRules\Rules\ForbiddenProtectedPropertyRule - - Symplify\PHPStanRules\Rules\NoMethodTagInClassDocblockRule - - # comlexity - - Symplify\PHPStanRules\Rules\Complexity\ForbiddenSameNamedNewInstanceRule - - - Symplify\PHPStanRules\Rules\Complexity\ForbiddenArrayMethodCallRule - - Symplify\PHPStanRules\Rules\Complexity\ForbiddenComplexForeachIfExprRule - - Symplify\PHPStanRules\Rules\ForbiddenThisArgumentRule - - Symplify\PHPStanRules\Rules\ForbiddenSpreadOperatorRule - - Symplify\PHPStanRules\Rules\ForbiddenAnonymousClassRule - - Symplify\PHPStanRules\Rules\CheckRequiredInterfaceInContractNamespaceRule - - Symplify\PHPStanRules\Symfony\Rules\PreventDoubleSetParameterRule - - Symplify\PHPStanRules\Rules\NoEmptyClassRule - - # naming - - Symplify\PHPStanRules\Rules\RequireAttributeNameRule diff --git a/config/symplify-rules.neon b/config/symplify-rules.neon deleted file mode 100644 index 14511f7a..00000000 --- a/config/symplify-rules.neon +++ /dev/null @@ -1,32 +0,0 @@ -includes: - # 1. basic static sets - - static-rules.neon - - # 2. prepared sets - - array-rules.neon - - code-complexity-rules.neon - - forbidden-static-rules.neon - - regex-rules.neon - - packages/symfony/symfony-rules.neon - - test-rules.neon - - naming-rules.neon - - collector-rules.neon - - # 3. custom symplify configuratoin - - configurable-rules.neon - -services: - - - class: Symplify\PHPStanRules\Rules\Enum\RequireConstantInMethodCallPositionRule - tags: [phpstan.rules.rule] - arguments: - requiredConstantInMethodCall: - Symfony\Component\Console\Command\Command: - addArgument: [0] - addOption: [0] - Symfony\Component\Console\Input\InputInterface: - getOption: [0] - getArgument: [0] - PhpParser\Node: - getAttribute: [0] - setAttribute: [0] diff --git a/config/test-rules.neon b/config/test-rules.neon deleted file mode 100644 index e0bddfaa..00000000 --- a/config/test-rules.neon +++ /dev/null @@ -1,4 +0,0 @@ -rules: - - Symplify\PHPStanRules\Rules\NoConstructorInTestRule - - Symplify\PHPStanRules\Rules\CheckNotTestsNamespaceOutsideTestsDirectoryRule - - Symplify\PHPStanRules\Rules\ForbiddenTestsNamespaceOutsideTestsDirectoryRule diff --git a/config/type-coverage-rules.neon b/config/type-coverage-rules.neon deleted file mode 100644 index de975571..00000000 --- a/config/type-coverage-rules.neon +++ /dev/null @@ -1,37 +0,0 @@ -services: - - - class: Symplify\PHPStanRules\Rules\Explicit\PropertyTypeDeclarationSeaLevelRule - tags: [phpstan.rules.rule] - arguments: - # very strict :) - minimalLevel: 0.99 - printSuggestions: true - - - - class: Symplify\PHPStanRules\Rules\Explicit\ParamTypeDeclarationSeaLevelRule - tags: [phpstan.rules.rule] - arguments: - # very strict :) - minimalLevel: 0.99 - printSuggestions: true - - - - class: Symplify\PHPStanRules\Rules\Explicit\ReturnTypeDeclarationSeaLevelRule - tags: [phpstan.rules.rule] - arguments: - # very strict :) - minimalLevel: 0.99 - printSuggestions: true - - # for "type declaration sea level" - - - class: Symplify\PHPStanRules\Collector\FunctionLike\ParamTypeSeaLevelCollector - tags: [phpstan.collector] - - - - class: Symplify\PHPStanRules\Collector\FunctionLike\ReturnTypeSeaLevelCollector - tags: [phpstan.collector] - - - - class: Symplify\PHPStanRules\Collector\ClassLike\PropertyTypeSeaLevelCollector - tags: [phpstan.collector] diff --git a/docs/rules_overview.md b/docs/rules_overview.md deleted file mode 100644 index 683d5580..00000000 --- a/docs/rules_overview.md +++ /dev/null @@ -1,4609 +0,0 @@ -# 120 Rules Overview - -## 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: - -
- -## BoolishClassMethodPrefixRule - -Method `"%s()"` returns bool type, so the name should start with is/has/was... - -- class: [`Symplify\PHPStanRules\Rules\BoolishClassMethodPrefixRule`](../src/Rules/BoolishClassMethodPrefixRule.php) - -```php -class SomeClass -{ - public function old(): bool - { - return $this->age > 100; - } -} -``` - -:x: - -
- -```php -class SomeClass -{ - public function isOld(): bool - { - return $this->age > 100; - } -} -``` - -:+1: - -
- -## CheckAttributteArgumentClassExistsRule - -Class was not found - -- class: [`Symplify\PHPStanRules\Rules\CheckAttributteArgumentClassExistsRule`](../src/Rules/CheckAttributteArgumentClassExistsRule.php) - -```php -#[SomeAttribute(firstName: 'MissingClass::class')] -class SomeClass -{ -} -``` - -:x: - -
- -```php -#[SomeAttribute(firstName: ExistingClass::class)] -class SomeClass -{ -} -``` - -:+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: - -
- -## CheckNotTestsNamespaceOutsideTestsDirectoryRule - -"*Test.php" file cannot be located outside "Tests" namespace - -- class: [`Symplify\PHPStanRules\Rules\CheckNotTestsNamespaceOutsideTestsDirectoryRule`](../src/Rules/CheckNotTestsNamespaceOutsideTestsDirectoryRule.php) - -```php -// file: "SomeTest.php -namespace App; - -class SomeTest -{ -} -``` - -:x: - -
- -```php -// file: "SomeTest.php -namespace App\Tests; - -class SomeTest -{ -} -``` - -:+1: - -
- -## CheckRequiredInterfaceInContractNamespaceRule - -Interface must be located in "Contract" 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: - -
- -## CheckSprintfMatchingTypesRule - -`sprintf()` call mask types does not match provided arguments types - -- class: [`Symplify\PHPStanRules\Rules\Missing\CheckSprintfMatchingTypesRule`](../src/Rules/Missing/CheckSprintfMatchingTypesRule.php) - -```php -echo sprintf('My name is %s and I have %d children', 10, 'Tomas'); -``` - -:x: - -
- -```php -echo sprintf('My name is %s and I have %d children', 'Tomas', 10); -``` - -:+1: - -
- -## CheckTypehintCallerTypeRule - -Parameter %d should use "%s" type as the only type passed to this method - -- class: [`Symplify\PHPStanRules\Rules\CheckTypehintCallerTypeRule`](../src/Rules/CheckTypehintCallerTypeRule.php) - -```php -use PhpParser\Node; -use PhpParser\Node\Expr\MethodCall; - -class SomeClass -{ - public function run(MethodCall $node) - { - $this->isCheck($node); - } - - private function isCheck(Node $node) - { - } -} -``` - -:x: - -
- -```php -use PhpParser\Node\Expr\MethodCall; - -class SomeClass -{ - public function run(MethodCall $node) - { - $this->isCheck($node); - } - - private function isCheck(MethodCall $node) - { - } -} -``` - -:+1: - -
- -## ClassExtendingExclusiveNamespaceRule - -Define in which namespaces (using *, ** or ? glob-like pattern matching) can classes extending specified class or implementing specified interface exist - -:wrench: **configure it!** - -- class: [`Symplify\PHPStanRules\Rules\ClassExtendingExclusiveNamespaceRule`](../src/Rules/ClassExtendingExclusiveNamespaceRule.php) - -```yaml -services: - - - class: Symplify\PHPStanRules\Rules\ClassExtendingExclusiveNamespaceRule - tags: [phpstan.rules.rule] - arguments: - guards: - Symfony\Component\Form\FormTypeInterface: - - 'App\Form\**' -``` - -↓ - -```php -namespace App; - -// AbstractType implements \Symfony\Component\Form\FormTypeInterface -use Symfony\Component\Form\AbstractType; - -class UserForm extends AbstractType -{ -} -``` - -:x: - -
- -```php -namespace App\Form; - -use Symfony\Component\Form\AbstractType; - -class UserForm extends AbstractType -{ -} -``` - -:+1: - -
- -```yaml -services: - - - class: Symplify\PHPStanRules\Rules\ClassExtendingExclusiveNamespaceRule - tags: [phpstan.rules.rule] - arguments: - guards: - 'App\Component\PriceEngine\**': - - 'App\Component\PriceEngine\**' - - 'App\Component\PriceEngineImpl\**' -``` - -↓ - -```php -namespace App\Services; - -use App\Component\PriceEngine\PriceProviderInterface; - -class CustomerProductProvider extends PriceProviderInterface -{ -} -``` - -:x: - -
- -```php -namespace App\Component\PriceEngineImpl; - -use App\Component\PriceEngine\PriceProviderInterface; - -class CustomerProductProvider extends PriceProviderInterface -{ -} -``` - -:+1: - -
- -## ClassLikeCognitiveComplexityRule - -Cognitive complexity of class/trait must be under specific limit - -:wrench: **configure it!** - -- class: [`Symplify\PHPStanRules\CognitiveComplexity\Rules\ClassLikeCognitiveComplexityRule`](../packages/CognitiveComplexity/Rules/ClassLikeCognitiveComplexityRule.php) - -```yaml -services: - - - class: Symplify\PHPStanRules\CognitiveComplexity\Rules\ClassLikeCognitiveComplexityRule - tags: [phpstan.rules.rule] - arguments: - maxClassCognitiveComplexity: 10 - scoreCompositionOverInheritance: true -``` - -↓ - -```php -class SomeClass -{ - public function simple($value) - { - if ($value !== 1) { - if ($value !== 2) { - return false; - } - } - - return true; - } - - public function another($value) - { - if ($value !== 1 && $value !== 2) { - return false; - } - - return true; - } -} -``` - -:x: - -
- -```php -class SomeClass -{ - public function simple($value) - { - return $this->someOtherService->count($value); - } - - public function another($value) - { - return $this->someOtherService->delete($value); - } -} -``` - -:+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: - -
- -## EmbeddedEnumClassConstSpotterRule - -Constants "%s" should be extract to standalone enum class - -:wrench: **configure it!** - -- class: [`Symplify\PHPStanRules\Rules\Enum\EmbeddedEnumClassConstSpotterRule`](../src/Rules/Enum/EmbeddedEnumClassConstSpotterRule.php) - -```yaml -services: - - - class: Symplify\PHPStanRules\Rules\Enum\EmbeddedEnumClassConstSpotterRule - tags: [phpstan.rules.rule] - arguments: - parentTypes: - - AbstractObject -``` - -↓ - -```php -class SomeProduct extends AbstractObject -{ - public const STATUS_ENABLED = 1; - - public const STATUS_DISABLED = 0; -} -``` - -:x: - -
- -```php -class SomeProduct extends AbstractObject -{ -} - -class SomeStatus -{ - public const ENABLED = 1; - - public const DISABLED = 0; -} -``` - -:+1: - -
- -## ExclusiveDependencyRule - -Dependency of specific type can be used only in specific class types - -:wrench: **configure it!** - -- class: [`Symplify\PHPStanRules\Rules\ExclusiveDependencyRule`](../src/Rules/ExclusiveDependencyRule.php) - -```yaml -services: - - - class: Symplify\PHPStanRules\Rules\ExclusiveDependencyRule - tags: [phpstan.rules.rule] - arguments: - allowedExclusiveDependencyInTypes: - Doctrine\ORM\EntityManager: - - '*Repository' - Doctrine\ORM\EntityManagerInterface: - - '*Repository' -``` - -↓ - -```php -final class CheckboxController -{ - public function __construct( - private EntityManagerInterface $entityManager - ) { - } -} -``` - -:x: - -
- -```php -final class CheckboxRepository -{ - public function __construct( - private EntityManagerInterface $entityManager - ) { - } -} -``` - -:+1: - -
- -## ExclusiveNamespaceRule - -Exclusive namespace can only contain classes of specific type, nothing else - -:wrench: **configure it!** - -- class: [`Symplify\PHPStanRules\Rules\ExclusiveNamespaceRule`](../src/Rules/ExclusiveNamespaceRule.php) - -```yaml -services: - - - class: Symplify\PHPStanRules\Rules\ExclusiveNamespaceRule - tags: [phpstan.rules.rule] - arguments: - namespaceParts: - - Presenter -``` - -↓ - -```php -namespace App\Presenter; - -class SomeRepository -{ -} -``` - -:x: - -
- -```php -namespace App\Presenter; - -class SomePresenter -{ -} -``` - -:+1: - -
- -## ExplicitMethodCallOverMagicGetSetRule - -Instead of magic property "%s" access use direct explicit `"%s->%s()"` method call - -- class: [`Symplify\PHPStanRules\Rules\Explicit\ExplicitMethodCallOverMagicGetSetRule`](../src/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule.php) - -```php -use Nette\SmartObject; - -final class MagicObject -{ - // adds magic __get() and __set() methods - use SmartObject; - - private $name; - - public function getName() - { - return $this->name; - } -} - -$magicObject = new MagicObject(); -// magic re-directed to method -$magicObject->name; -``` - -:x: - -
- -```php -use Nette\SmartObject; - -final class MagicObject -{ - // adds magic __get() and __set() methods - use SmartObject; - - private $name; - - public function getName() - { - return $this->name; - } -} - -$magicObject = new MagicObject(); -// explicit -$magicObject->getName(); -``` - -:+1: - -
- -## ForbiddenAlwaysSetterCallRule - -The "%s" class always calls `"%s()"` setters, better move it to constructor - -- class: [`Symplify\PHPStanRules\Rules\Domain\ForbiddenAlwaysSetterCallRule`](../src/Rules/Domain/ForbiddenAlwaysSetterCallRule.php) - -```php -$firstPerson = new Person(); -$firstPerson->setName('John'); - -$secondPerson = new Person(); -$secondPerson->setName('Van'); -``` - -:x: - -
- -```php -$firstPerson = new Person('John'); - -$secondPerson = new Person('Van'); -``` - -:+1: - -
- -## ForbiddenAnonymousClassRule - -Anonymous class is not allowed. - -- class: [`Symplify\PHPStanRules\Rules\ForbiddenAnonymousClassRule`](../src/Rules/ForbiddenAnonymousClassRule.php) - -```php -new class {}; -``` - -:x: - -
- -```php -class SomeClass -{ - -} - -new SomeClass; -``` - -:+1: - -
- -## ForbiddenArrayDestructRule - -Array destruct is not allowed. Use value object to pass data instead - -- class: [`Symplify\PHPStanRules\Rules\ForbiddenArrayDestructRule`](../src/Rules/ForbiddenArrayDestructRule.php) - -```php -final class SomeClass -{ - public function run(): void - { - [$firstValue, $secondValue] = $this->getRandomData(); - } -} -``` - -:x: - -
- -```php -final class SomeClass -{ - public function run(): void - { - $valueObject = $this->getValueObject(); - $firstValue = $valueObject->getFirstValue(); - $secondValue = $valueObject->getSecondValue(); - } -} -``` - -:+1: - -
- -## 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: - -
- -## ForbiddenArrayWithStringKeysRule - -Array with keys is not allowed. Use value object to pass data instead - -- class: [`Symplify\PHPStanRules\Rules\ForbiddenArrayWithStringKeysRule`](../src/Rules/ForbiddenArrayWithStringKeysRule.php) - -```php -final class SomeClass -{ - public function run() - { - return [ - 'name' => 'John', - 'surname' => 'Dope', - ]; - } -} -``` - -:x: - -
- -```php -final class SomeClass -{ - public function run() - { - return new Person('John', 'Dope'); - } -} -``` - -:+1: - -
- -## ForbiddenComplexForeachIfExprRule - -`foreach()`, `while()`, `for()` or `if()` cannot contain a complex expression. Extract it to a new variable on a line before - -- class: [`Symplify\PHPStanRules\Rules\Complexity\ForbiddenComplexForeachIfExprRule`](../src/Rules/Complexity/ForbiddenComplexForeachIfExprRule.php) - -```php -foreach ($this->getData($arg) as $key => $item) { - // ... -} -``` - -:x: - -
- -```php -$data = $this->getData($arg); -foreach ($data as $key => $item) { - // ... -} -``` - -:+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: - -
- -## ForbiddenInlineClassMethodRule - -Method `"%s()"` only calling another method call and has no added value. Use the inlined call instead - -- class: [`Symplify\PHPStanRules\Rules\Complexity\ForbiddenInlineClassMethodRule`](../src/Rules/Complexity/ForbiddenInlineClassMethodRule.php) - -```php -class SomeClass -{ - public function run() - { - return $this->away(); - } - - private function away() - { - return mt_rand(0, 100); - } -} -``` - -:x: - -
- -```php -class SomeClass -{ - public function run() - { - return mt_rand(0, 100); - } -} -``` - -:+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: - -
- -## ForbiddenNamedArgumentsRule - -Named arguments do not add any value here. Use normal arguments in the same order - -- class: [`Symplify\PHPStanRules\Rules\Complexity\ForbiddenNamedArgumentsRule`](../src/Rules/Complexity/ForbiddenNamedArgumentsRule.php) - -```php -return strlen(string: 'name'); -``` - -:x: - -
- -```php -return strlen('name'); -``` - -:+1: - -
- -## ForbiddenNestedCallInAssertMethodCallRule - -Decouple method call in assert to standalone line to make test core more readable - -- class: [`Symplify\PHPStanRules\Rules\ForbiddenNestedCallInAssertMethodCallRule`](../src/Rules/ForbiddenNestedCallInAssertMethodCallRule.php) - -```php -use PHPUnit\Framework\TestCase; - -final class SomeClass extends TestCase -{ - public function test() - { - $this->assertSame('oooo', $this->someMethodCall()); - } -} -``` - -:x: - -
- -```php -use PHPUnit\Framework\TestCase; - -final class SomeClass extends TestCase -{ - public function test() - { - $result = $this->someMethodCall(); - $this->assertSame('oooo', $result); - } -} -``` - -:+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: - -
- -## ForbiddenParamTypeRemovalRule - -Removing parent param type is forbidden - -- class: [`Symplify\PHPStanRules\Rules\ForbiddenParamTypeRemovalRule`](../src/Rules/ForbiddenParamTypeRemovalRule.php) - -```php -interface RectorInterface -{ - public function refactor(Node $node); -} - -final class SomeRector implements RectorInterface -{ - public function refactor($node) - { - } -} -``` - -:x: - -
- -```php -interface RectorInterface -{ - public function refactor(Node $node); -} - -final class SomeRector implements RectorInterface -{ - public function refactor(Node $node) - { - } -} -``` - -:+1: - -
- -## ForbiddenProtectedPropertyRule - -Property with protected modifier is not allowed. Use interface contract method instead - -- class: [`Symplify\PHPStanRules\Rules\ForbiddenProtectedPropertyRule`](../src/Rules/ForbiddenProtectedPropertyRule.php) - -```php -class SomeClass -{ - protected $repository; -} -``` - -:x: - -
- -```php -class SomeClass implements RepositoryAwareInterface -{ - public function getRepository() - { - // .... - } -} -``` - -:+1: - -
- -## ForbiddenSameNamedNewInstanceRule - -New objects with "%s" name are overridden. This can lead to unwanted bugs, please pick a different name to avoid it. - -- class: [`Symplify\PHPStanRules\Rules\Complexity\ForbiddenSameNamedNewInstanceRule`](../src/Rules/Complexity/ForbiddenSameNamedNewInstanceRule.php) - -```php -$product = new Product(); -$product = new Product(); - -$this->productRepository->save($product); -``` - -:x: - -
- -```php -$firstProduct = new Product(); -$secondProduct = new Product(); - -$this->productRepository->save($firstProduct); -``` - -:+1: - -
- -## ForbiddenSpreadOperatorRule - -Spread operator is not allowed. - -- class: [`Symplify\PHPStanRules\Rules\ForbiddenSpreadOperatorRule`](../src/Rules/ForbiddenSpreadOperatorRule.php) - -```php -$args = [$firstValue, $secondValue]; -$message = sprintf('%s', ...$args); -``` - -:x: - -
- -```php -$message = sprintf('%s', $firstValue, $secondValue); -``` - -:+1: - -
- -## ForbiddenTestsNamespaceOutsideTestsDirectoryRule - -"Tests" namespace can be only in "/tests" directory - -- class: [`Symplify\PHPStanRules\Rules\ForbiddenTestsNamespaceOutsideTestsDirectoryRule`](../src/Rules/ForbiddenTestsNamespaceOutsideTestsDirectoryRule.php) - -```php -// file path: "src/SomeClass.php" - -namespace App\Tests; - -class SomeClass -{ -} -``` - -:x: - -
- -```php -// file path: "tests/SomeClass.php" - -namespace App\Tests; - -class SomeClass -{ -} -``` - -:+1: - -
- -## ForbiddenThisArgumentRule - -`$this` as argument is not allowed. Refactor method to service composition - -- class: [`Symplify\PHPStanRules\Rules\ForbiddenThisArgumentRule`](../src/Rules/ForbiddenThisArgumentRule.php) - -```php -$this->someService->process($this, ...); -``` - -:x: - -
- -```php -$this->someService->process($value, ...); -``` - -:+1: - -
- -## FunctionLikeCognitiveComplexityRule - -Cognitive complexity of function/method must be under specific limit - -:wrench: **configure it!** - -- class: [`Symplify\PHPStanRules\CognitiveComplexity\Rules\FunctionLikeCognitiveComplexityRule`](../packages/CognitiveComplexity/Rules/FunctionLikeCognitiveComplexityRule.php) - -```yaml -services: - - - class: Symplify\PHPStanRules\CognitiveComplexity\Rules\FunctionLikeCognitiveComplexityRule - tags: [phpstan.rules.rule] - arguments: - maxMethodCognitiveComplexity: 5 -``` - -↓ - -```php -class SomeClass -{ - public function simple($value) - { - if ($value !== 1) { - if ($value !== 2) { - return false; - } - } - - return true; - } -} -``` - -:x: - -
- -```php -class SomeClass -{ - public function simple($value) - { - if ($value === 1) { - return true; - } - - return $value === 2; - } -} -``` - -:+1: - -
- -## IfElseToMatchSpotterRule - -If/else construction can be replace with more robust `match()` - -- class: [`Symplify\PHPStanRules\Rules\Spotter\IfElseToMatchSpotterRule`](../src/Rules/Spotter/IfElseToMatchSpotterRule.php) - -```php -class SomeClass -{ - public function spot($value) - { - if ($value === 100) { - $items = ['yes']; - } else { - $items = ['no']; - } - - return $items; - } -} -``` - -:x: - -
- -```php -class SomeClass -{ - public function spot($value) - { - return match($value) { - 100 => ['yes'], - default => ['no'], - }; - } -} -``` - -:+1: - -
- -## NarrowPublicClassMethodParamTypeByCallerTypeRule - -Parameters should use "%s" types as the only types passed to this method - -- class: [`Symplify\PHPStanRules\Rules\NarrowType\NarrowPublicClassMethodParamTypeByCallerTypeRule`](../src/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule.php) - -```php -use PhpParser\Node\Expr\MethodCall; - -final class SomeClass -{ - public function run(SomeService $someService, MethodCall $methodCall) - { - $someService->isCheck($node); - } -} - -final class SomeService -{ - public function isCheck($methodCall) - { - } -} -``` - -:x: - -
- -```php -use PhpParser\Node\Expr\MethodCall; - -final class SomeClass -{ - public function run(SomeService $someService, MethodCall $methodCall) - { - $someService->isCheck($node); - } -} - -final class SomeService -{ - public function isCheck(MethodCall $methodCall) - { - } -} -``` - -:+1: - -
- -## NoAbstractMethodRule - -Use explicit interface contract or a service over unclear abstract methods - -- class: [`Symplify\PHPStanRules\Rules\NoAbstractMethodRule`](../src/Rules/NoAbstractMethodRule.php) - -```php -abstract class SomeClass -{ - abstract public function run(); -} -``` - -:x: - -
- -```php -abstract class SomeClass implements RunnableInterface -{ -} - -interface RunnableInterface -{ - public function run(); -} -``` - -:+1: - -
- -## NoAbstractRule - -Instead of abstract class, use specific service with composition - -- class: [`Symplify\PHPStanRules\Rules\Complexity\NoAbstractRule`](../src/Rules/Complexity/NoAbstractRule.php) - -```php -final class NormalHelper extends AbstractHelper -{ -} - -abstract class AbstractHelper -{ -} -``` - -:x: - -
- -```php -final class NormalHelper -{ - public function __construct( - private SpecificHelper $specificHelper - ) { - } -} - -final class SpecificHelper -{ -} -``` - -:+1: - -
- -## NoArrayAccessOnObjectRule - -Use explicit methods over array access on object - -- class: [`Symplify\PHPStanRules\Rules\NoArrayAccessOnObjectRule`](../src/Rules/NoArrayAccessOnObjectRule.php) - -```php -class SomeClass -{ - public function run(MagicArrayObject $magicArrayObject) - { - return $magicArrayObject['more_magic']; - } -} -``` - -:x: - -
- -```php -class SomeClass -{ - public function run(MagicArrayObject $magicArrayObject) - { - return $magicArrayObject->getExplicitValue(); - } -} -``` - -:+1: - -
- -## NoArrayStringObjectReturnRule - -Use another value object over array with string-keys and objects, array - -- class: [`Symplify\PHPStanRules\Rules\NoArrayStringObjectReturnRule`](../src/Rules/NoArrayStringObjectReturnRule.php) - -```php -final class SomeClass -{ - public function getItems() - { - return $this->getValues(); - } - - /** - * @return array - */ - private function getValues() - { - } -} -``` - -:x: - -
- -```php -final class SomeClass -{ - public function getItems() - { - return $this->getValues(); - } - - /** - * @return WrappingValue[] - */ - private function getValues() - { - // ... - } -} -``` - -:+1: - -
- -## NoChainMethodCallRule - -Do not use chained method calls. Put each on separated lines. - -:wrench: **configure it!** - -- class: [`Symplify\PHPStanRules\ObjectCalisthenics\Rules\NoChainMethodCallRule`](../packages/ObjectCalisthenics/Rules/NoChainMethodCallRule.php) - -```yaml -services: - - - class: Symplify\PHPStanRules\ObjectCalisthenics\Rules\NoChainMethodCallRule - tags: [phpstan.rules.rule] - arguments: - allowedChainTypes: - - AllowedFluent -``` - -↓ - -```php -$this->runThis()->runThat(); - -$fluentClass = new AllowedFluent(); -$fluentClass->one()->two(); -``` - -:x: - -
- -```php -$this->runThis(); -$this->runThat(); - -$fluentClass = new AllowedFluent(); -$fluentClass->one()->two(); -``` - -:+1: - -
- -## NoClassWithStaticMethodWithoutStaticNameRule - -Class has a static method must so must contains "Static" in its name - -- class: [`Symplify\PHPStanRules\Rules\NoClassWithStaticMethodWithoutStaticNameRule`](../src/Rules/NoClassWithStaticMethodWithoutStaticNameRule.php) - -```php -class SomeClass -{ - public static function getSome() - { - } -} -``` - -:x: - -
- -```php -class SomeStaticClass -{ - public static function getSome() - { - } -} -``` - -:+1: - -
- -## NoConstantInterfaceRule - -Reserve interface for contract only. Move constant holder to a class soon-to-be Enum - -- class: [`Symplify\PHPStanRules\Rules\Enum\NoConstantInterfaceRule`](../src/Rules/Enum/NoConstantInterfaceRule.php) - -```php -interface SomeContract -{ - public const YES = 'yes'; - - public const NO = 'no'; -} -``` - -:x: - -
- -```php -class SomeValues -{ - public const YES = 'yes'; - - public const NO = 'no'; -} -``` - -:+1: - -
- -## NoConstructorInTestRule - -Do not use constructor in tests. Move to `setUp()` method - -- class: [`Symplify\PHPStanRules\Rules\NoConstructorInTestRule`](../src/Rules/NoConstructorInTestRule.php) - -```php -final class SomeTest -{ - public function __construct() - { - // ... - } -} -``` - -:x: - -
- -```php -final class SomeTest -{ - public function setUp() - { - // ... - } -} -``` - -:+1: - -
- -## NoConstructorSymfonyFormObjectRule - -This object is used in a Symfony form, that uses magic setters/getters, so it cannot have required constructor - -- class: [`Symplify\PHPStanRules\Symfony\Rules\NoConstructorSymfonyFormObjectRule`](../packages/Symfony/Rules/NoConstructorSymfonyFormObjectRule.php) - -```php -final class Ticket -{ - public function __construct(private int $price) - { - } -} - ---- - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\OptionsResolver\OptionsResolver; -use App\Entity\Ticket; - -final class TicketFormType extends AbstractType -{ - public function configureOptions(OptionsResolver $resolver): void - { - $resolver->setDefaults([ - 'data_class' => Ticket::class, - ]); - } -} -``` - -:x: - -
- -```php -final class Ticket -{ - private ?int $price = null; - - public function setPrice(int $price): void - { - $this->price = $price; - } - - public function getPrice(): ?int - { - return $this->price; - } -} - ---- - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\OptionsResolver\OptionsResolver; -use App\Entity\Ticket; - -final class TicketFormType extends AbstractType -{ - public function configureOptions(OptionsResolver $resolver): void - { - $resolver->setDefaults([ - 'data_class' => Ticket::class, - ]); - } -} -``` - -:+1: - -
- -## NoDefaultExceptionRule - -Use custom exceptions instead of native "%s" - -- class: [`Symplify\PHPStanRules\Rules\NoDefaultExceptionRule`](../src/Rules/NoDefaultExceptionRule.php) - -```php -throw new RuntimeException('...'); -``` - -:x: - -
- -```php -use App\Exception\FileNotFoundException; - -throw new FileNotFoundException('...'); -``` - -:+1: - -
- -## NoDuplicatedArgumentRule - -This call has duplicate argument - -- class: [`Symplify\PHPStanRules\Rules\Complexity\NoDuplicatedArgumentRule`](../src/Rules/Complexity/NoDuplicatedArgumentRule.php) - -```php -function run($one, $one); -``` - -:x: - -
- -```php -function run($one, $two); -``` - -:+1: - -
- -## NoDuplicatedRegexRule - -The "%s" constant contains duplicated regex "%s". Instead of duplicated regexes, extract domain regexes together to save maintenance - -- class: [`Symplify\PHPStanRules\Rules\Domain\NoDuplicatedRegexRule`](../src/Rules/Domain/NoDuplicatedRegexRule.php) - -```php -class SomeClass -{ - private const CLASS_NAME_REGEX = '#[\w\\]+#'; -} - -class AnotherClass -{ - private const DIFFERENT_NAME_REGEX = '#[\w\\]+#'; -} -``` - -:x: - -
- -```php -class ClassRegexRecipies -{ - private const NAME_REGEX = '#[\w\\]+#'; -} -``` - -:+1: - -
- -## NoDuplicatedShortClassNameRule - -Class with base "%s" name is already used in "%s". Use unique name to make classes easy to recognize - -:wrench: **configure it!** - -- class: [`Symplify\PHPStanRules\Rules\NoDuplicatedShortClassNameRule`](../src/Rules/NoDuplicatedShortClassNameRule.php) - -```yaml -services: - - - class: Symplify\PHPStanRules\Rules\NoDuplicatedShortClassNameRule - tags: [phpstan.rules.rule] - arguments: - toleratedNestingLevel: 1 -``` - -↓ - -```php -namespace App; - -class SomeClass -{ -} - -namespace App\Nested; - -class SomeClass -{ -} -``` - -:x: - -
- -```php -namespace App; - -class SomeClass -{ -} - -namespace App\Nested; - -class AnotherClass -{ -} -``` - -:+1: - -
- -## NoDuplicatedTraitMethodNameRule - -Method name `"%s()"` is used in multiple traits. Make it unique to avoid conflicts - -- class: [`Symplify\PHPStanRules\Rules\Complexity\NoDuplicatedTraitMethodNameRule`](../src/Rules/Complexity/NoDuplicatedTraitMethodNameRule.php) - -```php -trait FirstTrait -{ - public function run() - { - } -} - -trait SecondTrait -{ - public function run() - { - } -} -``` - -:x: - -
- -```php -trait FirstTrait -{ - public function run() - { - } -} - -trait SecondTrait -{ - public function fly() - { - } -} -``` - -:+1: - -
- -## NoDuplicatedVariableCasingNameRule - -Lowered variable "%s" is used in various-cased names: "%s", unite it to one - -- class: [`Symplify\PHPStanRules\Rules\Explicit\NoDuplicatedVariableCasingNameRule`](../src/Rules/Explicit/NoDuplicatedVariableCasingNameRule.php) - -```php -final class SomeClass -{ - public function run() - { - $run = 1; - } - - public function go() - { - $ruN = 2; - } -} -``` - -:x: - -
- -```php -final class SomeClass -{ - public function run() - { - $run = 1; - } - - public function go() - { - $run = 2; - } -} -``` - -:+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: - -
- -## NoDynamicPropertyOnStaticCallRule - -Use non-dynamic property on static calls or class const fetches - -- class: [`Symplify\PHPStanRules\Rules\NoDynamicPropertyOnStaticCallRule`](../src/Rules/NoDynamicPropertyOnStaticCallRule.php) - -```php -class SomeClass -{ - public function run() - { - return $this->connection::literal(); - } -} -``` - -:x: - -
- -```php -class SomeClass -{ - public function run() - { - return Connection::literal(); - } -} -``` - -:+1: - -
- -## NoEmptyClassRule - -There should be no empty class - -- class: [`Symplify\PHPStanRules\Rules\NoEmptyClassRule`](../src/Rules/NoEmptyClassRule.php) - -```php -class SomeClass -{ -} -``` - -:x: - -
- -```php -class SomeClass -{ - public function getSome() - { - } -} -``` - -:+1: - -
- -## NoFuncCallInMethodCallRule - -Separate function `"%s()"` in method call to standalone row to improve readability - -- class: [`Symplify\PHPStanRules\Rules\NoFuncCallInMethodCallRule`](../src/Rules/NoFuncCallInMethodCallRule.php) - -```php -final class SomeClass -{ - public function run($value): void - { - $this->someMethod(strlen('fooo')); - } - - // ... -} -``` - -:x: - -
- -```php -final class SomeClass -{ - public function run($value): void - { - $fooLength = strlen('fooo'); - $this->someMethod($fooLength); - } - - // ... -} -``` - -:+1: - -
- -## NoGetterAndPropertyRule - -There are 2 way to get "%s" value: public property and getter now - pick one to avoid variant behavior. - -- class: [`Symplify\PHPStanRules\Rules\Explicit\NoGetterAndPropertyRule`](../src/Rules/Explicit/NoGetterAndPropertyRule.php) - -```php -final class SomeProduct -{ - public $name; - - public function getName(): string - { - return $this->name; - } -} -``` - -:x: - -
- -```php -final class SomeProduct -{ - private $name; - - public function getName(): string - { - return $this->name; - } -} -``` - -:+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: - -
- -## NoIssetOnObjectRule - -Use default null value and nullable compare instead of isset on object - -- class: [`Symplify\PHPStanRules\Rules\NoIssetOnObjectRule`](../src/Rules/NoIssetOnObjectRule.php) - -```php -class SomeClass -{ - public function run() - { - if (random_int(0, 1)) { - $object = new SomeClass(); - } - - if (isset($object)) { - return $object; - } - } -} -``` - -:x: - -
- -```php -class SomeClass -{ - public function run() - { - $object = null; - if (random_int(0, 1)) { - $object = new SomeClass(); - } - - if ($object !== null) { - return $object; - } - } -} -``` - -:+1: - -
- -## NoMethodTagInClassDocblockRule - -Do not use `@method` tag in class docblock - -- class: [`Symplify\PHPStanRules\Rules\NoMethodTagInClassDocblockRule`](../src/Rules/NoMethodTagInClassDocblockRule.php) - -```php -/** - * @method getMagic() string - */ -class SomeClass -{ - public function __call() - { - // more magic - } -} -``` - -:x: - -
- -```php -class SomeClass -{ - public function getExplicitValue() - { - return 'explicit'; - } -} -``` - -:+1: - -
- -## NoMirrorAssertRule - -The assert is tautology that compares to itself. Fix it to different values - -- class: [`Symplify\PHPStanRules\Rules\Complexity\NoMirrorAssertRule`](../src/Rules/Complexity/NoMirrorAssertRule.php) - -```php -use PHPUnit\Framework\TestCase; - -final class AssertMirror extends TestCase -{ - public function test() - { - $this->assertSame(1, 1); - } -} -``` - -:x: - -
- -```php -use PHPUnit\Framework\TestCase; - -final class AssertMirror extends TestCase -{ - public function test() - { - $value = 200; - $this->assertSame(1, $value); - } -} -``` - -:+1: - -
- -## NoMissingArrayShapeReturnArrayRule - -Complete known array shape to the method `@return` type - -- class: [`Symplify\PHPStanRules\Rules\Explicit\NoMissingArrayShapeReturnArrayRule`](../src/Rules/Explicit/NoMissingArrayShapeReturnArrayRule.php) - -```php -function run(string $name) -{ - return ['name' => $name]; -} -``` - -:x: - -
- -```php -/** - * @return array{name: string} - */ -function run(string $name) -{ - return ['name' => $name]; -} -``` - -:+1: - -
- -## NoMissingAssingNoVoidMethodCallRule - -Method call return value that should be used, but is not - -- class: [`Symplify\PHPStanRules\Rules\Explicit\NoMissingAssingNoVoidMethodCallRule`](../src/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule.php) - -```php -class SomeClass -{ - public function run() - { - $this->getResult(); - } - - private function getResult() - { - return []; - } -} -``` - -:x: - -
- -```php -final class SomeClass -{ - public function run() - { - return $this->getResult(); - } - - private function getResult() - { - return []; - } -} -``` - -:+1: - -
- -## NoMissingDirPathRule - -The path "%s" was not found - -- class: [`Symplify\PHPStanRules\Rules\NoMissingDirPathRule`](../src/Rules/NoMissingDirPathRule.php) - -```php -$filePath = __DIR__ . '/missing_location.txt'; -``` - -:x: - -
- -```php -$filePath = __DIR__ . '/existing_location.txt'; -``` - -:+1: - -
- -## NoMixedArrayDimFetchRule - -Add explicit array type to assigned "%s" expression - -- class: [`Symplify\PHPStanRules\Rules\Explicit\NoMixedArrayDimFetchRule`](../src/Rules/Explicit/NoMixedArrayDimFetchRule.php) - -```php -class SomeClass -{ - private $items = []; - - public function addItem(string $key, string $value) - { - $this->items[$key] = $value; - } -} -``` - -:x: - -
- -```php -class SomeClass -{ - /** - * @var array - */ - private $items = []; - - public function addItem(string $key, string $value) - { - $this->items[$key] = $value; - } -} -``` - -:+1: - -
- -## NoMixedCallableRule - -Make callable type explicit. Here is how: https://phpstan.org/writing-php-code/phpdoc-types#callables - -- class: [`Symplify\PHPStanRules\Rules\Explicit\NoMixedCallableRule`](../src/Rules/Explicit/NoMixedCallableRule.php) - -```php -function run(callable $callable) -{ - return $callable(100); -} -``` - -:x: - -
- -```php -/** - * @param callable(): int $callable - */ -function run(callable $callable): int -{ - return $callable(100); -} -``` - -:+1: - -
- -## NoMixedMethodCallerRule - -Anonymous variable in a `%s->...()` method call can lead to false dead methods. Make sure the variable type is known - -- class: [`Symplify\PHPStanRules\Rules\Explicit\NoMixedMethodCallerRule`](../src/Rules/Explicit/NoMixedMethodCallerRule.php) - -```php -function run($unknownType) -{ - return $unknownType->call(); -} -``` - -:x: - -
- -```php -function run(KnownType $knownType) -{ - return $knownType->call(); -} -``` - -:+1: - -
- -## NoMixedPropertyFetcherRule - -Anonymous variables in a "%s->..." property fetch can lead to false dead property. Make sure the variable type is known - -- class: [`Symplify\PHPStanRules\Rules\Explicit\NoMixedPropertyFetcherRule`](../src/Rules/Explicit/NoMixedPropertyFetcherRule.php) - -```php -function run($unknownType) -{ - return $unknownType->name; -} -``` - -:x: - -
- -```php -function run(KnownType $knownType) -{ - return $knownType->name; -} -``` - -:+1: - -
- -## NoMultiArrayAssignRule - -Use value object over multi array assign - -- class: [`Symplify\PHPStanRules\Rules\NoMultiArrayAssignRule`](../src/Rules/NoMultiArrayAssignRule.php) - -```php -$values = []; -$values['person']['name'] = 'Tom'; -$values['person']['surname'] = 'Dev'; -``` - -:x: - -
- -```php -$values = []; -$values[] = new Person('Tom', 'Dev'); -``` - -:+1: - -
- -## NoNestedFuncCallRule - -Use separate function calls with readable variable names - -- class: [`Symplify\PHPStanRules\Rules\NoNestedFuncCallRule`](../src/Rules/NoNestedFuncCallRule.php) - -```php -$filteredValues = array_filter(array_map($callback, $items)); -``` - -:x: - -
- -```php -$mappedItems = array_map($callback, $items); -$filteredValues = array_filter($mappedItems); -``` - -:+1: - -
- -## NoNullableArrayPropertyRule - -Use required typed property over of nullable array property - -- class: [`Symplify\PHPStanRules\Rules\NoNullableArrayPropertyRule`](../src/Rules/NoNullableArrayPropertyRule.php) - -```php -final class SomeClass -{ - private ?array $property = null; -} -``` - -:x: - -
- -```php -final class SomeClass -{ - private array $property = []; -} -``` - -:+1: - -
- -## NoParentMethodCallOnNoOverrideProcessRule - -Do not call parent method if no override process - -- class: [`Symplify\PHPStanRules\Rules\NoParentMethodCallOnNoOverrideProcessRule`](../src/Rules/NoParentMethodCallOnNoOverrideProcessRule.php) - -```php -class SomeClass extends Printer -{ - public function print($nodes) - { - return parent::print($nodes); - } -} -``` - -:x: - -
- -```php -class SomeClass extends Printer -{ -} -``` - -:+1: - -
- -## NoProtectedElementInFinalClassRule - -Instead of protected element in final class use private element or contract method - -- class: [`Symplify\PHPStanRules\Rules\NoProtectedElementInFinalClassRule`](../src/Rules/NoProtectedElementInFinalClassRule.php) - -```php -final class SomeClass -{ - protected function run() - { - } -} -``` - -:x: - -
- -```php -final class SomeClass -{ - private function run() - { - } -} -``` - -:+1: - -
- -## NoPublicPropertyByTypeRule - -Class cannot have public properties. Use getter/setters instead - -:wrench: **configure it!** - -- class: [`Symplify\PHPStanRules\Rules\Privatization\NoPublicPropertyByTypeRule`](../src/Rules/Privatization/NoPublicPropertyByTypeRule.php) - -```yaml -services: - - - class: Symplify\PHPStanRules\Rules\Privatization\NoPublicPropertyByTypeRule - tags: [phpstan.rules.rule] - arguments: - classTypes: - - Entity -``` - -↓ - -```php -final class Person extends Entity -{ - public $name; -} -``` - -:x: - -
- -```php -final class Person extends Entity -{ - private $name; - - public function getName() - { - return $this->name; - } -} -``` - -:+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: - -
- -## NoRelativeFilePathRule - -Relative file path "%s" is not allowed, use absolute one with __DIR__ - -- class: [`Symplify\PHPStanRules\Rules\Explicit\NoRelativeFilePathRule`](../src/Rules/Explicit/NoRelativeFilePathRule.php) - -```php -$filePath = 'some_file.txt'; -``` - -:x: - -
- -```php -$filePath = __DIR__ . '/some_file.txt'; -``` - -:+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: - -
- -## NoRightPHPUnitAssertScalarRule - -The compare assert arguments are switched. Move the expected value to the 1st left - -- class: [`Symplify\PHPStanRules\Rules\PHPUnit\NoRightPHPUnitAssertScalarRule`](../src/Rules/PHPUnit/NoRightPHPUnitAssertScalarRule.php) - -```php -use PHPUnit\Framework\TestCase; - -final class SomeFlippedAssert extends TestCase -{ - public function test() - { - $value = 1000; - $this->assertSame($value, 10); - } -} -``` - -:x: - -
- -```php -use PHPUnit\Framework\TestCase; - -final class SomeFlippedAssert extends TestCase -{ - public function test() - { - $value = 1000; - $this->assertSame(10, $value); - } -} -``` - -:+1: - -
- -## NoShortNameRule - -Do not name "%s", shorter than %d chars - -:wrench: **configure it!** - -- class: [`Symplify\PHPStanRules\ObjectCalisthenics\Rules\NoShortNameRule`](../packages/ObjectCalisthenics/Rules/NoShortNameRule.php) - -```yaml -services: - - - class: Symplify\PHPStanRules\ObjectCalisthenics\Rules\NoShortNameRule - tags: [phpstan.rules.rule] - arguments: - minNameLength: 3 -``` - -↓ - -```php -function is() -{ -} -``` - -:x: - -
- -```php -function isClass() -{ -} -``` - -:+1: - -
- -## NoStaticPropertyRule - -Do not use static property - -- class: [`Symplify\PHPStanRules\Rules\NoStaticPropertyRule`](../src/Rules/NoStaticPropertyRule.php) - -```php -final class SomeClass -{ - private static $customFileNames = []; -} -``` - -:x: - -
- -```php -final class SomeClass -{ - private $customFileNames = []; -} -``` - -:+1: - -
- -## NoVoidGetterMethodRule - -Getter method must return something, not void - -- class: [`Symplify\PHPStanRules\Rules\NoVoidGetterMethodRule`](../src/Rules/NoVoidGetterMethodRule.php) - -```php -final class SomeClass -{ - public function getData(): void - { - // ... - } -} -``` - -:x: - -
- -```php -final class SomeClass -{ - public function getData(): array - { - // ... - } -} -``` - -:+1: - -
- -## ParamTypeDeclarationSeaLevelRule - -Out of %d possible param types, only %d %% actually have it. Add more param types to get over %d %% - -- class: [`Symplify\PHPStanRules\Rules\Explicit\ParamTypeDeclarationSeaLevelRule`](../src/Rules/Explicit/ParamTypeDeclarationSeaLevelRule.php) - -```php -final class SomeClass -{ - public function run($name, $age) - { - } -} -``` - -:x: - -
- -```php -final class SomeClass -{ - public function run(string $name, int $age) - { - } -} -``` - -:+1: - -
- -## PreferredAttributeOverAnnotationRule - -Use attribute instead of "%s" annotation - -:wrench: **configure it!** - -- class: [`Symplify\PHPStanRules\Rules\PreferredAttributeOverAnnotationRule`](../src/Rules/PreferredAttributeOverAnnotationRule.php) - -```yaml -services: - - - class: Symplify\PHPStanRules\Rules\PreferredAttributeOverAnnotationRule - tags: [phpstan.rules.rule] - arguments: - annotations: - - Symfony\Component\Routing\Annotation\Route -``` - -↓ - -```php -use Symfony\Component\Routing\Annotation\Route; - -class SomeController -{ - /** - * @Route() - */ - public function action() - { - } -} -``` - -:x: - -
- -```php -use Symfony\Component\Routing\Annotation\Route; - -class SomeController -{ - #[Route] - public function action() - { - } -} -``` - -:+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: - -
- -## PreferredRawDataInTestDataProviderRule - -Code configured at `setUp()` cannot be used in data provider. Move it to `test()` method - -- class: [`Symplify\PHPStanRules\Rules\PreferredRawDataInTestDataProviderRule`](../src/Rules/PreferredRawDataInTestDataProviderRule.php) - -```php -final class UseDataFromSetupInTestDataProviderTest extends TestCase -{ - private $data; - - protected function setUp(): void - { - $this->data = true; - } - - public function provideFoo() - { - yield [$this->data]; - } - - /** - * @dataProvider provideFoo - */ - public function testFoo($value) - { - $this->assertTrue($value); - } -} -``` - -:x: - -
- -```php -use stdClass; - -final class UseRawDataForTestDataProviderTest -{ - private $obj; - - protected function setUp(): void - { - $this->obj = new stdClass; - } - - public function provideFoo() - { - yield [true]; - } - - /** - * @dataProvider provideFoo - */ - public function testFoo($value) - { - $this->obj->x = $value; - $this->assertTrue($this->obj->x); - } -} -``` - -:+1: - -
- -## PrefixAbstractClassRule - -Abstract class name "%s" must be prefixed with "Abstract" - -- class: [`Symplify\PHPStanRules\Rules\PrefixAbstractClassRule`](../src/Rules/PrefixAbstractClassRule.php) - -```php -abstract class SomeClass -{ -} -``` - -:x: - -
- -```php -abstract class AbstractSomeClass -{ -} -``` - -:+1: - -
- -## PreventDoubleSetParameterRule - -Set param value is overridden. Merge it to previous set above - -- class: [`Symplify\PHPStanRules\Symfony\Rules\PreventDoubleSetParameterRule`](../packages/Symfony/Rules/PreventDoubleSetParameterRule.php) - -```php -use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; - -return static function (ContainerConfigurator $containerConfigurator): void { - $parameters = $containerConfigurator->parameters(); - - $parameters->set('some_param', [1]); - $parameters->set('some_param', [2]); -}; -``` - -:x: - -
- -```php -use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; - -return static function (ContainerConfigurator $containerConfigurator): void { - $parameters = $containerConfigurator->parameters(); - - $parameters->set('some_param', [1, 2]); -}; -``` - -:+1: - -
- -## PreventDuplicateClassMethodRule - -Content of method `"%s()"` is duplicated. Use unique content or service instead - -:wrench: **configure it!** - -- class: [`Symplify\PHPStanRules\Rules\PreventDuplicateClassMethodRule`](../src/Rules/PreventDuplicateClassMethodRule.php) - -```yaml -services: - - - class: Symplify\PHPStanRules\Rules\PreventDuplicateClassMethodRule - tags: [phpstan.rules.rule] - arguments: - minimumLineCount: 3 -``` - -↓ - -```php -class SomeClass -{ - public function someMethod() - { - echo 'statement'; - $value = new SmartFinder(); - } -} - -class AnotherClass -{ - public function someMethod() - { - echo 'statement'; - $differentValue = new SmartFinder(); - } -} -``` - -:x: - -
- -```php -class SomeClass -{ - public function someMethod() - { - echo 'statement'; - $value = new SmartFinder(); - } -} -} -``` - -:+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 -{ - protected function run() - { - } -} -``` - -:x: - -
- -```php -class SomeParentClass -{ - public function run() - { - } -} - -class SomeClass -{ - public function run() - { - } -} -``` - -:+1: - -
- -## PropertyTypeDeclarationSeaLevelRule - -Out of %d possible property types, only %d %% actually have it. Add more property types to get over %d %% - -- class: [`Symplify\PHPStanRules\Rules\Explicit\PropertyTypeDeclarationSeaLevelRule`](../src/Rules/Explicit/PropertyTypeDeclarationSeaLevelRule.php) - -```php -final class SomeClass -{ - public $name; -} -``` - -:x: - -
- -```php -final class SomeClass -{ - public string $name; -} -``` - -:+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: - -
- -## RequireCascadeValidateRule - -Property "$%s" is missing `@Valid` annotation - -- class: [`Symplify\PHPStanRules\Symfony\Rules\RequireCascadeValidateRule`](../packages/Symfony/Rules/RequireCascadeValidateRule.php) - -```php -use Symfony\Component\Form\AbstractType; -use Symfony\Component\OptionsResolver\OptionsResolver; -use Symfony\Component\Validator\Constraints\Valid; - -final class NullablePropertyFormType extends AbstractType -{ - public function configureOptions(OptionsResolver $optionsResolver): void - { - $optionsResolver->setDefaults([ - 'data_class' => SomeEntity::class, - 'constraints' => new Valid(), - ]); - } -} - -class SomeEntity -{ - /** - * @var NestedEntity - */ - private $nestedEntity; -} -``` - -:x: - -
- -```php -use Symfony\Component\Validator\Constraints as Assert; - -class SomeEntity -{ - /** - * @Assert\Valid - * @var NestedEntity - */ - private $nestedEntity; -} -``` - -:+1: - -
- -## RequireConstantInMethodCallPositionRule - -Parameter argument on position %d must use constant - -:wrench: **configure it!** - -- class: [`Symplify\PHPStanRules\Rules\Enum\RequireConstantInMethodCallPositionRule`](../src/Rules/Enum/RequireConstantInMethodCallPositionRule.php) - -```yaml -services: - - - class: Symplify\PHPStanRules\Rules\Enum\RequireConstantInMethodCallPositionRule - tags: [phpstan.rules.rule] - arguments: - requiredLocalConstantInMethodCall: - SomeType: - someMethod: - - 0 -``` - -↓ - -```php -class SomeClass -{ - public function someMethod(SomeType $someType) - { - $someType->someMethod('hey'); - } -} -``` - -:x: - -
- -```php -class SomeClass -{ - private const HEY = 'hey' - - public function someMethod(SomeType $someType) - { - $someType->someMethod(self::HEY); - } -} -``` - -:+1: - -
- -## RequireEnumDocBlockOnConstantListPassRule - -On passing a constant, the method should have an enum type. See https://phpstan.org/writing-php-code/phpdoc-types#literals-and-constants - -- class: [`Symplify\PHPStanRules\Rules\Enum\RequireEnumDocBlockOnConstantListPassRule`](../src/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule.php) - -```php -final class Direction -{ - public const LEFT = 'left'; - - public const RIGHT = 'right'; -} - -final class Driver -{ - public function goToWork() - { - $this->turn(Direction::LEFT); - } - - private function turn(string $direction) - { - // ... - } -} -``` - -:x: - -
- -```php -final class Direction -{ - public const LEFT = 'left'; - - public const RIGHT = 'right'; -} - -final class Driver -{ - public function goToWork() - { - $this->turn(Direction::LEFT); - } - - /** - * @param Direction::* - */ - private function turn(string $direction) - { - // ... - } -} -``` - -:+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`](../packages/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: - -
- -## RequireNamedCommandRule - -The command is missing `$this->setName("...")` or [#AsCommand] attribute to set the name - -- class: [`Symplify\PHPStanRules\Symfony\Rules\RequireNamedCommandRule`](../packages/Symfony/Rules/RequireNamedCommandRule.php) - -```php -use Symfony\Component\Console\Command\Command; - -final class SomeCommand extends Command -{ - public function configure() - { - } -} -``` - -:x: - -
- -```php -use Symfony\Component\Console\Command\Command; - -final class SomeCommand extends Command -{ - public function configure() - { - $this->setName('some'); - } -} -``` - -:+1: - -
- -## RequireNativeArraySymfonyRenderCallRule - -Second argument of `$this->render("template.twig",` [...]) method should be explicit array, to avoid accidental variable override, see https://tomasvotruba.com/blog/2021/02/15/how-dangerous-is-your-nette-template-assign/ - -- class: [`Symplify\PHPStanRules\Symfony\Rules\RequireNativeArraySymfonyRenderCallRule`](../packages/Symfony/Rules/RequireNativeArraySymfonyRenderCallRule.php) - -```php -use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; - -class SomeController extends AbstractController -{ - public function default() - { - $parameters['name'] = 'John'; - $parameters['name'] = 'Doe'; - return $this->render('...', $parameters); - } -} -``` - -:x: - -
- -```php -use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; - -class SomeController extends AbstractController -{ - public function default() - { - return $this->render('...', [ - 'name' => 'John' - ]); - } -} -``` - -:+1: - -
- -## RequireNewArgumentConstantRule - -New expression argument on position %d must use constant over value - -:wrench: **configure it!** - -- class: [`Symplify\PHPStanRules\Rules\Enum\RequireNewArgumentConstantRule`](../src/Rules/Enum/RequireNewArgumentConstantRule.php) - -```yaml -services: - - - class: Symplify\PHPStanRules\Rules\Enum\RequireNewArgumentConstantRule - tags: [phpstan.rules.rule] - arguments: - constantArgByNewByType: - Symfony\Component\Console\Input\InputOption: - - 2 -``` - -↓ - -```php -use Symfony\Component\Console\Input\InputOption; - -$inputOption = new InputOption('name', null, 2); -``` - -:x: - -
- -```php -use Symfony\Component\Console\Input\InputOption; - -$inputOption = new InputOption('name', null, InputOption::VALUE_REQUIRED); -``` - -:+1: - -
- -## RequireSpecificReturnTypeOverAbstractRule - -Provide more specific return type "%s" over abstract one - -- class: [`Symplify\PHPStanRules\Rules\Explicit\RequireSpecificReturnTypeOverAbstractRule`](../src/Rules/Explicit/RequireSpecificReturnTypeOverAbstractRule.php) - -```php -final class IssueControlFactory -{ - public function create(): Control - { - return new IssueControl(); - } -} - -final class IssueControl extends Control -{ -} -``` - -:x: - -
- -```php -final class IssueControlFactory -{ - public function create(): IssueControl - { - return new IssueControl(); - } -} - -final class IssueControl extends Control -{ -} -``` - -:+1: - -
- -## RequireStringRegexMatchKeyRule - -Regex must use string named capture groups instead of numeric - -- class: [`Symplify\PHPStanRules\Rules\RequireStringRegexMatchKeyRule`](../src/Rules/RequireStringRegexMatchKeyRule.php) - -```php -use Nette\Utils\Strings; - -class SomeClass -{ - private const REGEX = '#(a content)#'; - - public function run() - { - $matches = Strings::match('a content', self::REGEX); - if ($matches) { - echo $matches[1]; - } - } -} -``` - -:x: - -
- -```php -use Nette\Utils\Strings; - -class SomeClass -{ - private const REGEX = '#(?a content)#'; - - public function run() - { - $matches = Strings::match('a content', self::REGEX); - if ($matches) { - echo $matches['content']; - } - } -} -``` - -:+1: - -
- -## RequireThisCallOnLocalMethodRule - -Use "$this->()" instead of "self::()" to call local method - -- class: [`Symplify\PHPStanRules\Rules\RequireThisCallOnLocalMethodRule`](../src/Rules/RequireThisCallOnLocalMethodRule.php) - -```php -class SomeClass -{ - public function run() - { - self::execute(); - } - - private function execute() - { - } -} -``` - -:x: - -
- -```php -class SomeClass -{ - public function run() - { - $this->execute(); - } - - private function execute() - { - } -} -``` - -:+1: - -
- -## RequireThisOnParentMethodCallRule - -Use "$this->()" instead of "parent::()" unless in the same named method - -- class: [`Symplify\PHPStanRules\Rules\RequireThisOnParentMethodCallRule`](../src/Rules/RequireThisOnParentMethodCallRule.php) - -```php -class SomeParentClass -{ - public function run() - { - } -} - -class SomeClass extends SomeParentClass -{ - public function go() - { - parent::run(); - } -} -``` - -:x: - -
- -```php -class SomeParentClass -{ - public function run() - { - } -} - -class SomeClass extends SomeParentClass -{ - public function go() - { - $this->run(); - } -} -``` - -:+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: - -
- -## RequiredAbstractClassKeywordRule - -Class name starting with "Abstract" must have an `abstract` keyword - -- class: [`Symplify\PHPStanRules\Rules\RequiredAbstractClassKeywordRule`](../src/Rules/RequiredAbstractClassKeywordRule.php) - -```php -class AbstractClass -{ -} -``` - -:x: - -
- -```php -abstract class AbstractClass -{ -} -``` - -:+1: - -
- -## ReturnTypeDeclarationSeaLevelRule - -Out of %d possible return types, only %d %% actually have it. Add more return types to get over %d %% - -- class: [`Symplify\PHPStanRules\Rules\Explicit\ReturnTypeDeclarationSeaLevelRule`](../src/Rules/Explicit/ReturnTypeDeclarationSeaLevelRule.php) - -```php -final class SomeClass -{ - public function run() - { - } -} -``` - -:x: - -
- -```php -final class SomeClass -{ - public function run(): void - { - } -} -``` - -:+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: - -
- -## SuffixInterfaceRule - -Interface must be suffixed with "Interface" exclusively - -- class: [`Symplify\PHPStanRules\Rules\SuffixInterfaceRule`](../src/Rules/SuffixInterfaceRule.php) - -```php -interface SomeClass -{ -} -``` - -:x: - -
- -```php -interface SomeInterface -{ -} -``` - -:+1: - -
- -## SuffixTraitRule - -Trait must be suffixed by "Trait" exclusively - -- class: [`Symplify\PHPStanRules\Rules\SuffixTraitRule`](../src/Rules/SuffixTraitRule.php) - -```php -trait SomeClass -{ -} -``` - -:x: - -
- -```php -trait SomeTrait -{ -} -``` - -:+1: - -
- -## SwitchToMatchSpotterRule - -Switch construction can be replace with more robust `match()` - -- class: [`Symplify\PHPStanRules\Rules\Spotter\SwitchToMatchSpotterRule`](../src/Rules/Spotter/SwitchToMatchSpotterRule.php) - -```php -switch ($key) { - case 1: - return 100; - case 2: - return 200; - default: - return 300; -}; -``` - -:x: - -
- -```php -return match($key) { - 1 => 100, - 2 => 200, - default => 300, -}; -``` - -:+1: - -
- -## TwigPublicCallableExistsRule - -The callable method [$this, "%s"] was not found - -- class: [`Symplify\PHPStanRules\Symfony\Rules\TwigPublicCallableExistsRule`](../packages/Symfony/Rules/TwigPublicCallableExistsRule.php) - -```php -use Twig\Extension\AbstractExtension; -use Twig_SimpleFunction; - -final class TwigExtensionWithMissingCallable extends AbstractExtension -{ - public function getFunctions() - { - return [ - new Twig_SimpleFunction('someFunctionName', [$this, 'someMethod']), - ]; - } -} -``` - -:x: - -
- -```php -use Twig\Extension\AbstractExtension; -use Twig_SimpleFunction; - -final class TwigExtensionWithMissingCallable extends AbstractExtension -{ - public function getFunctions() - { - return [ - new Twig_SimpleFunction('someFunctionName', [$this, 'someMethod']), - ]; - } - - public function someMethod() - { - // ... - } -} -``` - -:+1: - -
- -## UnusedPublicClassConstRule - -Class constant "%s" is never used outside of its class - -- class: [`Symplify\PHPStanRules\Rules\DeadCode\UnusedPublicClassConstRule`](../src/Rules/DeadCode/UnusedPublicClassConstRule.php) - -```php -final class Direction -{ - public LEFT = 'left'; - - public RIGHT = 'right'; - - public STOP = 'stop'; -} - -if ($direction === Direction::LEFT) { - echo 'left'; -} - -if ($direction === Direction::RIGHT) { - echo 'right'; -} -``` - -:x: - -
- -```php -final class Direction -{ - public LEFT = 'left'; - - public RIGHT = 'right'; -} - -if ($direction === Direction::LEFT) { - echo 'left'; -} - -if ($direction === Direction::RIGHT) { - echo 'right'; -} -``` - -:+1: - -
- -## UnusedPublicClassMethodRule - -Class method `"%s()"` is never used outside of its class - -- class: [`Symplify\PHPStanRules\Rules\DeadCode\UnusedPublicClassMethodRule`](../src/Rules/DeadCode/UnusedPublicClassMethodRule.php) - -```php -final class Car -{ - public function turn() - { - } - - public function stay() - { - } -} - -final class Driver -{ - public function driveCar(Car $car) - { - $car->turn(); - } -} -``` - -:x: - -
- -```php -final class Car -{ - public function turn() - { - } -} - -final class Driver -{ - public function driveCar(Car $car) - { - $car->turn(); - } -} -``` - -:+1: - -
- -## UnusedPublicPropertyRule - -Property `"%s()"` is never used outside of its class - -- class: [`Symplify\PHPStanRules\Rules\DeadCode\UnusedPublicPropertyRule`](../src/Rules/DeadCode/UnusedPublicPropertyRule.php) - -```php -final class Car -{ - public $name; - - public function getName() - { - return $this->name; - } -} -``` - -:x: - -
- -```php -final class Car -{ - private $name; - - public function getName() - { - return $this->name; - } -} -``` - -:+1: - -
- -## UnusedPublicStaticPropertyRule - -Public property "$%s" is never used outside of its class - -- class: [`Symplify\PHPStanRules\Rules\DeadCode\UnusedPublicStaticPropertyRule`](../src/Rules/DeadCode/UnusedPublicStaticPropertyRule.php) - -```php -final class ResultProvider -{ - public static $some; - - public function getSome() - { - return self::$some; - } -} -``` - -:x: - -
- -```php -final class ResultProvider -{ - private static $some; - - public function getSome() - { - return self::$some; - } -} -``` - -:+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: - -
- -## ValueObjectOverArrayShapeRule - -Instead of array shape, use value object with specific types in constructor and getters - -- class: [`Symplify\PHPStanRules\Rules\Explicit\ValueObjectOverArrayShapeRule`](../src/Rules/Explicit/ValueObjectOverArrayShapeRule.php) - -```php -/** - * @return array{line: int} - */ -function createConfiguration() -{ - return ['line' => 100]; -} -``` - -:x: - -
- -```php -function createConfiguration() -{ - return new Configuration(100); -} - -final class Configuration -{ - public function __construct( - private int $line - ) { - } - - public function getLine(): int - { - return $this->line; - } -} -``` - -:+1: - -
diff --git a/ecs.php b/ecs.php new file mode 100644 index 00000000..7a5dab64 --- /dev/null +++ b/ecs.php @@ -0,0 +1,18 @@ +withPaths([ + __DIR__ . '/config', + __DIR__ . '/src', + __DIR__ . '/tests', + ]) + ->withRootFiles() + ->withPreparedSets(psr12: true, common: true) + ->withSkip([ + '*/Source/*', + '*/Fixture/*', + ]); diff --git a/full-tool-build.sh b/full-tool-build.sh new file mode 100644 index 00000000..a2b95d50 --- /dev/null +++ b/full-tool-build.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +# add patches +composer install --ansi + +# but skip dev dependencies +composer update --no-dev --ansi + +# remove tests and useless files, to make downgraded, scoped and deployed codebase as small as possible +rm -rf tests + +# downgrade with rector +mkdir rector-local +composer require rector/rector --working-dir rector-local +rector-local/vendor/bin/rector process bin src vendor --config build/rector-downgrade-php-72.php --ansi diff --git a/packages-tests/CognitiveComplexity/AstCognitiveComplexityAnalyzer/AstCognitiveComplexityAnalyzerTest.php b/packages-tests/CognitiveComplexity/AstCognitiveComplexityAnalyzer/AstCognitiveComplexityAnalyzerTest.php deleted file mode 100644 index 89923823..00000000 --- a/packages-tests/CognitiveComplexity/AstCognitiveComplexityAnalyzer/AstCognitiveComplexityAnalyzerTest.php +++ /dev/null @@ -1,80 +0,0 @@ -create($tempFile, [__DIR__ . '/config/configured_service.neon'], []); - - $this->astCognitiveComplexityAnalyzer = $container->getByType(AstCognitiveComplexityAnalyzer::class); - } - - /** - * @dataProvider provideTokensAndExpectedCognitiveComplexity() - */ - public function test(SmartFileInfo $fixtureFileInfo): void - { - $inputAndExpected = StaticFixtureSplitter::splitFileInfoToInputAndExpected($fixtureFileInfo); - - $functionLike = $this->parseFileToFirstFunctionLike($inputAndExpected->getInput()); - $cognitiveComplexity = $this->astCognitiveComplexityAnalyzer->analyzeFunctionLike($functionLike); - - $this->assertSame((int) $inputAndExpected->getExpected(), $cognitiveComplexity); - } - - /** - * Here are tested all examples from https://www.sonarsource.com/docs/CognitiveComplexity.pdf - * - * @return Iterator - */ - public function provideTokensAndExpectedCognitiveComplexity(): Iterator - { - return StaticFixtureFinder::yieldDirectory(__DIR__ . '/Source'); - } - - private function parseFileToFirstFunctionLike(string $fileContent): ClassMethod | Function_ - { - $parserFactory = new ParserFactory(); - $parser = $parserFactory->create(ParserFactory::ONLY_PHP7); - $nodes = $parser->parse($fileContent); - - $nodeFinder = new NodeFinder(); - $firstFunctionlike = $nodeFinder->findFirst( - (array) $nodes, - static fn (Node $node): bool => $node instanceof ClassMethod || $node instanceof Function_ - ); - - if ($firstFunctionlike instanceof ClassMethod) { - return $firstFunctionlike; - } - - if ($firstFunctionlike instanceof Function_) { - return $firstFunctionlike; - } - - throw new ShouldNotHappenException(); - } -} diff --git a/packages-tests/CognitiveComplexity/AstCognitiveComplexityAnalyzer/Source/function.php.inc b/packages-tests/CognitiveComplexity/AstCognitiveComplexityAnalyzer/Source/function.php.inc deleted file mode 100644 index 762df229..00000000 --- a/packages-tests/CognitiveComplexity/AstCognitiveComplexityAnalyzer/Source/function.php.inc +++ /dev/null @@ -1,19 +0,0 @@ -create($tempFile, [__DIR__ . '/config/configured_service.neon'], []); - - $this->compositionOverInheritanceAnalyzer = $container->getByType(CompositionOverInheritanceAnalyzer::class); - } - - /** - * @dataProvider provideTokensAndExpectedCognitiveComplexity() - */ - public function test(SmartFileInfo $fixtureFileInfo): void - { - $inputAndExpected = StaticFixtureSplitter::splitFileInfoToInputAndExpected($fixtureFileInfo); - - $classLike = $this->parseFileToFirstClass($inputAndExpected->getInput()); - $cognitiveComplexity = $this->compositionOverInheritanceAnalyzer->analyzeClassLike($classLike); - - $this->assertSame((int) $inputAndExpected->getExpected(), $cognitiveComplexity); - } - - /** - * Here are tested all examples from https://www.sonarsource.com/docs/CognitiveComplexity.pdf - * - * @return Iterator - */ - public function provideTokensAndExpectedCognitiveComplexity(): Iterator - { - return StaticFixtureFinder::yieldDirectory(__DIR__ . '/Source'); - } - - private function parseFileToFirstClass(string $fileContent): Class_ - { - $parserFactory = new ParserFactory(); - $parser = $parserFactory->create(ParserFactory::ONLY_PHP7); - $nodes = $parser->parse($fileContent); - - $nodeFinder = new NodeFinder(); - $firstClass = $nodeFinder->findFirst((array) $nodes, static fn (Node $node): bool => $node instanceof Class_); - - if (! $firstClass instanceof Class_) { - throw new ShouldNotHappenException(); - } - - return $firstClass; - } -} diff --git a/packages-tests/CognitiveComplexity/CompositionOverInheritanceAnalyzer/Source/class.php.inc b/packages-tests/CognitiveComplexity/CompositionOverInheritanceAnalyzer/Source/class.php.inc deleted file mode 100644 index e59daf41..00000000 --- a/packages-tests/CognitiveComplexity/CompositionOverInheritanceAnalyzer/Source/class.php.inc +++ /dev/null @@ -1,8 +0,0 @@ - - */ -final class ClassLikeCognitiveComplexityRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideDataForTest() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function test(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideDataForTest(): Iterator - { - $errorMessage = sprintf(ClassLikeCognitiveComplexityRule::ERROR_MESSAGE, 54, 50); - yield [__DIR__ . '/Fixture/ClassWithManyComplexMethods.php', [[$errorMessage, 7]]]; - - $errorMessage = sprintf(ClassLikeCognitiveComplexityRule::ERROR_MESSAGE, 9, 5); - yield [__DIR__ . '/Fixture/SimpleCommand.php', [[$errorMessage, 9]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(ClassLikeCognitiveComplexityRule::class); - } -} diff --git a/packages-tests/CognitiveComplexity/Rules/ClassLikeCognitiveComplexityRule/ClassLikeCompositionOverInheritanceRuleTest.php b/packages-tests/CognitiveComplexity/Rules/ClassLikeCognitiveComplexityRule/ClassLikeCompositionOverInheritanceRuleTest.php deleted file mode 100644 index 8398e867..00000000 --- a/packages-tests/CognitiveComplexity/Rules/ClassLikeCognitiveComplexityRule/ClassLikeCompositionOverInheritanceRuleTest.php +++ /dev/null @@ -1,50 +0,0 @@ - - */ -final class ClassLikeCompositionOverInheritanceRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideDataForTest() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function test(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideDataForTest(): Iterator - { - $errorMessage = sprintf(ClassLikeCognitiveComplexityRule::ERROR_MESSAGE, 54, 50); - yield [__DIR__ . '/Fixture/ClassWithManyComplexMethods.php', [[$errorMessage, 7]]]; - - $errorMessage = sprintf(ClassLikeCognitiveComplexityRule::ERROR_MESSAGE, 34, 5); - yield [__DIR__ . '/Fixture/SimpleCommand.php', [[$errorMessage, 9]]]; - - $errorMessage = sprintf(ClassLikeCognitiveComplexityRule::ERROR_MESSAGE, 44, 5); - yield [__DIR__ . '/Fixture/NonFinalClass.php', [[$errorMessage, 9]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_composition_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(ClassLikeCognitiveComplexityRule::class); - } -} diff --git a/packages-tests/CognitiveComplexity/Rules/ClassLikeCognitiveComplexityRule/Fixture/ClassWithManyComplexMethods.php b/packages-tests/CognitiveComplexity/Rules/ClassLikeCognitiveComplexityRule/Fixture/ClassWithManyComplexMethods.php deleted file mode 100644 index 5ddd9be5..00000000 --- a/packages-tests/CognitiveComplexity/Rules/ClassLikeCognitiveComplexityRule/Fixture/ClassWithManyComplexMethods.php +++ /dev/null @@ -1,98 +0,0 @@ -livestreamVideos as $livestreamVideo) { // operation: +1 - if ($livestreamVideo->getSlug() !== $slug) { // operation: +1, nesting: +1 - continue; - } - - return $livestreamVideo; // 1 - } - - $recodedEvents = array_merge($this->recordedMeetups, $this->recordedConferences); - - foreach ($recodedEvents as $recodedEvent) { // operation: +1 - $videos = $recodedEvent->getVideos(); - foreach ($videos as $video) { // operation: +1, nesting: +1 - if ($video->getSlug() !== $slug) { // operation: +1, nesting: +2 - continue; - } - - return $video; - } - } - - throw new VideoNotFoundException($slug); - } -} diff --git a/packages-tests/CognitiveComplexity/Rules/FunctionLikeCognitiveComplexityRule/Fixture/function.php.inc b/packages-tests/CognitiveComplexity/Rules/FunctionLikeCognitiveComplexityRule/Fixture/function.php.inc deleted file mode 100644 index 193bc0b7..00000000 --- a/packages-tests/CognitiveComplexity/Rules/FunctionLikeCognitiveComplexityRule/Fixture/function.php.inc +++ /dev/null @@ -1,18 +0,0 @@ - - */ -final class FunctionLikeCognitiveComplexityRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideDataForTest() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function test(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideDataForTest(): Iterator - { - $errorMessage = sprintf(FunctionLikeCognitiveComplexityRule::ERROR_MESSAGE, 'someFunction()', 9, 8); - yield [__DIR__ . '/Fixture/function.php.inc', [[$errorMessage, 3]]]; - - $errorMessage = sprintf( - FunctionLikeCognitiveComplexityRule::ERROR_MESSAGE, - ClassMethodOverComplicated::class . '::someMethod()', - 9, - 8 - ); - yield [__DIR__ . '/Fixture/ClassMethodOverComplicated.php', [[$errorMessage, 7]]]; - - $errorMessage = sprintf( - FunctionLikeCognitiveComplexityRule::ERROR_MESSAGE, - VideoRepository::class . '::findBySlug()', - 9, - 8 - ); - yield [__DIR__ . '/Fixture/VideoRepository.php', [[$errorMessage, 12]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(FunctionLikeCognitiveComplexityRule::class); - } -} diff --git a/packages-tests/CognitiveComplexity/Rules/FunctionLikeCognitiveComplexityRule/config/configured_rule.neon b/packages-tests/CognitiveComplexity/Rules/FunctionLikeCognitiveComplexityRule/config/configured_rule.neon deleted file mode 100644 index beb2ec53..00000000 --- a/packages-tests/CognitiveComplexity/Rules/FunctionLikeCognitiveComplexityRule/config/configured_rule.neon +++ /dev/null @@ -1,16 +0,0 @@ -includes: - - ../../../../../config/packages/cognitive-complexity/cognitive-complexity-services.neon - - ../../../../../tests/config/included_services.neon - -services: - - - class: Symplify\PHPStanRules\CognitiveComplexity\Rules\FunctionLikeCognitiveComplexityRule - tags: [phpstan.rules.rule] - arguments: - maxMethodCognitiveComplexity: 8 - - - - class: Symplify\PHPStanRules\CognitiveComplexity\Rules\ClassLikeCognitiveComplexityRule - tags: [phpstan.rules.rule] - arguments: - maxClassCognitiveComplexity: 50 diff --git a/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/DibiMaskMatchesVariableTypeRuleTest.php b/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/DibiMaskMatchesVariableTypeRuleTest.php deleted file mode 100644 index 36844597..00000000 --- a/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/DibiMaskMatchesVariableTypeRuleTest.php +++ /dev/null @@ -1,61 +0,0 @@ - - */ -final class DibiMaskMatchesVariableTypeRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - $errorMessage = sprintf(DibiMaskMatchesVariableTypeRule::ERROR_MESSAGE, '%v', 'string', 'array'); - yield [__DIR__ . '/Fixture/InvalidType.php', [[$errorMessage, 13]]]; - - $errorMessage = sprintf(DibiMaskMatchesVariableTypeRule::ERROR_MESSAGE, '%in', 'string', 'array'); - yield [__DIR__ . '/Fixture/InvalidAssignType.php', [[$errorMessage, 12]]]; - - yield [__DIR__ . '/Fixture/InvalidArray.php', [[$errorMessage, 12]]]; - - yield [__DIR__ . '/Fixture/NotNullableArray.php', [[$errorMessage, 13]]]; - - yield [__DIR__ . '/Fixture/SkipValidAssignType.php', []]; - yield [__DIR__ . '/Fixture/SkipValidArray.php', []]; - yield [__DIR__ . '/Fixture/SkipMatchingType.php', []]; - - yield [__DIR__ . '/Fixture/SkipMaskNonDibi.php', []]; - yield [__DIR__ . '/Fixture/SkipNullableArray.php', []]; - - yield [__DIR__ . '/Fixture/SkipArrayUnionArray.php', []]; - yield [__DIR__ . '/Fixture/SkipValidJustUnionType.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(DibiMaskMatchesVariableTypeRule::class); - } -} diff --git a/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/Fixture/InvalidArray.php b/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/Fixture/InvalidArray.php deleted file mode 100644 index 10bf4757..00000000 --- a/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/Fixture/InvalidArray.php +++ /dev/null @@ -1,17 +0,0 @@ - 'string', - ]; - - return $params; - } -} diff --git a/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/Fixture/InvalidAssignType.php b/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/Fixture/InvalidAssignType.php deleted file mode 100644 index 55e44d86..00000000 --- a/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/Fixture/InvalidAssignType.php +++ /dev/null @@ -1,16 +0,0 @@ -query('INSERT INTO table %v', $string); - } -} diff --git a/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/Fixture/NotNullableArray.php b/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/Fixture/NotNullableArray.php deleted file mode 100644 index 62393f4d..00000000 --- a/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/Fixture/NotNullableArray.php +++ /dev/null @@ -1,23 +0,0 @@ -getIds() !== null) { - $params['i%in'] = 'string'; - } - - return $params; - } - - public function getIds(): array|null - { - return []; - } -} diff --git a/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/Fixture/SkipArrayUnionArray.php b/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/Fixture/SkipArrayUnionArray.php deleted file mode 100644 index 2056153e..00000000 --- a/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/Fixture/SkipArrayUnionArray.php +++ /dev/null @@ -1,32 +0,0 @@ - $userIds, - ]; - } - if ($ids !== null) { - $params = [ - 'id%in' => $ids, - ]; - } - - return $this->db->query('SELECT [id], [user_id] FROM [...] WHERE %and', $params); - } -} diff --git a/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/Fixture/SkipMaskNonDibi.php b/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/Fixture/SkipMaskNonDibi.php deleted file mode 100644 index 303a2670..00000000 --- a/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/Fixture/SkipMaskNonDibi.php +++ /dev/null @@ -1,15 +0,0 @@ -query('INSERT INTO table %ve', $string); - } -} diff --git a/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/Fixture/SkipMatchingType.php b/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/Fixture/SkipMatchingType.php deleted file mode 100644 index 4e3f607d..00000000 --- a/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/Fixture/SkipMatchingType.php +++ /dev/null @@ -1,16 +0,0 @@ - 'hello', - 'b' => true, - ]; - - $connection->query('INSERT INTO table %v', $arr); - } -} diff --git a/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/Fixture/SkipNullableArray.php b/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/Fixture/SkipNullableArray.php deleted file mode 100644 index b5902f6c..00000000 --- a/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/Fixture/SkipNullableArray.php +++ /dev/null @@ -1,23 +0,0 @@ -getIds() !== null) { - $params['i%in'] = $this->getIds(); - } - - return $params; - } - - public function getIds(): array|null - { - return []; - } -} diff --git a/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/Fixture/SkipValidArray.php b/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/Fixture/SkipValidArray.php deleted file mode 100644 index 525c7345..00000000 --- a/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/Fixture/SkipValidArray.php +++ /dev/null @@ -1,17 +0,0 @@ - ['string'], - ]; - - return $params; - } -} diff --git a/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/Fixture/SkipValidAssignType.php b/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/Fixture/SkipValidAssignType.php deleted file mode 100644 index 72121d7b..00000000 --- a/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/Fixture/SkipValidAssignType.php +++ /dev/null @@ -1,16 +0,0 @@ -findBy([ - 'i2%in' => $itemIds, - ]) : []; - } - - private function findBy($criteria) - { - } -} diff --git a/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/config/configured_rule.neon b/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/config/configured_rule.neon deleted file mode 100644 index 3fa31be5..00000000 --- a/packages-tests/Nette/Rules/DibiMaskMatchesVariableTypeRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/config_tests.neon - -rules: - - Symplify\PHPStanRules\Nette\Rules\DibiMaskMatchesVariableTypeRule diff --git a/packages-tests/Nette/Rules/ForbiddenNetteInjectOverrideRule/Fixture/OverrideParentInject.php b/packages-tests/Nette/Rules/ForbiddenNetteInjectOverrideRule/Fixture/OverrideParentInject.php deleted file mode 100644 index e86a9250..00000000 --- a/packages-tests/Nette/Rules/ForbiddenNetteInjectOverrideRule/Fixture/OverrideParentInject.php +++ /dev/null @@ -1,16 +0,0 @@ -someParentType = $anotherType; - } -} diff --git a/packages-tests/Nette/Rules/ForbiddenNetteInjectOverrideRule/Fixture/OverrideParentInjectAttribute.php b/packages-tests/Nette/Rules/ForbiddenNetteInjectOverrideRule/Fixture/OverrideParentInjectAttribute.php deleted file mode 100644 index 27f2d5f3..00000000 --- a/packages-tests/Nette/Rules/ForbiddenNetteInjectOverrideRule/Fixture/OverrideParentInjectAttribute.php +++ /dev/null @@ -1,15 +0,0 @@ -someAttributeType = $anotherType; - } -} diff --git a/packages-tests/Nette/Rules/ForbiddenNetteInjectOverrideRule/Fixture/OverrideParentInjectClassMethodAttribute.php b/packages-tests/Nette/Rules/ForbiddenNetteInjectOverrideRule/Fixture/OverrideParentInjectClassMethodAttribute.php deleted file mode 100644 index b43a5481..00000000 --- a/packages-tests/Nette/Rules/ForbiddenNetteInjectOverrideRule/Fixture/OverrideParentInjectClassMethodAttribute.php +++ /dev/null @@ -1,16 +0,0 @@ -someType = $anotherType; - } -} diff --git a/packages-tests/Nette/Rules/ForbiddenNetteInjectOverrideRule/Fixture/OverrideParentInjectOutsideConstructor.php b/packages-tests/Nette/Rules/ForbiddenNetteInjectOverrideRule/Fixture/OverrideParentInjectOutsideConstructor.php deleted file mode 100644 index f39342c2..00000000 --- a/packages-tests/Nette/Rules/ForbiddenNetteInjectOverrideRule/Fixture/OverrideParentInjectOutsideConstructor.php +++ /dev/null @@ -1,15 +0,0 @@ -someType = $anotherType; - } -} diff --git a/packages-tests/Nette/Rules/ForbiddenNetteInjectOverrideRule/Fixture/SkipCurrentMethodInject.php b/packages-tests/Nette/Rules/ForbiddenNetteInjectOverrideRule/Fixture/SkipCurrentMethodInject.php deleted file mode 100644 index 062590da..00000000 --- a/packages-tests/Nette/Rules/ForbiddenNetteInjectOverrideRule/Fixture/SkipCurrentMethodInject.php +++ /dev/null @@ -1,18 +0,0 @@ -someType = $anotherType; - } -} diff --git a/packages-tests/Nette/Rules/ForbiddenNetteInjectOverrideRule/Fixture/SkipNonInjectAssign.php b/packages-tests/Nette/Rules/ForbiddenNetteInjectOverrideRule/Fixture/SkipNonInjectAssign.php deleted file mode 100644 index e2e60e7f..00000000 --- a/packages-tests/Nette/Rules/ForbiddenNetteInjectOverrideRule/Fixture/SkipNonInjectAssign.php +++ /dev/null @@ -1,22 +0,0 @@ -someType = $anotherType; - } -} diff --git a/packages-tests/Nette/Rules/ForbiddenNetteInjectOverrideRule/Fixture/SkipParentAnnotatedProperty.php b/packages-tests/Nette/Rules/ForbiddenNetteInjectOverrideRule/Fixture/SkipParentAnnotatedProperty.php deleted file mode 100644 index fb043cd9..00000000 --- a/packages-tests/Nette/Rules/ForbiddenNetteInjectOverrideRule/Fixture/SkipParentAnnotatedProperty.php +++ /dev/null @@ -1,15 +0,0 @@ -payload->user = $name; - } -} diff --git a/packages-tests/Nette/Rules/ForbiddenNetteInjectOverrideRule/ForbiddenNetteInjectOverrideRuleTest.php b/packages-tests/Nette/Rules/ForbiddenNetteInjectOverrideRule/ForbiddenNetteInjectOverrideRuleTest.php deleted file mode 100644 index 360b6e76..00000000 --- a/packages-tests/Nette/Rules/ForbiddenNetteInjectOverrideRule/ForbiddenNetteInjectOverrideRuleTest.php +++ /dev/null @@ -1,60 +0,0 @@ - - */ -final class ForbiddenNetteInjectOverrideRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [ - __DIR__ . '/Fixture/OverrideParentInject.php', - [[ForbiddenNetteInjectOverrideRule::ERROR_MESSAGE, 14]], - ]; - - yield [ - __DIR__ . '/Fixture/OverrideParentInjectAttribute.php', - [[ForbiddenNetteInjectOverrideRule::ERROR_MESSAGE, 13]], - ]; - - yield [ - __DIR__ . '/Fixture/OverrideParentInjectClassMethodAttribute.php', - [[ForbiddenNetteInjectOverrideRule::ERROR_MESSAGE, 14]], - ]; - - yield [__DIR__ . '/Fixture/SkipNonInjectAssign.php', []]; - yield [__DIR__ . '/Fixture/SkipCurrentMethodInject.php', []]; - yield [__DIR__ . '/Fixture/SkipParentAnnotatedProperty.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(ForbiddenNetteInjectOverrideRule::class); - } -} diff --git a/packages-tests/Nette/Rules/ForbiddenNetteInjectOverrideRule/Source/AbstractInjectParentClass.php b/packages-tests/Nette/Rules/ForbiddenNetteInjectOverrideRule/Source/AbstractInjectParentClass.php deleted file mode 100644 index b7bd5082..00000000 --- a/packages-tests/Nette/Rules/ForbiddenNetteInjectOverrideRule/Source/AbstractInjectParentClass.php +++ /dev/null @@ -1,20 +0,0 @@ -someType = $someType; - } -} diff --git a/packages-tests/Nette/Rules/ForbiddenNetteInjectOverrideRule/Source/AbstractUnrelatedClass.php b/packages-tests/Nette/Rules/ForbiddenNetteInjectOverrideRule/Source/AbstractUnrelatedClass.php deleted file mode 100644 index c52493bc..00000000 --- a/packages-tests/Nette/Rules/ForbiddenNetteInjectOverrideRule/Source/AbstractUnrelatedClass.php +++ /dev/null @@ -1,9 +0,0 @@ - - */ -final class NoInjectOnFinalRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorsWithLines - */ - public function testRule(string $filePath, array $expectedErrorsWithLines): void - { - $this->analyse([$filePath], $expectedErrorsWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipInjectOnNonAbstract.php', []]; - yield [__DIR__ . '/Fixture/SkipAbstractClass.php', []]; - - yield [ - __DIR__ . '/Fixture/InjectOnNonAbstractWithAbstractParent.php', - [[NoInjectOnFinalRule::ERROR_MESSAGE, 15]], - ]; - - yield [__DIR__ . '/Fixture/InjectAttributeWithParent.php', [[NoInjectOnFinalRule::ERROR_MESSAGE, 15]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoInjectOnFinalRule::class); - } -} diff --git a/packages-tests/Nette/Rules/NoInjectOnFinalRule/Source/SomeType.php b/packages-tests/Nette/Rules/NoInjectOnFinalRule/Source/SomeType.php deleted file mode 100644 index aa6d27be..00000000 --- a/packages-tests/Nette/Rules/NoInjectOnFinalRule/Source/SomeType.php +++ /dev/null @@ -1,9 +0,0 @@ - - */ -final class NoNetteArrayAccessInControlRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipNoArrayDimFetch.php', []]; - yield [__DIR__ . '/Fixture/SkipDimFetchOutsideNette.php', []]; - - yield [__DIR__ . '/Fixture/ArrayDimFetchInForm.php', [ - [NoNetteArrayAccessInControlRule::ERROR_MESSAGE, 13], - ]]; - - yield [__DIR__ . '/Fixture/ArrayDimFetchInPresenter.php', [ - [NoNetteArrayAccessInControlRule::ERROR_MESSAGE, 13], - ]]; - - yield [__DIR__ . '/Fixture/ArrayDimFetchInControl.php', [ - [NoNetteArrayAccessInControlRule::ERROR_MESSAGE, 13], - ]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoNetteArrayAccessInControlRule::class); - } -} diff --git a/packages-tests/Nette/Rules/NoNetteArrayAccessInControlRule/config/configured_rule.neon b/packages-tests/Nette/Rules/NoNetteArrayAccessInControlRule/config/configured_rule.neon deleted file mode 100644 index 6120457d..00000000 --- a/packages-tests/Nette/Rules/NoNetteArrayAccessInControlRule/config/configured_rule.neon +++ /dev/null @@ -1,6 +0,0 @@ -includes: - - ../../../../../tests/config/included_services.neon - - ../../../../../config/packages/nette/services.neon - -rules: - - Symplify\PHPStanRules\Nette\Rules\NoNetteArrayAccessInControlRule diff --git a/packages-tests/Nette/Rules/NoNetteDoubleTemplateAssignRule/Fixture/DoubleAssignPresenter.php b/packages-tests/Nette/Rules/NoNetteDoubleTemplateAssignRule/Fixture/DoubleAssignPresenter.php deleted file mode 100644 index 4c84fb5d..00000000 --- a/packages-tests/Nette/Rules/NoNetteDoubleTemplateAssignRule/Fixture/DoubleAssignPresenter.php +++ /dev/null @@ -1,16 +0,0 @@ -template->key = '1000'; - $this->template->key = '100'; - } -} diff --git a/packages-tests/Nette/Rules/NoNetteDoubleTemplateAssignRule/Fixture/SkipIfElseAssign.php b/packages-tests/Nette/Rules/NoNetteDoubleTemplateAssignRule/Fixture/SkipIfElseAssign.php deleted file mode 100644 index 56529141..00000000 --- a/packages-tests/Nette/Rules/NoNetteDoubleTemplateAssignRule/Fixture/SkipIfElseAssign.php +++ /dev/null @@ -1,19 +0,0 @@ -template->key = '1000'; - } else { - $this->template->key = '100'; - } - } -} diff --git a/packages-tests/Nette/Rules/NoNetteDoubleTemplateAssignRule/Fixture/SkipNoPresenter.php b/packages-tests/Nette/Rules/NoNetteDoubleTemplateAssignRule/Fixture/SkipNoPresenter.php deleted file mode 100644 index 40b297b3..00000000 --- a/packages-tests/Nette/Rules/NoNetteDoubleTemplateAssignRule/Fixture/SkipNoPresenter.php +++ /dev/null @@ -1,14 +0,0 @@ -template->key = '1000'; - $this->template->key = '100'; - } -} diff --git a/packages-tests/Nette/Rules/NoNetteDoubleTemplateAssignRule/Fixture/SkipUniqueAssignPresenter.php b/packages-tests/Nette/Rules/NoNetteDoubleTemplateAssignRule/Fixture/SkipUniqueAssignPresenter.php deleted file mode 100644 index ceb623d8..00000000 --- a/packages-tests/Nette/Rules/NoNetteDoubleTemplateAssignRule/Fixture/SkipUniqueAssignPresenter.php +++ /dev/null @@ -1,16 +0,0 @@ -template->key = '1000'; - $this->template->anotherKey = '100'; - } -} diff --git a/packages-tests/Nette/Rules/NoNetteDoubleTemplateAssignRule/NoNetteDoubleTemplateAssignRuleTest.php b/packages-tests/Nette/Rules/NoNetteDoubleTemplateAssignRule/NoNetteDoubleTemplateAssignRuleTest.php deleted file mode 100644 index a4e91c1a..00000000 --- a/packages-tests/Nette/Rules/NoNetteDoubleTemplateAssignRule/NoNetteDoubleTemplateAssignRuleTest.php +++ /dev/null @@ -1,48 +0,0 @@ - - */ -final class NoNetteDoubleTemplateAssignRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipIfElseAssign.php', []]; - yield [__DIR__ . '/Fixture/SkipUniqueAssignPresenter.php', []]; - yield [__DIR__ . '/Fixture/SkipNoPresenter.php', []]; - - $errorMessage = sprintf(NoNetteDoubleTemplateAssignRule::ERROR_MESSAGE, 'key'); - yield [__DIR__ . '/Fixture/DoubleAssignPresenter.php', [[$errorMessage, 11]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoNetteDoubleTemplateAssignRule::class); - } -} diff --git a/packages-tests/Nette/Rules/NoNetteDoubleTemplateAssignRule/config/configured_rule.neon b/packages-tests/Nette/Rules/NoNetteDoubleTemplateAssignRule/config/configured_rule.neon deleted file mode 100644 index c8040dfa..00000000 --- a/packages-tests/Nette/Rules/NoNetteDoubleTemplateAssignRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/config_tests.neon - -rules: - - Symplify\PHPStanRules\Nette\Rules\NoNetteDoubleTemplateAssignRule diff --git a/packages-tests/Nette/Rules/NoNetteInjectAndConstructorRule/Fixture/InjectAttributePropertyAndConstructor.php b/packages-tests/Nette/Rules/NoNetteInjectAndConstructorRule/Fixture/InjectAttributePropertyAndConstructor.php deleted file mode 100644 index a9ec9d32..00000000 --- a/packages-tests/Nette/Rules/NoNetteInjectAndConstructorRule/Fixture/InjectAttributePropertyAndConstructor.php +++ /dev/null @@ -1,18 +0,0 @@ -name = 'hey'; - } -} diff --git a/packages-tests/Nette/Rules/NoNetteInjectAndConstructorRule/Fixture/InjectMethodAndConstructor.php b/packages-tests/Nette/Rules/NoNetteInjectAndConstructorRule/Fixture/InjectMethodAndConstructor.php deleted file mode 100644 index c98d5da4..00000000 --- a/packages-tests/Nette/Rules/NoNetteInjectAndConstructorRule/Fixture/InjectMethodAndConstructor.php +++ /dev/null @@ -1,23 +0,0 @@ -name = 'hey'; - } - - public function injectAnything() - { - $this->name = 'hey'; - } -} diff --git a/packages-tests/Nette/Rules/NoNetteInjectAndConstructorRule/Fixture/InjectPropertyAndConstructor.php b/packages-tests/Nette/Rules/NoNetteInjectAndConstructorRule/Fixture/InjectPropertyAndConstructor.php deleted file mode 100644 index 49fa0617..00000000 --- a/packages-tests/Nette/Rules/NoNetteInjectAndConstructorRule/Fixture/InjectPropertyAndConstructor.php +++ /dev/null @@ -1,18 +0,0 @@ -name = 'hey'; - } -} diff --git a/packages-tests/Nette/Rules/NoNetteInjectAndConstructorRule/Fixture/SkipAbstract.php b/packages-tests/Nette/Rules/NoNetteInjectAndConstructorRule/Fixture/SkipAbstract.php deleted file mode 100644 index 948787cb..00000000 --- a/packages-tests/Nette/Rules/NoNetteInjectAndConstructorRule/Fixture/SkipAbstract.php +++ /dev/null @@ -1,23 +0,0 @@ -name = 'hey'; - } - - public function injectAnything() - { - $this->name = 'hey'; - } -} diff --git a/packages-tests/Nette/Rules/NoNetteInjectAndConstructorRule/Fixture/SkipOnlyConstructor.php b/packages-tests/Nette/Rules/NoNetteInjectAndConstructorRule/Fixture/SkipOnlyConstructor.php deleted file mode 100644 index 80ed6e14..00000000 --- a/packages-tests/Nette/Rules/NoNetteInjectAndConstructorRule/Fixture/SkipOnlyConstructor.php +++ /dev/null @@ -1,18 +0,0 @@ -name = 'hey'; - } -} diff --git a/packages-tests/Nette/Rules/NoNetteInjectAndConstructorRule/NoNetteInjectAndConstructorRuleTest.php b/packages-tests/Nette/Rules/NoNetteInjectAndConstructorRule/NoNetteInjectAndConstructorRuleTest.php deleted file mode 100644 index 6f32130d..00000000 --- a/packages-tests/Nette/Rules/NoNetteInjectAndConstructorRule/NoNetteInjectAndConstructorRuleTest.php +++ /dev/null @@ -1,56 +0,0 @@ - - */ -final class NoNetteInjectAndConstructorRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipOnlyConstructor.php', []]; - yield [__DIR__ . '/Fixture/SkipAbstract.php', []]; - - yield [__DIR__ . '/Fixture/InjectMethodAndConstructor.php', [ - [NoNetteInjectAndConstructorRule::ERROR_MESSAGE, 7], - ]]; - - yield [__DIR__ . '/Fixture/InjectAttributePropertyAndConstructor.php', [ - [NoNetteInjectAndConstructorRule::ERROR_MESSAGE, 9], - ]]; - - yield [__DIR__ . '/Fixture/InjectPropertyAndConstructor.php', [ - [NoNetteInjectAndConstructorRule::ERROR_MESSAGE, 7], - ]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoNetteInjectAndConstructorRule::class); - } -} diff --git a/packages-tests/Nette/Rules/NoNetteInjectAndConstructorRule/config/configured_rule.neon b/packages-tests/Nette/Rules/NoNetteInjectAndConstructorRule/config/configured_rule.neon deleted file mode 100644 index 0b5c2f29..00000000 --- a/packages-tests/Nette/Rules/NoNetteInjectAndConstructorRule/config/configured_rule.neon +++ /dev/null @@ -1,6 +0,0 @@ -includes: - - ../../../../../tests/config/included_services.neon - - ../../../../../config/packages/nette/services.neon - -rules: - - Symplify\PHPStanRules\Nette\Rules\NoNetteInjectAndConstructorRule diff --git a/packages-tests/Nette/Rules/ValidNetteInjectRule/Fixture/PrivateInject.php b/packages-tests/Nette/Rules/ValidNetteInjectRule/Fixture/PrivateInject.php deleted file mode 100644 index 1b276e78..00000000 --- a/packages-tests/Nette/Rules/ValidNetteInjectRule/Fixture/PrivateInject.php +++ /dev/null @@ -1,14 +0,0 @@ - - */ -final class ValidNetteInjectRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipCorrectInject.php', []]; - yield [__DIR__ . '/Fixture/SkipCorrectInjectAttribute.php', []]; - - yield [__DIR__ . '/Fixture/PrivateInjectMethod.php', [[ValidNetteInjectRule::ERROR_MESSAGE, 12]]]; - yield [__DIR__ . '/Fixture/PrivateInjectAttribute.php', [[ValidNetteInjectRule::ERROR_MESSAGE, 14]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(ValidNetteInjectRule::class); - } -} diff --git a/packages-tests/Nette/Rules/ValidNetteInjectRule/config/configured_rule.neon b/packages-tests/Nette/Rules/ValidNetteInjectRule/config/configured_rule.neon deleted file mode 100644 index 88935a4c..00000000 --- a/packages-tests/Nette/Rules/ValidNetteInjectRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/config_tests.neon - -rules: - - Symplify\PHPStanRules\Nette\Rules\ValidNetteInjectRule diff --git a/packages-tests/Nette/config/config_tests.neon b/packages-tests/Nette/config/config_tests.neon deleted file mode 100644 index 18ed3f09..00000000 --- a/packages-tests/Nette/config/config_tests.neon +++ /dev/null @@ -1,3 +0,0 @@ -includes: - - ../../../tests/config/included_services.neon - - ../../../config/packages/nette/services.neon diff --git a/packages-tests/ObjectCalisthenics/Rules/NoChainMethodCallRule/Fixture/ChainMethodCall.php b/packages-tests/ObjectCalisthenics/Rules/NoChainMethodCallRule/Fixture/ChainMethodCall.php deleted file mode 100644 index 9de33bf3..00000000 --- a/packages-tests/ObjectCalisthenics/Rules/NoChainMethodCallRule/Fixture/ChainMethodCall.php +++ /dev/null @@ -1,13 +0,0 @@ -also()->more(); - } -} diff --git a/packages-tests/ObjectCalisthenics/Rules/NoChainMethodCallRule/Fixture/SkipExtraAllowedClass.php b/packages-tests/ObjectCalisthenics/Rules/NoChainMethodCallRule/Fixture/SkipExtraAllowedClass.php deleted file mode 100644 index 79d4fb3d..00000000 --- a/packages-tests/ObjectCalisthenics/Rules/NoChainMethodCallRule/Fixture/SkipExtraAllowedClass.php +++ /dev/null @@ -1,15 +0,0 @@ -yes()->please()->yes(); - } -} diff --git a/packages-tests/ObjectCalisthenics/Rules/NoChainMethodCallRule/Fixture/SkipNullsafeCalls.php b/packages-tests/ObjectCalisthenics/Rules/NoChainMethodCallRule/Fixture/SkipNullsafeCalls.php deleted file mode 100644 index c63a184a..00000000 --- a/packages-tests/ObjectCalisthenics/Rules/NoChainMethodCallRule/Fixture/SkipNullsafeCalls.php +++ /dev/null @@ -1,15 +0,0 @@ -getClassReflection()?->getName(); - } -} diff --git a/packages-tests/ObjectCalisthenics/Rules/NoChainMethodCallRule/Fixture/SkipSymfonyConfig.php b/packages-tests/ObjectCalisthenics/Rules/NoChainMethodCallRule/Fixture/SkipSymfonyConfig.php deleted file mode 100644 index 61b5bff5..00000000 --- a/packages-tests/ObjectCalisthenics/Rules/NoChainMethodCallRule/Fixture/SkipSymfonyConfig.php +++ /dev/null @@ -1,15 +0,0 @@ -services(); - - $services->defaults() - ->public() - ->autowire(); -}; diff --git a/packages-tests/ObjectCalisthenics/Rules/NoChainMethodCallRule/Fixture/SkipTrinaryLogic.php b/packages-tests/ObjectCalisthenics/Rules/NoChainMethodCallRule/Fixture/SkipTrinaryLogic.php deleted file mode 100644 index ccfeb7dc..00000000 --- a/packages-tests/ObjectCalisthenics/Rules/NoChainMethodCallRule/Fixture/SkipTrinaryLogic.php +++ /dev/null @@ -1,15 +0,0 @@ -isSuperTypeOf(new StringType())->yes(); - } -} diff --git a/packages-tests/ObjectCalisthenics/Rules/NoChainMethodCallRule/NoChainMethodCallRuleTest.php b/packages-tests/ObjectCalisthenics/Rules/NoChainMethodCallRule/NoChainMethodCallRuleTest.php deleted file mode 100644 index 1aa32aae..00000000 --- a/packages-tests/ObjectCalisthenics/Rules/NoChainMethodCallRule/NoChainMethodCallRuleTest.php +++ /dev/null @@ -1,47 +0,0 @@ - - */ -final class NoChainMethodCallRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/ChainMethodCall.php', [[NoChainMethodCallRule::ERROR_MESSAGE, 11]]]; - yield [__DIR__ . '/Fixture/SkipSymfonyConfig.php', []]; - yield [__DIR__ . '/Fixture/SkipExtraAllowedClass.php', []]; - yield [__DIR__ . '/Fixture/SkipTrinaryLogic.php', []]; - yield [__DIR__ . '/Fixture/SkipNullsafeCalls.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/standalone_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoChainMethodCallRule::class); - } -} diff --git a/packages-tests/ObjectCalisthenics/Rules/NoChainMethodCallRule/Source/SomeAllowedFluent.php b/packages-tests/ObjectCalisthenics/Rules/NoChainMethodCallRule/Source/SomeAllowedFluent.php deleted file mode 100644 index e2c86f93..00000000 --- a/packages-tests/ObjectCalisthenics/Rules/NoChainMethodCallRule/Source/SomeAllowedFluent.php +++ /dev/null @@ -1,18 +0,0 @@ - - */ -final class NoShortNameRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipId.php', []]; - - $errorMessage = sprintf(NoShortNameRule::ERROR_MESSAGE, 'em', 3); - $yeErrorMEssage = sprintf(NoShortNameRule::ERROR_MESSAGE, 'YE', 3); - yield [__DIR__ . '/Fixture/ShortNamingClass.php', [[$errorMessage, 9], [$yeErrorMEssage, 11]]]; - - $errorMessage = sprintf(NoShortNameRule::ERROR_MESSAGE, 'n', 3); - yield [__DIR__ . '/Fixture/ShortClosureParam.php', [[$errorMessage, 11]]]; - yield [__DIR__ . '/Fixture/ShortParam.php', [[$errorMessage, 9]]]; - - $errorMessage = sprintf(NoShortNameRule::ERROR_MESSAGE, 'n', 3); - yield [ - __DIR__ . '/Fixture/ShortAssignParameter.php', - [[$errorMessage, 11], [$errorMessage, 13], [$errorMessage, 15]], ]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoShortNameRule::class); - } -} diff --git a/packages-tests/ObjectCalisthenics/Rules/NoShortNameRule/config/configured_rule.neon b/packages-tests/ObjectCalisthenics/Rules/NoShortNameRule/config/configured_rule.neon deleted file mode 100644 index d6dfcdb9..00000000 --- a/packages-tests/ObjectCalisthenics/Rules/NoShortNameRule/config/configured_rule.neon +++ /dev/null @@ -1,11 +0,0 @@ -includes: - - ../../../../../tests/config/included_services.neon - -services: - - - class: Symplify\PHPStanRules\ObjectCalisthenics\Rules\NoShortNameRule - tags: [phpstan.rules.rule] - arguments: - minNameLength: 3 - allowedShortNames: - - id diff --git a/packages-tests/Symfony/Rules/PreventDoubleSetParameterRule/Fixture/DuplicateConstantValue.php b/packages-tests/Symfony/Rules/PreventDoubleSetParameterRule/Fixture/DuplicateConstantValue.php deleted file mode 100644 index f9180407..00000000 --- a/packages-tests/Symfony/Rules/PreventDoubleSetParameterRule/Fixture/DuplicateConstantValue.php +++ /dev/null @@ -1,12 +0,0 @@ -parameters(); - $parameters->set(OptionConstants::NAME, 'b'); - $parameters->set(OptionConstants::NAME, 'c'); -}; diff --git a/packages-tests/Symfony/Rules/PreventDoubleSetParameterRule/Fixture/DuplicateValue.php b/packages-tests/Symfony/Rules/PreventDoubleSetParameterRule/Fixture/DuplicateValue.php deleted file mode 100644 index efffe9be..00000000 --- a/packages-tests/Symfony/Rules/PreventDoubleSetParameterRule/Fixture/DuplicateValue.php +++ /dev/null @@ -1,11 +0,0 @@ -parameters(); - $parameters->set('a', 'b'); - $parameters->set('a', 'c'); -}; \ No newline at end of file diff --git a/packages-tests/Symfony/Rules/PreventDoubleSetParameterRule/Fixture/SkipConfigService.php b/packages-tests/Symfony/Rules/PreventDoubleSetParameterRule/Fixture/SkipConfigService.php deleted file mode 100644 index eb9e60bd..00000000 --- a/packages-tests/Symfony/Rules/PreventDoubleSetParameterRule/Fixture/SkipConfigService.php +++ /dev/null @@ -1,12 +0,0 @@ -services(); - $services->defaults() - ->autowire() - ->public(); -}; diff --git a/packages-tests/Symfony/Rules/PreventDoubleSetParameterRule/Fixture/SkipNoDuplicateValue.php b/packages-tests/Symfony/Rules/PreventDoubleSetParameterRule/Fixture/SkipNoDuplicateValue.php deleted file mode 100644 index ed8436b2..00000000 --- a/packages-tests/Symfony/Rules/PreventDoubleSetParameterRule/Fixture/SkipNoDuplicateValue.php +++ /dev/null @@ -1,11 +0,0 @@ -parameters(); - $parameters->set('a', 'b'); - $parameters->set('b', 'c'); -}; \ No newline at end of file diff --git a/packages-tests/Symfony/Rules/PreventDoubleSetParameterRule/Fixture/SkipOnce.php b/packages-tests/Symfony/Rules/PreventDoubleSetParameterRule/Fixture/SkipOnce.php deleted file mode 100644 index 78f93039..00000000 --- a/packages-tests/Symfony/Rules/PreventDoubleSetParameterRule/Fixture/SkipOnce.php +++ /dev/null @@ -1,10 +0,0 @@ -parameters(); - $parameters->set('a', 'b'); -}; \ No newline at end of file diff --git a/packages-tests/Symfony/Rules/PreventDoubleSetParameterRule/Fixture/SkipeOnlyOneMethodCall.php b/packages-tests/Symfony/Rules/PreventDoubleSetParameterRule/Fixture/SkipeOnlyOneMethodCall.php deleted file mode 100644 index 511bc5e1..00000000 --- a/packages-tests/Symfony/Rules/PreventDoubleSetParameterRule/Fixture/SkipeOnlyOneMethodCall.php +++ /dev/null @@ -1,9 +0,0 @@ -parameters(); -}; \ No newline at end of file diff --git a/packages-tests/Symfony/Rules/PreventDoubleSetParameterRule/PreventDoubleSetParameterRuleTest.php b/packages-tests/Symfony/Rules/PreventDoubleSetParameterRule/PreventDoubleSetParameterRuleTest.php deleted file mode 100644 index 7b755b27..00000000 --- a/packages-tests/Symfony/Rules/PreventDoubleSetParameterRule/PreventDoubleSetParameterRuleTest.php +++ /dev/null @@ -1,49 +0,0 @@ - - */ -final class PreventDoubleSetParameterRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipConfigService.php', []]; - yield [__DIR__ . '/Fixture/SkipeOnlyOneMethodCall.php', []]; - yield [__DIR__ . '/Fixture/SkipOnce.php', []]; - yield [__DIR__ . '/Fixture/SkipNoDuplicateValue.php', []]; - - yield [__DIR__ . '/Fixture/DuplicateValue.php', [[PreventDoubleSetParameterRule::ERROR_MESSAGE, 10]]]; - yield [__DIR__ . '/Fixture/DuplicateConstantValue.php', [[PreventDoubleSetParameterRule::ERROR_MESSAGE, 11]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(PreventDoubleSetParameterRule::class); - } -} diff --git a/packages-tests/Symfony/Rules/PreventDoubleSetParameterRule/Source/OptionConstants.php b/packages-tests/Symfony/Rules/PreventDoubleSetParameterRule/Source/OptionConstants.php deleted file mode 100644 index 8287ba9f..00000000 --- a/packages-tests/Symfony/Rules/PreventDoubleSetParameterRule/Source/OptionConstants.php +++ /dev/null @@ -1,13 +0,0 @@ - - */ -final class RequireInvokableControllerRulePhp80Test extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - /** - * @return Iterator> - */ - public function provideData(): Iterator - { - yield [ - __DIR__ . '/Fixture/MissnamedRouteAttributeController.php', - [[RequireInvokableControllerRule::ERROR_MESSAGE, 12]], - ]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(RequireInvokableControllerRule::class); - } -} diff --git a/packages-tests/Symfony/Rules/RequireInvokableControllerRule/RequireInvokableControllerRuleTest.php b/packages-tests/Symfony/Rules/RequireInvokableControllerRule/RequireInvokableControllerRuleTest.php deleted file mode 100644 index 633791ef..00000000 --- a/packages-tests/Symfony/Rules/RequireInvokableControllerRule/RequireInvokableControllerRuleTest.php +++ /dev/null @@ -1,46 +0,0 @@ - - */ -final class RequireInvokableControllerRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipInvokableController.php', []]; - yield [__DIR__ . '/Fixture/SkipRandomPublicMethodController.php', []]; - - yield [__DIR__ . '/Fixture/MissnamedController.php', [[RequireInvokableControllerRule::ERROR_MESSAGE, 15]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(RequireInvokableControllerRule::class); - } -} diff --git a/packages-tests/Symfony/Rules/RequireInvokableControllerRule/config/configured_rule.neon b/packages-tests/Symfony/Rules/RequireInvokableControllerRule/config/configured_rule.neon deleted file mode 100644 index 336e8b30..00000000 --- a/packages-tests/Symfony/Rules/RequireInvokableControllerRule/config/configured_rule.neon +++ /dev/null @@ -1,6 +0,0 @@ -includes: - - ../../../../../tests/config/included_services.neon - - ../../../../../config/packages/symfony/services.neon - -rules: - - Symplify\PHPStanRules\Symfony\Rules\RequireInvokableControllerRule diff --git a/packages-tests/Symfony/Rules/RequireNamedCommandRule/Fixture/MissingNameCommand.php b/packages-tests/Symfony/Rules/RequireNamedCommandRule/Fixture/MissingNameCommand.php deleted file mode 100644 index 2a73b76f..00000000 --- a/packages-tests/Symfony/Rules/RequireNamedCommandRule/Fixture/MissingNameCommand.php +++ /dev/null @@ -1,14 +0,0 @@ -setName('named'); - } -} diff --git a/packages-tests/Symfony/Rules/RequireNamedCommandRule/RequireNamedCommandRuleTest.php b/packages-tests/Symfony/Rules/RequireNamedCommandRule/RequireNamedCommandRuleTest.php deleted file mode 100644 index 91bfeb21..00000000 --- a/packages-tests/Symfony/Rules/RequireNamedCommandRule/RequireNamedCommandRuleTest.php +++ /dev/null @@ -1,51 +0,0 @@ - - */ -final class RequireNamedCommandRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipNamedCommand.php', []]; - yield [__DIR__ . '/Fixture/SkipAbstractMissingNameCommand.php', []]; - yield [__DIR__ . '/Fixture/SkipAttributeNamedCommand.php', []]; - - yield [__DIR__ . '/Fixture/MissingNameCommand.php', [[RequireNamedCommandRule::ERROR_MESSAGE, 9]]]; - yield [ - __DIR__ . '/Fixture/MissingNameCommandWithoutConfigureMethod.php', - [[RequireNamedCommandRule::ERROR_MESSAGE, 9]], - ]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(RequireNamedCommandRule::class); - } -} diff --git a/packages-tests/Symfony/Rules/RequireNamedCommandRule/config/configured_rule.neon b/packages-tests/Symfony/Rules/RequireNamedCommandRule/config/configured_rule.neon deleted file mode 100644 index 8d10a766..00000000 --- a/packages-tests/Symfony/Rules/RequireNamedCommandRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../../../tests/config/included_services.neon - -rules: - - Symplify\PHPStanRules\Symfony\Rules\RequireNamedCommandRule diff --git a/packages-tests/Symfony/Rules/RequireNativeArraySymfonyRenderCallRule/Fixture/ParameterAsSecondArgument.php b/packages-tests/Symfony/Rules/RequireNativeArraySymfonyRenderCallRule/Fixture/ParameterAsSecondArgument.php deleted file mode 100644 index 04561989..00000000 --- a/packages-tests/Symfony/Rules/RequireNativeArraySymfonyRenderCallRule/Fixture/ParameterAsSecondArgument.php +++ /dev/null @@ -1,19 +0,0 @@ -render('...', $parameters); - } -} diff --git a/packages-tests/Symfony/Rules/RequireNativeArraySymfonyRenderCallRule/Fixture/SkipCorrectControllerRender.php b/packages-tests/Symfony/Rules/RequireNativeArraySymfonyRenderCallRule/Fixture/SkipCorrectControllerRender.php deleted file mode 100644 index faae5349..00000000 --- a/packages-tests/Symfony/Rules/RequireNativeArraySymfonyRenderCallRule/Fixture/SkipCorrectControllerRender.php +++ /dev/null @@ -1,17 +0,0 @@ -render('...', [ - 'name' => 'John' - ]); - } -} diff --git a/packages-tests/Symfony/Rules/RequireNativeArraySymfonyRenderCallRule/Fixture/SkipNoSecondArgument.php b/packages-tests/Symfony/Rules/RequireNativeArraySymfonyRenderCallRule/Fixture/SkipNoSecondArgument.php deleted file mode 100644 index 909d602e..00000000 --- a/packages-tests/Symfony/Rules/RequireNativeArraySymfonyRenderCallRule/Fixture/SkipNoSecondArgument.php +++ /dev/null @@ -1,15 +0,0 @@ -render('...'); - } -} diff --git a/packages-tests/Symfony/Rules/RequireNativeArraySymfonyRenderCallRule/RequireNativeArraySymfonyRenderCallRuleTest.php b/packages-tests/Symfony/Rules/RequireNativeArraySymfonyRenderCallRule/RequireNativeArraySymfonyRenderCallRuleTest.php deleted file mode 100644 index e75971c5..00000000 --- a/packages-tests/Symfony/Rules/RequireNativeArraySymfonyRenderCallRule/RequireNativeArraySymfonyRenderCallRuleTest.php +++ /dev/null @@ -1,48 +0,0 @@ - - */ -final class RequireNativeArraySymfonyRenderCallRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipNoSecondArgument.php', []]; - yield [__DIR__ . '/Fixture/SkipCorrectControllerRender.php', []]; - - yield [ - __DIR__ . '/Fixture/ParameterAsSecondArgument.php', - [[RequireNativeArraySymfonyRenderCallRule::ERROR_MESSAGE, 17]], ]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(RequireNativeArraySymfonyRenderCallRule::class); - } -} diff --git a/packages-tests/Symfony/Rules/RequireNativeArraySymfonyRenderCallRule/config/configured_rule.neon b/packages-tests/Symfony/Rules/RequireNativeArraySymfonyRenderCallRule/config/configured_rule.neon deleted file mode 100644 index 89bfdc77..00000000 --- a/packages-tests/Symfony/Rules/RequireNativeArraySymfonyRenderCallRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../../../tests/config/included_services.neon - -rules: - - Symplify\PHPStanRules\Symfony\Rules\RequireNativeArraySymfonyRenderCallRule diff --git a/packages-tests/Symfony/Rules/TwigPublicCallableExistsRule/Fixture/SkipTwigExtensionWithExistingCallable.php b/packages-tests/Symfony/Rules/TwigPublicCallableExistsRule/Fixture/SkipTwigExtensionWithExistingCallable.php deleted file mode 100644 index cab62714..00000000 --- a/packages-tests/Symfony/Rules/TwigPublicCallableExistsRule/Fixture/SkipTwigExtensionWithExistingCallable.php +++ /dev/null @@ -1,23 +0,0 @@ - - */ -final class TwigPublicCallableExistsRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipTwigExtensionWithExistingCallable.php', []]; - - $errorMessage = sprintf(TwigPublicCallableExistsRule::ERROR_MESSAGE, 'notHere'); - yield [__DIR__ . '/Fixture/TwigExtensionWithMissingCallable.php', [[$errorMessage, 15]]]; - } - - protected function getRule(): Rule - { - return new TwigPublicCallableExistsRule(); - } -} diff --git a/packages/CognitiveComplexity/AstCognitiveComplexityAnalyzer.php b/packages/CognitiveComplexity/AstCognitiveComplexityAnalyzer.php deleted file mode 100644 index 0e973849..00000000 --- a/packages/CognitiveComplexity/AstCognitiveComplexityAnalyzer.php +++ /dev/null @@ -1,64 +0,0 @@ -complexityNodeTraverserFactory = $complexityNodeTraverserFactory; - $this->cognitiveComplexityDataCollector = $cognitiveComplexityDataCollector; - $this->nestingNodeVisitor = $nestingNodeVisitor; - } - - public function analyzeClassLike(Class_ $class): int - { - $totalCognitiveComplexity = 0; - foreach ($class->getMethods() as $classMethod) { - $totalCognitiveComplexity += $this->analyzeFunctionLike($classMethod); - } - - return $totalCognitiveComplexity; - } - - /** - * @api - * @param \PhpParser\Node\Stmt\Function_|\PhpParser\Node\Stmt\ClassMethod $functionLike - */ - public function analyzeFunctionLike($functionLike): int - { - $this->cognitiveComplexityDataCollector->reset(); - $this->nestingNodeVisitor->reset(); - - $nodeTraverser = $this->complexityNodeTraverserFactory->create(); - $nodeTraverser->traverse([$functionLike]); - - return $this->cognitiveComplexityDataCollector->getCognitiveComplexity(); - } -} diff --git a/packages/CognitiveComplexity/CompositionOverInheritanceAnalyzer.php b/packages/CognitiveComplexity/CompositionOverInheritanceAnalyzer.php deleted file mode 100644 index 62b6396e..00000000 --- a/packages/CognitiveComplexity/CompositionOverInheritanceAnalyzer.php +++ /dev/null @@ -1,74 +0,0 @@ -astCognitiveComplexityAnalyzer = $astCognitiveComplexityAnalyzer; - } - - public function analyzeClassLike(Class_ $class): int - { - $totalCognitiveComplexity = $this->astCognitiveComplexityAnalyzer->analyzeClassLike($class); - - // non final classes are more complex - if (! $class->isFinal()) { - $totalCognitiveComplexity += self::NON_FINAL_CLASS_SCORE; - } - - // classes extending from another are more complex - if ($class->extends !== null) { - $totalCognitiveComplexity += self::INHERITANCE_CLASS_SCORE; - } - - // classes using traits are more complex - $totalCognitiveComplexity += $this->analyzeTraitUses($class); - - return $totalCognitiveComplexity; - } - - private function analyzeTraitUses(Class_ $class): int - { - $traitComplexity = 0; - - foreach ($class->stmts as $stmt) { - // trait-use can only appear as the very first statement in a class - if ($stmt instanceof TraitUse) { - $traitComplexity += count($stmt->traits) * self::TRAIT_SCORE; - } else { - break; - } - } - - return $traitComplexity; - } -} diff --git a/packages/CognitiveComplexity/DataCollector/CognitiveComplexityDataCollector.php b/packages/CognitiveComplexity/DataCollector/CognitiveComplexityDataCollector.php deleted file mode 100644 index 8d717fbd..00000000 --- a/packages/CognitiveComplexity/DataCollector/CognitiveComplexityDataCollector.php +++ /dev/null @@ -1,39 +0,0 @@ -operationComplexity; - } - - public function increaseNesting(int $steps): void - { - $this->nestingComplexity += $steps; - } - - public function getCognitiveComplexity(): int - { - return $this->nestingComplexity + $this->operationComplexity; - } - - public function reset(): void - { - $this->operationComplexity = 0; - $this->nestingComplexity = 0; - } -} diff --git a/packages/CognitiveComplexity/NodeAnalyzer/ComplexityAffectingNodeFinder.php b/packages/CognitiveComplexity/NodeAnalyzer/ComplexityAffectingNodeFinder.php deleted file mode 100644 index 05610484..00000000 --- a/packages/CognitiveComplexity/NodeAnalyzer/ComplexityAffectingNodeFinder.php +++ /dev/null @@ -1,98 +0,0 @@ -> - */ - private const BREAKING_NODE_TYPES = [Continue_::class, Goto_::class, Break_::class]; - - /** - * B1. Increments - * - * @var array> - */ - private const INCREASING_NODE_TYPES = [ - If_::class, - Else_::class, - ElseIf_::class, - Switch_::class, - For_::class, - Foreach_::class, - While_::class, - Do_::class, - Catch_::class, - // && - BooleanAnd::class, - Ternary::class, - ]; - - public function isIncrementingNode(Node $node): bool - { - // B1. ternary operator - if ($this->isInstanceOf($node, self::INCREASING_NODE_TYPES)) { - return true; - } - - if ($node instanceof Ternary) { - return true; - } - - return $this->isBreakingNode($node); - } - - public function isBreakingNode(Node $node): bool - { - // B1. goto LABEL, break LABEL, continue LABEL - if ($this->isInstanceOf($node, self::BREAKING_NODE_TYPES)) { - // skip empty breaks - /** @var Goto_|Break_|Continue_ $node */ - if ($node instanceof Goto_ && $node->name !== null) { - return true; - } - - if (($node instanceof Break_ || $node instanceof Continue_) && $node->num !== null) { - return true; - } - } - - return false; - } - - /** - * @param class-string[] $types - */ - private function isInstanceOf(Node $node, array $types): bool - { - foreach ($types as $type) { - if (is_a($node, $type, true)) { - return true; - } - } - - return false; - } -} diff --git a/packages/CognitiveComplexity/NodeTraverser/ComplexityNodeTraverserFactory.php b/packages/CognitiveComplexity/NodeTraverser/ComplexityNodeTraverserFactory.php deleted file mode 100644 index fc580a6e..00000000 --- a/packages/CognitiveComplexity/NodeTraverser/ComplexityNodeTraverserFactory.php +++ /dev/null @@ -1,35 +0,0 @@ -nestingNodeVisitor = $nestingNodeVisitor; - $this->complexityNodeVisitor = $complexityNodeVisitor; - } - - public function create(): NodeTraverser - { - $nodeTraverser = new NodeTraverser(); - $nodeTraverser->addVisitor($this->nestingNodeVisitor); - $nodeTraverser->addVisitor($this->complexityNodeVisitor); - - return $nodeTraverser; - } -} diff --git a/packages/CognitiveComplexity/NodeVisitor/ComplexityNodeVisitor.php b/packages/CognitiveComplexity/NodeVisitor/ComplexityNodeVisitor.php deleted file mode 100644 index 643d7426..00000000 --- a/packages/CognitiveComplexity/NodeVisitor/ComplexityNodeVisitor.php +++ /dev/null @@ -1,38 +0,0 @@ -cognitiveComplexityDataCollector = $cognitiveComplexityDataCollector; - $this->complexityAffectingNodeFinder = $complexityAffectingNodeFinder; - } - - public function enterNode(Node $node): ?Node - { - if (! $this->complexityAffectingNodeFinder->isIncrementingNode($node)) { - return null; - } - - $this->cognitiveComplexityDataCollector->increaseOperation(); - - return null; - } -} diff --git a/packages/CognitiveComplexity/NodeVisitor/NestingNodeVisitor.php b/packages/CognitiveComplexity/NodeVisitor/NestingNodeVisitor.php deleted file mode 100644 index d067f8ff..00000000 --- a/packages/CognitiveComplexity/NodeVisitor/NestingNodeVisitor.php +++ /dev/null @@ -1,110 +0,0 @@ -> - */ - private const NESTING_NODE_TYPES = [ - If_::class, - For_::class, - While_::class, - Catch_::class, - Closure::class, - Foreach_::class, - Do_::class, - Ternary::class, - ]; - - /** - * @var int - */ - private $measuredNestingLevel = 1; - - /** - * @var int - */ - private $previousNestingLevel = 0; - /** - * @var \Symplify\PHPStanRules\CognitiveComplexity\DataCollector\CognitiveComplexityDataCollector - */ - private $cognitiveComplexityDataCollector; - /** - * @var \Symplify\PHPStanRules\CognitiveComplexity\NodeAnalyzer\ComplexityAffectingNodeFinder - */ - private $complexityAffectingNodeFinder; - public function __construct(CognitiveComplexityDataCollector $cognitiveComplexityDataCollector, ComplexityAffectingNodeFinder $complexityAffectingNodeFinder) - { - $this->cognitiveComplexityDataCollector = $cognitiveComplexityDataCollector; - $this->complexityAffectingNodeFinder = $complexityAffectingNodeFinder; - } - - public function reset(): void - { - $this->measuredNestingLevel = 1; - } - - public function enterNode(Node $node): ?Node - { - if ($this->isNestingNode($node)) { - ++$this->measuredNestingLevel; - } - - if (! $this->complexityAffectingNodeFinder->isIncrementingNode($node)) { - return null; - } - - if ($this->complexityAffectingNodeFinder->isBreakingNode($node)) { - $this->previousNestingLevel = $this->measuredNestingLevel; - return null; - } - - // B2. Nesting level - if ($this->measuredNestingLevel > 1 && $this->previousNestingLevel < $this->measuredNestingLevel) { - // only going deeper, not on the same level - $nestingComplexity = $this->measuredNestingLevel - 2; - $this->cognitiveComplexityDataCollector->increaseNesting($nestingComplexity); - } - - $this->previousNestingLevel = $this->measuredNestingLevel; - - return null; - } - - public function leaveNode(Node $node): ?Node - { - if ($this->isNestingNode($node)) { - --$this->measuredNestingLevel; - } - - return null; - } - - private function isNestingNode(Node $node): bool - { - foreach (self::NESTING_NODE_TYPES as $nestingNodeType) { - if (is_a($node, $nestingNodeType, true)) { - return true; - } - } - - return false; - } -} diff --git a/packages/CognitiveComplexity/Rules/ClassLikeCognitiveComplexityRule.php b/packages/CognitiveComplexity/Rules/ClassLikeCognitiveComplexityRule.php deleted file mode 100644 index 2f1eb03d..00000000 --- a/packages/CognitiveComplexity/Rules/ClassLikeCognitiveComplexityRule.php +++ /dev/null @@ -1,143 +0,0 @@ -astCognitiveComplexityAnalyzer = $astCognitiveComplexityAnalyzer; - $this->compositionOverInheritanceAnalyzer = $compositionOverInheritanceAnalyzer; - $this->maxClassCognitiveComplexity = $maxClassCognitiveComplexity; - $this->scoreCompositionOverInheritance = $scoreCompositionOverInheritance; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classLike = $node->getOriginalNode(); - if (! $classLike instanceof Class_) { - return []; - } - - $measuredCognitiveComplexity = $this->resolveMeasuredCognitiveComplexity($classLike); - if ($measuredCognitiveComplexity <= $this->maxClassCognitiveComplexity) { - return []; - } - - $message = sprintf(self::ERROR_MESSAGE, $measuredCognitiveComplexity, $this->maxClassCognitiveComplexity); - - return [$message]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition( - 'Cognitive complexity of class/trait must be under specific limit', - [new ConfiguredCodeSample( - <<<'CODE_SAMPLE' -class SomeClass -{ - public function simple($value) - { - if ($value !== 1) { - if ($value !== 2) { - return false; - } - } - - return true; - } - - public function another($value) - { - if ($value !== 1 && $value !== 2) { - return false; - } - - return true; - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -class SomeClass -{ - public function simple($value) - { - return $this->someOtherService->count($value); - } - - public function another($value) - { - return $this->someOtherService->delete($value); - } -} -CODE_SAMPLE - , - [ - 'maxClassCognitiveComplexity' => 10, - 'scoreCompositionOverInheritance' => true, - ] - )] - ); - } - - private function resolveMeasuredCognitiveComplexity(Class_ $class): int - { - if ($this->scoreCompositionOverInheritance) { - return $this->compositionOverInheritanceAnalyzer->analyzeClassLike($class); - } - - return $this->astCognitiveComplexityAnalyzer->analyzeClassLike($class); - } -} diff --git a/packages/CognitiveComplexity/Rules/FunctionLikeCognitiveComplexityRule.php b/packages/CognitiveComplexity/Rules/FunctionLikeCognitiveComplexityRule.php deleted file mode 100644 index 3850927d..00000000 --- a/packages/CognitiveComplexity/Rules/FunctionLikeCognitiveComplexityRule.php +++ /dev/null @@ -1,159 +0,0 @@ -astCognitiveComplexityAnalyzer = $astCognitiveComplexityAnalyzer; - $this->maxMethodCognitiveComplexity = $maxMethodCognitiveComplexity; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return FunctionLike::class; - } - - /** - * @param FunctionLike $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! $node instanceof ClassMethod && ! $node instanceof Function_) { - return []; - } - - $functionLikeCognitiveComplexity = $this->astCognitiveComplexityAnalyzer->analyzeFunctionLike($node); - if ($functionLikeCognitiveComplexity <= $this->maxMethodCognitiveComplexity) { - return []; - } - - $functionLikeName = $this->resolveFunctionName($node, $scope); - - $message = sprintf( - self::ERROR_MESSAGE, - $functionLikeName, - $functionLikeCognitiveComplexity, - $this->maxMethodCognitiveComplexity - ); - - return [$message]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition( - 'Cognitive complexity of function/method must be under specific limit', - [new ConfiguredCodeSample( - <<<'CODE_SAMPLE' -class SomeClass -{ - public function simple($value) - { - if ($value !== 1) { - if ($value !== 2) { - return false; - } - } - - return true; - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -class SomeClass -{ - public function simple($value) - { - if ($value === 1) { - return true; - } - - return $value === 2; - } -} -CODE_SAMPLE - , - [ - 'maxMethodCognitiveComplexity' => 5, - ] - )] - ); - } - - private function resolveFunctionName(FunctionLike $functionLike, Scope $scope): string - { - if ($functionLike instanceof Function_) { - return $functionLike->name . '()'; - } - - if ($functionLike instanceof ClassMethod) { - $name = ''; - - $classReflection = $scope->getClassReflection(); - if ($classReflection !== null) { - $name = $classReflection->getName() . '::'; - } - - return $name . $functionLike->name . '()'; - } - - if ($functionLike instanceof Closure) { - return 'closure'; - } - - if ($functionLike instanceof ArrowFunction) { - return 'arrow function'; - } - - throw new ShouldNotHappenException(); - } -} diff --git a/packages/ObjectCalisthenics/NodeVisitor/NullsafeCheckedNodeVisitor.php b/packages/ObjectCalisthenics/NodeVisitor/NullsafeCheckedNodeVisitor.php deleted file mode 100644 index dd443faf..00000000 --- a/packages/ObjectCalisthenics/NodeVisitor/NullsafeCheckedNodeVisitor.php +++ /dev/null @@ -1,23 +0,0 @@ -var->setAttribute(AttributeKey::NULLSAFE_CHECKED, true); - return null; - } -} diff --git a/packages/ObjectCalisthenics/Rules/NoChainMethodCallRule.php b/packages/ObjectCalisthenics/Rules/NoChainMethodCallRule.php deleted file mode 100644 index 78a81191..00000000 --- a/packages/ObjectCalisthenics/Rules/NoChainMethodCallRule.php +++ /dev/null @@ -1,103 +0,0 @@ - - */ -final class NoChainMethodCallRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'Do not use chained method calls. Put each on separated lines.'; - /** - * @var \Symplify\PHPStanRules\NodeAnalyzer\MethodCall\AllowedChainCallSkipper - */ - private $allowedChainCallSkipper; - /** - * @var class-string[] - */ - private $allowedChainTypes = []; - /** - * @param class-string[] $allowedChainTypes - */ - public function __construct(AllowedChainCallSkipper $allowedChainCallSkipper, array $allowedChainTypes = []) - { - $this->allowedChainCallSkipper = $allowedChainCallSkipper; - $this->allowedChainTypes = $allowedChainTypes; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return MethodCall::class; - } - - /** - * @param MethodCall $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! $node->var instanceof MethodCall) { - return []; - } - - // skip nullsafe chain - $isNullsafeChecked = (bool) $node->var->getAttribute(AttributeKey::NULLSAFE_CHECKED); - if ($isNullsafeChecked) { - return []; - } - - if ($this->allowedChainCallSkipper->isAllowedFluentMethodCall($scope, $node, $this->allowedChainTypes)) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new ConfiguredCodeSample( - <<<'CODE_SAMPLE' -$this->runThis()->runThat(); - -$fluentClass = new AllowedFluent(); -$fluentClass->one()->two(); -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -$this->runThis(); -$this->runThat(); - -$fluentClass = new AllowedFluent(); -$fluentClass->one()->two(); -CODE_SAMPLE - , - [ - 'allowedChainTypes' => ['AllowedFluent'], - ] - ), - ]); - } -} diff --git a/packages/ObjectCalisthenics/Rules/NoShortNameRule.php b/packages/ObjectCalisthenics/Rules/NoShortNameRule.php deleted file mode 100644 index 72389692..00000000 --- a/packages/ObjectCalisthenics/Rules/NoShortNameRule.php +++ /dev/null @@ -1,137 +0,0 @@ -minNameLength = $minNameLength; - $this->allowedShortNames = $allowedShortNames; - } - /** - * @return array> - */ - public function getNodeTypes(): array - { - return [ - ClassLike::class, - Function_::class, - ClassMethod::class, - Const_::class, - PropertyProperty::class, - Variable::class, - Param::class, - ]; - } - /** - * @param ClassLike|Function_|ClassMethod|Const_|PropertyProperty|Variable|Param $node - * @return array - */ - public function process(Node $node, Scope $scope): array - { - if ($node instanceof Variable || $node instanceof Param) { - if ($node instanceof Param) { - $node = $node->var; - } - - if (! $node instanceof Variable) { - return []; - } - - return $this->processVariable($node); - } - - $name = (string) $node->name; - if ($this->isNameValid($name)) { - return []; - } - - $errorMessage = sprintf(self::ERROR_MESSAGE, $name, $this->minNameLength); - return [$errorMessage]; - } - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new ConfiguredCodeSample( - <<<'CODE_SAMPLE' -function is() -{ -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -function isClass() -{ -} -CODE_SAMPLE - , - [ - 'minNameLength' => 3, - ] - ), - ]); - } - /** - * @return string[] - */ - private function processVariable(Variable $variable): array - { - if (! is_string($variable->name)) { - return []; - } - - $variableName = $variable->name; - if ($this->isNameValid($variableName)) { - return []; - } - - $errorMessage = sprintf(self::ERROR_MESSAGE, $variableName, $this->minNameLength); - return [$errorMessage]; - } - private function isNameValid(string $name): bool - { - if (Strings::length($name) >= $this->minNameLength) { - return true; - } - - return in_array($name, $this->allowedShortNames, true); - } -} diff --git a/packages/Symfony/Finder/ArrayKeyFinder.php b/packages/Symfony/Finder/ArrayKeyFinder.php deleted file mode 100644 index 13c7e86c..00000000 --- a/packages/Symfony/Finder/ArrayKeyFinder.php +++ /dev/null @@ -1,44 +0,0 @@ -nodeFinder = new NodeFinder(); - } - - public function findArrayItemExprByKeyName(ClassMethod $classMethod, string $desiredKeyName): ?Expr - { - /** @var ArrayItem[] $arrayItems */ - $arrayItems = $this->nodeFinder->findInstanceOf($classMethod, ArrayItem::class); - - foreach ($arrayItems as $arrayItem) { - if (! $arrayItem->key instanceof String_) { - continue; - } - - if ($arrayItem->key->value !== $desiredKeyName) { - continue; - } - - return $arrayItem->value; - } - - return null; - } -} diff --git a/packages/Symfony/NodeAnalyzer/SymfonyControllerAnalyzer.php b/packages/Symfony/NodeAnalyzer/SymfonyControllerAnalyzer.php deleted file mode 100644 index b66c9d16..00000000 --- a/packages/Symfony/NodeAnalyzer/SymfonyControllerAnalyzer.php +++ /dev/null @@ -1,44 +0,0 @@ -attributeFinder = $attributeFinder; - } - - public function isControllerActionMethod(ClassMethod $classMethod): bool - { - if (! $classMethod->isPublic()) { - return false; - } - - if ($this->attributeFinder->hasAttribute($classMethod, self::ROUTE_ATTRIBUTE)) { - return true; - } - - $docComment = $classMethod->getDocComment(); - if (! $docComment instanceof Doc) { - return false; - } - - return strpos($docComment->getText(), '@Route') !== false; - } -} diff --git a/packages/Symfony/NodeAnalyzer/SymfonyPhpConfigClosureAnalyzer.php b/packages/Symfony/NodeAnalyzer/SymfonyPhpConfigClosureAnalyzer.php deleted file mode 100644 index ed9ae0f9..00000000 --- a/packages/Symfony/NodeAnalyzer/SymfonyPhpConfigClosureAnalyzer.php +++ /dev/null @@ -1,31 +0,0 @@ -params; - if (count($params) !== 1) { - return false; - } - - $param = $params[0]; - if (! $param->type instanceof Name) { - return false; - } - - $paramType = $param->type->toString(); - return is_a( - $paramType, - 'Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator', - true - ); - } -} diff --git a/packages/Symfony/PropertyMetadataResolver.php b/packages/Symfony/PropertyMetadataResolver.php deleted file mode 100644 index 21d671c2..00000000 --- a/packages/Symfony/PropertyMetadataResolver.php +++ /dev/null @@ -1,62 +0,0 @@ -getNativeReflection(); - - foreach ($nativeReflection->getProperties() as $nativeReflectionProperty) { - $propertyName = $nativeReflectionProperty->getName(); - - $phpstanPropertyReflection = $classReflection->getProperty($propertyName, $scope); - $propertyLine = $this->resolvePropertyLine($phpstanPropertyReflection, $propertyName); - - /** @var PhpPropertyReflection $phpstanPropertyReflection */ - $propertyMetadatas[] = new PropertyMetadata( - $phpstanPropertyReflection, - $nativeReflectionProperty, - $propertyLine - ); - } - - return $propertyMetadatas; - } - - private function resolvePropertyLine(PropertyReflection $phpstanPropertyReflection, string $propertyName): int - { - $declaringClassReflection = $phpstanPropertyReflection->getDeclaringClass(); - - $reflector = (new BetterReflection())->reflector(); - - $reflectionClass = $reflector->reflectClass($declaringClassReflection->getName()); - if (! $reflectionClass->hasProperty($propertyName)) { - throw new ShouldNotHappenException(); - } - - $reflectionProperty = $reflectionClass->getProperty($propertyName); - if (! $reflectionProperty instanceof ReflectionProperty) { - throw new ShouldNotHappenException(); - } - - return $reflectionProperty->getStartLine(); - } -} diff --git a/packages/Symfony/Rules/NoConstructorSymfonyFormObjectRule.php b/packages/Symfony/Rules/NoConstructorSymfonyFormObjectRule.php deleted file mode 100644 index 1f479c88..00000000 --- a/packages/Symfony/Rules/NoConstructorSymfonyFormObjectRule.php +++ /dev/null @@ -1,183 +0,0 @@ - - * - * @see \Symplify\PHPStanRules\Tests\Symfony\Rules\NoConstructorSymfonyFormObjectRule\NoConstructorSymfonyFormObjectRuleTest - */ -final class NoConstructorSymfonyFormObjectRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'This object is used in a Symfony form, that uses magic setters/getters, so it cannot have required constructor'; - /** - * @var \PHPStan\Reflection\ReflectionProvider - */ - private $reflectionProvider; - - public function __construct(ReflectionProvider $reflectionProvider) - { - $this->reflectionProvider = $reflectionProvider; - } - - public function getNodeType(): string - { - return CollectedDataNode::class; - } - - /** - * @return RuleError[] - */ - public function processNode(Node $node, Scope $scope): array - { - $formTypeClassesCollector = $node->get(FormTypeClassCollector::class); - $formTypeClasses = Arrays::flatten($formTypeClassesCollector); - - $ruleErrors = []; - - foreach ($formTypeClasses as $formTypeClass) { - if (! $this->reflectionProvider->hasClass($formTypeClass)) { - continue; - } - - $formTypeClassReflection = $this->reflectionProvider->getClass($formTypeClass); - - // no constructor, we can skip - $constructorClassReflection = $formTypeClassReflection->getConstructor(); - if (! $constructorClassReflection instanceof PhpMethodReflection) { - continue; - } - - if (! $this->hasClassMethodRequiredParameter($constructorClassReflection)) { - continue; - } - - $nativeClassReflection = $formTypeClassReflection->getNativeReflection(); - $classLine = $nativeClassReflection->getStartLine(); - - $ruleErrorBuilder = RuleErrorBuilder::message(self::ERROR_MESSAGE); - $fileName = $formTypeClassReflection->getFileName(); - if (is_string($fileName)) { - $ruleErrorBuilder->file($fileName); - } - - if (is_int($classLine)) { - $ruleErrorBuilder->line($classLine); - } - - $ruleErrors[] = $ruleErrorBuilder->build(); - } - - return $ruleErrors; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition( - self::ERROR_MESSAGE, - [ - new CodeSample( - <<<'CODE_SAMPLE' -final class Ticket -{ - public function __construct(private int $price) - { - } -} - ---- - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\OptionsResolver\OptionsResolver; -use App\Entity\Ticket; - -final class TicketFormType extends AbstractType -{ - public function configureOptions(OptionsResolver $resolver): void - { - $resolver->setDefaults([ - 'data_class' => Ticket::class, - ]); - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -final class Ticket -{ - private ?int $price = null; - - public function setPrice(int $price): void - { - $this->price = $price; - } - - public function getPrice(): ?int - { - return $this->price; - } -} - ---- - -use Symfony\Component\Form\AbstractType; -use Symfony\Component\OptionsResolver\OptionsResolver; -use App\Entity\Ticket; - -final class TicketFormType extends AbstractType -{ - public function configureOptions(OptionsResolver $resolver): void - { - $resolver->setDefaults([ - 'data_class' => Ticket::class, - ]); - } -} -CODE_SAMPLE - ), - ] - ); - } - - private function hasClassMethodRequiredParameter(PhpMethodReflection $phpMethodReflection): bool - { - $parametersAcceptorWithPhpDocs = ParametersAcceptorSelector::selectSingle($phpMethodReflection->getVariants()); - - // no parameters in constructor → we can skip - if ($parametersAcceptorWithPhpDocs->getParameters() === []) { - return false; - } - - foreach ($parametersAcceptorWithPhpDocs->getParameters() as $parameterReflectionWithPhpDoc) { - /** @var PhpParameterReflection $parameterReflectionWithPhpDoc */ - if ($parameterReflectionWithPhpDoc->isOptional()) { - continue; - } - - return true; - } - - return false; - } -} diff --git a/packages/Symfony/Rules/PreventDoubleSetParameterRule.php b/packages/Symfony/Rules/PreventDoubleSetParameterRule.php deleted file mode 100644 index a868f371..00000000 --- a/packages/Symfony/Rules/PreventDoubleSetParameterRule.php +++ /dev/null @@ -1,153 +0,0 @@ - - */ -final class PreventDoubleSetParameterRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'Set param value is overridden. Merge it to previous set above'; - - /** - * @var array - */ - private $setParametersNamesByFile = []; - /** - * @var \Symplify\PHPStanRules\Symfony\NodeAnalyzer\SymfonyPhpConfigClosureAnalyzer - */ - private $symfonyPhpConfigClosureAnalyzer; - /** - * @var \PhpParser\NodeFinder - */ - private $nodeFinder; - public function __construct(SymfonyPhpConfigClosureAnalyzer $symfonyPhpConfigClosureAnalyzer, NodeFinder $nodeFinder) - { - $this->symfonyPhpConfigClosureAnalyzer = $symfonyPhpConfigClosureAnalyzer; - $this->nodeFinder = $nodeFinder; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return Closure::class; - } - - /** - * @param Closure $node - * @return RuleError[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! $this->symfonyPhpConfigClosureAnalyzer->isSymfonyPhpConfig($node)) { - return []; - } - - /** @var MethodCall[] $methodCalls */ - $methodCalls = $this->nodeFinder->findInstanceOf($node, MethodCall::class); - - $errorMessages = []; - - foreach ($methodCalls as $methodCall) { - if (! $methodCall->name instanceof Identifier) { - continue; - } - - $methodCallName = $methodCall->name->toString(); - if ($methodCallName !== 'set') { - continue; - } - - if (! $this->isVariableName($methodCall->var, 'parameters')) { - continue; - } - - $firstArg = $methodCall->getArgs()[0]; - $firstArgType = $scope->getType($firstArg->value); - - if (! $firstArgType instanceof ConstantStringType) { - continue; - } - - $setParameterName = $firstArgType->getValue(); - $previousSetParameterNames = $this->setParametersNamesByFile[$scope->getFile()] ?? []; - - if (in_array($setParameterName, $previousSetParameterNames, true)) { - $errorMessages[] = RuleErrorBuilder::message(self::ERROR_MESSAGE) - ->line($methodCall->getLine()) - ->build(); - } - - $this->setParametersNamesByFile[$scope->getFile()][] = $setParameterName; - } - - return $errorMessages; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; - -return static function (ContainerConfigurator $containerConfigurator): void { - $parameters = $containerConfigurator->parameters(); - - $parameters->set('some_param', [1]); - $parameters->set('some_param', [2]); -}; -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; - -return static function (ContainerConfigurator $containerConfigurator): void { - $parameters = $containerConfigurator->parameters(); - - $parameters->set('some_param', [1, 2]); -}; -CODE_SAMPLE - ), - ]); - } - - private function isVariableName(Expr $expr, string $name): bool - { - if (! $expr instanceof Variable) { - return false; - } - - if (! is_string($expr->name)) { - return false; - } - - return $expr->name === $name; - } -} diff --git a/packages/Symfony/Rules/RequireCascadeValidateRule.php b/packages/Symfony/Rules/RequireCascadeValidateRule.php deleted file mode 100644 index 1e727b89..00000000 --- a/packages/Symfony/Rules/RequireCascadeValidateRule.php +++ /dev/null @@ -1,252 +0,0 @@ - - * - * @see \Symplify\PHPStanRules\Tests\Symfony\Rules\RequireCascadeValidateRule\RequireCascadeValidateRuleTest - */ -final class RequireCascadeValidateRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'Property "$%s" is missing @Valid annotation'; - /** - * @var \PHPStan\Reflection\ReflectionProvider - */ - private $reflectionProvider; - /** - * @var \Symplify\PHPStanRules\Symfony\Finder\ArrayKeyFinder - */ - private $arrayKeyFinder; - /** - * @var \Symplify\PHPStanRules\Symfony\PropertyMetadataResolver - */ - private $propertyMetadataResolver; - public function __construct(ReflectionProvider $reflectionProvider, ArrayKeyFinder $arrayKeyFinder, PropertyMetadataResolver $propertyMetadataResolver) - { - $this->reflectionProvider = $reflectionProvider; - $this->arrayKeyFinder = $arrayKeyFinder; - $this->propertyMetadataResolver = $propertyMetadataResolver; - } - - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return RuleError[]|string[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classReflection = $node->getClassReflection(); - if (! $classReflection->isSubclassOf('Symfony\Component\Form\AbstractType')) { - return []; - } - - /** @var Class_ $classLike */ - $classLike = $node->getOriginalNode(); - $configureOptionsClassMethod = $classLike->getMethod('configureOptions'); - - if ($configureOptionsClassMethod instanceof ClassMethod) { - return $this->processConfigureOptionsClassMethod($configureOptionsClassMethod, $scope); - } - - return []; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -use Symfony\Component\Form\AbstractType; -use Symfony\Component\OptionsResolver\OptionsResolver; -use Symfony\Component\Validator\Constraints\Valid; - -final class NullablePropertyFormType extends AbstractType -{ - public function configureOptions(OptionsResolver $optionsResolver): void - { - $optionsResolver->setDefaults([ - 'data_class' => SomeEntity::class, - 'constraints' => new Valid(), - ]); - } -} - -class SomeEntity -{ - /** - * @var NestedEntity - */ - private $nestedEntity; -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -use Symfony\Component\Validator\Constraints as Assert; - -class SomeEntity -{ - /** - * @Assert\Valid - * @var NestedEntity - */ - private $nestedEntity; -} -CODE_SAMPLE - ), ]); - } - - private function hasConstraintValidOption(ClassMethod $configureOptionsClassMethod, Scope $scope): bool - { - $expr = $this->arrayKeyFinder->findArrayItemExprByKeyName($configureOptionsClassMethod, 'constraints'); - if (! $expr instanceof New_) { - return false; - } - - if ($expr->class instanceof Expr) { - $classType = $scope->getType($expr->class); - if (! $classType instanceof ConstantStringType) { - return false; - } - - $className = $classType->getValue(); - } elseif ($expr->class instanceof Name) { - $className = $expr->class->toString(); - } else { - return false; - } - - return $className === 'Symfony\Component\Validator\Constraints\Valid'; - } - - private function resolveDataClassReflection(ClassMethod $classMethod, Scope $scope): ?ClassReflection - { - $expr = $this->arrayKeyFinder->findArrayItemExprByKeyName($classMethod, 'data_class'); - if (! $expr instanceof Expr) { - return null; - } - - $valueType = $scope->getType($expr); - if (! $valueType instanceof ConstantStringType) { - return null; - } - - $value = $valueType->getValue(); - if (! $this->reflectionProvider->hasClass($value)) { - return null; - } - - return $this->reflectionProvider->getClass($value); - } - - /** - * @return RuleError[] - */ - private function processConfigureOptionsClassMethod(ClassMethod $configureOptionsClassMethod, Scope $scope): array - { - if (! $this->hasConstraintValidOption($configureOptionsClassMethod, $scope)) { - return []; - } - - $dataClassReflection = $this->resolveDataClassReflection($configureOptionsClassMethod, $scope); - if (! $dataClassReflection instanceof ClassReflection) { - return []; - } - - $propertyMetadatas = $this->propertyMetadataResolver->resolvePropertyMetadatas($dataClassReflection, $scope); - - $ruleErrors = []; - - foreach ($propertyMetadatas as $propertyMetadata) { - // is property with object type? - $propertyType = $propertyMetadata->getPropertyType(); - - $propertyType = $this->unwrapType($propertyType); - if (! $propertyType instanceof ObjectType) { - continue; - } - - // skip PHP native classes - $classReflection = $propertyType->getClassReflection(); - if (! $classReflection instanceof ClassReflection) { - throw new ShouldNotHappenException(); - } - - if ($classReflection->isBuiltin()) { - continue; - } - - // does it have @Valid annotation? - if ($this->hasValidAnnotation($propertyMetadata)) { - continue; - } - - $errorMessage = sprintf(self::ERROR_MESSAGE, $propertyMetadata->getPropertyName()); - - $ruleErrors[] = RuleErrorBuilder::message($errorMessage) - ->file($propertyMetadata->getFileName()) - ->line($propertyMetadata->getPropertyLine()) - ->build(); - } - - return $ruleErrors; - } - - private function hasValidAnnotation(PropertyMetadata $propertyMetadata): bool - { - if (strpos($propertyMetadata->getDocComment(), '@Valid') !== false) { - return true; - } - - return strpos($propertyMetadata->getDocComment(), '@Assert\Valid') !== false; - } - - private function unwrapType(Type $type): Type - { - if (TypeCombinator::containsNull($type)) { - $type = TypeCombinator::removeNull($type); - } - - // collection types - if ($type instanceof ArrayType) { - return $type->getItemType(); - } - - return $type; - } -} diff --git a/packages/Symfony/Rules/RequireInvokableControllerRule.php b/packages/Symfony/Rules/RequireInvokableControllerRule.php deleted file mode 100644 index 1e2ac249..00000000 --- a/packages/Symfony/Rules/RequireInvokableControllerRule.php +++ /dev/null @@ -1,116 +0,0 @@ -symfonyControllerAnalyzer = $symfonyControllerAnalyzer; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return RuleError[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classReflection = $node->getClassReflection(); - if ( - ! $classReflection->isSubclassOf('Symfony\Bundle\FrameworkBundle\Controller\AbstractController') && - ! $classReflection->isSubclassOf('Symfony\Bundle\FrameworkBundle\Controller\Controller') - ) { - return []; - } - - $ruleErrors = []; - - $classLike = $node->getOriginalNode(); - foreach ($classLike->getMethods() as $classMethod) { - if (! $this->symfonyControllerAnalyzer->isControllerActionMethod($classMethod)) { - continue; - } - - if ($classMethod->isMagic()) { - continue; - } - - if ($classMethod->name->toString() === MethodName::INVOKE) { - continue; - } - - $ruleErrors[] = RuleErrorBuilder::message(self::ERROR_MESSAGE) - ->line($classMethod->getLine()) - ->build(); - } - - return $ruleErrors; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; -use Symfony\Component\Routing\Annotation\Route; - -final class SomeController extends AbstractController -{ - #[Route()] - public function someMethod() - { - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; -use Symfony\Component\Routing\Annotation\Route; - -final class SomeController extends AbstractController -{ - #[Route()] - public function __invoke() - { - } -} -CODE_SAMPLE - ), - ]); - } -} diff --git a/packages/Symfony/Rules/RequireNamedCommandRule.php b/packages/Symfony/Rules/RequireNamedCommandRule.php deleted file mode 100644 index 20c0231a..00000000 --- a/packages/Symfony/Rules/RequireNamedCommandRule.php +++ /dev/null @@ -1,175 +0,0 @@ - - */ -final class RequireNamedCommandRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'The command is missing $this->setName("...") or [#AsCommand] attribute to set the name'; - - /** - * @var string - */ - private const COMMAND_ATTRIBUTE = 'Symfony\Component\Console\Attribute\AsCommand'; - /** - * @var \Symplify\PHPStanRules\NodeAnalyzer\AttributeFinder - */ - private $attributeFinder; - /** - * @var \PhpParser\NodeFinder - */ - private $nodeFinder; - - public function __construct(AttributeFinder $attributeFinder, NodeFinder $nodeFinder) - { - $this->attributeFinder = $attributeFinder; - $this->nodeFinder = $nodeFinder; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! $this->isInNonAbstractCommand($node)) { - return []; - } - - $classLike = $node->getOriginalNode(); - if (! $classLike instanceof Class_) { - return []; - } - - if ($this->attributeFinder->hasAttribute($classLike, self::COMMAND_ATTRIBUTE)) { - return []; - } - - if ($this->hasConfigureClassMethodWithSetName($classLike)) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -use Symfony\Component\Console\Command\Command; - -final class SomeCommand extends Command -{ - public function configure() - { - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -use Symfony\Component\Console\Command\Command; - -final class SomeCommand extends Command -{ - public function configure() - { - $this->setName('some'); - } -} -CODE_SAMPLE - ), - ]); - } - - private function containsSetNameMethodCall(ClassMethod $classMethod): bool - { - /** @var MethodCall[] $methodCalls */ - $methodCalls = $this->nodeFinder->findInstanceOf($classMethod, MethodCall::class); - - foreach ($methodCalls as $methodCall) { - if (! $this->isVariableThis($methodCall->var)) { - continue; - } - - if (! $methodCall->name instanceof Identifier) { - continue; - } - - if ($methodCall->name->toString() !== 'setName') { - continue; - } - - return true; - } - - return false; - } - - private function isInNonAbstractCommand(InClassNode $inClassNode): bool - { - $classReflection = $inClassNode->getClassReflection(); - if ($classReflection->isAbstract()) { - return false; - } - - return $classReflection->isSubclassOf(Command::class); - } - - private function hasConfigureClassMethodWithSetName(Class_ $class): bool - { - $configureClassMethod = $class->getMethod('configure'); - if (! $configureClassMethod instanceof ClassMethod) { - return false; - } - - return $this->containsSetNameMethodCall($configureClassMethod); - } - - private function isVariableThis(Expr $expr): bool - { - if (! $expr instanceof Variable) { - return false; - } - - if (! is_string($expr->name)) { - return false; - } - - return $expr->name === 'this'; - } -} diff --git a/packages/Symfony/Rules/RequireNativeArraySymfonyRenderCallRule.php b/packages/Symfony/Rules/RequireNativeArraySymfonyRenderCallRule.php deleted file mode 100644 index 1d0b9ffb..00000000 --- a/packages/Symfony/Rules/RequireNativeArraySymfonyRenderCallRule.php +++ /dev/null @@ -1,116 +0,0 @@ -render("template.twig", [...]) method should be explicit array, to avoid accidental variable override, see https://tomasvotruba.com/blog/2021/02/15/how-dangerous-is-your-nette-template-assign/'; - - /** - * @return class-string - */ - public function getNodeType(): string - { - return MethodCall::class; - } - - /** - * @param MethodCall $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! $node->name instanceof Identifier) { - return []; - } - - if ($node->name->toString() !== 'render') { - return []; - } - - $callerType = $scope->getType($node->var); - if (! $callerType instanceof ThisType) { - return []; - } - - $classReflection = $scope->getClassReflection(); - if (! $classReflection instanceof ClassReflection) { - return []; - } - - if (! $classReflection->isSubclassOf(AbstractController::class)) { - return []; - } - - if (count($node->args) !== 2) { - return []; - } - - $argOrVariadicPlaceholder = $node->args[1]; - if (! $argOrVariadicPlaceholder instanceof Arg) { - return []; - } - - $secondArgValue = $argOrVariadicPlaceholder->value; - if ($secondArgValue instanceof Array_) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [new CodeSample( - <<<'CODE_SAMPLE' -use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; - -class SomeController extends AbstractController -{ - public function default() - { - $parameters['name'] = 'John'; - $parameters['name'] = 'Doe'; - return $this->render('...', $parameters); - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; - -class SomeController extends AbstractController -{ - public function default() - { - return $this->render('...', [ - 'name' => 'John' - ]); - } -} -CODE_SAMPLE - )]); - } -} diff --git a/packages/Symfony/Rules/TwigPublicCallableExistsRule.php b/packages/Symfony/Rules/TwigPublicCallableExistsRule.php deleted file mode 100644 index f80bc1dc..00000000 --- a/packages/Symfony/Rules/TwigPublicCallableExistsRule.php +++ /dev/null @@ -1,152 +0,0 @@ -getClassReflection(); - if (! $classReflection instanceof ClassReflection) { - return []; - } - - if (! $classReflection->isSubclassOf(AbstractExtension::class)) { - return []; - } - - $twoExprs = $this->matchTwoExprs($node); - if (! $twoExprs instanceof TwoExprs) { - return []; - } - - if (! $this->isThisVariable($twoExprs->getFirstExpr())) { - return []; - } - - $secondExpr = $twoExprs->getSecondExpr(); - if (! $secondExpr instanceof String_) { - return []; - } - - $methodName = $secondExpr->value; - if ($classReflection->hasMethod($methodName)) { - return []; - } - - $errorMessage = sprintf(self::ERROR_MESSAGE, $methodName); - return [$errorMessage]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -use Twig\Extension\AbstractExtension; -use Twig_SimpleFunction; - -final class TwigExtensionWithMissingCallable extends AbstractExtension -{ - public function getFunctions() - { - return [ - new Twig_SimpleFunction('someFunctionName', [$this, 'someMethod']), - ]; - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -use Twig\Extension\AbstractExtension; -use Twig_SimpleFunction; - -final class TwigExtensionWithMissingCallable extends AbstractExtension -{ - public function getFunctions() - { - return [ - new Twig_SimpleFunction('someFunctionName', [$this, 'someMethod']), - ]; - } - - public function someMethod() - { - // ... - } -} -CODE_SAMPLE - ), - ]); - } - - private function matchTwoExprs(Array_ $array): ?TwoExprs - { - if (count($array->items) !== 2) { - return null; - } - - $firstItem = $array->items[0]; - if (! $firstItem instanceof ArrayItem) { - return null; - } - - if (! $firstItem->value instanceof Variable) { - return null; - } - - $firstExpr = $firstItem->value; - - $secondItem = $array->items[1]; - if (! $secondItem instanceof ArrayItem) { - return null; - } - - $secondExpr = $secondItem->value; - - return new TwoExprs($firstExpr, $secondExpr); - } - - private function isThisVariable(Expr $expr): bool - { - if (! $expr instanceof Variable) { - return false; - } - - return $expr->name === 'this'; - } -} diff --git a/packages/Symfony/ValueObject/PropertyMetadata.php b/packages/Symfony/ValueObject/PropertyMetadata.php deleted file mode 100644 index 029c9251..00000000 --- a/packages/Symfony/ValueObject/PropertyMetadata.php +++ /dev/null @@ -1,64 +0,0 @@ -phpPropertyReflection = $phpPropertyReflection; - $this->nativeReflectionProperty = $nativeReflectionProperty; - $this->propertyLine = $propertyLine; - } - - public function getPropertyType(): Type - { - return $this->phpPropertyReflection->getReadableType(); - } - - public function getDocComment(): string - { - return (string) $this->phpPropertyReflection->getDocComment(); - } - - public function getFileName(): string - { - $reflectionClass = $this->nativeReflectionProperty->getDeclaringClass(); - - $fileName = $reflectionClass->getFileName(); - if ($fileName === false) { - throw new ShouldNotHappenException(); - } - - return $fileName; - } - - public function getPropertyName(): string - { - return $this->nativeReflectionProperty->getName(); - } - - public function getPropertyLine(): int - { - return $this->propertyLine; - } -} diff --git a/packages/Symfony/ValueObject/TwoExprs.php b/packages/Symfony/ValueObject/TwoExprs.php deleted file mode 100644 index 37750e81..00000000 --- a/packages/Symfony/ValueObject/TwoExprs.php +++ /dev/null @@ -1,34 +0,0 @@ -firstExpr = $firstExpr; - $this->secondExpr = $secondExpr; - } - - public function getFirstExpr(): Expr - { - return $this->firstExpr; - } - - public function getSecondExpr(): Expr - { - return $this->secondExpr; - } -} diff --git a/packages/Testing/StaticPHPUnitEnvironment.php b/packages/Testing/StaticPHPUnitEnvironment.php deleted file mode 100644 index 49669822..00000000 --- a/packages/Testing/StaticPHPUnitEnvironment.php +++ /dev/null @@ -1,16 +0,0 @@ - + + tests + tests/Rules/ClassNameRespectsParentSuffixRule/Fixture/ diff --git a/rector.php b/rector.php new file mode 100644 index 00000000..e68c64ff --- /dev/null +++ b/rector.php @@ -0,0 +1,41 @@ +sets([ + PHPUnitSetList::PHPUNIT_100, + SetList::CODE_QUALITY, + SetList::DEAD_CODE, + LevelSetList::UP_TO_PHP_81, + SetList::CODING_STYLE, + SetList::TYPE_DECLARATION, + SetList::NAMING, + SetList::PRIVATIZATION, + SetList::EARLY_RETURN, + PHPUnitSetList::PHPUNIT_CODE_QUALITY, + ]); + + $rectorConfig->paths([ + __DIR__ . '/config', + __DIR__ . '/src', + __DIR__ . '/tests', + ]); + + $rectorConfig->importNames(); + + $rectorConfig->skip([ + '*/Source/*', + '*/Fixture/*', + ]); + + $rectorConfig->ruleWithConfiguration(\Rector\Php55\Rector\String_\StringClassNameToClassConstantRector::class, [ + 'Symfony\Component\Console\*', + 'Rector\Contract\Rector\ConfigurableRectorInterface', + ]); +}; diff --git a/src-for-tests/SomeClass.php b/src-for-tests/SomeClass.php deleted file mode 100644 index 17ce8504..00000000 --- a/src-for-tests/SomeClass.php +++ /dev/null @@ -1,13 +0,0 @@ -name; - } -} diff --git a/src/Collector/ClassConst/ClassConstFetchCollector.php b/src/Collector/ClassConst/ClassConstFetchCollector.php deleted file mode 100644 index 7d68484a..00000000 --- a/src/Collector/ClassConst/ClassConstFetchCollector.php +++ /dev/null @@ -1,55 +0,0 @@ - - * @deprecated - */ -final class ClassConstFetchCollector implements Collector -{ - public function getNodeType(): string - { - return ClassConstFetch::class; - } - - /** - * @param ClassConstFetch $node - * @return string[]|null - */ - public function processNode(Node $node, Scope $scope): ?array - { - if (! $node->class instanceof Name) { - return null; - } - - if (! $node->name instanceof Identifier) { - return null; - } - - $className = $node->class->toString(); - $constantName = $node->name->toString(); - - $classReflection = $scope->getClassReflection(); - if ($classReflection !== null && $classReflection->hasConstant($constantName)) { - $constantReflection = $classReflection->getConstant($constantName); - $declaringClass = $constantReflection->getDeclaringClass(); - if ($declaringClass->getFileName() !== $classReflection->getFileName()) { - return [$declaringClass->getName() . '::' . $constantName]; - } - - return null; - } - - return [$className . '::' . $constantName]; - } -} diff --git a/src/Collector/ClassConst/PublicClassLikeConstCollector.php b/src/Collector/ClassConst/PublicClassLikeConstCollector.php deleted file mode 100644 index b2bfe5bd..00000000 --- a/src/Collector/ClassConst/PublicClassLikeConstCollector.php +++ /dev/null @@ -1,60 +0,0 @@ -> - * @deprecated - */ -final class PublicClassLikeConstCollector implements Collector -{ - /** - * @var \Symplify\PHPStanRules\PhpDoc\ApiDocStmtAnalyzer - */ - private $apiDocStmtAnalyzer; - public function __construct(ApiDocStmtAnalyzer $apiDocStmtAnalyzer) - { - $this->apiDocStmtAnalyzer = $apiDocStmtAnalyzer; - } - - public function getNodeType(): string - { - return ClassConst::class; - } - - /** - * @param ClassConst $node - * @return array|null - */ - public function processNode(Node $node, Scope $scope): ?array - { - $classReflection = $scope->getClassReflection(); - if (! $classReflection instanceof ClassReflection) { - return null; - } - - if (! $node->isPublic()) { - return null; - } - - if ($this->apiDocStmtAnalyzer->isApiDoc($node, $classReflection)) { - return null; - } - - $constantNames = []; - foreach ($node->consts as $constConst) { - $constantNames[] = [$classReflection->getName(), $constConst->name->toString(), $node->getLine()]; - } - - return $constantNames; - } -} diff --git a/src/Collector/ClassConst/RegexClassConstCollector.php b/src/Collector/ClassConst/RegexClassConstCollector.php deleted file mode 100644 index 0f4f35fd..00000000 --- a/src/Collector/ClassConst/RegexClassConstCollector.php +++ /dev/null @@ -1,57 +0,0 @@ -> - */ -final class RegexClassConstCollector implements Collector -{ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return array - */ - public function processNode(Node $node, Scope $scope): ?array - { - $classLike = $node->getOriginalNode(); - - $collectedConstants = []; - - foreach ($classLike->getConstants() as $classConst) { - // we need exactly one constant - if (count($classConst->consts) !== 1) { - continue; - } - - $constConst = $classConst->consts[0]; - $constantName = $constConst->name->toString(); - - if (substr_compare($constantName, '_REGEX', -strlen('_REGEX')) !== 0) { - continue; - } - - $constValueType = $scope->getType($constConst->value); - if (! $constValueType instanceof ConstantStringType) { - continue; - } - - $resolvedValue = $constValueType->getValue(); - $collectedConstants[] = [$constantName, $resolvedValue, $constConst->getLine()]; - } - - return $collectedConstants; - } -} diff --git a/src/Collector/ClassLike/PropertyTypeSeaLevelCollector.php b/src/Collector/ClassLike/PropertyTypeSeaLevelCollector.php deleted file mode 100644 index fa281f5d..00000000 --- a/src/Collector/ClassLike/PropertyTypeSeaLevelCollector.php +++ /dev/null @@ -1,72 +0,0 @@ -> - * - * @see \Symplify\PHPStanRules\Rules\Explicit\PropertyTypeDeclarationSeaLevelRule - */ -final class PropertyTypeSeaLevelCollector implements Collector -{ - /** - * @readonly - * @var \PhpParser\PrettyPrinter\Standard - */ - private $printerStandard; - public function __construct(Standard $printerStandard) - { - $this->printerStandard = $printerStandard; - } - - public function getNodeType(): string - { - return ClassLike::class; - } - - /** - * @param ClassLike $node - * @return array{int, int, string} - */ - public function processNode(Node $node, Scope $scope): ?array - { - $printedProperties = ''; - - // return typed properties/all properties - $propertyCount = count($node->getProperties()); - - $typedPropertyCount = 0; - - foreach ($node->getProperties() as $property) { - if ($property->type instanceof Node) { - ++$typedPropertyCount; - continue; - } - - $docComment = $property->getDocComment(); - if ($docComment instanceof Doc) { - $docCommentText = $docComment->getText(); - - // skip as unable to type - if (strpos($docCommentText, 'callable') !== false || strpos($docCommentText, 'resource') !== false) { - ++$typedPropertyCount; - continue; - } - } - - // give useful context - $printedProperties .= PHP_EOL . PHP_EOL . $this->printerStandard->prettyPrint([$property]); - } - - return [$typedPropertyCount, $propertyCount, $printedProperties]; - } -} diff --git a/src/Collector/ClassLike/TraitMethodNameCollector.php b/src/Collector/ClassLike/TraitMethodNameCollector.php deleted file mode 100644 index 5def4d50..00000000 --- a/src/Collector/ClassLike/TraitMethodNameCollector.php +++ /dev/null @@ -1,65 +0,0 @@ -> - */ -final class TraitMethodNameCollector implements Collector -{ - /** - * @var \PHPStan\Reflection\ReflectionProvider - */ - private $reflectionProvider; - public function __construct(ReflectionProvider $reflectionProvider) - { - $this->reflectionProvider = $reflectionProvider; - } - - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return array{string[], int}|null - */ - public function processNode(Node $node, Scope $scope): ?array - { - $classLike = $node->getOriginalNode(); - - if (! $classLike instanceof Class_) { - return null; - } - - $traitClassMethodNames = []; - - foreach ($classLike->getTraitUses() as $traitUse) { - foreach ($traitUse->traits as $trait) { - $traitName = $trait->toString(); - if (! $this->reflectionProvider->hasClass($traitName)) { - continue; - } - - $traitReflection = $this->reflectionProvider->getClass($traitName); - $nativeTraitReflection = $traitReflection->getNativeReflection(); - - foreach ($nativeTraitReflection->getMethods() as $methodReflection) { - $traitClassMethodNames[] = $methodReflection->getName(); - } - } - } - - return [$traitClassMethodNames, $node->getLine()]; - } -} diff --git a/src/Collector/ClassMethod/ClassMethodContentCollector.php b/src/Collector/ClassMethod/ClassMethodContentCollector.php deleted file mode 100644 index 5f99c87c..00000000 --- a/src/Collector/ClassMethod/ClassMethodContentCollector.php +++ /dev/null @@ -1,100 +0,0 @@ - - */ -final class ClassMethodContentCollector implements Collector -{ - /** - * @var array - */ - private const EXCLUDED_TYPES = [Kernel::class, Extension::class, TestCase::class]; - - /** - * @var string[] - */ - private const EXCLUDED_METHOD_NAMES = ['getNodeType', 'getNodeTypes']; - /** - * @var \Symplify\PHPStanRules\Printer\DuplicatedClassMethodPrinter - */ - private $duplicatedClassMethodPrinter; - public function __construct(DuplicatedClassMethodPrinter $duplicatedClassMethodPrinter) - { - $this->duplicatedClassMethodPrinter = $duplicatedClassMethodPrinter; - } - - public function getNodeType(): string - { - return InClassMethodNode::class; - } - - /** - * @param InClassMethodNode $node - * @return mixed[]|null - */ - public function processNode(Node $node, Scope $scope): ?array - { - $classMethod = $node->getOriginalNode(); - if ($this->shouldSkipClassMethod($classMethod, $scope)) { - return null; - } - - $classMethodName = $classMethod->name->toString(); - if (in_array($classMethodName, self::EXCLUDED_METHOD_NAMES, true)) { - return null; - } - - $printedClassMethod = $this->duplicatedClassMethodPrinter->printClassMethod($classMethod); - - return [$classMethodName, $classMethod->getLine(), $printedClassMethod]; - } - - private function shouldSkipClassMethod(ClassMethod $classMethod, Scope $scope): bool - { - if ($classMethod->isMagic()) { - return true; - } - - // traits are to magic to analyse - if ($scope->isInTrait()) { - return true; - } - - if (! $scope->isInClass()) { - return true; - } - - return $this->shouldSkipClassType($scope); - } - - private function shouldSkipClassType(Scope $scope): bool - { - $classReflection = $scope->getClassReflection(); - if (! $classReflection instanceof ClassReflection) { - return true; - } - - foreach (self::EXCLUDED_TYPES as $excludedType) { - if ($classReflection->isSubclassOf($excludedType)) { - return true; - } - } - - return false; - } -} diff --git a/src/Collector/ClassMethod/FormTypeClassCollector.php b/src/Collector/ClassMethod/FormTypeClassCollector.php deleted file mode 100644 index a2b359ee..00000000 --- a/src/Collector/ClassMethod/FormTypeClassCollector.php +++ /dev/null @@ -1,129 +0,0 @@ - - */ -final class FormTypeClassCollector implements Collector -{ - /** - * @var \PhpParser\NodeFinder - */ - private $nodeFinder; - public function __construct(NodeFinder $nodeFinder) - { - $this->nodeFinder = $nodeFinder; - } - public function getNodeType(): string - { - return ClassMethod::class; - } - - /** - * @param ClassMethod $node - * @return string[]|null - */ - public function processNode(Node $node, Scope $scope): ?array - { - $methodName = $node->name->toString(); - if ($methodName !== 'configureOptions') { - return null; - } - - $stmts = $node->stmts; - if (! is_array($stmts)) { - return null; - } - - /** @var MethodCall[] $methodCalls */ - $methodCalls = $this->nodeFinder->findInstanceOf($stmts, MethodCall::class); - - foreach ($methodCalls as $methodCall) { - if (! $methodCall->name instanceof Identifier) { - continue; - } - - $methodCallName = $methodCall->name->toString(); - if ($methodCallName === 'setDefaults') { - return $this->resolveDataClassFromSetDefaults($methodCall, $scope); - } - - if ($methodCallName === 'setDefault') { - return $this->resolveDataClassFromSetDefault($methodCall, $scope); - } - } - - return null; - } - - /** - * @return string[]|null - */ - private function resolveDataClassFromSetDefaults(MethodCall $methodCall, Scope $scope): ?array - { - /** @var ArrayItem[] $arrayItems */ - $arrayItems = $this->nodeFinder->findInstanceOf($methodCall->args, ArrayItem::class); - - foreach ($arrayItems as $arrayItem) { - if (! $arrayItem->key instanceof String_) { - continue; - } - - $arrayItemKey = $arrayItem->key->value; - if ($arrayItemKey !== 'data_class') { - continue; - } - - $arrayValueType = $scope->getType($arrayItem->value); - if (! $arrayValueType instanceof ConstantStringType) { - continue; - } - - return [$arrayValueType->getValue()]; - } - - return null; - } - - /** - * @return string[]|null - */ - private function resolveDataClassFromSetDefault(MethodCall $methodCall, Scope $scope): ?array - { - $args = $methodCall->getArgs(); - if (count($args) !== 2) { - return null; - } - - $firstArgValue = $args[0]->value; - if (! $firstArgValue instanceof String_) { - return null; - } - - if ($firstArgValue->value !== 'data_class') { - return null; - } - - $secondArgValue = $args[1]->value; - $secondArgType = $scope->getType($secondArgValue); - if (! $secondArgType instanceof ConstantStringType) { - return null; - } - - return [$secondArgType->getValue()]; - } -} diff --git a/src/Collector/ClassMethod/MethodCallCollector.php b/src/Collector/ClassMethod/MethodCallCollector.php deleted file mode 100644 index 509d0504..00000000 --- a/src/Collector/ClassMethod/MethodCallCollector.php +++ /dev/null @@ -1,84 +0,0 @@ -|null> - * @deprecated - */ -final class MethodCallCollector implements Collector -{ - /** - * @var \PHPStan\Reflection\ReflectionProvider - */ - private $reflectionProvider; - /** - * @var \Symplify\PHPStanRules\Matcher\ClassMethodCallReferenceResolver - */ - private $classMethodCallReferenceResolver; - public function __construct(ReflectionProvider $reflectionProvider, ClassMethodCallReferenceResolver $classMethodCallReferenceResolver) - { - $this->reflectionProvider = $reflectionProvider; - $this->classMethodCallReferenceResolver = $classMethodCallReferenceResolver; - } - public function getNodeType(): string - { - return MethodCall::class; - } - - /** - * @param MethodCall $node - * @return string[]|null - */ - public function processNode(Node $node, Scope $scope): ?array - { - if ($node->name instanceof Expr) { - return null; - } - - $classMethodCallReference = $this->classMethodCallReferenceResolver->resolve($node, $scope, false); - if (! $classMethodCallReference instanceof MethodCallReference) { - return null; - } - - $className = $classMethodCallReference->getClass(); - $methodName = $classMethodCallReference->getMethod(); - - $classMethodReferences = $this->findParentClassMethodReferences($className, $methodName); - $classMethodReferences[] = $className . '::' . $methodName; - - return $classMethodReferences; - } - - /** - * @return string[] - */ - private function findParentClassMethodReferences(string $className, string $methodName): array - { - if (! $this->reflectionProvider->hasClass($className)) { - return []; - } - - $classReflection = $this->reflectionProvider->getClass($className); - - $classMethodReferences = []; - foreach ($classReflection->getParents() as $parentClassReflection) { - if ($parentClassReflection->hasNativeMethod($methodName)) { - $classMethodReferences[] = $parentClassReflection->getName() . '::' . $methodName; - } - } - - return $classMethodReferences; - } -} diff --git a/src/Collector/ClassMethod/NewAndSetterCallsCollector.php b/src/Collector/ClassMethod/NewAndSetterCallsCollector.php deleted file mode 100644 index 9684b4f3..00000000 --- a/src/Collector/ClassMethod/NewAndSetterCallsCollector.php +++ /dev/null @@ -1,173 +0,0 @@ ->> - */ -final class NewAndSetterCallsCollector implements Collector -{ - /** - * @var \PHPStan\Reflection\ReflectionProvider - */ - private $reflectionProvider; - public function __construct(ReflectionProvider $reflectionProvider) - { - $this->reflectionProvider = $reflectionProvider; - } - - public function getNodeType(): string - { - return ClassMethod::class; - } - - /** - * @param ClassMethod $node - * @return array>|null - */ - public function processNode(Node $node, Scope $scope): ?array - { - $currentClassName = null; - $currentVariableName = null; - - $collected = []; - - // collect new + setter calls - foreach ((array) $node->stmts as $stmt) { - $assign = $this->matchExprAssignToVariable($stmt); - - if ($assign instanceof Assign) { - /** @var New_ $new */ - $new = $assign->expr; - if (! $new->class instanceof Name) { - continue; - } - - /** @var Variable $variable */ - $variable = $assign->var; - - if (! is_string($variable->name)) { - continue; - } - - $currentVariableName = $variable->name; - $className = $new->class->toString(); - - // not found - if ($this->shouldSkipClassName($className)) { - continue; - } - - $currentClassName = $className; - } - - // let's collect calls on existing variable - if (! is_string($currentVariableName)) { - continue; - } - - if (! is_string($currentClassName)) { - continue; - } - - if (! $stmt instanceof Expression) { - continue; - } - - if (! $stmt->expr instanceof MethodCall) { - continue; - } - - $methodCall = $stmt->expr; - if (! $methodCall->var instanceof Variable) { - continue; - } - - if ($methodCall->var->name instanceof Expr) { - continue; - } - - // matching variable name? - $variableName = $methodCall->var->name; - if ($variableName !== $currentVariableName) { - continue; - } - - if (! $methodCall->name instanceof Identifier) { - continue; - } - - $methodName = $methodCall->name->toString(); - $collected[$currentClassName][$variableName][] = $methodName; - } - - if ($collected === []) { - return null; - } - - return $collected; - } - - private function matchExprAssignToVariable(Stmt $stmt): ?Assign - { - if (! $stmt instanceof Expression) { - return null; - } - - if (! $stmt->expr instanceof Assign) { - return null; - } - - $assign = $stmt->expr; - if (! $assign->expr instanceof New_) { - return null; - } - - if (! $assign->var instanceof Variable) { - return null; - } - - return $assign; - } - - private function shouldSkipClassName(string $className): bool - { - // not found, probably not a class - if (! $this->reflectionProvider->hasClass($className)) { - return true; - } - - $classReflection = $this->reflectionProvider->getClass($className); - - // skip internal classes - if ($classReflection->isBuiltin()) { - return true; - } - - $fileName = $classReflection->getFileName(); - - // not found - if ($fileName === null) { - return true; - } - - return strpos($fileName, 'vendor') !== false; - } -} diff --git a/src/Collector/ClassMethod/PublicClassMethodCollector.php b/src/Collector/ClassMethod/PublicClassMethodCollector.php deleted file mode 100644 index 5f603126..00000000 --- a/src/Collector/ClassMethod/PublicClassMethodCollector.php +++ /dev/null @@ -1,82 +0,0 @@ - - * @deprecated - */ -final class PublicClassMethodCollector implements Collector -{ - /** - * @var \Symplify\PHPStanRules\PhpDoc\ApiDocStmtAnalyzer - */ - private $apiDocStmtAnalyzer; - /** - * @var \Symplify\PHPStanRules\Matcher\Collector\PublicClassMethodMatcher - */ - private $publicClassMethodMatcher; - public function __construct(ApiDocStmtAnalyzer $apiDocStmtAnalyzer, PublicClassMethodMatcher $publicClassMethodMatcher) - { - $this->apiDocStmtAnalyzer = $apiDocStmtAnalyzer; - $this->publicClassMethodMatcher = $publicClassMethodMatcher; - } - public function getNodeType(): string - { - return ClassMethod::class; - } - - /** - * @param ClassMethod $node - * @return array|null - */ - public function processNode(Node $node, Scope $scope): ?array - { - $classReflection = $scope->getClassReflection(); - - // skip - if ($classReflection instanceof ClassReflection && $classReflection->isSubclassOf( - ExtensionInterface::class - )) { - return null; - } - - if ($this->publicClassMethodMatcher->shouldSkipClassMethod($node)) { - return null; - } - - // only if the class has no parents/implementers, to avoid class method required by contracts - $classReflection = $scope->getClassReflection(); - if (! $classReflection instanceof ClassReflection) { - return null; - } - - if ($this->apiDocStmtAnalyzer->isApiDoc($node, $classReflection)) { - return null; - } - - if ($this->publicClassMethodMatcher->shouldSkipClassReflection($classReflection)) { - return null; - } - - $methodName = $node->name->toString(); - - // is this method required by parent contract? skip it - if ($this->publicClassMethodMatcher->isUsedByParentClassOrInterface($classReflection, $methodName)) { - return null; - } - - return [$classReflection->getName(), $methodName, $node->getLine()]; - } -} diff --git a/src/Collector/ClassMethod/PublicClassMethodParamTypesCollector.php b/src/Collector/ClassMethod/PublicClassMethodParamTypesCollector.php index 19a685b4..bfd6cbfc 100644 --- a/src/Collector/ClassMethod/PublicClassMethodParamTypesCollector.php +++ b/src/Collector/ClassMethod/PublicClassMethodParamTypesCollector.php @@ -2,39 +2,27 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Collector\ClassMethod; +namespace Rector\TypePerfect\Collector\ClassMethod; use PhpParser\Node; use PhpParser\Node\Stmt\ClassMethod; use PHPStan\Analyser\Scope; use PHPStan\Collectors\Collector; use PHPStan\Reflection\ClassReflection; -use Symplify\PHPStanRules\Matcher\Collector\PublicClassMethodMatcher; -use Symplify\PHPStanRules\PhpDoc\ApiDocStmtAnalyzer; -use Symplify\PHPStanRules\Printer\CollectorMetadataPrinter; +use Rector\TypePerfect\Matcher\Collector\PublicClassMethodMatcher; +use Rector\TypePerfect\PhpDoc\ApiDocStmtAnalyzer; +use Rector\TypePerfect\Printer\CollectorMetadataPrinter; /** * @implements Collector */ final class PublicClassMethodParamTypesCollector implements Collector { - /** - * @var \Symplify\PHPStanRules\PhpDoc\ApiDocStmtAnalyzer - */ - private $apiDocStmtAnalyzer; - /** - * @var \Symplify\PHPStanRules\Matcher\Collector\PublicClassMethodMatcher - */ - private $publicClassMethodMatcher; - /** - * @var \Symplify\PHPStanRules\Printer\CollectorMetadataPrinter - */ - private $collectorMetadataPrinter; - public function __construct(ApiDocStmtAnalyzer $apiDocStmtAnalyzer, PublicClassMethodMatcher $publicClassMethodMatcher, CollectorMetadataPrinter $collectorMetadataPrinter) - { - $this->apiDocStmtAnalyzer = $apiDocStmtAnalyzer; - $this->publicClassMethodMatcher = $publicClassMethodMatcher; - $this->collectorMetadataPrinter = $collectorMetadataPrinter; + public function __construct( + private readonly ApiDocStmtAnalyzer $apiDocStmtAnalyzer, + private readonly PublicClassMethodMatcher $publicClassMethodMatcher, + private readonly CollectorMetadataPrinter $collectorMetadataPrinter + ) { } public function getNodeType(): string @@ -62,7 +50,7 @@ public function processNode(Node $node, Scope $scope): ?array return null; } - if ($this->apiDocStmtAnalyzer->isApiDoc($node, $classReflection)) { + if ($this->apiDocStmtAnalyzer->hasApiDoc($node, $classReflection)) { return null; } diff --git a/src/Collector/Class_/PublicPropertyCollector.php b/src/Collector/Class_/PublicPropertyCollector.php deleted file mode 100644 index 317970df..00000000 --- a/src/Collector/Class_/PublicPropertyCollector.php +++ /dev/null @@ -1,75 +0,0 @@ -> - * @deprecated - */ -final class PublicPropertyCollector implements Collector -{ - /** - * @var \Symplify\PHPStanRules\PhpDoc\ApiDocStmtAnalyzer - */ - private $apiDocStmtAnalyzer; - public function __construct(ApiDocStmtAnalyzer $apiDocStmtAnalyzer) - { - $this->apiDocStmtAnalyzer = $apiDocStmtAnalyzer; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return array|null - */ - public function processNode(Node $node, Scope $scope): ?array - { - $classReflection = $scope->getClassReflection(); - if (! $classReflection instanceof ClassReflection) { - return null; - } - - if ($this->apiDocStmtAnalyzer->isApiDoc($node, $classReflection)) { - return null; - } - - $classLike = $node->getOriginalNode(); - if (! $classLike instanceof Class_) { - return null; - } - - $publicPropertyNames = []; - foreach ($classLike->getProperties() as $property) { - if (! $property->isPublic()) { - continue; - } - - foreach ($property->props as $propertyProperty) { - $publicPropertyNames[] = [ - $classReflection->getName(), - $propertyProperty->name->toString(), - $node->getLine(), - ]; - } - } - - return $publicPropertyNames; - } -} diff --git a/src/Collector/Class_/PublicStaticPropertyCollector.php b/src/Collector/Class_/PublicStaticPropertyCollector.php deleted file mode 100644 index 6e8386f3..00000000 --- a/src/Collector/Class_/PublicStaticPropertyCollector.php +++ /dev/null @@ -1,79 +0,0 @@ -> - * @deprecated - */ -final class PublicStaticPropertyCollector implements Collector -{ - /** - * @var \Symplify\PHPStanRules\PhpDoc\ApiDocStmtAnalyzer - */ - private $apiDocStmtAnalyzer; - public function __construct(ApiDocStmtAnalyzer $apiDocStmtAnalyzer) - { - $this->apiDocStmtAnalyzer = $apiDocStmtAnalyzer; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return array|null - */ - public function processNode(Node $node, Scope $scope): ?array - { - $classReflection = $scope->getClassReflection(); - if (! $classReflection instanceof ClassReflection) { - return null; - } - - if ($this->apiDocStmtAnalyzer->isApiDoc($node, $classReflection)) { - return null; - } - - $classLike = $node->getOriginalNode(); - if (! $classLike instanceof Class_) { - return null; - } - - $staticPropertyNames = []; - foreach ($classLike->getProperties() as $property) { - if (! $property->isPublic()) { - continue; - } - - if (! $property->isStatic()) { - continue; - } - - foreach ($property->props as $propertyProperty) { - $staticPropertyNames[] = [ - $classReflection->getName(), - $propertyProperty->name->toString(), - $node->getLine(), - ]; - } - } - - return $staticPropertyNames; - } -} diff --git a/src/Collector/FunctionLike/ParamTypeSeaLevelCollector.php b/src/Collector/FunctionLike/ParamTypeSeaLevelCollector.php deleted file mode 100644 index 8998185c..00000000 --- a/src/Collector/FunctionLike/ParamTypeSeaLevelCollector.php +++ /dev/null @@ -1,90 +0,0 @@ -> - * - * @see \Symplify\PHPStanRules\Rules\Explicit\ParamTypeDeclarationSeaLevelRule - */ -final class ParamTypeSeaLevelCollector implements Collector -{ - /** - * @readonly - * @var \PhpParser\PrettyPrinter\Standard - */ - private $printerStandard; - public function __construct(Standard $printerStandard) - { - $this->printerStandard = $printerStandard; - } - - public function getNodeType(): string - { - return FunctionLike::class; - } - - /** - * @param FunctionLike $node - * @return array{int, int, string} - */ - public function processNode(Node $node, Scope $scope): ?array - { - if ($this->shouldSkipFunctionLike($node)) { - return [0, 0, '']; - } - - $paramCount = count($node->getParams()); - - $typedParamCount = 0; - foreach ($node->getParams() as $param) { - if ($param->variadic) { - // skip variadic - --$paramCount; - continue; - } - - if ($param->type === null) { - continue; - } - - ++$typedParamCount; - } - - // missing at least 1 type - $printedClassMethod = $paramCount !== $typedParamCount ? $this->printerStandard->prettyPrint([$node]) : ''; - - return [$typedParamCount, $paramCount, $printedClassMethod]; - } - - private function shouldSkipFunctionLike(FunctionLike $functionLike): bool - { - // nothing to analyse - if ($functionLike->getParams() === []) { - return true; - } - - return $this->hasFunctionLikeCallableParam($functionLike); - } - - private function hasFunctionLikeCallableParam(FunctionLike $functionLike): bool - { - // skip callable, can be anythings - $docComment = $functionLike->getDocComment(); - if (! $docComment instanceof Doc) { - return false; - } - - $docCommentText = $docComment->getText(); - return strpos($docCommentText, '@param callable') !== false; - } -} diff --git a/src/Collector/FunctionLike/ReturnTypeSeaLevelCollector.php b/src/Collector/FunctionLike/ReturnTypeSeaLevelCollector.php deleted file mode 100644 index e557eb6f..00000000 --- a/src/Collector/FunctionLike/ReturnTypeSeaLevelCollector.php +++ /dev/null @@ -1,56 +0,0 @@ -> - * - * @see \Symplify\PHPStanRules\Rules\Explicit\ReturnTypeDeclarationSeaLevelRule - */ -final class ReturnTypeSeaLevelCollector implements Collector -{ - /** - * @readonly - * @var \PhpParser\PrettyPrinter\Standard - */ - private $printerStandard; - public function __construct(Standard $printerStandard) - { - $this->printerStandard = $printerStandard; - } - - public function getNodeType(): string - { - return ClassMethod::class; - } - - /** - * @param ClassMethod $node - * @return array{int, int, string} - */ - public function processNode(Node $node, Scope $scope): ?array - { - // skip magic - if ($node->isMagic()) { - return [0, 0, '']; - } - - if ($node->returnType instanceof Node) { - $typedReturnCount = 1; - $printedNode = ''; - } else { - $typedReturnCount = 0; - $printedNode = $this->printerStandard->prettyPrint([$node]); - } - - return [$typedReturnCount, 1, $printedNode]; - } -} diff --git a/src/Collector/MethodCall/MethodCallArgTypesCollector.php b/src/Collector/MethodCall/MethodCallArgTypesCollector.php index c2791b76..d5a7d12c 100644 --- a/src/Collector/MethodCall/MethodCallArgTypesCollector.php +++ b/src/Collector/MethodCall/MethodCallArgTypesCollector.php @@ -2,34 +2,27 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Collector\MethodCall; +namespace Rector\TypePerfect\Collector\MethodCall; use PhpParser\Node; use PhpParser\Node\Expr\MethodCall; use PHPStan\Analyser\Scope; use PHPStan\Collectors\Collector; -use Symplify\PHPStanRules\Matcher\ClassMethodCallReferenceResolver; -use Symplify\PHPStanRules\Printer\CollectorMetadataPrinter; -use Symplify\PHPStanRules\ValueObject\MethodCallReference; +use Rector\TypePerfect\Matcher\ClassMethodCallReferenceResolver; +use Rector\TypePerfect\Printer\CollectorMetadataPrinter; +use Rector\TypePerfect\ValueObject\MethodCallReference; /** * @implements Collector|null> */ final class MethodCallArgTypesCollector implements Collector { - /** - * @var \Symplify\PHPStanRules\Matcher\ClassMethodCallReferenceResolver - */ - private $classMethodCallReferenceResolver; - /** - * @var \Symplify\PHPStanRules\Printer\CollectorMetadataPrinter - */ - private $collectorMetadataPrinter; - public function __construct(ClassMethodCallReferenceResolver $classMethodCallReferenceResolver, CollectorMetadataPrinter $collectorMetadataPrinter) - { - $this->classMethodCallReferenceResolver = $classMethodCallReferenceResolver; - $this->collectorMetadataPrinter = $collectorMetadataPrinter; + public function __construct( + private readonly ClassMethodCallReferenceResolver $classMethodCallReferenceResolver, + private readonly CollectorMetadataPrinter $collectorMetadataPrinter, + ) { } + public function getNodeType(): string { return MethodCall::class; @@ -50,13 +43,17 @@ public function processNode(Node $node, Scope $scope): ?array return null; } - $className = $classMethodCallReference->getClass(); - $methodName = $classMethodCallReference->getMethod(); - - $classMethodReference = $className . '::' . $methodName; + $classMethodReference = $this->createClassMethodReference($classMethodCallReference); $stringArgTypesString = $this->collectorMetadataPrinter->printArgTypesAsString($node, $scope); - return [$classMethodReference, $stringArgTypesString]; } + + private function createClassMethodReference(MethodCallReference $classMethodCallReference): string + { + $className = $classMethodCallReference->getClass(); + $methodName = $classMethodCallReference->getMethod(); + + return $className . '::' . $methodName; + } } diff --git a/src/Collector/MethodCallableNode/MethodCallableCollector.php b/src/Collector/MethodCallableNode/MethodCallableCollector.php new file mode 100644 index 00000000..667324be --- /dev/null +++ b/src/Collector/MethodCallableNode/MethodCallableCollector.php @@ -0,0 +1,58 @@ +|null> + * + * PHPStan has special node for first class callables of MethodCall + * + * @see https://github.com/phpstan/phpstan-src/blob/511c1e435fb43b8eb0ac310e6aa3230147963790/src/Analyser/NodeScopeResolver.php#L1936 + */ +final class MethodCallableCollector implements Collector +{ + public function __construct( + private readonly ClassMethodCallReferenceResolver $classMethodCallReferenceResolver, + ) { + } + + public function getNodeType(): string + { + return MethodCallableNode::class; + } + + /** + * @param MethodCallableNode $node + * @return array{string}|null + */ + public function processNode(Node $node, Scope $scope): ?array + { + $classMethodCallReference = $this->classMethodCallReferenceResolver->resolve($node, $scope, true); + if (! $classMethodCallReference instanceof MethodCallReference) { + return null; + } + + $classMethodReference = $this->createClassMethodReference($classMethodCallReference); + + // special case that should skip everything + return [$classMethodReference]; + } + + private function createClassMethodReference(MethodCallReference $classMethodCallReference): string + { + $className = $classMethodCallReference->getClass(); + $methodName = $classMethodCallReference->getMethod(); + + return $className . '::' . $methodName; + } +} diff --git a/src/Collector/PropertyFetch/PublicPropertyFetchCollector.php b/src/Collector/PropertyFetch/PublicPropertyFetchCollector.php deleted file mode 100644 index 461d15a7..00000000 --- a/src/Collector/PropertyFetch/PublicPropertyFetchCollector.php +++ /dev/null @@ -1,58 +0,0 @@ - - * @deprecated - */ -final class PublicPropertyFetchCollector implements Collector -{ - /** - * @return class-string - */ - public function getNodeType(): string - { - return PropertyFetch::class; - } - - /** - * @param PropertyFetch $node - * @return string[]|null - */ - public function processNode(Node $node, Scope $scope): ?array - { - if (! $node->var instanceof Variable) { - return null; - } - - // skip local - if ($node->var->name === 'this') { - return null; - } - - if (! $node->name instanceof Identifier) { - return null; - } - - $propertyFetcherType = $scope->getType($node->var); - if (! $propertyFetcherType instanceof TypeWithClassName) { - return null; - } - - $className = $propertyFetcherType->getClassName(); - $propertyName = $node->name->toString(); - - return [$className . '::' . $propertyName]; - } -} diff --git a/src/Collector/StaticPropertyFetch/PublicStaticPropertyFetchCollector.php b/src/Collector/StaticPropertyFetch/PublicStaticPropertyFetchCollector.php deleted file mode 100644 index 7da157a7..00000000 --- a/src/Collector/StaticPropertyFetch/PublicStaticPropertyFetchCollector.php +++ /dev/null @@ -1,49 +0,0 @@ - - * @deprecated - */ -final class PublicStaticPropertyFetchCollector implements Collector -{ - public function getNodeType(): string - { - return StaticPropertyFetch::class; - } - - /** - * @param StaticPropertyFetch $node - * @return string[]|null - */ - public function processNode(Node $node, Scope $scope): ?array - { - if (! $node->class instanceof Name) { - return null; - } - - if (! $node->name instanceof Identifier) { - return null; - } - - if ($node->class->toString() === 'self') { - // self fetch is allowed - return null; - } - - $className = $node->class->toString(); - $propertyName = $node->name->toString(); - - return [$className . '::' . $propertyName]; - } -} diff --git a/src/Collector/Variable/VariableNameCollector.php b/src/Collector/Variable/VariableNameCollector.php deleted file mode 100644 index e8e46c40..00000000 --- a/src/Collector/Variable/VariableNameCollector.php +++ /dev/null @@ -1,35 +0,0 @@ -|null> - */ -final class VariableNameCollector implements Collector -{ - public function getNodeType(): string - { - return Variable::class; - } - - /** - * @param Variable $node - * @return array{string, int}|null - */ - public function processNode(Node $node, Scope $scope): ?array - { - if ($node->name instanceof Expr) { - return null; - } - - return [$node->name, $node->getLine()]; - } -} diff --git a/src/Composer/ClassNamespaceMatcher.php b/src/Composer/ClassNamespaceMatcher.php deleted file mode 100644 index 4207e6c6..00000000 --- a/src/Composer/ClassNamespaceMatcher.php +++ /dev/null @@ -1,69 +0,0 @@ -directoryChecker = $directoryChecker; - } - - /** - * @param array $autoloadPsr4Paths - * @return ClassNamespaceAndDirectory[] - */ - public function matchPossibleDirectoriesForClass( - string $namespaceBeforeClass, - array $autoloadPsr4Paths, - Scope $scope - ): array { - $namespaceToDirectories = []; - - foreach ($autoloadPsr4Paths as $namespace => $directory) { - $namespace = rtrim($namespace, '\\') . '\\'; - if ($namespaceBeforeClass === $namespace) { - return []; - } - - $directories = $this->standardizeToArray($directory); - foreach ($directories as $directory) { - if (! $this->directoryChecker->isInDirectoryNamed($scope, $directory)) { - continue; - } - - $namespaceToDirectories[] = new ClassNamespaceAndDirectory( - $namespace, - $directory, - $namespaceBeforeClass - ); - continue 2; - } - } - - return $namespaceToDirectories; - } - - /** - * @param string|string[] $items - * @return string[] - */ - private function standardizeToArray($items): array - { - if (! is_array($items)) { - return [$items]; - } - - return $items; - } -} diff --git a/src/Composer/ComposerAutoloadResolver.php b/src/Composer/ComposerAutoloadResolver.php deleted file mode 100644 index 3d5c2252..00000000 --- a/src/Composer/ComposerAutoloadResolver.php +++ /dev/null @@ -1,34 +0,0 @@ - - */ - public function getPsr4Autoload(): array - { - if (! file_exists(self::COMPOSER_JSON_FILE)) { - return []; - } - - $fileContent = FileSystem::read(self::COMPOSER_JSON_FILE); - $composerJsonContent = Json::decode($fileContent, Json::FORCE_ARRAY); - - $autoloadPsr4 = $composerJsonContent['autoload']['psr-4'] ?? []; - $autoloadDevPsr4 = $composerJsonContent['autoload-dev']['psr-4'] ?? []; - - return array_merge($autoloadPsr4, $autoloadDevPsr4); - } -} diff --git a/src/Composer/ComposerVendorAutoloadResolver.php b/src/Composer/ComposerVendorAutoloadResolver.php deleted file mode 100644 index e0ead830..00000000 --- a/src/Composer/ComposerVendorAutoloadResolver.php +++ /dev/null @@ -1,25 +0,0 @@ - - */ - public function getPsr4Autoload(): array - { - if (! file_exists(self::COMPOSER_JSON_FILE)) { - return []; - } - - return require self::COMPOSER_JSON_FILE; - } -} diff --git a/src/Composer/Psr4PathValidator.php b/src/Composer/Psr4PathValidator.php deleted file mode 100644 index 2a4cf0c0..00000000 --- a/src/Composer/Psr4PathValidator.php +++ /dev/null @@ -1,47 +0,0 @@ -getSingleDirectory(), '/'); - $splitPaths = Strings::split($file, '#\/' . preg_quote($singleDirectory, '#') . '\/#'); - - if (count($splitPaths) === 1) { - return false; - } - - $directoryInNamespacedRoot = dirname($splitPaths[1]); - $normalizedDirectoryInNamespacedRoot = $this->normalizePath($directoryInNamespacedRoot); - - $namespaceSuffixByDirectoryClass = ltrim($normalizedDirectoryInNamespacedRoot, '\\'); - - // @todo put into value object - $namespaceSuffixByNamespaceBeforeClass = rtrim( - Strings::substring( - $classNamespaceAndDirectory->getNamespaceBeforeClass(), - strlen($classNamespaceAndDirectory->getNamespace()) - ), - '\\' - ); - - return $namespaceSuffixByDirectoryClass === $namespaceSuffixByNamespaceBeforeClass; - } - - private function normalizePath(string $path): string - { - return str_replace('/', '\\', $path); - } -} diff --git a/src/Contract/ManyNodeRuleInterface.php b/src/Contract/ManyNodeRuleInterface.php deleted file mode 100644 index 76a2a7b9..00000000 --- a/src/Contract/ManyNodeRuleInterface.php +++ /dev/null @@ -1,25 +0,0 @@ -> - */ - public function getNodeTypes(): array; - - /** - * @return array - */ - public function process(Node $node, Scope $scope): array; -} diff --git a/src/Contract/PhpDocParser/PhpDocNodeVisitorInterface.php b/src/Contract/PhpDocParser/PhpDocNodeVisitorInterface.php deleted file mode 100644 index 3e68fbfa..00000000 --- a/src/Contract/PhpDocParser/PhpDocNodeVisitorInterface.php +++ /dev/null @@ -1,27 +0,0 @@ -isNonEnumConstantName($prefix); - } - - private function isNonEnumConstantName(string $name): bool - { - // not enum, but rather validation limit - if (strncmp($name, 'MIN_', strlen('MIN_')) === 0) { - return true; - } - - if (substr_compare($name, '_MIN', -strlen('_MIN')) === 0) { - return true; - } - - if (strncmp($name, 'MAX_', strlen('MAX_')) === 0) { - return true; - } - - return substr_compare($name, '_MAX', -strlen('_MAX')) === 0; - } -} diff --git a/src/Enum/MethodName.php b/src/Enum/MethodName.php deleted file mode 100644 index a1410b9d..00000000 --- a/src/Enum/MethodName.php +++ /dev/null @@ -1,23 +0,0 @@ - $configuration - * @return RequiredWithMessage[] forbidden values as keys, optional helpful messages as value - */ - public function normalizeConfig(array $configuration): array - { - $requiredWithMessages = []; - - foreach ($configuration as $key => $value) { - if (is_int($key)) { - $requiredWithMessages[] = new RequiredWithMessage($value, null); - } elseif (is_string($key)) { - $requiredWithMessages[] = new RequiredWithMessage($key, $value); - } else { - throw new ShouldNotHappenException(); - } - } - - return $requiredWithMessages; - } -} diff --git a/src/Formatter/SeaLevelRuleErrorFormatter.php b/src/Formatter/SeaLevelRuleErrorFormatter.php deleted file mode 100644 index 15797850..00000000 --- a/src/Formatter/SeaLevelRuleErrorFormatter.php +++ /dev/null @@ -1,51 +0,0 @@ -= $minimalLevel) { - return []; - } - - $errorMessage = sprintf( - $message, - $propertyCount, - $propertyTypeDeclarationSeaLevel * 100, - $minimalLevel * 100 - ); - - if ($errors !== []) { - $errorMessage .= PHP_EOL . PHP_EOL; - $errorMessage .= implode(PHP_EOL . PHP_EOL, $errors); - $errorMessage .= PHP_EOL; - - // keep error printable - $errorMessage = Strings::truncate($errorMessage, 8000); - } - - return [$errorMessage]; - } -} diff --git a/src/Location/DirectoryChecker.php b/src/Location/DirectoryChecker.php deleted file mode 100644 index b1d0858c..00000000 --- a/src/Location/DirectoryChecker.php +++ /dev/null @@ -1,37 +0,0 @@ -isInDirectoryNamed($scope, $directoryName)) { - return true; - } - } - - return false; - } - - public function isInDirectoryNamed(Scope $scope, string $directoryName): bool - { - $normalized = $this->normalizePath($directoryName); - $directoryName = rtrim($normalized, '\/'); - - return strpos($scope->getFile(), DIRECTORY_SEPARATOR . $directoryName . DIRECTORY_SEPARATOR) !== false; - } - - private function normalizePath(string $directoryName): string - { - return str_replace('/', DIRECTORY_SEPARATOR, $directoryName); - } -} diff --git a/src/Matcher/ArrayStringAndFnMatcher.php b/src/Matcher/ArrayStringAndFnMatcher.php deleted file mode 100644 index 3fd3e8d6..00000000 --- a/src/Matcher/ArrayStringAndFnMatcher.php +++ /dev/null @@ -1,51 +0,0 @@ -isMatch($currentValue, $matchingValues)) { - return true; - } - - foreach ($matchingValues as $matchingValue) { - if (is_a($currentValue, $matchingValue, true)) { - return true; - } - } - - return false; - } - - /** - * @param string[] $matchingValues - */ - public function isMatch(string $currentValue, array $matchingValues): bool - { - foreach ($matchingValues as $matchingValue) { - if ($currentValue === $matchingValue) { - return true; - } - - if (fnmatch($matchingValue, $currentValue)) { - return true; - } - - if (fnmatch($matchingValue, $currentValue, FNM_NOESCAPE)) { - return true; - } - } - - return false; - } -} diff --git a/src/Matcher/ClassLikeNameMatcher.php b/src/Matcher/ClassLikeNameMatcher.php deleted file mode 100644 index 2022233d..00000000 --- a/src/Matcher/ClassLikeNameMatcher.php +++ /dev/null @@ -1,37 +0,0 @@ -\-\#]#'; - - public function isClassLikeNameMatchedAgainstPattern(string $classLikeName, string $namespaceWildcardPattern): bool - { - $regex = Strings::replace($namespaceWildcardPattern, self::REGEX_FOR_WILDCARD_TO_REGEX, static function (array $matches) : string { - switch ($matches[0]) { - case '**': - return '.*'; - case '*': - return '[^\\\\]*'; - case '?': - return '[^\\\\]'; - default: - return '\\' . $matches[0]; - } - }); - - return (bool) Strings::match($classLikeName, '#^' . $regex . '$#s'); - } -} diff --git a/src/Matcher/ClassMethodCallReferenceResolver.php b/src/Matcher/ClassMethodCallReferenceResolver.php index 285c10f6..747be901 100644 --- a/src/Matcher/ClassMethodCallReferenceResolver.php +++ b/src/Matcher/ClassMethodCallReferenceResolver.php @@ -2,25 +2,34 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Matcher; +namespace Rector\TypePerfect\Matcher; use PhpParser\Node\Expr; use PhpParser\Node\Expr\MethodCall; use PHPStan\Analyser\Scope; +use PHPStan\Node\MethodCallableNode; use PHPStan\Type\ThisType; use PHPStan\Type\TypeCombinator; use PHPStan\Type\TypeWithClassName; -use Symplify\PHPStanRules\ValueObject\MethodCallReference; +use Rector\TypePerfect\ValueObject\MethodCallReference; final class ClassMethodCallReferenceResolver { - public function resolve(MethodCall $methodCall, Scope $scope, bool $allowThisType): ?MethodCallReference + public function resolve(MethodCall|MethodCallableNode $methodCallOrMethodCallable, Scope $scope, bool $allowThisType): ?MethodCallReference { - if ($methodCall->name instanceof Expr) { + if ($methodCallOrMethodCallable instanceof MethodCallableNode) { + $methodName = $methodCallOrMethodCallable->getName(); + $variable = $methodCallOrMethodCallable->getVar(); + } else { + $methodName = $methodCallOrMethodCallable->name; + $variable = $methodCallOrMethodCallable->var; + } + + if ($methodName instanceof Expr) { return null; } - $callerType = $scope->getType($methodCall->var); + $callerType = $scope->getType($variable); // remove optional nullable type if (TypeCombinator::containsNull($callerType)) { @@ -37,8 +46,8 @@ public function resolve(MethodCall $methodCall, Scope $scope, bool $allowThisTyp // move to the class where method is defined, e.g. parent class defines the method, so it should be checked there $className = $callerType->getClassName(); - $methodName = $methodCall->name->toString(); + $methodNameString = $methodName->toString(); - return new MethodCallReference($className, $methodName); + return new MethodCallReference($className, $methodNameString); } } diff --git a/src/Matcher/Collector/PublicClassMethodMatcher.php b/src/Matcher/Collector/PublicClassMethodMatcher.php index 97944388..bedca81c 100644 --- a/src/Matcher/Collector/PublicClassMethodMatcher.php +++ b/src/Matcher/Collector/PublicClassMethodMatcher.php @@ -2,20 +2,18 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Matcher\Collector; +namespace Rector\TypePerfect\Matcher\Collector; use PhpParser\Comment\Doc; use PhpParser\Node\Stmt\ClassMethod; use PHPStan\Reflection\ClassReflection; -use PHPUnit\Framework\TestCase; -use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; final class PublicClassMethodMatcher { /** * @var array */ - private const SKIPPED_TYPES = [TestCase::class, ContainerConfigurator::class]; + private const SKIPPED_TYPES = ['PHPUnit\Framework\TestCase', 'Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator']; public function shouldSkipClassReflection(ClassReflection $classReflection): bool { @@ -73,6 +71,6 @@ public function shouldSkipClassMethod(ClassMethod $classMethod): bool $doc = $classMethod->getDocComment(); // skip symfony action - return $doc instanceof Doc && strpos($doc->getText(), '@Route') !== false; + return $doc instanceof Doc && str_contains($doc->getText(), '@Route'); } } diff --git a/src/Matcher/ObjectTypeMatcher.php b/src/Matcher/ObjectTypeMatcher.php deleted file mode 100644 index e78f5cf6..00000000 --- a/src/Matcher/ObjectTypeMatcher.php +++ /dev/null @@ -1,52 +0,0 @@ -getType($expr); - - $exprType = $this->resolveIntersectionedExprType($exprType); - if (! $exprType instanceof ObjectType) { - return false; - } - - foreach ($types as $type) { - if ($exprType->isInstanceOf($type)->yes()) { - return true; - } - } - - return false; - } - - private function resolveIntersectionedExprType(Type $type): Type - { - if (! $type instanceof IntersectionType) { - return $type; - } - - // resolve nested generics to object type - foreach ($type->getTypes() as $intersectionedType) { - if ($intersectionedType instanceof ObjectType) { - return $intersectionedType; - } - } - - // fallback - return $type; - } -} diff --git a/src/Matcher/PositionMatcher.php b/src/Matcher/PositionMatcher.php deleted file mode 100644 index 29687206..00000000 --- a/src/Matcher/PositionMatcher.php +++ /dev/null @@ -1,40 +0,0 @@ -containsTypeAnalyser = $containsTypeAnalyser; - } - - /** - * @param class-string $desiredType - * @param array $positionsByMethods - * @return int[]|null - */ - public function matchPositions( - MethodCall $methodCall, - Scope $scope, - string $desiredType, - array $positionsByMethods, - string $methodName - ): ?array { - if (! $this->containsTypeAnalyser->containsExprType($methodCall->var, $scope, $desiredType)) { - return null; - } - - return $positionsByMethods[$methodName] ?? null; - } -} diff --git a/src/Matcher/SharedNamePrefixMatcher.php b/src/Matcher/SharedNamePrefixMatcher.php deleted file mode 100644 index f784b7ec..00000000 --- a/src/Matcher/SharedNamePrefixMatcher.php +++ /dev/null @@ -1,63 +0,0 @@ - - */ - public function match(array $values): array - { - $groups = []; - - $valuesCount = \count($values); - - for ($i = 0; $i < $valuesCount; ++$i) { - for ($j = $i + 1; $j < $valuesCount; ++$j) { - $pos = $this->strcmppos($values[$i], $values[$j]); - $prefix = \substr($values[$i], 0, $pos + 1); - - // append to grouping for this prefix. include both strings - this - // gives duplicates which we'll merge later - $groups[$prefix][] = [$values[$i], $values[$j]]; - } - } - - $uniqueGroupsByPrefix = []; - foreach ($groups as $prefix => $group) { - // to remove duplicates introduced above - $uniqueGroups = \array_unique(Arrays::flatten($group)); - - $uniqueGroupsByPrefix[$prefix] = $uniqueGroups; - } - - return $uniqueGroupsByPrefix; - } - - private function strcmppos(string $left, string $right): int - { - if ($left === '') { - return -1; - } - - if ($right === '') { - return -1; - } - - $position = 0; - while ($left[$position] && $left[$position] === $right[$position]) { - ++$position; - } - - return $position - 1; - } -} diff --git a/src/Naming/BoolishNameAnalyser.php b/src/Naming/BoolishNameAnalyser.php deleted file mode 100644 index fa0df357..00000000 --- a/src/Naming/BoolishNameAnalyser.php +++ /dev/null @@ -1,49 +0,0 @@ -removeAbstractInterfacePrefixSuffix($expectedSuffix); - - // special case for tests - if ($expectedSuffix === 'TestCase') { - return 'Test'; - } - - return $expectedSuffix; - } - - private function removeAbstractInterfacePrefixSuffix(string $parentType): string - { - if (substr_compare($parentType, 'Interface', -strlen('Interface')) === 0) { - $parentType = Strings::substring($parentType, 0, -strlen('Interface')); - } - - if (substr_compare($parentType, 'Abstract', -strlen('Abstract')) === 0) { - $parentType = Strings::substring($parentType, 0, -strlen('Abstract')); - } - - if (strncmp($parentType, 'Abstract', strlen('Abstract')) === 0) { - return Strings::substring($parentType, strlen('Abstract')); - } - - return $parentType; - } -} diff --git a/src/NodeAnalyzer/ArrayAnalyzer.php b/src/NodeAnalyzer/ArrayAnalyzer.php deleted file mode 100644 index 8aae3fb1..00000000 --- a/src/NodeAnalyzer/ArrayAnalyzer.php +++ /dev/null @@ -1,34 +0,0 @@ -items as $arrayItem) { - if ($arrayItem === null) { - continue; - } - - /** @var ArrayItem $arrayItem */ - if ($arrayItem->key === null) { - continue; - } - - if (! $arrayItem->key instanceof String_) { - continue; - } - - return true; - } - - return false; - } -} diff --git a/src/NodeAnalyzer/AttributeFinder.php b/src/NodeAnalyzer/AttributeFinder.php deleted file mode 100644 index a35793d6..00000000 --- a/src/NodeAnalyzer/AttributeFinder.php +++ /dev/null @@ -1,60 +0,0 @@ -findAttribute($node, $desiredAttributeClass); - } - - /** - * @return Attribute[] - * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Property|\PhpParser\Node\Stmt\ClassLike|\PhpParser\Node\Param $node - */ - private function findAttributes($node): array - { - $attributes = []; - - foreach ($node->attrGroups as $attrGroup) { - $attributes = array_merge($attributes, $attrGroup->attrs); - } - - return $attributes; - } - - /** - * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Property|\PhpParser\Node\Stmt\ClassLike|\PhpParser\Node\Param $node - */ - private function findAttribute( - $node, - string $desiredAttributeClass - ): ?Attribute { - $attributes = $this->findAttributes($node); - - foreach ($attributes as $attribute) { - if (! $attribute->name instanceof FullyQualified) { - continue; - } - - if ($attribute->name->toString() === $desiredAttributeClass) { - return $attribute; - } - } - - return null; - } -} diff --git a/src/NodeAnalyzer/AutowiredMethodPropertyAnalyzer.php b/src/NodeAnalyzer/AutowiredMethodPropertyAnalyzer.php deleted file mode 100644 index 537caf71..00000000 --- a/src/NodeAnalyzer/AutowiredMethodPropertyAnalyzer.php +++ /dev/null @@ -1,54 +0,0 @@ -hasAttributes($classMethod, ['Symfony\Contracts\Service\Attribute\Required']); - - $docComment = $classMethod->getDocComment(); - if (! $docComment instanceof Doc) { - return $hasRequiredAttribute; - } - - if ((bool) Strings::match($docComment->getText(), self::REQUIRED_DOCBLOCK_REGEX)) { - return true; - } - - return $hasRequiredAttribute; - } - - /** - * @param string[] $desiredAttributeClasses - * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Property $stmt - */ - private function hasAttributes($stmt, array $desiredAttributeClasses): bool - { - foreach ($stmt->attrGroups as $attrGroup) { - foreach ($attrGroup->attrs as $attribute) { - $attributeName = $attribute->name->toString(); - - if (in_array($attributeName, $desiredAttributeClasses, true)) { - return true; - } - } - } - - return false; - } -} diff --git a/src/NodeAnalyzer/CacheIfAnalyzer.php b/src/NodeAnalyzer/CacheIfAnalyzer.php deleted file mode 100644 index 6bf63169..00000000 --- a/src/NodeAnalyzer/CacheIfAnalyzer.php +++ /dev/null @@ -1,69 +0,0 @@ -typeAwareNodeFinder = $typeAwareNodeFinder; - } - public function isDefaultNullAssign(If_ $if): bool - { - if ($if->else !== null) { - return false; - } - - /** @var BinaryOp[] $binaryOps */ - $binaryOps = $this->typeAwareNodeFinder->findInstanceOf($if->cond, BinaryOp::class); - if ($this->hasIdenticalToNull($binaryOps)) { - return true; - } - - $empty = $this->typeAwareNodeFinder->findFirstInstanceOf($if->cond, Empty_::class); - if ($empty instanceof Empty_) { - return true; - } - - $isset = $this->typeAwareNodeFinder->findFirstInstanceOf($if->cond, Isset_::class); - return $isset instanceof Isset_; - } - - /** - * @param BinaryOp[] $binaryOps - */ - private function hasIdenticalToNull(array $binaryOps): bool - { - foreach ($binaryOps as $binaryOp) { - if (! $binaryOp instanceof Identical && ! $binaryOp instanceof NotIdentical) { - continue; - } - - if (! $binaryOp->right instanceof ConstFetch) { - continue; - } - - $constFetch = $binaryOp->right; - if ($constFetch->name->toLowerString() === 'null') { - return true; - } - } - - return false; - } -} diff --git a/src/NodeAnalyzer/ClassAnalyzer.php b/src/NodeAnalyzer/ClassAnalyzer.php deleted file mode 100644 index 97fd81c3..00000000 --- a/src/NodeAnalyzer/ClassAnalyzer.php +++ /dev/null @@ -1,25 +0,0 @@ -getConstants() as $classConst) { - $constConst = $classConst->consts[0]; - $constantNames[] = $constConst->name->toString(); - } - - return $constantNames; - } -} diff --git a/src/NodeAnalyzer/DependencyNodeAnalyzer.php b/src/NodeAnalyzer/DependencyNodeAnalyzer.php deleted file mode 100644 index 7f43d8ce..00000000 --- a/src/NodeAnalyzer/DependencyNodeAnalyzer.php +++ /dev/null @@ -1,126 +0,0 @@ -nodeFinder = $nodeFinder; - $this->autowiredMethodPropertyAnalyzer = $autowiredMethodPropertyAnalyzer; - } - - public function isInsideAbstractClassAndPassedAsDependency(Property $property, Class_ $class): bool - { - if (! $class->isAbstract()) { - return false; - } - - $classMethod = $class->getMethod(MethodName::CONSTRUCTOR) ?? $class->getMethod(MethodName::SET_UP); - if (! $classMethod instanceof ClassMethod) { - return false; - } - - /** @var Assign[] $assigns */ - $assigns = $this->nodeFinder->findInstanceOf($classMethod, Assign::class); - if ($assigns === []) { - return false; - } - - return $this->isBeingAssignedInAssigns($property, $assigns); - } - - public function isInsideClassAndAutowiredMethod(Property $property, Class_ $class): bool - { - $propertyProperty = $property->props[0]; - $propertyName = $propertyProperty->name->toString(); - - foreach ($class->getMethods() as $classMethod) { - /** @var PropertyFetch[] $propertyFetches */ - $propertyFetches = $this->nodeFinder->findInstanceOf($classMethod, PropertyFetch::class); - - foreach ($propertyFetches as $propertyFetch) { - if (! $propertyFetch->name instanceof Identifier) { - continue; - } - - if ($propertyFetch->name->toString() !== $propertyName) { - continue; - } - - if ($this->autowiredMethodPropertyAnalyzer->detect($classMethod)) { - return true; - } - } - } - - return false; - } - - /** - * @param Assign[] $assigns - */ - private function isBeingAssignedInAssigns(Property $property, array $assigns): bool - { - foreach ($assigns as $assign) { - if (! $assign->var instanceof PropertyFetch) { - continue; - } - - if ($this->isPropertyFetchAndPropertyMatch($assign->var, $property)) { - return true; - } - } - - return false; - } - - private function isPropertyFetchAndPropertyMatch(PropertyFetch $propertyFetch, Property $property): bool - { - if (! $this->isLocalPropertyFetch($propertyFetch)) { - return false; - } - - if (! $propertyFetch->name instanceof Identifier) { - return false; - } - - $propertyProperty = $property->props[0]; - $assignedPropertyName = $propertyProperty->name->toString(); - - return $propertyFetch->name->toString() === $assignedPropertyName; - } - - private function isLocalPropertyFetch(PropertyFetch $propertyFetch): bool - { - if (! $propertyFetch->var instanceof Variable) { - return false; - } - - if (! is_string($propertyFetch->var->name)) { - return false; - } - - return $propertyFetch->var->name === 'this'; - } -} diff --git a/src/NodeAnalyzer/EnumAnalyzer.php b/src/NodeAnalyzer/EnumAnalyzer.php deleted file mode 100644 index 9086229b..00000000 --- a/src/NodeAnalyzer/EnumAnalyzer.php +++ /dev/null @@ -1,58 +0,0 @@ -barePhpDocParser = $barePhpDocParser; - } - - public function detect(Scope $scope, ClassLike $classLike): bool - { - if (! $classLike instanceof Class_) { - return false; - } - - $classReflection = $scope->getClassReflection(); - if (! $classReflection instanceof ClassReflection) { - return false; - } - - if ($this->hasEnumAnnotation($classLike)) { - return true; - } - - if ($classReflection->isSubclassOf(Enum::class)) { - return true; - } - - // is in /Enum/ namespace - return strpos($classReflection->getName(), '\\Enum\\') !== false; - } - - private function hasEnumAnnotation(Class_ $class): bool - { - $phpPhpDocNode = $this->barePhpDocParser->parseNode($class); - if (! $phpPhpDocNode instanceof PhpDocNode) { - return false; - } - - return (bool) $phpPhpDocNode->getTagsByName('@enum'); - } -} diff --git a/src/NodeAnalyzer/FileCheckingFuncCallAnalyzer.php b/src/NodeAnalyzer/FileCheckingFuncCallAnalyzer.php deleted file mode 100644 index ed1b0011..00000000 --- a/src/NodeAnalyzer/FileCheckingFuncCallAnalyzer.php +++ /dev/null @@ -1,33 +0,0 @@ -cond instanceof FuncCall) { - return false; - } - - $funcCallCond = $node->cond; - if (! $funcCallCond->name instanceof Name) { - return false; - } - - $funcCallName = $funcCallCond->name->toString(); - - return in_array($funcCallName, ['is_file', 'file_exists', 'is_dir'], true); - } -} diff --git a/src/NodeAnalyzer/IfElseBranchAnalyzer.php b/src/NodeAnalyzer/IfElseBranchAnalyzer.php deleted file mode 100644 index a729c4c0..00000000 --- a/src/NodeAnalyzer/IfElseBranchAnalyzer.php +++ /dev/null @@ -1,39 +0,0 @@ -getStmt(); - if ($stmt instanceof Expression) { - $stmt = $stmt->expr; - } - - if ($stmt instanceof Return_) { - ++$returnBranchCount; - } elseif ($stmt instanceof Assign) { - ++$assignBranchCount; - } - } - - return new ReturnAndAssignBranchCounts($returnBranchCount, $assignBranchCount); - } -} diff --git a/src/NodeAnalyzer/IfResemblingMatchAnalyzer.php b/src/NodeAnalyzer/IfResemblingMatchAnalyzer.php deleted file mode 100644 index 025ea0fd..00000000 --- a/src/NodeAnalyzer/IfResemblingMatchAnalyzer.php +++ /dev/null @@ -1,110 +0,0 @@ -printerStandard = $printerStandard; - $this->nodeFinder = $nodeFinder; - } - /** - * @param IfAndCondExpr[] $ifsAndCondExprs - */ - public function isUniqueCompareBinaryConds(array $ifsAndCondExprs): bool - { - $comparedExprContent = []; - - foreach ($ifsAndCondExprs as $ifAndCondExpr) { - if ($ifAndCondExpr->getCondExpr() === null) { - continue; - } - - $condExpr = $ifAndCondExpr->getCondExpr(); - if (! $condExpr instanceof BinaryOp) { - return false; - } - - if (! $this->hasExclusiveIdenticalorEqual($condExpr)) { - return false; - } - - // assuming the left is compared expression - $comparedExprContent[] = $this->printerStandard->prettyPrintExpr($condExpr->left); - } - - $uniqueComparedExprContent = array_unique($comparedExprContent); - return count($uniqueComparedExprContent) === 1; - } - - private function hasExclusivelyCompare(BooleanOr $booleanOr): bool - { - if (! $this->isIdenticalOrEqual($booleanOr->left)) { - return false; - } - - return $this->isIdenticalOrEqual($booleanOr->right); - } - - private function isIdenticalOrEqual(Expr $expr): bool - { - if ($expr instanceof BooleanOr) { - return $this->hasExclusivelyCompare($expr); - } - - if ($expr instanceof Identical) { - return true; - } - - return $expr instanceof Equal; - } - - private function hasExclusiveIdenticalorEqual(BinaryOp $binaryOp): bool - { - // has only ==, === and || binaries? - $nestedBinaryOps = $this->nodeFinder->findInstanceOf($binaryOp, BinaryOp::class); - - foreach ($nestedBinaryOps as $nestedBinaryOp) { - if ($nestedBinaryOp instanceof Identical) { - continue; - } - - if ($nestedBinaryOp instanceof Equal) { - continue; - } - - if ($nestedBinaryOp instanceof BooleanOr) { - // only allowed - if ($this->hasExclusivelyCompare($nestedBinaryOp)) { - continue; - } - - return false; - } - - return false; - } - - return true; - } -} diff --git a/src/NodeAnalyzer/MethodCall/AllowedChainCallSkipper.php b/src/NodeAnalyzer/MethodCall/AllowedChainCallSkipper.php deleted file mode 100644 index 4fbe9bbc..00000000 --- a/src/NodeAnalyzer/MethodCall/AllowedChainCallSkipper.php +++ /dev/null @@ -1,86 +0,0 @@ - - */ - private const ALLOWED_CHAIN_TYPES = [ - 'PhpParser\Builder', - 'DateTimeInterface', - 'Doctrine\ORM\Query', - 'Doctrine\ORM\QueryBuilder', - 'PharIo\Version\Version', - 'PharIo\Version\VersionNumber', - 'PHPStan\Reflection\PassedByReference', - 'PHPStan\Rules\RuleErrorBuilder', - 'PHPStan\TrinaryLogic', - 'Symfony\Component\DependencyInjection\Alias', - 'Symfony\Component\DependencyInjection\ContainerBuilder', - 'Symfony\Component\DependencyInjection\Definition', - 'Symfony\Component\DependencyInjection\Loader\Configurator\AbstractConfigurator', - 'Symfony\Component\Routing\RouteCollection', - 'Symfony\Component\Routing\Loader\Configurator\RouteConfigurator', - 'Symfony\Component\Finder\Finder', - 'Symfony\Component\String\AbstractString', - // symfony - // php-scoper finder - 'Isolated\Symfony\Component\Finder\Finder', - 'React\ChildProcess\Process', - 'Symplify\EasyCodingStandard\Contract\Application\FileProcessorInterface', - 'Stringy\Stringy', - // also trinary logic ↓ - 'Symfony\Component\Process\Process', - 'Symfony\Component\HttpFoundation\Request', - 'Symplify\MonorepoBuilder\Release\Process\ProcessRunner', - 'Symfony\Component\Console\Command\Command', - 'Symfony\Component\Console\Application', - 'Symfony\Component\HttpFoundation\RequestStack', - 'PHPStan\PhpDocParser\Parser\TokenIterator', - 'DOMElement', - 'DateTimeInterface', - 'Clue\React\NDJson\Encoder', - 'React\Promise\Promise', - 'Nette\Loaders\RobotLoader', - // mocks - 'PHPUnit\Framework\MockObject\Builder\InvocationMocker', - ]; - /** - * @var \Symplify\PHPStanRules\Matcher\ObjectTypeMatcher - */ - private $objectTypeMatcher; - - public function __construct(ObjectTypeMatcher $objectTypeMatcher) - { - $this->objectTypeMatcher = $objectTypeMatcher; - } - - /** - * @param string[] $extraAllowedTypes - */ - public function isAllowedFluentMethodCall(Scope $scope, MethodCall $methodCall, array $extraAllowedTypes = []): bool - { - $allowedTypes = array_merge($extraAllowedTypes, self::ALLOWED_CHAIN_TYPES); - - if ($this->objectTypeMatcher->isExprTypes($methodCall, $scope, $allowedTypes)) { - return true; - } - - // skip fluent call, possibly mock on final class - $callerType = $scope->getType($methodCall->var); - if ($callerType instanceof ErrorType) { - return true; - } - - return $this->objectTypeMatcher->isExprTypes($methodCall->var, $scope, $allowedTypes); - } -} diff --git a/src/NodeAnalyzer/MethodCall/MethodCallClassConstFetchPositionResolver.php b/src/NodeAnalyzer/MethodCall/MethodCallClassConstFetchPositionResolver.php deleted file mode 100644 index ad2756c0..00000000 --- a/src/NodeAnalyzer/MethodCall/MethodCallClassConstFetchPositionResolver.php +++ /dev/null @@ -1,57 +0,0 @@ -getArgs() as $position => $arg) { - if ($arg->value instanceof ClassConstFetch) { - $classConstFetch = $arg->value; - if (! $this->isEnumLikeClassConstFetch($classConstFetch)) { - continue; - } - - if (! is_int($position)) { - throw new ShouldNotHappenException(); - } - - $argPositions[] = $position; - } - } - - return $argPositions; - } - - private function isEnumLikeClassConstFetch(ClassConstFetch $classConstFetch): bool - { - if (! $classConstFetch->name instanceof Identifier) { - return false; - } - - $classConstName = $classConstFetch->name; - if ($classConstFetch->class instanceof Expr) { - return false; - } - - if ($classConstFetch->class->toString() === 'self') { - return false; - } - - return $classConstName->toString() !== 'class'; - } -} diff --git a/src/NodeAnalyzer/ProtectedAnalyzer.php b/src/NodeAnalyzer/ProtectedAnalyzer.php deleted file mode 100644 index c66e2808..00000000 --- a/src/NodeAnalyzer/ProtectedAnalyzer.php +++ /dev/null @@ -1,37 +0,0 @@ -dependencyNodeAnalyzer = $dependencyNodeAnalyzer; - $this->typeNodeAnalyzer = $typeNodeAnalyzer; - } - public function isProtectedPropertyOrClassConstAllowed(Property $property, Class_ $class): bool - { - if ($this->dependencyNodeAnalyzer->isInsideAbstractClassAndPassedAsDependency($property, $class)) { - return true; - } - - if ($this->dependencyNodeAnalyzer->isInsideClassAndAutowiredMethod($property, $class)) { - return true; - } - - return $this->typeNodeAnalyzer->isStaticAndContainerOrKernelType($property); - } -} diff --git a/src/NodeAnalyzer/RegexFuncCallAnalyzer.php b/src/NodeAnalyzer/RegexFuncCallAnalyzer.php deleted file mode 100644 index 29c10f60..00000000 --- a/src/NodeAnalyzer/RegexFuncCallAnalyzer.php +++ /dev/null @@ -1,32 +0,0 @@ -name instanceof Name) { - return false; - } - - $funcCallName = $funcCall->name->toString(); - return in_array($funcCallName, self::FUNC_CALLS_WITH_FIRST_ARG_REGEX, true); - } -} diff --git a/src/NodeAnalyzer/RegexStaticCallAnalyzer.php b/src/NodeAnalyzer/RegexStaticCallAnalyzer.php deleted file mode 100644 index bbf0630a..00000000 --- a/src/NodeAnalyzer/RegexStaticCallAnalyzer.php +++ /dev/null @@ -1,35 +0,0 @@ -class instanceof Name) { - return false; - } - - if ($staticCall->class->toString() !== 'Nette\Utils\Strings') { - return false; - } - - if (! $staticCall->name instanceof Identifier) { - return false; - } - - $staticCallName = $staticCall->name->toString(); - return in_array($staticCallName, self::NETTE_UTILS_CALLS_METHOD_NAMES_WITH_SECOND_ARG_REGEX, true); - } -} diff --git a/src/NodeAnalyzer/ScalarValueResolver.php b/src/NodeAnalyzer/ScalarValueResolver.php deleted file mode 100644 index 28786246..00000000 --- a/src/NodeAnalyzer/ScalarValueResolver.php +++ /dev/null @@ -1,118 +0,0 @@ - $args - * @return mixed[] - */ - public function resolveValuesCountFromArgs(array $args, Scope $scope): array - { - $resolveValues = $this->resolvedValues($args, $scope); - - // filter out false/true values - $resolvedValuesWithoutBool = \array_filter( - $resolveValues, - function ($value) : bool { - return ! $this->shouldSkipValue($value); - } - ); - if ($resolvedValuesWithoutBool === []) { - return []; - } - - return $this->countValues($resolvedValuesWithoutBool); - } - - /** - * @param array $args - * @return mixed[] - */ - private function resolvedValues(array $args, Scope $scope): array - { - $passedValues = []; - foreach ($args as $arg) { - if (! $arg instanceof Arg) { - continue; - } - - $valueType = $scope->getType($arg->value); - if (! $valueType instanceof ConstantScalarType) { - continue; - } - - $resolvedValue = $valueType->getValue(); - - // skip simple values - if ($resolvedValue === '') { - continue; - } - - $passedValues[] = $resolvedValue; - } - - return $passedValues; - } - - /** - * @param mixed[] $values - * @return mixed[] - */ - private function countValues(array $values): array - { - if ($values === []) { - return []; - } - - // the array_count_values ignores "null", so we have to translate it to string here - /** @var array $values */ - $values = array_filter($values, function ($value) : bool { - return $this->isFilterableValue($value); - }); - - return \array_count_values($values); - } - - /** - * Makes values ready for array_count_values(), it accepts only numeric or strings; no objects nor arrays - * @param mixed $value - */ - private function isFilterableValue($value): bool - { - if (is_numeric($value)) { - return true; - } - - return is_string($value); - } - - /** - * @param mixed $value - */ - private function shouldSkipValue($value): bool - { - // value could not be resolved - if ($value === null) { - return true; - } - - if (is_array($value)) { - return true; - } - - // simple values, probably boolean markers or type constants - if (\in_array($value, [0, 1], true)) { - return true; - } - - return \is_bool($value); - } -} diff --git a/src/NodeAnalyzer/SprintfSpecifierTypeResolver.php b/src/NodeAnalyzer/SprintfSpecifierTypeResolver.php deleted file mode 100644 index 0f85ff20..00000000 --- a/src/NodeAnalyzer/SprintfSpecifierTypeResolver.php +++ /dev/null @@ -1,54 +0,0 @@ ->> - * - * @see https://www.php.net/manual/en/function.sprintf.php > "Specifiers" - */ - private const MASK_TO_STATIC_TYPES_MAP = [ - '%s' => [StringType::class], - '%d' => [IntegerType::class, FloatType::class], - '%f' => [FloatType::class], - // @todo if needed - ]; - - /** - * @param string[] $specifiers - * @return array> - * - * @see https://www.php.net/manual/en/function.sprintf.php > "Specifiers" - */ - public function resolveFromSpecifiers(array $specifiers): array - { - $expectedTypes = []; - - foreach ($specifiers as $specifier) { - $types = []; - - if (isset(self::MASK_TO_STATIC_TYPES_MAP[$specifier])) { - $typeClasses = self::MASK_TO_STATIC_TYPES_MAP[$specifier]; - foreach ($typeClasses as $typeClass) { - $types[] = new $typeClass(); - } - } else { - $types = [new MixedType()]; - } - - $expectedTypes[] = $types; - } - - return $expectedTypes; - } -} diff --git a/src/NodeAnalyzer/TypeNodeAnalyzer.php b/src/NodeAnalyzer/TypeNodeAnalyzer.php deleted file mode 100644 index 364f3f91..00000000 --- a/src/NodeAnalyzer/TypeNodeAnalyzer.php +++ /dev/null @@ -1,43 +0,0 @@ -isStatic()) { - return false; - } - - $docComment = $property->getDocComment(); - if (! $docComment instanceof Doc) { - return false; - } - - $docCommentText = $docComment->getText(); - if (Strings::match($docCommentText, self::KERNEL_REGEX)) { - return true; - } - - return (bool) Strings::match($docCommentText, self::CONTAINER_REGEX); - } -} diff --git a/src/NodeFinder/ClassLikeNameFinder.php b/src/NodeFinder/ClassLikeNameFinder.php deleted file mode 100644 index af976813..00000000 --- a/src/NodeFinder/ClassLikeNameFinder.php +++ /dev/null @@ -1,158 +0,0 @@ -[A-Za-z0-9\\\\]+?)\\s*;#sm'; - - /** - * @var array - */ - private static $cache = []; - - /** - * @var array - */ - private $autoloadPsr4Paths = []; - /** - * @var \Symplify\PHPStanRules\Matcher\ClassLikeNameMatcher - */ - private $classLikeNameMatcher; - public function __construct(ClassLikeNameMatcher $classLikeNameMatcher, ComposerAutoloadResolver $composerAutoloadResolver, ComposerVendorAutoloadResolver $composerVendorAutoloadResolver) - { - $this->classLikeNameMatcher = $classLikeNameMatcher; - $this->autoloadPsr4Paths = array_merge($composerAutoloadResolver->getPsr4Autoload(), $composerVendorAutoloadResolver->getPsr4Autoload()); - } - - /** - * Works with projects which respect PSR4 standard, iterates the smallest possible amount of directories / files - * based on namespace pattern - * - * @return string[]|mixed[] - */ - public function getClassLikeNamesMatchingNamespacePattern(string $namespacePattern): array - { - if (isset(self::$cache[$namespacePattern])) { - return self::$cache[$namespacePattern]; - } - - $narrowedNamespace = $this->getNarrowedNamespaceForSearch($namespacePattern); - $possibleDirectories = $this->getPossibleDirectoriesForNamespace($narrowedNamespace); - $keepExistingDirectoriesCallback = static function (string $directory) : bool { - return is_dir($directory); - }; - $filteredPossibleDirectories = array_filter($possibleDirectories, $keepExistingDirectoriesCallback); - - if ($filteredPossibleDirectories === []) { - return []; - } - - $finderFiles = Finder::create()->files()->in($filteredPossibleDirectories)->name('*.php'); - $classLikeNames = []; - - foreach ($finderFiles as $finderFile) { - $realPath = $finderFile->getRealpath(); - $classLikeName = basename($realPath, '.php'); - - $src = file_get_contents($realPath); - if (! $src) { - continue; - } - - $namespace = $this->getNamespaceFromSrc($src); - if ($namespace !== null) { - $classLikeName = sprintf('%s\\%s', $namespace, $classLikeName); - } - - if ($this->classLikeNameMatcher->isClassLikeNameMatchedAgainstPattern($classLikeName, $namespacePattern)) { - $classLikeNames[] = $classLikeName; - } - } - - self::$cache[$namespacePattern] = $classLikeNames; - - return $classLikeNames; - } - - private function getNamespaceFromSrc(string $src): ?string - { - $matches = Strings::match($src, self::EXTRACT_NAMESPACE_REGEX); - if ($matches) { - return $matches['namespace']; - } - - return null; - } - - private function getNarrowedNamespaceForSearch(string $namespacePattern): string - { - $isNarrowed = false; - $namespacePatternParts = explode('\\', $namespacePattern); - $namespacePatternPartsBeforeVariable = []; - foreach ($namespacePatternParts as $namespacePatternPart) { - if (strpos($namespacePatternPart, '*') !== false || strpos($namespacePatternPart, '?') !== false) { - $isNarrowed = true; - break; - } - - $namespacePatternPartsBeforeVariable[] = $namespacePatternPart; - } - - $narrowedNamespace = implode('\\', $namespacePatternPartsBeforeVariable); - if ($isNarrowed && $narrowedNamespace !== '') { - $narrowedNamespace .= '\\'; - } - - return $narrowedNamespace; - } - - /** - * @return string[] - */ - private function getPossibleDirectoriesForNamespace(string $narrowedNamespace): array - { - $narrowedNamespaceIsEmpty = $narrowedNamespace === ''; - $possibleDirectories = []; - $narrowestNamespaceLength = 0; - foreach ($this->autoloadPsr4Paths as $namespace => $directories) { - if ($narrowedNamespaceIsEmpty || strncmp($narrowedNamespace, $namespace, strlen($namespace)) === 0) { - if (! $narrowedNamespaceIsEmpty) { - $namespaceLength = strlen($namespace); - if ($narrowestNamespaceLength < $namespaceLength) { - $narrowestNamespaceLength = $namespaceLength; - $possibleDirectories = []; - } else { - continue; - } - } - - $directories = is_array($directories) ? $directories : [$directories]; - foreach ($directories as $directory) { - $possibleDirectories[] = $directory . DIRECTORY_SEPARATOR . str_replace( - '\\', - DIRECTORY_SEPARATOR, - substr($narrowedNamespace, strlen($namespace)) - ); - } - } - } - - return $possibleDirectories; - } -} diff --git a/src/NodeFinder/ClassMethodNodeFinder.php b/src/NodeFinder/ClassMethodNodeFinder.php index df4e53b0..d1b19459 100644 --- a/src/NodeFinder/ClassMethodNodeFinder.php +++ b/src/NodeFinder/ClassMethodNodeFinder.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\NodeFinder; +namespace Rector\TypePerfect\NodeFinder; use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Identifier; @@ -10,18 +10,15 @@ use PhpParser\Node\Stmt\ClassMethod; use PHPStan\Analyser\Scope; use PHPStan\Reflection\ClassReflection; -use Symplify\PHPStanRules\Reflection\ReflectionParser; +use Rector\TypePerfect\Reflection\ReflectionParser; final class ClassMethodNodeFinder { - /** - * @var \Symplify\PHPStanRules\Reflection\ReflectionParser - */ - private $reflectionParser; - public function __construct(ReflectionParser $reflectionParser) - { - $this->reflectionParser = $reflectionParser; + public function __construct( + private readonly ReflectionParser $reflectionParser, + ) { } + public function findByMethodCall(MethodCall $methodCall, Scope $scope): ?ClassMethod { $classReflection = $scope->getClassReflection(); @@ -40,7 +37,6 @@ public function findByMethodCall(MethodCall $methodCall, Scope $scope): ?ClassMe $methodCallName = $methodCall->name->toString(); - /** @var ClassMethod|null $classMethod */ $classMethod = $classLike->getMethod($methodCallName); if (! $classMethod instanceof ClassMethod) { return null; diff --git a/src/NodeFinder/MethodCallNodeFinder.php b/src/NodeFinder/MethodCallNodeFinder.php index 991b7bb5..585ee3d5 100644 --- a/src/NodeFinder/MethodCallNodeFinder.php +++ b/src/NodeFinder/MethodCallNodeFinder.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\NodeFinder; +namespace Rector\TypePerfect\NodeFinder; use PhpParser\Node; use PhpParser\Node\Expr\MethodCall; @@ -10,29 +10,21 @@ use PhpParser\NodeFinder; use PHPStan\Analyser\Scope; use PHPStan\Reflection\ClassReflection; -use Symplify\PHPStanRules\Printer\NodeComparator; -use Symplify\PHPStanRules\Reflection\ReflectionParser; +use Rector\TypePerfect\Printer\NodeComparator; +use Rector\TypePerfect\Reflection\ReflectionParser; +use Webmozart\Assert\Assert; final class MethodCallNodeFinder { - /** - * @var \Symplify\PHPStanRules\Reflection\ReflectionParser - */ - private $reflectionParser; - /** - * @var \PhpParser\NodeFinder - */ - private $nodeFinder; - /** - * @var \Symplify\PHPStanRules\Printer\NodeComparator - */ - private $nodeComparator; - public function __construct(ReflectionParser $reflectionParser, NodeFinder $nodeFinder, NodeComparator $nodeComparator) - { - $this->reflectionParser = $reflectionParser; - $this->nodeFinder = $nodeFinder; - $this->nodeComparator = $nodeComparator; + private NodeFinder $nodeFinder; + + public function __construct( + private readonly ReflectionParser $reflectionParser, + private readonly NodeComparator $nodeComparator, + ) { + $this->nodeFinder = new NodeFinder(); } + /** * @return MethodCall[] */ @@ -48,7 +40,7 @@ public function findUsages(MethodCall $methodCall, Scope $scope): array return []; } - return $this->nodeFinder->find($classLike, function (Node $node) use ($methodCall): bool { + $methodCalls = $this->nodeFinder->find($classLike, function (Node $node) use ($methodCall): bool { if (! $node instanceof MethodCall) { return false; } @@ -59,5 +51,9 @@ public function findUsages(MethodCall $methodCall, Scope $scope): array return $this->nodeComparator->areNodesEqual($node->name, $methodCall->name); }); + + Assert::allIsInstanceOf($methodCalls, MethodCall::class); + + return $methodCalls; } } diff --git a/src/NodeFinder/ReturnNodeFinder.php b/src/NodeFinder/ReturnNodeFinder.php index a615c658..88594551 100644 --- a/src/NodeFinder/ReturnNodeFinder.php +++ b/src/NodeFinder/ReturnNodeFinder.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\NodeFinder; +namespace Rector\TypePerfect\NodeFinder; use PhpParser\Node; use PhpParser\Node\Expr; @@ -10,20 +10,16 @@ use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\Stmt\Return_; use PhpParser\NodeTraverser; -use Symplify\PHPStanRules\NodeTraverser\SimpleCallableNodeTraverser; +use Rector\TypePerfect\NodeTraverser\SimpleCallableNodeTraverser; final class ReturnNodeFinder { - /** - * @var \Symplify\PHPStanRules\NodeTraverser\SimpleCallableNodeTraverser - */ - private $simpleCallableNodeTraverser; - public function __construct(SimpleCallableNodeTraverser $simpleCallableNodeTraverser) - { - $this->simpleCallableNodeTraverser = $simpleCallableNodeTraverser; + public function __construct( + private readonly SimpleCallableNodeTraverser $simpleCallableNodeTraverser + ) { } - public function findOnlyReturnsExpr(ClassMethod $classMethod): ?\PhpParser\Node\Expr + public function findOnlyReturnsExpr(ClassMethod $classMethod): Expr|null { $returns = $this->findReturnsWithValues($classMethod); if (count($returns) !== 1) { @@ -53,7 +49,7 @@ public function findReturnsWithValues(ClassMethod $classMethod): array return null; } - if ($node->expr === null) { + if (! $node->expr instanceof Expr) { return null; } diff --git a/src/NodeFinder/TypeAwareNodeFinder.php b/src/NodeFinder/TypeAwareNodeFinder.php deleted file mode 100644 index 751378f4..00000000 --- a/src/NodeFinder/TypeAwareNodeFinder.php +++ /dev/null @@ -1,47 +0,0 @@ -nodeFinder = $nodeFinder; - } - - /** - * @template TNode as Node - * - * @param mixed[]|\PhpParser\Node $nodes - * @param class-string $type - * @return TNode|null - */ - public function findFirstInstanceOf($nodes, string $type): ?Node - { - return $this->nodeFinder->findFirstInstanceOf($nodes, $type); - } - - /** - * @template TNode as Node - * - * @param mixed[]|\PhpParser\Node $nodes - * @param class-string $type - * @return TNode[] - */ - public function findInstanceOf($nodes, string $type): array - { - return $this->nodeFinder->findInstanceOf($nodes, $type); - } -} diff --git a/src/NodeTraverser/SimpleCallableNodeTraverser.php b/src/NodeTraverser/SimpleCallableNodeTraverser.php index e2a050c9..e5f896ee 100644 --- a/src/NodeTraverser/SimpleCallableNodeTraverser.php +++ b/src/NodeTraverser/SimpleCallableNodeTraverser.php @@ -2,11 +2,11 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\NodeTraverser; +namespace Rector\TypePerfect\NodeTraverser; use PhpParser\Node; use PhpParser\NodeTraverser; -use Symplify\PHPStanRules\NodeVisitor\CallableNodeVisitor; +use Rector\TypePerfect\NodeVisitor\CallableNodeVisitor; /** * @api @@ -15,9 +15,9 @@ final class SimpleCallableNodeTraverser { /** * @param callable(Node $node): (int|Node|null) $callable - * @param \PhpParser\Node|mixed[]|null $nodes + * @param Node|Node[]|null $nodes */ - public function traverseNodesWithCallable($nodes, callable $callable): void + public function traverseNodesWithCallable(Node | array | null $nodes, callable $callable): void { if ($nodes === null) { return; diff --git a/src/NodeVisitor/AssignedToPropertyNodeVisitor.php b/src/NodeVisitor/AssignedToPropertyNodeVisitor.php deleted file mode 100644 index d465540c..00000000 --- a/src/NodeVisitor/AssignedToPropertyNodeVisitor.php +++ /dev/null @@ -1,26 +0,0 @@ -expr->setAttribute(AttributeKey::ASSIGNED_TO, $node->var); - return null; - } -} diff --git a/src/NodeVisitor/CallableNodeVisitor.php b/src/NodeVisitor/CallableNodeVisitor.php index 86545660..0f50d5a4 100644 --- a/src/NodeVisitor/CallableNodeVisitor.php +++ b/src/NodeVisitor/CallableNodeVisitor.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\NodeVisitor; +namespace Rector\TypePerfect\NodeVisitor; use PhpParser\Node; use PhpParser\Node\Expr; @@ -25,10 +25,7 @@ public function __construct(callable $callable) $this->callable = $callable; } - /** - * @return int|\PhpParser\Node|null - */ - public function enterNode(Node $node) + public function enterNode(Node $node): int|Node|null { $originalNode = $node; diff --git a/src/NodeVisitor/FlatConcatFindingNodeVisitor.php b/src/NodeVisitor/FlatConcatFindingNodeVisitor.php deleted file mode 100644 index 1a65ffad..00000000 --- a/src/NodeVisitor/FlatConcatFindingNodeVisitor.php +++ /dev/null @@ -1,67 +0,0 @@ -fileCheckingFuncCallAnalyzer = $fileCheckingFuncCallAnalyzer; - } - - /** - * @param Node[] $nodes - */ - public function beforeTraverse(array $nodes) - { - $this->foundNodes = []; - return null; - } - - public function enterNode(Node $node) - { - if ($this->fileCheckingFuncCallAnalyzer->isFileExistCheck($node)) { - return NodeTraverser::DONT_TRAVERSE_CHILDREN; - } - - if (! $node instanceof Concat) { - return null; - } - - if ($node->left instanceof Concat) { - return NodeTraverser::DONT_TRAVERSE_CHILDREN; - } - - if ($node->right instanceof Concat) { - return NodeTraverser::DONT_TRAVERSE_CURRENT_AND_CHILDREN; - } - - $this->foundNodes[] = $node; - return null; - } - - /** - * @return Concat[] - */ - public function getFoundNodes(): array - { - return $this->foundNodes; - } -} diff --git a/src/NodeVisitor/StringOutsideConcatFindingNodeVisitor.php b/src/NodeVisitor/StringOutsideConcatFindingNodeVisitor.php deleted file mode 100644 index 4c759f09..00000000 --- a/src/NodeVisitor/StringOutsideConcatFindingNodeVisitor.php +++ /dev/null @@ -1,93 +0,0 @@ -fileCheckingFuncCallAnalyzer = $fileCheckingFuncCallAnalyzer; - } - - /** - * @param Node[] $nodes - */ - public function beforeTraverse(array $nodes) - { - $this->foundNodes = []; - return null; - } - - public function enterNode(Node $node) - { - if ($this->fileCheckingFuncCallAnalyzer->isFileExistCheck($node)) { - return NodeTraverser::DONT_TRAVERSE_CHILDREN; - } - - if ($this->isStrFuncCall($node)) { - return NodeTraverser::DONT_TRAVERSE_CHILDREN; - } - - if ($node instanceof Concat) { - return NodeTraverser::DONT_TRAVERSE_CHILDREN; - } - - if (! $node instanceof String_) { - return null; - } - - $stringKind = $node->getAttribute(AttributeKey::KIND); - - // skip here/now docs, not a file - if (in_array($stringKind, [String_::KIND_HEREDOC, String_::KIND_NOWDOC], true)) { - return null; - } - - $this->foundNodes[] = $node; - return null; - } - - /** - * @return String_[] - */ - public function getFoundNodes(): array - { - return $this->foundNodes; - } - - private function isStrFuncCall(Node $node): bool - { - if (! $node instanceof FuncCall) { - return false; - } - - if (! $node->name instanceof Name) { - return false; - } - - $functionName = $node->name->toString(); - - return in_array($functionName, ['str_ends_with', 'strpos', 'str_stars_with', 'sprintf'], true); - } -} diff --git a/src/ParentClassMethodNodeResolver.php b/src/ParentClassMethodNodeResolver.php deleted file mode 100644 index ac400faa..00000000 --- a/src/ParentClassMethodNodeResolver.php +++ /dev/null @@ -1,64 +0,0 @@ -reflectionParser = $reflectionParser; - $this->reflectionProvider = $reflectionProvider; - } - - public function resolveParentClassMethod(Scope $scope, string $methodName): ?ClassMethod - { - $parentClassReflections = $this->getParentClassReflections($scope); - - foreach ($parentClassReflections as $parentClassReflection) { - if (! $parentClassReflection->hasMethod($methodName)) { - continue; - } - - $classReflection = $this->reflectionProvider->getClass($parentClassReflection->getName()); - $parentMethodReflection = $classReflection->getMethod($methodName, $scope); - return $this->reflectionParser->parseMethodReflection($parentMethodReflection); - } - - return null; - } - - /** - * @return ClassReflection[] - */ - private function getParentClassReflections(Scope $scope): array - { - $mainClassReflection = $scope->getClassReflection(); - if (! $mainClassReflection instanceof ClassReflection) { - return []; - } - - // all parent classes and interfaces - return array_filter( - $mainClassReflection->getAncestors(), - static function (ClassReflection $classReflection) use ($mainClassReflection) : bool { - return $classReflection !== $mainClassReflection; - } - ); - } -} diff --git a/src/ParentGuard/ParentClassMethodGuard.php b/src/ParentGuard/ParentClassMethodGuard.php deleted file mode 100644 index f592cadf..00000000 --- a/src/ParentGuard/ParentClassMethodGuard.php +++ /dev/null @@ -1,28 +0,0 @@ -parentMethodResolver = $parentMethodResolver; - } - - public function isClassMethodGuardedByParentClassMethod(ClassMethod $classMethod, Scope $scope): bool - { - $phpMethodReflection = $this->parentMethodResolver->resolve($scope, $classMethod->name->toString()); - return $phpMethodReflection instanceof PhpMethodReflection; - } -} diff --git a/src/ParentGuard/ParentElementResolver/ParentMethodResolver.php b/src/ParentGuard/ParentElementResolver/ParentMethodResolver.php deleted file mode 100644 index 5b605b5c..00000000 --- a/src/ParentGuard/ParentElementResolver/ParentMethodResolver.php +++ /dev/null @@ -1,39 +0,0 @@ -getClassReflection(); - if (! $classReflection instanceof ClassReflection) { - return null; - } - - /** @var ClassReflection[] $parentClassLikeReflections */ - $parentClassLikeReflections = array_merge($classReflection->getParents(), $classReflection->getInterfaces()); - - foreach ($parentClassLikeReflections as $parentClassLikeReflection) { - // this is needed, as PHPStan takes parent @method anontation as real method - if (! $parentClassLikeReflection->hasNativeMethod($methodName)) { - continue; - } - - $nativeMethodReflection = $parentClassLikeReflection->getNativeMethod($methodName); - if (! $nativeMethodReflection instanceof PhpMethodReflection) { - continue; - } - - return $nativeMethodReflection; - } - - return null; - } -} diff --git a/src/ParentGuard/ParentElementResolver/ParentMethodReturnTypeResolver.php b/src/ParentGuard/ParentElementResolver/ParentMethodReturnTypeResolver.php deleted file mode 100644 index 2608e5e7..00000000 --- a/src/ParentGuard/ParentElementResolver/ParentMethodReturnTypeResolver.php +++ /dev/null @@ -1,54 +0,0 @@ -getFunction(); - if (! $functionReflection instanceof MethodReflection) { - return null; - } - - $classReflection = $scope->getClassReflection(); - if (! $classReflection instanceof ClassReflection) { - return null; - } - - $methodName = $functionReflection->getName(); - - /** @var ClassReflection[] $parentClassLikeReflections */ - $parentClassLikeReflections = array_merge($classReflection->getParents(), $classReflection->getInterfaces()); - - foreach ($parentClassLikeReflections as $parentClassLikeReflection) { - if (! $parentClassLikeReflection->hasMethod($methodName)) { - continue; - } - - $nativeMethodReflection = $parentClassLikeReflection->getNativeMethod($methodName); - if (! $nativeMethodReflection instanceof PhpMethodReflection) { - continue; - } - - $parametersAcceptor = ParametersAcceptorSelector::selectSingle($nativeMethodReflection->getVariants()); - if (! $parametersAcceptor instanceof FunctionVariant) { - continue; - } - - return $parametersAcceptor->getReturnType(); - } - - return null; - } -} diff --git a/src/ParentGuard/ParentPropertyGuard.php b/src/ParentGuard/ParentPropertyGuard.php deleted file mode 100644 index 2eef1535..00000000 --- a/src/ParentGuard/ParentPropertyGuard.php +++ /dev/null @@ -1,33 +0,0 @@ -props[0]; - $propertyName = $propertyProperty->name->toString(); - - $classReflection = $scope->getClassReflection(); - if (! $classReflection instanceof ClassReflection) { - return false; - } - - foreach ($classReflection->getParents() as $parentClassReflectoin) { - if (! $parentClassReflectoin->hasNativeProperty($propertyName)) { - continue; - } - - return true; - } - - return false; - } -} diff --git a/src/PhpDoc/ApiDocStmtAnalyzer.php b/src/PhpDoc/ApiDocStmtAnalyzer.php index 41058e21..205efc83 100644 --- a/src/PhpDoc/ApiDocStmtAnalyzer.php +++ b/src/PhpDoc/ApiDocStmtAnalyzer.php @@ -2,29 +2,29 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\PhpDoc; +namespace Rector\TypePerfect\PhpDoc; use PhpParser\Comment\Doc; -use PhpParser\Node\Stmt; +use PhpParser\Node\Stmt\ClassMethod; use PHPStan\PhpDoc\ResolvedPhpDocBlock; use PHPStan\Reflection\ClassReflection; final class ApiDocStmtAnalyzer { - public function isApiDoc(Stmt $stmt, ClassReflection $classReflection): bool + public function hasApiDoc(ClassMethod $classMethod, ClassReflection $classReflection): bool { if ($classReflection->getResolvedPhpDoc() instanceof ResolvedPhpDocBlock) { $resolvedPhpDoc = $classReflection->getResolvedPhpDoc(); - if (strpos($resolvedPhpDoc->getPhpDocString(), '@api') !== false) { + if (str_contains($resolvedPhpDoc->getPhpDocString(), '@api')) { return true; } } - $docComment = $stmt->getDocComment(); + $docComment = $classMethod->getDocComment(); if (! $docComment instanceof Doc) { return false; } - return strpos($docComment->getText(), '@api') !== false; + return str_contains($docComment->getText(), '@api'); } } diff --git a/src/PhpDoc/BarePhpDocParser.php b/src/PhpDoc/BarePhpDocParser.php deleted file mode 100644 index 1df08e51..00000000 --- a/src/PhpDoc/BarePhpDocParser.php +++ /dev/null @@ -1,82 +0,0 @@ -phpDocParser = $phpDocParser; - $this->lexer = $lexer; - } - - /** - * @api - */ - public function parseNode(Node $node): ?PhpDocNode - { - $docComment = $node->getDocComment(); - if (! $docComment instanceof Doc) { - return null; - } - - return $this->parseDocBlock($docComment->getText()); - } - - /** - * @api - * @return PhpDocTagNode[] - */ - public function parseNodeToPhpDocTagNodes(Node $node): array - { - $phpDocNode = $this->parseNode($node); - if (! $phpDocNode instanceof PhpDocNode) { - return []; - } - - return $this->resolvePhpDocTagNodes($phpDocNode); - } - - private function parseDocBlock(string $docBlock): PhpDocNode - { - $tokens = $this->lexer->tokenize($docBlock); - $tokenIterator = new TokenIterator($tokens); - - return $this->phpDocParser->parse($tokenIterator); - } - - /** - * @return PhpDocTagNode[] - */ - private function resolvePhpDocTagNodes(PhpDocNode $phpDocNode): array - { - $phpDocTagNodes = []; - foreach ($phpDocNode->children as $phpDocChildNode) { - if (! $phpDocChildNode instanceof PhpDocTagNode) { - continue; - } - - $phpDocTagNodes[] = $phpDocChildNode; - } - - return $phpDocTagNodes; - } -} diff --git a/src/PhpDoc/ClassAnnotationResolver.php b/src/PhpDoc/ClassAnnotationResolver.php deleted file mode 100644 index 95ca7e5c..00000000 --- a/src/PhpDoc/ClassAnnotationResolver.php +++ /dev/null @@ -1,55 +0,0 @@ -simplePhpDocParser = $simplePhpDocParser; - $this->classReferencePhpDocNodeTraverser = $classReferencePhpDocNodeTraverser; - } - - /** - * @api - * @return string[] - */ - public function resolveClassAnnotations(Node $node, Scope $scope): array - { - $phpDocNode = $this->simplePhpDocParser->parseNode($node); - if (! $phpDocNode instanceof PhpDocNode) { - return []; - } - - $classReflection = $scope->getClassReflection(); - if (! $classReflection instanceof ClassReflection) { - return []; - } - - $this->classReferencePhpDocNodeTraverser->decoratePhpDocNode($phpDocNode, $classReflection); - - $classAnnotations = []; - foreach ($phpDocNode->getTags() as $phpDocTagNode) { - $classAnnotations[] = $phpDocTagNode->name; - } - - return $classAnnotations; - } -} diff --git a/src/PhpDoc/ClassReferencePhpDocNodeVisitor.php b/src/PhpDoc/ClassReferencePhpDocNodeVisitor.php deleted file mode 100644 index 8d80d3ff..00000000 --- a/src/PhpDoc/ClassReferencePhpDocNodeVisitor.php +++ /dev/null @@ -1,73 +0,0 @@ -reflectionProvider = $reflectionProvider; - } - - public function configureClassName(string $className): void - { - $this->className = $className; - } - - public function enterNode(Node $node): Node - { - if ($node instanceof PhpDocTagNode) { - $this->processPhpDocTagNode($node); - } - - return $node; - } - - private function resolveShortNamesToFullyQualified(string $currentName, string $className): ?string - { - if (! class_exists($className)) { - return null; - } - - $classReflection = $this->reflectionProvider->getClass($className); - - return Reflection::expandClassName($currentName, $classReflection->getNativeReflection()); - } - - private function processPhpDocTagNode(PhpDocTagNode $phpDocTagNode): void - { - if ($this->className === null) { - throw new ShouldNotHappenException(); - } - - $shortClassName = trim($phpDocTagNode->name, '@'); - - // lowercased, probably non class annotation - if (strtolower($shortClassName) === $shortClassName) { - return; - } - - $resolvedFullyQualifiedName = $this->resolveShortNamesToFullyQualified($shortClassName, $this->className); - if ($resolvedFullyQualifiedName) { - $phpDocTagNode->name = $resolvedFullyQualifiedName; - } - } -} diff --git a/src/PhpDoc/PhpDocNodeTraverser/ClassReferencePhpDocNodeTraverser.php b/src/PhpDoc/PhpDocNodeTraverser/ClassReferencePhpDocNodeTraverser.php deleted file mode 100644 index e565758e..00000000 --- a/src/PhpDoc/PhpDocNodeTraverser/ClassReferencePhpDocNodeTraverser.php +++ /dev/null @@ -1,32 +0,0 @@ -classReferencePhpDocNodeVisitor = $classReferencePhpDocNodeVisitor; - } - - public function decoratePhpDocNode(PhpDocNode $simplePhpDocNode, ClassReflection $classReflection): void - { - $phpDocNodeTraverser = new PhpDocNodeTraverser(); - - $this->classReferencePhpDocNodeVisitor->configureClassName($classReflection->getName()); - $phpDocNodeTraverser->addPhpDocNodeVisitor($this->classReferencePhpDocNodeVisitor); - - $phpDocNodeTraverser->traverse($simplePhpDocNode); - } -} diff --git a/src/PhpDoc/PhpDocResolver.php b/src/PhpDoc/PhpDocResolver.php deleted file mode 100644 index 94073ac9..00000000 --- a/src/PhpDoc/PhpDocResolver.php +++ /dev/null @@ -1,34 +0,0 @@ -fileTypeMapper = $fileTypeMapper; - } - - public function resolve(Scope $scope, ClassReflection $classReflection, Doc $doc): ResolvedPhpDocBlock - { - return $this->fileTypeMapper->getResolvedPhpDoc( - $scope->getFile(), - $classReflection->getName(), - null, - null, - $doc->getText() - ); - } -} diff --git a/src/PhpDoc/SeePhpDocTagNodesFinder.php b/src/PhpDoc/SeePhpDocTagNodesFinder.php deleted file mode 100644 index 5e1acd2c..00000000 --- a/src/PhpDoc/SeePhpDocTagNodesFinder.php +++ /dev/null @@ -1,35 +0,0 @@ -getPhpDocNodes() as $phpDocNode) { - foreach ($phpDocNode->children as $phpDocChildNode) { - if (! $phpDocChildNode instanceof PhpDocTagNode) { - continue; - } - - if ($phpDocChildNode->name !== '@see') { - continue; - } - - $seePhpDocTagNodes[] = $phpDocChildNode; - } - } - - return $seePhpDocTagNodes; - } -} diff --git a/src/PhpDocParser/PhpDocNodeTraverser.php b/src/PhpDocParser/PhpDocNodeTraverser.php deleted file mode 100644 index 9eba9e07..00000000 --- a/src/PhpDocParser/PhpDocNodeTraverser.php +++ /dev/null @@ -1,246 +0,0 @@ -phpDocNodeVisitors[] = $phpDocNodeVisitor; - } - - public function traverse(Node $node): void - { - foreach ($this->phpDocNodeVisitors as $phpDocNodeVisitor) { - $phpDocNodeVisitor->beforeTraverse($node); - } - - $node = $this->traverseNode($node); - - foreach ($this->phpDocNodeVisitors as $phpDocNodeVisitor) { - $phpDocNodeVisitor->afterTraverse($node); - } - } - - /** - * @param callable(Node $node): (int|null|Node) $callable - */ - public function traverseWithCallable(Node $node, string $docContent, callable $callable): void - { - $callablePhpDocNodeVisitor = new CallablePhpDocNodeVisitor($callable, $docContent); - $this->addPhpDocNodeVisitor($callablePhpDocNodeVisitor); - - $this->traverse($node); - } - - /** - * @template TNode of Node - * @param TNode $node - * @return TNode - */ - private function traverseNode(Node $node): Node - { - $subNodeNames = array_keys(get_object_vars($node)); - - foreach ($subNodeNames as $subNodeName) { - $subNode = &$node->{$subNodeName}; - - if (\is_array($subNode)) { - $subNode = $this->traverseArray($subNode); - } elseif ($subNode instanceof Node) { - $breakVisitorIndex = null; - $traverseChildren = true; - - foreach ($this->phpDocNodeVisitors as $visitorIndex => $phpDocNodeVisitor) { - $return = $phpDocNodeVisitor->enterNode($subNode); - - if ($return !== null) { - if ($return instanceof Node) { - $subNode = $return; - } elseif ($return === self::DONT_TRAVERSE_CHILDREN) { - $traverseChildren = false; - } elseif ($return === self::DONT_TRAVERSE_CURRENT_AND_CHILDREN) { - $traverseChildren = false; - $breakVisitorIndex = $visitorIndex; - break; - } elseif ($return === self::STOP_TRAVERSAL) { - $this->stopTraversal = true; - } elseif ($return === self::NODE_REMOVE) { - $subNode = null; - continue 2; - } else { - throw new InvalidTraverseException( - 'enterNode() returned invalid value of type ' . gettype($return) - ); - } - } - } - - if ($traverseChildren) { - $subNode = $this->traverseNode($subNode); - if ($this->stopTraversal) { - break; - } - } - - foreach ($this->phpDocNodeVisitors as $visitorIndex => $phpDocNodeVisitor) { - $phpDocNodeVisitor->leaveNode($subNode); - - if ($breakVisitorIndex === $visitorIndex) { - break; - } - } - } - } - - return $node; - } - - /** - * @param array $nodes - * @return array - */ - private function traverseArray(array $nodes): array - { - foreach ($nodes as $key => &$node) { - // can be string or something else - if (! $node instanceof Node) { - continue; - } - - $traverseChildren = true; - $breakVisitorIndex = null; - - foreach ($this->phpDocNodeVisitors as $visitorIndex => $phpDocNodeVisitor) { - $return = $phpDocNodeVisitor->enterNode($node); - - if ($return !== null) { - if ($return instanceof Node) { - $node = $return; - } elseif ($return === self::DONT_TRAVERSE_CHILDREN) { - $traverseChildren = false; - } elseif ($return === self::DONT_TRAVERSE_CURRENT_AND_CHILDREN) { - $traverseChildren = false; - $breakVisitorIndex = $visitorIndex; - break; - } elseif ($return === self::STOP_TRAVERSAL) { - $this->stopTraversal = true; - } elseif ($return === self::NODE_REMOVE) { - // remove node - unset($nodes[$key]); - continue 2; - } else { - throw new InvalidTraverseException('enterNode() returned invalid value of type ' . gettype( - $return - )); - } - } - } - - // should traverse node childrens properties? - if ($traverseChildren) { - $node = $this->traverseNode($node); - if ($this->stopTraversal) { - break; - } - } - - foreach ($this->phpDocNodeVisitors as $visitorIndex => $phpDocNodeVisitor) { - $return = $phpDocNodeVisitor->leaveNode($node); - - if ($return !== null) { - if ($return instanceof Node) { - $node = $return; - } elseif (\is_array($return)) { - $doNodes[] = [$key, $return]; - break; - } elseif ($return === self::NODE_REMOVE) { - $doNodes[] = [$key, []]; - break; - } elseif ($return === self::STOP_TRAVERSAL) { - $this->stopTraversal = true; - break 2; - } else { - throw new InvalidTraverseException( - 'leaveNode() returned invalid value of type ' . gettype($return) - ); - } - } - - if ($breakVisitorIndex === $visitorIndex) { - break; - } - } - } - - return $nodes; - } -} diff --git a/src/PhpDocParser/PhpDocNodeVisitor/AbstractPhpDocNodeVisitor.php b/src/PhpDocParser/PhpDocNodeVisitor/AbstractPhpDocNodeVisitor.php deleted file mode 100644 index c4a251ce..00000000 --- a/src/PhpDocParser/PhpDocNodeVisitor/AbstractPhpDocNodeVisitor.php +++ /dev/null @@ -1,38 +0,0 @@ -docContent = $docContent; - $this->callable = $callable; - } - - /** - * @return int|\PHPStan\PhpDocParser\Ast\Node|null - */ - public function enterNode(Node $node) - { - $callable = $this->callable; - return $callable($node, $this->docContent); - } -} diff --git a/src/PhpDocParser/SimplePhpDocParser.php b/src/PhpDocParser/SimplePhpDocParser.php deleted file mode 100644 index 1e8af9d8..00000000 --- a/src/PhpDocParser/SimplePhpDocParser.php +++ /dev/null @@ -1,48 +0,0 @@ -phpDocParser = $phpDocParser; - $this->lexer = $lexer; - } - - public function parseNode(Node $node): ?PhpDocNode - { - $docComment = $node->getDocComment(); - if (! $docComment instanceof Doc) { - return null; - } - - return $this->parseDocBlock($docComment->getText()); - } - - public function parseDocBlock(string $docBlock): PhpDocNode - { - $tokens = $this->lexer->tokenize($docBlock); - $tokenIterator = new TokenIterator($tokens); - - $phpDocNode = $this->phpDocParser->parse($tokenIterator); - return new PhpDocNode($phpDocNode->children); - } -} diff --git a/src/Printer/CollectorMetadataPrinter.php b/src/Printer/CollectorMetadataPrinter.php index 72f87216..5dab9d65 100644 --- a/src/Printer/CollectorMetadataPrinter.php +++ b/src/Printer/CollectorMetadataPrinter.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Printer; +namespace Rector\TypePerfect\Printer; use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Identifier; @@ -24,14 +24,11 @@ use PHPStan\Type\Type; use PHPStan\Type\UnionType as PHPStanUnionType; use PHPStan\Type\VerbosityLevel; -use Symplify\PHPStanRules\Enum\Types\ResolvedTypes; +use Rector\TypePerfect\Enum\Types\ResolvedTypes; final class CollectorMetadataPrinter { - /** - * @var \PhpParser\PrettyPrinter\Standard - */ - private $printerStandard; + private readonly Standard $printerStandard; public function __construct() { diff --git a/src/Printer/DuplicatedClassMethodPrinter.php b/src/Printer/DuplicatedClassMethodPrinter.php deleted file mode 100644 index c192d85c..00000000 --- a/src/Printer/DuplicatedClassMethodPrinter.php +++ /dev/null @@ -1,35 +0,0 @@ -standard = $standard; - } - - public function printClassMethod(ClassMethod $classMethod): string - { - $content = $this->standard->prettyPrint((array) $classMethod->stmts); - return Strings::replace($content, self::VARIABLE_REGEX, static function (array $match) : string { - return '$a'; - }); - } -} diff --git a/src/Printer/NodeComparator.php b/src/Printer/NodeComparator.php index 7d3939e5..f5cbabd5 100644 --- a/src/Printer/NodeComparator.php +++ b/src/Printer/NodeComparator.php @@ -2,57 +2,24 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Printer; +namespace Rector\TypePerfect\Printer; use PhpParser\Node; -use PhpParser\Node\Arg; -use PhpParser\Node\Param; use PhpParser\PrettyPrinter\Standard; -use Symplify\PHPStanRules\Enum\AttributeKey; final class NodeComparator { - /** - * @var \PhpParser\PrettyPrinter\Standard - */ - private $standard; - public function __construct(Standard $standard) - { - $this->standard = $standard; + public function __construct( + private readonly Standard $standard + ) { } public function areNodesEqual(Node $firstNode, Node $secondNode): bool { // remove comments from nodes - $firstNode->setAttribute(AttributeKey::COMMENTS, null); - $secondNode->setAttribute(AttributeKey::COMMENTS, null); + $firstNode->setAttribute('comments', null); + $secondNode->setAttribute('comments', null); return $this->standard->prettyPrint([$firstNode]) === $this->standard->prettyPrint([$secondNode]); } - - /** - * @param array $methodCallArgs - * @param Param[] $classMethodParams - */ - public function areArgsAndParamsSame(array $methodCallArgs, array $classMethodParams): bool - { - if (count($methodCallArgs) !== count($classMethodParams)) { - return false; - } - - foreach ($methodCallArgs as $key => $arg) { - $param = $classMethodParams[$key]; - - $argContent = $this->standard->prettyPrint([$arg]); - $paramContent = $this->standard->prettyPrint([$param]); - - if ($argContent === $paramContent) { - continue; - } - - return false; - } - - return true; - } } diff --git a/src/Reflection/MethodCallNodeAnalyzer.php b/src/Reflection/MethodCallNodeAnalyzer.php deleted file mode 100644 index 053c77d9..00000000 --- a/src/Reflection/MethodCallNodeAnalyzer.php +++ /dev/null @@ -1,57 +0,0 @@ -resolveCallerClassReflection($scope, $methodCall); - - if (! $callerClassReflection instanceof ClassReflection) { - return null; - } - - if (! $methodCall->name instanceof Identifier) { - return null; - } - - $methodName = $methodCall->name->toString(); - - $extendedMethodReflection = $callerClassReflection->getMethod($methodName, $scope); - if (! $extendedMethodReflection instanceof PhpMethodReflection) { - return null; - } - - return $extendedMethodReflection; - } - - private function resolveCallerClassReflection(Scope $scope, MethodCall $methodCall): ?ClassReflection - { - $callerType = $scope->getType($methodCall->var); - if (! $callerType instanceof TypeWithClassName) { - return null; - } - - if ($callerType instanceof StaticType) { - $callerType = $callerType->getStaticObjectType(); - } - - if (! $callerType instanceof ObjectType) { - return null; - } - - return $callerType->getClassReflection(); - } -} diff --git a/src/Reflection/MethodNodeAnalyser.php b/src/Reflection/MethodNodeAnalyser.php index 3c1fdd00..6e99e480 100644 --- a/src/Reflection/MethodNodeAnalyser.php +++ b/src/Reflection/MethodNodeAnalyser.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Reflection; +namespace Rector\TypePerfect\Reflection; use PHPStan\Analyser\Scope; use PHPStan\Reflection\ClassReflection; @@ -12,7 +12,7 @@ final class MethodNodeAnalyser { public function hasParentVendorLock(Scope $scope, string $methodName): bool { - return $this->matchFirstParentClassMethod($scope, $methodName) !== null; + return $this->matchFirstParentClassMethod($scope, $methodName) instanceof MethodReflection; } public function matchFirstParentClassMethod(Scope $scope, string $methodName): ?MethodReflection diff --git a/src/Reflection/PublicClassReflectionAnalyzer.php b/src/Reflection/PublicClassReflectionAnalyzer.php deleted file mode 100644 index 4f47e8cf..00000000 --- a/src/Reflection/PublicClassReflectionAnalyzer.php +++ /dev/null @@ -1,30 +0,0 @@ -hasNativeProperty($propertyName)) { - return false; - } - - $phpPropertyReflection = $classReflection->getNativeProperty($propertyName); - return $phpPropertyReflection->isPublic(); - } - - public function hasPublicNativeMethod(ClassReflection $classReflection, string $getterMethodName): bool - { - if (! $classReflection->hasNativeMethod($getterMethodName)) { - return false; - } - - $extendedMethodReflection = $classReflection->getNativeMethod($getterMethodName); - return $extendedMethodReflection->isPublic(); - } -} diff --git a/src/Reflection/ReflectionParser.php b/src/Reflection/ReflectionParser.php index 2d464fb6..27f9818c 100644 --- a/src/Reflection/ReflectionParser.php +++ b/src/Reflection/ReflectionParser.php @@ -2,74 +2,34 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Reflection; +namespace Rector\TypePerfect\Reflection; use Nette\Utils\FileSystem; +use PhpParser\Node; use PhpParser\Node\Stmt\ClassLike; -use PhpParser\Node\Stmt\ClassMethod; -use PhpParser\Node\Stmt\Property; +use PhpParser\NodeFinder; use PhpParser\NodeTraverser; use PhpParser\NodeVisitor\NameResolver; use PhpParser\Parser; use PhpParser\ParserFactory; use PHPStan\Reflection\ClassReflection; -use PHPStan\Reflection\MethodReflection; -use ReflectionClass; -use ReflectionMethod; -use ReflectionProperty; -use Symplify\PHPStanRules\NodeFinder\TypeAwareNodeFinder; use Throwable; -/** - * @api - */ final class ReflectionParser { /** * @var array */ - private $classesByFilename = []; + private array $classesByFilename = []; - /** - * @var \PhpParser\Parser - */ - private $parser; - /** - * @var \Symplify\PHPStanRules\NodeFinder\TypeAwareNodeFinder - */ - private $typeAwareNodeFinder; + private readonly Parser $parser; - public function __construct( - TypeAwareNodeFinder $typeAwareNodeFinder - ) { - $this->typeAwareNodeFinder = $typeAwareNodeFinder; + public function __construct() + { $parserFactory = new ParserFactory(); $this->parser = $parserFactory->create(ParserFactory::PREFER_PHP7); } - /** - * @param \ReflectionMethod|\PHPStan\Reflection\MethodReflection $reflectionMethod - */ - public function parseMethodReflection($reflectionMethod): ?ClassMethod - { - $classLike = $this->parseNativeClassReflection($reflectionMethod->getDeclaringClass()); - if (! $classLike instanceof ClassLike) { - return null; - } - - return $classLike->getMethod($reflectionMethod->getName()); - } - - public function parsePropertyReflection(ReflectionProperty $reflectionProperty): ?Property - { - $class = $this->parseNativeClassReflection($reflectionProperty->getDeclaringClass()); - if (! $class instanceof ClassLike) { - return null; - } - - return $class->getProperty($reflectionProperty->getName()); - } - public function parseClassReflection(ClassReflection $classReflection): ?ClassLike { $fileName = $classReflection->getFileName(); @@ -80,24 +40,7 @@ public function parseClassReflection(ClassReflection $classReflection): ?ClassLi return $this->parseFilenameToClass($fileName); } - /** - * @param \ReflectionClass|\PHPStan\Reflection\ClassReflection $reflectionClass - */ - private function parseNativeClassReflection($reflectionClass): ?ClassLike - { - $fileName = $reflectionClass->getFileName(); - if ($fileName === false) { - return null; - } - - if ($fileName === null) { - return null; - } - - return $this->parseFilenameToClass($fileName); - } - - private function parseFilenameToClass(string $fileName): ?\PhpParser\Node\Stmt\ClassLike + private function parseFilenameToClass(string $fileName): ClassLike|null { if (isset($this->classesByFilename[$fileName])) { return $this->classesByFilename[$fileName]; @@ -113,12 +56,12 @@ private function parseFilenameToClass(string $fileName): ?\PhpParser\Node\Stmt\C $nodeTraverser = new NodeTraverser(); $nodeTraverser->addVisitor(new NameResolver()); $nodeTraverser->traverse($stmts); - } catch (Throwable $exception) { + } catch (Throwable) { // not reachable return null; } - $classLike = $this->typeAwareNodeFinder->findFirstInstanceOf($stmts, ClassLike::class); + $classLike = $this->findFirstClassLike($stmts); if (! $classLike instanceof ClassLike) { return null; } @@ -127,4 +70,19 @@ private function parseFilenameToClass(string $fileName): ?\PhpParser\Node\Stmt\C return $classLike; } + + /** + * @param Node[] $nodes + */ + private function findFirstClassLike(array $nodes): ?ClassLike + { + $nodeFinder = new NodeFinder(); + + $foundClassLike = $nodeFinder->findFirstInstanceOf($nodes, ClassLike::class); + if ($foundClassLike instanceof ClassLike) { + return $foundClassLike; + } + + return null; + } } diff --git a/src/Reflection/StaticCallNodeAnalyzer.php b/src/Reflection/StaticCallNodeAnalyzer.php deleted file mode 100644 index 7ccf4b68..00000000 --- a/src/Reflection/StaticCallNodeAnalyzer.php +++ /dev/null @@ -1,78 +0,0 @@ -reflectionProvider = $reflectionProvider; - } - /** - * @api - */ - public function isAbstractMethodStaticCall(Expr $expr, Scope $scope): bool - { - if (! $expr instanceof StaticCall) { - return false; - } - - $callerType = $this->resolveStaticCallCallerType($expr, $scope); - - if (! $expr->name instanceof Identifier) { - return false; - } - - $methodName = $expr->name->toString(); - - foreach ($callerType->getReferencedClasses() as $referencedClass) { - if (! $this->reflectionProvider->hasClass($referencedClass)) { - continue; - } - - $classReflection = $this->reflectionProvider->getClass($referencedClass); - - if (! $classReflection->hasMethod($methodName)) { - continue; - } - - $methodReflection = $classReflection->getMethod($methodName, $scope); - if (! $methodReflection instanceof PhpMethodReflection) { - continue; - } - - // cannot replace abstract call with direct one - if ($methodReflection->isAbstract()) { - return true; - } - } - - return false; - } - - private function resolveStaticCallCallerType(StaticCall $staticCall, Scope $scope): Type - { - if ($staticCall->class instanceof Name) { - $className = $staticCall->class->toString(); - return new ObjectType($className); - } - - return $scope->getType($staticCall->class); - } -} diff --git a/src/Rules/AbstractSymplifyRule.php b/src/Rules/AbstractSymplifyRule.php deleted file mode 100644 index b4514136..00000000 --- a/src/Rules/AbstractSymplifyRule.php +++ /dev/null @@ -1,50 +0,0 @@ - - */ -abstract class AbstractSymplifyRule implements Rule, ManyNodeRuleInterface -{ - /** - * @return class-string - */ - public function getNodeType(): string - { - return Node::class; - } - - /** - * @return string[]|RuleError[] - */ - public function processNode(Node $node, Scope $scope): array - { - if ($this->shouldSkipNode($node)) { - return []; - } - - return $this->process($node, $scope); - } - - private function shouldSkipNode(Node $node): bool - { - $nodeTypes = $this->getNodeTypes(); - foreach ($nodeTypes as $nodeType) { - if (is_a($node, $nodeType, true)) { - return false; - } - } - - return true; - } -} diff --git a/src/Rules/AnnotateRegexClassConstWithRegexLinkRule.php b/src/Rules/AnnotateRegexClassConstWithRegexLinkRule.php deleted file mode 100644 index b496d20f..00000000 --- a/src/Rules/AnnotateRegexClassConstWithRegexLinkRule.php +++ /dev/null @@ -1,136 +0,0 @@ - - */ - public function getNodeType(): string - { - return ClassConst::class; - } - - /** - * @param ClassConst $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (count($node->consts) !== 1) { - return []; - } - - $onlyConst = $node->consts[0]; - if (! $onlyConst->value instanceof String_) { - return []; - } - - $constantName = (string) $onlyConst->name; - if (! $this->isRegexPatternConstantName($constantName)) { - return []; - } - - $stringValue = $onlyConst->value->value; - if (! $this->isNonSingleCharRegexPattern($stringValue)) { - return []; - } - - // is regex patern - if ($this->hasDocBlockWithRegexLink($node)) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [new CodeSample( - <<<'CODE_SAMPLE' -class SomeClass -{ - private const COMPLICATED_REGEX = '#some_complicated_stu|ff#'; -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -class SomeClass -{ - /** - * @see https://regex101.com/r/SZr0X5/12 - */ - private const COMPLICATED_REGEX = '#some_complicated_stu|ff#'; -} -CODE_SAMPLE - )]); - } - - private function isNonSingleCharRegexPattern(string $value): bool - { - // skip 1-char regexs - if (Strings::length($value) < 4) { - return false; - } - - $firstChar = $value[0]; - - if (ctype_alpha($firstChar)) { - return false; - } - - $patternWithoutModifiers = rtrim($value, self::ALL_MODIFIERS); - - if (Strings::length($patternWithoutModifiers) < 1) { - return false; - } - - $lastChar = Strings::substring($patternWithoutModifiers, -1, 1); - // this is probably a regex - return $firstChar === $lastChar; - } - - private function hasDocBlockWithRegexLink(ClassConst $classConst): bool - { - $docComment = $classConst->getDocComment(); - if (! $docComment instanceof Doc) { - return false; - } - - $docCommentText = $docComment->getText(); - return strpos($docCommentText, '@see https://regex101.com/r') !== false; - } - - private function isRegexPatternConstantName(string $constantName): bool - { - return substr_compare($constantName, '_REGEX', -strlen('_REGEX')) === 0; - } -} diff --git a/src/Rules/BoolishClassMethodPrefixRule.php b/src/Rules/BoolishClassMethodPrefixRule.php deleted file mode 100644 index f92b5d15..00000000 --- a/src/Rules/BoolishClassMethodPrefixRule.php +++ /dev/null @@ -1,165 +0,0 @@ -boolishNameAnalyser = $boolishNameAnalyser; - $this->returnNodeFinder = $returnNodeFinder; - $this->parentClassMethodGuard = $parentClassMethodGuard; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return ClassMethod::class; - } - - /** - * @param ClassMethod $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classReflection = $scope->getClassReflection(); - if (! $classReflection instanceof ClassReflection) { - return []; - } - - if ($this->shouldSkip($node, $scope, $classReflection)) { - return []; - } - - $errorMessage = sprintf(self::ERROR_MESSAGE, (string) $node->name); - return [$errorMessage]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -class SomeClass -{ - public function old(): bool - { - return $this->age > 100; - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -class SomeClass -{ - public function isOld(): bool - { - return $this->age > 100; - } -} -CODE_SAMPLE - ), - ]); - } - - private function shouldSkip(ClassMethod $classMethod, Scope $scope, ClassReflection $classReflection): bool - { - $classMethodName = $classMethod->name->toString(); - - if ($this->parentClassMethodGuard->isClassMethodGuardedByParentClassMethod($classMethod, $scope)) { - return true; - } - - $returns = $this->returnNodeFinder->findReturnsWithValues($classMethod); - // nothing was returned - if ($returns === []) { - return true; - } - - $extendedMethodReflection = $classReflection->getNativeMethod($classMethodName); - $returnType = ParametersAcceptorSelector::selectSingle($extendedMethodReflection->getVariants()) - ->getReturnType(); - - if (! $returnType instanceof BooleanType && ! $this->areOnlyBoolReturnNodes($returns, $scope)) { - return true; - } - - if ($this->boolishNameAnalyser->isBoolish($classMethodName)) { - return true; - } - - // is required by an interface - return $this->isMethodRequiredByParentInterface($classReflection, $classMethodName); - } - - /** - * @param Return_[] $returns - */ - private function areOnlyBoolReturnNodes(array $returns, Scope $scope): bool - { - foreach ($returns as $return) { - if ($return->expr === null) { - continue; - } - - $returnedNodeType = $scope->getType($return->expr); - if (! $returnedNodeType instanceof BooleanType) { - return false; - } - } - - return true; - } - - private function isMethodRequiredByParentInterface(ClassReflection $classReflection, string $methodName): bool - { - $interfaces = $classReflection->getInterfaces(); - foreach ($interfaces as $interface) { - if ($interface->hasMethod($methodName)) { - return true; - } - } - - return false; - } -} diff --git a/src/Rules/CheckAttributteArgumentClassExistsRule.php b/src/Rules/CheckAttributteArgumentClassExistsRule.php deleted file mode 100644 index 56a8d34f..00000000 --- a/src/Rules/CheckAttributteArgumentClassExistsRule.php +++ /dev/null @@ -1,110 +0,0 @@ - - */ -final class CheckAttributteArgumentClassExistsRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'Class was not found'; - /** - * @var \PHPStan\Reflection\ReflectionProvider - */ - private $reflectionProvider; - public function __construct(ReflectionProvider $reflectionProvider) - { - $this->reflectionProvider = $reflectionProvider; - } - - public function getNodeType(): string - { - return AttributeGroup::class; - } - - /** - * @param AttributeGroup $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - $ruleErrors = []; - - foreach ($node->attrs as $attribute) { - foreach ($attribute->args as $arg) { - $value = $arg->value; - if (! $this->isClassConstFetch($value)) { - continue; - } - - $valueType = $scope->getType($value); - if (! $valueType instanceof ConstantStringType) { - $ruleErrors[] = self::ERROR_MESSAGE; - continue; - } - - if ($this->reflectionProvider->hasClass($valueType->getValue())) { - continue; - } - - $ruleErrors[] = self::ERROR_MESSAGE; - } - } - - return $ruleErrors; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -#[SomeAttribute(firstName: 'MissingClass::class')] -class SomeClass -{ -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -#[SomeAttribute(firstName: ExistingClass::class)] -class SomeClass -{ -} -CODE_SAMPLE - ), - ]); - } - - private function isClassConstFetch(Expr $expr): bool - { - if (! $expr instanceof ClassConstFetch) { - return false; - } - - if (! $expr->name instanceof Identifier) { - return false; - } - - return $expr->name->toString() === 'class'; - } -} diff --git a/src/Rules/CheckClassNamespaceFollowPsr4Rule.php b/src/Rules/CheckClassNamespaceFollowPsr4Rule.php deleted file mode 100644 index 3c1766e8..00000000 --- a/src/Rules/CheckClassNamespaceFollowPsr4Rule.php +++ /dev/null @@ -1,136 +0,0 @@ - - */ - private $autoloadPsr4Paths = []; - /** - * @var \Symplify\PHPStanRules\Composer\Psr4PathValidator - */ - private $psr4PathValidator; - /** - * @var \Symplify\PHPStanRules\Composer\ClassNamespaceMatcher - */ - private $classNamespaceMatcher; - - public function __construct( - ComposerAutoloadResolver $composerAutoloadResolver, - Psr4PathValidator $psr4PathValidator, - ClassNamespaceMatcher $classNamespaceMatcher - ) { - $this->psr4PathValidator = $psr4PathValidator; - $this->classNamespaceMatcher = $classNamespaceMatcher; - $this->autoloadPsr4Paths = $composerAutoloadResolver->getPsr4Autoload(); - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return ClassLike::class; - } - - /** - * @param ClassLike $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if ($this->autoloadPsr4Paths === []) { - return []; - } - - $namespaceBeforeClass = $this->resolveNamespaceBeforeClass($node, $scope); - if ($namespaceBeforeClass === null) { - return []; - } - - $filePath = str_replace('\\', '/', $scope->getFile()); - - $possibleNamespacesToDirectories = $this->classNamespaceMatcher->matchPossibleDirectoriesForClass( - $namespaceBeforeClass, - $this->autoloadPsr4Paths, - $scope - ); - - if ($possibleNamespacesToDirectories === []) { - return []; - } - - foreach ($possibleNamespacesToDirectories as $possibleNamespaceToDirectory) { - if ($this->psr4PathValidator->isClassNamespaceCorrect($possibleNamespaceToDirectory, $filePath)) { - return []; - } - } - - if ($namespaceBeforeClass === '') { - return []; - } - - $namespacePart = substr($namespaceBeforeClass, 0, -1); - $errorMessage = sprintf(self::ERROR_MESSAGE, $namespacePart); - - return [$errorMessage]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -// defined "Foo\Bar" namespace in composer.json > autoload > psr-4 -namespace Foo; - -class Baz -{ -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -// defined "Foo\Bar" namespace in composer.json > autoload > psr-4 -namespace Foo\Bar; - -class Baz -{ -} -CODE_SAMPLE - ), - ]); - } - - private function resolveNamespaceBeforeClass(ClassLike $classLike, Scope $scope): ?string - { - if (! $classLike->name instanceof Identifier) { - return null; - } - - return $scope->getNamespace() . '\\'; - } -} diff --git a/src/Rules/CheckNotTestsNamespaceOutsideTestsDirectoryRule.php b/src/Rules/CheckNotTestsNamespaceOutsideTestsDirectoryRule.php deleted file mode 100644 index 56e7e594..00000000 --- a/src/Rules/CheckNotTestsNamespaceOutsideTestsDirectoryRule.php +++ /dev/null @@ -1,82 +0,0 @@ - - */ - public function getNodeType(): string - { - return Namespace_::class; - } - - /** - * @param Namespace_ $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! $node->name instanceof Name) { - return []; - } - - $matches = Strings::match($node->name->toString(), Regex::TESTS_PART_REGEX); - if ($matches !== null) { - return []; - } - - if (substr_compare($scope->getFile(), 'Test.php', -strlen('Test.php')) !== 0) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -// file: "SomeTest.php -namespace App; - -class SomeTest -{ -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -// file: "SomeTest.php -namespace App\Tests; - -class SomeTest -{ -} -CODE_SAMPLE - ), - ]); - } -} diff --git a/src/Rules/CheckRequiredInterfaceInContractNamespaceRule.php b/src/Rules/CheckRequiredInterfaceInContractNamespaceRule.php deleted file mode 100644 index f8736836..00000000 --- a/src/Rules/CheckRequiredInterfaceInContractNamespaceRule.php +++ /dev/null @@ -1,81 +0,0 @@ - - */ -final class CheckRequiredInterfaceInContractNamespaceRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'Interface must be located in "Contract" namespace'; - - /** - * @var string - * @see https://regex101.com/r/kmrIG1/1 - */ - private const A_CONTRACT_NAMESPACE_REGEX = '#\bContract\b#'; - - /** - * @return class-string - */ - public function getNodeType(): string - { - return Interface_::class; - } - - /** - * @param Interface_ $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - $namespace = $scope->getNamespace(); - if ($namespace === null) { - return []; - } - - if (Strings::match($namespace, self::A_CONTRACT_NAMESPACE_REGEX)) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -namespace App\Repository; - -interface ProductRepositoryInterface -{ -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -namespace App\Contract\Repository; - -interface ProductRepositoryInterface -{ -} -CODE_SAMPLE - ), - ]); - } -} diff --git a/src/Rules/ClassExtendingExclusiveNamespaceRule.php b/src/Rules/ClassExtendingExclusiveNamespaceRule.php deleted file mode 100644 index 7c243437..00000000 --- a/src/Rules/ClassExtendingExclusiveNamespaceRule.php +++ /dev/null @@ -1,199 +0,0 @@ -> - */ - private $guards; - - /** - * @param array> $guards - */ - public function __construct(ClassLikeNameMatcher $classLikeNameMatcher, ClassLikeNameFinder $classLikeNameFinder, array $guards) - { - $this->classLikeNameMatcher = $classLikeNameMatcher; - $this->classLikeNameFinder = $classLikeNameFinder; - $this->guards = $guards; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classReflection = $node->getClassReflection(); - $classLikeName = $classReflection->getName(); - - $namespace = $scope->getNamespace(); - if ($namespace === null) { - return []; - } - - foreach ($this->guards as $guardedTypeOrNamespacePattern => $allowedNamespacePatterns) { - if (! $this->isSubjectToGuardedTypeOrNamespacePattern($classReflection, $guardedTypeOrNamespacePattern)) { - continue; - } - - if (! $this->isInAllowedNamespace($allowedNamespacePatterns, $classLikeName)) { - $nativeReflectionClass = $classReflection->getNativeReflection(); - $errorMessage = sprintf(self::ERROR_MESSAGE, $classLikeName, Json::encode($allowedNamespacePatterns, 0), $nativeReflectionClass->getNamespaceName()); - - return [$errorMessage]; - } - } - - return []; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition('Define in which namespaces (using *, ** or ? glob-like pattern matching) can classes extending specified class or implementing specified interface exist', [ - new ConfiguredCodeSample( - <<<'CODE_SAMPLE' -namespace App; - -// AbstractType implements \Symfony\Component\Form\FormTypeInterface -use Symfony\Component\Form\AbstractType; - -class UserForm extends AbstractType -{ -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -namespace App\Form; - -use Symfony\Component\Form\AbstractType; - -class UserForm extends AbstractType -{ -} -CODE_SAMPLE - , - [ - 'guards' => [ - 'Symfony\Component\Form\FormTypeInterface' => ['App\Form\**'], - ], - ] - ), - new ConfiguredCodeSample( - <<<'CODE_SAMPLE' -namespace App\Services; - -use App\Component\PriceEngine\PriceProviderInterface; - -class CustomerProductProvider extends PriceProviderInterface -{ -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -namespace App\Component\PriceEngineImpl; - -use App\Component\PriceEngine\PriceProviderInterface; - -class CustomerProductProvider extends PriceProviderInterface -{ -} -CODE_SAMPLE - , - [ - 'guards' => [ - 'App\Component\PriceEngine\**' => [ - 'App\Component\PriceEngine\**', - 'App\Component\PriceEngineImpl\**', - ], - ], - ] - ), - ]); - } - - private function isSubjectToGuardedTypeOrNamespacePattern(ClassReflection $classReflection, string $guardedTypeOrNamespacePattern): bool - { - $isGuardedSubjectNamespacePattern = strpos($guardedTypeOrNamespacePattern, '*') !== false || strpos($guardedTypeOrNamespacePattern, '?') !== false; - $isGuardedSubjectType = ! $isGuardedSubjectNamespacePattern; - if ($isGuardedSubjectType && ! $classReflection->isSubclassOf($guardedTypeOrNamespacePattern)) { - return false; - } - if (! $isGuardedSubjectNamespacePattern) { - return true; - } - return $this->isSubjectSubclassOfGuardedPattern($guardedTypeOrNamespacePattern, $classReflection); - } - - private function isSubjectSubclassOfGuardedPattern( - string $guardedTypeOrNamespacePattern, - ClassReflection $classReflection - ): bool { - $classLikeNames = $this->classLikeNameFinder->getClassLikeNamesMatchingNamespacePattern( - $guardedTypeOrNamespacePattern - ); - foreach ($classLikeNames as $classLikeName) { - if ($classReflection->isSubclassOf($classLikeName)) { - return true; - } - } - - return false; - } - - /** - * @param mixed $allowedNamespacePatterns - */ - private function isInAllowedNamespace($allowedNamespacePatterns, string $classLikeName): bool - { - foreach ($allowedNamespacePatterns as $allowedNamespacePattern) { - if ($this->classLikeNameMatcher->isClassLikeNameMatchedAgainstPattern( - $classLikeName, - $allowedNamespacePattern - )) { - return true; - } - } - - return false; - } -} diff --git a/src/Rules/ClassNameRespectsParentSuffixRule.php b/src/Rules/ClassNameRespectsParentSuffixRule.php deleted file mode 100644 index 4a6c8b82..00000000 --- a/src/Rules/ClassNameRespectsParentSuffixRule.php +++ /dev/null @@ -1,144 +0,0 @@ -classToSuffixResolver = $classToSuffixResolver; - $this->parentClasses = array_merge($parentClasses, self::DEFAULT_PARENT_CLASSES); - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classLike = $node->getOriginalNode(); - if (! $classLike instanceof Class_) { - return []; - } - - $classReflection = $node->getClassReflection(); - if ($classReflection->isAbstract()) { - return []; - } - - if ($classReflection->isAnonymous()) { - return []; - } - - return $this->processClassNameAndShort($classReflection); - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new ConfiguredCodeSample( - <<<'CODE_SAMPLE' -class Some extends Command -{ -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -class SomeCommand extends Command -{ -} -CODE_SAMPLE - , - [ - 'parentClasses' => [Command::class], - ] - ), - ]); - } - - /** - * @return array - */ - private function processClassNameAndShort(ClassReflection $classReflection): array - { - foreach ($this->parentClasses as $parentClass) { - if (! $classReflection->isSubclassOf($parentClass)) { - continue; - } - - $expectedSuffix = $this->classToSuffixResolver->resolveFromClass($parentClass); - if (substr_compare($classReflection->getName(), $expectedSuffix, -strlen($expectedSuffix)) === 0) { - return []; - } - - $errorMessage = sprintf(self::ERROR_MESSAGE, $expectedSuffix); - return [$errorMessage]; - } - - return []; - } -} diff --git a/src/Rules/Complexity/ForbiddenArrayMethodCallRule.php b/src/Rules/Complexity/ForbiddenArrayMethodCallRule.php deleted file mode 100644 index 2d0c4650..00000000 --- a/src/Rules/Complexity/ForbiddenArrayMethodCallRule.php +++ /dev/null @@ -1,112 +0,0 @@ - - */ - public function getNodeType(): string - { - return Array_::class; - } - - /** - * @param Array_ $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (count($node->items) !== 2) { - return []; - } - - $typeWithClassName = $this->resolveFirstArrayItemClassType($node, $scope); - if (! $typeWithClassName instanceof TypeWithClassName) { - return []; - } - - $methodName = $this->resolveSecondArrayItemMethodName($node, $scope); - if ($methodName === null) { - return []; - } - - // does method exist? - if (! $typeWithClassName->hasMethod($methodName)->yes()) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -usort($items, [$this, "method"]); -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -usort($items, function (array $apples) { - return $this->method($apples); -}; -CODE_SAMPLE - ), - ]); - } - - private function resolveFirstArrayItemClassType(Array_ $array, Scope $scope): ?TypeWithClassName - { - $firstItem = $array->items[0]; - if (! $firstItem instanceof ArrayItem) { - return null; - } - - $firstItemType = $scope->getType($firstItem->value); - if (! $firstItemType instanceof TypeWithClassName) { - return null; - } - - return $firstItemType; - } - - private function resolveSecondArrayItemMethodName(Array_ $array, Scope $scope): ?string - { - $secondItem = $array->items[1]; - if (! $secondItem instanceof ArrayItem) { - return null; - } - - $secondItemValue = $secondItem->value; - - $secondItemType = $scope->getType($secondItemValue); - if (! $secondItemType instanceof ConstantStringType) { - return null; - } - - return $secondItemType->getValue(); - } -} diff --git a/src/Rules/Complexity/ForbiddenComplexForeachIfExprRule.php b/src/Rules/Complexity/ForbiddenComplexForeachIfExprRule.php deleted file mode 100644 index 65b640b3..00000000 --- a/src/Rules/Complexity/ForbiddenComplexForeachIfExprRule.php +++ /dev/null @@ -1,155 +0,0 @@ -> - */ - private const CALL_CLASS_TYPES = [MethodCall::class, StaticCall::class]; - - /** - * @var array - */ - private const ALLOWED_CLASS_TYPES = [Strings::class, TrinaryLogic::class]; - /** - * @var \PhpParser\NodeFinder - */ - private $nodeFinder; - /** - * @var \Symplify\PHPStanRules\TypeAnalyzer\ContainsTypeAnalyser - */ - private $containsTypeAnalyser; - public function __construct(NodeFinder $nodeFinder, ContainsTypeAnalyser $containsTypeAnalyser) - { - $this->nodeFinder = $nodeFinder; - $this->containsTypeAnalyser = $containsTypeAnalyser; - } - - /** - * @return array> - */ - public function getNodeTypes(): array - { - return [Foreach_::class, If_::class, ElseIf_::class, For_::class, Do_::class, While_::class]; - } - - /** - * @param Foreach_|If_|ElseIf_ $node - * @return string[] - */ - public function process(Node $node, Scope $scope): array - { - $expr = $node instanceof Foreach_ ? $node->expr : $node->cond; - - $assigns = $this->nodeFinder->findInstanceOf($expr, Assign::class); - if ($assigns !== []) { - return [self::ERROR_MESSAGE]; - } - - foreach (self::CALL_CLASS_TYPES as $expressionClassType) { - /** @var MethodCall[]|StaticCall[] $calls */ - $calls = $this->nodeFinder->findInstanceOf($expr, $expressionClassType); - foreach ($calls as $call) { - if ($this->shouldSkipCall($call, $scope)) { - continue; - } - - return [self::ERROR_MESSAGE]; - } - } - - return []; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -foreach ($this->getData($arg) as $key => $item) { - // ... -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -$data = $this->getData($arg); -foreach ($data as $key => $item) { - // ... -} -CODE_SAMPLE - ), - ]); - } - - /** - * @param \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall $expr - */ - private function shouldSkipCall($expr, Scope $scope): bool - { - if ($expr->args === []) { - return true; - } - - if ($this->isAllowedCallerType($scope, $expr)) { - return true; - } - - if ($this->containsTypeAnalyser->containsExprTypes($expr, $scope, self::ALLOWED_CLASS_TYPES)) { - return true; - } - - $callType = $scope->getType($expr); - return $callType instanceof BooleanType; - } - - /** - * @param \PhpParser\Node\Expr\StaticCall|\PhpParser\Node\Expr\MethodCall $node - */ - private function isAllowedCallerType(Scope $scope, $node): bool - { - if ($node instanceof StaticCall) { - if ($node->class instanceof Name) { - $className = $node->class->toString(); - return in_array($className, self::ALLOWED_CLASS_TYPES, true); - } - - return false; - } - - return $this->containsTypeAnalyser->containsExprTypes($node->var, $scope, self::ALLOWED_CLASS_TYPES); - } -} diff --git a/src/Rules/Complexity/ForbiddenInlineClassMethodRule.php b/src/Rules/Complexity/ForbiddenInlineClassMethodRule.php deleted file mode 100644 index 5435882a..00000000 --- a/src/Rules/Complexity/ForbiddenInlineClassMethodRule.php +++ /dev/null @@ -1,167 +0,0 @@ -nodeFinder = $nodeFinder; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return RuleError[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classLike = $node->getOriginalNode(); - if (! $classLike instanceof Class_) { - return []; - } - - foreach ($classLike->getMethods() as $classMethod) { - if (! $classMethod->isPrivate()) { - continue; - } - - // must be exactly one line - if (count((array) $classMethod->stmts) !== 1) { - continue; - } - - $onlyStmt = $classMethod->stmts[0] ?? null; - if (! $onlyStmt instanceof Return_) { - continue; - } - - if (! $onlyStmt->expr instanceof MethodCall) { - continue; - } - - $methodName = $classMethod->name->toString(); - - // this method is called just once in the rest of project - $usedMethodCalls = $this->findMethodCalls($classLike, $methodName); - - // we look exactly for one match - if (count($usedMethodCalls) === 1) { - $errorMessage = sprintf(self::ERROR_MESSAGE, $methodName); - - $ruleErrorBuilder = RuleErrorBuilder::message($errorMessage) - ->line($classMethod->getLine()); - - return [$ruleErrorBuilder->build()]; - } - } - - return []; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -class SomeClass -{ - public function run() - { - return $this->away(); - } - - private function away() - { - return mt_rand(0, 100); - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -class SomeClass -{ - public function run() - { - return mt_rand(0, 100); - } -} -CODE_SAMPLE - ), - ]); - } - - /** - * @return MethodCall[] - */ - private function findMethodCalls(Class_ $class, string $methodName): array - { - /** @var MethodCall[] $methodCalls */ - $methodCalls = $this->nodeFinder->findInstanceOf($class, MethodCall::class); - - $usedMethodCalls = []; - foreach ($methodCalls as $methodCall) { - if (! $methodCall->name instanceof Identifier) { - continue; - } - - $methodCallName = $methodCall->name->toString(); - if ($methodCallName !== $methodName) { - continue; - } - - // is local variable? - if (! $methodCall->var instanceof Variable) { - continue; - } - - if (! is_string($methodCall->var->name)) { - continue; - } - - if ($methodCall->var->name !== 'this') { - continue; - } - - $usedMethodCalls[] = $methodCall; - } - - return $usedMethodCalls; - } -} diff --git a/src/Rules/Complexity/ForbiddenNamedArgumentsRule.php b/src/Rules/Complexity/ForbiddenNamedArgumentsRule.php deleted file mode 100644 index c5887ad0..00000000 --- a/src/Rules/Complexity/ForbiddenNamedArgumentsRule.php +++ /dev/null @@ -1,66 +0,0 @@ - - */ - public function getNodeType(): string - { - return CallLike::class; - } - - /** - * @param CallLike $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - foreach ($node->getArgs() as $arg) { - if ($arg->name === null) { - continue; - } - - return [self::ERROR_MESSAGE]; - } - - return []; - } -} diff --git a/src/Rules/Complexity/ForbiddenSameNamedNewInstanceRule.php b/src/Rules/Complexity/ForbiddenSameNamedNewInstanceRule.php deleted file mode 100644 index 0da89967..00000000 --- a/src/Rules/Complexity/ForbiddenSameNamedNewInstanceRule.php +++ /dev/null @@ -1,135 +0,0 @@ - - */ -final class ForbiddenSameNamedNewInstanceRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'New objects with "%s" name are overridden. This can lead to unwanted bugs, please pick a different name to avoid it.'; - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -$product = new Product(); -$product = new Product(); - -$this->productRepository->save($product); -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -$firstProduct = new Product(); -$secondProduct = new Product(); - -$this->productRepository->save($firstProduct); -CODE_SAMPLE - ), - ]); - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return Expression::class; - } - - /** - * @param Expression $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! $node->expr instanceof Assign) { - return []; - } - - if ($this->shouldSkip($scope, $node)) { - return []; - } - - $assign = $node->expr; - - if (! $assign->var instanceof Variable) { - return []; - } - - if (! $assign->expr instanceof New_) { - return []; - } - - if (! is_string($assign->var->name)) { - return []; - } - - // is type already defined? - $variableName = $assign->var->name; - if (! $scope->hasVariableType($variableName)->yes()) { - return []; - } - - $variableType = $scope->getVariableType($variableName); - if ($variableType instanceof NullType) { - return []; - } - - $exprType = $scope->getType($node->expr); - if (! $exprType instanceof ObjectType) { - return []; - } - - $errorMessage = sprintf(self::ERROR_MESSAGE, '$' . $variableName); - return [$errorMessage]; - } - - private function shouldSkip(Scope $scope, Expression $expression): bool - { - if ($this->isNestedInForeach($expression)) { - return true; - } - - $classReflection = $scope->getClassReflection(); - - // skip tests, are easier to re-use variable there - return $classReflection instanceof ClassReflection && $classReflection->isSubclassOf(TestCase::class); - } - - private function isNestedInForeach(Expression $expression): bool - { - // only available on stmt - $parentStmtTypes = $expression->getAttribute(AttributeKey::PARENT_STMT_TYPES); - if (! is_array($parentStmtTypes)) { - return false; - } - - // skip in foreach, as nesting might be on purpose - return in_array(Foreach_::class, $parentStmtTypes, true); - } -} diff --git a/src/Rules/Complexity/NoAbstractRule.php b/src/Rules/Complexity/NoAbstractRule.php deleted file mode 100644 index 3df92e79..00000000 --- a/src/Rules/Complexity/NoAbstractRule.php +++ /dev/null @@ -1,101 +0,0 @@ - - */ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classLike = $node->getOriginalNode(); - if (! $classLike instanceof Class_) { - return []; - } - - if (! $classLike->isAbstract()) { - return []; - } - - $classReflection = $scope->getClassReflection(); - if (! $classReflection instanceof ClassReflection) { - return []; - } - - foreach (self::ALLOWED_TYPES as $allowedType) { - if ($classReflection->isSubclassOf($allowedType)) { - return []; - } - } - - return [self::ERROR_MESSAGE]; - } -} diff --git a/src/Rules/Complexity/NoDuplicatedArgumentRule.php b/src/Rules/Complexity/NoDuplicatedArgumentRule.php deleted file mode 100644 index 93c766b1..00000000 --- a/src/Rules/Complexity/NoDuplicatedArgumentRule.php +++ /dev/null @@ -1,123 +0,0 @@ -reflectionProvider = $reflectionProvider; - $this->scalarValueResolver = $scalarValueResolver; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return CallLike::class; - } - - /** - * @param CallLike $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! $node instanceof MethodCall && ! $node instanceof FuncCall && ! $node instanceof StaticCall) { - return []; - } - - if ($this->shouldSkip($node, $scope)) { - return []; - } - - $countValues = $this->scalarValueResolver->resolveValuesCountFromArgs($node->getArgs(), $scope); - - // each of kind - if ($countValues === []) { - return []; - } - - $maxCountValues = max($countValues); - if ($maxCountValues === 1) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition( - self::ERROR_MESSAGE, - [new CodeSample( - <<<'CODE_SAMPLE' -function run($one, $one); -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -function run($one, $two); -CODE_SAMPLE - )] - ); - } - - /** - * @param \PhpParser\Node\Expr\StaticCall|\PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\FuncCall $expr - */ - private function shouldSkip($expr, Scope $scope): bool - { - if (\count($expr->args) < 2) { - return true; - } - - if ($expr instanceof FuncCall) { - if (! $expr->name instanceof Name) { - return true; - } - - if (! $this->reflectionProvider->hasFunction($expr->name, $scope)) { - return false; - } - - // skip native functions - $functionReflection = $this->reflectionProvider->getFunction($expr->name, $scope); - return $functionReflection->isBuiltin(); - } - - return false; - } -} diff --git a/src/Rules/Complexity/NoDuplicatedTraitMethodNameRule.php b/src/Rules/Complexity/NoDuplicatedTraitMethodNameRule.php deleted file mode 100644 index 0ada4b6b..00000000 --- a/src/Rules/Complexity/NoDuplicatedTraitMethodNameRule.php +++ /dev/null @@ -1,122 +0,0 @@ - - */ -final class NoDuplicatedTraitMethodNameRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'Method name "%s()" is used in multiple traits. Make it unique to avoid conflicts'; - - /** - * @return class-string - */ - public function getNodeType(): string - { - return CollectedDataNode::class; - } - - /** - * @param CollectedDataNode $node - * @return RuleError[] - */ - public function processNode(Node $node, Scope $scope): array - { - $traitMethodNameCollector = $node->get(TraitMethodNameCollector::class); - - $traitsByMethodName = []; - foreach ($traitMethodNameCollector as $fileName => $collectedData) { - foreach ($collectedData as [$traitNames, $line]) { - foreach ($traitNames as $traitName) { - /** @var string $traitName */ - $traitsByMethodName[$traitName][] = $fileName; - } - } - } - - return $this->createRuleErrors($traitsByMethodName); - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition( - self::ERROR_MESSAGE, - [new CodeSample( - <<<'CODE_SAMPLE' -trait FirstTrait -{ - public function run() - { - } -} - -trait SecondTrait -{ - public function run() - { - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -trait FirstTrait -{ - public function run() - { - } -} - -trait SecondTrait -{ - public function fly() - { - } -} -CODE_SAMPLE - )] - ); - } - - /** - * @param array $traitsByMethodName - * @return RuleError[] - */ - private function createRuleErrors(array $traitsByMethodName): array - { - $ruleErrors = []; - - foreach ($traitsByMethodName as $traitMethodName => $traitFiles) { - if (count($traitFiles) === 1) { - continue; - } - - foreach ($traitFiles as $traitFile) { - $errorMessage = sprintf(self::ERROR_MESSAGE, $traitMethodName); - $ruleErrors[] = RuleErrorBuilder::message($errorMessage) - ->file($traitFile) - ->build(); - } - } - - return $ruleErrors; - } -} diff --git a/src/Rules/Complexity/NoMirrorAssertRule.php b/src/Rules/Complexity/NoMirrorAssertRule.php deleted file mode 100644 index 42037d41..00000000 --- a/src/Rules/Complexity/NoMirrorAssertRule.php +++ /dev/null @@ -1,167 +0,0 @@ -standard = $standard; - $this->nodeFinder = $nodeFinder; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -use PHPUnit\Framework\TestCase; - -final class AssertMirror extends TestCase -{ - public function test() - { - $this->assertSame(1, 1); - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -use PHPUnit\Framework\TestCase; - -final class AssertMirror extends TestCase -{ - public function test() - { - $value = 200; - $this->assertSame(1, $value); - } -} -CODE_SAMPLE - ), - ]); - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return RuleError[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classReflection = $scope->getClassReflection(); - if (! $classReflection instanceof ClassReflection) { - return []; - } - - if (! $classReflection->isSubclassOf('PHPUnit\Framework\TestCase')) { - return []; - } - - $classLike = $node->getOriginalNode(); - if (! $classLike instanceof Class_) { - return []; - } - - $errorMessages = []; - - $assertMethodCalls = $this->findAssertMethodCalls($classLike); - - foreach ($assertMethodCalls as $assertMethodCall) { - if (! $this->areFirstAndSecondArgTheSame($assertMethodCall)) { - continue; - } - - $errorMessages[] = RuleErrorBuilder::message(self::ERROR_MESSAGE) - ->line($assertMethodCall->getLine()) - ->build(); - } - - return $errorMessages; - } - - private function areFirstAndSecondArgTheSame(MethodCall $methodCall): bool - { - $args = $methodCall->getArgs(); - - $firstArgValue = $args[0]->value; - $secondArgValue = $args[1]->value; - - $firstArgValueContent = $this->standard->prettyPrintExpr($firstArgValue); - $secondArgValueContent = $this->standard->prettyPrintExpr($secondArgValue); - - return $firstArgValueContent === $secondArgValueContent; - } - - /** - * @return MethodCall[] - */ - private function findAssertMethodCalls(Class_ $class): array - { - /** @var MethodCall[] $methodCalls */ - $methodCalls = $this->nodeFinder->findInstanceOf($class->stmts, MethodCall::class); - - $assertMethodCalls = []; - - foreach ($methodCalls as $methodCall) { - // compare 1st and 2nd value - if (count($methodCall->getArgs()) < 2) { - continue; - } - - // only "assert*" methods - if (! $methodCall->name instanceof Identifier) { - continue; - } - - $methodCallName = $methodCall->name->toString(); - if (strncmp($methodCallName, 'assert', strlen('assert')) !== 0) { - continue; - } - - $assertMethodCalls[] = $methodCall; - } - - return $assertMethodCalls; - } -} diff --git a/src/Rules/DeadCode/UnusedPublicClassConstRule.php b/src/Rules/DeadCode/UnusedPublicClassConstRule.php deleted file mode 100644 index 107bc118..00000000 --- a/src/Rules/DeadCode/UnusedPublicClassConstRule.php +++ /dev/null @@ -1,94 +0,0 @@ -build(), - ]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -final class Direction -{ - public LEFT = 'left'; - - public RIGHT = 'right'; - - public STOP = 'stop'; -} - -if ($direction === Direction::LEFT) { - echo 'left'; -} - -if ($direction === Direction::RIGHT) { - echo 'right'; -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -final class Direction -{ - public LEFT = 'left'; - - public RIGHT = 'right'; -} - -if ($direction === Direction::LEFT) { - echo 'left'; -} - -if ($direction === Direction::RIGHT) { - echo 'right'; -} -CODE_SAMPLE - ), - ]); - } -} diff --git a/src/Rules/DeadCode/UnusedPublicClassMethodRule.php b/src/Rules/DeadCode/UnusedPublicClassMethodRule.php deleted file mode 100644 index 53877724..00000000 --- a/src/Rules/DeadCode/UnusedPublicClassMethodRule.php +++ /dev/null @@ -1,96 +0,0 @@ -build(), - ]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -final class Car -{ - public function turn() - { - } - - public function stay() - { - } -} - -final class Driver -{ - public function driveCar(Car $car) - { - $car->turn(); - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -final class Car -{ - public function turn() - { - } -} - -final class Driver -{ - public function driveCar(Car $car) - { - $car->turn(); - } -} -CODE_SAMPLE - ), - ]); - } -} diff --git a/src/Rules/DeadCode/UnusedPublicPropertyRule.php b/src/Rules/DeadCode/UnusedPublicPropertyRule.php deleted file mode 100644 index f96e9e0b..00000000 --- a/src/Rules/DeadCode/UnusedPublicPropertyRule.php +++ /dev/null @@ -1,77 +0,0 @@ -build(), - ]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -final class Car -{ - public $name; - - public function getName() - { - return $this->name; - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -final class Car -{ - private $name; - - public function getName() - { - return $this->name; - } -} -CODE_SAMPLE - ), - ]); - } -} diff --git a/src/Rules/DeadCode/UnusedPublicStaticPropertyRule.php b/src/Rules/DeadCode/UnusedPublicStaticPropertyRule.php deleted file mode 100644 index c6c14d7a..00000000 --- a/src/Rules/DeadCode/UnusedPublicStaticPropertyRule.php +++ /dev/null @@ -1,82 +0,0 @@ -build(), - ]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -final class ResultProvider -{ - public static $some; - - public function getSome() - { - return self::$some; - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -final class ResultProvider -{ - private static $some; - - public function getSome() - { - return self::$some; - } -} -CODE_SAMPLE - ), - ]); - } -} diff --git a/src/Rules/Domain/ForbiddenAlwaysSetterCallRule.php b/src/Rules/Domain/ForbiddenAlwaysSetterCallRule.php deleted file mode 100644 index 1dc20e83..00000000 --- a/src/Rules/Domain/ForbiddenAlwaysSetterCallRule.php +++ /dev/null @@ -1,114 +0,0 @@ - - * - * @see \Symplify\PHPStanRules\Tests\Rules\Domain\ForbiddenAlwaysSetterCallRule\ForbiddenAlwaysSetterCallRuleTest - */ -final class ForbiddenAlwaysSetterCallRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'The "%s" class always calls "%s()" setters, better move it to constructor'; - - public function getNodeType(): string - { - return CollectedDataNode::class; - } - - /** - * @param CollectedDataNode $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - $newAndSetterCalls = $node->get(NewAndSetterCallsCollector::class); - - $formTypeClassesCollector = $node->get(FormTypeClassCollector::class); - $formTypeClasses = Arrays::flatten($formTypeClassesCollector); - - $groupedCallsByClass = $this->createGrouppedCallsByClass($newAndSetterCalls); - - $ruleErrors = []; - - foreach ($groupedCallsByClass as $class => $methodCalls) { - // skip classes that are used in form_types, they always need setters/getters - if (in_array($class, $formTypeClasses, true)) { - continue; - } - - if (count($methodCalls) === 1) { - continue; - } - - $alwaysCalledMethodCalls = array_intersect(...$methodCalls); - if ($alwaysCalledMethodCalls === []) { - continue; - } - - $ruleErrors[] = sprintf(self::ERROR_MESSAGE, $class, implode('()", "', $alwaysCalledMethodCalls)); - } - - return $ruleErrors; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -$firstPerson = new Person(); -$firstPerson->setName('John'); - -$secondPerson = new Person(); -$secondPerson->setName('Van'); -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -$firstPerson = new Person('John'); - -$secondPerson = new Person('Van'); -CODE_SAMPLE - ), - ]); - } - - /** - * @param mixed[] $collections - * @return array - */ - private function createGrouppedCallsByClass(array $collections): array - { - $groupedCallsByClass = []; - - foreach ($collections as $collection) { - foreach ($collection as $methodCallsByVariableAndClass) { - foreach ($methodCallsByVariableAndClass as $className => $methodCallsByVariable) { - foreach ($methodCallsByVariable as $methodCalls) { - /** @var string $className */ - /** @var string[] $methodCalls */ - $groupedCallsByClass[$className][] = $methodCalls; - } - } - } - } - - return $groupedCallsByClass; - } -} diff --git a/src/Rules/Domain/NoDuplicatedRegexRule.php b/src/Rules/Domain/NoDuplicatedRegexRule.php deleted file mode 100644 index 07766cd4..00000000 --- a/src/Rules/Domain/NoDuplicatedRegexRule.php +++ /dev/null @@ -1,128 +0,0 @@ - - */ - public function getNodeType(): string - { - return CollectedDataNode::class; - } - - /** - * @param CollectedDataNode $node - * @return RuleError[] - */ - public function processNode(Node $node, Scope $scope): array - { - $regexClassConsts = $node->get(RegexClassConstCollector::class); - $regexConstMetadatasBySharedRegex = $this->groupConstantsBySharedValue($regexClassConsts); - - return $this->createRuleErrorsForDuplicatedRegexes($regexConstMetadatasBySharedRegex); - } - - /** - * @param mixed[] $regexClassConsts - * @return array - */ - private function groupConstantsBySharedValue(array $regexClassConsts): array - { - $regexConstMetadataBySharedRegex = []; - - foreach ($regexClassConsts as $filePath => $collectedDatas) { - foreach ($collectedDatas as $collectedData) { - foreach ($collectedData as [$constName, $regexValue, $line]) { - $regexConstMetadataBySharedRegex[$regexValue][] = new ClassConstRegexMetadata( - $constName, - $regexValue, - $filePath, - $line - ); - } - } - } - - return $regexConstMetadataBySharedRegex; - } - - /** - * @param array $regexConstMetadatasBySharedRegex - * @return RuleError[] - */ - private function createRuleErrorsForDuplicatedRegexes(array $regexConstMetadatasBySharedRegex): array - { - $ruleErrors = []; - - foreach ($regexConstMetadatasBySharedRegex as $regexConstMetadatas) { - if (count($regexConstMetadatas) === 1) { - continue; - } - - foreach ($regexConstMetadatas as $regexConstMetadata) { - $errorMessage = sprintf( - self::ERROR_MESSAGE, - $regexConstMetadata->getConstantName(), - $regexConstMetadata->getRegexValue() - ); - - $ruleErrors[] = RuleErrorBuilder::message($errorMessage) - ->line($regexConstMetadata->getLine()) - ->file($regexConstMetadata->getFilePath()) - ->build(); - } - } - - return $ruleErrors; - } -} diff --git a/src/Rules/Domain/RequireAttributeNamespaceRule.php b/src/Rules/Domain/RequireAttributeNamespaceRule.php deleted file mode 100644 index dafcd091..00000000 --- a/src/Rules/Domain/RequireAttributeNamespaceRule.php +++ /dev/null @@ -1,79 +0,0 @@ - - */ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classReflection = $node->getClassReflection(); - if (! $classReflection->isAttributeClass()) { - return []; - } - - // is class in "Attribute" namespace? - $className = $classReflection->getName(); - if (strpos($className, '\\Attribute\\') !== false) { - return []; - } - - return [self::ERROR_MESSAGE]; - } -} diff --git a/src/Rules/Domain/RequireExceptionNamespaceRule.php b/src/Rules/Domain/RequireExceptionNamespaceRule.php deleted file mode 100644 index bf922c56..00000000 --- a/src/Rules/Domain/RequireExceptionNamespaceRule.php +++ /dev/null @@ -1,82 +0,0 @@ - - */ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classReflection = $node->getClassReflection(); - if (! $classReflection->isClass()) { - return []; - } - - if (! $classReflection->isSubclassOf('Exception')) { - return []; - } - - // is class in "Exception" namespace? - $className = $classReflection->getName(); - if (strpos($className, '\\Exception\\') !== false) { - return []; - } - - return [self::ERROR_MESSAGE]; - } -} diff --git a/src/Rules/Enum/EmbeddedEnumClassConstSpotterRule.php b/src/Rules/Enum/EmbeddedEnumClassConstSpotterRule.php deleted file mode 100644 index c6a9d593..00000000 --- a/src/Rules/Enum/EmbeddedEnumClassConstSpotterRule.php +++ /dev/null @@ -1,165 +0,0 @@ - - */ - private $parentTypes; - - /** - * @param array $parentTypes - */ - public function __construct(ClassAnalyzer $classAnalyzer, SharedNamePrefixMatcher $sharedNamePrefixMatcher, EnumConstantAnalyzer $enumConstantAnalyzer, array $parentTypes) - { - $this->classAnalyzer = $classAnalyzer; - $this->sharedNamePrefixMatcher = $sharedNamePrefixMatcher; - $this->enumConstantAnalyzer = $enumConstantAnalyzer; - $this->parentTypes = $parentTypes; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return mixed[] - */ - public function processNode(Node $node, Scope $scope): array - { - if ($this->shouldSkip($node)) { - return []; - } - - $classLike = $node->getOriginalNode(); - if (! $classLike instanceof Class_) { - return []; - } - - $constantNames = $this->classAnalyzer->resolveConstantNames($classLike); - - $groupedByPrefix = $this->sharedNamePrefixMatcher->match($constantNames); - - $enumConstantNamesGroup = []; - - foreach ($groupedByPrefix as $prefix => $constantNames) { - if (\count($constantNames) < 1) { - continue; - } - - if ($this->enumConstantAnalyzer->isNonEnumConstantPrefix($prefix)) { - continue; - } - - $enumConstantNamesGroup[] = $constantNames; - } - - return $this->createErrorMessages($enumConstantNamesGroup); - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [new ConfiguredCodeSample( - <<<'CODE_SAMPLE' -class SomeProduct extends AbstractObject -{ - public const STATUS_ENABLED = 1; - - public const STATUS_DISABLED = 0; -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -class SomeProduct extends AbstractObject -{ -} - -class SomeStatus -{ - public const ENABLED = 1; - - public const DISABLED = 0; -} -CODE_SAMPLE - , - [ - 'parentTypes' => ['AbstractObject'], - ] - )]); - } - - private function shouldSkip(InClassNode $inClassNode): bool - { - $classReflection = $inClassNode->getClassReflection(); - - // already enum - if (strpos($classReflection->getName(), '\\Enum\\') !== false && strpos($classReflection->getName(), '\\Rules\\Enum\\') === false) { - return true; - } - - foreach ($this->parentTypes as $parentType) { - if ($classReflection->isSubclassOf($parentType)) { - return false; - } - } - - return true; - } - - /** - * @param string[][] $enumConstantNamesGroup - * @return string[] - */ - private function createErrorMessages(array $enumConstantNamesGroup): array - { - $errorMessages = []; - - foreach ($enumConstantNamesGroup as $enumConstantNameGroup) { - $enumConstantNamesString = \implode('", "', $enumConstantNameGroup); - $errorMessages[] = \sprintf(self::ERROR_MESSAGE, $enumConstantNamesString); - } - - return $errorMessages; - } -} diff --git a/src/Rules/Enum/NoConstantInterfaceRule.php b/src/Rules/Enum/NoConstantInterfaceRule.php deleted file mode 100644 index a67481b5..00000000 --- a/src/Rules/Enum/NoConstantInterfaceRule.php +++ /dev/null @@ -1,70 +0,0 @@ - - */ - public function getNodeType(): string - { - return Interface_::class; - } - - /** - * @param Interface_ $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if ($node->getConstants() === []) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -interface SomeContract -{ - public const YES = 'yes'; - - public const NO = 'no'; -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -class SomeValues -{ - public const YES = 'yes'; - - public const NO = 'no'; -} -CODE_SAMPLE - ), - ]); - } -} diff --git a/src/Rules/Enum/RequireConstantInMethodCallPositionRule.php b/src/Rules/Enum/RequireConstantInMethodCallPositionRule.php deleted file mode 100644 index addffe05..00000000 --- a/src/Rules/Enum/RequireConstantInMethodCallPositionRule.php +++ /dev/null @@ -1,160 +0,0 @@ -> - */ - private $requiredConstantInMethodCall; - - /** - * @param array> $requiredConstantInMethodCall - */ - public function __construct(PositionMatcher $positionMatcher, array $requiredConstantInMethodCall) - { - $this->positionMatcher = $positionMatcher; - $this->requiredConstantInMethodCall = $requiredConstantInMethodCall; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return MethodCall::class; - } - - /** - * @param MethodCall $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! $node->name instanceof Identifier) { - return []; - } - - return $this->getErrorMessages($node, $scope, $this->requiredConstantInMethodCall); - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new ConfiguredCodeSample( - <<<'CODE_SAMPLE' -class SomeClass -{ - public function someMethod(SomeType $someType) - { - $someType->someMethod('hey'); - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -class SomeClass -{ - private const HEY = 'hey' - - public function someMethod(SomeType $someType) - { - $someType->someMethod(self::HEY); - } -} -CODE_SAMPLE - , - [ - 'requiredLocalConstantInMethodCall' => [ - 'SomeType' => [ - 'someMethod' => [0], - ], - ], - ] - ), - ]); - } - - /** - * @param array> $config - * @return string[] - */ - private function getErrorMessages(MethodCall $methodCall, Scope $scope, array $config): array - { - /** @var Identifier $name */ - $name = $methodCall->name; - $methodName = (string) $name; - $errorMessages = []; - - foreach ($config as $type => $positionsByMethods) { - $positions = $this->positionMatcher->matchPositions( - $methodCall, - $scope, - $type, - $positionsByMethods, - $methodName - ); - if ($positions === null) { - continue; - } - - foreach ($methodCall->args as $key => $arg) { - if (! $arg instanceof Arg) { - continue; - } - - if ($this->shouldSkipArg($key, $positions, $arg)) { - continue; - } - - $errorMessages[] = sprintf(self::ERROR_MESSAGE, $key); - } - } - - return $errorMessages; - } - - /** - * @param int[] $positions - */ - private function shouldSkipArg(int $key, array $positions, Arg $arg): bool - { - if (! in_array($key, $positions, true)) { - return true; - } - - if ($arg->value instanceof Variable) { - return true; - } - - return $arg->value instanceof ClassConstFetch; - } -} diff --git a/src/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule.php b/src/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule.php deleted file mode 100644 index 2bbb46b8..00000000 --- a/src/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule.php +++ /dev/null @@ -1,200 +0,0 @@ - - */ -final class RequireEnumDocBlockOnConstantListPassRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'On passing a constant, the method should have an enum type. See https://phpstan.org/writing-php-code/phpdoc-types#literals-and-constants'; - - /** - * These types expect constant lists that are not enums - * - * @var string[] - */ - private const SKIPPED_CLASS_TYPES = [ - 'Symplify\PackageBuilder\Parameter\ParameterProvider', - AbstractConfigurator::class, - ParameterBagInterface::class, - ]; - /** - * @var \Symplify\PHPStanRules\Reflection\MethodCallNodeAnalyzer - */ - private $methodCallNodeAnalyzer; - /** - * @var \Symplify\PHPStanRules\NodeAnalyzer\MethodCall\MethodCallClassConstFetchPositionResolver - */ - private $methodCallClassConstFetchPositionResolver; - public function __construct(MethodCallNodeAnalyzer $methodCallNodeAnalyzer, MethodCallClassConstFetchPositionResolver $methodCallClassConstFetchPositionResolver) - { - $this->methodCallNodeAnalyzer = $methodCallNodeAnalyzer; - $this->methodCallClassConstFetchPositionResolver = $methodCallClassConstFetchPositionResolver; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return MethodCall::class; - } - - /** - * @param MethodCall $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - // has argument of constant class reference - $classConstFetchArgPositions = $this->methodCallClassConstFetchPositionResolver->resolve($node); - if ($classConstFetchArgPositions === []) { - return []; - } - - $parameterReflections = $this->resolveParameterReflections($node, $scope); - - foreach ($parameterReflections as $position => $parameterReflection) { - // is desired arg position? - if (! in_array($position, $classConstFetchArgPositions, true)) { - continue; - } - - // this must be some more strict type - if ($parameterReflection->getType() instanceof StringType) { - return [self::ERROR_MESSAGE]; - } - } - - return []; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -final class Direction -{ - public const LEFT = 'left'; - - public const RIGHT = 'right'; -} - -final class Driver -{ - public function goToWork() - { - $this->turn(Direction::LEFT); - } - - private function turn(string $direction) - { - // ... - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -final class Direction -{ - public const LEFT = 'left'; - - public const RIGHT = 'right'; -} - -final class Driver -{ - public function goToWork() - { - $this->turn(Direction::LEFT); - } - - /** - * @param Direction::* - */ - private function turn(string $direction) - { - // ... - } -} -CODE_SAMPLE - ), - ]); - } - - /** - * @return array - */ - private function resolveParameterReflections(MethodCall $methodCall, Scope $scope): array - { - $phpMethodReflection = $this->methodCallNodeAnalyzer->resolveMethodCallReflection($methodCall, $scope); - if (! $phpMethodReflection instanceof PhpMethodReflection) { - return []; - } - - // is skipped type? - if ($this->shouldSkipClass($phpMethodReflection->getDeclaringClass())) { - return []; - } - - $parametersAcceptorWithPhpDocs = ParametersAcceptorSelector::selectSingle($phpMethodReflection->getVariants()); - return $parametersAcceptorWithPhpDocs->getParameters(); - } - - private function shouldSkipClass(ClassReflection $classReflection): bool - { - if ($classReflection->isInternal()) { - return true; - } - - $fileName = $classReflection->getFileName(); - if (! is_string($fileName)) { - return true; - } - - // skip vendor classes, as we cannot change them - if (strpos($fileName, '/vendor/') !== false) { - return true; - } - - foreach (self::SKIPPED_CLASS_TYPES as $skippedClassType) { - // skip vendor class, as we can't reach it - if ($classReflection->isSubclassOf($skippedClassType)) { - return true; - } - - if ($skippedClassType === $classReflection->getName()) { - return true; - } - } - - return false; - } -} diff --git a/src/Rules/Enum/RequireNewArgumentConstantRule.php b/src/Rules/Enum/RequireNewArgumentConstantRule.php deleted file mode 100644 index baf9986a..00000000 --- a/src/Rules/Enum/RequireNewArgumentConstantRule.php +++ /dev/null @@ -1,107 +0,0 @@ - - */ - private $constantArgByNewByType; - - /** - * @param array $constantArgByNewByType - */ - public function __construct(array $constantArgByNewByType) - { - $this->constantArgByNewByType = $constantArgByNewByType; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return New_::class; - } - - /** - * @param New_ $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - $class = $node->class; - if (! $class instanceof FullyQualified) { - return []; - } - - $className = $class->toString(); - if (! array_key_exists($className, $this->constantArgByNewByType)) { - return []; - } - - $args = $node->args; - $positions = $this->constantArgByNewByType[$className]; - - foreach ($positions as $position) { - $argOrVariadicPlaceholder = $args[$position]; - if (! $argOrVariadicPlaceholder instanceof Arg) { - continue; - } - - if (! $argOrVariadicPlaceholder->value instanceof ClassConstFetch) { - return [sprintf(self::ERROR_MESSAGE, $position)]; - } - } - - return []; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new ConfiguredCodeSample( - <<<'CODE_SAMPLE' -use Symfony\Component\Console\Input\InputOption; - -$inputOption = new InputOption('name', null, 2); -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -use Symfony\Component\Console\Input\InputOption; - -$inputOption = new InputOption('name', null, InputOption::VALUE_REQUIRED); -CODE_SAMPLE - , - [ - 'constantArgByNewByType' => [ - InputOption::class => [2], - ], - ] - ), - ]); - } -} diff --git a/src/Rules/Enum/RequireUniqueEnumConstantRule.php b/src/Rules/Enum/RequireUniqueEnumConstantRule.php deleted file mode 100644 index eb50e10c..00000000 --- a/src/Rules/Enum/RequireUniqueEnumConstantRule.php +++ /dev/null @@ -1,138 +0,0 @@ -enumAnalyzer = $enumAnalyzer; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! $this->enumAnalyzer->detect($scope, $node->getOriginalNode())) { - return []; - } - - $classLike = $node->getOriginalNode(); - $constantValues = $this->resolveClassConstantValues($classLike, $scope); - if ($constantValues === []) { - return []; - } - - $duplicatedConstantValues = $this->filterDuplicatedValues($constantValues); - if ($duplicatedConstantValues === []) { - return []; - } - - $errorMessage = sprintf(self::ERROR_MESSAGE, implode('", "', $duplicatedConstantValues)); - return [$errorMessage]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -use MyCLabs\Enum\Enum; - -class SomeClass extends Enum -{ - private const YES = 'yes'; - - private const NO = 'yes'; -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -use MyCLabs\Enum\Enum; - -class SomeClass extends Enum -{ - private const YES = 'yes'; - - private const NO = 'no'; -} -CODE_SAMPLE - ), - ]); - } - - /** - * @param array $values - * @return array - */ - private function filterDuplicatedValues(array $values): array - { - $countValues = array_count_values($values); - - $duplicatedValues = []; - foreach ($countValues as $valueName => $valueCount) { - if ($valueCount <= 1) { - continue; - } - - $duplicatedValues[] = $valueName; - } - - return $duplicatedValues; - } - - /** - * @return array - */ - private function resolveClassConstantValues(ClassLike $classLike, Scope $scope): array - { - $constantValues = []; - foreach ($classLike->getConstants() as $classConst) { - foreach ($classConst->consts as $const) { - $constValueType = $scope->getType($const->value); - if (! $constValueType instanceof ConstantStringType) { - continue; - } - - $constantValues[] = $constValueType->getValue(); - } - } - - return $constantValues; - } -} diff --git a/src/Rules/ExclusiveDependencyRule.php b/src/Rules/ExclusiveDependencyRule.php deleted file mode 100644 index 09b1ef4f..00000000 --- a/src/Rules/ExclusiveDependencyRule.php +++ /dev/null @@ -1,169 +0,0 @@ - - */ - private $allowedExclusiveDependencyInTypes; - - /** - * @param array $allowedExclusiveDependencyInTypes - */ - public function __construct(ArrayStringAndFnMatcher $arrayStringAndFnMatcher, array $allowedExclusiveDependencyInTypes) - { - $this->arrayStringAndFnMatcher = $arrayStringAndFnMatcher; - $this->allowedExclusiveDependencyInTypes = $allowedExclusiveDependencyInTypes; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return InClassMethodNode::class; - } - - /** - * @param InClassMethodNode $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classMethod = $node->getOriginalNode(); - if ($classMethod->name->toString() !== MethodName::CONSTRUCTOR) { - return []; - } - - $extendedMethodReflection = $node->getMethodReflection(); - $declaringClassReflection = $extendedMethodReflection->getDeclaringClass(); - - $className = $declaringClassReflection->getName(); - $paramTypes = $this->resolveParamTypes($classMethod); - - foreach ($paramTypes as $paramType) { - foreach ($this->allowedExclusiveDependencyInTypes as $dependencyType => $allowedTypes) { - if ($this->isExclusiveMatchingDependency($paramType, $dependencyType, $className, $allowedTypes)) { - continue; - } - - $errorMessage = sprintf(self::ERROR_MESSAGE, $dependencyType, implode('", "', $allowedTypes)); - return [$errorMessage]; - } - } - - return []; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition('Dependency of specific type can be used only in specific class types', [ - new ConfiguredCodeSample( - <<<'CODE_SAMPLE' -final class CheckboxController -{ - public function __construct( - private EntityManagerInterface $entityManager - ) { - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -final class CheckboxRepository -{ - public function __construct( - private EntityManagerInterface $entityManager - ) { - } -} -CODE_SAMPLE - , - [ - 'allowedExclusiveDependencyInTypes' => [ - 'Doctrine\ORM\EntityManager' => ['*Repository'], - 'Doctrine\ORM\EntityManagerInterface' => ['*Repository'], - ], - ] - ), - ]); - } - - /** - * @param string[] $allowedTypes - */ - private function isExclusiveMatchingDependency( - string $paramType, - string $dependencyType, - string $className, - array $allowedTypes - ): bool { - if (! $this->arrayStringAndFnMatcher->isMatch($paramType, [$dependencyType])) { - return true; - } - - // instancef of but with static reflection - $classObjectType = new ObjectType($className); - foreach ($allowedTypes as $allowedType) { - if ($classObjectType->isInstanceOf($allowedType)->yes()) { - return true; - } - } - - return $this->arrayStringAndFnMatcher->isMatch($className, $allowedTypes); - } - - /** - * @return string[] - */ - private function resolveParamTypes(ClassMethod $classMethod): array - { - $paramTypes = []; - - foreach ($classMethod->params as $param) { - /** @var Param $param */ - if ($param->type === null) { - continue; - } - - if (! $param->type instanceof Identifier && ! $param->type instanceof Name) { - continue; - } - - $paramTypes[] = $param->type->toString(); - } - - return $paramTypes; - } -} diff --git a/src/Rules/ExclusiveNamespaceRule.php b/src/Rules/ExclusiveNamespaceRule.php deleted file mode 100644 index 9ca27c47..00000000 --- a/src/Rules/ExclusiveNamespaceRule.php +++ /dev/null @@ -1,124 +0,0 @@ -namespaceParts = $namespaceParts; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classReflection = $node->getClassReflection(); - $className = $classReflection->getName(); - - // skip interface and tests, except tests here - if (Strings::match($className, self::EXCLUDED_NAMESPACE_REGEX)) { - return []; - } - - $namespace = $scope->getNamespace(); - if ($namespace === null) { - return []; - } - - foreach ($this->namespaceParts as $namespacePart) { - if (substr_compare($namespace, $namespacePart, -strlen($namespacePart)) !== 0) { - continue; - } - - if (Strings::match($className, self::EXCLUDED_SUFFIX_REGEX)) { - continue; - } - - if (substr_compare($className, $namespacePart, -strlen($namespacePart)) === 0) { - continue; - } - - $errorMessage = sprintf(self::ERROR_MESSAGE, $namespace, $namespacePart); - return [$errorMessage]; - } - - return []; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition('Exclusive namespace can only contain classes of specific type, nothing else', [ - new ConfiguredCodeSample( - <<<'CODE_SAMPLE' -namespace App\Presenter; - -class SomeRepository -{ -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -namespace App\Presenter; - -class SomePresenter -{ -} -CODE_SAMPLE - , - [ - 'namespaceParts' => ['Presenter'], - ] - ), - ]); - } -} diff --git a/src/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule.php b/src/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule.php deleted file mode 100644 index 4dc884d1..00000000 --- a/src/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule.php +++ /dev/null @@ -1,221 +0,0 @@ -%s()" method call'; - - /** - * @var string - */ - private const GET_METHOD_NAME = '__get'; - - /** - * @var string - */ - private const SET_METHOD_NAME = '__set'; - /** - * @var \Symplify\PHPStanRules\Reflection\PublicClassReflectionAnalyzer - */ - private $publicClassReflectionAnalyzer; - - public function __construct(PublicClassReflectionAnalyzer $publicClassReflectionAnalyzer) - { - $this->publicClassReflectionAnalyzer = $publicClassReflectionAnalyzer; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -use Nette\SmartObject; - -final class MagicObject -{ - // adds magic __get() and __set() methods - use SmartObject; - - private $name; - - public function getName() - { - return $this->name; - } -} - -$magicObject = new MagicObject(); -// magic re-directed to method -$magicObject->name; -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -use Nette\SmartObject; - -final class MagicObject -{ - // adds magic __get() and __set() methods - use SmartObject; - - private $name; - - public function getName() - { - return $this->name; - } -} - -$magicObject = new MagicObject(); -// explicit -$magicObject->getName(); -CODE_SAMPLE - ), - - ]); - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return PropertyFetch::class; - } - - /** - * @param PropertyFetch $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - // skip local "$this" calls - if ($this->isVariableThis($node->var)) { - return []; - } - - $callerClassReflection = $this->resolveClassReflection($scope, $node->var); - if (! $callerClassReflection instanceof ClassReflection) { - return []; - } - - if (! $node->name instanceof Identifier) { - return []; - } - - $propertyName = $node->name->toString(); - - // has public native property? - if ($this->publicClassReflectionAnalyzer->hasPublicNativeProperty($callerClassReflection, $propertyName)) { - return []; - } - - if ($scope->isInExpressionAssign($node)) { - return $this->processSetterMethodCall($node, $callerClassReflection, $propertyName); - } - - return $this->processGetterMethodCall($node, $callerClassReflection, $propertyName); - } - - private function resolveClassReflection(Scope $scope, Expr $expr): ?\PHPStan\Reflection\ClassReflection - { - $callerType = $scope->getType($expr); - if (! $callerType instanceof TypeWithClassName) { - return null; - } - - return $callerType->getClassReflection(); - } - - /** - * @return string[] - */ - private function processSetterMethodCall( - PropertyFetch $propertyFetch, - ClassReflection $classReflection, - string $propertyName - ): array { - if (! $classReflection->hasNativeMethod(self::SET_METHOD_NAME)) { - return []; - } - - $setterMethodName = 'set' . \ucfirst($propertyName); - if (! $this->publicClassReflectionAnalyzer->hasPublicNativeMethod($classReflection, $setterMethodName)) { - return []; - } - - $errorMessage = $this->createErrorMessage($propertyFetch, $propertyName, $setterMethodName); - return [$errorMessage]; - } - - /** - * @return string[] - */ - private function processGetterMethodCall( - PropertyFetch $propertyFetch, - ClassReflection $classReflection, - string $propertyName - ): array { - if (! $classReflection->hasNativeMethod(self::GET_METHOD_NAME)) { - return []; - } - - $getterMethodName = 'get' . \ucfirst($propertyName); - $isserMethodName = 'is' . \ucfirst($propertyName); - - $possibleMethodNames = [$getterMethodName, $isserMethodName]; - - foreach ($possibleMethodNames as $possibleMethodName) { - if (! $this->publicClassReflectionAnalyzer->hasPublicNativeMethod($classReflection, $possibleMethodName)) { - continue; - } - - $errorMessage = $this->createErrorMessage($propertyFetch, $propertyName, $possibleMethodName); - return [$errorMessage]; - } - - return []; - } - - private function createErrorMessage(PropertyFetch $propertyFetch, string $propertyName, string $methodName): string - { - $printedPropertyFetch = (string) $propertyFetch->var->getAttribute(AttributeKey::PHPSTAN_CACHE_PRINTER); - return \sprintf(self::ERROR_MESSAGE, $propertyName, $printedPropertyFetch, $methodName); - } - - private function isVariableThis(Expr $expr): bool - { - if (! $expr instanceof Variable) { - return false; - } - - if (! is_string($expr->name)) { - return false; - } - - return $expr->name === 'this'; - } -} diff --git a/src/Rules/Explicit/NoDuplicatedVariableCasingNameRule.php b/src/Rules/Explicit/NoDuplicatedVariableCasingNameRule.php deleted file mode 100644 index 7951a73f..00000000 --- a/src/Rules/Explicit/NoDuplicatedVariableCasingNameRule.php +++ /dev/null @@ -1,120 +0,0 @@ - - */ - public function getNodeType(): string - { - return CollectedDataNode::class; - } - - /** - * @param CollectedDataNode $node - * @return RuleError[] - */ - public function processNode(Node $node, Scope $scope): array - { - $variableNamesGroups = $node->get(VariableNameCollector::class); - - $variableMetadataByVariableNames = []; - $ruleErrors = []; - - foreach ($variableNamesGroups as $filePath => $variableNameGroups) { - foreach ($variableNameGroups as [$variableName, $line]) { - // keep only unique names - /** @var string $variableName */ - $variableMetadataByVariableNames[$variableName] = new VariableNameMetadata( - $variableName, - $filePath, - $line - ); - } - } - - $variableMetadataByVariableLowercasedName = []; - foreach ($variableMetadataByVariableNames as $variableName => $variableMetadata) { - $variableMetadataByVariableLowercasedName[strtolower($variableName)][] = $variableMetadata; - } - - foreach ($variableMetadataByVariableLowercasedName as $lowercasedName => $variableNameMetadatas) { - if (count($variableNameMetadatas) === 1) { - continue; - } - - /** @var VariableNameMetadata $variableNameMetadata */ - foreach ($variableNameMetadatas as $variableNameMetadata) { - $errorMessage = sprintf(self::ERROR_MESSAGE, $lowercasedName, $variableNameMetadata->getVariableName()); - $ruleErrors[] = RuleErrorBuilder::message($errorMessage) - ->file($variableNameMetadata->getFilePath()) - ->line($variableNameMetadata->getLineNumber()) - ->build(); - } - } - - return $ruleErrors; - } -} diff --git a/src/Rules/Explicit/NoGetterAndPropertyRule.php b/src/Rules/Explicit/NoGetterAndPropertyRule.php deleted file mode 100644 index b1225052..00000000 --- a/src/Rules/Explicit/NoGetterAndPropertyRule.php +++ /dev/null @@ -1,126 +0,0 @@ -name; - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -final class SomeProduct -{ - private $name; - - public function getName(): string - { - return $this->name; - } -} -CODE_SAMPLE - ), - ]); - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classLike = $node->getOriginalNode(); - - $errors = []; - - $publicPropertyNames = $this->resolvePublicPropertyNames($classLike); - $publicMethodNames = $this->resolvePublicMethodNames($classLike); - - foreach ($publicPropertyNames as $publicPropertyName) { - $getterMethodName = 'get' . ucfirst($publicPropertyName); - $isserMethodName = 'is' . ucfirst($publicPropertyName); - - if (! array_intersect([$getterMethodName, $isserMethodName], $publicMethodNames)) { - continue; - } - - $errors[] = sprintf(self::ERROR_MESSAGE, $publicPropertyName); - } - - return $errors; - } - - /** - * @return string[] - */ - private function resolvePublicPropertyNames(ClassLike $classLike): array - { - $propertyNames = []; - foreach ($classLike->getProperties() as $property) { - if (! $property->isPublic()) { - continue; - } - - $propertyProperty = $property->props[0]; - $propertyNames[] = $propertyProperty->name->toString(); - } - - return $propertyNames; - } - - /** - * @return string[] - */ - private function resolvePublicMethodNames(ClassLike $classLike): array - { - $methodNames = []; - foreach ($classLike->getMethods() as $classMethod) { - if (! $classMethod->isPublic()) { - continue; - } - - $methodNames[] = $classMethod->name->toString(); - } - - return $methodNames; - } -} diff --git a/src/Rules/Explicit/NoMissingArrayShapeReturnArrayRule.php b/src/Rules/Explicit/NoMissingArrayShapeReturnArrayRule.php deleted file mode 100644 index 115edd64..00000000 --- a/src/Rules/Explicit/NoMissingArrayShapeReturnArrayRule.php +++ /dev/null @@ -1,139 +0,0 @@ - - */ -final class NoMissingArrayShapeReturnArrayRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'Complete known array shape to the method @return type'; - /** - * @var \PhpParser\NodeFinder - */ - private $nodeFinder; - /** - * @var \Symplify\PHPStanRules\TypeResolver\ClassMethodReturnTypeResolver - */ - private $classMethodReturnTypeResolver; - /** - * @var \Symplify\PHPStanRules\TypeAnalyzer\ArrayShapeDetector - */ - private $arrayShapeDetector; - - public function __construct(NodeFinder $nodeFinder, ClassMethodReturnTypeResolver $classMethodReturnTypeResolver, ArrayShapeDetector $arrayShapeDetector) - { - $this->nodeFinder = $nodeFinder; - $this->classMethodReturnTypeResolver = $classMethodReturnTypeResolver; - $this->arrayShapeDetector = $arrayShapeDetector; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return ClassMethod::class; - } - - /** - * @param ClassMethod $node - * @return mixed[] - */ - public function processNode(Node $node, Scope $scope): array - { - $errorMessages = []; - - /** @var Return_[] $returns */ - $returns = $this->nodeFinder->findInstanceOf($node, Return_::class); - - foreach ($returns as $return) { - if (! $return->expr instanceof Expr) { - continue; - } - - if (! $this->arrayShapeDetector->isTypeArrayShapeCandidate($return->expr, $scope)) { - continue; - } - - // skip event subscriber static method - if ($node->name->toString() === 'getSubscribedEvents') { - return []; - } - - if ($this->hasClassMethodReturnConstantArrayType($node, $scope)) { - continue; - } - - $errorMessages[] = RuleErrorBuilder::message(self::ERROR_MESSAGE) - ->line($return->getLine()) - ->build(); - } - - return $errorMessages; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -function run(string $name) -{ - return ['name' => $name]; -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -/** - * @return array{name: string} - */ -function run(string $name) -{ - return ['name' => $name]; -} -CODE_SAMPLE - ), - ]); - } - - private function hasClassMethodReturnConstantArrayType(ClassMethod $classMethod, Scope $scope): bool - { - $classMethodReturnType = $this->classMethodReturnTypeResolver->resolve($classMethod, $scope); - if ($classMethodReturnType instanceof ConstantArrayType) { - return true; - } - - if ($classMethodReturnType instanceof UnionType) { - foreach ($classMethodReturnType->getTypes() as $unionedType) { - if ($unionedType instanceof ConstantArrayType) { - return true; - } - } - } - - return false; - } -} diff --git a/src/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule.php b/src/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule.php deleted file mode 100644 index ea701e72..00000000 --- a/src/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule.php +++ /dev/null @@ -1,163 +0,0 @@ - - */ -final class NoMissingAssingNoVoidMethodCallRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'Method call return value that should be used, but is not'; - - /** - * @var string[] - */ - private const SKIPPED_TYPES = [ - 'Symfony\Component\Finder\Finder', - 'PhpParser\NodeTraverser', - 'Symfony\Component\DependencyInjection\Loader\Configurator\AbstractConfigurator', - 'Symfony\Component\Routing\Loader\Configurator\ImportConfigurator', - 'Nette\Neon\Traverser', - 'PHP_CodeSniffer\Fixer', - 'PhpCsFixer\Tokenizer\Tokens', - 'Latte\Engine', - 'React\Promise\Promise', - 'React\Promise\PromiseInterface', - ]; - /** - * @var \Symplify\PHPStanRules\NodeAnalyzer\MethodCall\AllowedChainCallSkipper - */ - private $allowedChainCallSkipper; - public function __construct(AllowedChainCallSkipper $allowedChainCallSkipper) - { - $this->allowedChainCallSkipper = $allowedChainCallSkipper; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return Expression::class; - } - - /** - * @param Expression $node - * @return mixed[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! $node->expr instanceof MethodCall) { - return []; - } - - $methodCall = $node->expr; - $methodCallReturnType = $scope->getType($methodCall); - - if ($this->isVoidishType($methodCallReturnType)) { - return []; - } - - if ($this->isFluentMethodCall($methodCallReturnType, $scope, $methodCall)) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -class SomeClass -{ - public function run() - { - $this->getResult(); - } - - private function getResult() - { - return []; - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -final class SomeClass -{ - public function run() - { - return $this->getResult(); - } - - private function getResult() - { - return []; - } -} -CODE_SAMPLE - ), - ]); - } - - private function isFluentMethodCall(Type $methodCallReturnType, Scope $scope, MethodCall $methodCall): bool - { - if ($this->allowedChainCallSkipper->isAllowedFluentMethodCall($scope, $methodCall, self::SKIPPED_TYPES)) { - return true; - } - - // 2. filter skipped call return types - if ($methodCallReturnType instanceof ThisType) { - $methodCallReturnType = $methodCallReturnType->getStaticObjectType(); - } - - $currentClassReflection = $scope->getClassReflection(); - - if ($methodCallReturnType instanceof ObjectType) { - // 3. skip self static call - return $currentClassReflection instanceof ClassReflection && $currentClassReflection->getName() === $methodCallReturnType->getClassName(); - } - - $callerType = $scope->getType($methodCall->var); - return $callerType->equals($methodCallReturnType); - } - - private function isVoidishType(Type $type): bool - { - if ($type instanceof VoidType) { - return true; - } - - if ($type instanceof NeverType) { - return true; - } - - return $type instanceof MixedType; - } -} diff --git a/src/Rules/Explicit/NoMixedArrayDimFetchRule.php b/src/Rules/Explicit/NoMixedArrayDimFetchRule.php deleted file mode 100644 index 03874a44..00000000 --- a/src/Rules/Explicit/NoMixedArrayDimFetchRule.php +++ /dev/null @@ -1,173 +0,0 @@ - should be defined there. - * - * @see \Symplify\PHPStanRules\Tests\Rules\Explicit\NoMixedArrayDimFetchRule\NoMixedArrayDimFetchRuleTest - */ -final class NoMixedArrayDimFetchRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'Add explicit array type to assigned "%s" expression'; - - /** - * @var \PhpParser\PrettyPrinter\Standard - */ - private $printerStandard; - - public function __construct() - { - $this->printerStandard = new Standard(); - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return Assign::class; - } - - /** - * @param Assign $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! $node->var instanceof ArrayDimFetch) { - return []; - } - - $arrayDimFetch = $node->var; - - // only check for exact dim values - if ($arrayDimFetch->dim === null) { - return []; - } - - if (! $arrayDimFetch->var instanceof PropertyFetch && ! $arrayDimFetch->var instanceof Variable) { - return []; - } - - if ($this->isExternalClass($arrayDimFetch, $scope)) { - return []; - } - - $rootDimFetchType = $scope->getType($arrayDimFetch->var); - - // skip complex types for now - if ($this->shouldSkipRootDimFetchType($rootDimFetchType)) { - return []; - } - - $printedVariable = $this->printerStandard->prettyPrintExpr($arrayDimFetch->var); - - return [sprintf(self::ERROR_MESSAGE, $printedVariable)]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [new CodeSample( - <<<'CODE_SAMPLE' -class SomeClass -{ - private $items = []; - - public function addItem(string $key, string $value) - { - $this->items[$key] = $value; - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -class SomeClass -{ - /** - * @var array - */ - private $items = []; - - public function addItem(string $key, string $value) - { - $this->items[$key] = $value; - } -} -CODE_SAMPLE - ), - ]); - } - - private function shouldSkipRootDimFetchType(Type $type): bool - { - if ($type instanceof UnionType) { - return true; - } - - if ($type instanceof IntersectionType) { - return true; - } - - if ($type instanceof StringType) { - return true; - } - - return $type instanceof ArrayType && ! $type->getKeyType() instanceof MixedType; - } - - private function isExternalClass(ArrayDimFetch $arrayDimFetch, Scope $scope): bool - { - if (! $arrayDimFetch->var instanceof PropertyFetch) { - return false; - } - - $propertyFetch = $arrayDimFetch->var; - - $propertyFetcherType = $scope->getType($propertyFetch->var); - if (! $propertyFetcherType instanceof ObjectType) { - return false; - } - - $classReflection = $propertyFetcherType->getClassReflection(); - if (! $classReflection instanceof ClassReflection) { - return true; - } - - if ($classReflection->isInternal()) { - return true; - } - - $fileName = $classReflection->getFileName(); - if ($fileName === null) { - return false; - } - - return strpos($fileName, '/vendor/') !== false; - } -} diff --git a/src/Rules/Explicit/NoMixedCallableRule.php b/src/Rules/Explicit/NoMixedCallableRule.php deleted file mode 100644 index 9398b003..00000000 --- a/src/Rules/Explicit/NoMixedCallableRule.php +++ /dev/null @@ -1,105 +0,0 @@ -classMethodReturnTypeResolver = $classMethodReturnTypeResolver; - } - - /** - * @return array> - */ - public function getNodeTypes(): array - { - return [Variable::class, ClassMethod::class]; - } - - /** - * @param Variable|ClassMethod $node - * @return string[] - */ - public function process(Node $node, Scope $scope): array - { - if ($node instanceof ClassMethod) { - $elementType = $this->classMethodReturnTypeResolver->resolve($node, $scope); - } else { - $elementType = $scope->getType($node); - } - - $ruleErrors = []; - - TypeTraverser::map($elementType, static function (Type $type, callable $callable) use (&$ruleErrors): Type { - if (! $type instanceof CallableType) { - return $callable($type, $callable); - } - - // some params are defined, good - if ($type->getParameters() !== []) { - return $callable($type, $callable); - } - - if (! $type->getReturnType() instanceof MixedType) { - return $callable($type, $callable); - } - - $ruleErrors[] = self::ERROR_MESSAGE; - return $callable($type, $callable); - }); - - return $ruleErrors; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition( - self::ERROR_MESSAGE, - [new CodeSample( - <<<'CODE_SAMPLE' -function run(callable $callable) -{ - return $callable(100); -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -/** - * @param callable(): int $callable - */ -function run(callable $callable): int -{ - return $callable(100); -} -CODE_SAMPLE - )] - ); - } -} diff --git a/src/Rules/Explicit/NoMixedMethodCallerRule.php b/src/Rules/Explicit/NoMixedMethodCallerRule.php deleted file mode 100644 index 64027ad4..00000000 --- a/src/Rules/Explicit/NoMixedMethodCallerRule.php +++ /dev/null @@ -1,84 +0,0 @@ -...()` method call can lead to false dead methods. Make sure the variable type is known'; - /** - * @var \PhpParser\PrettyPrinter\Standard - */ - private $printerStandard; - public function __construct(Standard $printerStandard) - { - $this->printerStandard = $printerStandard; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return MethodCall::class; - } - - /** - * @param MethodCall $node - * @return mixed[] - */ - public function processNode(Node $node, Scope $scope): array - { - $callerType = $scope->getType($node->var); - if (! $callerType instanceof MixedType) { - return []; - } - - if ($callerType instanceof ErrorType) { - return []; - } - - $printedMethodCall = $this->printerStandard->prettyPrintExpr($node->var); - - return [sprintf(self::ERROR_MESSAGE, $printedMethodCall)]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -function run($unknownType) -{ - return $unknownType->call(); -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -function run(KnownType $knownType) -{ - return $knownType->call(); -} -CODE_SAMPLE - ), - ]); - } -} diff --git a/src/Rules/Explicit/NoRelativeFilePathRule.php b/src/Rules/Explicit/NoRelativeFilePathRule.php deleted file mode 100644 index d2771c98..00000000 --- a/src/Rules/Explicit/NoRelativeFilePathRule.php +++ /dev/null @@ -1,140 +0,0 @@ - - */ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return RuleError[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classLike = $node->getOriginalNode(); - $strings = $this->findBareStrings($classLike); - - $errorMessages = []; - - foreach ($strings as $string) { - // is it a file string? - if (! $this->isFileString($string)) { - continue; - } - - $errorMessage = sprintf(self::ERROR_MESSAGE, $string->value); - - $errorMessages[] = RuleErrorBuilder::message($errorMessage) - ->line($string->getLine()) - ->build(); - } - - return $errorMessages; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -$filePath = 'some_file.txt'; -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -$filePath = __DIR__ . '/some_file.txt'; -CODE_SAMPLE - ), - ]); - } - - /** - * @return String_[] - */ - private function findBareStrings(ClassLike $classLike): array - { - // mimics node finding visitors of NodeFinder with ability to stop traversing deeper - $nodeTraverser = new NodeTraverser(); - - $stringOutsideConcatFindingNodeVisitor = new StringOutsideConcatFindingNodeVisitor( - new FileCheckingFuncCallAnalyzer() - ); - - $nodeTraverser->addVisitor($stringOutsideConcatFindingNodeVisitor); - $nodeTraverser->traverse($classLike->stmts); - - return $stringOutsideConcatFindingNodeVisitor->getFoundNodes(); - } - - private function isFileString(String_ $string): bool - { - // probably an url - if (Strings::match($string->value, self::URL_START_REGEX)) { - return false; - } - - $pathInfo = pathinfo($string->value); - if (! isset($pathInfo['extension'])) { - return false; - } - - $fileExtension = $pathInfo['extension']; - - if (strlen($fileExtension) > 3) { - return false; - } - - if (strlen($fileExtension) < 3) { - return false; - } - - if ($pathInfo['filename'] === '') { - return false; - } - - if (strpos($pathInfo['filename'], '*') !== false) { - return false; - } - - // only letters - return ctype_alpha($fileExtension); - } -} diff --git a/src/Rules/Explicit/ParamTypeDeclarationSeaLevelRule.php b/src/Rules/Explicit/ParamTypeDeclarationSeaLevelRule.php deleted file mode 100644 index 4fe95cee..00000000 --- a/src/Rules/Explicit/ParamTypeDeclarationSeaLevelRule.php +++ /dev/null @@ -1,119 +0,0 @@ - - */ -final class ParamTypeDeclarationSeaLevelRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'Out of %d possible param types, only %d %% actually have it. Add more param types to get over %d %%'; - /** - * @var \Symplify\PHPStanRules\Formatter\SeaLevelRuleErrorFormatter - */ - private $seaLevelRuleErrorFormatter; - /** - * @var float - */ - private $minimalLevel = 0.80; - /** - * @var bool - */ - private $printSuggestions = true; - - public function __construct(SeaLevelRuleErrorFormatter $seaLevelRuleErrorFormatter, float $minimalLevel = 0.80, bool $printSuggestions = true) - { - $this->seaLevelRuleErrorFormatter = $seaLevelRuleErrorFormatter; - $this->minimalLevel = $minimalLevel; - $this->printSuggestions = $printSuggestions; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return CollectedDataNode::class; - } - - /** - * @param CollectedDataNode $node - * @return mixed[] - */ - public function processNode(Node $node, Scope $scope): array - { - $paramSeaLevelDataByFilePath = $node->get(ParamTypeSeaLevelCollector::class); - - $typedParamCount = 0; - $paramCount = 0; - - $printedClassMethods = []; - - foreach ($paramSeaLevelDataByFilePath as $paramSeaLevelData) { - foreach ($paramSeaLevelData as $nestedParamSeaLevelData) { - $typedParamCount += $nestedParamSeaLevelData[0]; - $paramCount += $nestedParamSeaLevelData[1]; - - if (! $this->printSuggestions) { - continue; - } - - /** @var string $printedClassMethod */ - $printedClassMethod = $nestedParamSeaLevelData[2]; - if ($printedClassMethod !== '') { - $printedClassMethods[] = trim($printedClassMethod); - } - } - } - - return $this->seaLevelRuleErrorFormatter->formatErrors( - self::ERROR_MESSAGE, - $this->minimalLevel, - $paramCount, - $typedParamCount, - $printedClassMethods - ); - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -final class SomeClass -{ - public function run($name, $age) - { - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -final class SomeClass -{ - public function run(string $name, int $age) - { - } -} -CODE_SAMPLE - ), - ]); - } -} diff --git a/src/Rules/Explicit/PropertyTypeDeclarationSeaLevelRule.php b/src/Rules/Explicit/PropertyTypeDeclarationSeaLevelRule.php deleted file mode 100644 index 4ec8724a..00000000 --- a/src/Rules/Explicit/PropertyTypeDeclarationSeaLevelRule.php +++ /dev/null @@ -1,115 +0,0 @@ - - */ -final class PropertyTypeDeclarationSeaLevelRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'Out of %d possible property types, only %d %% actually have it. Add more property types to get over %d %%'; - /** - * @var \Symplify\PHPStanRules\Formatter\SeaLevelRuleErrorFormatter - */ - private $seaLevelRuleErrorFormatter; - /** - * @var float - */ - private $minimalLevel = 0.80; - /** - * @var bool - */ - private $printSuggestions = true; - - public function __construct(SeaLevelRuleErrorFormatter $seaLevelRuleErrorFormatter, float $minimalLevel = 0.80, bool $printSuggestions = true) - { - $this->seaLevelRuleErrorFormatter = $seaLevelRuleErrorFormatter; - $this->minimalLevel = $minimalLevel; - $this->printSuggestions = $printSuggestions; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return CollectedDataNode::class; - } - - /** - * @param CollectedDataNode $node - * @return mixed[] - */ - public function processNode(Node $node, Scope $scope): array - { - $propertySeaLevelDataByFilePath = $node->get(PropertyTypeSeaLevelCollector::class); - - $typedPropertyCount = 0; - $propertyCount = 0; - - $printedUntypedPropertiesContents = []; - - foreach ($propertySeaLevelDataByFilePath as $propertySeaLevelData) { - foreach ($propertySeaLevelData as $nestedPropertySeaLevelData) { - $typedPropertyCount += $nestedPropertySeaLevelData[0]; - $propertyCount += $nestedPropertySeaLevelData[1]; - - if (! $this->printSuggestions) { - continue; - } - - /** @var string $printedPropertyContent */ - $printedPropertyContent = $nestedPropertySeaLevelData[2]; - if ($printedPropertyContent !== '') { - $printedUntypedPropertiesContents[] = trim($printedPropertyContent); - } - } - } - - return $this->seaLevelRuleErrorFormatter->formatErrors( - self::ERROR_MESSAGE, - $this->minimalLevel, - $propertyCount, - $typedPropertyCount, - $printedUntypedPropertiesContents - ); - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -final class SomeClass -{ - public $name; -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -final class SomeClass -{ - public string $name; -} -CODE_SAMPLE - ), - ]); - } -} diff --git a/src/Rules/Explicit/ReturnTypeDeclarationSeaLevelRule.php b/src/Rules/Explicit/ReturnTypeDeclarationSeaLevelRule.php deleted file mode 100644 index 90957fe5..00000000 --- a/src/Rules/Explicit/ReturnTypeDeclarationSeaLevelRule.php +++ /dev/null @@ -1,119 +0,0 @@ - - */ -final class ReturnTypeDeclarationSeaLevelRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'Out of %d possible return types, only %d %% actually have it. Add more return types to get over %d %%'; - /** - * @var \Symplify\PHPStanRules\Formatter\SeaLevelRuleErrorFormatter - */ - private $seaLevelRuleErrorFormatter; - /** - * @var float - */ - private $minimalLevel = 0.80; - /** - * @var bool - */ - private $printSuggestions = true; - - public function __construct(SeaLevelRuleErrorFormatter $seaLevelRuleErrorFormatter, float $minimalLevel = 0.80, bool $printSuggestions = true) - { - $this->seaLevelRuleErrorFormatter = $seaLevelRuleErrorFormatter; - $this->minimalLevel = $minimalLevel; - $this->printSuggestions = $printSuggestions; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return CollectedDataNode::class; - } - - /** - * @param CollectedDataNode $node - * @return mixed[] - */ - public function processNode(Node $node, Scope $scope): array - { - $returnSeaLevelDataByFilePath = $node->get(ReturnTypeSeaLevelCollector::class); - - $typedReturnCount = 0; - $returnCount = 0; - - $printedClassMethods = []; - - foreach ($returnSeaLevelDataByFilePath as $returnSeaLevelData) { - foreach ($returnSeaLevelData as $nestedReturnSeaLevelData) { - $typedReturnCount += $nestedReturnSeaLevelData[0]; - $returnCount += $nestedReturnSeaLevelData[1]; - - if (! $this->printSuggestions) { - continue; - } - - /** @var string $printedClassMethod */ - $printedClassMethod = $nestedReturnSeaLevelData[2]; - if ($printedClassMethod !== '') { - $printedClassMethods[] = trim($printedClassMethod); - } - } - } - - return $this->seaLevelRuleErrorFormatter->formatErrors( - self::ERROR_MESSAGE, - $this->minimalLevel, - $returnCount, - $typedReturnCount, - $printedClassMethods - ); - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -final class SomeClass -{ - public function run() - { - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -final class SomeClass -{ - public function run(): void - { - } -} -CODE_SAMPLE - ), - ]); - } -} diff --git a/src/Rules/Explicit/ValueObjectOverArrayShapeRule.php b/src/Rules/Explicit/ValueObjectOverArrayShapeRule.php deleted file mode 100644 index 2c33bdb4..00000000 --- a/src/Rules/Explicit/ValueObjectOverArrayShapeRule.php +++ /dev/null @@ -1,149 +0,0 @@ - 100]; -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -function createConfiguration() -{ - return new Configuration(100); -} - -final class Configuration -{ - public function __construct( - private int $line - ) { - } - - public function getLine(): int - { - return $this->line; - } -} -CODE_SAMPLE - ), - ]); - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return FunctionLike::class; - } - - /** - * @param FunctionLike $node - * @return mixed[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! $node instanceof ClassMethod && ! $node instanceof Function_) { - return []; - } - - $docComment = $node->getDocComment(); - if (! $docComment instanceof Doc) { - return []; - } - - if ($this->isIteratorReturnType($node)) { - return []; - } - - $match = Strings::match($docComment->getText(), self::ARRAY_SHAPE_REGEX); - if ($match === null) { - return []; - } - - // constructor is allowed, as API entrance - if ($node instanceof ClassMethod && $node->isMagic()) { - return []; - } - - if ($this->isSerializableObject($scope)) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - private function isSerializableObject(Scope $scope): bool - { - $classReflection = $scope->getClassReflection(); - if (! $classReflection instanceof ClassReflection) { - return false; - } - - if ($classReflection->implementsInterface(Serializable::class)) { - return true; - } - - return $classReflection->implementsInterface(JsonSerializable::class); - } - - /** - * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_ $node - */ - private function isIteratorReturnType($node): bool - { - $returnType = $node->returnType; - if (! $returnType instanceof FullyQualified) { - return false; - } - - $returnTypeClass = $returnType->toString(); - return $returnTypeClass === Iterator::class; - } -} diff --git a/src/Rules/ForbiddenAnonymousClassRule.php b/src/Rules/ForbiddenAnonymousClassRule.php deleted file mode 100644 index 6b187287..00000000 --- a/src/Rules/ForbiddenAnonymousClassRule.php +++ /dev/null @@ -1,66 +0,0 @@ - - */ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classReflection = $node->getClassReflection(); - if (! $classReflection->isAnonymous()) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -new class {}; -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -class SomeClass -{ - -} - -new SomeClass; -CODE_SAMPLE - ), - ]); - } -} diff --git a/src/Rules/ForbiddenArrayDestructRule.php b/src/Rules/ForbiddenArrayDestructRule.php deleted file mode 100644 index 27a37705..00000000 --- a/src/Rules/ForbiddenArrayDestructRule.php +++ /dev/null @@ -1,152 +0,0 @@ -reflectionProvider = $reflectionProvider; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return Assign::class; - } - - /** - * @param Assign $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! $node->var instanceof Array_) { - return []; - } - - // swaps are allowed - if ($node->expr instanceof Array_) { - return []; - } - - if ($this->isAllowedCall($node)) { - return []; - } - - // is 3rd party method call → nothing we can do about it - if ($this->isVendorProvider($node, $scope)) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -final class SomeClass -{ - public function run(): void - { - [$firstValue, $secondValue] = $this->getRandomData(); - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -final class SomeClass -{ - public function run(): void - { - $valueObject = $this->getValueObject(); - $firstValue = $valueObject->getFirstValue(); - $secondValue = $valueObject->getSecondValue(); - } -} -CODE_SAMPLE - ), - ]); - } - - private function isAllowedCall(Assign $assign): bool - { - // "explode()" is allowed - if ($assign->expr instanceof FuncCall && $assign->expr->name instanceof Name && $assign->expr->name->toString() === 'explode') { - return true; - } - - // Strings::split() is allowed - if (! $assign->expr instanceof StaticCall) { - return false; - } - - $staticCall = $assign->expr; - if (! $staticCall->name instanceof Identifier) { - return false; - } - - return $staticCall->name->toString() === 'split'; - } - - private function isVendorProvider(Assign $assign, Scope $scope): bool - { - if (! $assign->expr instanceof MethodCall) { - return false; - } - - $callerType = $scope->getType($assign->expr->var); - if (! $callerType instanceof ObjectType) { - return false; - } - - $classReflection = $this->reflectionProvider->getClass($callerType->getClassName()); - $fileName = $classReflection->getFileName(); - if ($fileName === null) { - return true; - } - - return (bool) Strings::match($fileName, self::VENDOR_DIRECTORY_REGEX); - } -} diff --git a/src/Rules/ForbiddenArrayWithStringKeysRule.php b/src/Rules/ForbiddenArrayWithStringKeysRule.php deleted file mode 100644 index 357463e4..00000000 --- a/src/Rules/ForbiddenArrayWithStringKeysRule.php +++ /dev/null @@ -1,160 +0,0 @@ - - */ -final class ForbiddenArrayWithStringKeysRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'Array with keys is not allowed. Use value object to pass data instead'; - - /** - * @var string - * @see https://regex101.com/r/ddj4mB/2 - */ - private const TEST_FILE_REGEX = '#(Test|TestCase)\.php$#'; - /** - * @var \Symplify\PHPStanRules\ParentGuard\ParentElementResolver\ParentMethodReturnTypeResolver - */ - private $parentMethodReturnTypeResolver; - /** - * @var \Symplify\PHPStanRules\NodeAnalyzer\ArrayAnalyzer - */ - private $arrayAnalyzer; - public function __construct(ParentMethodReturnTypeResolver $parentMethodReturnTypeResolver, ArrayAnalyzer $arrayAnalyzer) - { - $this->parentMethodReturnTypeResolver = $parentMethodReturnTypeResolver; - $this->arrayAnalyzer = $arrayAnalyzer; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return Return_::class; - } - - /** - * @param Return_ $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! $node->expr instanceof Array_) { - return []; - } - - if ($this->shouldSkip($scope)) { - return []; - } - - if (! $this->arrayAnalyzer->isArrayWithStringKey($node->expr)) { - return []; - } - - // is return array required by parent - $parentMethodReturnType = $this->parentMethodReturnTypeResolver->resolve($scope); - if ($parentMethodReturnType instanceof ArrayType) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -final class SomeClass -{ - public function run() - { - return [ - 'name' => 'John', - 'surname' => 'Dope', - ]; - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -final class SomeClass -{ - public function run() - { - return new Person('John', 'Dope'); - } -} -CODE_SAMPLE - ), - ]); - } - - private function shouldSkip(Scope $scope): bool - { - if ($this->shouldSkipClass($scope)) { - return true; - } - - if (Strings::match($scope->getFile(), self::TEST_FILE_REGEX)) { - return true; - } - - // skip examples in Rector::getDefinition() method - return in_array($scope->getFunctionName(), ['getDefinition', MethodName::CONSTRUCTOR], true); - } - - private function shouldSkipClass(Scope $scope): bool - { - $classReflection = $scope->getClassReflection(); - if ($classReflection instanceof ClassReflection) { - if ($classReflection->isSubclassOf(JsonSerializable::class)) { - return true; - } - - if (strpos($classReflection->getName(), 'json') !== false) { - return true; - } - - if (strpos($classReflection->getName(), 'Json') !== false) { - return true; - } - } - - $filePath = $scope->getFile(); - - // php-scoper config, it return magic array by design - if (strpos($filePath, 'scoper') !== false) { - return true; - } - - // skip Symfony bundles.php - return substr_compare($filePath, 'bundles.php', -strlen('bundles.php')) === 0; - } -} diff --git a/src/Rules/ForbiddenExtendOfNonAbstractClassRule.php b/src/Rules/ForbiddenExtendOfNonAbstractClassRule.php deleted file mode 100644 index 63452abb..00000000 --- a/src/Rules/ForbiddenExtendOfNonAbstractClassRule.php +++ /dev/null @@ -1,91 +0,0 @@ - - */ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classReflection = $node->getClassReflection(); - - $parentClassReflection = $classReflection->getParentClass(); - if (! $parentClassReflection instanceof ClassReflection) { - return []; - } - - if ($parentClassReflection->isAbstract()) { - return []; - } - - // skip native PHP classes - if ($parentClassReflection->isBuiltin()) { - return []; - } - - // skip vendor based classes, as designed for extension - $fileName = $parentClassReflection->getFileName(); - if (is_string($fileName) && strpos($fileName, 'vendor') !== false) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -final class SomeClass extends ParentClass -{ -} - -class ParentClass -{ -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -final class SomeClass extends ParentClass -{ -} - -abstract class ParentClass -{ -} -CODE_SAMPLE - ), - ]); - } -} diff --git a/src/Rules/ForbiddenFuncCallRule.php b/src/Rules/ForbiddenFuncCallRule.php deleted file mode 100644 index 05da8ee3..00000000 --- a/src/Rules/ForbiddenFuncCallRule.php +++ /dev/null @@ -1,159 +0,0 @@ - - */ - private $forbiddenFunctions; - /** - * @var \Symplify\PHPStanRules\Matcher\ArrayStringAndFnMatcher - */ - private $arrayStringAndFnMatcher; - /** - * @var \Symplify\PHPStanRules\Formatter\RequiredWithMessageFormatter - */ - private $requiredWithMessageFormatter; - /** - * @param string[]|array $forbiddenFunctions - */ - public function __construct(array $forbiddenFunctions, ArrayStringAndFnMatcher $arrayStringAndFnMatcher, RequiredWithMessageFormatter $requiredWithMessageFormatter) - { - $this->forbiddenFunctions = $forbiddenFunctions; - $this->arrayStringAndFnMatcher = $arrayStringAndFnMatcher; - $this->requiredWithMessageFormatter = $requiredWithMessageFormatter; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return FuncCall::class; - } - - /** - * @param FuncCall $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! $node->name instanceof Name) { - return []; - } - - $funcName = $node->name->toString(); - - $requiredWithMessages = $this->requiredWithMessageFormatter->normalizeConfig($this->forbiddenFunctions); - foreach ($requiredWithMessages as $requiredWithMessage) { - if (! $this->arrayStringAndFnMatcher->isMatch($funcName, [$requiredWithMessage->getRequired()])) { - continue; - } - - // special cases - if ($this->shouldAllowSpecialCase($node, $scope, $funcName)) { - continue; - } - - $errorMessage = $this->createErrorMessage($requiredWithMessage, $funcName); - return [$errorMessage]; - } - - return []; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new ConfiguredCodeSample( - <<<'CODE_SAMPLE' -echo eval('...'); -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -echo '...'; -CODE_SAMPLE - , - [ - 'forbiddenFunctions' => ['eval'], - ] - ), - new ConfiguredCodeSample( - <<<'CODE_SAMPLE' -dump($value); -echo $value; -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -echo $value; -CODE_SAMPLE - , - [ - 'forbiddenFunctions' => [ - 'dump' => 'seems you missed some debugging function', - ], - ] - ), - ]); - } - - private function shouldAllowSpecialCase(FuncCall $funcCall, Scope $scope, string $functionName): bool - { - if ($functionName !== 'property_exists') { - return false; - } - - $argOrVariadicPlaceholder = $funcCall->args[0]; - if (! $argOrVariadicPlaceholder instanceof Arg) { - return false; - } - - $firstArgValue = $argOrVariadicPlaceholder->value; - - $firstArgType = $scope->getType($firstArgValue); - // non nullable - $firstArgType = TypeCombinator::removeNull($firstArgType); - - $simpleXmlElementObjectType = new ObjectType(SimpleXMLElement::class); - - return $simpleXmlElementObjectType->isSuperTypeOf($firstArgType) - ->yes(); - } - - private function createErrorMessage(RequiredWithMessage $requiredWithMessage, string $funcName): string - { - if ($requiredWithMessage->getMessage() === null) { - return sprintf(self::ERROR_MESSAGE, $funcName); - } - - return sprintf(self::ERROR_MESSAGE . ': ' . $requiredWithMessage->getMessage(), $funcName); - } -} diff --git a/src/Rules/ForbiddenMultipleClassLikeInOneFileRule.php b/src/Rules/ForbiddenMultipleClassLikeInOneFileRule.php deleted file mode 100644 index 972af039..00000000 --- a/src/Rules/ForbiddenMultipleClassLikeInOneFileRule.php +++ /dev/null @@ -1,98 +0,0 @@ -nodeFinder = $nodeFinder; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return FileNode::class; - } - - /** - * @param FileNode $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - /** @var ClassLike[] $classLikes */ - $classLikes = $this->nodeFinder->findInstanceOf($node->getNodes(), ClassLike::class); - - $findclassLikes = []; - foreach ($classLikes as $classLike) { - if ($classLike->name === null) { - continue; - } - - $findclassLikes[] = $classLike; - } - - if (count($findclassLikes) <= 1) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -// src/SomeClass.php -class SomeClass -{ -} - -interface SomeInterface -{ -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -// src/SomeClass.php -class SomeClass -{ -} - -// src/SomeInterface.php -interface SomeInterface -{ -} -CODE_SAMPLE - ), - ]); - } -} diff --git a/src/Rules/ForbiddenNestedCallInAssertMethodCallRule.php b/src/Rules/ForbiddenNestedCallInAssertMethodCallRule.php deleted file mode 100644 index 2ee85fdc..00000000 --- a/src/Rules/ForbiddenNestedCallInAssertMethodCallRule.php +++ /dev/null @@ -1,115 +0,0 @@ -nodeFinder = $nodeFinder; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return MethodCall::class; - } - - /** - * @param MethodCall $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! $node->name instanceof Identifier) { - return []; - } - - $methodName = $node->name->toString(); - if ($this->shouldSkipMethodName($methodName, $node)) { - return []; - } - - $argMethodCall = $this->nodeFinder->findFirstInstanceOf($node->getArgs()[1], MethodCall::class); - if (! $argMethodCall instanceof MethodCall) { - return []; - } - - if ($argMethodCall->getArgs() === []) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -use PHPUnit\Framework\TestCase; - -final class SomeClass extends TestCase -{ - public function test() - { - $this->assertSame('oooo', $this->someMethodCall()); - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -use PHPUnit\Framework\TestCase; - -final class SomeClass extends TestCase -{ - public function test() - { - $result = $this->someMethodCall(); - $this->assertSame('oooo', $result); - } -} -CODE_SAMPLE - ), - ]); - } - - private function shouldSkipMethodName(string $methodName, MethodCall $methodCall): bool - { - if (strncmp($methodName, 'assert', strlen('assert')) !== 0) { - return true; - } - - if (in_array($methodName, ['assertTrue', 'assertFalse'], true)) { - return true; - } - - return count($methodCall->args) <= 1; - } -} diff --git a/src/Rules/ForbiddenNodeRule.php b/src/Rules/ForbiddenNodeRule.php deleted file mode 100644 index 84a3959c..00000000 --- a/src/Rules/ForbiddenNodeRule.php +++ /dev/null @@ -1,96 +0,0 @@ - - */ -final class ForbiddenNodeRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = '"%s" is forbidden to use'; - - /** - * @var array> - */ - private $forbiddenNodes = []; - /** - * @var \PhpParser\PrettyPrinter\Standard - */ - private $standard; - - /** - * @param array> $forbiddenNodes - */ - public function __construct( - Standard $standard, - array $forbiddenNodes - ) { - $this->standard = $standard; - Assert::allIsAOf($forbiddenNodes, Node::class); - - $this->forbiddenNodes = $forbiddenNodes; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return Node::class; - } - - /** - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - foreach ($this->forbiddenNodes as $forbiddenNode) { - if (! is_a($node, $forbiddenNode, true)) { - continue; - } - - $name = $this->standard->prettyPrint([$node]); - $errorMessage = sprintf(self::ERROR_MESSAGE, $name); - - return [$errorMessage]; - } - - return []; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new ConfiguredCodeSample( - <<<'CODE_SAMPLE' -return @strlen('...'); -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -return strlen('...'); -CODE_SAMPLE - , - [ - 'forbiddenNodes' => [ErrorSuppress::class], - ] - ), - ]); - } -} diff --git a/src/Rules/ForbiddenParamTypeRemovalRule.php b/src/Rules/ForbiddenParamTypeRemovalRule.php index 4bce3582..5f31a286 100644 --- a/src/Rules/ForbiddenParamTypeRemovalRule.php +++ b/src/Rules/ForbiddenParamTypeRemovalRule.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Rules; +namespace Rector\TypePerfect\Rules; use PhpParser\Node; use PhpParser\Node\Stmt\ClassMethod; @@ -11,13 +11,11 @@ use PHPStan\Rules\Rule; use PHPStan\Type\MixedType; use PHPStan\Type\Type; -use Symplify\PHPStanRules\Reflection\MethodNodeAnalyser; -use Symplify\RuleDocGenerator\Contract\DocumentedRuleInterface; -use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; -use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; +use Rector\TypePerfect\Reflection\MethodNodeAnalyser; /** - * @see \Symplify\PHPStanRules\Tests\Rules\ForbiddenParamTypeRemovalRule\ForbiddenParamTypeRemovalRuleTest + * @see \Rector\TypePerfect\Tests\Rules\ForbiddenParamTypeRemovalRule\ForbiddenParamTypeRemovalRuleTest + * @implements Rule */ final class ForbiddenParamTypeRemovalRule implements Rule { @@ -25,14 +23,10 @@ final class ForbiddenParamTypeRemovalRule implements Rule * @var string */ public const ERROR_MESSAGE = 'Removing parent param type is forbidden'; - /** - * @var \Symplify\PHPStanRules\Reflection\MethodNodeAnalyser - */ - private $methodNodeAnalyser; - public function __construct(MethodNodeAnalyser $methodNodeAnalyser) - { - $this->methodNodeAnalyser = $methodNodeAnalyser; + public function __construct( + private readonly MethodNodeAnalyser $methodNodeAnalyser + ) { } /** @@ -76,41 +70,6 @@ public function processNode(Node $node, Scope $scope): array return []; } - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -interface RectorInterface -{ - public function refactor(Node $node); -} - -final class SomeRector implements RectorInterface -{ - public function refactor($node) - { - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -interface RectorInterface -{ - public function refactor(Node $node); -} - -final class SomeRector implements RectorInterface -{ - public function refactor(Node $node) - { - } -} -CODE_SAMPLE - ), - ]); - } - private function resolveParentParamType(PhpMethodReflection $phpMethodReflection, int $paramPosition): Type { foreach ($phpMethodReflection->getVariants() as $parametersAcceptorWithPhpDoc) { diff --git a/src/Rules/ForbiddenProtectedPropertyRule.php b/src/Rules/ForbiddenProtectedPropertyRule.php deleted file mode 100644 index 24bd2f28..00000000 --- a/src/Rules/ForbiddenProtectedPropertyRule.php +++ /dev/null @@ -1,110 +0,0 @@ - - */ -final class ForbiddenProtectedPropertyRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'Property with protected modifier is not allowed. Use interface contract method instead'; - /** - * @var \Symplify\PHPStanRules\NodeAnalyzer\ProtectedAnalyzer - */ - private $protectedAnalyzer; - /** - * @var \Symplify\PHPStanRules\ParentGuard\ParentPropertyGuard - */ - private $parentPropertyGuard; - public function __construct(ProtectedAnalyzer $protectedAnalyzer, ParentPropertyGuard $parentPropertyGuard) - { - $this->protectedAnalyzer = $protectedAnalyzer; - $this->parentPropertyGuard = $parentPropertyGuard; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return RuleError[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classLike = $node->getOriginalNode(); - if (! $classLike instanceof Class_) { - return []; - } - - $errorMessages = []; - - foreach ($classLike->getProperties() as $property) { - if (! $property->isProtected()) { - continue; - } - - if ($this->parentPropertyGuard->isPropertyGuarded($property, $scope)) { - continue; - } - - if ($this->protectedAnalyzer->isProtectedPropertyOrClassConstAllowed($property, $classLike)) { - continue; - } - - $errorMessages[] = RuleErrorBuilder::message(self::ERROR_MESSAGE) - ->line($property->getLine()) - ->build(); - } - - return $errorMessages; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -class SomeClass -{ - protected $repository; -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -class SomeClass implements RepositoryAwareInterface -{ - public function getRepository() - { - // .... - } -} -CODE_SAMPLE - ), - ]); - } -} diff --git a/src/Rules/ForbiddenSpreadOperatorRule.php b/src/Rules/ForbiddenSpreadOperatorRule.php deleted file mode 100644 index b9cc7b82..00000000 --- a/src/Rules/ForbiddenSpreadOperatorRule.php +++ /dev/null @@ -1,110 +0,0 @@ -> - */ - public function getNodeTypes(): array - { - return [ - Closure::class, - ArrowFunction::class, - ClassMethod::class, - Function_::class, - MethodCall::class, - StaticCall::class, - FuncCall::class, - ]; - } - - /** - * @param Closure|ArrowFunction|MethodCall|StaticCall|FuncCall|ClassMethod|Function_ $node - * @return string[] - */ - public function process(Node $node, Scope $scope): array - { - if ($node instanceof FunctionLike) { - if (! $this->hasVariadicParam($node)) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - foreach ($node->args as $key => $arg) { - if (! $arg instanceof Arg) { - continue; - } - - if (! $arg->unpack) { - continue; - } - - if ($key === 0) { - // unpack args on 1st position cannot be skipped - return []; - } - - return [self::ERROR_MESSAGE]; - } - - return []; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -$args = [$firstValue, $secondValue]; -$message = sprintf('%s', ...$args); -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -$message = sprintf('%s', $firstValue, $secondValue); -CODE_SAMPLE - ), - ]); - } - - /** - * @param \PhpParser\Node\Expr\Closure|\PhpParser\Node\Expr\ArrowFunction|\PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_ $node - */ - private function hasVariadicParam($node): bool - { - foreach ($node->params as $param) { - if ($param->variadic) { - return true; - } - } - - return false; - } -} diff --git a/src/Rules/ForbiddenTestsNamespaceOutsideTestsDirectoryRule.php b/src/Rules/ForbiddenTestsNamespaceOutsideTestsDirectoryRule.php deleted file mode 100644 index a1fbd080..00000000 --- a/src/Rules/ForbiddenTestsNamespaceOutsideTestsDirectoryRule.php +++ /dev/null @@ -1,98 +0,0 @@ -directoryChecker = $directoryChecker; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return Namespace_::class; - } - - /** - * @param Namespace_ $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! $node->name instanceof Name) { - return []; - } - - $matches = Strings::match($node->name->toString(), Regex::TESTS_PART_REGEX); - if ($matches === null) { - return []; - } - - if ($this->directoryChecker->isInDirectoryNames($scope, ['tests', 'packages-tests'])) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::DESCRIPTION, [ - new CodeSample( - <<<'CODE_SAMPLE' -// file path: "src/SomeClass.php" - -namespace App\Tests; - -class SomeClass -{ -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -// file path: "tests/SomeClass.php" - -namespace App\Tests; - -class SomeClass -{ -} -CODE_SAMPLE - ), - ]); - } -} diff --git a/src/Rules/ForbiddenThisArgumentRule.php b/src/Rules/ForbiddenThisArgumentRule.php deleted file mode 100644 index f23f6e87..00000000 --- a/src/Rules/ForbiddenThisArgumentRule.php +++ /dev/null @@ -1,133 +0,0 @@ -> - */ - private const ALLOWED_CALLER_CLASSES = [ - // workaround type - 'Symplify\PackageBuilder\Reflection\PrivatesCaller', - ]; - /** - * @var \Symplify\PHPStanRules\TypeAnalyzer\ContainsTypeAnalyser - */ - private $containsTypeAnalyser; - - public function __construct(ContainsTypeAnalyser $containsTypeAnalyser) - { - $this->containsTypeAnalyser = $containsTypeAnalyser; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return CallLike::class; - } - - /** - * @param CallLike $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! $node instanceof MethodCall && ! $node instanceof FuncCall && ! $node instanceof StaticCall) { - return []; - } - - if ($this->shouldSkip($node, $scope)) { - return []; - } - - foreach ($node->getArgs() as $arg) { - $argType = $scope->getType($arg->value); - if (! $argType instanceof ThisType) { - continue; - } - - if ($this->shouldSkipClass($scope)) { - continue; - } - - return [self::ERROR_MESSAGE]; - } - - return []; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -$this->someService->process($this, ...); -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -$this->someService->process($value, ...); -CODE_SAMPLE - ), - ]); - } - - private function shouldSkipClass(Scope $scope): bool - { - $classReflection = $scope->getClassReflection(); - if (! $classReflection instanceof ClassReflection) { - return false; - } - - return $classReflection->isSubclassOf(Kernel::class); - } - - /** - * @param \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\FuncCall|\PhpParser\Node\Expr\StaticCall $node - */ - private function shouldSkip($node, Scope $scope): bool - { - if ($node instanceof MethodCall) { - return $this->containsTypeAnalyser->containsExprTypes($node->var, $scope, self::ALLOWED_CALLER_CLASSES); - } - - if ($node instanceof FuncCall) { - if (! $node->name instanceof Name) { - return false; - } - - return $node->name->toString() === 'method_exists'; - } - - return false; - } -} diff --git a/src/Rules/Missing/CheckSprintfMatchingTypesRule.php b/src/Rules/Missing/CheckSprintfMatchingTypesRule.php deleted file mode 100644 index 349e6b97..00000000 --- a/src/Rules/Missing/CheckSprintfMatchingTypesRule.php +++ /dev/null @@ -1,141 +0,0 @@ -sprintfSpecifierTypeResolver = $sprintfSpecifierTypeResolver; - $this->matchingTypeAnalyzer = $matchingTypeAnalyzer; - $this->argTypeResolver = $argTypeResolver; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return FuncCall::class; - } - - /** - * @param FuncCall $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! $node->name instanceof Name) { - return []; - } - - $funcCallName = $node->name->toString(); - if ($funcCallName !== 'sprintf') { - return []; - } - - $firstArg = $node->getArgs()[0]; - $formatArgType = $scope->getType($firstArg->value); - - if (! $formatArgType instanceof ConstantStringType) { - return []; - } - - $specifiersMatches = $this->resolveSpecifierMatches($formatArgType); - - $argTypes = $this->argTypeResolver->resolveArgTypesWithoutFirst($node, $scope); - $expectedTypesByPosition = $this->sprintfSpecifierTypeResolver->resolveFromSpecifiers($specifiersMatches); - - // miss-matching count, handled by native PHPStan rule - if (count($argTypes) !== count($expectedTypesByPosition)) { - return []; - } - - foreach ($argTypes as $key => $argType) { - $expectedTypes = $expectedTypesByPosition[$key]; - - if ($this->matchingTypeAnalyzer->isTypeMatchingExpectedTypes($argType, $expectedTypes)) { - continue; - } - - return [self::ERROR_MESSAGE]; - } - - return []; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition( - self::ERROR_MESSAGE, - [ - new CodeSample( - <<<'CODE_SAMPLE' -echo sprintf('My name is %s and I have %d children', 10, 'Tomas'); - -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -echo sprintf('My name is %s and I have %d children', 'Tomas', 10); -CODE_SAMPLE - ), - ] - ); - } - - /** - * @see https://github.com/phpstan/phpstan-src/blob/e10a7aac373e8b6f21b430034fc693300c2bbb69/src/Rules/Functions/PrintfParametersRule.php#L105-L115 - * @return string[] - */ - private function resolveSpecifierMatches(ConstantStringType $constantStringType): array - { - $value = $constantStringType->getValue(); - $pattern = '#%(?:(?\d+)\$)?[-+]?(?:[ 0]|(?:\'[^%]))?-?\d*(?:\.\d*)?' . self::SPECIFIERS . '#'; - - $allMatches = Strings::matchAll($value, $pattern); - return Arrays::flatten($allMatches); - } -} diff --git a/src/Rules/CheckTypehintCallerTypeRule.php b/src/Rules/NarrowPrivateClassMethodParamTypeRule.php similarity index 63% rename from src/Rules/CheckTypehintCallerTypeRule.php rename to src/Rules/NarrowPrivateClassMethodParamTypeRule.php index 9ac7274f..6ba107aa 100644 --- a/src/Rules/CheckTypehintCallerTypeRule.php +++ b/src/Rules/NarrowPrivateClassMethodParamTypeRule.php @@ -2,53 +2,46 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Rules; +namespace Rector\TypePerfect\Rules; use PhpParser\Node; use PhpParser\Node\Arg; +use PhpParser\Node\Expr; use PhpParser\Node\Expr\MethodCall; +use PhpParser\Node\Expr\Variable; use PhpParser\Node\Name\FullyQualified; use PhpParser\Node\Param; use PhpParser\Node\Stmt\ClassMethod; use PHPStan\Analyser\Scope; +use PHPStan\Reflection\ClassReflection; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleError; use PHPStan\Rules\RuleErrorBuilder; +use PHPStan\Type\Generic\TemplateType; use PHPStan\Type\IntersectionType; use PHPStan\Type\MixedType; use PHPStan\Type\ObjectType; -use PHPStan\Type\ThisType; use PHPStan\Type\Type; use PHPStan\Type\UnionType; use PHPStan\Type\VerbosityLevel; -use Symplify\PHPStanRules\NodeFinder\ClassMethodNodeFinder; -use Symplify\PHPStanRules\NodeFinder\MethodCallNodeFinder; -use Symplify\RuleDocGenerator\Contract\DocumentedRuleInterface; -use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; -use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; +use Rector\TypePerfect\NodeFinder\ClassMethodNodeFinder; +use Rector\TypePerfect\NodeFinder\MethodCallNodeFinder; /** - * @see \Symplify\PHPStanRules\Tests\Rules\CheckTypehintCallerTypeRule\CheckTypehintCallerTypeRuleTest + * @see \Rector\TypePerfect\Tests\Rules\CheckTypehintCallerTypeRule\CheckTypehintCallerTypeRuleTest + * @implements Rule */ -final class CheckTypehintCallerTypeRule implements Rule +final class NarrowPrivateClassMethodParamTypeRule implements Rule { /** * @var string */ public const ERROR_MESSAGE = 'Parameter %d should use "%s" type as the only type passed to this method'; - /** - * @var \Symplify\PHPStanRules\NodeFinder\MethodCallNodeFinder - */ - private $methodCallNodeFinder; - /** - * @var \Symplify\PHPStanRules\NodeFinder\ClassMethodNodeFinder - */ - private $classMethodNodeFinder; - public function __construct(MethodCallNodeFinder $methodCallNodeFinder, ClassMethodNodeFinder $classMethodNodeFinder) - { - $this->methodCallNodeFinder = $methodCallNodeFinder; - $this->classMethodNodeFinder = $classMethodNodeFinder; + public function __construct( + private readonly MethodCallNodeFinder $methodCallNodeFinder, + private readonly ClassMethodNodeFinder $classMethodNodeFinder + ) { } /** @@ -70,52 +63,19 @@ public function processNode(Node $node, Scope $scope): array return []; } - $type = $scope->getType($node->var); - if (! $type instanceof ThisType) { + if (! $node->var instanceof Variable) { return []; } - return $this->validateArgVsParamTypes($args, $node, $scope); - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -use PhpParser\Node; -use PhpParser\Node\Expr\MethodCall; - -class SomeClass -{ - public function run(MethodCall $node) - { - $this->isCheck($node); - } - - private function isCheck(Node $node) - { - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -use PhpParser\Node\Expr\MethodCall; + if (! is_string($node->var->name)) { + return []; + } -class SomeClass -{ - public function run(MethodCall $node) - { - $this->isCheck($node); - } + if ($node->var->name !== 'this') { + return []; + } - private function isCheck(MethodCall $node) - { - } -} -CODE_SAMPLE - ), - ]); + return $this->validateArgVsParamTypes($args, $node, $scope); } /** @@ -149,13 +109,7 @@ private function validateArgVsParamTypes(array $args, MethodCall $methodCall, Sc continue; } - $argType = $scope->getType($arg->value); - - if ($argType instanceof MixedType) { - continue; - } - - $paramErrorMessage = $this->validateParam($param, $position, $argType); + $paramErrorMessage = $this->validateParam($param, $position, $arg->value, $scope); if (! $paramErrorMessage instanceof RuleError) { continue; } @@ -167,7 +121,7 @@ private function validateArgVsParamTypes(array $args, MethodCall $methodCall, Sc return $errorMessages; } - private function validateParam(Param $param, int $position, Type $argType): ?RuleError + private function validateParam(Param $param, int $position, Expr $expr, Scope $scope): ?RuleError { $type = $param->type; @@ -176,6 +130,15 @@ private function validateParam(Param $param, int $position, Type $argType): ?Rul return null; } + $argType = $scope->getType($expr); + if ($argType instanceof MixedType) { + return null; + } + + if ($argType instanceof TemplateType) { + return null; + } + // not solveable yet, work with PHP 8 code only if ($argType instanceof UnionType) { return null; @@ -191,6 +154,11 @@ private function validateParam(Param $param, int $position, Type $argType): ?Rul return null; } + $classReflection = $objectType->getClassReflection(); + if ($classReflection instanceof ClassReflection && $classReflection->isAbstract()) { + return null; + } + // handle weird type substration cases $paramTypeAsString = $objectType->describe(VerbosityLevel::typeOnly()); $argTypeAsString = $argType->describe(VerbosityLevel::typeOnly()); diff --git a/src/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule.php b/src/Rules/NarrowPublicClassMethodParamTypeRule.php similarity index 68% rename from src/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule.php rename to src/Rules/NarrowPublicClassMethodParamTypeRule.php index 421cd81e..e391d4dc 100644 --- a/src/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule.php +++ b/src/Rules/NarrowPublicClassMethodParamTypeRule.php @@ -2,32 +2,31 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Rules\NarrowType; +namespace Rector\TypePerfect\Rules; +use Nette\Utils\Arrays; use PhpParser\Node; use PHPStan\Analyser\Scope; use PHPStan\Node\CollectedDataNode; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleError; use PHPStan\Rules\RuleErrorBuilder; -use Symplify\PHPStanRules\Collector\ClassMethod\PublicClassMethodParamTypesCollector; -use Symplify\PHPStanRules\Collector\MethodCall\MethodCallArgTypesCollector; -use Symplify\PHPStanRules\Enum\Types\ResolvedTypes; -use Symplify\RuleDocGenerator\Contract\DocumentedRuleInterface; -use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; -use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; +use Rector\TypePerfect\Collector\ClassMethod\PublicClassMethodParamTypesCollector; +use Rector\TypePerfect\Collector\MethodCall\MethodCallArgTypesCollector; +use Rector\TypePerfect\Collector\MethodCallableNode\MethodCallableCollector; +use Rector\TypePerfect\Enum\Types\ResolvedTypes; /** - * @see \Symplify\PHPStanRules\Tests\Rules\NarrowType\NarrowPublicClassMethodParamTypeByCallerTypeRule\NarrowPublicClassMethodParamTypeByCallerTypeRuleTest + * @see \Rector\TypePerfect\Tests\Rules\NarrowPublicClassMethodParamTypeByCallerTypeRule\NarrowPublicClassMethodParamTypeByCallerTypeRuleTest * * @implements Rule */ -final class NarrowPublicClassMethodParamTypeByCallerTypeRule implements Rule +final class NarrowPublicClassMethodParamTypeRule implements Rule { /** * @var string */ - public const ERROR_MESSAGE = 'Parameters should use "%s" types as the only types passed to this method'; + public const ERROR_MESSAGE = 'Parameters should have "%s" types as the only types passed to this method'; /** * @return class-string @@ -69,6 +68,7 @@ public function processNode(Node $node, Scope $scope): array $ruleErrors[] = RuleErrorBuilder::message($errorMessage) ->file($filePath) ->line($line) + ->identifier('type_perfect.narrow_public_param_type') ->build(); } } @@ -76,51 +76,6 @@ public function processNode(Node $node, Scope $scope): array return $ruleErrors; } - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -use PhpParser\Node\Expr\MethodCall; - -final class SomeClass -{ - public function run(SomeService $someService, MethodCall $methodCall) - { - $someService->isCheck($node); - } -} - -final class SomeService -{ - public function isCheck($methodCall) - { - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -use PhpParser\Node\Expr\MethodCall; - -final class SomeClass -{ - public function run(SomeService $someService, MethodCall $methodCall) - { - $someService->isCheck($node); - } -} - -final class SomeService -{ - public function isCheck(MethodCall $methodCall) - { - } -} -CODE_SAMPLE - ), - ]); - } - /** * @return array */ @@ -128,11 +83,20 @@ private function resolveClassMethodReferenceToArgTypes(CollectedDataNode $collec { $methodCallArgTypesByFilePath = $collectedDataNode->get(MethodCallArgTypesCollector::class); + // these should be skipped completely, as we have no idea what is being passed there + $methodCallablesByFilePath = $collectedDataNode->get(MethodCallableCollector::class); + $methodFirstClassCallables = Arrays::flatten($methodCallablesByFilePath); + // group call references and types $classMethodReferenceToTypes = []; foreach ($methodCallArgTypesByFilePath as $methodCallArgTypes) { foreach ($methodCallArgTypes as [$classMethodReference, $argTypesString]) { + // skip it + if (in_array($classMethodReference, $methodFirstClassCallables, true)) { + continue; + } + $classMethodReferenceToTypes[$classMethodReference][] = $argTypesString; } } diff --git a/src/Rules/NoAbstractMethodRule.php b/src/Rules/NoAbstractMethodRule.php deleted file mode 100644 index 0c609b59..00000000 --- a/src/Rules/NoAbstractMethodRule.php +++ /dev/null @@ -1,70 +0,0 @@ - - */ - public function getNodeType(): string - { - return ClassMethod::class; - } - - /** - * @param ClassMethod $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! $node->isAbstract()) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -abstract class SomeClass -{ - abstract public function run(); -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -abstract class SomeClass implements RunnableInterface -{ -} - -interface RunnableInterface -{ - public function run(); -} -CODE_SAMPLE - ), - ]); - } -} diff --git a/src/Rules/NoArrayAccessOnObjectRule.php b/src/Rules/NoArrayAccessOnObjectRule.php index 8f78755e..0fb2943a 100644 --- a/src/Rules/NoArrayAccessOnObjectRule.php +++ b/src/Rules/NoArrayAccessOnObjectRule.php @@ -2,20 +2,19 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Rules; +namespace Rector\TypePerfect\Rules; use PhpParser\Node; use PhpParser\Node\Expr\ArrayDimFetch; use PHPStan\Analyser\Scope; use PHPStan\Rules\Rule; -use PHPStan\Type\TypeWithClassName; -use Symplify\PHPStanRules\Matcher\ArrayStringAndFnMatcher; -use Symplify\RuleDocGenerator\Contract\DocumentedRuleInterface; -use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; -use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; +use PHPStan\Rules\RuleError; +use PHPStan\Rules\RuleErrorBuilder; +use PHPStan\Type\ObjectType; /** - * @see \Symplify\PHPStanRules\Tests\Rules\NoArrayAccessOnObjectRule\NoArrayAccessOnObjectRuleTest + * @see \Rector\TypePerfect\Tests\Rules\NoArrayAccessOnObjectRule\NoArrayAccessOnObjectRuleTest + * @implements Rule */ final class NoArrayAccessOnObjectRule implements Rule { @@ -25,18 +24,9 @@ final class NoArrayAccessOnObjectRule implements Rule public const ERROR_MESSAGE = 'Use explicit methods over array access on object'; /** - * @var array + * @var string[] */ - private const ALLOWED_CLASSES = ['SplFixedArray', 'SimpleXMLElement']; - /** - * @var \Symplify\PHPStanRules\Matcher\ArrayStringAndFnMatcher - */ - private $arrayStringAndFnMatcher; - - public function __construct(ArrayStringAndFnMatcher $arrayStringAndFnMatcher) - { - $this->arrayStringAndFnMatcher = $arrayStringAndFnMatcher; - } + private const ALLOWED_CLASSES = ['SplFixedArray', 'SimpleXMLElement', 'Iterator', 'Aws\ResultInterface', 'Symfony\Component\Form\FormInterface']; /** * @return class-string @@ -48,47 +38,35 @@ public function getNodeType(): string /** * @param ArrayDimFetch $node - * @return string[] + * @return RuleError[] */ public function processNode(Node $node, Scope $scope): array { - $varStaticType = $scope->getType($node->var); - - if (! $varStaticType instanceof TypeWithClassName) { + $varType = $scope->getType($node->var); + if (! $varType instanceof ObjectType) { return []; } - if ($this->arrayStringAndFnMatcher->isMatchWithIsA($varStaticType->getClassName(), self::ALLOWED_CLASSES)) { + if ($this->isAllowedObjectType($varType)) { return []; } - return [self::ERROR_MESSAGE]; - } + $ruleError = RuleErrorBuilder::message(self::ERROR_MESSAGE) + ->line($node->getLine()) + ->identifier('type_perfect.no_array_access_on_object') + ->build(); - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -class SomeClass -{ - public function run(MagicArrayObject $magicArrayObject) - { - return $magicArrayObject['more_magic']; + return [$ruleError]; } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -class SomeClass -{ - public function run(MagicArrayObject $magicArrayObject) + + private function isAllowedObjectType(ObjectType $objectType): bool { - return $magicArrayObject->getExplicitValue(); - } -} -CODE_SAMPLE - ), - ]); + foreach (self::ALLOWED_CLASSES as $allowedClass) { + if ($objectType->isInstanceOf($allowedClass)->yes()) { + return true; + } + } + + return false; } } diff --git a/src/Rules/NoArrayStringObjectReturnRule.php b/src/Rules/NoArrayStringObjectReturnRule.php deleted file mode 100644 index e25113e3..00000000 --- a/src/Rules/NoArrayStringObjectReturnRule.php +++ /dev/null @@ -1,115 +0,0 @@ -'; - - /** - * @return class-string - */ - public function getNodeType(): string - { - return Return_::class; - } - - /** - * @param Return_ $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if ($node->expr === null) { - return []; - } - - // skip func call that only delegates - if ($node->expr instanceof FuncCall) { - return []; - } - - $returnedExprType = $scope->getType($node->expr); - if (! $this->isArrayStringToObjectType($returnedExprType)) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -final class SomeClass -{ - public function getItems() - { - return $this->getValues(); - } - - /** - * @return array - */ - private function getValues() - { - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -final class SomeClass -{ - public function getItems() - { - return $this->getValues(); - } - - /** - * @return WrappingValue[] - */ - private function getValues() - { - // ... - } -} -CODE_SAMPLE - ), - ]); - } - - private function isArrayStringToObjectType(Type $type): bool - { - if (! $type instanceof ArrayType) { - return false; - } - - if (! $type->getKeyType() instanceof StringType) { - return false; - } - - return $type->getItemType() instanceof ObjectType; - } -} diff --git a/src/Rules/NoClassWithStaticMethodWithoutStaticNameRule.php b/src/Rules/NoClassWithStaticMethodWithoutStaticNameRule.php deleted file mode 100644 index 6d9cb80b..00000000 --- a/src/Rules/NoClassWithStaticMethodWithoutStaticNameRule.php +++ /dev/null @@ -1,174 +0,0 @@ - - */ - private const ALLOWED_CLASS_TYPES = [ - // symfony classes with static methods - 'Symfony\Component\EventDispatcher\EventSubscriberInterface', - 'Symfony\Component\Console\Command\Command', - ]; - /** - * @var \PhpParser\NodeFinder - */ - private $nodeFinder; - /** - * @var \Symplify\PHPStanRules\Matcher\ArrayStringAndFnMatcher - */ - private $arrayStringAndFnMatcher; - - public function __construct(NodeFinder $nodeFinder, ArrayStringAndFnMatcher $arrayStringAndFnMatcher) - { - $this->nodeFinder = $nodeFinder; - $this->arrayStringAndFnMatcher = $arrayStringAndFnMatcher; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classLike = $node->getOriginalNode(); - if (! $classLike instanceof Class_) { - return []; - } - - if (! $classLike->name instanceof Identifier) { - return []; - } - - if (! $this->isClassWithStaticMethod($classLike)) { - return []; - } - - // skip anonymous class - $shortClassName = $classLike->name->toString(); - if ($shortClassName === '') { - return []; - } - - // already has "Static" in the name - if (strpos($shortClassName, 'Static') !== false) { - return []; - } - - if ($this->shouldSkipClassName($node)) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -class SomeClass -{ - public static function getSome() - { - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -class SomeStaticClass -{ - public static function getSome() - { - } -} -CODE_SAMPLE - ), - ]); - } - - private function isClassWithStaticMethod(Class_ $class): bool - { - $classMethods = $class->getMethods(); - - foreach ($classMethods as $classMethod) { - if (! $classMethod->isStatic()) { - continue; - } - - if ($this->isStaticConstructorOfValueObject($classMethod)) { - continue; - } - - return true; - } - - return false; - } - - private function shouldSkipClassName(InClassNode $inClassNode): bool - { - $classReflection = $inClassNode->getClassReflection(); - - return $this->arrayStringAndFnMatcher->isMatchWithIsA( - $classReflection->getName(), - self::ALLOWED_CLASS_TYPES - ); - } - - private function isStaticConstructorOfValueObject(ClassMethod $classMethod): bool - { - return (bool) $this->nodeFinder->findFirst((array) $classMethod->stmts, static function (Node $node): bool { - if (! $node instanceof Return_) { - return false; - } - - $returnedExpr = $node->expr; - if (! $returnedExpr instanceof New_) { - return false; - } - - if (! $returnedExpr->class instanceof Name) { - return false; - } - - return $returnedExpr->class->toString() === 'self'; - }); - } -} diff --git a/src/Rules/NoConstructorInTestRule.php b/src/Rules/NoConstructorInTestRule.php deleted file mode 100644 index f8df06ae..00000000 --- a/src/Rules/NoConstructorInTestRule.php +++ /dev/null @@ -1,87 +0,0 @@ - - */ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return RuleError[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classReflection = $node->getClassReflection(); - if (substr_compare($classReflection->getName(), 'Test', -strlen('Test')) !== 0) { - return []; - } - - $classLike = $node->getOriginalNode(); - $constructorClassMethod = $classLike->getMethod(MethodName::CONSTRUCTOR); - if (! $constructorClassMethod instanceof ClassMethod) { - return []; - } - - $ruleError = RuleErrorBuilder::message(self::ERROR_MESSAGE) - ->line($constructorClassMethod->getLine()) - ->build(); - - return [$ruleError]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -final class SomeTest -{ - public function __construct() - { - // ... - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -final class SomeTest -{ - public function setUp() - { - // ... - } -} -CODE_SAMPLE - ), - ]); - } -} diff --git a/src/Rules/NoDefaultExceptionRule.php b/src/Rules/NoDefaultExceptionRule.php deleted file mode 100644 index 62271fcc..00000000 --- a/src/Rules/NoDefaultExceptionRule.php +++ /dev/null @@ -1,80 +0,0 @@ - - */ - public function getNodeType(): string - { - return Throw_::class; - } - - /** - * @param Throw_ $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - $thrownExpr = $node->expr; - if (! $thrownExpr instanceof New_) { - return []; - } - - if (! $thrownExpr->class instanceof Name) { - return []; - } - - $exceptionClassName = $thrownExpr->class->toString(); - if (! is_a($exceptionClassName, Throwable::class, true)) { - return []; - } - - // fast way to detect native exceptions - if (strpos($exceptionClassName, '\\') !== false) { - return []; - } - - return [sprintf(self::ERROR_MESSAGE, $exceptionClassName)]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -throw new RuntimeException('...'); -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -use App\Exception\FileNotFoundException; - -throw new FileNotFoundException('...'); -CODE_SAMPLE - ), - ]); - } -} diff --git a/src/Rules/NoDuplicatedShortClassNameRule.php b/src/Rules/NoDuplicatedShortClassNameRule.php deleted file mode 100644 index 7622fd53..00000000 --- a/src/Rules/NoDuplicatedShortClassNameRule.php +++ /dev/null @@ -1,177 +0,0 @@ - - */ - private $declaredClassesByShortName = []; - /** - * @var int - */ - private $toleratedNestingLevel; - - public function __construct(int $toleratedNestingLevel) - { - $this->toleratedNestingLevel = $toleratedNestingLevel; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classReflection = $node->getClassReflection(); - - $className = $classReflection->getName(); - if ($this->isAllowedClass($className)) { - return []; - } - - $classLike = $node->getOriginalNode(); - if (! $classLike->name instanceof Identifier) { - return []; - } - - $shortClassName = $classLike->name->toString(); - - // make sure classes are unique - $existingClassesByShortClassName = $this->resolveExistingClassesByShortClassName($shortClassName, $className); - $this->declaredClassesByShortName[$shortClassName] = $existingClassesByShortClassName; - - $classes = $this->declaredClassesByShortName[$shortClassName] ?? []; - if (count($classes) <= 1) { - return []; - } - - // is nesting level tolerated? - e.g. in case of monorepo project, it's ok to have duplicated classes in 2 levels, e.g. Symplify\\CodingStandard\\ - $classesByToleratedNamespace = []; - - $classesByShortNameCount = count($classes); - - foreach ($classes as $class) { - $toleratedNamespace = Strings::before($class, '\\', $this->toleratedNestingLevel); - $classesByToleratedNamespace[$toleratedNamespace][] = $class; - } - - $toleratedNamespaces = array_keys($classesByToleratedNamespace); - - // this namespace has many classes tolerated → skip it - if (count($toleratedNamespaces) >= $classesByShortNameCount) { - return []; - } - - $errorMessage = sprintf(self::ERROR_MESSAGE, $shortClassName, implode('", "', $classes)); - return [$errorMessage]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new ConfiguredCodeSample( - <<<'CODE_SAMPLE' -namespace App; - -class SomeClass -{ -} - -namespace App\Nested; - -class SomeClass -{ -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -namespace App; - -class SomeClass -{ -} - -namespace App\Nested; - -class AnotherClass -{ -} -CODE_SAMPLE - , - [ - 'toleratedNestingLevel' => 1, - ] - ), - ]); - } - - private function isAllowedClass(string $name): bool - { - // is allowed - foreach (self::ALLOWED_CLASS_NAMES as $allowedClassName) { - if (! Strings::match($name, $allowedClassName)) { - continue; - } - - return true; - } - - return false; - } - - /** - * @return string[] - */ - private function resolveExistingClassesByShortClassName(string $shortClassName, string $className): array - { - $existingClassesByShortClassName = $this->declaredClassesByShortName[$shortClassName] ?? []; - $existingClassesByShortClassName[] = $className; - - return array_unique($existingClassesByShortClassName); - } -} diff --git a/src/Rules/NoDynamicNameRule.php b/src/Rules/NoDynamicNameRule.php deleted file mode 100644 index 20fe703c..00000000 --- a/src/Rules/NoDynamicNameRule.php +++ /dev/null @@ -1,113 +0,0 @@ -callableTypeAnalyzer = $callableTypeAnalyzer; - } - - /** - * @return array> - */ - public function getNodeTypes(): array - { - return [ - MethodCall::class, - StaticCall::class, - FuncCall::class, - StaticPropertyFetch::class, - PropertyFetch::class, - ClassConstFetch::class, - ]; - } - - /** - * @param MethodCall|StaticCall|FuncCall|StaticPropertyFetch|PropertyFetch|ClassConstFetch $node - * @return string[] - */ - public function process(Node $node, Scope $scope): array - { - if ($node instanceof ClassConstFetch || $node instanceof StaticPropertyFetch) { - if (! $node->class instanceof Expr) { - return []; - } - - if (! $node->name instanceof Identifier) { - return []; - } - - if ($node->name->toString() === 'class') { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - if (! $node->name instanceof Expr) { - return []; - } - - if ($this->callableTypeAnalyzer->isClosureOrCallableType($scope, $node->name)) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -class SomeClass -{ - public function old(): bool - { - return $this->${variable}; - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -class SomeClass -{ - public function old(): bool - { - return $this->specificMethodName(); - } -} -CODE_SAMPLE - ), - ]); - } -} diff --git a/src/Rules/NoDynamicPropertyOnStaticCallRule.php b/src/Rules/NoDynamicPropertyOnStaticCallRule.php deleted file mode 100644 index 2e40fa10..00000000 --- a/src/Rules/NoDynamicPropertyOnStaticCallRule.php +++ /dev/null @@ -1,96 +0,0 @@ -staticCallNodeAnalyzer = $staticCallNodeAnalyzer; - } - - /** - * @return array> - */ - public function getNodeTypes(): array - { - return [StaticCall::class, ClassConstFetch::class]; - } - - /** - * @param StaticCall|ClassConstFetch $node - * @return string[] - */ - public function process(Node $node, Scope $scope): array - { - if ($node->class instanceof Name) { - return []; - } - - if ($this->staticCallNodeAnalyzer->isAbstractMethodStaticCall($node, $scope)) { - return []; - } - - if ($node->name instanceof Identifier && $node->name->toString() === 'class') { - return []; - } - - $callerType = $scope->getType($node->class); - if ($callerType instanceof UnionType) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -class SomeClass -{ - public function run() - { - return $this->connection::literal(); - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -class SomeClass -{ - public function run() - { - return Connection::literal(); - } -} -CODE_SAMPLE - ), - ]); - } -} diff --git a/src/Rules/NoEmptyClassRule.php b/src/Rules/NoEmptyClassRule.php deleted file mode 100644 index d7a77ce6..00000000 --- a/src/Rules/NoEmptyClassRule.php +++ /dev/null @@ -1,143 +0,0 @@ -reflectionProvider = $reflectionProvider; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classLike = $node->getOriginalNode(); - if ($classLike->stmts !== []) { - return []; - } - - // skip attribute - if ($this->isAttributeClass($node)) { - return []; - } - - if ($this->shouldSkipClassLike($classLike, $node)) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -class SomeClass -{ -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -class SomeClass -{ - public function getSome() - { - } -} -CODE_SAMPLE - ), - ]); - } - - private function shouldSkipClassLike(ClassLike $classLike, InClassNode $inClassNode): bool - { - if (! $classLike instanceof Class_ && ! $classLike instanceof Trait_) { - return true; - } - - $classReflection = $inClassNode->getClassReflection(); - if ($classReflection->isSubclassOf(Throwable::class)) { - return true; - } - - if ($classLike->getComments() !== []) { - return true; - } - - return $this->isFinalClassWithAbstractOrInterfaceParent($classLike); - } - - /** - * @param \PhpParser\Node\Stmt\Class_|\PhpParser\Node\Stmt\Trait_ $classLike - */ - private function isFinalClassWithAbstractOrInterfaceParent($classLike): bool - { - if (! $classLike instanceof Class_) { - return false; - } - - if ($classLike->implements !== []) { - return true; - } - - if (! $classLike->isFinal()) { - return false; - } - - if (! $classLike->extends instanceof Name) { - return false; - } - - $parentClass = $classLike->extends->toString(); - $parentClassReflection = $this->reflectionProvider->getClass($parentClass); - - return $parentClassReflection->isAbstract(); - } - - private function isAttributeClass(InClassNode $inClassNode): bool - { - $classReflection = $inClassNode->getClassReflection(); - return $classReflection->isAttributeClass(); - } -} diff --git a/src/Rules/NoEmptyOnObjectRule.php b/src/Rules/NoEmptyOnObjectRule.php new file mode 100644 index 00000000..99c68052 --- /dev/null +++ b/src/Rules/NoEmptyOnObjectRule.php @@ -0,0 +1,59 @@ + + */ +final class NoEmptyOnObjectRule implements Rule +{ + /** + * @var string + */ + public const ERROR_MESSAGE = 'Use instanceof instead of empty() on object'; + + public function getNodeType(): string + { + return Empty_::class; + } + + /** + * @param Empty_ $node + * @return RuleError[] + */ + public function processNode(Node $node, Scope $scope): array + { + $expr = $node->expr; + if ($this->shouldSkipVariable($expr, $scope)) { + return []; + } + + $ruleError = RuleErrorBuilder::message(self::ERROR_MESSAGE) + ->line($node->getLine()) + ->identifier('type_perfect.no_empty_on_object') + ->build(); + + return [$ruleError]; + } + + private function shouldSkipVariable(Expr $expr, Scope $scope): bool + { + if ($expr instanceof ArrayDimFetch) { + return true; + } + + $varType = $scope->getType($expr); + return $varType->getObjectClassNames() === []; + } +} diff --git a/src/Rules/NoFuncCallInMethodCallRule.php b/src/Rules/NoFuncCallInMethodCallRule.php deleted file mode 100644 index 932a3477..00000000 --- a/src/Rules/NoFuncCallInMethodCallRule.php +++ /dev/null @@ -1,116 +0,0 @@ - - */ - public function getNodeType(): string - { - return MethodCall::class; - } - - /** - * @param MethodCall $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - $messages = []; - - foreach ($node->args as $arg) { - if (! $arg instanceof Arg) { - continue; - } - - if (! $arg->value instanceof FuncCall) { - continue; - } - - $funcCallName = $this->resolveFuncCallName($arg); - - if (strpos($funcCallName, '\\') !== false) { - continue; - } - - if (in_array($funcCallName, self::ALLOWED_FUNC_CALL_NAMES, true)) { - continue; - } - - $messages[] = sprintf(self::ERROR_MESSAGE, $funcCallName); - } - - return $messages; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -final class SomeClass -{ - public function run($value): void - { - $this->someMethod(strlen('fooo')); - } - - // ... -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -final class SomeClass -{ - public function run($value): void - { - $fooLength = strlen('fooo'); - $this->someMethod($fooLength); - } - - // ... -} -CODE_SAMPLE - ), - ]); - } - - private function resolveFuncCallName(Arg $arg): string - { - /** @var FuncCall $funcCall */ - $funcCall = $arg->value; - if ($funcCall->name instanceof Expr) { - return '*dynamic*'; - } - - return (string) $funcCall->name; - } -} diff --git a/src/Rules/NoInlineStringRegexRule.php b/src/Rules/NoInlineStringRegexRule.php deleted file mode 100644 index b65c03b8..00000000 --- a/src/Rules/NoInlineStringRegexRule.php +++ /dev/null @@ -1,154 +0,0 @@ -regexFuncCallAnalyzer = $regexFuncCallAnalyzer; - $this->regexStaticCallAnalyzer = $regexStaticCallAnalyzer; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return CallLike::class; - } - - /** - * @param Node\Expr\CallLike $node - * @return mixed[]|string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if ($node instanceof FuncCall) { - return $this->processRegexFuncCall($node); - } - - if ($node instanceof StaticCall) { - return $this->processRegexStaticCall($node); - } - - return []; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -class SomeClass -{ - public function run($value) - { - return preg_match('#some_stu|ff#', $value); - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -class SomeClass -{ - /** - * @var string - */ - public const SOME_STUFF_REGEX = '#some_stu|ff#'; - - public function run($value) - { - return preg_match(self::SOME_STUFF_REGEX, $value); - } -} -CODE_SAMPLE - ), - ]); - } - - /** - * @return string[] - */ - private function processRegexFuncCall(FuncCall $funcCall): array - { - if (! $this->regexFuncCallAnalyzer->isRegexFuncCall($funcCall)) { - return []; - } - - $firstArgOrVariadicPlaceholder = $funcCall->args[0]; - if (! $firstArgOrVariadicPlaceholder instanceof Arg) { - return []; - } - - // it's not string → good - if (! $firstArgOrVariadicPlaceholder->value instanceof String_) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - /** - * @return string[] - */ - private function processRegexStaticCall(StaticCall $staticCall): array - { - if (! $this->regexStaticCallAnalyzer->isRegexStaticCall($staticCall)) { - return []; - } - - $argOrVariadicPlaceholder = $staticCall->args[1]; - if (! $argOrVariadicPlaceholder instanceof Arg) { - return []; - } - - $secondArgValue = $argOrVariadicPlaceholder->value; - - // it's not string → good - if (! $secondArgValue instanceof String_) { - return []; - } - - $regexValue = $secondArgValue->value; - - if (Strings::length($regexValue) <= 7) { - return []; - } - - return [self::ERROR_MESSAGE]; - } -} diff --git a/src/Rules/NoIssetOnObjectRule.php b/src/Rules/NoIssetOnObjectRule.php index 27c3abf3..8b272528 100644 --- a/src/Rules/NoIssetOnObjectRule.php +++ b/src/Rules/NoIssetOnObjectRule.php @@ -2,117 +2,54 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Rules; +namespace Rector\TypePerfect\Rules; use PhpParser\Node; use PhpParser\Node\Expr; use PhpParser\Node\Expr\ArrayDimFetch; -use PhpParser\Node\Expr\Empty_; use PhpParser\Node\Expr\Isset_; use PHPStan\Analyser\Scope; -use PHPStan\Type\TypeWithClassName; -use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; -use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; +use PHPStan\Rules\Rule; +use PHPStan\Rules\RuleError; +use PHPStan\Rules\RuleErrorBuilder; /** - * @see \Symplify\PHPStanRules\Tests\Rules\NoIssetOnObjectRule\NoIssetOnObjectRuleTest + * @see \Rector\TypePerfect\Tests\Rules\NoIssetOnObjectRule\NoIssetOnObjectRuleTest + * @implements Rule */ -final class NoIssetOnObjectRule extends AbstractSymplifyRule +final class NoIssetOnObjectRule implements Rule { /** * @var string */ - public const ERROR_MESSAGE = 'Use default null value and nullable compare instead of isset on object'; + public const ERROR_MESSAGE = 'Use instanceof instead of isset() on object'; - /** - * @return array> - */ - public function getNodeTypes(): array - { - return [Empty_::class, Isset_::class]; - } - - /** - * @param Empty_|Isset_ $node - * @return string[] - */ - public function process(Node $node, Scope $scope): array - { - if ($node instanceof Isset_) { - return $this->processIsset($node, $scope); - } - - return $this->processEmpty($node, $scope); - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -class SomeClass -{ - public function run() - { - if (random_int(0, 1)) { - $object = new SomeClass(); - } - - if (isset($object)) { - return $object; - } - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -class SomeClass -{ - public function run() + public function getNodeType(): string { - $object = null; - if (random_int(0, 1)) { - $object = new SomeClass(); - } - - if ($object !== null) { - return $object; - } - } -} -CODE_SAMPLE - ), - ]); + return Isset_::class; } /** - * @return string[] + * @param Isset_ $node + * + * @return RuleError[] */ - private function processIsset(Isset_ $isset, Scope $scope): array + public function processNode(Node $node, Scope $scope): array { - foreach ($isset->vars as $var) { + foreach ($node->vars as $var) { if ($this->shouldSkipVariable($var, $scope)) { continue; } - return [self::ERROR_MESSAGE]; - } - - return []; - } + $ruleError = RuleErrorBuilder::message(self::ERROR_MESSAGE) + ->line($node->getLine()) + ->identifier('type_perfect.no_isset_on_object') + ->build(); - /** - * @return string[] - */ - private function processEmpty(Empty_ $empty, Scope $scope): array - { - $expr = $empty->expr; - - if ($this->shouldSkipVariable($expr, $scope)) { - return []; + return [$ruleError]; } - return [self::ERROR_MESSAGE]; + return []; } private function shouldSkipVariable(Expr $expr, Scope $scope): bool @@ -122,7 +59,6 @@ private function shouldSkipVariable(Expr $expr, Scope $scope): bool } $varType = $scope->getType($expr); - - return ! $varType instanceof TypeWithClassName; + return $varType->getObjectClassNames() === []; } } diff --git a/src/Rules/NoMethodTagInClassDocblockRule.php b/src/Rules/NoMethodTagInClassDocblockRule.php deleted file mode 100644 index 71c437d4..00000000 --- a/src/Rules/NoMethodTagInClassDocblockRule.php +++ /dev/null @@ -1,95 +0,0 @@ - - */ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - $docComment = $node->getDocComment(); - if (! $docComment instanceof Doc) { - return []; - } - - if (! Strings::match($docComment->getText(), self::METHOD_TAG_REGEX)) { - return []; - } - - // enums are the only exception for annotation - $classReflection = $node->getClassReflection(); - if ($classReflection->isSubclassOf(Enum::class)) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -/** - * @method getMagic() string - */ -class SomeClass -{ - public function __call() - { - // more magic - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -class SomeClass -{ - public function getExplicitValue() - { - return 'explicit'; - } -} -CODE_SAMPLE - ), - ]); - } -} diff --git a/src/Rules/NoMissingDirPathRule.php b/src/Rules/NoMissingDirPathRule.php deleted file mode 100644 index bbd90104..00000000 --- a/src/Rules/NoMissingDirPathRule.php +++ /dev/null @@ -1,144 +0,0 @@ - - */ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return RuleError[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classLike = $node->getOriginalNode(); - - $classReflection = $scope->getClassReflection(); - if (! $classReflection instanceof ClassReflection) { - return []; - } - - // test fixture can exist or not, better skip this case to avoid false positives - if ($classReflection->isSubclassOf(TestCase::class)) { - return []; - } - - // mimics node finding visitors of NodeFinder with ability to stop traversing deeper - $nodeTraverser = new NodeTraverser(); - $flatConcatFindingNodeVisitor = new FlatConcatFindingNodeVisitor(new FileCheckingFuncCallAnalyzer()); - - $nodeTraverser->addVisitor($flatConcatFindingNodeVisitor); - $nodeTraverser->traverse($classLike->stmts); - - $concats = $flatConcatFindingNodeVisitor->getFoundNodes(); - $errorMessages = []; - - foreach ($concats as $concat) { - if (! $concat->left instanceof Dir) { - return []; - } - - if (! $concat->right instanceof String_) { - return []; - } - - $string = $concat->right; - $relativeDirPath = $string->value; - - if ($this->shouldSkip($relativeDirPath)) { - continue; - } - - $realDirectory = dirname($scope->getFile()); - $fileRealPath = $realDirectory . $relativeDirPath; - - if (file_exists($fileRealPath)) { - continue; - } - - $errorMessages[] = RuleErrorBuilder::message(sprintf(self::ERROR_MESSAGE, $relativeDirPath)) - ->line($concat->getLine()) - ->build(); - } - - return $errorMessages; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -$filePath = __DIR__ . '/missing_location.txt'; -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -$filePath = __DIR__ . '/existing_location.txt'; -CODE_SAMPLE - ), - ]); - } - - private function shouldSkip(string $relativeDirPath): bool - { - // is vendor autolaod? it yet to be exist - if (Strings::match($relativeDirPath, self::VENDOR_REGEX)) { - return true; - } - - if (strpos($relativeDirPath, '*') !== false) { - return true; - } - - $bracketMatches = Strings::match($relativeDirPath, self::BRACKET_PATH_REGEX); - return $bracketMatches !== null; - } -} diff --git a/src/Rules/NoMixedMethodCallerRule.php b/src/Rules/NoMixedMethodCallerRule.php new file mode 100644 index 00000000..dbf198fc --- /dev/null +++ b/src/Rules/NoMixedMethodCallerRule.php @@ -0,0 +1,66 @@ + + */ +final class NoMixedMethodCallerRule implements Rule +{ + /** + * @var string + */ + public const ERROR_MESSAGE = 'Mixed variable in a `%s->...()` method call can lead to false dead methods. Make sure the variable type is known'; + + public function __construct( + private readonly Standard $printerStandard, + ) { + } + + /** + * @return class-string + */ + public function getNodeType(): string + { + return MethodCall::class; + } + + /** + * @param MethodCall $node + * @return mixed[] + */ + public function processNode(Node $node, Scope $scope): array + { + $callerType = $scope->getType($node->var); + if (! $callerType instanceof MixedType) { + return []; + } + + if ($callerType instanceof ErrorType) { + return []; + } + + $printedMethodCall = $this->printerStandard->prettyPrintExpr($node->var); + + $errorMessage = sprintf(self::ERROR_MESSAGE, $printedMethodCall); + + $ruleError = RuleErrorBuilder::message($errorMessage) + ->line($node->getLine()) + ->identifier('type_perfect.no_mixed_method_caller') + ->build(); + + return [$ruleError]; + } +} diff --git a/src/Rules/Explicit/NoMixedPropertyFetcherRule.php b/src/Rules/NoMixedPropertyFetcherRule.php similarity index 52% rename from src/Rules/Explicit/NoMixedPropertyFetcherRule.php rename to src/Rules/NoMixedPropertyFetcherRule.php index 4c5d3aa5..7d97ba10 100644 --- a/src/Rules/Explicit/NoMixedPropertyFetcherRule.php +++ b/src/Rules/NoMixedPropertyFetcherRule.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Rules\Explicit; +namespace Rector\TypePerfect\Rules; use PhpParser\Node; use PhpParser\Node\Expr\PropertyFetch; @@ -10,12 +10,10 @@ use PHPStan\Analyser\Scope; use PHPStan\Rules\Rule; use PHPStan\Type\MixedType; -use Symplify\RuleDocGenerator\Contract\DocumentedRuleInterface; -use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; -use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; /** - * @see \Symplify\PHPStanRules\Tests\Rules\Explicit\NoMixedPropertyFetcherRule\NoMixedPropertyFetcherRuleTest + * @see \Rector\TypePerfect\Tests\Rules\NoMixedPropertyFetcherRule\NoMixedPropertyFetcherRuleTest + * @implements Rule */ final class NoMixedPropertyFetcherRule implements Rule { @@ -23,13 +21,10 @@ final class NoMixedPropertyFetcherRule implements Rule * @var string */ public const ERROR_MESSAGE = 'Anonymous variables in a "%s->..." property fetch can lead to false dead property. Make sure the variable type is known'; - /** - * @var \PhpParser\PrettyPrinter\Standard - */ - private $standard; - public function __construct(Standard $standard) - { - $this->standard = $standard; + + public function __construct( + private readonly Standard $standard, + ) { } /** @@ -55,25 +50,4 @@ public function processNode(Node $node, Scope $scope): array return [sprintf(self::ERROR_MESSAGE, $printedVar)]; } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -function run($unknownType) -{ - return $unknownType->name; -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -function run(KnownType $knownType) -{ - return $knownType->name; -} -CODE_SAMPLE - ), - ]); - } } diff --git a/src/Rules/NoMultiArrayAssignRule.php b/src/Rules/NoMultiArrayAssignRule.php deleted file mode 100644 index 12c0ae2a..00000000 --- a/src/Rules/NoMultiArrayAssignRule.php +++ /dev/null @@ -1,150 +0,0 @@ - - */ -final class NoMultiArrayAssignRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'Use value object over multi array assign'; - /** - * @var \Symplify\PHPStanRules\Printer\NodeComparator - */ - private $nodeComparator; - - public function __construct(NodeComparator $nodeComparator) - { - $this->nodeComparator = $nodeComparator; - } - - public function getNodeType(): string - { - return Node::class; - } - - /** - * @return RuleError[] - */ - public function processNode(Node $node, Scope $scope): array - { - // check all of stmts aware nodes, see https://github.com/nikic/PHP-Parser/pull/836 - if (! $node instanceof ClassMethod && ! $node instanceof Function_ && ! $node instanceof Closure && ! $node instanceof If_ && ! $node instanceof Else_) { - return []; - } - - foreach ((array) $node->stmts as $key => $stmt) { - $firstArrayDimFetch = $this->matchAssignToArrayDimFetch($stmt); - if (! $firstArrayDimFetch instanceof ArrayDimFetch) { - continue; - } - - $nextStmt = $node->stmts[$key + 1] ?? null; - if (! $nextStmt instanceof Stmt) { - return []; - } - - $secondArrayDimFetch = $this->matchAssignToArrayDimFetch($nextStmt); - if (! $secondArrayDimFetch instanceof ArrayDimFetch) { - continue; - } - - if (! $this->haveSameArrayDimFetchNonEmptyRoot($firstArrayDimFetch, $secondArrayDimFetch)) { - continue; - } - - $ruleError = RuleErrorBuilder::message(self::ERROR_MESSAGE) - ->line($nextStmt->getLine()) - ->build(); - - return [$ruleError]; - } - - return []; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -$values = []; -$values['person']['name'] = 'Tom'; -$values['person']['surname'] = 'Dev'; -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -$values = []; -$values[] = new Person('Tom', 'Dev'); -CODE_SAMPLE - ), - ]); - } - - private function haveSameArrayDimFetchNonEmptyRoot( - ArrayDimFetch $firstArrayDimFetch, - ArrayDimFetch $secondArrayDimFetch - ): bool { - $singleNestedFirstArrayDimFetch = $this->resolveSingleNestedArrayDimFetch($firstArrayDimFetch); - - if ($singleNestedFirstArrayDimFetch->dim === null) { - return false; - } - - $singleNestedSecondArrayDimFetch = $this->resolveSingleNestedArrayDimFetch($secondArrayDimFetch); - - return $this->nodeComparator->areNodesEqual($singleNestedFirstArrayDimFetch, $singleNestedSecondArrayDimFetch); - } - - private function resolveSingleNestedArrayDimFetch(ArrayDimFetch $arrayDimFetch): ArrayDimFetch - { - while ($arrayDimFetch->var instanceof ArrayDimFetch) { - $arrayDimFetch = $arrayDimFetch->var; - } - - return $arrayDimFetch; - } - - private function matchAssignToArrayDimFetch(Stmt $stmt): ?ArrayDimFetch - { - if (! $stmt instanceof Expression) { - return null; - } - - if (! $stmt->expr instanceof Assign) { - return null; - } - - $assign = $stmt->expr; - if (! $assign->var instanceof ArrayDimFetch) { - return null; - } - - return $assign->var; - } -} diff --git a/src/Rules/NoNestedFuncCallRule.php b/src/Rules/NoNestedFuncCallRule.php deleted file mode 100644 index cb37cceb..00000000 --- a/src/Rules/NoNestedFuncCallRule.php +++ /dev/null @@ -1,124 +0,0 @@ -nodeFinder = $nodeFinder; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return FuncCall::class; - } - - /** - * @param FuncCall $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! $node->name instanceof Name) { - return []; - } - - $rootFuncCallName = $node->name->toString(); - if ($rootFuncCallName === 'assert') { - return []; - } - - $allowedNames = array_diff(self::ALLOWED_FUNC_NAMES, [$rootFuncCallName]); - - foreach ($node->getArgs() as $arg) { - // avoid nesting checks, e.g. usort() - if ($arg->value instanceof Closure) { - continue; - } - - /** @var FuncCall[] $nestedFuncCalls */ - $nestedFuncCalls = $this->nodeFinder->findInstanceOf($arg, FuncCall::class); - - foreach ($nestedFuncCalls as $nestedFuncCall) { - if (! $nestedFuncCall->name instanceof Name) { - continue; - } - - $nestedFuncCallName = $nestedFuncCall->name->toString(); - if (in_array($nestedFuncCallName, $allowedNames, true)) { - continue; - } - - return [self::ERROR_MESSAGE]; - } - } - - return []; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -$filteredValues = array_filter(array_map($callback, $items)); -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -$mappedItems = array_map($callback, $items); -$filteredValues = array_filter($mappedItems); -CODE_SAMPLE - ), - ]); - } -} diff --git a/src/Rules/NoNullableArrayPropertyRule.php b/src/Rules/NoNullableArrayPropertyRule.php deleted file mode 100644 index 173d1f34..00000000 --- a/src/Rules/NoNullableArrayPropertyRule.php +++ /dev/null @@ -1,72 +0,0 @@ - - */ - public function getNodeType(): string - { - return Property::class; - } - - /** - * @param Property $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! $node->type instanceof NullableType) { - return []; - } - - $typeName = $node->type->type->toString(); - if ($typeName !== 'array') { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -final class SomeClass -{ - private ?array $property = null; -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -final class SomeClass -{ - private array $property = []; -} -CODE_SAMPLE - ), - ]); - } -} diff --git a/src/Rules/NoParentMethodCallOnNoOverrideProcessRule.php b/src/Rules/NoParentMethodCallOnNoOverrideProcessRule.php deleted file mode 100644 index 5d8ec575..00000000 --- a/src/Rules/NoParentMethodCallOnNoOverrideProcessRule.php +++ /dev/null @@ -1,126 +0,0 @@ -nodeComparator = $nodeComparator; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return ClassMethod::class; - } - - /** - * @param ClassMethod $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - $onlyNode = $this->resolveOnlyNode($node); - if (! $onlyNode instanceof StaticCall) { - return []; - } - - if (! $this->isParentSelfMethodStaticCall($onlyNode, $node)) { - return []; - } - - $methodCallArgs = $onlyNode->args; - $classMethodParams = $node->params; - - if (! $this->nodeComparator->areArgsAndParamsSame($methodCallArgs, $classMethodParams)) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -class SomeClass extends Printer -{ - public function print($nodes) - { - return parent::print($nodes); - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -class SomeClass extends Printer -{ -} -CODE_SAMPLE - ), - ]); - } - - private function isParentSelfMethodStaticCall(StaticCall $staticCall, ClassMethod $classMethod): bool - { - if (! $staticCall->class instanceof Name) { - return false; - } - - if ($staticCall->class->toString() !== 'parent') { - return false; - } - - if (! $staticCall->name instanceof Identifier) { - return false; - } - - return $staticCall->name->toString() === $classMethod->name->toString(); - } - - private function resolveOnlyNode(ClassMethod $classMethod): ?Node - { - $stmts = (array) $classMethod->stmts; - if (count($stmts) !== 1) { - return null; - } - - $onlyStmt = $stmts[0]; - if (! $onlyStmt instanceof Expression) { - return null; - } - - return $onlyStmt->expr; - } -} diff --git a/src/Rules/NoProtectedElementInFinalClassRule.php b/src/Rules/NoProtectedElementInFinalClassRule.php deleted file mode 100644 index a2e81644..00000000 --- a/src/Rules/NoProtectedElementInFinalClassRule.php +++ /dev/null @@ -1,187 +0,0 @@ -parentClassMethodGuard = $parentClassMethodGuard; - } - - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return RuleError[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classLike = $node->getOriginalNode(); - if (! $classLike instanceof Class_) { - return []; - } - - if (! $classLike->isFinal()) { - return []; - } - - $propertyErrorMessages = $this->processProperties($classLike->getProperties(), $scope); - $classMethodErrorMessages = $this->processClassMethods($classLike->getMethods(), $scope); - - return array_merge($propertyErrorMessages, $classMethodErrorMessages); - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -final class SomeClass -{ - protected function run() - { - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -final class SomeClass -{ - private function run() - { - } -} -CODE_SAMPLE - ), - ]); - } - - /** - * @param ClassMethod[] $classMethods - * @return RuleError[] - */ - private function processClassMethods(array $classMethods, Scope $scope): array - { - $errorMessages = []; - - foreach ($classMethods as $classMethod) { - if (! $classMethod->isProtected()) { - continue; - } - - if ($this->shouldSkipClassMethod($classMethod, $scope)) { - continue; - } - - $errorMessages[] = $this->createErrorMessageWithLine($classMethod); - } - - return $errorMessages; - } - - private function shouldSkipClassMethod(ClassMethod $classMethod, Scope $scope): bool - { - // is Symfony Kernel required magic method? - if ($this->isSymfonyMicroKernelRequired($classMethod, $scope)) { - return true; - } - - return $this->parentClassMethodGuard->isClassMethodGuardedByParentClassMethod($classMethod, $scope); - } - - private function shouldSkipProperty(Property $property, Scope $scope): bool - { - $classReflection = $scope->getClassReflection(); - if (! $classReflection instanceof ClassReflection) { - return false; - } - - $propertyName = (string) $property->props[0]->name; - - foreach ($classReflection->getParents() as $parentClassReflection) { - if ($parentClassReflection->hasProperty($propertyName)) { - return true; - } - } - - return false; - } - - private function isSymfonyMicroKernelRequired(ClassMethod $classMethod, Scope $scope): bool - { - if (! in_array($classMethod->name->toString(), ['configureRoutes', 'configureContainer'], true)) { - return false; - } - - $classReflection = $scope->getClassReflection(); - if (! $classReflection instanceof ClassReflection) { - return false; - } - - return $classReflection->hasTraitUse(MicroKernelTrait::class); - } - - /** - * @param Property[] $properties - * @return RuleError[] - */ - private function processProperties(array $properties, Scope $scope): array - { - $errorMessages = []; - - foreach ($properties as $property) { - if (! $property->isProtected()) { - continue; - } - - if ($this->shouldSkipProperty($property, $scope)) { - continue; - } - - $errorMessages[] = $this->createErrorMessageWithLine($property); - } - - return $errorMessages; - } - - private function createErrorMessageWithLine(Node $node): RuleError - { - return RuleErrorBuilder::message(self::ERROR_MESSAGE) - ->line($node->getLine()) - ->build(); - } -} diff --git a/src/Rules/NoReferenceRule.php b/src/Rules/NoReferenceRule.php deleted file mode 100644 index 9a015de1..00000000 --- a/src/Rules/NoReferenceRule.php +++ /dev/null @@ -1,132 +0,0 @@ -parentClassMethodNodeResolver = $parentClassMethodNodeResolver; - } - - /** - * @return array> - */ - public function getNodeTypes(): array - { - return [ - ClassMethod::class, - Function_::class, - AssignRef::class, - Arg::class, - Foreach_::class, - ArrayItem::class, - ArrowFunction::class, - Closure::class, - ]; - } - - /** - * @param ClassMethod|Function_|AssignRef|Arg|Foreach_|ArrayItem|ArrowFunction|Closure $node - * @return string[] - */ - public function process(Node $node, Scope $scope): array - { - $errorMessages = []; - - if ($node instanceof AssignRef) { - $errorMessages[] = self::ERROR_MESSAGE; - } elseif ($node->byRef) { - $errorMessages[] = self::ERROR_MESSAGE; - } - - $paramErrorMessage = $this->collectParamErrorMessages($node, $scope); - $errorMessages = array_merge($errorMessages, $paramErrorMessage); - - return array_unique($errorMessages); - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -class SomeClass -{ - public function run(&$value) - { - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -class SomeClass -{ - public function run($value) - { - return $value; - } -} -CODE_SAMPLE - ), - ]); - } - - /** - * @return string[] - */ - private function collectParamErrorMessages(Node $node, Scope $scope): array - { - if (! $node instanceof Function_ && ! $node instanceof ClassMethod) { - return []; - } - - // has parent method? → skip it as enforced by parent - $methodName = (string) $node->name; - - $parentClassMethod = $this->parentClassMethodNodeResolver->resolveParentClassMethod($scope, $methodName); - if ($parentClassMethod instanceof ClassMethod) { - return []; - } - - $errorMessages = []; - foreach ($node->params as $param) { - /** @var Param $param */ - if (! $param->byRef) { - continue; - } - - $errorMessages[] = self::ERROR_MESSAGE; - } - - return $errorMessages; - } -} diff --git a/src/Rules/NoReturnArrayVariableListRule.php b/src/Rules/NoReturnArrayVariableListRule.php deleted file mode 100644 index 3e778502..00000000 --- a/src/Rules/NoReturnArrayVariableListRule.php +++ /dev/null @@ -1,167 +0,0 @@ -parentClassMethodNodeResolver = $parentClassMethodNodeResolver; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return Return_::class; - } - - /** - * @param Return_ $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if ($this->shouldSkip($scope, $node)) { - return []; - } - - /** @var Array_ $array */ - $array = $node->expr; - - $itemCount = count($array->items); - if ($itemCount < 2) { - return []; - } - - $exprCount = $this->resolveExprCount($array); - if ($exprCount < 2) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -class ReturnVariables -{ - public function run($value, $value2): array - { - return [$value, $value2]; - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -final class ReturnVariables -{ - public function run($value, $value2): ValueObject - { - return new ValueObject($value, $value2); - } -} -CODE_SAMPLE - ), - ]); - } - - private function shouldSkip(Scope $scope, Return_ $return): bool - { - // skip tests - if (Strings::match( - $scope->getFile(), - self::TESTS_DIRECTORY_REGEX - ) && ! StaticPHPUnitEnvironment::isPHPUnitRun()) { - return true; - } - - $namespace = $scope->getNamespace(); - if ($namespace === null) { - return true; - } - - if (strpos($namespace, 'Enum') !== false) { - return true; - } - - if (strpos($namespace, 'ValueObject') !== false) { - return true; - } - - if (! $return->expr instanceof Array_) { - return true; - } - - // guarded by parent method - - $functionLike = $scope->getFunction(); - if ($functionLike instanceof MethodReflection) { - $parentClassMethod = $this->parentClassMethodNodeResolver->resolveParentClassMethod( - $scope, - $functionLike->getName() - ); - - return $parentClassMethod instanceof ClassMethod; - } - - return false; - } - - private function resolveExprCount(Array_ $array): int - { - $exprCount = 0; - foreach ($array->items as $item) { - if (! $item instanceof ArrayItem) { - continue; - } - - if ($item->value instanceof New_) { - continue; - } - - ++$exprCount; - } - - return $exprCount; - } -} diff --git a/src/Rules/NoReturnFalseInNonBoolClassMethodRule.php b/src/Rules/NoReturnFalseInNonBoolClassMethodRule.php new file mode 100644 index 00000000..d8ea5028 --- /dev/null +++ b/src/Rules/NoReturnFalseInNonBoolClassMethodRule.php @@ -0,0 +1,78 @@ + + */ +final class NoReturnFalseInNonBoolClassMethodRule implements Rule +{ + /** + * @api + * @var string + */ + public const ERROR_MESSAGE = 'Returning false in non return bool class method. Use null with type|null instead or add bool return type'; + + private readonly NodeFinder $nodeFinder; + + public function __construct( + ) { + $this->nodeFinder = new NodeFinder(); + } + + /** + * @return class-string + */ + public function getNodeType(): string + { + return ClassMethod::class; + } + + /** + * @param ClassMethod $node + * @retur string[] + */ + public function processNode(Node $node, Scope $scope): array + { + if ($node->stmts === null) { + return []; + } + + if ($node->returnType instanceof Node) { + return []; + } + + /** @var Return_[] $returns */ + $returns = $this->nodeFinder->findInstanceOf($node->stmts, Return_::class); + + foreach ($returns as $return) { + if (! $return->expr instanceof Expr) { + continue; + } + + $exprType = $scope->getType($return->expr); + if (! $exprType instanceof ConstantBooleanType) { + continue; + } + + if ($exprType->getValue()) { + continue; + } + + return [self::ERROR_MESSAGE]; + } + + return []; + } +} diff --git a/src/Rules/NoReturnSetterMethodRule.php b/src/Rules/NoReturnSetterMethodRule.php deleted file mode 100644 index 2b0e8d84..00000000 --- a/src/Rules/NoReturnSetterMethodRule.php +++ /dev/null @@ -1,127 +0,0 @@ -typeAwareNodeFinder = $typeAwareNodeFinder; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return ClassMethod::class; - } - - /** - * @param ClassMethod $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classReflection = $scope->getClassReflection(); - if (! $classReflection instanceof ClassReflection) { - return []; - } - - if (! $classReflection->isClass()) { - return []; - } - - $classMethodName = $node->name->toString(); - if ($classMethodName === 'setUp') { - return []; - } - - if (! Strings::match($classMethodName, self::SETTER_START_REGEX)) { - return []; - } - - if (! $this->hasReturnReturnFunctionLike($node)) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -final class SomeClass -{ - private $name; - - public function setName(string $name): int - { - return 1000; - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -final class SomeClass -{ - private $name; - - public function setName(string $name): void - { - $this->name = $name; - } -} -CODE_SAMPLE - ), - ]); - } - - private function hasReturnReturnFunctionLike(ClassMethod $classMethod): bool - { - $returns = $this->typeAwareNodeFinder->findInstanceOf($classMethod, Return_::class); - foreach ($returns as $return) { - if ($return->expr !== null) { - return true; - } - } - - $yield = $this->typeAwareNodeFinder->findFirstInstanceOf($classMethod, Yield_::class); - return $yield instanceof Yield_; - } -} diff --git a/src/Rules/NoStaticPropertyRule.php b/src/Rules/NoStaticPropertyRule.php deleted file mode 100644 index f337bbe1..00000000 --- a/src/Rules/NoStaticPropertyRule.php +++ /dev/null @@ -1,104 +0,0 @@ - - */ - private const ALLOWED_TYPES = [ContainerInterface::class, Container::class, KernelInterface::class]; - /** - * @var \Symplify\PHPStanRules\TypeAnalyzer\ContainsTypeAnalyser - */ - private $containsTypeAnalyser; - - public function __construct(ContainsTypeAnalyser $containsTypeAnalyser) - { - $this->containsTypeAnalyser = $containsTypeAnalyser; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return StaticPropertyFetch::class; - } - - /** - * @param StaticPropertyFetch $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if ($this->isAbstractTestCase($scope)) { - return []; - } - - if ($this->containsTypeAnalyser->containsExprTypes($node, $scope, self::ALLOWED_TYPES)) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -final class SomeClass -{ - private static $customFileNames = []; -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -final class SomeClass -{ - private $customFileNames = []; -} -CODE_SAMPLE - ), - ]); - } - - private function isAbstractTestCase(Scope $scope): bool - { - $classReflection = $scope->getClassReflection(); - if (! $classReflection instanceof ClassReflection) { - return false; - } - - if (! $classReflection->isAbstract()) { - return false; - } - - return $classReflection->isSubclassOf(TestCase::class); - } -} diff --git a/src/Rules/NoVoidGetterMethodRule.php b/src/Rules/NoVoidGetterMethodRule.php deleted file mode 100644 index a1a0b155..00000000 --- a/src/Rules/NoVoidGetterMethodRule.php +++ /dev/null @@ -1,144 +0,0 @@ -> - */ - private const STOPPING_TYPES = [ - Return_::class, - Yield_::class, - // possibly unneded contract override - Throw_::class, - Node\Stmt\Throw_::class, - ]; - /** - * @var \Symplify\PHPStanRules\NodeFinder\TypeAwareNodeFinder - */ - private $typeAwareNodeFinder; - - public function __construct(TypeAwareNodeFinder $typeAwareNodeFinder) - { - $this->typeAwareNodeFinder = $typeAwareNodeFinder; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return ClassMethod::class; - } - - /** - * @param ClassMethod $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classReflection = $scope->getClassReflection(); - if (! $classReflection instanceof ClassReflection) { - return []; - } - - if (! $classReflection->isClass()) { - return []; - } - - if ($node->isAbstract()) { - return []; - } - - if (strncmp($node->name->toString(), 'get', strlen('get')) !== 0) { - return []; - } - - if (! $this->isVoidReturnClassMethod($node)) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -final class SomeClass -{ - public function getData(): void - { - // ... - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -final class SomeClass -{ - public function getData(): array - { - // ... - } -} -CODE_SAMPLE - ), - ]); - } - - private function isVoidReturnClassMethod(ClassMethod $classMethod): bool - { - if ($this->hasClassMethodVoidReturnType($classMethod)) { - return true; - } - - foreach (self::STOPPING_TYPES as $stoppingType) { - $foundNode = $this->typeAwareNodeFinder->findFirstInstanceOf($classMethod, $stoppingType); - if ($foundNode instanceof Node) { - return false; - } - } - - return true; - } - - private function hasClassMethodVoidReturnType(ClassMethod $classMethod): bool - { - if ($classMethod->returnType === null) { - return false; - } - - if (! $classMethod->returnType instanceof Identifier) { - return false; - } - - return $classMethod->returnType->toString() === 'void'; - } -} diff --git a/src/Rules/PHPUnit/NoRightPHPUnitAssertScalarRule.php b/src/Rules/PHPUnit/NoRightPHPUnitAssertScalarRule.php deleted file mode 100644 index ce11128e..00000000 --- a/src/Rules/PHPUnit/NoRightPHPUnitAssertScalarRule.php +++ /dev/null @@ -1,106 +0,0 @@ -name instanceof Identifier) { - return []; - } - - $methodName = $node->name->toString(); - if (! in_array($methodName, ['assertSame', 'assertEquals'], true)) { - return []; - } - - // is 2nd argument a scalar? should not be - $secondArg = $node->getArgs()[1]; - - $secondArgValue = $secondArg->value; - if (! $this->isScalarValue($secondArgValue)) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -use PHPUnit\Framework\TestCase; - -final class SomeFlippedAssert extends TestCase -{ - public function test() - { - $value = 1000; - $this->assertSame($value, 10); - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -use PHPUnit\Framework\TestCase; - -final class SomeFlippedAssert extends TestCase -{ - public function test() - { - $value = 1000; - $this->assertSame(10, $value); - } -} -CODE_SAMPLE - ), - ]); - } - - private function isScalarValue(Expr $expr): bool - { - if ($expr instanceof Scalar) { - return true; - } - - if ($expr instanceof ConstFetch) { - return true; - } - - return $expr instanceof ClassConstFetch; - } -} diff --git a/src/Rules/PreferredAttributeOverAnnotationRule.php b/src/Rules/PreferredAttributeOverAnnotationRule.php deleted file mode 100644 index d24a61ef..00000000 --- a/src/Rules/PreferredAttributeOverAnnotationRule.php +++ /dev/null @@ -1,122 +0,0 @@ -classAnnotationResolver = $classAnnotationResolver; - $this->annotations = $annotations; - } - - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return RuleError[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classLike = $node->getOriginalNode(); - if (! $classLike instanceof Class_) { - return []; - } - - $targetNodes = array_merge($classLike->getProperties(), $classLike->getMethods(), [$classLike]); - - $ruleErrors = []; - - foreach ($targetNodes as $targetNode) { - $classAnnotations = $this->classAnnotationResolver->resolveClassAnnotations($targetNode, $scope); - if ($classAnnotations === []) { - continue; - } - - $matchedAnnotations = array_intersect($classAnnotations, $this->annotations); - - foreach ($matchedAnnotations as $matchedAnnotation) { - $ruleErrors[] = RuleErrorBuilder::message(sprintf(self::ERROR_MESSAGE, $matchedAnnotation)) - ->line($targetNode->getLine()) - ->build(); - } - } - - return $ruleErrors; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new ConfiguredCodeSample( - <<<'CODE_SAMPLE' -use Symfony\Component\Routing\Annotation\Route; - -class SomeController -{ - /** - * @Route() - */ - public function action() - { - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -use Symfony\Component\Routing\Annotation\Route; - -class SomeController -{ - #[Route] - public function action() - { - } -} -CODE_SAMPLE - , - [ - 'annotations' => [Route::class], - ] - ), - ]); - } -} diff --git a/src/Rules/PreferredClassRule.php b/src/Rules/PreferredClassRule.php deleted file mode 100644 index 066901bd..00000000 --- a/src/Rules/PreferredClassRule.php +++ /dev/null @@ -1,173 +0,0 @@ -oldToPreferredClasses = $oldToPreferredClasses; - } - /** - * @return array> - */ - public function getNodeTypes(): array - { - return [New_::class, Name::class, InClassNode::class, StaticCall::class, Instanceof_::class]; - } - /** - * @param New_|Name|InClassNode|StaticCall|Instanceof_ $node - * @return string[] - */ - public function process(Node $node, Scope $scope): array - { - if ($node instanceof New_) { - return $this->processNew($node); - } - - if ($node instanceof InClassNode) { - return $this->processClass($node); - } - - if ($node instanceof StaticCall || $node instanceof Instanceof_) { - return $this->processExprWithClass($node); - } - - return $this->processClassName($node->toString()); - } - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new ConfiguredCodeSample( - <<<'CODE_SAMPLE' -class SomeClass -{ - public function run() - { - return new SplFileInfo('...'); - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -class SomeClass -{ - public function run() - { - return new CustomFileInfo('...'); - } -} -CODE_SAMPLE - , - [ - 'oldToPreferredClasses' => [ - SplFileInfo::class => 'CustomFileInfo', - ], - ] - ), - ]); - } - /** - * @return string[] - */ - private function processNew(New_ $new): array - { - if (! $new->class instanceof Name) { - return []; - } - - $className = $new->class->toString(); - return $this->processClassName($className); - } - /** - * @return string[] - */ - private function processClass(InClassNode $inClassNode): array - { - $classReflection = $inClassNode->getClassReflection(); - - $parentClassReflection = $classReflection->getParentClass(); - if (! $parentClassReflection instanceof ClassReflection) { - return []; - } - - $className = $classReflection->getName(); - - $parentClassName = $parentClassReflection->getName(); - foreach ($this->oldToPreferredClasses as $oldClass => $prefferedClass) { - if ($parentClassName !== $oldClass) { - continue; - } - - // check special case, when new class is actually the one we use - if ($prefferedClass === $className) { - return []; - } - - $errorMessage = sprintf(self::ERROR_MESSAGE, $oldClass, $prefferedClass); - return [$errorMessage]; - } - - return []; - } - /** - * @return string[] - */ - private function processClassName(string $className): array - { - foreach ($this->oldToPreferredClasses as $oldClass => $prefferedClass) { - if ($className !== $oldClass) { - continue; - } - - $errorMessage = sprintf(self::ERROR_MESSAGE, $oldClass, $prefferedClass); - return [$errorMessage]; - } - - return []; - } - /** - * @return string[] - * @param \PhpParser\Node\Expr\StaticCall|\PhpParser\Node\Expr\Instanceof_ $node - */ - private function processExprWithClass($node): array - { - if ($node->class instanceof Expr) { - return []; - } - - $className = (string) $node->class; - return $this->processClassName($className); - } -} diff --git a/src/Rules/PreferredRawDataInTestDataProviderRule.php b/src/Rules/PreferredRawDataInTestDataProviderRule.php deleted file mode 100644 index 553d96f9..00000000 --- a/src/Rules/PreferredRawDataInTestDataProviderRule.php +++ /dev/null @@ -1,192 +0,0 @@ -.*)\n?#'; - /** - * @var \PhpParser\NodeFinder - */ - private $nodeFinder; - - public function __construct(NodeFinder $nodeFinder) - { - $this->nodeFinder = $nodeFinder; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return RuleError[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classReflection = $scope->getClassReflection(); - if (! $classReflection instanceof ClassReflection) { - return []; - } - - if (! $classReflection->isSubclassOf(TestCase::class)) { - return []; - } - - $classLike = $node->getOriginalNode(); - if (! $classLike instanceof Class_) { - return []; - } - - $errorMessages = []; - - foreach ($classLike->getMethods() as $classMethod) { - if (! $classMethod->isPublic()) { - continue; - } - - $dataProviderClassMethod = $this->matchDataProviderMethodName($classLike, $classMethod); - if (! $dataProviderClassMethod instanceof ClassMethod) { - continue; - } - - if ($this->isSkipped($dataProviderClassMethod, $scope)) { - continue; - } - - $errorMessages[] = RuleErrorBuilder::message(self::ERROR_MESSAGE) - ->line($dataProviderClassMethod->getLine()) - ->build(); - } - - return $errorMessages; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -final class UseDataFromSetupInTestDataProviderTest extends TestCase -{ - private $data; - - protected function setUp(): void - { - $this->data = true; - } - - public function provideFoo() - { - yield [$this->data]; - } - - /** - * @dataProvider provideFoo - */ - public function testFoo($value) - { - $this->assertTrue($value); - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -use stdClass; - -final class UseRawDataForTestDataProviderTest -{ - private $obj; - - protected function setUp(): void - { - $this->obj = new stdClass; - } - - public function provideFoo() - { - yield [true]; - } - - /** - * @dataProvider provideFoo - */ - public function testFoo($value) - { - $this->obj->x = $value; - $this->assertTrue($this->obj->x); - } -} -CODE_SAMPLE - ), - ]); - } - - private function matchDataProviderMethodName(Class_ $class, ClassMethod $classMethod): ?ClassMethod - { - $docComment = $classMethod->getDocComment(); - if (! $docComment instanceof Doc) { - return null; - } - - $match = Strings::match($docComment->getText(), self::DATAPROVIDER_REGEX); - if (! $match) { - return null; - } - - $dataProviderMethodName = $match['dataProviderMethod']; - return $class->getMethod($dataProviderMethodName); - } - - private function isSkipped(ClassMethod $classMethod, Scope $scope): bool - { - /** @var Variable[] $variables */ - $variables = $this->nodeFinder->findInstanceOf((array) $classMethod->getStmts(), Variable::class); - foreach ($variables as $variable) { - $callerType = $scope->getType($variable); - if ($callerType instanceof ThisType) { - return false; - } - } - - return true; - } -} diff --git a/src/Rules/PrefixAbstractClassRule.php b/src/Rules/PrefixAbstractClassRule.php deleted file mode 100644 index eb7e0ec1..00000000 --- a/src/Rules/PrefixAbstractClassRule.php +++ /dev/null @@ -1,85 +0,0 @@ - - */ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classReflection = $node->getClassReflection(); - if ($classReflection->isAnonymous()) { - return []; - } - - $classLike = $node->getOriginalNode(); - if (! $classLike instanceof Class_) { - return []; - } - - if (! $classReflection->isAbstract()) { - return []; - } - - if (! $classLike->name instanceof Identifier) { - return []; - } - - $shortClassName = $classLike->name->toString(); - if (strncmp($shortClassName, 'Abstract', strlen('Abstract')) === 0) { - return []; - } - - return [sprintf(self::ERROR_MESSAGE, $shortClassName)]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -abstract class SomeClass -{ -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -abstract class AbstractSomeClass -{ -} -CODE_SAMPLE - ), - ]); - } -} diff --git a/src/Rules/PreventDuplicateClassMethodRule.php b/src/Rules/PreventDuplicateClassMethodRule.php deleted file mode 100644 index c8e88074..00000000 --- a/src/Rules/PreventDuplicateClassMethodRule.php +++ /dev/null @@ -1,153 +0,0 @@ - - */ -final class PreventDuplicateClassMethodRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'Content of method "%s()" is duplicated. Use unique content or service instead'; - /** - * @var int - */ - private $minimumLineCount = 3; - public function __construct(int $minimumLineCount = 3) - { - $this->minimumLineCount = $minimumLineCount; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return CollectedDataNode::class; - } - - /** - * @param CollectedDataNode $node - * @return RuleError[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classMethodsContentByFile = $node->get(ClassMethodContentCollector::class); - - $ruleErrors = []; - - $classMethodMetadatasByContentsHash = $this->groupClassMethodMetadatasByContentsHash( - $classMethodsContentByFile - ); - foreach ($classMethodMetadatasByContentsHash as $classMethodMetadatas) { - // keep only long enough methods - $classMethodMetadatas = array_filter( - $classMethodMetadatas, - function (ClassMethodMetadata $classMethodMetadata) : bool { - return $classMethodMetadata->getLineCount() >= $this->minimumLineCount; - } - ); - - // method is unique, we can skip it - if (count($classMethodMetadatas) === 1) { - continue; - } - - // report errors - /** @var ClassMethodMetadata $classMethodMetadata */ - foreach ($classMethodMetadatas as $classMethodMetadata) { - $errorMessage = sprintf(self::ERROR_MESSAGE, $classMethodMetadata->getMethodName()); - - $ruleErrors[] = RuleErrorBuilder::message($errorMessage) - ->file($classMethodMetadata->getFileName()) - ->line($classMethodMetadata->getLine()) - ->build(); - } - } - - return $ruleErrors; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new ConfiguredCodeSample( - <<<'CODE_SAMPLE' -class SomeClass -{ - public function someMethod() - { - echo 'statement'; - $value = new SmartFinder(); - } -} - -class AnotherClass -{ - public function someMethod() - { - echo 'statement'; - $differentValue = new SmartFinder(); - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -class SomeClass -{ - public function someMethod() - { - echo 'statement'; - $value = new SmartFinder(); - } -} -} -CODE_SAMPLE - , - [ - 'minimumLineCount' => 3, - ] - ), - ]); - } - - /** - * @param mixed[] $classMethodsContentByFile - * @return array - */ - private function groupClassMethodMetadatasByContentsHash(array $classMethodsContentByFile): array - { - $methodsNamesAndFilesByMethodContents = []; - - foreach ($classMethodsContentByFile as $fileName => $classMethodContents) { - foreach ($classMethodContents as [$methodName, $methodLine, $methodContents]) { - $methodContentsHash = md5($methodContents); - - $methodLineCount = substr_count($methodContents, "\n"); - - $methodsNamesAndFilesByMethodContents[$methodContentsHash][] = new ClassMethodMetadata($methodName, $methodLineCount, $fileName, $methodLine); - } - } - - return $methodsNamesAndFilesByMethodContents; - } -} diff --git a/src/Rules/PreventParentMethodVisibilityOverrideRule.php b/src/Rules/PreventParentMethodVisibilityOverrideRule.php deleted file mode 100644 index ea9e294e..00000000 --- a/src/Rules/PreventParentMethodVisibilityOverrideRule.php +++ /dev/null @@ -1,159 +0,0 @@ -reflectionProvider = $reflectionProvider; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return ClassMethod::class; - } - - /** - * @param ClassMethod $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if ($scope->getClassReflection() === null) { - return []; - } - - $classReflection = $scope->getClassReflection(); - $parentClassNames = $classReflection->getParentClassesNames(); - if ($parentClassNames === []) { - return []; - } - - $methodName = (string) $node->name; - foreach ($parentClassNames as $parentClassName) { - if (! $this->reflectionProvider->hasClass($parentClassName)) { - continue; - } - - $parentClassReflection = $this->reflectionProvider->getClass($parentClassName); - - if (! $parentClassReflection->hasMethod($methodName)) { - continue; - } - - $parentReflectionMethod = $parentClassReflection->getMethod($methodName, $scope); - if ($this->isClassMethodCompatibleWithParentReflectionMethod($node, $parentReflectionMethod)) { - return []; - } - - $methodVisibility = $this->resolveReflectionMethodVisibilityAsStrings($parentReflectionMethod); - - $errorMessage = sprintf(self::ERROR_MESSAGE, $methodName, $methodVisibility); - return [$errorMessage]; - } - - return []; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -class SomeParentClass -{ - public function run() - { - } -} - -class SomeClass -{ - protected function run() - { - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -class SomeParentClass -{ - public function run() - { - } -} - -class SomeClass -{ - public function run() - { - } -} -CODE_SAMPLE - ), - ]); - } - - private function isClassMethodCompatibleWithParentReflectionMethod( - ClassMethod $classMethod, - ExtendedMethodReflection $extendedMethodReflection - ): bool { - if ($extendedMethodReflection->isPublic() && $classMethod->isPublic()) { - return true; - } - - // see https://github.com/phpstan/phpstan/discussions/7456#discussioncomment-2927978 - $isProtectedMethod = ! $extendedMethodReflection->isPublic() && ! $extendedMethodReflection->isPrivate(); - if ($isProtectedMethod && $classMethod->isProtected()) { - return true; - } - - if (! $extendedMethodReflection->isPrivate()) { - return false; - } - - return $classMethod->isPrivate(); - } - - private function resolveReflectionMethodVisibilityAsStrings( - ExtendedMethodReflection $extendedMethodReflection - ): string { - if ($extendedMethodReflection->isPublic()) { - return 'public'; - } - - if ($extendedMethodReflection->isPrivate()) { - return 'private'; - } - - return 'protected'; - } -} diff --git a/src/Rules/Privatization/NoPublicPropertyByTypeRule.php b/src/Rules/Privatization/NoPublicPropertyByTypeRule.php deleted file mode 100644 index ee83de60..00000000 --- a/src/Rules/Privatization/NoPublicPropertyByTypeRule.php +++ /dev/null @@ -1,125 +0,0 @@ - - * - * @see \Symplify\PHPStanRules\Tests\Rules\Privatization\NoPublicPropertyByTypeRule\NoPublicPropertyByTypeRuleTest - */ -final class NoPublicPropertyByTypeRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'Class cannot have public properties. Use getter/setters instead'; - /** - * @var string[] - */ - private $classTypes; - /** - * @param string[] $classTypes - */ - public function __construct(array $classTypes) - { - $this->classTypes = $classTypes; - } - - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! $this->isClassMatch($node)) { - return []; - } - - $classLike = $node->getOriginalNode(); - if (! $classLike instanceof Class_) { - return []; - } - - if (! $this->hasClassPublicProperties($classLike)) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new ConfiguredCodeSample( - <<<'CODE_SAMPLE' -final class Person extends Entity -{ - public $name; -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -final class Person extends Entity -{ - private $name; - - public function getName() - { - return $this->name; - } -} -CODE_SAMPLE - , - [ - 'classTypes' => ['Entity'], - ] - ), - ]); - } - - private function hasClassPublicProperties(Class_ $class): bool - { - foreach ($class->getProperties() as $property) { - if ($property->isPublic()) { - return true; - } - } - - return false; - } - - private function isClassMatch(InClassNode $inClassNode): bool - { - $classReflection = $inClassNode->getClassReflection(); - if (! $classReflection->isClass()) { - return false; - } - - foreach ($this->classTypes as $classType) { - if (! $classReflection->isSubclassOf($classType)) { - continue; - } - - return true; - } - - return false; - } -} diff --git a/src/Rules/RegexSuffixInRegexConstantRule.php b/src/Rules/RegexSuffixInRegexConstantRule.php deleted file mode 100644 index a8b69985..00000000 --- a/src/Rules/RegexSuffixInRegexConstantRule.php +++ /dev/null @@ -1,158 +0,0 @@ -regexFuncCallAnalyzer = $regexFuncCallAnalyzer; - $this->regexStaticCallAnalyzer = $regexStaticCallAnalyzer; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return CallLike::class; - } - - /** - * @param Expr\CallLike $node - * @return mixed[]|string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if ($node instanceof FuncCall) { - return $this->processFuncCall($node); - } - - if ($node instanceof StaticCall) { - return $this->processStaticCall($node); - } - - return []; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -class SomeClass -{ - public const SOME_NAME = '#some\s+name#'; - - public function run($value) - { - $somePath = preg_match(self::SOME_NAME, $value); - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -class SomeClass -{ - public const SOME_NAME_REGEX = '#some\s+name#'; - - public function run($value) - { - $somePath = preg_match(self::SOME_NAME_REGEX, $value); - } -} -CODE_SAMPLE - ), - ]); - } - - /** - * @return string[] - */ - private function processConstantName(Expr $expr): array - { - if (! $expr instanceof ClassConstFetch) { - return []; - } - - if ($expr->name instanceof Expr) { - return []; - } - - $constantName = (string) $expr->name; - if (substr_compare($constantName, '_REGEX', -strlen('_REGEX')) === 0) { - return []; - } - - $errorMessage = sprintf(self::ERROR_MESSAGE, $constantName); - return [$errorMessage]; - } - - /** - * @return string[] - */ - private function processStaticCall(StaticCall $staticCall): array - { - if (! $this->regexStaticCallAnalyzer->isRegexStaticCall($staticCall)) { - return []; - } - - $argOrVariadicPlaceholder = $staticCall->args[1]; - if (! $argOrVariadicPlaceholder instanceof Arg) { - return []; - } - - return $this->processConstantName($argOrVariadicPlaceholder->value); - } - - /** - * @return string[] - */ - private function processFuncCall(FuncCall $funcCall): array - { - if (! $this->regexFuncCallAnalyzer->isRegexFuncCall($funcCall)) { - return []; - } - - $argOrVariadicPlaceholder = $funcCall->args[0]; - if (! $argOrVariadicPlaceholder instanceof Arg) { - return []; - } - - $firstArgValue = $argOrVariadicPlaceholder->value; - return $this->processConstantName($firstArgValue); - } -} diff --git a/src/Rules/RequireAttributeNameRule.php b/src/Rules/RequireAttributeNameRule.php deleted file mode 100644 index 9b5c14af..00000000 --- a/src/Rules/RequireAttributeNameRule.php +++ /dev/null @@ -1,92 +0,0 @@ - - */ -final class RequireAttributeNameRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'Attribute must have all names explicitly defined'; - - public function getNodeType(): string - { - return AttributeGroup::class; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -use Symfony\Component\Routing\Annotation\Route; - -class SomeController -{ - #[Route("/path")] - public function someAction() - { - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -use Symfony\Component\Routing\Annotation\Route; - -class SomeController -{ - #[Route(path: "/path")] - public function someAction() - { - } -} -CODE_SAMPLE - ), - ]); - } - - /** - * @param AttributeGroup $node - * @return RuleError[] - */ - public function processNode(Node $node, Scope $scope): array - { - $ruleErrors = []; - - foreach ($node->attrs as $attribute) { - $attributeName = $attribute->name->toString(); - if ($attributeName === Attribute::class) { - continue; - } - - foreach ($attribute->args as $arg) { - if ($arg->name !== null) { - continue; - } - - $ruleErrors[] = RuleErrorBuilder::message(self::ERROR_MESSAGE) - ->line($attribute->getLine()) - ->build(); - } - } - - return $ruleErrors; - } -} diff --git a/src/Rules/Explicit/RequireSpecificReturnTypeOverAbstractRule.php b/src/Rules/RequireSpecificReturnTypeOverAbstractRule.php similarity index 64% rename from src/Rules/Explicit/RequireSpecificReturnTypeOverAbstractRule.php rename to src/Rules/RequireSpecificReturnTypeOverAbstractRule.php index 866d1d8d..75e486b7 100644 --- a/src/Rules/Explicit/RequireSpecificReturnTypeOverAbstractRule.php +++ b/src/Rules/RequireSpecificReturnTypeOverAbstractRule.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Rules\Explicit; +namespace Rector\TypePerfect\Rules; use PhpParser\Node; use PhpParser\Node\Expr; @@ -14,14 +14,12 @@ use PHPStan\Type\ObjectType; use PHPStan\Type\Type; use PHPStan\Type\TypeWithClassName; -use Symplify\PHPStanRules\NodeFinder\ReturnNodeFinder; -use Symplify\PHPStanRules\Reflection\MethodNodeAnalyser; -use Symplify\RuleDocGenerator\Contract\DocumentedRuleInterface; -use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; -use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; +use Rector\TypePerfect\NodeFinder\ReturnNodeFinder; +use Rector\TypePerfect\Reflection\MethodNodeAnalyser; /** - * @see \Symplify\PHPStanRules\Tests\Rules\Explicit\RequireSpecificReturnTypeOverAbstractRule\RequireSpecificReturnTypeOverAbstractRuleTest + * @see \Rector\TypePerfect\Tests\Rules\RequireSpecificReturnTypeOverAbstractRule\RequireSpecificReturnTypeOverAbstractRuleTest + * @implements Rule */ final class RequireSpecificReturnTypeOverAbstractRule implements Rule { @@ -29,54 +27,11 @@ final class RequireSpecificReturnTypeOverAbstractRule implements Rule * @var string */ public const ERROR_MESSAGE = 'Provide more specific return type "%s" over abstract one'; - /** - * @var \Symplify\PHPStanRules\NodeFinder\ReturnNodeFinder - */ - private $returnNodeFinder; - /** - * @var \Symplify\PHPStanRules\Reflection\MethodNodeAnalyser - */ - private $methodNodeAnalyser; - public function __construct(ReturnNodeFinder $returnNodeFinder, MethodNodeAnalyser $methodNodeAnalyser) - { - $this->returnNodeFinder = $returnNodeFinder; - $this->methodNodeAnalyser = $methodNodeAnalyser; - } - public function getRuleDefinition(): RuleDefinition - { - // @see https://stitcher.io/blog/php-8-named-arguments#named-arguments-in-depth - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -final class IssueControlFactory -{ - public function create(): Control - { - return new IssueControl(); - } -} - -final class IssueControl extends Control -{ -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -final class IssueControlFactory -{ - public function create(): IssueControl - { - return new IssueControl(); - } -} - -final class IssueControl extends Control -{ -} -CODE_SAMPLE - ), - ]); + public function __construct( + private readonly ReturnNodeFinder $returnNodeFinder, + private readonly MethodNodeAnalyser $methodNodeAnalyser, + ) { } /** diff --git a/src/Rules/RequireStringRegexMatchKeyRule.php b/src/Rules/RequireStringRegexMatchKeyRule.php deleted file mode 100644 index c31714ba..00000000 --- a/src/Rules/RequireStringRegexMatchKeyRule.php +++ /dev/null @@ -1,182 +0,0 @@ -nodeFinder = $nodeFinder; - $this->reflectionParser = $reflectionParser; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return Assign::class; - } - - /** - * @param Assign $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if ($this->shouldSkipExpr($node->expr)) { - return []; - } - - if (! $node->var instanceof Variable) { - return []; - } - - $functionReflection = $scope->getFunction(); - if (! $functionReflection instanceof MethodReflection) { - return []; - } - - $classMethod = $this->reflectionParser->parseMethodReflection($functionReflection); - if (! $classMethod instanceof ClassMethod) { - return []; - } - - $usedAsArrayDimFetches = $this->findVariableArrayDimFetches($classMethod, $node->var); - if ($usedAsArrayDimFetches === []) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -use Nette\Utils\Strings; - -class SomeClass -{ - private const REGEX = '#(a content)#'; - - public function run() - { - $matches = Strings::match('a content', self::REGEX); - if ($matches) { - echo $matches[1]; - } - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -use Nette\Utils\Strings; - -class SomeClass -{ - private const REGEX = '#(?a content)#'; - - public function run() - { - $matches = Strings::match('a content', self::REGEX); - if ($matches) { - echo $matches['content']; - } - } -} -CODE_SAMPLE - ), - ]); - } - - /** - * @return ArrayDimFetch[] - */ - private function findVariableArrayDimFetches(ClassMethod $classMethod, Variable $variable): array - { - if (! is_string($variable->name)) { - return []; - } - - $variableName = $variable->name; - - return $this->nodeFinder->find($classMethod, static function (Node $node) use ($variableName): bool { - if (! $node instanceof ArrayDimFetch) { - return false; - } - - if (! $node->var instanceof Variable) { - return false; - } - - if (! $node->dim instanceof LNumber) { - return false; - } - - if (! is_string($node->var->name)) { - return false; - } - - return $node->var->name === $variableName; - }); - } - - private function shouldSkipExpr(Expr $expr): bool - { - if (! $expr instanceof StaticCall) { - return true; - } - - if (! $expr->class instanceof Name) { - return true; - } - - if ($expr->class->toString() !== 'Nette\Utils\Strings') { - return true; - } - - if (! $expr->name instanceof Identifier) { - return true; - } - - return $expr->name->toString() !== 'match'; - } -} diff --git a/src/Rules/RequireThisCallOnLocalMethodRule.php b/src/Rules/RequireThisCallOnLocalMethodRule.php deleted file mode 100644 index 2446aaa5..00000000 --- a/src/Rules/RequireThisCallOnLocalMethodRule.php +++ /dev/null @@ -1,137 +0,0 @@ - - */ -final class RequireThisCallOnLocalMethodRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'Use "$this->()" instead of "self::()" to call local method'; - /** - * @var \PhpParser\NodeFinder - */ - private $nodeFinder; - - public function __construct(NodeFinder $nodeFinder) - { - $this->nodeFinder = $nodeFinder; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return RuleError[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classLike = $node->getOriginalNode(); - if (! $classLike instanceof Class_) { - return []; - } - - $errorMessages = []; - - /** @var StaticCall[] $staticCalls */ - $staticCalls = $this->nodeFinder->findInstanceOf($classLike, StaticCall::class); - foreach ($staticCalls as $staticCall) { - if (! $staticCall->class instanceof Name) { - continue; - } - - $staticCallClass = $staticCall->class->toString(); - if ($staticCallClass !== 'self') { - continue; - } - - $classMethod = $this->getClassMethodInCurrentClass($staticCall, $classLike); - if (! $classMethod instanceof ClassMethod) { - continue; - } - - if ($classMethod->isStatic()) { - continue; - } - - $errorMessages[] = RuleErrorBuilder::message(self::ERROR_MESSAGE) - ->line($staticCall->getLine()) - ->build(); - } - - return $errorMessages; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -class SomeClass -{ - public function run() - { - self::execute(); - } - - private function execute() - { - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -class SomeClass -{ - public function run() - { - $this->execute(); - } - - private function execute() - { - } -} -CODE_SAMPLE - ), - ]); - } - - private function getClassMethodInCurrentClass(StaticCall $staticCall, Class_ $class): ?ClassMethod - { - if (! $staticCall->name instanceof Identifier) { - return null; - } - - $staticCallName = $staticCall->name->toString(); - return $class->getMethod($staticCallName); - } -} diff --git a/src/Rules/RequireThisOnParentMethodCallRule.php b/src/Rules/RequireThisOnParentMethodCallRule.php deleted file mode 100644 index 7d19a822..00000000 --- a/src/Rules/RequireThisOnParentMethodCallRule.php +++ /dev/null @@ -1,154 +0,0 @@ - - */ -final class RequireThisOnParentMethodCallRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'Use "$this->()" instead of "parent::()" unless in the same named method'; - /** - * @var \PhpParser\NodeFinder - */ - private $nodeFinder; - - public function __construct(NodeFinder $nodeFinder) - { - $this->nodeFinder = $nodeFinder; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return RuleError[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classLike = $node->getOriginalNode(); - if (! $classLike instanceof Class_) { - return []; - } - - $errorMessages = []; - - foreach ($classLike->getMethods() as $classMethod) { - /** @var StaticCall[] $staticCalls */ - $staticCalls = $this->nodeFinder->findInstanceOf($classMethod, StaticCall::class); - - foreach ($staticCalls as $staticCall) { - if ($this->isParentCallInSameClassMethod($staticCall, $classMethod)) { - continue; - } - - if (! $staticCall->name instanceof Identifier) { - continue; - } - - $staticCallMethodName = $staticCall->name->toString(); - if ($this->doesMethodExistsInCurrentClass($classLike, $staticCallMethodName)) { - continue; - } - - $errorMessages[] = RuleErrorBuilder::message(self::ERROR_MESSAGE) - ->line($staticCall->getLine()) - ->build(); - } - } - - return $errorMessages; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -class SomeParentClass -{ - public function run() - { - } -} - -class SomeClass extends SomeParentClass -{ - public function go() - { - parent::run(); - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -class SomeParentClass -{ - public function run() - { - } -} - -class SomeClass extends SomeParentClass -{ - public function go() - { - $this->run(); - } -} -CODE_SAMPLE - ), - ]); - } - - private function doesMethodExistsInCurrentClass(Class_ $class, string $methodName): bool - { - $classMethod = $class->getMethod($methodName); - return $classMethod instanceof ClassMethod; - } - - private function isParentCallInSameClassMethod(StaticCall $staticCall, ClassMethod $classMethod): bool - { - if (! $staticCall->class instanceof Name) { - return false; - } - - if ($staticCall->class->toString() !== 'parent') { - return true; - } - - if (! $staticCall->name instanceof Identifier) { - return false; - } - - return $classMethod->name->toString() === $staticCall->name->toString(); - } -} diff --git a/src/Rules/RequiredAbstractClassKeywordRule.php b/src/Rules/RequiredAbstractClassKeywordRule.php deleted file mode 100644 index 12db32df..00000000 --- a/src/Rules/RequiredAbstractClassKeywordRule.php +++ /dev/null @@ -1,75 +0,0 @@ - - */ - public function getNodeType(): string - { - return Class_::class; - } - - /** - * @param Class_ $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if ($node->isAbstract()) { - return []; - } - - // skip anonymous class - if (! $node->name instanceof Identifier) { - return []; - } - - $shortClassName = $node->name->toString(); - if (strncmp($shortClassName, 'Abstract', strlen('Abstract')) !== 0) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -class AbstractClass -{ -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -abstract class AbstractClass -{ -} -CODE_SAMPLE - ), - ]); - } -} diff --git a/src/Rules/SeeAnnotationToTestRule.php b/src/Rules/SeeAnnotationToTestRule.php deleted file mode 100644 index d6666d40..00000000 --- a/src/Rules/SeeAnnotationToTestRule.php +++ /dev/null @@ -1,160 +0,0 @@ -phpDocResolver = $phpDocResolver; - $this->seePhpDocTagNodesFinder = $seePhpDocTagNodesFinder; - $this->requiredSeeTypes = $requiredSeeTypes; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - $classReflection = $node->getClassReflection(); - if ($this->shouldSkipClassReflection($classReflection)) { - return []; - } - - $classLike = $node->getOriginalNode(); - if (! $classLike instanceof Class_) { - return []; - } - - $docComment = $node->getDocComment(); - $errorMessage = sprintf(self::ERROR_MESSAGE, $classReflection->getName()); - if (! $docComment instanceof Doc) { - return [$errorMessage]; - } - - $resolvedPhpDocBlock = $this->phpDocResolver->resolve($scope, $classReflection, $docComment); - - // skip deprectaed - $deprecatedTags = $resolvedPhpDocBlock->getDeprecatedTag(); - if ($deprecatedTags !== null) { - return []; - } - - $seeTags = $this->seePhpDocTagNodesFinder->find($resolvedPhpDocBlock); - if ($this->hasSeeTestCaseAnnotation($seeTags)) { - return []; - } - - return [$errorMessage]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new ConfiguredCodeSample( - <<<'CODE_SAMPLE' -class SomeClass extends Rule -{ -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -/** - * @see SomeClassTest - */ -class SomeClass extends Rule -{ -} -CODE_SAMPLE - , - [ - 'requiredSeeTypes' => ['Rule'], - ] - ), - ]); - } - - private function shouldSkipClassReflection(ClassReflection $classReflection): bool - { - if ($classReflection->isAbstract()) { - return true; - } - - foreach ($this->requiredSeeTypes as $requiredSeeType) { - if ($classReflection->isSubclassOf($requiredSeeType)) { - return false; - } - } - - return true; - } - - /** - * @param PhpDocTagNode[] $seeTags - */ - private function hasSeeTestCaseAnnotation(array $seeTags): bool - { - foreach ($seeTags as $seeTag) { - if (! $seeTag->value instanceof GenericTagValueNode) { - continue; - } - - if (is_a($seeTag->value->value, TestCase::class, true)) { - return true; - } - } - - return false; - } -} diff --git a/src/Rules/Spotter/IfElseToMatchSpotterRule.php b/src/Rules/Spotter/IfElseToMatchSpotterRule.php deleted file mode 100644 index 125c8aae..00000000 --- a/src/Rules/Spotter/IfElseToMatchSpotterRule.php +++ /dev/null @@ -1,184 +0,0 @@ -ifElseBranchAnalyzer = $ifElseBranchAnalyzer; - $this->ifResemblingMatchAnalyzer = $ifResemblingMatchAnalyzer; - $this->cacheIfAnalyzer = $cacheIfAnalyzer; - } - - /** - * @return class-string - */ - public function getNodeType(): string - { - return If_::class; - } - - /** - * @param If_ $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - // always need else - if (! $node->else instanceof Else_) { - return []; - } - - // at least 3 options in total, so we don't match simple if/else - if ($node->elseifs === []) { - return []; - } - - $branches = $this->mergeIfElseBranches($node); - - $ifsAndConds = []; - foreach ($branches as $branch) { - // must be exactly single item - if (count($branch->stmts) !== 1) { - return []; - } - - // the conditioned parameters must be the same - if ($branch instanceof If_ || $branch instanceof ElseIf_) { - $ifsAndConds[] = new IfAndCondExpr($branch->stmts[0], $branch->cond); - - continue; - } - - $ifsAndConds[] = new IfAndCondExpr($branch->stmts[0], null); - } - - if ($this->shouldSkipIfsAndConds($ifsAndConds, $node)) { - return []; - } - - $returnAndAssignBranchCounts = $this->ifElseBranchAnalyzer->resolveBranchTypesToCount($ifsAndConds); - - $branchCount = count($branches); - - if (! $this->isUnitedMatchingBranchType($returnAndAssignBranchCounts, $branchCount)) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -class SomeClass -{ - public function spot($value) - { - if ($value === 100) { - $items = ['yes']; - } else { - $items = ['no']; - } - - return $items; - } -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -class SomeClass -{ - public function spot($value) - { - return match($value) { - 100 => ['yes'], - default => ['no'], - }; - } -} -CODE_SAMPLE - ), - ]); - } - - private function isUnitedMatchingBranchType( - ReturnAndAssignBranchCounts $returnAndAssignBranchCounts, - int $branchCount - ): bool { - if ($returnAndAssignBranchCounts->getAssignTypeCount() === $branchCount) { - return true; - } - - return $returnAndAssignBranchCounts->getReturnTypeCount() === $branchCount; - } - - /** - * @return array - */ - private function mergeIfElseBranches(If_ $if): array - { - // all branches must have return or assign - at the same time - - /** @var array $branches */ - $branches = array_merge([$if], $if->elseifs); - if ($if->else instanceof Else_) { - $branches[] = $if->else; - } - - return $branches; - } - - /** - * @param IfAndCondExpr[] $ifsAndConds - */ - private function shouldSkipIfsAndConds(array $ifsAndConds, If_ $if): bool - { - if (! $this->ifResemblingMatchAnalyzer->isUniqueCompareBinaryConds($ifsAndConds)) { - return true; - } - - return $this->cacheIfAnalyzer->isDefaultNullAssign($if); - } -} diff --git a/src/Rules/Spotter/SwitchToMatchSpotterRule.php b/src/Rules/Spotter/SwitchToMatchSpotterRule.php deleted file mode 100644 index ad2d9578..00000000 --- a/src/Rules/Spotter/SwitchToMatchSpotterRule.php +++ /dev/null @@ -1,122 +0,0 @@ - - */ - public function getNodeType(): string - { - return Switch_::class; - } - - /** - * @param Switch_ $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! $this->hasDefaultCase($node)) { - return []; - } - - if (! $this->isMatchingSwitch($node)) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -switch ($key) { - case 1: - return 100; - case 2: - return 200; - default: - return 300; -}; -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -return match($key) { - 1 => 100, - 2 => 200, - default => 300, -}; -CODE_SAMPLE - ), - ]); - } - - private function hasDefaultCase(Switch_ $switch): bool - { - foreach ($switch->cases as $case) { - if ($case->cond === null) { - return true; - } - } - - return false; - } - - private function isMatchingSwitch(Switch_ $switch): bool - { - foreach ($switch->cases as $case) { - if ($case->cond === null) { - continue; - } - - // no stmts, merged with another case - if ($case->stmts === []) { - continue; - } - - // must be exact 1 stmts - if (count($case->stmts) !== 1) { - continue; - } - - $onlyStmt = $case->stmts[0]; - if ($onlyStmt instanceof Return_ && $onlyStmt->expr !== null) { - continue; - } - - if ($onlyStmt instanceof Throw_) { - continue; - } - - return false; - } - - return true; - } -} diff --git a/src/Rules/SuffixInterfaceRule.php b/src/Rules/SuffixInterfaceRule.php deleted file mode 100644 index 31f5f2cb..00000000 --- a/src/Rules/SuffixInterfaceRule.php +++ /dev/null @@ -1,73 +0,0 @@ - - */ - public function getNodeType(): string - { - return ClassLike::class; - } - - /** - * @param ClassLike $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (substr_compare((string) $node->name, 'Interface', -strlen('Interface')) === 0) { - if (! $node instanceof Interface_) { - return [self::ERROR_MESSAGE]; - } - - return []; - } - - if ($node instanceof Interface_) { - return [self::ERROR_MESSAGE]; - } - - return []; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -interface SomeClass -{ -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -interface SomeInterface -{ -} -CODE_SAMPLE - ), - ]); - } -} diff --git a/src/Rules/SuffixTraitRule.php b/src/Rules/SuffixTraitRule.php deleted file mode 100644 index 69129b47..00000000 --- a/src/Rules/SuffixTraitRule.php +++ /dev/null @@ -1,74 +0,0 @@ - - */ - public function getNodeType(): string - { - return ClassLike::class; - } - - /** - * @param ClassLike $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - $traitName = (string) $node->name; - if (substr_compare($traitName, 'Trait', -strlen('Trait')) === 0) { - if ($node instanceof Trait_) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - if ($node instanceof Trait_) { - return [self::ERROR_MESSAGE]; - } - - return []; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -trait SomeClass -{ -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -trait SomeTrait -{ -} -CODE_SAMPLE - ), - ]); - } -} diff --git a/src/Rules/UppercaseConstantRule.php b/src/Rules/UppercaseConstantRule.php deleted file mode 100644 index cce7d720..00000000 --- a/src/Rules/UppercaseConstantRule.php +++ /dev/null @@ -1,72 +0,0 @@ - - */ - public function getNodeType(): string - { - return ClassConst::class; - } - - /** - * @param ClassConst $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - foreach ($node->consts as $const) { - $constantName = (string) $const->name; - if (strtoupper($constantName) === $constantName) { - continue; - } - - $errorMessage = sprintf(self::ERROR_MESSAGE, $constantName); - return [$errorMessage]; - } - - return []; - } - - public function getRuleDefinition(): RuleDefinition - { - return new RuleDefinition(self::ERROR_MESSAGE, [ - new CodeSample( - <<<'CODE_SAMPLE' -final class SomeClass -{ - public const some = 'value'; -} -CODE_SAMPLE - , - <<<'CODE_SAMPLE' -final class SomeClass -{ - public const SOME = 'value'; -} -CODE_SAMPLE - ), - ]); - } -} diff --git a/src/TypeAnalyzer/ArrayShapeDetector.php b/src/TypeAnalyzer/ArrayShapeDetector.php deleted file mode 100644 index 3cbb43ed..00000000 --- a/src/TypeAnalyzer/ArrayShapeDetector.php +++ /dev/null @@ -1,50 +0,0 @@ -getType($expr); - if (! $exprType instanceof ConstantArrayType) { - return false; - } - - // empty array - if ($exprType->getIterableKeyType() instanceof NeverType) { - return false; - } - - return ! $this->hasConstantIntegerKeys($exprType); - } - - private function hasConstantIntegerKeys(ConstantArrayType $constantArrayType): bool - { - if ($constantArrayType->getKeyType() instanceof ConstantIntegerType) { - return true; - } - - if ($constantArrayType->getKeyType() instanceof UnionType) { - $keyType = $constantArrayType->getKeyType(); - foreach ($keyType->getTypes() as $unionedType) { - if (! $unionedType instanceof ConstantIntegerType) { - return false; - } - } - - return true; - } - - return false; - } -} diff --git a/src/TypeAnalyzer/CallableTypeAnalyzer.php b/src/TypeAnalyzer/CallableTypeAnalyzer.php deleted file mode 100644 index 196d09ab..00000000 --- a/src/TypeAnalyzer/CallableTypeAnalyzer.php +++ /dev/null @@ -1,42 +0,0 @@ -getType($expr); - $unwrappedNameStaticType = TypeCombinator::removeNull($nameStaticType); - - if ($unwrappedNameStaticType instanceof CallableType) { - return true; - } - - if ($unwrappedNameStaticType instanceof ClosureType) { - return true; - } - - return $this->isInvokableObjectType($unwrappedNameStaticType); - } - - private function isInvokableObjectType(Type $type): bool - { - if (! $type instanceof ObjectType) { - return false; - } - - return $type->hasMethod(MethodName::INVOKE)->yes(); - } -} diff --git a/src/TypeAnalyzer/ContainsTypeAnalyser.php b/src/TypeAnalyzer/ContainsTypeAnalyser.php deleted file mode 100644 index 3950d78a..00000000 --- a/src/TypeAnalyzer/ContainsTypeAnalyser.php +++ /dev/null @@ -1,117 +0,0 @@ -containsExprType($expr, $scope, $type)) { - continue; - } - - return true; - } - - return false; - } - - /** - * @param class-string $type - */ - public function containsExprType(Expr $expr, Scope $scope, string $type): bool - { - $exprType = $scope->getType($expr); - return $this->containsTypeExprType($exprType, $type); - } - - /** - * @param class-string $type - */ - private function containsTypeExprType(Type $exprType, string $type): bool - { - if ($exprType instanceof IntersectionType) { - $intersectionedTypes = $exprType->getTypes(); - foreach ($intersectionedTypes as $intersectionedType) { - if ($this->isExprTypeOfType($intersectionedType, $type)) { - return true; - } - } - } - - return $this->isExprTypeOfType($exprType, $type); - } - - /** - * @param class-string $class - */ - private function isUnionTypeWithClass(Type $type, string $class): bool - { - if (! $type instanceof UnionType) { - return false; - } - - $unionedTypes = $type->getTypes(); - foreach ($unionedTypes as $unionedType) { - if (! $unionedType instanceof TypeWithClassName) { - continue; - } - - if (is_a($unionedType->getClassName(), $class, true)) { - return true; - } - } - - return false; - } - - /** - * @param class-string $type - */ - private function isArrayWithItemType(Type $propertyType, string $type): bool - { - if (! $propertyType instanceof ArrayType) { - return false; - } - - $arrayItemType = $propertyType->getItemType(); - if (! $arrayItemType instanceof TypeWithClassName) { - return false; - } - - return is_a($arrayItemType->getClassName(), $type, true); - } - - /** - * @param class-string $type - */ - private function isExprTypeOfType(Type $exprType, string $type): bool - { - if ($exprType instanceof TypeWithClassName) { - return is_a($exprType->getClassName(), $type, true); - } - - if ($this->isUnionTypeWithClass($exprType, $type)) { - return true; - } - - return $this->isArrayWithItemType($exprType, $type); - } -} diff --git a/src/TypeAnalyzer/MatchingTypeAnalyzer.php b/src/TypeAnalyzer/MatchingTypeAnalyzer.php deleted file mode 100644 index 24e52db3..00000000 --- a/src/TypeAnalyzer/MatchingTypeAnalyzer.php +++ /dev/null @@ -1,75 +0,0 @@ -isUnionTypeMatch($argType, $expectedType)) { - return true; - } - - // special case for __toString() object - if ($this->isMatchingToStringObjectType($argType, $expectedType)) { - return true; - } - - if ($expectedType->isSuperTypeOf($argType)->yes()) { - return true; - } - - // handle "$%s" - if ($argType instanceof ErrorType) { - return true; - } - } - - return false; - } - - private function isMatchingToStringObjectType(Type $argType, Type $expectedType): bool - { - if (! $expectedType instanceof StringType) { - return false; - } - - if (! $argType instanceof ObjectType) { - return false; - } - - return $argType->hasMethod('__toString') - ->yes(); - } - - private function isUnionTypeMatch(Type $argType, Type $expectedType): bool - { - if (! $argType instanceof UnionType) { - return false; - } - - foreach ($argType->getTypes() as $unionedArgType) { - if ($expectedType->isSuperTypeOf($unionedArgType)->yes()) { - return true; - } - - if ($this->isMatchingToStringObjectType($unionedArgType, $expectedType)) { - return true; - } - } - - return false; - } -} diff --git a/src/TypeResolver/ArgTypeResolver.php b/src/TypeResolver/ArgTypeResolver.php deleted file mode 100644 index 63caebb8..00000000 --- a/src/TypeResolver/ArgTypeResolver.php +++ /dev/null @@ -1,28 +0,0 @@ -getArgs(); - unset($args[0]); - - $argTypes = []; - foreach ($args as $arg) { - $argTypes[] = $scope->getType($arg->value); - } - - return $argTypes; - } -} diff --git a/src/TypeResolver/ClassMethodReturnTypeResolver.php b/src/TypeResolver/ClassMethodReturnTypeResolver.php deleted file mode 100644 index a49509d2..00000000 --- a/src/TypeResolver/ClassMethodReturnTypeResolver.php +++ /dev/null @@ -1,35 +0,0 @@ -name->toString(); - - $classReflection = $scope->getClassReflection(); - if (! $classReflection instanceof ClassReflection) { - return new MixedType(); - } - - $extendedMethodReflection = $classReflection->getMethod($methodName, $scope); - - $parametersAcceptor = ParametersAcceptorSelector::selectSingle($extendedMethodReflection->getVariants()); - if (! $parametersAcceptor instanceof FunctionVariant) { - return new MixedType(); - } - - return $parametersAcceptor->getReturnType(); - } -} diff --git a/src/ValueObject/ClassConstRegexMetadata.php b/src/ValueObject/ClassConstRegexMetadata.php deleted file mode 100644 index 05987c40..00000000 --- a/src/ValueObject/ClassConstRegexMetadata.php +++ /dev/null @@ -1,52 +0,0 @@ -constantName = $constantName; - $this->regexValue = $regexValue; - $this->filePath = $filePath; - $this->line = $line; - } - - public function getConstantName(): string - { - return $this->constantName; - } - - public function getFilePath(): string - { - return $this->filePath; - } - - public function getRegexValue(): string - { - return $this->regexValue; - } - - public function getLine(): int - { - return $this->line; - } -} diff --git a/src/ValueObject/ClassNamespaceAndDirectory.php b/src/ValueObject/ClassNamespaceAndDirectory.php deleted file mode 100644 index 064a15d4..00000000 --- a/src/ValueObject/ClassNamespaceAndDirectory.php +++ /dev/null @@ -1,42 +0,0 @@ -namespace = $namespace; - $this->directory = $directory; - $this->namespaceBeforeClass = $namespaceBeforeClass; - } - - public function getNamespace(): string - { - return $this->namespace; - } - - public function getSingleDirectory(): string - { - return $this->directory; - } - - public function getNamespaceBeforeClass(): string - { - return $this->namespaceBeforeClass; - } -} diff --git a/src/ValueObject/Configuration/RequiredWithMessage.php b/src/ValueObject/Configuration/RequiredWithMessage.php deleted file mode 100644 index f6bf1eda..00000000 --- a/src/ValueObject/Configuration/RequiredWithMessage.php +++ /dev/null @@ -1,32 +0,0 @@ -required = $required; - $this->message = $message; - } - - public function getRequired(): string - { - return $this->required; - } - - public function getMessage(): ?string - { - return $this->message; - } -} diff --git a/src/ValueObject/Metadata/ClassMethodMetadata.php b/src/ValueObject/Metadata/ClassMethodMetadata.php deleted file mode 100644 index 551df8c4..00000000 --- a/src/ValueObject/Metadata/ClassMethodMetadata.php +++ /dev/null @@ -1,51 +0,0 @@ -methodName = $methodName; - $this->lineCount = $lineCount; - $this->fileName = $fileName; - $this->line = $line; - } - public function getFileName(): string - { - return $this->fileName; - } - - public function getMethodName(): string - { - return $this->methodName; - } - - public function getLine(): int - { - return $this->line; - } - - public function getLineCount(): int - { - return $this->lineCount; - } -} diff --git a/src/ValueObject/MethodCallReference.php b/src/ValueObject/MethodCallReference.php index 61644d2f..bb454c16 100644 --- a/src/ValueObject/MethodCallReference.php +++ b/src/ValueObject/MethodCallReference.php @@ -2,22 +2,14 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\ValueObject; +namespace Rector\TypePerfect\ValueObject; final class MethodCallReference { - /** - * @var string - */ - private $class; - /** - * @var string - */ - private $method; - public function __construct(string $class, string $method) - { - $this->class = $class; - $this->method = $method; + public function __construct( + private readonly string $class, + private readonly string $method + ) { } public function getClass(): string diff --git a/src/ValueObject/Regex.php b/src/ValueObject/Regex.php deleted file mode 100644 index b0a01d3d..00000000 --- a/src/ValueObject/Regex.php +++ /dev/null @@ -1,14 +0,0 @@ -stmt = $stmt; - $this->condExpr = $condExpr; - } - - public function getStmt(): Stmt - { - return $this->stmt; - } - - public function getCondExpr(): ?Expr - { - return $this->condExpr; - } -} diff --git a/src/ValueObject/Spotter/ReturnAndAssignBranchCounts.php b/src/ValueObject/Spotter/ReturnAndAssignBranchCounts.php deleted file mode 100644 index e1345c30..00000000 --- a/src/ValueObject/Spotter/ReturnAndAssignBranchCounts.php +++ /dev/null @@ -1,32 +0,0 @@ -returnTypeCount = $returnTypeCount; - $this->assignTypeCount = $assignTypeCount; - } - - public function getReturnTypeCount(): int - { - return $this->returnTypeCount; - } - - public function getAssignTypeCount(): int - { - return $this->assignTypeCount; - } -} diff --git a/src/ValueObject/VariableNameMetadata.php b/src/ValueObject/VariableNameMetadata.php deleted file mode 100644 index 31fa059f..00000000 --- a/src/ValueObject/VariableNameMetadata.php +++ /dev/null @@ -1,42 +0,0 @@ -variableName = $variableName; - $this->filePath = $filePath; - $this->lineNumber = $lineNumber; - } - - public function getVariableName(): string - { - return $this->variableName; - } - - public function getFilePath(): string - { - return $this->filePath; - } - - public function getLineNumber(): int - { - return $this->lineNumber; - } -} diff --git a/stubs/Dibi/Connection.php b/stubs/Dibi/Connection.php deleted file mode 100644 index c5a96d0c..00000000 --- a/stubs/Dibi/Connection.php +++ /dev/null @@ -1,13 +0,0 @@ -psr4PathValidator = new Psr4PathValidator(); - } - - /** - * @dataProvider provideCorrectData() - */ - public function testCorrectCase(string $namespace, string $directory): void - { - $isClassNamespaceCorrect = $this->isNamespaceAndDirectoryCorrect($namespace, $directory); - - $this->assertTrue($isClassNamespaceCorrect); - } - - /** - * @dataProvider provideFailingData() - */ - public function testFailingCase(string $namespace, string $directory): void - { - $isClassNamespaceCorrect = $this->isNamespaceAndDirectoryCorrect($namespace, $directory); - - $this->assertFalse($isClassNamespaceCorrect); - } - - /** - * @return Iterator - */ - public function provideCorrectData(): Iterator - { - yield ['Symplify\\PHPStanRules\\Tests\\', 'packages/phpstan-rules/tests']; - yield ['Symplify\\PHPStanRules\\Tests\\', 'packages/phpstan-rules/tests/']; - } - - public function provideFailingData(): Iterator - { - yield ['Symplify\\PHPStanRules\\Tests\\', 'packages/tests/']; - yield ['Symplify\\PHPStanRules\\Tests\\', 'packages/phpstan-rules/']; - yield ['PHPStanRules\\Tests', 'packages/tests/']; - } - - private function isNamespaceAndDirectoryCorrect(string $namespace, string $directory): bool - { - $classNamespaceAndDirectory = new ClassNamespaceAndDirectory( - $namespace, - $directory, - sprintf('%sComposer\\', $namespace) - ); - - return $this->psr4PathValidator->isClassNamespaceCorrect($classNamespaceAndDirectory, __FILE__); - } -} diff --git a/tests/Matcher/ClassLikeNameMatcherTest.php b/tests/Matcher/ClassLikeNameMatcherTest.php deleted file mode 100644 index 85342599..00000000 --- a/tests/Matcher/ClassLikeNameMatcherTest.php +++ /dev/null @@ -1,83 +0,0 @@ -classLikeNameMatcher = new ClassLikeNameMatcher(); - } - - /** - * @dataProvider provideData() - */ - public function test(string $classLikeName, string $namespaceWildcardPattern, bool $expectedIsMatched): void - { - $actualIsMatched = $this->classLikeNameMatcher->isClassLikeNameMatchedAgainstPattern( - $classLikeName, - $namespaceWildcardPattern - ); - - $this->assertSame($expectedIsMatched, $actualIsMatched); - } - - /** - * @return Iterator> - */ - public function provideData(): Iterator - { - yield 'identical class like names should match' => ['App\Form\MyForm', 'App\Form\MyForm', true]; - yield '* should match MyForm in the end of the namespace' => ['App\Form\MyForm', 'App\Form\*', true]; - yield '* should match Form in the middle of the namespace' => ['App\Form\MyForm', 'App\*\MyForm', true]; - yield '* should match App in the beginning of the namespace' => ['App\Form\MyForm', '*\Form\MyForm', true]; - yield '* should not match Form\Admin in the middle of the namespace' => [ - 'App\Form\Admin\MyForm', - 'App\*\MyForm', - false, - ]; - yield '** should match Form\Admin in the middle of the namespace' => [ - 'App\Form\Admin\MyForm', - 'App\**\MyForm', - true, - ]; - yield '** should match Admin\MyForm in the end of the namespace' => [ - 'App\Form\Admin\MyForm', - 'App\Form\**', - true, - ]; - yield '** should match App\Form in the beginning of the namespace' => [ - 'App\Form\Admin\MyForm', - '**\Admin\MyForm', - true, - ]; - yield 'first * should match Advanced and second * should match Form at the end of the namespace' => [ - 'App\Form\Admin\AdvancedForm', - 'App\Form\*\Advanced*', - true, - ]; - yield 'first ? should match F and second ? should match o in MyForm' => [ - 'App\Form\MyForm', - 'App\*\My??rm', - true, - ]; - yield '** should match Form\Admin, first ? should match F and second ? should match o in MyForm, * should match m' => [ - 'App\Form\Admin\MyForm', - 'App\**\My??r*', - true, - ]; - yield 'The escaping of regular expression characters should work correctly' => [ - 'App\.+[^]$(){}=!<>|:-#\Form\MyForm', - 'App\.+[^]$(){}=!<>|:-#\Form\**', - true, - ]; - } -} diff --git a/tests/Naming/ClassToSuffixResolverTest.php b/tests/Naming/ClassToSuffixResolverTest.php deleted file mode 100644 index 26734194..00000000 --- a/tests/Naming/ClassToSuffixResolverTest.php +++ /dev/null @@ -1,41 +0,0 @@ -classToSuffixResolver = new ClassToSuffixResolver(); - } - - /** - * @dataProvider provideData() - */ - public function test(string $className, string $expectedSuffix): void - { - $resolvedSuffix = $this->classToSuffixResolver->resolveFromClass($className); - $this->assertSame($expectedSuffix, $resolvedSuffix); - } - - /** - * @return Iterator - */ - public function provideData(): Iterator - { - yield ['Exception', 'Exception']; - yield [Command::class, 'Command']; - yield [TestCase::class, 'Test']; - yield [EventSubscriberInterface::class, 'EventSubscriber']; - } -} diff --git a/tests/NodeFinder/ClassLikeNameFinderTest.php b/tests/NodeFinder/ClassLikeNameFinderTest.php deleted file mode 100644 index 5a307d46..00000000 --- a/tests/NodeFinder/ClassLikeNameFinderTest.php +++ /dev/null @@ -1,117 +0,0 @@ -getByType(ClassLikeNameFinder::class); - - $actualClassLikeNames = $classLikeNameFinder->getClassLikeNamesMatchingNamespacePattern( - $namespaceWildcardPattern - ); - - sort($expectedClassLikeNames); - sort($actualClassLikeNames); - - $this->assertSame($expectedClassLikeNames, $actualClassLikeNames); - } - - /** - * @return Iterator> - */ - public function provideData(): Iterator - { - yield 'it should find all classes in PriceEngine directory' => [ - 'Symplify\PHPStanRules\Tests\Rules\ClassExtendingExclusiveNamespaceRule\Fixture\App\Component\PriceEngine\**', - [ - PriceProviderInterface::class, - ProductProviderInterface::class, - SkipFallbackPriceProviderInAuthorizedNamespace::class, - ], - ]; - - yield 'it should find all classes in PriceEngine and PriceEngineImpl directory' => [ - 'Symplify\PHPStanRules\Tests\Rules\ClassExtendingExclusiveNamespaceRule\Fixture\App\*\PriceEngine**', - [ - PriceProviderInterface::class, - ProductProviderInterface::class, - SkipFallbackPriceProviderInAuthorizedNamespace::class, - SkipCustomerPriceProviderInAuthorizedNamespace::class, - SkipCustomerProductProviderInAuthorizedNamespace::class, - SkipDealerPriceProviderInAuthorizedNamespace::class, - SkipDealerProductProviderInAuthorizedNamespace::class, - ], - ]; - - yield 'it should find all classes in Model\Customer\Request and Model\Order\Request directories' => [ - 'Symplify\PHPStanRules\Tests\Rules\ClassExtendingExclusiveNamespaceRule\Fixture\App\**\Request\**', - [ - SkipCustomerRequestModelInAuthorizedNamespace::class, - SkipOrderRequestModelInAuthorizedNamespace::class, - ], - ]; - - yield 'it should find all classes whose class name starts with SkipCustomer' => [ - '**\SkipCustomer*', - [ - SkipCustomerPriceProviderInAuthorizedNamespace::class, - SkipCustomerProductProviderInAuthorizedNamespace::class, - SkipCustomerRequestModelInAuthorizedNamespace::class, - ], - ]; - - yield 'it should find all classes whose class name matches Skip*Price*' => [ - '**\Skip*Price*', - [ - SkipCustomerPriceProviderInAuthorizedNamespace::class, - SkipDealerPriceProviderInAuthorizedNamespace::class, - SkipFallbackPriceProviderInAuthorizedNamespace::class, - ], - ]; - - yield 'it should find all classes whose class name matches S??p*Price*' => [ - '**\S??p*Price*', - [ - SkipCustomerPriceProviderInAuthorizedNamespace::class, - SkipDealerPriceProviderInAuthorizedNamespace::class, - SkipFallbackPriceProviderInAuthorizedNamespace::class, - ], - ]; - - yield 'it should find all classes in vendor for Symfony\Component\Finder\**' => [ - 'Symfony\Component\Finder\**\*Exception', - [AccessDeniedException::class, DirectoryNotFoundException::class], - ]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/../config/included_services.neon']; - } -} diff --git a/tests/Rules/AnnotateRegexClassConstWithRegexLinkRule/AnnotateRegexClassConstWithRegexLinkRuleTest.php b/tests/Rules/AnnotateRegexClassConstWithRegexLinkRule/AnnotateRegexClassConstWithRegexLinkRuleTest.php deleted file mode 100644 index 5c7d13b4..00000000 --- a/tests/Rules/AnnotateRegexClassConstWithRegexLinkRule/AnnotateRegexClassConstWithRegexLinkRuleTest.php +++ /dev/null @@ -1,51 +0,0 @@ - - */ -final class AnnotateRegexClassConstWithRegexLinkRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [ - __DIR__ . '/Fixture/ClassConstMissingLink.php', - [[AnnotateRegexClassConstWithRegexLinkRule::ERROR_MESSAGE, 12]], - ]; - - yield [__DIR__ . '/Fixture/SkipShort.php', []]; - yield [__DIR__ . '/Fixture/SkipWithLink.php', []]; - yield [__DIR__ . '/Fixture/SkipAlphabet.php', []]; - yield [__DIR__ . '/Fixture/SkipPlaceholder.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(AnnotateRegexClassConstWithRegexLinkRule::class); - } -} diff --git a/tests/Rules/AnnotateRegexClassConstWithRegexLinkRule/Fixture/ClassConstMissingLink.php b/tests/Rules/AnnotateRegexClassConstWithRegexLinkRule/Fixture/ClassConstMissingLink.php deleted file mode 100644 index 4756d3b7..00000000 --- a/tests/Rules/AnnotateRegexClassConstWithRegexLinkRule/Fixture/ClassConstMissingLink.php +++ /dev/null @@ -1,13 +0,0 @@ - - */ -final class BoolishClassMethodPrefixRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipParentContract.php', []]; - yield [__DIR__ . '/Fixture/SkipClassWithEmptyReturn.php', []]; - yield [__DIR__ . '/Fixture/SkipClassThatImplementsInterface.php', []]; - yield [__DIR__ . '/Fixture/SkipRequiredByInterface.php', []]; - yield [__DIR__ . '/Fixture/SkipNestedCallback.php', []]; - - $firstErrorMessage = sprintf(BoolishClassMethodPrefixRule::ERROR_MESSAGE, 'honesty'); - $secondErrorMessage = sprintf(BoolishClassMethodPrefixRule::ERROR_MESSAGE, 'thatWasGreat'); - - yield [ - __DIR__ . '/Fixture/ClassWithBoolishMethods.php', - [[$firstErrorMessage, 9], [$secondErrorMessage, 14]], - ]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(BoolishClassMethodPrefixRule::class); - } -} diff --git a/tests/Rules/BoolishClassMethodPrefixRule/Fixture/ClassWithBoolishMethods.php b/tests/Rules/BoolishClassMethodPrefixRule/Fixture/ClassWithBoolishMethods.php deleted file mode 100644 index 4c06e7aa..00000000 --- a/tests/Rules/BoolishClassMethodPrefixRule/Fixture/ClassWithBoolishMethods.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ -final class CheckAttributteArgumentClassExistsRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorsWithLines - */ - public function testRule(string $filePath, array $expectedErrorsWithLines): void - { - $this->analyse([$filePath], $expectedErrorsWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipExistingClassAttributeArgument.php', []]; - - yield [__DIR__ . '/Fixture/SomeClassWithAttributeArgumentMissingClass.php', [ - [CheckAttributteArgumentClassExistsRule::ERROR_MESSAGE, 9], - ]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(CheckAttributteArgumentClassExistsRule::class); - } -} diff --git a/tests/Rules/CheckAttributteArgumentClassExistsRule/Fixture/SkipExistingClassAttributeArgument.php b/tests/Rules/CheckAttributteArgumentClassExistsRule/Fixture/SkipExistingClassAttributeArgument.php deleted file mode 100644 index ee497f33..00000000 --- a/tests/Rules/CheckAttributteArgumentClassExistsRule/Fixture/SkipExistingClassAttributeArgument.php +++ /dev/null @@ -1,13 +0,0 @@ - - */ -final class CheckClassNamespaceFollowPsr4RuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorsWithLines - */ - public function testRule(string $filePath, array $expectedErrorsWithLines): void - { - $this->analyse([$filePath], $expectedErrorsWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipAnonymousClass.php', []]; - yield [__DIR__ . '/Fixture/SkipValidNamespaceInterface.php', []]; - - yield [__DIR__ . '/Fixture/InvalidNamespaceClass.php', [ - [sprintf(CheckClassNamespaceFollowPsr4Rule::ERROR_MESSAGE, 'Foo\Bar'), 7], - ]]; - yield [__DIR__ . '/Fixture/InvalidNamespaceInterface.php', [ - [sprintf(CheckClassNamespaceFollowPsr4Rule::ERROR_MESSAGE, 'Foo\Bar'), 7], - ]]; - yield [__DIR__ . '/Fixture/InvalidNamespaceTrait.php', [ - [sprintf(CheckClassNamespaceFollowPsr4Rule::ERROR_MESSAGE, 'Foo\Bar'), 7], - ]]; - - $errorMessage = sprintf( - CheckClassNamespaceFollowPsr4Rule::ERROR_MESSAGE, - 'Symplify\PHPStanRules\Tests\Rules\CheckClassNamespaceFollowPsr4Rule' - ); - yield [__DIR__ . '/Fixture/MissingFixtureNamespaceClass.php', [[$errorMessage, 7]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(CheckClassNamespaceFollowPsr4Rule::class); - } -} diff --git a/tests/Rules/CheckClassNamespaceFollowPsr4Rule/Fixture/InvalidNamespaceClass.php b/tests/Rules/CheckClassNamespaceFollowPsr4Rule/Fixture/InvalidNamespaceClass.php deleted file mode 100644 index 75cb9f95..00000000 --- a/tests/Rules/CheckClassNamespaceFollowPsr4Rule/Fixture/InvalidNamespaceClass.php +++ /dev/null @@ -1,10 +0,0 @@ - - */ -final class CheckNotTestsNamespaceOutsideTestsDirectoryRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorsWithLines - */ - public function testRule(string $filePath, array $expectedErrorsWithLines): void - { - $this->analyse([$filePath], $expectedErrorsWithLines); - } - - /** - * @return Iterator> - */ - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/Tests/SkipTestsNamespaceInsideTestsDirectoryClass.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(CheckNotTestsNamespaceOutsideTestsDirectoryRule::class); - } -} diff --git a/tests/Rules/CheckNotTestsNamespaceOutsideTestsDirectoryRule/Fixture/Tests/SkipTestsNamespaceInsideTestsDirectoryClass.php b/tests/Rules/CheckNotTestsNamespaceOutsideTestsDirectoryRule/Fixture/Tests/SkipTestsNamespaceInsideTestsDirectoryClass.php deleted file mode 100644 index 4986f089..00000000 --- a/tests/Rules/CheckNotTestsNamespaceOutsideTestsDirectoryRule/Fixture/Tests/SkipTestsNamespaceInsideTestsDirectoryClass.php +++ /dev/null @@ -1,10 +0,0 @@ - - */ -final class CheckRequiredInterfaceInContractNamespaceRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorsWithLines - */ - public function testRule(string $filePath, array $expectedErrorsWithLines): void - { - $this->analyse([$filePath], $expectedErrorsWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/Contract/SkipInterfaceInContract.php', []]; - yield [ - __DIR__ . '/Fixture/AnInterfaceNotInContract.php', - [[CheckRequiredInterfaceInContractNamespaceRule::ERROR_MESSAGE, 7]], ]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(CheckRequiredInterfaceInContractNamespaceRule::class); - } -} diff --git a/tests/Rules/CheckRequiredInterfaceInContractNamespaceRule/Fixture/AnInterfaceNotInContract.php b/tests/Rules/CheckRequiredInterfaceInContractNamespaceRule/Fixture/AnInterfaceNotInContract.php deleted file mode 100644 index 08a2d7dd..00000000 --- a/tests/Rules/CheckRequiredInterfaceInContractNamespaceRule/Fixture/AnInterfaceNotInContract.php +++ /dev/null @@ -1,10 +0,0 @@ - - */ -final class ClassExtendingExclusiveNamespaceRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - /** - * @return Iterator - */ - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/App/Command/SkipCommandInAuthorizedNamespace.php', []]; - yield [__DIR__ . '/Fixture/App/Form/SkipFormInAuthorizedNamespace.php', []]; - yield [__DIR__ . '/Fixture/App/Model/Customer/Request/SkipCustomerRequestModelInAuthorizedNamespace.php', []]; - yield [__DIR__ . '/Fixture/App/Model/Order/Request/SkipOrderRequestModelInAuthorizedNamespace.php', []]; - yield [__DIR__ . '/Fixture/App/Exception/SkipExceptionInAuthorizedNamespace.php', []]; - yield [__DIR__ . '/Fixture/App/Services/SkipExceptionInAuthorizedNamespace.php', []]; - yield [__DIR__ . '/Fixture/App/Component/PriceEngine/SkipFallbackPriceProviderInAuthorizedNamespace.php', []]; - yield [ - __DIR__ . '/Fixture/App/Component/PriceEngineImpl/SkipCustomerPriceProviderInAuthorizedNamespace.php', - [], - ]; - yield [ - __DIR__ . '/Fixture/App/Component/PriceEngineImpl/SkipCustomerProductProviderInAuthorizedNamespace.php', - [], - ]; - yield [ - __DIR__ . '/Fixture/App/Component/PriceEngineImpl/SkipDealerPriceProviderInAuthorizedNamespace.php', - [], - ]; - yield [ - __DIR__ . '/Fixture/App/Component/PriceEngineImpl/SkipDealerProductProviderInAuthorizedNamespace.php', - [], - ]; - - yield [ - __DIR__ . '/Fixture/App/CommandInUnauthorizedNamespace.php', - [ - [ - sprintf( - ClassExtendingExclusiveNamespaceRule::ERROR_MESSAGE, - CommandInUnauthorizedNamespace::class, - Json::encode( - [ - 'Symplify\PHPStanRules\Tests\Rules\ClassExtendingExclusiveNamespaceRule\Fixture\App\Command\**', - ] - ), - (new ReflectionClass(CommandInUnauthorizedNamespace::class))->getNamespaceName(), - ), - 9, - ], - ], - ]; - - yield [ - __DIR__ . '/Fixture/App/FormInUnauthorizedNamespace.php', - [ - [ - sprintf( - ClassExtendingExclusiveNamespaceRule::ERROR_MESSAGE, - FormInUnauthorizedNamespace::class, - Json::encode( - [ - 'Symplify\PHPStanRules\Tests\Rules\ClassExtendingExclusiveNamespaceRule\Fixture\App\Form\**', ] - ), - (new ReflectionClass(FormInUnauthorizedNamespace::class))->getNamespaceName(), - ), - 7, - ], - ], - ]; - - yield [ - __DIR__ . '/Fixture/App/Model/Customer/CustomerRequestModelInUnauthorizedNamespace.php', - [ - [ - sprintf( - ClassExtendingExclusiveNamespaceRule::ERROR_MESSAGE, - CustomerRequestModelInUnauthorizedNamespace::class, - Json::encode( - [ - 'Symplify\PHPStanRules\Tests\Rules\ClassExtendingExclusiveNamespaceRule\Fixture\App\Model\**\Request\**', ] - ), - (new ReflectionClass(CustomerRequestModelInUnauthorizedNamespace::class))->getNamespaceName(), - ), - 7, - ], - ], - ]; - - yield [ - __DIR__ . '/Fixture/App/Model/Order/OrderRequestModelInUnauthorizedNamespace.php', - [ - [ - sprintf( - ClassExtendingExclusiveNamespaceRule::ERROR_MESSAGE, - OrderRequestModelInUnauthorizedNamespace::class, - Json::encode( - [ - 'Symplify\PHPStanRules\Tests\Rules\ClassExtendingExclusiveNamespaceRule\Fixture\App\Model\**\Request\**', ] - ), - (new ReflectionClass(OrderRequestModelInUnauthorizedNamespace::class))->getNamespaceName(), - ), - 7, - ], - ], - ]; - - yield [ - __DIR__ . '/Fixture/App/ExceptionInUnauthorizedNamespace.php', - [ - [ - sprintf( - ClassExtendingExclusiveNamespaceRule::ERROR_MESSAGE, - ExceptionInUnauthorizedNamespace::class, - Json::encode([ - 'Symplify\PHPStanRules\Tests\Rules\ClassExtendingExclusiveNamespaceRule\Fixture\App\Exception\**', - 'Symplify\PHPStanRules\Tests\Rules\ClassExtendingExclusiveNamespaceRule\Fixture\App\Services\**', - ]), - (new ReflectionClass(ExceptionInUnauthorizedNamespace::class))->getNamespaceName(), - ), - 9, - ], - ], - ]; - - yield [ - __DIR__ . '/Fixture/App/Component/PriceProviderInUnauthorizedNamespace.php', - [ - [ - sprintf( - ClassExtendingExclusiveNamespaceRule::ERROR_MESSAGE, - PriceProviderInUnauthorizedNamespace::class, - Json::encode([ - 'Symplify\PHPStanRules\Tests\Rules\ClassExtendingExclusiveNamespaceRule\Fixture\App\Component\PriceEngine\**', - 'Symplify\PHPStanRules\Tests\Rules\ClassExtendingExclusiveNamespaceRule\Fixture\App\Component\PriceEngineImpl\**', - ]), - (new ReflectionClass(PriceProviderInUnauthorizedNamespace::class))->getNamespaceName(), - ), - 7, - ], - ], - ]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(ClassExtendingExclusiveNamespaceRule::class); - } -} diff --git a/tests/Rules/ClassExtendingExclusiveNamespaceRule/Fixture/App/Command/SkipCommandInAuthorizedNamespace.php b/tests/Rules/ClassExtendingExclusiveNamespaceRule/Fixture/App/Command/SkipCommandInAuthorizedNamespace.php deleted file mode 100644 index 0f8d13cd..00000000 --- a/tests/Rules/ClassExtendingExclusiveNamespaceRule/Fixture/App/Command/SkipCommandInAuthorizedNamespace.php +++ /dev/null @@ -1,11 +0,0 @@ - - */ -final class ClassNameRespectsParentSuffixRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipCommand.php', []]; - yield [__DIR__ . '/Fixture/SkipSomeEventSubscriber.php', []]; - yield [__DIR__ . '/Fixture/SkipFixer.php', []]; - yield [__DIR__ . '/Fixture/SkipAnonymousClass.php', []]; - yield [__DIR__ . '/Fixture/SkipTest.php', []]; - yield [__DIR__ . '/Fixture/SkipAbstractTestCase.php', []]; - - $errorMessage = sprintf(ClassNameRespectsParentSuffixRule::ERROR_MESSAGE, 'Test'); - yield [__DIR__ . '/Fixture/NonTestSuffix.php', [[$errorMessage, 9]]]; - - $errorMessage = sprintf(ClassNameRespectsParentSuffixRule::ERROR_MESSAGE, 'Command'); - yield [__DIR__ . '/Fixture/SomeController.php', [[$errorMessage, 9]]]; - - $errorMessage = sprintf(ClassNameRespectsParentSuffixRule::ERROR_MESSAGE, 'EventSubscriber'); - yield [__DIR__ . '/Fixture/SomeEventSubscriberFalse.php', [[$errorMessage, 9]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(ClassNameRespectsParentSuffixRule::class); - } -} diff --git a/tests/Rules/ClassNameRespectsParentSuffixRule/Fixture/NonTestSuffix.php b/tests/Rules/ClassNameRespectsParentSuffixRule/Fixture/NonTestSuffix.php deleted file mode 100644 index 6da9fb6a..00000000 --- a/tests/Rules/ClassNameRespectsParentSuffixRule/Fixture/NonTestSuffix.php +++ /dev/null @@ -1,11 +0,0 @@ - - */ -final class ForbiddenArrayMethodCallRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipNormalArray.php', []]; - yield [__DIR__ . '/Fixture/ReturnCallable.php', [[ForbiddenArrayMethodCallRule::ERROR_MESSAGE, 11]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(ForbiddenArrayMethodCallRule::class); - } -} diff --git a/tests/Rules/Complexity/ForbiddenArrayMethodCallRule/config/configured_rule.neon b/tests/Rules/Complexity/ForbiddenArrayMethodCallRule/config/configured_rule.neon deleted file mode 100644 index 6273d331..00000000 --- a/tests/Rules/Complexity/ForbiddenArrayMethodCallRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\Complexity\ForbiddenArrayMethodCallRule diff --git a/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/AssignInsideIf.php b/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/AssignInsideIf.php deleted file mode 100644 index 45b14286..00000000 --- a/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/AssignInsideIf.php +++ /dev/null @@ -1,14 +0,0 @@ -isValid($value)) { - return true; - } - } - - private function isValid(): bool - { - return (bool) mt_rand(0, 100); - } -} diff --git a/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/SkipIfWithBooleanFromExternalClass.php b/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/SkipIfWithBooleanFromExternalClass.php deleted file mode 100644 index 7839f2f4..00000000 --- a/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/SkipIfWithBooleanFromExternalClass.php +++ /dev/null @@ -1,29 +0,0 @@ -externalCaller = $externalCaller; - } - - public function run($value) - { - if ($this->externalCaller->returnsBool($value)) { - return 100; - } - - return 1000; - } -} diff --git a/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/SkipIfWithMethodCallWithoutParameter.php b/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/SkipIfWithMethodCallWithoutParameter.php deleted file mode 100644 index eda7bc95..00000000 --- a/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/SkipIfWithMethodCallWithoutParameter.php +++ /dev/null @@ -1,23 +0,0 @@ -getData() === []) { - - } elseif ($this->getData() !== []) { - - } - } - -} diff --git a/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/SkipMethodCallWithBooleanReturn.php b/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/SkipMethodCallWithBooleanReturn.php deleted file mode 100644 index b33640da..00000000 --- a/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/SkipMethodCallWithBooleanReturn.php +++ /dev/null @@ -1,24 +0,0 @@ -isSkipped($arg) === []) { - - } elseif ($obj->isSkipped($arg) !== []) { - - } - } - -} diff --git a/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/SkipNetteUtilsStringsMatchCall.php b/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/SkipNetteUtilsStringsMatchCall.php deleted file mode 100644 index 423a43d1..00000000 --- a/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/SkipNetteUtilsStringsMatchCall.php +++ /dev/null @@ -1,19 +0,0 @@ -isSuperTypeOf(new NullType())->yes()) { - return false; - } - - return false; - } -} diff --git a/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/SkipWithMethodCallWithoutParameter.php b/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/SkipWithMethodCallWithoutParameter.php deleted file mode 100644 index 6dcb3e27..00000000 --- a/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/SkipWithMethodCallWithoutParameter.php +++ /dev/null @@ -1,21 +0,0 @@ -getData() as $key => $item) { - - } - } - -} diff --git a/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/SkipWithStaticCallWithoutParameter.php b/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/SkipWithStaticCallWithoutParameter.php deleted file mode 100644 index 7aaa4552..00000000 --- a/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/SkipWithStaticCallWithoutParameter.php +++ /dev/null @@ -1,20 +0,0 @@ - $item) { - - } - } -} diff --git a/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/SkipWithoutMethodCall.php b/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/SkipWithoutMethodCall.php deleted file mode 100644 index e38eed16..00000000 --- a/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/SkipWithoutMethodCall.php +++ /dev/null @@ -1,19 +0,0 @@ - $item) { - - } - } -} diff --git a/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/WithMethodCallWithParameter.php b/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/WithMethodCallWithParameter.php deleted file mode 100644 index 52dc4f7f..00000000 --- a/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/WithMethodCallWithParameter.php +++ /dev/null @@ -1,21 +0,0 @@ -getData($arg) as $key => $item) { - - } - } - -} diff --git a/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/WithMethodCallWithParameterNotFromThis.php b/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/WithMethodCallWithParameterNotFromThis.php deleted file mode 100644 index 00d5b8a2..00000000 --- a/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/WithMethodCallWithParameterNotFromThis.php +++ /dev/null @@ -1,24 +0,0 @@ -getData($arg) === []) { - - } elseif ($obj->getData($arg) !== []) { - - } - } - -} diff --git a/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/WithStaticCallWithParameter.php b/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/WithStaticCallWithParameter.php deleted file mode 100644 index 7387f2b8..00000000 --- a/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Fixture/WithStaticCallWithParameter.php +++ /dev/null @@ -1,21 +0,0 @@ - $item) { - - } - } - -} diff --git a/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/ForbiddenComplexForeachIfExprRuleTest.php b/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/ForbiddenComplexForeachIfExprRuleTest.php deleted file mode 100644 index bf7eb68e..00000000 --- a/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/ForbiddenComplexForeachIfExprRuleTest.php +++ /dev/null @@ -1,74 +0,0 @@ - - */ -final class ForbiddenComplexForeachIfExprRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipWithoutMethodOrStaticCall.php', []]; - yield [__DIR__ . '/Fixture/SkipWithMethodCallWithoutParameter.php', []]; - yield [__DIR__ . '/Fixture/SkipWithStaticCallWithoutParameter.php', []]; - - yield [__DIR__ . '/Fixture/SkipAssignBeforeIf.php', []]; - yield [__DIR__ . '/Fixture/SkipAssignAfterIf.php', []]; - yield [__DIR__ . '/Fixture/AssignInsideIf.php', [[ForbiddenComplexForeachIfExprRule::ERROR_MESSAGE, 12]]]; - - yield [ - __DIR__ . '/Fixture/WithMethodCallWithParameter.php', - [[ForbiddenComplexForeachIfExprRule::ERROR_MESSAGE, 16]], - ]; - yield [ - __DIR__ . '/Fixture/WithStaticCallWithParameter.php', - [[ForbiddenComplexForeachIfExprRule::ERROR_MESSAGE, 16]], - ]; - - yield [__DIR__ . '/Fixture/SkipTrinaryLogic.php', []]; - yield [__DIR__ . '/Fixture/SkipWithoutMethodCall.php', []]; - yield [__DIR__ . '/Fixture/SkipWithMethodCallWithoutParameter.php', []]; - yield [__DIR__ . '/Fixture/SkipNetteUtilsStringsMatchCall.php', []]; - yield [__DIR__ . '/Fixture/SkipMethodCallWithBooleanReturn.php', []]; - - yield [__DIR__ . '/Fixture/SkipIfWithBoolean.php', []]; - yield [__DIR__ . '/Fixture/SkipIfWithBooleanFromExternalClass.php', []]; - - yield [ - __DIR__ . '/Fixture/WithMethodCallWithParameterNotFromThis.php', [ - [ForbiddenComplexForeachIfExprRule::ERROR_MESSAGE, 17], - [ForbiddenComplexForeachIfExprRule::ERROR_MESSAGE, 19], - ], - ]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(ForbiddenComplexForeachIfExprRule::class); - } -} diff --git a/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Source/ExternalCaller.php b/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Source/ExternalCaller.php deleted file mode 100644 index e872cf0e..00000000 --- a/tests/Rules/Complexity/ForbiddenComplexForeachIfExprRule/Source/ExternalCaller.php +++ /dev/null @@ -1,22 +0,0 @@ -away(); - } - - private function away() - { - return mt_rand(0, 100) + 100; - } -} diff --git a/tests/Rules/Complexity/ForbiddenInlineClassMethodRule/Fixture/SkipUsedTwice.php b/tests/Rules/Complexity/ForbiddenInlineClassMethodRule/Fixture/SkipUsedTwice.php deleted file mode 100644 index 200022f0..00000000 --- a/tests/Rules/Complexity/ForbiddenInlineClassMethodRule/Fixture/SkipUsedTwice.php +++ /dev/null @@ -1,23 +0,0 @@ -away(); - } - - public function run2() - { - return $this->away(); - } - - private function away() - { - return mt_rand(0, 100); - } -} diff --git a/tests/Rules/Complexity/ForbiddenInlineClassMethodRule/Fixture/SomeClassWithInlinedMethod.php b/tests/Rules/Complexity/ForbiddenInlineClassMethodRule/Fixture/SomeClassWithInlinedMethod.php deleted file mode 100644 index 34f35de1..00000000 --- a/tests/Rules/Complexity/ForbiddenInlineClassMethodRule/Fixture/SomeClassWithInlinedMethod.php +++ /dev/null @@ -1,23 +0,0 @@ -away(); - } - - private function away() - { - return $this->exploreMethod(); - } - - private function exploreMethod(): int - { - return mt_rand(0, 100); - } -} diff --git a/tests/Rules/Complexity/ForbiddenInlineClassMethodRule/ForbiddenInlineClassMethodRuleTest.php b/tests/Rules/Complexity/ForbiddenInlineClassMethodRule/ForbiddenInlineClassMethodRuleTest.php deleted file mode 100644 index 96a7fad4..00000000 --- a/tests/Rules/Complexity/ForbiddenInlineClassMethodRule/ForbiddenInlineClassMethodRuleTest.php +++ /dev/null @@ -1,52 +0,0 @@ - - */ -final class ForbiddenInlineClassMethodRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - /** - * @return Iterator>> - */ - public function provideData(): Iterator - { - yield [ - __DIR__ . '/Fixture/SomeClassWithInlinedMethod.php', [ - [sprintf(ForbiddenInlineClassMethodRule::ERROR_MESSAGE, 'away'), 14], - ], ]; - - yield [__DIR__ . '/Fixture/SkipUsedTwice.php', []]; - yield [__DIR__ . '/Fixture/SkipNoMethodCall.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(ForbiddenInlineClassMethodRule::class); - } -} diff --git a/tests/Rules/Complexity/ForbiddenInlineClassMethodRule/config/configured_rule.neon b/tests/Rules/Complexity/ForbiddenInlineClassMethodRule/config/configured_rule.neon deleted file mode 100644 index c882a64d..00000000 --- a/tests/Rules/Complexity/ForbiddenInlineClassMethodRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\Complexity\ForbiddenInlineClassMethodRule diff --git a/tests/Rules/Complexity/ForbiddenNamedArgumentsRule/Fixture/ClassWithNamedArguments.php b/tests/Rules/Complexity/ForbiddenNamedArgumentsRule/Fixture/ClassWithNamedArguments.php deleted file mode 100644 index 09fbf89f..00000000 --- a/tests/Rules/Complexity/ForbiddenNamedArgumentsRule/Fixture/ClassWithNamedArguments.php +++ /dev/null @@ -1,13 +0,0 @@ - - */ -final class ForbiddenNamedArgumentsRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipAttributeNamedArguments.php', []]; - yield [__DIR__ . '/Fixture/SkipNormalArguments.php', []]; - - yield [ - __DIR__ . '/Fixture/ClassWithNamedArguments.php', - [[ForbiddenNamedArgumentsRule::ERROR_MESSAGE, 11]], - ]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(ForbiddenNamedArgumentsRule::class); - } -} diff --git a/tests/Rules/Complexity/ForbiddenNamedArgumentsRule/Source/SimpleAttribute.php b/tests/Rules/Complexity/ForbiddenNamedArgumentsRule/Source/SimpleAttribute.php deleted file mode 100644 index 2f451a92..00000000 --- a/tests/Rules/Complexity/ForbiddenNamedArgumentsRule/Source/SimpleAttribute.php +++ /dev/null @@ -1,15 +0,0 @@ -var instanceof ArrayDimFetch) { - $arrayDimFetch = $arrayDimFetch->var; - } - } -} diff --git a/tests/Rules/Complexity/ForbiddenSameNamedNewInstanceRule/Fixture/SkipNonObjectAssigns.php b/tests/Rules/Complexity/ForbiddenSameNamedNewInstanceRule/Fixture/SkipNonObjectAssigns.php deleted file mode 100644 index 8c72b86a..00000000 --- a/tests/Rules/Complexity/ForbiddenSameNamedNewInstanceRule/Fixture/SkipNonObjectAssigns.php +++ /dev/null @@ -1,14 +0,0 @@ - - */ -final class ForbiddenSameNamedNewInstanceRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipDifferentNames.php', []]; - yield [__DIR__ . '/Fixture/SkipNullDefaultAssign.php', []]; - yield [__DIR__ . '/Fixture/SkipNonObjectAssigns.php', []]; - yield [__DIR__ . '/Fixture/SkipForeachNewNesting.php', []]; - yield [__DIR__ . '/Fixture/SkipForeachVariableAssign.php', []]; - - $errorMessage = sprintf(ForbiddenSameNamedNewInstanceRule::ERROR_MESSAGE, '$someProduct'); - yield [__DIR__ . '/Fixture/SameObjectAssigns.php', [[$errorMessage, 14]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(ForbiddenSameNamedNewInstanceRule::class); - } -} diff --git a/tests/Rules/Complexity/ForbiddenSameNamedNewInstanceRule/Source/SomeProduct.php b/tests/Rules/Complexity/ForbiddenSameNamedNewInstanceRule/Source/SomeProduct.php deleted file mode 100644 index 471e5116..00000000 --- a/tests/Rules/Complexity/ForbiddenSameNamedNewInstanceRule/Source/SomeProduct.php +++ /dev/null @@ -1,10 +0,0 @@ - - */ -final class NoAbstractRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipNonAbstractClass.php', []]; - yield [__DIR__ . '/Fixture/SkipAbstractTestCase.php', []]; - yield [__DIR__ . '/Fixture/AbstractClass.php', [[NoAbstractRule::ERROR_MESSAGE, 7]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoAbstractRule::class,); - } -} diff --git a/tests/Rules/Complexity/NoAbstractRule/config/configured_rule.neon b/tests/Rules/Complexity/NoAbstractRule/config/configured_rule.neon deleted file mode 100644 index f3baf2db..00000000 --- a/tests/Rules/Complexity/NoAbstractRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\Complexity\NoAbstractRule diff --git a/tests/Rules/Complexity/NoDuplicatedArgumentRule/Fixture/DuplicatedCall.php b/tests/Rules/Complexity/NoDuplicatedArgumentRule/Fixture/DuplicatedCall.php deleted file mode 100644 index 33c32c60..00000000 --- a/tests/Rules/Complexity/NoDuplicatedArgumentRule/Fixture/DuplicatedCall.php +++ /dev/null @@ -1,17 +0,0 @@ -go(1000, 1000); - } - - public function go($value, $anotherValue) - { - } -} diff --git a/tests/Rules/Complexity/NoDuplicatedArgumentRule/Fixture/SkipArrayCombine.php b/tests/Rules/Complexity/NoDuplicatedArgumentRule/Fixture/SkipArrayCombine.php deleted file mode 100644 index 5f8fa498..00000000 --- a/tests/Rules/Complexity/NoDuplicatedArgumentRule/Fixture/SkipArrayCombine.php +++ /dev/null @@ -1,14 +0,0 @@ -go(false, false); - } - - public function go($value, $anotherValue) - { - } -} diff --git a/tests/Rules/Complexity/NoDuplicatedArgumentRule/Fixture/SkipDifferentValues.php b/tests/Rules/Complexity/NoDuplicatedArgumentRule/Fixture/SkipDifferentValues.php deleted file mode 100644 index 48f6e394..00000000 --- a/tests/Rules/Complexity/NoDuplicatedArgumentRule/Fixture/SkipDifferentValues.php +++ /dev/null @@ -1,17 +0,0 @@ -go(1, 100); - } - - public function go($value, $anotherValue) - { - } -} diff --git a/tests/Rules/Complexity/NoDuplicatedArgumentRule/Fixture/SkipFunctionExprName.php b/tests/Rules/Complexity/NoDuplicatedArgumentRule/Fixture/SkipFunctionExprName.php deleted file mode 100644 index 3f1d15cb..00000000 --- a/tests/Rules/Complexity/NoDuplicatedArgumentRule/Fixture/SkipFunctionExprName.php +++ /dev/null @@ -1,13 +0,0 @@ -go(1, 1); - } - - public function go($value, $anotherValue) - { - } -} diff --git a/tests/Rules/Complexity/NoDuplicatedArgumentRule/NoDuplicatedArgumentRuleTest.php b/tests/Rules/Complexity/NoDuplicatedArgumentRule/NoDuplicatedArgumentRuleTest.php deleted file mode 100644 index 22a717fd..00000000 --- a/tests/Rules/Complexity/NoDuplicatedArgumentRule/NoDuplicatedArgumentRuleTest.php +++ /dev/null @@ -1,49 +0,0 @@ - - */ -final class NoDuplicatedArgumentRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[]|array> $expectedErrorsWithLines - */ - public function testRule(string $filePath, array $expectedErrorsWithLines): void - { - $this->analyse([$filePath], $expectedErrorsWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipDifferentValues.php', []]; - yield [__DIR__ . '/Fixture/SkipBool.php', []]; - yield [__DIR__ . '/Fixture/SkipSimpleNumbers.php', []]; - yield [__DIR__ . '/Fixture/SkipFunctionExprName.php', []]; - yield [__DIR__ . '/Fixture/SkipFunctionExprName.php', []]; - - yield [__DIR__ . '/Fixture/DuplicatedCall.php', [[NoDuplicatedArgumentRule::ERROR_MESSAGE, 11]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoDuplicatedArgumentRule::class); - } -} diff --git a/tests/Rules/Complexity/NoDuplicatedArgumentRule/config/configured_rule.neon b/tests/Rules/Complexity/NoDuplicatedArgumentRule/config/configured_rule.neon deleted file mode 100644 index 3f9a0b1e..00000000 --- a/tests/Rules/Complexity/NoDuplicatedArgumentRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\Complexity\NoDuplicatedArgumentRule diff --git a/tests/Rules/Complexity/NoDuplicatedTraitMethodNameRule/Fixture/ClassUsingOneTrait.php b/tests/Rules/Complexity/NoDuplicatedTraitMethodNameRule/Fixture/ClassUsingOneTrait.php deleted file mode 100644 index 7cdcbfc0..00000000 --- a/tests/Rules/Complexity/NoDuplicatedTraitMethodNameRule/Fixture/ClassUsingOneTrait.php +++ /dev/null @@ -1,8 +0,0 @@ - - */ -final class NoDuplicatedTraitMethodNameRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * - * @param string[] $filePaths - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(array $filePaths, array $expectedErrorMessagesWithLines): void - { - $this->analyse($filePaths, $expectedErrorMessagesWithLines); - } - - /** - * @return Iterator - */ - public function provideData(): Iterator - { - $errorMessage = sprintf(NoDuplicatedTraitMethodNameRule::ERROR_MESSAGE, 'run'); - yield [ - [__DIR__ . '/Fixture/ClassUsingOneTrait.php', __DIR__ . '/Fixture/ClassUsingSecondTrait.php'], - [[$errorMessage, -1], [$errorMessage, -1]], - ]; - - yield [[__DIR__ . '/Fixture/ClassUsingOneTrait.php'], []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - /** - * @return Collector[] - */ - protected function getCollectors(): array - { - return [self::getContainer()->getByType(TraitMethodNameCollector::class)]; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoDuplicatedTraitMethodNameRule::class); - } -} diff --git a/tests/Rules/Complexity/NoDuplicatedTraitMethodNameRule/config/configured_rule.neon b/tests/Rules/Complexity/NoDuplicatedTraitMethodNameRule/config/configured_rule.neon deleted file mode 100644 index 670313ff..00000000 --- a/tests/Rules/Complexity/NoDuplicatedTraitMethodNameRule/config/configured_rule.neon +++ /dev/null @@ -1,12 +0,0 @@ -includes: - - ../../../../config/included_services.neon - -services: - - - class: Symplify\PHPStanRules\Rules\Complexity\NoDuplicatedTraitMethodNameRule - tags: [phpstan.rules.rule] - - - - class: Symplify\PHPStanRules\Collector\ClassLike\TraitMethodNameCollector - tags: [phpstan.collector] - diff --git a/tests/Rules/Complexity/NoMirrorAssertRule/Fixture/AssertMirror.php b/tests/Rules/Complexity/NoMirrorAssertRule/Fixture/AssertMirror.php deleted file mode 100644 index 8ac5e9d2..00000000 --- a/tests/Rules/Complexity/NoMirrorAssertRule/Fixture/AssertMirror.php +++ /dev/null @@ -1,15 +0,0 @@ -assertSame(1, 1); - } -} diff --git a/tests/Rules/Complexity/NoMirrorAssertRule/Fixture/SameConstant.php b/tests/Rules/Complexity/NoMirrorAssertRule/Fixture/SameConstant.php deleted file mode 100644 index 4714c44f..00000000 --- a/tests/Rules/Complexity/NoMirrorAssertRule/Fixture/SameConstant.php +++ /dev/null @@ -1,17 +0,0 @@ -assertSame(self::LEFT, self::LEFT); - } -} diff --git a/tests/Rules/Complexity/NoMirrorAssertRule/Fixture/SkipDifferentAssert.php b/tests/Rules/Complexity/NoMirrorAssertRule/Fixture/SkipDifferentAssert.php deleted file mode 100644 index 4e379f73..00000000 --- a/tests/Rules/Complexity/NoMirrorAssertRule/Fixture/SkipDifferentAssert.php +++ /dev/null @@ -1,16 +0,0 @@ -assertSame(1, $value); - } -} diff --git a/tests/Rules/Complexity/NoMirrorAssertRule/Fixture/SkipDifferentConstant.php b/tests/Rules/Complexity/NoMirrorAssertRule/Fixture/SkipDifferentConstant.php deleted file mode 100644 index 5407f66e..00000000 --- a/tests/Rules/Complexity/NoMirrorAssertRule/Fixture/SkipDifferentConstant.php +++ /dev/null @@ -1,19 +0,0 @@ -assertSame(self::LEFT, self::RIGHT); - } -} diff --git a/tests/Rules/Complexity/NoMirrorAssertRule/Fixture/SkipNoTestCase.php b/tests/Rules/Complexity/NoMirrorAssertRule/Fixture/SkipNoTestCase.php deleted file mode 100644 index 6184a4a7..00000000 --- a/tests/Rules/Complexity/NoMirrorAssertRule/Fixture/SkipNoTestCase.php +++ /dev/null @@ -1,13 +0,0 @@ -assertSame(1, 1); - } -} diff --git a/tests/Rules/Complexity/NoMirrorAssertRule/Fixture/SkipNonAssertMirror.php b/tests/Rules/Complexity/NoMirrorAssertRule/Fixture/SkipNonAssertMirror.php deleted file mode 100644 index 55c1519b..00000000 --- a/tests/Rules/Complexity/NoMirrorAssertRule/Fixture/SkipNonAssertMirror.php +++ /dev/null @@ -1,19 +0,0 @@ -someMethodCall(1, 1); - } - - private function someMethodCall($first, $second) - { - } -} diff --git a/tests/Rules/Complexity/NoMirrorAssertRule/NoMirrorAssertRuleTest.php b/tests/Rules/Complexity/NoMirrorAssertRule/NoMirrorAssertRuleTest.php deleted file mode 100644 index 2d328255..00000000 --- a/tests/Rules/Complexity/NoMirrorAssertRule/NoMirrorAssertRuleTest.php +++ /dev/null @@ -1,49 +0,0 @@ - - */ -final class NoMirrorAssertRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[]|array> $expectedErrorsWithLines - */ - public function testRule(string $filePath, array $expectedErrorsWithLines): void - { - $this->analyse([$filePath], $expectedErrorsWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipDifferentConstant.php', []]; - yield [__DIR__ . '/Fixture/SkipDifferentAssert.php', []]; - yield [__DIR__ . '/Fixture/SkipNoTestCase.php', []]; - yield [__DIR__ . '/Fixture/SkipNonAssertMirror.php', []]; - - yield [__DIR__ . '/Fixture/SameConstant.php', [[NoMirrorAssertRule::ERROR_MESSAGE, 15]]]; - yield [__DIR__ . '/Fixture/AssertMirror.php', [[NoMirrorAssertRule::ERROR_MESSAGE, 13]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoMirrorAssertRule::class); - } -} diff --git a/tests/Rules/Complexity/NoMirrorAssertRule/config/configured_rule.neon b/tests/Rules/Complexity/NoMirrorAssertRule/config/configured_rule.neon deleted file mode 100644 index cc81a547..00000000 --- a/tests/Rules/Complexity/NoMirrorAssertRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\Complexity\NoMirrorAssertRule diff --git a/tests/Rules/DeadCode/UnusedPublicClassConstRule/Fixture/LocallyUsedPublicConstant.php b/tests/Rules/DeadCode/UnusedPublicClassConstRule/Fixture/LocallyUsedPublicConstant.php deleted file mode 100644 index 92f4ae7f..00000000 --- a/tests/Rules/DeadCode/UnusedPublicClassConstRule/Fixture/LocallyUsedPublicConstant.php +++ /dev/null @@ -1,15 +0,0 @@ - - */ -final class UnusedPublicClassConstRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param string[] $filePaths - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(array $filePaths, array $expectedErrorMessagesWithLines): void - { - $this->analyse($filePaths, $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - $errorMessage = sprintf(UnusedPublicClassConstRule::ERROR_MESSAGE, 'UNUSED'); - yield [[__DIR__ . '/Fixture/UnusedPublicConstant.php'], [[$errorMessage, 9]]]; - - $errorMessage = sprintf(UnusedPublicClassConstRule::ERROR_MESSAGE, 'UNUSED'); - yield [[__DIR__ . '/Fixture/UnusedPublicConstantFromInterface.php'], [[$errorMessage, 9]]]; - - $errorMessage = sprintf(UnusedPublicClassConstRule::ERROR_MESSAGE, 'LOCALLY_ONLY'); - yield [[__DIR__ . '/Fixture/LocallyUsedPublicConstant.php'], [[$errorMessage, 9]]]; - - yield [[__DIR__ . '/Fixture/SkipApiPublicConstant.php'], []]; - yield [[__DIR__ . '/Fixture/SkipPrivateConstant.php'], []]; - yield [[__DIR__ . '/Fixture/SkipApiClassPublicConstant.php'], []]; - yield [[__DIR__ . '/Fixture/SkipUsedPublicConstant.php', __DIR__ . '/Source/ConstantUser.php'], []]; - - yield [[__DIR__ . '/Fixture/SkipInterfaceConstantUsed.php', __DIR__ . '/Source/InterfaceConstantUser.php'], []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - /** - * @return array - */ - protected function getCollectors(): array - { - $publicClassLikeConstCollector = self::getContainer()->getByType(PublicClassLikeConstCollector::class); - return [new ClassConstFetchCollector(), $publicClassLikeConstCollector]; - } - - protected function getRule(): Rule - { - $container = self::getContainer(); - return $container->getByType(UnusedPublicClassConstRule::class); - } -} diff --git a/tests/Rules/DeadCode/UnusedPublicClassConstRule/config/configured_rule.neon b/tests/Rules/DeadCode/UnusedPublicClassConstRule/config/configured_rule.neon deleted file mode 100644 index 7d8c7e77..00000000 --- a/tests/Rules/DeadCode/UnusedPublicClassConstRule/config/configured_rule.neon +++ /dev/null @@ -1,11 +0,0 @@ -includes: - - ../../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\DeadCode\UnusedPublicClassConstRule - -services: - - - class: Symplify\PHPStanRules\Collector\ClassConst\PublicClassLikeConstCollector - tags: - - phpstan.collector diff --git a/tests/Rules/DeadCode/UnusedPublicClassMethodRule/Fixture/InterfaceWithExtraMethod.php b/tests/Rules/DeadCode/UnusedPublicClassMethodRule/Fixture/InterfaceWithExtraMethod.php deleted file mode 100644 index 910f7e7c..00000000 --- a/tests/Rules/DeadCode/UnusedPublicClassMethodRule/Fixture/InterfaceWithExtraMethod.php +++ /dev/null @@ -1,18 +0,0 @@ -runHere(); - } - - public function runHere() - { - } -} diff --git a/tests/Rules/DeadCode/UnusedPublicClassMethodRule/Fixture/SkipChildUsedPublicMethod.php b/tests/Rules/DeadCode/UnusedPublicClassMethodRule/Fixture/SkipChildUsedPublicMethod.php deleted file mode 100644 index 3e6754d0..00000000 --- a/tests/Rules/DeadCode/UnusedPublicClassMethodRule/Fixture/SkipChildUsedPublicMethod.php +++ /dev/null @@ -1,14 +0,0 @@ -fetchAll(); - } -} diff --git a/tests/Rules/DeadCode/UnusedPublicClassMethodRule/Fixture/SkipClassWithAttribute.php b/tests/Rules/DeadCode/UnusedPublicClassMethodRule/Fixture/SkipClassWithAttribute.php deleted file mode 100644 index b8df3f0a..00000000 --- a/tests/Rules/DeadCode/UnusedPublicClassMethodRule/Fixture/SkipClassWithAttribute.php +++ /dev/null @@ -1,15 +0,0 @@ -useMe(); - } -} diff --git a/tests/Rules/DeadCode/UnusedPublicClassMethodRule/Source/Contract/MethodRequiredInterface.php b/tests/Rules/DeadCode/UnusedPublicClassMethodRule/Source/Contract/MethodRequiredInterface.php deleted file mode 100644 index f92c56bc..00000000 --- a/tests/Rules/DeadCode/UnusedPublicClassMethodRule/Source/Contract/MethodRequiredInterface.php +++ /dev/null @@ -1,9 +0,0 @@ -useMeMaybe(); - } -} diff --git a/tests/Rules/DeadCode/UnusedPublicClassMethodRule/Source/ParentClassWithPublicMethod.php b/tests/Rules/DeadCode/UnusedPublicClassMethodRule/Source/ParentClassWithPublicMethod.php deleted file mode 100644 index b633f581..00000000 --- a/tests/Rules/DeadCode/UnusedPublicClassMethodRule/Source/ParentClassWithPublicMethod.php +++ /dev/null @@ -1,11 +0,0 @@ - - */ -final class UnusedPublicClassMethodRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param string[] $filePaths - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(array $filePaths, array $expectedErrorMessagesWithLines): void - { - $this->analyse($filePaths, $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - $errorMessage = sprintf(UnusedPublicClassMethodRule::ERROR_MESSAGE, 'runHere'); - yield [[__DIR__ . '/Fixture/LocallyUsedPublicMethod.php'], [[$errorMessage, 14]]]; - - $errorMessage = sprintf(UnusedPublicClassMethodRule::ERROR_MESSAGE, 'extraMethod'); - yield [[__DIR__ . '/Fixture/InterfaceWithExtraMethod.php'], [[$errorMessage, 15]]]; - - // public methods expected - yield [[__DIR__ . '/Fixture/SkipTestPublicMethod.php'], []]; - - // method required by parent - yield [[__DIR__ . '/Fixture/SkipParentMethodOverride.php'], []]; - yield [[__DIR__ . '/Fixture/SkipImplementsInterfaceCoveredByContract.php'], []]; - - yield [[__DIR__ . '/Fixture/SkipClassWithAttribute.php'], []]; - yield [[__DIR__ . '/Fixture/SkipStaticPublicMethod.php'], []]; - yield [[__DIR__ . '/Fixture/SkipPublicApiClassMethod.php'], []]; - yield [[__DIR__ . '/Fixture/SkipInterfaceMethod.php'], []]; - yield [[__DIR__ . '/Fixture/SkipPrivateClassMethod.php'], []]; - yield [[__DIR__ . '/Fixture/SkipUsedPublicMethod.php', __DIR__ . '/Source/ClassMethodCaller.php'], []]; - - yield [[ - __DIR__ . '/Fixture/SkipNullableUsedPublicMethod.php', __DIR__ . '/Source/NullableClassMethodCaller.php', ], - [], - ]; - - // parent abstract method used by child call - yield [[ - __DIR__ . '/Fixture/SkipChildUsedPublicMethod.php', - __DIR__ . '/Source/Repository/AbstractRepository.php', - __DIR__ . '/Source/Repository/ChildRepository.php', - ], []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - /** - * @return array - */ - protected function getCollectors(): array - { - $publicClassMethodCollector = self::getContainer()->getByType(PublicClassMethodCollector::class); - $methodCallCollector = self::getContainer()->getByType(MethodCallCollector::class); - - return [$methodCallCollector, $publicClassMethodCollector]; - } - - protected function getRule(): Rule - { - $container = self::getContainer(); - return $container->getByType(UnusedPublicClassMethodRule::class); - } -} diff --git a/tests/Rules/DeadCode/UnusedPublicClassMethodRule/config/configured_rule.neon b/tests/Rules/DeadCode/UnusedPublicClassMethodRule/config/configured_rule.neon deleted file mode 100644 index d45239b3..00000000 --- a/tests/Rules/DeadCode/UnusedPublicClassMethodRule/config/configured_rule.neon +++ /dev/null @@ -1,16 +0,0 @@ -includes: - - ../../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\DeadCode\UnusedPublicClassMethodRule - -services: - - - class: Symplify\PHPStanRules\Collector\ClassMethod\PublicClassMethodCollector - tags: - - phpstan.collector - - - - class: Symplify\PHPStanRules\Collector\ClassMethod\MethodCallCollector - tags: - - phpstan.collector diff --git a/tests/Rules/Domain/NoDuplicatedRegexRule/Fixture/DuplicatedRegexConst.php b/tests/Rules/Domain/NoDuplicatedRegexRule/Fixture/DuplicatedRegexConst.php deleted file mode 100644 index 5461c0b5..00000000 --- a/tests/Rules/Domain/NoDuplicatedRegexRule/Fixture/DuplicatedRegexConst.php +++ /dev/null @@ -1,12 +0,0 @@ - - */ -final class NoDuplicatedRegexRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param string[] $filePaths - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(array $filePaths, array $expectedErrorMessagesWithLines): void - { - $this->analyse($filePaths, $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - $firstErrorMessage = sprintf(NoDuplicatedRegexRule::ERROR_MESSAGE, 'FIRST_REGEX', "#\d+#"); - $secondErrorMessage = sprintf(NoDuplicatedRegexRule::ERROR_MESSAGE, 'SECOND_REGEX', "#\d+#"); - - yield [[__DIR__ . '/Fixture/DuplicatedRegexConst.php'], [ - [$firstErrorMessage, 9], - [$secondErrorMessage, 11], - ]]; - - yield [[__DIR__ . '/Fixture/SkipUniqueRegexConst.php'], []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoDuplicatedRegexRule::class); - } - - /** - * @return Collector[] - */ - protected function getCollectors(): array - { - $regexClassConstCollector = self::getContainer()->getByType(RegexClassConstCollector::class); - return [$regexClassConstCollector]; - } -} diff --git a/tests/Rules/Domain/NoDuplicatedRegexRule/config/configured_rule.neon b/tests/Rules/Domain/NoDuplicatedRegexRule/config/configured_rule.neon deleted file mode 100644 index 4b120dd6..00000000 --- a/tests/Rules/Domain/NoDuplicatedRegexRule/config/configured_rule.neon +++ /dev/null @@ -1,11 +0,0 @@ -includes: - - ../../../../config/included_services.neon - -services: - - - class: Symplify\PHPStanRules\Rules\Domain\NoDuplicatedRegexRule - tags: [phpstan.rules.rule] - - - - class: Symplify\PHPStanRules\Collector\ClassConst\RegexClassConstCollector - tags: [phpstan.collector] diff --git a/tests/Rules/Domain/RequireAttributeNamespaceRule/Fixture/Attribute/SkipCorrectAttribute.php b/tests/Rules/Domain/RequireAttributeNamespaceRule/Fixture/Attribute/SkipCorrectAttribute.php deleted file mode 100644 index bfc2a1dd..00000000 --- a/tests/Rules/Domain/RequireAttributeNamespaceRule/Fixture/Attribute/SkipCorrectAttribute.php +++ /dev/null @@ -1,10 +0,0 @@ - - */ -final class RequireAttributeNamespaceRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/MisslocatedAttribute.php', [[RequireAttributeNamespaceRule::ERROR_MESSAGE, 7]]]; - yield [__DIR__ . '/Fixture/Attribute/SkipCorrectAttribute.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(RequireAttributeNamespaceRule::class); - } -} diff --git a/tests/Rules/Domain/RequireAttributeNamespaceRule/config/configured_rule.neon b/tests/Rules/Domain/RequireAttributeNamespaceRule/config/configured_rule.neon deleted file mode 100644 index 5443e442..00000000 --- a/tests/Rules/Domain/RequireAttributeNamespaceRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\Domain\RequireAttributeNamespaceRule diff --git a/tests/Rules/Domain/RequireExceptionNamespaceRule/Fixture/Exception/SkipCorrectException.php b/tests/Rules/Domain/RequireExceptionNamespaceRule/Fixture/Exception/SkipCorrectException.php deleted file mode 100644 index 8e0aa4e8..00000000 --- a/tests/Rules/Domain/RequireExceptionNamespaceRule/Fixture/Exception/SkipCorrectException.php +++ /dev/null @@ -1,9 +0,0 @@ - - */ -final class RequireExceptionNamespaceRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/MisslocatedException.php', [[RequireExceptionNamespaceRule::ERROR_MESSAGE, 7]]]; - yield [__DIR__ . '/Fixture/Exception/SkipCorrectException.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(RequireExceptionNamespaceRule::class); - } -} diff --git a/tests/Rules/Domain/RequireExceptionNamespaceRule/config/configured_rule.neon b/tests/Rules/Domain/RequireExceptionNamespaceRule/config/configured_rule.neon deleted file mode 100644 index d344fc41..00000000 --- a/tests/Rules/Domain/RequireExceptionNamespaceRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\Domain\RequireExceptionNamespaceRule diff --git a/tests/Rules/Enum/EmbeddedEnumClassConstSpotterRule/EmbeddedEnumClassConstSpotterRuleTest.php b/tests/Rules/Enum/EmbeddedEnumClassConstSpotterRule/EmbeddedEnumClassConstSpotterRuleTest.php deleted file mode 100644 index fc119405..00000000 --- a/tests/Rules/Enum/EmbeddedEnumClassConstSpotterRule/EmbeddedEnumClassConstSpotterRuleTest.php +++ /dev/null @@ -1,50 +0,0 @@ - - */ -final class EmbeddedEnumClassConstSpotterRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[]|array> $expectedErrorsWithLines - */ - public function testRule(string $filePath, array $expectedErrorsWithLines): void - { - $this->analyse([$filePath], $expectedErrorsWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipVariousConstantName.php', []]; - yield [__DIR__ . '/Fixture/SkipMinMax.php', []]; - yield [__DIR__ . '/Fixture/SkipMinMaxMultiple.php', []]; - - $errorMessage = \sprintf(EmbeddedEnumClassConstSpotterRule::ERROR_MESSAGE, 'TYPE_ACTIVE", "TYPE_PASSIVE'); - yield [__DIR__ . '/Fixture/ClassWithEnums.php', [[$errorMessage, 9]]]; - - yield [__DIR__ . '/Fixture/MixOfMultipleClassWithEnums.php', [[$errorMessage, 9]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(EmbeddedEnumClassConstSpotterRule::class); - } -} diff --git a/tests/Rules/Enum/EmbeddedEnumClassConstSpotterRule/Fixture/ClassWithEnums.php b/tests/Rules/Enum/EmbeddedEnumClassConstSpotterRule/Fixture/ClassWithEnums.php deleted file mode 100644 index 4442cf4a..00000000 --- a/tests/Rules/Enum/EmbeddedEnumClassConstSpotterRule/Fixture/ClassWithEnums.php +++ /dev/null @@ -1,14 +0,0 @@ - - */ -final class NoConstantInterfaceRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipInterfaceWithMethods.php', []]; - yield [__DIR__ . '/Fixture/InterfaceWithConstants.php', [[NoConstantInterfaceRule::ERROR_MESSAGE, 7]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoConstantInterfaceRule::class); - } -} diff --git a/tests/Rules/Enum/NoConstantInterfaceRule/config/configured_rule.neon b/tests/Rules/Enum/NoConstantInterfaceRule/config/configured_rule.neon deleted file mode 100644 index 39acc4ff..00000000 --- a/tests/Rules/Enum/NoConstantInterfaceRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\Enum\NoConstantInterfaceRule diff --git a/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Fixture/IntersectionNode.php b/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Fixture/IntersectionNode.php deleted file mode 100644 index c563e273..00000000 --- a/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Fixture/IntersectionNode.php +++ /dev/null @@ -1,19 +0,0 @@ -getAttribute('parent'); - } -} diff --git a/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Fixture/NestedNode.php b/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Fixture/NestedNode.php deleted file mode 100644 index d3fc305b..00000000 --- a/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Fixture/NestedNode.php +++ /dev/null @@ -1,21 +0,0 @@ -getAttribute('parent'); - if (! $parent instanceof Arg) { - return false; - } - - return $parent->getAttribute('parent'); - } -} diff --git a/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Fixture/SkipWithConstant.php b/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Fixture/SkipWithConstant.php deleted file mode 100644 index 606f7ddd..00000000 --- a/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Fixture/SkipWithConstant.php +++ /dev/null @@ -1,21 +0,0 @@ -call(self::TYPE); - } -} diff --git a/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Fixture/SkipWithConstantExternal.php b/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Fixture/SkipWithConstantExternal.php deleted file mode 100644 index fc48a23d..00000000 --- a/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Fixture/SkipWithConstantExternal.php +++ /dev/null @@ -1,17 +0,0 @@ -call(SomeConstantList::TYPE); - } -} diff --git a/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Fixture/SkipWithConstantLocal.php b/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Fixture/SkipWithConstantLocal.php deleted file mode 100644 index baf44165..00000000 --- a/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Fixture/SkipWithConstantLocal.php +++ /dev/null @@ -1,21 +0,0 @@ -call(self::TYPE); - } -} diff --git a/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Fixture/SkipWithVariable.php b/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Fixture/SkipWithVariable.php deleted file mode 100644 index 7c40aa65..00000000 --- a/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Fixture/SkipWithVariable.php +++ /dev/null @@ -1,16 +0,0 @@ -call($variable); - } -} diff --git a/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Fixture/SomeMethodCallWithoutConstant.php b/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Fixture/SomeMethodCallWithoutConstant.php deleted file mode 100644 index 977e461b..00000000 --- a/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Fixture/SomeMethodCallWithoutConstant.php +++ /dev/null @@ -1,16 +0,0 @@ -call('some_type'); - } -} diff --git a/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Fixture/SomeMethodCallWithoutConstantExternal.php b/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Fixture/SomeMethodCallWithoutConstantExternal.php deleted file mode 100644 index c5e6f9e6..00000000 --- a/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Fixture/SomeMethodCallWithoutConstantExternal.php +++ /dev/null @@ -1,16 +0,0 @@ -call('some_type'); - } -} diff --git a/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Fixture/SomeMethodCallWithoutConstantLocal.php b/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Fixture/SomeMethodCallWithoutConstantLocal.php deleted file mode 100644 index 0bee77d1..00000000 --- a/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Fixture/SomeMethodCallWithoutConstantLocal.php +++ /dev/null @@ -1,16 +0,0 @@ -call('some_type'); - } -} diff --git a/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Fixture/SymfonyPHPConfigParameterSetter.php b/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Fixture/SymfonyPHPConfigParameterSetter.php deleted file mode 100644 index 0f73dfd0..00000000 --- a/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Fixture/SymfonyPHPConfigParameterSetter.php +++ /dev/null @@ -1,16 +0,0 @@ -parameters(); - $parameters->set('key', 'value'); - } -} diff --git a/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/RequireConstantInMethodCallPositionRuleTest.php b/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/RequireConstantInMethodCallPositionRuleTest.php deleted file mode 100644 index e45b3552..00000000 --- a/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/RequireConstantInMethodCallPositionRuleTest.php +++ /dev/null @@ -1,61 +0,0 @@ - - */ -final class RequireConstantInMethodCallPositionRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipWithConstantLocal.php', []]; - yield [__DIR__ . '/Fixture/SkipWithConstantExternal.php', []]; - yield [__DIR__ . '/Fixture/SkipWithVariable.php', []]; - - $errorMessageLocal = sprintf(RequireConstantInMethodCallPositionRule::ERROR_MESSAGE, 0); - yield [__DIR__ . '/Fixture/SomeMethodCallWithoutConstantLocal.php', [[$errorMessageLocal, 14]]]; - - $errorMessageExternal = sprintf(RequireConstantInMethodCallPositionRule::ERROR_MESSAGE, 0); - yield [__DIR__ . '/Fixture/SomeMethodCallWithoutConstantExternal.php', [[$errorMessageExternal, 14]]]; - - yield [__DIR__ . '/Fixture/SkipWithConstant.php', []]; - yield [__DIR__ . '/Fixture/SkipWithVariable.php', []]; - - $errorMessage = sprintf(RequireConstantInMethodCallPositionRule::ERROR_MESSAGE, 0); - yield [__DIR__ . '/Fixture/SomeMethodCallWithoutConstant.php', [[$errorMessage, 14]]]; - yield [__DIR__ . '/Fixture/SymfonyPHPConfigParameterSetter.php', [[$errorMessage, 14]]]; - - yield [__DIR__ . '/Fixture/NestedNode.php', [[$errorMessage, 14], [$errorMessage, 19]]]; - yield [__DIR__ . '/Fixture/IntersectionNode.php', [[$errorMessage, 17]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(RequireConstantInMethodCallPositionRule::class); - } -} diff --git a/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Source/AlwaysCallMeWithConstant.php b/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Source/AlwaysCallMeWithConstant.php deleted file mode 100644 index c0b881f8..00000000 --- a/tests/Rules/Enum/RequireConstantInMethodCallPositionRule/Source/AlwaysCallMeWithConstant.php +++ /dev/null @@ -1,12 +0,0 @@ -turn(Direction::LEFT); - } - - private function turn(string $direction) - { - } -} diff --git a/tests/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule/Fixture/ExternalNoType.php b/tests/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule/Fixture/ExternalNoType.php deleted file mode 100644 index 363511bc..00000000 --- a/tests/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule/Fixture/ExternalNoType.php +++ /dev/null @@ -1,17 +0,0 @@ -turn(Direction::LEFT); - } -} diff --git a/tests/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule/Fixture/OnePositionCovered.php b/tests/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule/Fixture/OnePositionCovered.php deleted file mode 100644 index fbc11d3a..00000000 --- a/tests/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule/Fixture/OnePositionCovered.php +++ /dev/null @@ -1,22 +0,0 @@ -turn(Direction::LEFT, Direction::RIGHT); - } - - /** - * @param Direction::* $direction - */ - private function turn(string $direction, string $otherDirection) - { - } -} diff --git a/tests/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule/Fixture/SkipClassConstReference.php b/tests/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule/Fixture/SkipClassConstReference.php deleted file mode 100644 index d04b38f1..00000000 --- a/tests/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule/Fixture/SkipClassConstReference.php +++ /dev/null @@ -1,16 +0,0 @@ -turn(Direction::class); - } -} diff --git a/tests/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule/Fixture/SkipExternalCarWithType.php b/tests/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule/Fixture/SkipExternalCarWithType.php deleted file mode 100644 index ca942c56..00000000 --- a/tests/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule/Fixture/SkipExternalCarWithType.php +++ /dev/null @@ -1,16 +0,0 @@ -turn(Direction::LEFT); - } -} diff --git a/tests/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule/Fixture/SkipMoreStrings.php b/tests/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule/Fixture/SkipMoreStrings.php deleted file mode 100644 index 405849cd..00000000 --- a/tests/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule/Fixture/SkipMoreStrings.php +++ /dev/null @@ -1,23 +0,0 @@ -turn(Direction::LEFT, 'three'); - } - - /** - * @param Direction::* $direction - */ - private function turn(string $direction, string $gear) - { - } -} diff --git a/tests/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule/Fixture/SkipParameterProvider.php b/tests/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule/Fixture/SkipParameterProvider.php deleted file mode 100644 index 6f91eaf7..00000000 --- a/tests/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule/Fixture/SkipParameterProvider.php +++ /dev/null @@ -1,15 +0,0 @@ -provideParameter(ParameterName::SOURCE); - } -} diff --git a/tests/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule/Fixture/SkipSelfReference.php b/tests/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule/Fixture/SkipSelfReference.php deleted file mode 100644 index c0ac2ef3..00000000 --- a/tests/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule/Fixture/SkipSelfReference.php +++ /dev/null @@ -1,17 +0,0 @@ -turn(self::DIRECTION_LEFT); - } -} diff --git a/tests/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule/Fixture/SkipWithEnumLikeType.php b/tests/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule/Fixture/SkipWithEnumLikeType.php deleted file mode 100644 index 218985f4..00000000 --- a/tests/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule/Fixture/SkipWithEnumLikeType.php +++ /dev/null @@ -1,22 +0,0 @@ -turn(Direction::LEFT); - } - - /** - * @param Direction::* $direction - */ - private function turn(string $direction) - { - } -} diff --git a/tests/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule/RequireEnumDocBlockOnConstantListPassRuleTest.php b/tests/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule/RequireEnumDocBlockOnConstantListPassRuleTest.php deleted file mode 100644 index 101ec284..00000000 --- a/tests/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule/RequireEnumDocBlockOnConstantListPassRuleTest.php +++ /dev/null @@ -1,63 +0,0 @@ - - */ -final class RequireEnumDocBlockOnConstantListPassRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorsWithLines - */ - public function testRule(string $filePath, array $expectedErrorsWithLines): void - { - $this->analyse([$filePath], $expectedErrorsWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipWithEnumLikeType.php', []]; - yield [__DIR__ . '/Fixture/SkipMoreStrings.php', []]; - yield [__DIR__ . '/Fixture/SkipExternalCarWithType.php', []]; - yield [__DIR__ . '/Fixture/SkipClassConstReference.php', []]; - yield [__DIR__ . '/Fixture/SkipSelfReference.php', []]; - yield [__DIR__ . '/Fixture/SkipParameterProvider.php', []]; - - yield [ - __DIR__ . '/Fixture/ClassWithoutParamEnumType.php', - [[RequireEnumDocBlockOnConstantListPassRule::ERROR_MESSAGE, 13]], - ]; - - yield [ - __DIR__ . '/Fixture/OnePositionCovered.php', - [[RequireEnumDocBlockOnConstantListPassRule::ERROR_MESSAGE, 13]], - ]; - - yield [ - __DIR__ . '/Fixture/ExternalNoType.php', - [[RequireEnumDocBlockOnConstantListPassRule::ERROR_MESSAGE, 15]], - ]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(RequireEnumDocBlockOnConstantListPassRule::class); - } -} diff --git a/tests/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule/Source/Direction.php b/tests/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule/Source/Direction.php deleted file mode 100644 index 73c7f7ea..00000000 --- a/tests/Rules/Enum/RequireEnumDocBlockOnConstantListPassRule/Source/Direction.php +++ /dev/null @@ -1,12 +0,0 @@ - - */ -final class RequireNewArgumentConstantRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkippedInstance.php', []]; - yield [__DIR__ . '/Fixture/SkipInputOptionInstanceWithConstantParameter.php', []]; - - yield [__DIR__ . '/Fixture/InputOptionInstanceWithNonConstantParameter.php', [ - [sprintf(RequireNewArgumentConstantRule::ERROR_MESSAGE, 2), 9], - ]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(RequireNewArgumentConstantRule::class); - } -} diff --git a/tests/Rules/Enum/RequireNewArgumentConstantRule/config/configured_rule.neon b/tests/Rules/Enum/RequireNewArgumentConstantRule/config/configured_rule.neon deleted file mode 100644 index cc2b72e5..00000000 --- a/tests/Rules/Enum/RequireNewArgumentConstantRule/config/configured_rule.neon +++ /dev/null @@ -1,7 +0,0 @@ -services: - - - class: Symplify\PHPStanRules\Rules\Enum\RequireNewArgumentConstantRule - tags: [phpstan.rules.rule] - arguments: - constantArgByNewByType: - Symfony\Component\Console\Input\InputOption: [2] diff --git a/tests/Rules/Enum/RequireUniqueEnumConstantRule/Fixture/InvalidAnnotationEnum.php b/tests/Rules/Enum/RequireUniqueEnumConstantRule/Fixture/InvalidAnnotationEnum.php deleted file mode 100644 index a50ff5c8..00000000 --- a/tests/Rules/Enum/RequireUniqueEnumConstantRule/Fixture/InvalidAnnotationEnum.php +++ /dev/null @@ -1,15 +0,0 @@ - - */ -final class RequireUniqueEnumConstantRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - $expectedErrorMessage = sprintf(RequireUniqueEnumConstantRule::ERROR_MESSAGE, 'yes'); - yield [__DIR__ . '/Fixture/InvalidEnum.php', [[$expectedErrorMessage, 8]]]; - yield [__DIR__ . '/Fixture/InvalidAnnotationEnum.php', [[$expectedErrorMessage, 8]]]; - - yield [__DIR__ . '/Fixture/SkipValidEnum.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(RequireUniqueEnumConstantRule::class); - } -} diff --git a/tests/Rules/Enum/RequireUniqueEnumConstantRule/config/configured_rule.neon b/tests/Rules/Enum/RequireUniqueEnumConstantRule/config/configured_rule.neon deleted file mode 100644 index 317a3057..00000000 --- a/tests/Rules/Enum/RequireUniqueEnumConstantRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\Enum\RequireUniqueEnumConstantRule diff --git a/tests/Rules/ExclusiveDependencyRule/ExclusiveDependencyRuleTest.php b/tests/Rules/ExclusiveDependencyRule/ExclusiveDependencyRuleTest.php deleted file mode 100644 index 4a682590..00000000 --- a/tests/Rules/ExclusiveDependencyRule/ExclusiveDependencyRuleTest.php +++ /dev/null @@ -1,59 +0,0 @@ - - */ -final class ExclusiveDependencyRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - /** - * @return Iterator - */ - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipNotSpecified.php', []]; - yield [__DIR__ . '/Fixture/SkipSomeRepository.php', []]; - yield [__DIR__ . '/Fixture/SkipAllowedEventSubscriber.php', []]; - - $errorMessage = sprintf( - ExclusiveDependencyRule::ERROR_MESSAGE, - EntityManager::class, - implode('", "', [AllowedEventSubscriber::class, '*Repository']) - ); - - yield [__DIR__ . '/Fixture/SomeController.php', [[$errorMessage, 9]]]; - yield [__DIR__ . '/Fixture/WarnController.php', [[$errorMessage, 16]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(ExclusiveDependencyRule::class); - } -} diff --git a/tests/Rules/ExclusiveDependencyRule/Fixture/SkipAllowedEventSubscriber.php b/tests/Rules/ExclusiveDependencyRule/Fixture/SkipAllowedEventSubscriber.php deleted file mode 100644 index 981c6eb2..00000000 --- a/tests/Rules/ExclusiveDependencyRule/Fixture/SkipAllowedEventSubscriber.php +++ /dev/null @@ -1,16 +0,0 @@ -entityManager = $entityManager; - } -} diff --git a/tests/Rules/ExclusiveDependencyRule/Fixture/SomeController.php b/tests/Rules/ExclusiveDependencyRule/Fixture/SomeController.php deleted file mode 100644 index 74c88ea4..00000000 --- a/tests/Rules/ExclusiveDependencyRule/Fixture/SomeController.php +++ /dev/null @@ -1,13 +0,0 @@ -entityManager = $entityManager; - } -} diff --git a/tests/Rules/ExclusiveDependencyRule/Source/AllowedEventSubscriber.php b/tests/Rules/ExclusiveDependencyRule/Source/AllowedEventSubscriber.php deleted file mode 100644 index 2510c11d..00000000 --- a/tests/Rules/ExclusiveDependencyRule/Source/AllowedEventSubscriber.php +++ /dev/null @@ -1,9 +0,0 @@ - - */ -final class ExclusiveNamespaceRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - $errorMessage = sprintf( - ExclusiveNamespaceRule::ERROR_MESSAGE, - 'Symplify\PHPStanRules\Tests\Rules\ExclusiveNamespaceRule\Fixture\Presenter', - 'Presenter' - ); - yield [__DIR__ . '/Fixture/Presenter/SomeRepository.php', [[$errorMessage, 7]]]; - - yield [__DIR__ . '/Fixture/Presenter/Contract/SkipContract.php', []]; - yield [__DIR__ . '/Fixture/Presenter/Exception/SkipException.php', []]; - yield [__DIR__ . '/Fixture/Presenter/SkipSomeTest.php', []]; - yield [__DIR__ . '/Fixture/Presenter/SkipPresenter.php', []]; - yield [__DIR__ . '/Fixture/SkipNotMatched.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(ExclusiveNamespaceRule::class); - } -} diff --git a/tests/Rules/ExclusiveNamespaceRule/Fixture/Presenter/Contract/SkipContract.php b/tests/Rules/ExclusiveNamespaceRule/Fixture/Presenter/Contract/SkipContract.php deleted file mode 100644 index 19627262..00000000 --- a/tests/Rules/ExclusiveNamespaceRule/Fixture/Presenter/Contract/SkipContract.php +++ /dev/null @@ -1,10 +0,0 @@ - - */ -final class ExplicitMethodCallOverMagicGetSetRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorsWithLines - */ - public function testRule(string $filePath, array $expectedErrorsWithLines): void - { - $this->analyse([$filePath], $expectedErrorsWithLines); - } - - public function provideData(): Iterator - { - $getterErrorMessage = \sprintf( - ExplicitMethodCallOverMagicGetSetRule::ERROR_MESSAGE, - 'id', - '$someSmartObject', - 'getId' - ); - yield [__DIR__ . '/Fixture/MagicGetter.php', [[$getterErrorMessage, 13]]]; - - $setterErrorMessage = \sprintf( - ExplicitMethodCallOverMagicGetSetRule::ERROR_MESSAGE, - 'id', - '$someSmartObject', - 'setId' - ); - yield [__DIR__ . '/Fixture/MagicSetter.php', [[$setterErrorMessage, 13]]]; - - $boolGetterErrorMessage = \sprintf( - ExplicitMethodCallOverMagicGetSetRule::ERROR_MESSAGE, - 'valid', - '$someSmartObject', - 'isValid' - ); - yield [__DIR__ . '/Fixture/MagicIsGetter.php', [[$boolGetterErrorMessage, 16]]]; - - yield [__DIR__ . '/Fixture/SkipNormalPropertyFetch.php', []]; - yield [__DIR__ . '/Fixture/SkipPrivateMethod.php', []]; - yield [__DIR__ . '/Fixture/SkipAssignToPositions.php', []]; - yield [__DIR__ . '/Fixture/SkipLocalGetter.php', []]; - yield [__DIR__ . '/Fixture/SkipGetterOnObjectWithoutMagicGet.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(ExplicitMethodCallOverMagicGetSetRule::class); - } -} diff --git a/tests/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule/Fixture/MagicGetter.php b/tests/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule/Fixture/MagicGetter.php deleted file mode 100644 index 3126604a..00000000 --- a/tests/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule/Fixture/MagicGetter.php +++ /dev/null @@ -1,15 +0,0 @@ -id; - } -} diff --git a/tests/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule/Fixture/MagicIsGetter.php b/tests/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule/Fixture/MagicIsGetter.php deleted file mode 100644 index b5aba947..00000000 --- a/tests/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule/Fixture/MagicIsGetter.php +++ /dev/null @@ -1,18 +0,0 @@ -valid; - } -} diff --git a/tests/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule/Fixture/MagicSetter.php b/tests/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule/Fixture/MagicSetter.php deleted file mode 100644 index e62cbd1d..00000000 --- a/tests/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule/Fixture/MagicSetter.php +++ /dev/null @@ -1,15 +0,0 @@ -id = 100; - } -} diff --git a/tests/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule/Fixture/SkipAssignToPositions.php b/tests/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule/Fixture/SkipAssignToPositions.php deleted file mode 100644 index 9ad64780..00000000 --- a/tests/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule/Fixture/SkipAssignToPositions.php +++ /dev/null @@ -1,15 +0,0 @@ -assignedProperty = 1000; - } -} diff --git a/tests/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule/Fixture/SkipGetterOnObjectWithoutMagicGet.php b/tests/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule/Fixture/SkipGetterOnObjectWithoutMagicGet.php deleted file mode 100644 index 8b795a1f..00000000 --- a/tests/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule/Fixture/SkipGetterOnObjectWithoutMagicGet.php +++ /dev/null @@ -1,15 +0,0 @@ -id; - } -} diff --git a/tests/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule/Fixture/SkipLocalGetter.php b/tests/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule/Fixture/SkipLocalGetter.php deleted file mode 100644 index 2380b1f0..00000000 --- a/tests/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule/Fixture/SkipLocalGetter.php +++ /dev/null @@ -1,19 +0,0 @@ -value; - } -} diff --git a/tests/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule/Fixture/SkipNormalPropertyFetch.php b/tests/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule/Fixture/SkipNormalPropertyFetch.php deleted file mode 100644 index 8ecf1fb1..00000000 --- a/tests/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule/Fixture/SkipNormalPropertyFetch.php +++ /dev/null @@ -1,15 +0,0 @@ -normalProperty; - } -} diff --git a/tests/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule/Fixture/SkipPrivateMethod.php b/tests/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule/Fixture/SkipPrivateMethod.php deleted file mode 100644 index 7c1fa083..00000000 --- a/tests/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule/Fixture/SkipPrivateMethod.php +++ /dev/null @@ -1,15 +0,0 @@ -privateMethod; - } -} diff --git a/tests/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule/Source/AbstractMagicGet.php b/tests/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule/Source/AbstractMagicGet.php deleted file mode 100644 index 9ba7a7e7..00000000 --- a/tests/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule/Source/AbstractMagicGet.php +++ /dev/null @@ -1,13 +0,0 @@ -id; - } - - public $normalProperty; -} diff --git a/tests/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule/Source/SomeObjectWithMagicGet.php b/tests/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule/Source/SomeObjectWithMagicGet.php deleted file mode 100644 index 3815e727..00000000 --- a/tests/Rules/Explicit/ExplicitMethodCallOverMagicGetSetRule/Source/SomeObjectWithMagicGet.php +++ /dev/null @@ -1,27 +0,0 @@ - - */ -final class NoDuplicatedVariableCasingNameRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorsWithLines - */ - public function testRule(string $filePath, array $expectedErrorsWithLines): void - { - $this->analyse([$filePath], $expectedErrorsWithLines); - } - - public function provideData(): Iterator - { - $firstErrorMessage = sprintf(NoDuplicatedVariableCasingNameRule::ERROR_MESSAGE, 'value', 'value'); - $secondErrorMessage = sprintf(NoDuplicatedVariableCasingNameRule::ERROR_MESSAGE, 'value', 'valUE'); - - yield [__DIR__ . '/Fixture/DifferentCasingNames.php', [ - [$firstErrorMessage, 11], - [$secondErrorMessage, 13], - ]]; - - yield [__DIR__ . '/Fixture/SkipUnitedName.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - /** - * @return Collector[] - */ - protected function getCollectors(): array - { - return [new VariableNameCollector()]; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoDuplicatedVariableCasingNameRule::class); - } -} diff --git a/tests/Rules/Explicit/NoDuplicatedVariableCasingNameRule/config/configured_rule.neon b/tests/Rules/Explicit/NoDuplicatedVariableCasingNameRule/config/configured_rule.neon deleted file mode 100644 index cb77b5c0..00000000 --- a/tests/Rules/Explicit/NoDuplicatedVariableCasingNameRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\Explicit\NoDuplicatedVariableCasingNameRule diff --git a/tests/Rules/Explicit/NoGetterAndPropertyRule/Fixture/PublicAndIsser.php b/tests/Rules/Explicit/NoGetterAndPropertyRule/Fixture/PublicAndIsser.php deleted file mode 100644 index 0f00ca15..00000000 --- a/tests/Rules/Explicit/NoGetterAndPropertyRule/Fixture/PublicAndIsser.php +++ /dev/null @@ -1,15 +0,0 @@ -isEnabled(); - } -} diff --git a/tests/Rules/Explicit/NoGetterAndPropertyRule/Fixture/SkipPrivateMethod.php b/tests/Rules/Explicit/NoGetterAndPropertyRule/Fixture/SkipPrivateMethod.php deleted file mode 100644 index c2368b65..00000000 --- a/tests/Rules/Explicit/NoGetterAndPropertyRule/Fixture/SkipPrivateMethod.php +++ /dev/null @@ -1,15 +0,0 @@ -name; - } -} diff --git a/tests/Rules/Explicit/NoGetterAndPropertyRule/Fixture/SkipProtectedProperty.php b/tests/Rules/Explicit/NoGetterAndPropertyRule/Fixture/SkipProtectedProperty.php deleted file mode 100644 index b8ffe5e2..00000000 --- a/tests/Rules/Explicit/NoGetterAndPropertyRule/Fixture/SkipProtectedProperty.php +++ /dev/null @@ -1,15 +0,0 @@ -name; - } -} diff --git a/tests/Rules/Explicit/NoGetterAndPropertyRule/Fixture/SomeClassWithPublicAndGetter.php b/tests/Rules/Explicit/NoGetterAndPropertyRule/Fixture/SomeClassWithPublicAndGetter.php deleted file mode 100644 index 56bb75ea..00000000 --- a/tests/Rules/Explicit/NoGetterAndPropertyRule/Fixture/SomeClassWithPublicAndGetter.php +++ /dev/null @@ -1,15 +0,0 @@ -name; - } -} diff --git a/tests/Rules/Explicit/NoGetterAndPropertyRule/NoGetterAndPropertyRuleTest.php b/tests/Rules/Explicit/NoGetterAndPropertyRule/NoGetterAndPropertyRuleTest.php deleted file mode 100644 index fa178191..00000000 --- a/tests/Rules/Explicit/NoGetterAndPropertyRule/NoGetterAndPropertyRuleTest.php +++ /dev/null @@ -1,50 +0,0 @@ - - */ -final class NoGetterAndPropertyRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorsWithLines - */ - public function testRule(string $filePath, array $expectedErrorsWithLines): void - { - $this->analyse([$filePath], $expectedErrorsWithLines); - } - - public function provideData(): Iterator - { - $boolGetterErrorMessage = \sprintf(NoGetterAndPropertyRule::ERROR_MESSAGE, 'enabled'); - yield [__DIR__ . '/Fixture/PublicAndIsser.php', [[$boolGetterErrorMessage, 7]]]; - - $boolGetterErrorMessage = \sprintf(NoGetterAndPropertyRule::ERROR_MESSAGE, 'name'); - yield [__DIR__ . '/Fixture/SomeClassWithPublicAndGetter.php', [[$boolGetterErrorMessage, 7]]]; - - yield [__DIR__ . '/Fixture/SkipPrivateMethod.php', []]; - yield [__DIR__ . '/Fixture/SkipProtectedProperty.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoGetterAndPropertyRule::class); - } -} diff --git a/tests/Rules/Explicit/NoGetterAndPropertyRule/config/configured_rule.neon b/tests/Rules/Explicit/NoGetterAndPropertyRule/config/configured_rule.neon deleted file mode 100644 index df0726a1..00000000 --- a/tests/Rules/Explicit/NoGetterAndPropertyRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\Explicit\NoGetterAndPropertyRule diff --git a/tests/Rules/Explicit/NoMissingArrayShapeReturnArrayRule/Fixture/MissingShape.php b/tests/Rules/Explicit/NoMissingArrayShapeReturnArrayRule/Fixture/MissingShape.php deleted file mode 100644 index 5afe8bee..00000000 --- a/tests/Rules/Explicit/NoMissingArrayShapeReturnArrayRule/Fixture/MissingShape.php +++ /dev/null @@ -1,13 +0,0 @@ - $name]; - } -} diff --git a/tests/Rules/Explicit/NoMissingArrayShapeReturnArrayRule/Fixture/MissingShapeWithArray.php b/tests/Rules/Explicit/NoMissingArrayShapeReturnArrayRule/Fixture/MissingShapeWithArray.php deleted file mode 100644 index 25434b8c..00000000 --- a/tests/Rules/Explicit/NoMissingArrayShapeReturnArrayRule/Fixture/MissingShapeWithArray.php +++ /dev/null @@ -1,13 +0,0 @@ - $name]; - } -} diff --git a/tests/Rules/Explicit/NoMissingArrayShapeReturnArrayRule/Fixture/SkipClassList.php b/tests/Rules/Explicit/NoMissingArrayShapeReturnArrayRule/Fixture/SkipClassList.php deleted file mode 100644 index 2e810ba3..00000000 --- a/tests/Rules/Explicit/NoMissingArrayShapeReturnArrayRule/Fixture/SkipClassList.php +++ /dev/null @@ -1,16 +0,0 @@ - ['onPrepare', -5], - ]; - } -} diff --git a/tests/Rules/Explicit/NoMissingArrayShapeReturnArrayRule/Fixture/SkipKnownShape.php b/tests/Rules/Explicit/NoMissingArrayShapeReturnArrayRule/Fixture/SkipKnownShape.php deleted file mode 100644 index cf9b9f20..00000000 --- a/tests/Rules/Explicit/NoMissingArrayShapeReturnArrayRule/Fixture/SkipKnownShape.php +++ /dev/null @@ -1,16 +0,0 @@ - $name]; - } -} diff --git a/tests/Rules/Explicit/NoMissingArrayShapeReturnArrayRule/Fixture/SkipSingleValue.php b/tests/Rules/Explicit/NoMissingArrayShapeReturnArrayRule/Fixture/SkipSingleValue.php deleted file mode 100644 index a42189ac..00000000 --- a/tests/Rules/Explicit/NoMissingArrayShapeReturnArrayRule/Fixture/SkipSingleValue.php +++ /dev/null @@ -1,13 +0,0 @@ - 10) { - return ['name' => $name]; - } - - return ['surname' => $name]; - } -} diff --git a/tests/Rules/Explicit/NoMissingArrayShapeReturnArrayRule/NoMissingArrayShapeReturnArrayRuleTest.php b/tests/Rules/Explicit/NoMissingArrayShapeReturnArrayRule/NoMissingArrayShapeReturnArrayRuleTest.php deleted file mode 100644 index bf08be73..00000000 --- a/tests/Rules/Explicit/NoMissingArrayShapeReturnArrayRule/NoMissingArrayShapeReturnArrayRuleTest.php +++ /dev/null @@ -1,54 +0,0 @@ - - */ -final class NoMissingArrayShapeReturnArrayRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[]|array> $expectedErrorsWithLines - */ - public function testRule(string $filePath, array $expectedErrorsWithLines): void - { - $this->analyse([$filePath], $expectedErrorsWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/MissingShape.php', [[NoMissingArrayShapeReturnArrayRule::ERROR_MESSAGE, 11]]]; - yield [ - __DIR__ . '/Fixture/MissingShapeWithArray.php', - [[NoMissingArrayShapeReturnArrayRule::ERROR_MESSAGE, 11]], - ]; - - yield [__DIR__ . '/Fixture/SkipKnownShape.php', []]; - yield [__DIR__ . '/Fixture/SkipDefaultEmptyArray.php', []]; - yield [__DIR__ . '/Fixture/SkipSingleValue.php', []]; - yield [__DIR__ . '/Fixture/SkipClassList.php', []]; - yield [__DIR__ . '/Fixture/SkipEventSubscriber.php', []]; - yield [__DIR__ . '/Fixture/SkipUnionOfArrayShapes.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoMissingArrayShapeReturnArrayRule::class); - } -} diff --git a/tests/Rules/Explicit/NoMissingArrayShapeReturnArrayRule/config/configured_rule.neon b/tests/Rules/Explicit/NoMissingArrayShapeReturnArrayRule/config/configured_rule.neon deleted file mode 100644 index efb5e557..00000000 --- a/tests/Rules/Explicit/NoMissingArrayShapeReturnArrayRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\Explicit\NoMissingArrayShapeReturnArrayRule diff --git a/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/Fixture/ReturnedNoVoid.php b/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/Fixture/ReturnedNoVoid.php deleted file mode 100644 index 6e7138be..00000000 --- a/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/Fixture/ReturnedNoVoid.php +++ /dev/null @@ -1,18 +0,0 @@ -getResult(); - } - - private function getResult(): array - { - return []; - } -} diff --git a/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/Fixture/SkipCommandOptions.php b/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/Fixture/SkipCommandOptions.php deleted file mode 100644 index 324c844d..00000000 --- a/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/Fixture/SkipCommandOptions.php +++ /dev/null @@ -1,17 +0,0 @@ -addArgument('...'); - - $this->addOption('...'); - } -} diff --git a/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/Fixture/SkipDefaultSymfonyAutowire.php b/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/Fixture/SkipDefaultSymfonyAutowire.php deleted file mode 100644 index c8977e6a..00000000 --- a/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/Fixture/SkipDefaultSymfonyAutowire.php +++ /dev/null @@ -1,19 +0,0 @@ -services(); - - $services->defaults() - ->public() - ->autowire(); - } -} diff --git a/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/Fixture/SkipFluentOutsideOnPurpose.php b/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/Fixture/SkipFluentOutsideOnPurpose.php deleted file mode 100644 index 185a14b2..00000000 --- a/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/Fixture/SkipFluentOutsideOnPurpose.php +++ /dev/null @@ -1,18 +0,0 @@ -setName('name'); - } - - private function setName(string $name): self - { - return $this; - } -} diff --git a/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/Fixture/SkipNodeTraverser.php b/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/Fixture/SkipNodeTraverser.php deleted file mode 100644 index ce756bd8..00000000 --- a/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/Fixture/SkipNodeTraverser.php +++ /dev/null @@ -1,16 +0,0 @@ -traverse([]); - } -} diff --git a/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/Fixture/SkipReturnedNoVoid.php b/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/Fixture/SkipReturnedNoVoid.php deleted file mode 100644 index 61b05539..00000000 --- a/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/Fixture/SkipReturnedNoVoid.php +++ /dev/null @@ -1,18 +0,0 @@ -getResult(); - } - - private function getResult() - { - return []; - } -} diff --git a/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/Fixture/SkipStaticReturn.php b/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/Fixture/SkipStaticReturn.php deleted file mode 100644 index 40447941..00000000 --- a/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/Fixture/SkipStaticReturn.php +++ /dev/null @@ -1,27 +0,0 @@ -getStatic(); - } - - /** - * @param CompilerPassInterface[] $compilerPasses - */ - public function withContainerBuilder(ContainerBuilder $containerBuilder, array $compilerPasses): void - { - foreach ($compilerPasses as $compilerPass) { - $containerBuilder->loadFromExtension('...', []); - } - } -} diff --git a/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/Fixture/SkipSymfonyContainerConfigurator.php b/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/Fixture/SkipSymfonyContainerConfigurator.php deleted file mode 100644 index 00547276..00000000 --- a/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/Fixture/SkipSymfonyContainerConfigurator.php +++ /dev/null @@ -1,19 +0,0 @@ -services(); - $services->set('value'); - - $services->set('value') - ->call('this', ['that']); - } -} diff --git a/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/Fixture/SkipTokens.php b/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/Fixture/SkipTokens.php deleted file mode 100644 index 2f93f2a9..00000000 --- a/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/Fixture/SkipTokens.php +++ /dev/null @@ -1,19 +0,0 @@ - $tokens - */ - public function run(Tokens $tokens) - { - $tokens->ensureWhitespaceAtIndex(1, 2, ''); - } -} diff --git a/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/NoMissingAssingNoVoidMethodCallRuleTest.php b/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/NoMissingAssingNoVoidMethodCallRuleTest.php deleted file mode 100644 index 4a9dcf72..00000000 --- a/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/NoMissingAssingNoVoidMethodCallRuleTest.php +++ /dev/null @@ -1,51 +0,0 @@ - - */ -final class NoMissingAssingNoVoidMethodCallRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorsWithLines - */ - public function testRule(string $filePath, array $expectedErrorsWithLines): void - { - $this->analyse([$filePath], $expectedErrorsWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/ReturnedNoVoid.php', [[NoMissingAssingNoVoidMethodCallRule::ERROR_MESSAGE, 11]]]; - - yield [__DIR__ . '/Fixture/SkipTokens.php', []]; - yield [__DIR__ . '/Fixture/SkipReturnedNoVoid.php', []]; - yield [__DIR__ . '/Fixture/SkipFluentOutsideOnPurpose.php', []]; - yield [__DIR__ . '/Fixture/SkipSymfonyContainerConfigurator.php', []]; - yield [__DIR__ . '/Fixture/SkipDefaultSymfonyAutowire.php', []]; - yield [__DIR__ . '/Fixture/SkipNodeTraverser.php', []]; - yield [__DIR__ . '/Fixture/SkipCommandOptions.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoMissingAssingNoVoidMethodCallRule::class); - } -} diff --git a/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/Source/AbstractCommand.php b/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/Source/AbstractCommand.php deleted file mode 100644 index 2050040c..00000000 --- a/tests/Rules/Explicit/NoMissingAssingNoVoidMethodCallRule/Source/AbstractCommand.php +++ /dev/null @@ -1,11 +0,0 @@ -items[$key] = $value; - } -} diff --git a/tests/Rules/Explicit/NoMixedArrayDimFetchRule/Fixture/SkipExternalPhpParser.php b/tests/Rules/Explicit/NoMixedArrayDimFetchRule/Fixture/SkipExternalPhpParser.php deleted file mode 100644 index 8228e972..00000000 --- a/tests/Rules/Explicit/NoMixedArrayDimFetchRule/Fixture/SkipExternalPhpParser.php +++ /dev/null @@ -1,16 +0,0 @@ -params[5] = $param; - } -} diff --git a/tests/Rules/Explicit/NoMixedArrayDimFetchRule/Fixture/SkipString.php b/tests/Rules/Explicit/NoMixedArrayDimFetchRule/Fixture/SkipString.php deleted file mode 100644 index cbe84482..00000000 --- a/tests/Rules/Explicit/NoMixedArrayDimFetchRule/Fixture/SkipString.php +++ /dev/null @@ -1,13 +0,0 @@ - - */ - private $items = []; - - public function addItem(string $key, string $value) - { - $this->items[$key] = $value; - } -} diff --git a/tests/Rules/Explicit/NoMixedArrayDimFetchRule/NoMixedArrayDimFetchRuleTest.php b/tests/Rules/Explicit/NoMixedArrayDimFetchRule/NoMixedArrayDimFetchRuleTest.php deleted file mode 100644 index a9a50736..00000000 --- a/tests/Rules/Explicit/NoMixedArrayDimFetchRule/NoMixedArrayDimFetchRuleTest.php +++ /dev/null @@ -1,48 +0,0 @@ - - */ -final class NoMixedArrayDimFetchRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[]|array> $expectedErrorsWithLines - */ - public function testRule(string $filePath, array $expectedErrorsWithLines): void - { - $this->analyse([$filePath], $expectedErrorsWithLines); - } - - public function provideData(): Iterator - { - $errorMessage = sprintf(NoMixedArrayDimFetchRule::ERROR_MESSAGE, '$this->items'); - yield [__DIR__ . '/Fixture/ReportUntypedArray.php', [[$errorMessage, 13]]]; - - yield [__DIR__ . '/Fixture/SkipTypedArray.php', []]; - yield [__DIR__ . '/Fixture/SkipString.php', []]; - yield [__DIR__ . '/Fixture/SkipExternalPhpParser.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoMixedArrayDimFetchRule::class); - } -} diff --git a/tests/Rules/Explicit/NoMixedArrayDimFetchRule/config/configured_rule.neon b/tests/Rules/Explicit/NoMixedArrayDimFetchRule/config/configured_rule.neon deleted file mode 100644 index 4c094909..00000000 --- a/tests/Rules/Explicit/NoMixedArrayDimFetchRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\Explicit\NoMixedArrayDimFetchRule diff --git a/tests/Rules/Explicit/NoMixedCallableRule/Fixture/DocOnlyNullableReturnCallable.php b/tests/Rules/Explicit/NoMixedCallableRule/Fixture/DocOnlyNullableReturnCallable.php deleted file mode 100644 index 693bed02..00000000 --- a/tests/Rules/Explicit/NoMixedCallableRule/Fixture/DocOnlyNullableReturnCallable.php +++ /dev/null @@ -1,17 +0,0 @@ - - */ -final class NoMixedCallableRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[]|array> $expectedErrorsWithLines - */ - public function testRule(string $filePath, array $expectedErrorsWithLines): void - { - $this->analyse([$filePath], $expectedErrorsWithLines); - } - - public function provideData(): Iterator - { - // variable - yield [__DIR__ . '/Fixture/MixedCallable.php', [[NoMixedCallableRule::ERROR_MESSAGE, 11]]]; - yield [__DIR__ . '/Fixture/NullableMixedCallable.php', [[NoMixedCallableRule::ERROR_MESSAGE, 11]]]; - yield [__DIR__ . '/Fixture/UnionMixedCallable.php', [[NoMixedCallableRule::ERROR_MESSAGE, 11]]]; - yield [__DIR__ . '/Fixture/SkipReturnDefinedCallable.php', []]; - yield [__DIR__ . '/Fixture/SkipParamDefinedCallable.php', []]; - - // class method return - yield [__DIR__ . '/Fixture/ReturnCallable.php', [[NoMixedCallableRule::ERROR_MESSAGE, 12]]]; - yield [__DIR__ . '/Fixture/NullableReturnCallable.php', [[NoMixedCallableRule::ERROR_MESSAGE, 12]]]; - yield [__DIR__ . '/Fixture/DocOnlyNullableReturnCallable.php', [[NoMixedCallableRule::ERROR_MESSAGE, 13]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoMixedCallableRule::class); - } -} diff --git a/tests/Rules/Explicit/NoMixedCallableRule/config/configured_rule.neon b/tests/Rules/Explicit/NoMixedCallableRule/config/configured_rule.neon deleted file mode 100644 index cc933539..00000000 --- a/tests/Rules/Explicit/NoMixedCallableRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\Explicit\NoMixedCallableRule diff --git a/tests/Rules/Explicit/NoMixedMethodCallerRule/Fixture/SkipKnownCallerType.php b/tests/Rules/Explicit/NoMixedMethodCallerRule/Fixture/SkipKnownCallerType.php deleted file mode 100644 index c655b48b..00000000 --- a/tests/Rules/Explicit/NoMixedMethodCallerRule/Fixture/SkipKnownCallerType.php +++ /dev/null @@ -1,15 +0,0 @@ -call(); - } -} diff --git a/tests/Rules/Explicit/NoMixedMethodCallerRule/config/configured_rule.neon b/tests/Rules/Explicit/NoMixedMethodCallerRule/config/configured_rule.neon deleted file mode 100644 index 5c539a2b..00000000 --- a/tests/Rules/Explicit/NoMixedMethodCallerRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\Explicit\NoMixedMethodCallerRule diff --git a/tests/Rules/Explicit/NoMixedPropertyFetcherRule/Fixture/DynamicName.php b/tests/Rules/Explicit/NoMixedPropertyFetcherRule/Fixture/DynamicName.php deleted file mode 100644 index 9e47185a..00000000 --- a/tests/Rules/Explicit/NoMixedPropertyFetcherRule/Fixture/DynamicName.php +++ /dev/null @@ -1,15 +0,0 @@ -{$name}; - } -} diff --git a/tests/Rules/Explicit/NoMixedPropertyFetcherRule/Fixture/SkipDynamicNameWithKnownType.php b/tests/Rules/Explicit/NoMixedPropertyFetcherRule/Fixture/SkipDynamicNameWithKnownType.php deleted file mode 100644 index 8ffba3b0..00000000 --- a/tests/Rules/Explicit/NoMixedPropertyFetcherRule/Fixture/SkipDynamicNameWithKnownType.php +++ /dev/null @@ -1,15 +0,0 @@ -{$name}; - } -} diff --git a/tests/Rules/Explicit/NoMixedPropertyFetcherRule/Fixture/SkipKnownFetcherType.php b/tests/Rules/Explicit/NoMixedPropertyFetcherRule/Fixture/SkipKnownFetcherType.php deleted file mode 100644 index 588d7930..00000000 --- a/tests/Rules/Explicit/NoMixedPropertyFetcherRule/Fixture/SkipKnownFetcherType.php +++ /dev/null @@ -1,15 +0,0 @@ -name; - } -} diff --git a/tests/Rules/Explicit/NoMixedPropertyFetcherRule/Source/KnownType.php b/tests/Rules/Explicit/NoMixedPropertyFetcherRule/Source/KnownType.php deleted file mode 100644 index b99e5da7..00000000 --- a/tests/Rules/Explicit/NoMixedPropertyFetcherRule/Source/KnownType.php +++ /dev/null @@ -1,10 +0,0 @@ -files() - ->in($sources) - ->name('*.php.inc') - ->path('Fixture') - ->sortByName(); - } -} diff --git a/tests/Rules/Explicit/NoRelativeFilePathRule/Fixture/SkipNoFileBefore.php b/tests/Rules/Explicit/NoRelativeFilePathRule/Fixture/SkipNoFileBefore.php deleted file mode 100644 index 9cca4129..00000000 --- a/tests/Rules/Explicit/NoRelativeFilePathRule/Fixture/SkipNoFileBefore.php +++ /dev/null @@ -1,18 +0,0 @@ - - */ -final class NoRelativeFilePathRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[]|array> $expectedErrorsWithLines - */ - public function testRule(string $filePath, array $expectedErrorsWithLines): void - { - $this->analyse([$filePath], $expectedErrorsWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipMaskFinder.php', []]; - yield [__DIR__ . '/Fixture/SkipStrEndsWith.php', []]; - yield [__DIR__ . '/Fixture/SkipRegexConsts.php', []]; - yield [__DIR__ . '/Fixture/SkipHereNowDoc.php', []]; - yield [__DIR__ . '/Fixture/SkipNoFileBefore.php', []]; - yield [__DIR__ . '/Fixture/SkipAbsoluteFilePath.php', []]; - yield [__DIR__ . '/Fixture/SkipSimpleString.php', []]; - yield [__DIR__ . '/Fixture/SkipNotAFileExtension.php', []]; - - $errorMessage = sprintf(NoRelativeFilePathRule::ERROR_MESSAGE, 'some_relative_path.txt'); - yield [__DIR__ . '/Fixture/RelativeFilePath.php', [[$errorMessage, 11]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoRelativeFilePathRule::class); - } -} diff --git a/tests/Rules/Explicit/NoRelativeFilePathRule/config/configured_rule.neon b/tests/Rules/Explicit/NoRelativeFilePathRule/config/configured_rule.neon deleted file mode 100644 index 4f602548..00000000 --- a/tests/Rules/Explicit/NoRelativeFilePathRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\Explicit\NoRelativeFilePathRule diff --git a/tests/Rules/Explicit/RequireSpecificReturnTypeOverAbstractRule/Fixture/SkipSpecificReturnType.php b/tests/Rules/Explicit/RequireSpecificReturnTypeOverAbstractRule/Fixture/SkipSpecificReturnType.php deleted file mode 100644 index ab1e38aa..00000000 --- a/tests/Rules/Explicit/RequireSpecificReturnTypeOverAbstractRule/Fixture/SkipSpecificReturnType.php +++ /dev/null @@ -1,15 +0,0 @@ - $latteFilters - */ - public function __construct(array $latteFilters) - { - } -} diff --git a/tests/Rules/Explicit/ValueObjectOverArrayShapeRule/Fixture/SkipJsonSerializable.php b/tests/Rules/Explicit/ValueObjectOverArrayShapeRule/Fixture/SkipJsonSerializable.php deleted file mode 100644 index 59daef33..00000000 --- a/tests/Rules/Explicit/ValueObjectOverArrayShapeRule/Fixture/SkipJsonSerializable.php +++ /dev/null @@ -1,25 +0,0 @@ - - */ -final class ValueObjectOverArrayShapeRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SomeArrayShapeReturn.php', [[ValueObjectOverArrayShapeRule::ERROR_MESSAGE, 12]]]; - - yield [__DIR__ . '/Fixture/SkipJsonSerializable.php', []]; - yield [__DIR__ . '/Fixture/SkipNoArrayShape.php', []]; - yield [__DIR__ . '/Fixture/SkipConstructorAsIntroData.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(ValueObjectOverArrayShapeRule::class); - } -} diff --git a/tests/Rules/Explicit/ValueObjectOverArrayShapeRule/config/configured_rule.neon b/tests/Rules/Explicit/ValueObjectOverArrayShapeRule/config/configured_rule.neon deleted file mode 100644 index a4fc55ea..00000000 --- a/tests/Rules/Explicit/ValueObjectOverArrayShapeRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\Explicit\ValueObjectOverArrayShapeRule diff --git a/tests/Rules/ForbiddenAnonymousClassRule/Fixture/AnonymousClass.php b/tests/Rules/ForbiddenAnonymousClassRule/Fixture/AnonymousClass.php deleted file mode 100644 index 6a4b4981..00000000 --- a/tests/Rules/ForbiddenAnonymousClassRule/Fixture/AnonymousClass.php +++ /dev/null @@ -1,13 +0,0 @@ - - */ -final class ForbiddenAnonymousClassRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipDedicatedClass.php', []]; - yield [__DIR__ . '/Fixture/AnonymousClass.php', [[ForbiddenAnonymousClassRule::ERROR_MESSAGE, 11]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(ForbiddenAnonymousClassRule::class); - } -} diff --git a/tests/Rules/ForbiddenAnonymousClassRule/config/configured_rule.neon b/tests/Rules/ForbiddenAnonymousClassRule/config/configured_rule.neon deleted file mode 100644 index 884665a6..00000000 --- a/tests/Rules/ForbiddenAnonymousClassRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\ForbiddenAnonymousClassRule diff --git a/tests/Rules/ForbiddenArrayDestructRule/Fixture/ClassWithArrayDestruct.php b/tests/Rules/ForbiddenArrayDestructRule/Fixture/ClassWithArrayDestruct.php deleted file mode 100644 index ae385694..00000000 --- a/tests/Rules/ForbiddenArrayDestructRule/Fixture/ClassWithArrayDestruct.php +++ /dev/null @@ -1,18 +0,0 @@ -getResult(); - } - - public function getResult() - { - return [1, 2]; - } -} diff --git a/tests/Rules/ForbiddenArrayDestructRule/Fixture/SkipExplode.php b/tests/Rules/ForbiddenArrayDestructRule/Fixture/SkipExplode.php deleted file mode 100644 index b105cdf2..00000000 --- a/tests/Rules/ForbiddenArrayDestructRule/Fixture/SkipExplode.php +++ /dev/null @@ -1,13 +0,0 @@ -getValues(); - } -} diff --git a/tests/Rules/ForbiddenArrayDestructRule/Fixture/SkipStringsSplit.php b/tests/Rules/ForbiddenArrayDestructRule/Fixture/SkipStringsSplit.php deleted file mode 100644 index bf2d43ac..00000000 --- a/tests/Rules/ForbiddenArrayDestructRule/Fixture/SkipStringsSplit.php +++ /dev/null @@ -1,15 +0,0 @@ - - */ -final class ForbiddenArrayDestructRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/ClassWithArrayDestruct.php', [[ForbiddenArrayDestructRule::ERROR_MESSAGE, 11]]]; - yield [__DIR__ . '/Fixture/SkipSwap.php', []]; - yield [__DIR__ . '/Fixture/SkipExplode.php', []]; - yield [__DIR__ . '/Fixture/SkipStringsSplit.php', []]; - yield [__DIR__ . '/Fixture/SkipExternalReturnArray.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(ForbiddenArrayDestructRule::class); - } -} diff --git a/tests/Rules/ForbiddenArrayDestructRule/config/configured_rule.neon b/tests/Rules/ForbiddenArrayDestructRule/config/configured_rule.neon deleted file mode 100644 index 707d0b89..00000000 --- a/tests/Rules/ForbiddenArrayDestructRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\ForbiddenArrayDestructRule diff --git a/tests/Rules/ForbiddenArrayWithStringKeysRule/Fixture/ArrayWithStrings.php b/tests/Rules/ForbiddenArrayWithStringKeysRule/Fixture/ArrayWithStrings.php deleted file mode 100644 index bb8a0cff..00000000 --- a/tests/Rules/ForbiddenArrayWithStringKeysRule/Fixture/ArrayWithStrings.php +++ /dev/null @@ -1,15 +0,0 @@ - 'value' - ]; - } -} diff --git a/tests/Rules/ForbiddenArrayWithStringKeysRule/Fixture/SkipArrayRequiredParentContract.php b/tests/Rules/ForbiddenArrayWithStringKeysRule/Fixture/SkipArrayRequiredParentContract.php deleted file mode 100644 index d8cf41c8..00000000 --- a/tests/Rules/ForbiddenArrayWithStringKeysRule/Fixture/SkipArrayRequiredParentContract.php +++ /dev/null @@ -1,17 +0,0 @@ - 'value', - ]; - } -} diff --git a/tests/Rules/ForbiddenArrayWithStringKeysRule/Fixture/SkipDataInGetDefinition.php b/tests/Rules/ForbiddenArrayWithStringKeysRule/Fixture/SkipDataInGetDefinition.php deleted file mode 100644 index 9b40c18d..00000000 --- a/tests/Rules/ForbiddenArrayWithStringKeysRule/Fixture/SkipDataInGetDefinition.php +++ /dev/null @@ -1,15 +0,0 @@ - 'value' - ]; - } -} diff --git a/tests/Rules/ForbiddenArrayWithStringKeysRule/Fixture/SkipDataInTest.php b/tests/Rules/ForbiddenArrayWithStringKeysRule/Fixture/SkipDataInTest.php deleted file mode 100644 index 85555e56..00000000 --- a/tests/Rules/ForbiddenArrayWithStringKeysRule/Fixture/SkipDataInTest.php +++ /dev/null @@ -1,15 +0,0 @@ - 'value' - ]; - } -} diff --git a/tests/Rules/ForbiddenArrayWithStringKeysRule/Fixture/SkipDataInTestCase.php b/tests/Rules/ForbiddenArrayWithStringKeysRule/Fixture/SkipDataInTestCase.php deleted file mode 100644 index bbe6fe55..00000000 --- a/tests/Rules/ForbiddenArrayWithStringKeysRule/Fixture/SkipDataInTestCase.php +++ /dev/null @@ -1,15 +0,0 @@ - 'value' - ]; - } -} diff --git a/tests/Rules/ForbiddenArrayWithStringKeysRule/Fixture/SkipJsonNamed.php b/tests/Rules/ForbiddenArrayWithStringKeysRule/Fixture/SkipJsonNamed.php deleted file mode 100644 index 097807d0..00000000 --- a/tests/Rules/ForbiddenArrayWithStringKeysRule/Fixture/SkipJsonNamed.php +++ /dev/null @@ -1,15 +0,0 @@ - 'yes', - ]; - } -} diff --git a/tests/Rules/ForbiddenArrayWithStringKeysRule/Fixture/SkipJsonSerializable.php b/tests/Rules/ForbiddenArrayWithStringKeysRule/Fixture/SkipJsonSerializable.php deleted file mode 100644 index 26797b00..00000000 --- a/tests/Rules/ForbiddenArrayWithStringKeysRule/Fixture/SkipJsonSerializable.php +++ /dev/null @@ -1,24 +0,0 @@ - - */ - public function jsonSerialize() - { - return [ - 'name' => $this->name, - 'surname' => $this->surname, - ]; - } -} diff --git a/tests/Rules/ForbiddenArrayWithStringKeysRule/Fixture/SkipNonConstantString.php b/tests/Rules/ForbiddenArrayWithStringKeysRule/Fixture/SkipNonConstantString.php deleted file mode 100644 index 612342ec..00000000 --- a/tests/Rules/ForbiddenArrayWithStringKeysRule/Fixture/SkipNonConstantString.php +++ /dev/null @@ -1,16 +0,0 @@ - 'value' - ]; - } -} diff --git a/tests/Rules/ForbiddenArrayWithStringKeysRule/ForbiddenArrayWithStringKeysRuleTest.php b/tests/Rules/ForbiddenArrayWithStringKeysRule/ForbiddenArrayWithStringKeysRuleTest.php deleted file mode 100644 index 176037d1..00000000 --- a/tests/Rules/ForbiddenArrayWithStringKeysRule/ForbiddenArrayWithStringKeysRuleTest.php +++ /dev/null @@ -1,51 +0,0 @@ - - */ -final class ForbiddenArrayWithStringKeysRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/ArrayWithStrings.php', [[ForbiddenArrayWithStringKeysRule::ERROR_MESSAGE, 11]]]; - - yield [__DIR__ . '/Fixture/SkipJsonNamed.php', []]; - yield [__DIR__ . '/Fixture/SkipJsonSerializable.php', []]; - yield [__DIR__ . '/Fixture/SkipArrayRequiredParentContract.php', []]; - yield [__DIR__ . '/Fixture/SkipDataInTest.php', []]; - yield [__DIR__ . '/Fixture/SkipDataInTestCase.php', []]; - yield [__DIR__ . '/Fixture/SkipDataInGetDefinition.php', []]; - yield [__DIR__ . '/Fixture/SkipNonConstantString.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(ForbiddenArrayWithStringKeysRule::class); - } -} diff --git a/tests/Rules/ForbiddenArrayWithStringKeysRule/Source/ObjectWithOptions.php b/tests/Rules/ForbiddenArrayWithStringKeysRule/Source/ObjectWithOptions.php deleted file mode 100644 index 48e074a1..00000000 --- a/tests/Rules/ForbiddenArrayWithStringKeysRule/Source/ObjectWithOptions.php +++ /dev/null @@ -1,12 +0,0 @@ - - */ -final class ForbiddenFuncCallRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - $errorMessage = sprintf(ForbiddenFuncCallRule::ERROR_MESSAGE, 'dump'); - yield [__DIR__ . '/Fixture/DebugFuncCall.php', [[$errorMessage, 11]]]; - - $errorMessage = sprintf(ForbiddenFuncCallRule::ERROR_MESSAGE, 'extract'); - yield [__DIR__ . '/Fixture/ExtractCall.php', [[$errorMessage, 11]]]; - - $errorMessage = sprintf(ForbiddenFuncCallRule::ERROR_MESSAGE, 'curl_init'); - yield [__DIR__ . '/Fixture/CurlCall.php', [[$errorMessage, 11]]]; - - $errorMessage = sprintf(ForbiddenFuncCallRule::ERROR_MESSAGE, 'property_exists'); - yield [__DIR__ . '/Fixture/PropertyExists.php', [[$errorMessage, 11]]]; - - yield [__DIR__ . '/Fixture/SkipPropertyExistsOnXml.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(ForbiddenFuncCallRule::class); - } -} diff --git a/tests/Rules/ForbiddenFuncCallRule/ForbiddenFuncCallRuleWithDeprecationsTest.php b/tests/Rules/ForbiddenFuncCallRule/ForbiddenFuncCallRuleWithDeprecationsTest.php deleted file mode 100644 index 9b3c4f63..00000000 --- a/tests/Rules/ForbiddenFuncCallRule/ForbiddenFuncCallRuleWithDeprecationsTest.php +++ /dev/null @@ -1,61 +0,0 @@ - - */ -final class ForbiddenFuncCallRuleWithDeprecationsTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - // custom messages are defined in the config file - - $errorMessage = sprintf(ForbiddenFuncCallRule::ERROR_MESSAGE, 'dump'); - $errorMessage .= ': seems you missed some debugging function'; - yield [__DIR__ . '/Fixture/DebugFuncCall.php', [[$errorMessage, 11]]]; - - $errorMessage = sprintf(ForbiddenFuncCallRule::ERROR_MESSAGE, 'extract'); - $errorMessage .= ': you shouldn"t use this dynamic things'; - yield [__DIR__ . '/Fixture/ExtractCall.php', [[$errorMessage, 11]]]; - - $errorMessage = sprintf(ForbiddenFuncCallRule::ERROR_MESSAGE, 'curl_init'); - $errorMessage .= ': we use a proper http client these days'; - yield [__DIR__ . '/Fixture/CurlCall.php', [[$errorMessage, 11]]]; - - // custom error defined as empty-string -> just prints the default message - $errorMessage = sprintf(ForbiddenFuncCallRule::ERROR_MESSAGE, 'property_exists'); - yield [__DIR__ . '/Fixture/PropertyExists.php', [[$errorMessage, 11]]]; - - yield [__DIR__ . '/Fixture/SkipPropertyExistsOnXml.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule_with_deprecations.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(ForbiddenFuncCallRule::class); - } -} diff --git a/tests/Rules/ForbiddenFuncCallRule/config/configured_rule.neon b/tests/Rules/ForbiddenFuncCallRule/config/configured_rule.neon deleted file mode 100644 index bcc99b22..00000000 --- a/tests/Rules/ForbiddenFuncCallRule/config/configured_rule.neon +++ /dev/null @@ -1,13 +0,0 @@ -includes: - - ../../../config/included_services.neon - -services: - - - class: Symplify\PHPStanRules\Rules\ForbiddenFuncCallRule - tags: [phpstan.rules.rule] - arguments: - forbiddenFunctions: - - 'extract' - - 'dump' - - 'curl_*' - - 'property_exists' diff --git a/tests/Rules/ForbiddenFuncCallRule/config/configured_rule_with_deprecations.neon b/tests/Rules/ForbiddenFuncCallRule/config/configured_rule_with_deprecations.neon deleted file mode 100644 index 0442c12b..00000000 --- a/tests/Rules/ForbiddenFuncCallRule/config/configured_rule_with_deprecations.neon +++ /dev/null @@ -1,13 +0,0 @@ -includes: - - ../../../config/included_services.neon - -services: - - - class: Symplify\PHPStanRules\Rules\ForbiddenFuncCallRule - tags: [phpstan.rules.rule] - arguments: - forbiddenFunctions: - 'extract': 'you shouldn"t use this dynamic things' - 'dump': 'seems you missed some debugging function' - 'curl_*': 'we use a proper http client these days' - - 'property_exists' diff --git a/tests/Rules/ForbiddenMultipleClassLikeInOneFileRule/Fixture/MultipleClassLike.php b/tests/Rules/ForbiddenMultipleClassLikeInOneFileRule/Fixture/MultipleClassLike.php deleted file mode 100644 index ebe21580..00000000 --- a/tests/Rules/ForbiddenMultipleClassLikeInOneFileRule/Fixture/MultipleClassLike.php +++ /dev/null @@ -1,17 +0,0 @@ - - */ -final class ForbiddenMultipleClassLikeInOneFileRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipOneInterface.php', []]; - yield [__DIR__ . '/Fixture/SkipOneClassWithAnonymousClass.php', []]; - yield [__DIR__ . '/Fixture/SkipOneClass.php', []]; - yield [__DIR__ . '/Fixture/SkipOneTrait.php', []]; - - yield [ - __DIR__ . '/Fixture/MultipleClassLike.php', - [[ForbiddenMultipleClassLikeInOneFileRule::ERROR_MESSAGE, 3]], - ]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(ForbiddenMultipleClassLikeInOneFileRule::class); - } -} diff --git a/tests/Rules/ForbiddenMultipleClassLikeInOneFileRule/config/configured_rule.neon b/tests/Rules/ForbiddenMultipleClassLikeInOneFileRule/config/configured_rule.neon deleted file mode 100644 index e641c8bf..00000000 --- a/tests/Rules/ForbiddenMultipleClassLikeInOneFileRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\ForbiddenMultipleClassLikeInOneFileRule diff --git a/tests/Rules/ForbiddenNestedCallInAssertMethodCallRule/Fixture/NestedAssertMethodCall.php b/tests/Rules/ForbiddenNestedCallInAssertMethodCallRule/Fixture/NestedAssertMethodCall.php deleted file mode 100644 index efe43bbe..00000000 --- a/tests/Rules/ForbiddenNestedCallInAssertMethodCallRule/Fixture/NestedAssertMethodCall.php +++ /dev/null @@ -1,16 +0,0 @@ -assertSame('...', $values->run(1000)); - } -} diff --git a/tests/Rules/ForbiddenNestedCallInAssertMethodCallRule/Fixture/SkipAssertNothing.php b/tests/Rules/ForbiddenNestedCallInAssertMethodCallRule/Fixture/SkipAssertNothing.php deleted file mode 100644 index b27cfc14..00000000 --- a/tests/Rules/ForbiddenNestedCallInAssertMethodCallRule/Fixture/SkipAssertNothing.php +++ /dev/null @@ -1,13 +0,0 @@ -assertNothing(); - } -} diff --git a/tests/Rules/ForbiddenNestedCallInAssertMethodCallRule/Fixture/SkipAssertTrue.php b/tests/Rules/ForbiddenNestedCallInAssertMethodCallRule/Fixture/SkipAssertTrue.php deleted file mode 100644 index 266de36e..00000000 --- a/tests/Rules/ForbiddenNestedCallInAssertMethodCallRule/Fixture/SkipAssertTrue.php +++ /dev/null @@ -1,16 +0,0 @@ -assertTrue($values->run(1000)); - } -} diff --git a/tests/Rules/ForbiddenNestedCallInAssertMethodCallRule/Fixture/SkipCleanAssert.php b/tests/Rules/ForbiddenNestedCallInAssertMethodCallRule/Fixture/SkipCleanAssert.php deleted file mode 100644 index b6196647..00000000 --- a/tests/Rules/ForbiddenNestedCallInAssertMethodCallRule/Fixture/SkipCleanAssert.php +++ /dev/null @@ -1,14 +0,0 @@ -assertSame('...', $values); - } -} diff --git a/tests/Rules/ForbiddenNestedCallInAssertMethodCallRule/Fixture/SkipSimpleGetter.php b/tests/Rules/ForbiddenNestedCallInAssertMethodCallRule/Fixture/SkipSimpleGetter.php deleted file mode 100644 index e24ece5f..00000000 --- a/tests/Rules/ForbiddenNestedCallInAssertMethodCallRule/Fixture/SkipSimpleGetter.php +++ /dev/null @@ -1,16 +0,0 @@ -assertSame('...', $values->run()); - } -} diff --git a/tests/Rules/ForbiddenNestedCallInAssertMethodCallRule/ForbiddenNestedCallInAssertMethodCallRuleTest.php b/tests/Rules/ForbiddenNestedCallInAssertMethodCallRule/ForbiddenNestedCallInAssertMethodCallRuleTest.php deleted file mode 100644 index d334ffc9..00000000 --- a/tests/Rules/ForbiddenNestedCallInAssertMethodCallRule/ForbiddenNestedCallInAssertMethodCallRuleTest.php +++ /dev/null @@ -1,50 +0,0 @@ - - */ -final class ForbiddenNestedCallInAssertMethodCallRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipAssertNothing.php', []]; - yield [__DIR__ . '/Fixture/SkipCleanAssert.php', []]; - yield [__DIR__ . '/Fixture/SkipSimpleGetter.php', []]; - yield [__DIR__ . '/Fixture/SkipAssertTrue.php', []]; - - yield [__DIR__ . '/Fixture/NestedAssertMethodCall.php', [ - [ForbiddenNestedCallInAssertMethodCallRule::ERROR_MESSAGE, 14], - ]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(ForbiddenNestedCallInAssertMethodCallRule::class); - } -} diff --git a/tests/Rules/ForbiddenNestedCallInAssertMethodCallRule/Source/AnyOtherObject.php b/tests/Rules/ForbiddenNestedCallInAssertMethodCallRule/Source/AnyOtherObject.php deleted file mode 100644 index 6be9584f..00000000 --- a/tests/Rules/ForbiddenNestedCallInAssertMethodCallRule/Source/AnyOtherObject.php +++ /dev/null @@ -1,12 +0,0 @@ - - */ -final class ForbiddenNodeRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - /** - * @return \Iterator>|string[]> - */ - public function provideData(): Iterator - { - $errorMessage = sprintf(ForbiddenNodeRule::ERROR_MESSAGE, 'empty($value)'); - yield [__DIR__ . '/Fixture/EmptyCall.php', [[$errorMessage, 11]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(ForbiddenNodeRule::class); - } -} diff --git a/tests/Rules/ForbiddenNodeRule/config/configured_rule.neon b/tests/Rules/ForbiddenNodeRule/config/configured_rule.neon deleted file mode 100644 index ea9c437a..00000000 --- a/tests/Rules/ForbiddenNodeRule/config/configured_rule.neon +++ /dev/null @@ -1,12 +0,0 @@ -includes: - - ../../../config/included_services.neon - -services: - - - class: Symplify\PHPStanRules\Rules\ForbiddenNodeRule - tags: [phpstan.rules.rule] - arguments: - forbiddenNodes: - - PhpParser\Node\Expr\Empty_ - - PhpParser\Node\Stmt\Switch_ - - PhpParser\Node\Expr\ErrorSuppress diff --git a/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/AnInterface.php b/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/AnInterface.php index 25678b83..ab429378 100644 --- a/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/AnInterface.php +++ b/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/AnInterface.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\ForbiddenParamTypeRemovalRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\ForbiddenParamTypeRemovalRule\Fixture; interface AnInterface { diff --git a/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/AnInterfaceOther.php b/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/AnInterfaceOther.php index cd5ab51a..e3f503d0 100644 --- a/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/AnInterfaceOther.php +++ b/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/AnInterfaceOther.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\ForbiddenParamTypeRemovalRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\ForbiddenParamTypeRemovalRule\Fixture; use stdClass; diff --git a/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/HasDifferentParameterWithInterfaceMethod.php b/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/HasDifferentParameterWithInterfaceMethod.php index 2d1e5c6d..1ffc743f 100644 --- a/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/HasDifferentParameterWithInterfaceMethod.php +++ b/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/HasDifferentParameterWithInterfaceMethod.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\ForbiddenParamTypeRemovalRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\ForbiddenParamTypeRemovalRule\Fixture; class HasDifferentParameterWithInterfaceMethod implements AnInterface, AnInterfaceOther { diff --git a/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/HasDifferentParameterWithParentMethod.php b/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/HasDifferentParameterWithParentMethod.php index 21291bd1..16d5d64c 100644 --- a/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/HasDifferentParameterWithParentMethod.php +++ b/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/HasDifferentParameterWithParentMethod.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\ForbiddenParamTypeRemovalRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\ForbiddenParamTypeRemovalRule\Fixture; class HasDifferentParameterWithParentMethod extends ParentClass { diff --git a/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/ParentClass.php b/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/ParentClass.php index 7b046f03..79f41a91 100644 --- a/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/ParentClass.php +++ b/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/ParentClass.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\ForbiddenParamTypeRemovalRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\ForbiddenParamTypeRemovalRule\Fixture; class ParentClass { diff --git a/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/RemoveParentType.php b/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/RemoveParentType.php index 18a18474..ebb25795 100644 --- a/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/RemoveParentType.php +++ b/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/RemoveParentType.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\ForbiddenParamTypeRemovalRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\ForbiddenParamTypeRemovalRule\Fixture; -use Symplify\PHPStanRules\Tests\Rules\ForbiddenParamTypeRemovalRule\Source\SomeRectorInterface; +use Rector\TypePerfect\Tests\Rules\ForbiddenParamTypeRemovalRule\Source\SomeRectorInterface; final class RemoveParentType implements SomeRectorInterface { diff --git a/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/SkipHasSameParameterWithInterfaceMethod.php b/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/SkipHasSameParameterWithInterfaceMethod.php index 32b55871..76df50e7 100644 --- a/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/SkipHasSameParameterWithInterfaceMethod.php +++ b/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/SkipHasSameParameterWithInterfaceMethod.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\ForbiddenParamTypeRemovalRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\ForbiddenParamTypeRemovalRule\Fixture; use stdClass; diff --git a/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/SkipHasSameParameterWithParentMethod.php b/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/SkipHasSameParameterWithParentMethod.php index 8e4da473..62650fbc 100644 --- a/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/SkipHasSameParameterWithParentMethod.php +++ b/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/SkipHasSameParameterWithParentMethod.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\ForbiddenParamTypeRemovalRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\ForbiddenParamTypeRemovalRule\Fixture; class SkipHasSameParameterWithParentMethod extends ParentClass { diff --git a/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/SkipIndirectRemoval.php b/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/SkipIndirectRemoval.php index f8bc6d0c..3c324a0c 100644 --- a/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/SkipIndirectRemoval.php +++ b/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/SkipIndirectRemoval.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\ForbiddenParamTypeRemovalRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\ForbiddenParamTypeRemovalRule\Fixture; use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; diff --git a/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/SkipNoParent.php b/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/SkipNoParent.php index 233b7a74..29aef297 100644 --- a/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/SkipNoParent.php +++ b/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/SkipNoParent.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\ForbiddenParamTypeRemovalRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\ForbiddenParamTypeRemovalRule\Fixture; class SkipNoParent { diff --git a/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/SkipNoType.php b/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/SkipNoType.php index 654e0946..036cd261 100644 --- a/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/SkipNoType.php +++ b/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/SkipNoType.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\ForbiddenParamTypeRemovalRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\ForbiddenParamTypeRemovalRule\Fixture; -use Symplify\PHPStanRules\Tests\Rules\ForbiddenParamTypeRemovalRule\Source\NoTypeInterface; +use Rector\TypePerfect\Tests\Rules\ForbiddenParamTypeRemovalRule\Source\NoTypeInterface; final class SkipNoType implements NoTypeInterface { diff --git a/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/SkipNotHasParentMethod.php b/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/SkipNotHasParentMethod.php index dbe8218a..389f851d 100644 --- a/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/SkipNotHasParentMethod.php +++ b/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/SkipNotHasParentMethod.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\ForbiddenParamTypeRemovalRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\ForbiddenParamTypeRemovalRule\Fixture; class SkipNotHasParentMethod extends ParentClass { diff --git a/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/SkipPhpDocType.php b/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/SkipPhpDocType.php index 05835e8c..e1d2f52a 100644 --- a/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/SkipPhpDocType.php +++ b/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/SkipPhpDocType.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\ForbiddenParamTypeRemovalRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\ForbiddenParamTypeRemovalRule\Fixture; -use Symplify\PHPStanRules\Tests\Rules\ForbiddenParamTypeRemovalRule\Source\PhpDocType; +use Rector\TypePerfect\Tests\Rules\ForbiddenParamTypeRemovalRule\Source\PhpDocType; final class SkipPhpDocType extends PhpDocType { diff --git a/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/SkipPresentType.php b/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/SkipPresentType.php index 86637d7f..3193a2c1 100644 --- a/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/SkipPresentType.php +++ b/tests/Rules/ForbiddenParamTypeRemovalRule/Fixture/SkipPresentType.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\ForbiddenParamTypeRemovalRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\ForbiddenParamTypeRemovalRule\Fixture; -use Symplify\PHPStanRules\Tests\Rules\ForbiddenParamTypeRemovalRule\Source\SomeNode; -use Symplify\PHPStanRules\Tests\Rules\ForbiddenParamTypeRemovalRule\Source\SomeRectorInterface; +use Rector\TypePerfect\Tests\Rules\ForbiddenParamTypeRemovalRule\Source\SomeNode; +use Rector\TypePerfect\Tests\Rules\ForbiddenParamTypeRemovalRule\Source\SomeRectorInterface; final class SkipPresentType implements SomeRectorInterface { diff --git a/tests/Rules/ForbiddenParamTypeRemovalRule/ForbiddenParamTypeRemovalRuleTest.php b/tests/Rules/ForbiddenParamTypeRemovalRule/ForbiddenParamTypeRemovalRuleTest.php index 5f5a6b12..b0e5845f 100644 --- a/tests/Rules/ForbiddenParamTypeRemovalRule/ForbiddenParamTypeRemovalRuleTest.php +++ b/tests/Rules/ForbiddenParamTypeRemovalRule/ForbiddenParamTypeRemovalRuleTest.php @@ -2,28 +2,26 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\ForbiddenParamTypeRemovalRule; +namespace Rector\TypePerfect\Tests\Rules\ForbiddenParamTypeRemovalRule; use Iterator; use PHPStan\Rules\Rule; use PHPStan\Testing\RuleTestCase; -use Symplify\PHPStanRules\Rules\ForbiddenParamTypeRemovalRule; +use PHPUnit\Framework\Attributes\DataProvider; +use Rector\TypePerfect\Rules\ForbiddenParamTypeRemovalRule; -/** - * @extends RuleTestCase - */ final class ForbiddenParamTypeRemovalRuleTest extends RuleTestCase { /** - * @dataProvider provideData() * @param mixed[] $expectedErrorMessagesWithLines */ + #[DataProvider('provideData')] public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void { $this->analyse([$filePath], $expectedErrorMessagesWithLines); } - public function provideData(): Iterator + public static function provideData(): Iterator { yield [__DIR__ . '/Fixture/SkipPhpDocType.php', []]; yield [__DIR__ . '/Fixture/SkipPresentType.php', []]; diff --git a/tests/Rules/ForbiddenParamTypeRemovalRule/Source/NoTypeInterface.php b/tests/Rules/ForbiddenParamTypeRemovalRule/Source/NoTypeInterface.php index aeeccbf3..adabceaa 100644 --- a/tests/Rules/ForbiddenParamTypeRemovalRule/Source/NoTypeInterface.php +++ b/tests/Rules/ForbiddenParamTypeRemovalRule/Source/NoTypeInterface.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\ForbiddenParamTypeRemovalRule\Source; +namespace Rector\TypePerfect\Tests\Rules\ForbiddenParamTypeRemovalRule\Source; interface NoTypeInterface { diff --git a/tests/Rules/ForbiddenParamTypeRemovalRule/Source/PhpDocType.php b/tests/Rules/ForbiddenParamTypeRemovalRule/Source/PhpDocType.php index 4f54a977..10963080 100644 --- a/tests/Rules/ForbiddenParamTypeRemovalRule/Source/PhpDocType.php +++ b/tests/Rules/ForbiddenParamTypeRemovalRule/Source/PhpDocType.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\ForbiddenParamTypeRemovalRule\Source; +namespace Rector\TypePerfect\Tests\Rules\ForbiddenParamTypeRemovalRule\Source; class PhpDocType { diff --git a/tests/Rules/ForbiddenParamTypeRemovalRule/Source/SomeNode.php b/tests/Rules/ForbiddenParamTypeRemovalRule/Source/SomeNode.php index c297e19b..effb9995 100644 --- a/tests/Rules/ForbiddenParamTypeRemovalRule/Source/SomeNode.php +++ b/tests/Rules/ForbiddenParamTypeRemovalRule/Source/SomeNode.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\ForbiddenParamTypeRemovalRule\Source; +namespace Rector\TypePerfect\Tests\Rules\ForbiddenParamTypeRemovalRule\Source; final class SomeNode { diff --git a/tests/Rules/ForbiddenParamTypeRemovalRule/Source/SomeRectorInterface.php b/tests/Rules/ForbiddenParamTypeRemovalRule/Source/SomeRectorInterface.php index 2855efb7..5584a4a8 100644 --- a/tests/Rules/ForbiddenParamTypeRemovalRule/Source/SomeRectorInterface.php +++ b/tests/Rules/ForbiddenParamTypeRemovalRule/Source/SomeRectorInterface.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\ForbiddenParamTypeRemovalRule\Source; +namespace Rector\TypePerfect\Tests\Rules\ForbiddenParamTypeRemovalRule\Source; interface SomeRectorInterface { diff --git a/tests/Rules/ForbiddenParamTypeRemovalRule/config/configured_rule.neon b/tests/Rules/ForbiddenParamTypeRemovalRule/config/configured_rule.neon index 5f36f90b..8fadb5a0 100644 --- a/tests/Rules/ForbiddenParamTypeRemovalRule/config/configured_rule.neon +++ b/tests/Rules/ForbiddenParamTypeRemovalRule/config/configured_rule.neon @@ -1,5 +1,5 @@ includes: - - ../../../config/included_services.neon + - ../../../../config/services.neon rules: - - Symplify\PHPStanRules\Rules\ForbiddenParamTypeRemovalRule + - Rector\TypePerfect\Rules\ForbiddenParamTypeRemovalRule diff --git a/tests/Rules/ForbiddenProtectedPropertyRule/Fixture/HasProtectedPropertyAndConstant.php b/tests/Rules/ForbiddenProtectedPropertyRule/Fixture/HasProtectedPropertyAndConstant.php deleted file mode 100644 index 31bb89e1..00000000 --- a/tests/Rules/ForbiddenProtectedPropertyRule/Fixture/HasProtectedPropertyAndConstant.php +++ /dev/null @@ -1,16 +0,0 @@ -config = $configuration; - } -} diff --git a/tests/Rules/ForbiddenProtectedPropertyRule/Fixture/SkipAbstractClassWithAutowireInjection.php b/tests/Rules/ForbiddenProtectedPropertyRule/Fixture/SkipAbstractClassWithAutowireInjection.php deleted file mode 100644 index d08b2c34..00000000 --- a/tests/Rules/ForbiddenProtectedPropertyRule/Fixture/SkipAbstractClassWithAutowireInjection.php +++ /dev/null @@ -1,18 +0,0 @@ -config = $configuration; - } -} diff --git a/tests/Rules/ForbiddenProtectedPropertyRule/Fixture/SkipAbstractClassWithConstructorInjection.php b/tests/Rules/ForbiddenProtectedPropertyRule/Fixture/SkipAbstractClassWithConstructorInjection.php deleted file mode 100644 index c087b386..00000000 --- a/tests/Rules/ForbiddenProtectedPropertyRule/Fixture/SkipAbstractClassWithConstructorInjection.php +++ /dev/null @@ -1,15 +0,0 @@ -config = $configuration; - } -} diff --git a/tests/Rules/ForbiddenProtectedPropertyRule/Fixture/SkipAbstractClassWithConstructorSetValues.php b/tests/Rules/ForbiddenProtectedPropertyRule/Fixture/SkipAbstractClassWithConstructorSetValues.php deleted file mode 100644 index 31f51c69..00000000 --- a/tests/Rules/ForbiddenProtectedPropertyRule/Fixture/SkipAbstractClassWithConstructorSetValues.php +++ /dev/null @@ -1,15 +0,0 @@ -whatever = 10000; - } -} diff --git a/tests/Rules/ForbiddenProtectedPropertyRule/Fixture/SkipAbstractClassWithTestCaseSetUp.php b/tests/Rules/ForbiddenProtectedPropertyRule/Fixture/SkipAbstractClassWithTestCaseSetUp.php deleted file mode 100644 index cd3566ef..00000000 --- a/tests/Rules/ForbiddenProtectedPropertyRule/Fixture/SkipAbstractClassWithTestCaseSetUp.php +++ /dev/null @@ -1,17 +0,0 @@ -config = 100; - } -} diff --git a/tests/Rules/ForbiddenProtectedPropertyRule/Fixture/SkipHasNonProtectedPropertyAndConstant.php b/tests/Rules/ForbiddenProtectedPropertyRule/Fixture/SkipHasNonProtectedPropertyAndConstant.php deleted file mode 100644 index 148fa3d4..00000000 --- a/tests/Rules/ForbiddenProtectedPropertyRule/Fixture/SkipHasNonProtectedPropertyAndConstant.php +++ /dev/null @@ -1,17 +0,0 @@ - - */ -final class ForbiddenProtectedPropertyRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipAbstractClassWithAutowireAttributeInjection.php', []]; - yield [__DIR__ . '/Fixture/SkipParentGuardedProperty.php', []]; - yield [__DIR__ . '/Fixture/SkipHasNonProtectedPropertyAndConstant.php', []]; - yield [__DIR__ . '/Fixture/SkipAbstractClassWithConstructorInjection.php', []]; - yield [__DIR__ . '/Fixture/SkipAbstractClassWithConstructorSetValues.php', []]; - yield [__DIR__ . '/Fixture/SkipAbstractClassWithAutowireInjection.php', []]; - yield [__DIR__ . '/Fixture/SkipAbstractClassWithTestCaseSetUp.php', []]; - yield [__DIR__ . '/Fixture/SkipAbstractAnyTestCase.php', []]; - - yield [__DIR__ . '/Fixture/HasProtectedPropertyAndConstant.php', [ - [ForbiddenProtectedPropertyRule::ERROR_MESSAGE, 11], - [ForbiddenProtectedPropertyRule::ERROR_MESSAGE, 15], - ]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(ForbiddenProtectedPropertyRule::class); - } -} diff --git a/tests/Rules/ForbiddenProtectedPropertyRule/Source/ParentClassWithProperty.php b/tests/Rules/ForbiddenProtectedPropertyRule/Source/ParentClassWithProperty.php deleted file mode 100644 index d72a32e3..00000000 --- a/tests/Rules/ForbiddenProtectedPropertyRule/Source/ParentClassWithProperty.php +++ /dev/null @@ -1,10 +0,0 @@ -process(...$paths); - } -} diff --git a/tests/Rules/ForbiddenSpreadOperatorRule/Fixture/SkipNoSpreadOperator.php b/tests/Rules/ForbiddenSpreadOperatorRule/Fixture/SkipNoSpreadOperator.php deleted file mode 100644 index 5bfc7359..00000000 --- a/tests/Rules/ForbiddenSpreadOperatorRule/Fixture/SkipNoSpreadOperator.php +++ /dev/null @@ -1,13 +0,0 @@ - - */ -final class ForbiddenSpreadOperatorRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipNoSpreadOperator.php', []]; - yield [__DIR__ . '/Fixture/SkipFirstVariadic.php', []]; - - yield [__DIR__ . '/Fixture/SpreadOperator.php', [[ForbiddenSpreadOperatorRule::ERROR_MESSAGE, 11]]]; - yield [__DIR__ . '/Fixture/SpreadOperatorAsMethodArg.php', [[ForbiddenSpreadOperatorRule::ERROR_MESSAGE, 9]]]; - yield [__DIR__ . '/Fixture/SpreadOperatorAsFunctionArg.php', [[ForbiddenSpreadOperatorRule::ERROR_MESSAGE, 7]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(ForbiddenSpreadOperatorRule::class); - } -} diff --git a/tests/Rules/ForbiddenSpreadOperatorRule/Source/ClassMethodWithFirstArgumentVariadic.php b/tests/Rules/ForbiddenSpreadOperatorRule/Source/ClassMethodWithFirstArgumentVariadic.php deleted file mode 100644 index 48ed71c5..00000000 --- a/tests/Rules/ForbiddenSpreadOperatorRule/Source/ClassMethodWithFirstArgumentVariadic.php +++ /dev/null @@ -1,12 +0,0 @@ - - */ -final class ForbiddenTestsNamespaceOutsideTestsDirectoryRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorsWithLines - */ - public function testRule(string $filePath, array $expectedErrorsWithLines): void - { - $this->analyse([$filePath], $expectedErrorsWithLines); - } - - /** - * @return Iterator> - */ - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/tests/SkipTestsNamespaceInsideTestsDirectoryClass.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(ForbiddenTestsNamespaceOutsideTestsDirectoryRule::class); - } -} diff --git a/tests/Rules/ForbiddenTestsNamespaceOutsideTestsDirectoryRule/config/configured_rule.neon b/tests/Rules/ForbiddenTestsNamespaceOutsideTestsDirectoryRule/config/configured_rule.neon deleted file mode 100644 index b4a4244b..00000000 --- a/tests/Rules/ForbiddenTestsNamespaceOutsideTestsDirectoryRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\ForbiddenTestsNamespaceOutsideTestsDirectoryRule diff --git a/tests/Rules/ForbiddenThisArgumentRule/Fixture/ArgInFuncCall.php b/tests/Rules/ForbiddenThisArgumentRule/Fixture/ArgInFuncCall.php deleted file mode 100644 index 34b84fc1..00000000 --- a/tests/Rules/ForbiddenThisArgumentRule/Fixture/ArgInFuncCall.php +++ /dev/null @@ -1,13 +0,0 @@ -service->execute($this); - } - - public function registerContainerConfiguration(LoaderInterface $loader): void - { - } - - public function registerBundles(): iterable - { - } -} diff --git a/tests/Rules/ForbiddenThisArgumentRule/Fixture/SkipMethodExists.php b/tests/Rules/ForbiddenThisArgumentRule/Fixture/SkipMethodExists.php deleted file mode 100644 index 0b70308a..00000000 --- a/tests/Rules/ForbiddenThisArgumentRule/Fixture/SkipMethodExists.php +++ /dev/null @@ -1,17 +0,0 @@ -service->execute(Foo::class); - } -} diff --git a/tests/Rules/ForbiddenThisArgumentRule/Fixture/SkipNotVariable.php b/tests/Rules/ForbiddenThisArgumentRule/Fixture/SkipNotVariable.php deleted file mode 100644 index 8b71ce2a..00000000 --- a/tests/Rules/ForbiddenThisArgumentRule/Fixture/SkipNotVariable.php +++ /dev/null @@ -1,13 +0,0 @@ -service->execute(execute()); - } -} diff --git a/tests/Rules/ForbiddenThisArgumentRule/Fixture/SkipReflectionCalling.php b/tests/Rules/ForbiddenThisArgumentRule/Fixture/SkipReflectionCalling.php deleted file mode 100644 index a5cbe6ed..00000000 --- a/tests/Rules/ForbiddenThisArgumentRule/Fixture/SkipReflectionCalling.php +++ /dev/null @@ -1,15 +0,0 @@ -callPrivateMethod($this, 'run', []); - } -} diff --git a/tests/Rules/ForbiddenThisArgumentRule/Fixture/StaticCall.php b/tests/Rules/ForbiddenThisArgumentRule/Fixture/StaticCall.php deleted file mode 100644 index 2519e567..00000000 --- a/tests/Rules/ForbiddenThisArgumentRule/Fixture/StaticCall.php +++ /dev/null @@ -1,15 +0,0 @@ -service->execute($this); - } -} diff --git a/tests/Rules/ForbiddenThisArgumentRule/Fixture/ThisArgumentCopy.php b/tests/Rules/ForbiddenThisArgumentRule/Fixture/ThisArgumentCopy.php deleted file mode 100644 index 96fa1302..00000000 --- a/tests/Rules/ForbiddenThisArgumentRule/Fixture/ThisArgumentCopy.php +++ /dev/null @@ -1,14 +0,0 @@ -service->execute($self); - } -} diff --git a/tests/Rules/ForbiddenThisArgumentRule/ForbiddenThisArgumentRuleTest.php b/tests/Rules/ForbiddenThisArgumentRule/ForbiddenThisArgumentRuleTest.php deleted file mode 100644 index 875988ed..00000000 --- a/tests/Rules/ForbiddenThisArgumentRule/ForbiddenThisArgumentRuleTest.php +++ /dev/null @@ -1,52 +0,0 @@ - - */ -final class ForbiddenThisArgumentRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipMethodExists.php', []]; - yield [__DIR__ . '/Fixture/SkipReflectionCalling.php', []]; - yield [__DIR__ . '/Fixture/SkipNotVariable.php', []]; - yield [__DIR__ . '/Fixture/SkipNotThis.php', []]; - yield [__DIR__ . '/Fixture/SkipExtendsKernel.php', []]; - - yield [__DIR__ . '/Fixture/StaticCall.php', [[ForbiddenThisArgumentRule::ERROR_MESSAGE, 13]]]; - yield [__DIR__ . '/Fixture/ThisArgument.php', [[ForbiddenThisArgumentRule::ERROR_MESSAGE, 11]]]; - yield [__DIR__ . '/Fixture/ThisArgumentCopy.php', [[ForbiddenThisArgumentRule::ERROR_MESSAGE, 12]]]; - yield [__DIR__ . '/Fixture/ArgInFuncCall.php', [[ForbiddenThisArgumentRule::ERROR_MESSAGE, 11]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(ForbiddenThisArgumentRule::class); - } -} diff --git a/tests/Rules/ForbiddenThisArgumentRule/Source/SomeStaticService.php b/tests/Rules/ForbiddenThisArgumentRule/Source/SomeStaticService.php deleted file mode 100644 index 2651dc72..00000000 --- a/tests/Rules/ForbiddenThisArgumentRule/Source/SomeStaticService.php +++ /dev/null @@ -1,12 +0,0 @@ - - */ -final class CheckSprintfMatchingTypesRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/MissMatchSprintf.php', [[CheckSprintfMatchingTypesRule::ERROR_MESSAGE, 11]]]; - - yield [__DIR__ . '/Fixture/SkipCorrectSprintf.php', []]; - yield [__DIR__ . '/Fixture/SkipCorrectForeachKey.php', []]; - yield [__DIR__ . '/Fixture/SkipToString.php', []]; - yield [__DIR__ . '/Fixture/SkipErrorType.php', []]; - yield [__DIR__ . '/Fixture/SkipValidTernary.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(CheckSprintfMatchingTypesRule::class); - } -} diff --git a/tests/Rules/Missing/CheckSprintfMatchingTypesRule/Fixture/MissMatchSprintf.php b/tests/Rules/Missing/CheckSprintfMatchingTypesRule/Fixture/MissMatchSprintf.php deleted file mode 100644 index 56c98eb5..00000000 --- a/tests/Rules/Missing/CheckSprintfMatchingTypesRule/Fixture/MissMatchSprintf.php +++ /dev/null @@ -1,13 +0,0 @@ - 'value', - 100 => '1' - ]; - - $messages = []; - foreach ($values as $key => $value) { - $messages[] = sprintf('String key %s', $key); - } - } -} diff --git a/tests/Rules/Missing/CheckSprintfMatchingTypesRule/Fixture/SkipCorrectSprintf.php b/tests/Rules/Missing/CheckSprintfMatchingTypesRule/Fixture/SkipCorrectSprintf.php deleted file mode 100644 index 78f785b6..00000000 --- a/tests/Rules/Missing/CheckSprintfMatchingTypesRule/Fixture/SkipCorrectSprintf.php +++ /dev/null @@ -1,13 +0,0 @@ -value = $value; - } - - public function __toString() - { - return $this->value; - } -} diff --git a/tests/Rules/Missing/CheckSprintfMatchingTypesRule/config/configured_rule.neon b/tests/Rules/Missing/CheckSprintfMatchingTypesRule/config/configured_rule.neon deleted file mode 100644 index 3415ee0e..00000000 --- a/tests/Rules/Missing/CheckSprintfMatchingTypesRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\Missing\CheckSprintfMatchingTypesRule diff --git a/tests/Rules/CheckTypehintCallerTypeRule/CheckTypehintCallerTypeRuleTest.php b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/CheckTypehintCallerTypeRuleTest.php similarity index 65% rename from tests/Rules/CheckTypehintCallerTypeRule/CheckTypehintCallerTypeRuleTest.php rename to tests/Rules/NarrowPrivateClassMethodParamTypeRule/CheckTypehintCallerTypeRuleTest.php index 1f518804..acd6b267 100644 --- a/tests/Rules/CheckTypehintCallerTypeRule/CheckTypehintCallerTypeRuleTest.php +++ b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/CheckTypehintCallerTypeRuleTest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\CheckTypehintCallerTypeRule; +namespace Rector\TypePerfect\Tests\Rules\NarrowPrivateClassMethodParamTypeRule; use Iterator; use PhpParser\Node\Arg; @@ -10,23 +10,21 @@ use PhpParser\Node\Param; use PHPStan\Rules\Rule; use PHPStan\Testing\RuleTestCase; -use Symplify\PHPStanRules\Rules\CheckTypehintCallerTypeRule; +use PHPUnit\Framework\Attributes\DataProvider; +use Rector\TypePerfect\Rules\NarrowPrivateClassMethodParamTypeRule; -/** - * @extends RuleTestCase - */ -final class CheckTypehintCallerTypeRuleTest extends RuleTestCase +final class NarrowPrivateClassMethodParamTypeRuleTest extends RuleTestCase { /** - * @dataProvider provideData() * @param mixed[] $expectedErrorsWithLines */ + #[DataProvider('provideData')] public function testRule(string $filePath, array $expectedErrorsWithLines): void { $this->analyse([$filePath], $expectedErrorsWithLines); } - public function provideData(): Iterator + public static function provideData(): Iterator { yield [__DIR__ . '/Fixture/SkipDuplicatedCallOfSameMethodWithComment.php', []]; @@ -43,13 +41,15 @@ public function provideData(): Iterator yield [__DIR__ . '/Fixture/SkipMultipleUsed.php', []]; yield [__DIR__ . '/Fixture/SkipNotPrivate.php', []]; - $errorMessage = sprintf(CheckTypehintCallerTypeRule::ERROR_MESSAGE, 1, MethodCall::class); + $errorMessage = sprintf(NarrowPrivateClassMethodParamTypeRule::ERROR_MESSAGE, 1, MethodCall::class); yield [__DIR__ . '/Fixture/Fixture.php', [[$errorMessage, 19]]]; yield [__DIR__ . '/Fixture/DifferentClassSameMethodCallName.php', [[$errorMessage, 25]]]; - $argErrorMessage = sprintf(CheckTypehintCallerTypeRule::ERROR_MESSAGE, 1, Arg::class); - $paramErrorMessage = sprintf(CheckTypehintCallerTypeRule::ERROR_MESSAGE, 2, Param::class); + $argErrorMessage = sprintf(NarrowPrivateClassMethodParamTypeRule::ERROR_MESSAGE, 1, Arg::class); + $paramErrorMessage = sprintf(NarrowPrivateClassMethodParamTypeRule::ERROR_MESSAGE, 2, Param::class); yield [__DIR__ . '/Fixture/DoubleShot.php', [[$argErrorMessage, 15], [$paramErrorMessage, 15]]]; + yield [__DIR__ . '/Fixture/SkipGenericType.php', []]; + yield [__DIR__ . '/Fixture/SkipAbstractBase.php', []]; } /** @@ -62,6 +62,6 @@ public static function getAdditionalConfigFiles(): array protected function getRule(): Rule { - return self::getContainer()->getByType(CheckTypehintCallerTypeRule::class); + return self::getContainer()->getByType(NarrowPrivateClassMethodParamTypeRule::class); } } diff --git a/tests/Rules/CheckTypehintCallerTypeRule/Fixture/DifferentClassSameMethodCallName.php b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/DifferentClassSameMethodCallName.php similarity index 67% rename from tests/Rules/CheckTypehintCallerTypeRule/Fixture/DifferentClassSameMethodCallName.php rename to tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/DifferentClassSameMethodCallName.php index b915601b..31c25875 100644 --- a/tests/Rules/CheckTypehintCallerTypeRule/Fixture/DifferentClassSameMethodCallName.php +++ b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/DifferentClassSameMethodCallName.php @@ -2,12 +2,12 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\CheckTypehintCallerTypeRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\NarrowPrivateClassMethodParamTypeRule\Fixture; use PhpParser\Node; use PhpParser\Node\Expr\MethodCall; -use Symplify\PHPStanRules\Tests\Rules\CheckTypehintCallerTypeRule\Source\AnotherClassWithRun; -use Symplify\PHPStanRules\Tests\Rules\PreferredClassRule\Fixture\SomeStaticCall; +use Rector\TypePerfect\Tests\Rules\NarrowPrivateClassMethodParamTypeRule\Source\AnotherClassWithRun; +use Rector\TypePerfect\Tests\Rules\PreferredClassRule\Fixture\SomeStaticCall; class DifferentClassSameMethodCallName { diff --git a/tests/Rules/CheckTypehintCallerTypeRule/Fixture/DoubleShot.php b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/DoubleShot.php similarity index 75% rename from tests/Rules/CheckTypehintCallerTypeRule/Fixture/DoubleShot.php rename to tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/DoubleShot.php index 189b34b1..a9a8d499 100644 --- a/tests/Rules/CheckTypehintCallerTypeRule/Fixture/DoubleShot.php +++ b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/DoubleShot.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\CheckTypehintCallerTypeRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\NarrowPrivateClassMethodParamTypeRule\Fixture; use PhpParser\Node; diff --git a/tests/Rules/CheckTypehintCallerTypeRule/Fixture/Fixture.php b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/Fixture.php similarity index 77% rename from tests/Rules/CheckTypehintCallerTypeRule/Fixture/Fixture.php rename to tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/Fixture.php index d018bc45..68bd53cc 100644 --- a/tests/Rules/CheckTypehintCallerTypeRule/Fixture/Fixture.php +++ b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/Fixture.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\CheckTypehintCallerTypeRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\NarrowPrivateClassMethodParamTypeRule\Fixture; use PhpParser\Node; use PhpParser\Node\Expr\MethodCall; diff --git a/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipAbstractBase.php b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipAbstractBase.php new file mode 100644 index 00000000..ecafcfb7 --- /dev/null +++ b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipAbstractBase.php @@ -0,0 +1,16 @@ +isCheck($arg); + } + private function isCheck(ConceptBase $arg) + { + } +} diff --git a/tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipAlreadyCorrectType.php b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipAlreadyCorrectType.php similarity index 78% rename from tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipAlreadyCorrectType.php rename to tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipAlreadyCorrectType.php index 02afd973..f74f3dd6 100644 --- a/tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipAlreadyCorrectType.php +++ b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipAlreadyCorrectType.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\CheckTypehintCallerTypeRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\NarrowPrivateClassMethodParamTypeRule\Fixture; use PhpParser\Node; use PhpParser\Node\Expr\MethodCall; diff --git a/tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipCorrectUnionType.php b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipCorrectUnionType.php similarity index 86% rename from tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipCorrectUnionType.php rename to tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipCorrectUnionType.php index d65fe635..9480df8a 100644 --- a/tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipCorrectUnionType.php +++ b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipCorrectUnionType.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\CheckTypehintCallerTypeRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\NarrowPrivateClassMethodParamTypeRule\Fixture; use PhpParser\Node\Expr\Assign; use PhpParser\Node\Stmt\Return_; diff --git a/tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipDuplicatedCallOfSameMethodWithComment.php b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipDuplicatedCallOfSameMethodWithComment.php similarity index 84% rename from tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipDuplicatedCallOfSameMethodWithComment.php rename to tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipDuplicatedCallOfSameMethodWithComment.php index a639dd02..632fc7de 100644 --- a/tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipDuplicatedCallOfSameMethodWithComment.php +++ b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipDuplicatedCallOfSameMethodWithComment.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\CheckTypehintCallerTypeRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\NarrowPrivateClassMethodParamTypeRule\Fixture; use PHPStan\Node\FileNode; use Rector\Core\PhpParser\Node\CustomNode\FileWithoutNamespace; diff --git a/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipGenericType.php b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipGenericType.php new file mode 100644 index 00000000..e62b5097 --- /dev/null +++ b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipGenericType.php @@ -0,0 +1,31 @@ +getsAGeneric($node); + } + + /** + * @param T $node + * @return void + */ + private function getsAGeneric(Node $node) + { + } +} diff --git a/tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipMayOverrideArg.php b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipMayOverrideArg.php similarity index 82% rename from tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipMayOverrideArg.php rename to tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipMayOverrideArg.php index f6ad3ced..b2658cd3 100644 --- a/tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipMayOverrideArg.php +++ b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipMayOverrideArg.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\CheckTypehintCallerTypeRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\NarrowPrivateClassMethodParamTypeRule\Fixture; use PhpParser\Node; use PhpParser\Node\Expr\MethodCall; diff --git a/tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipMixed.php b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipMixed.php similarity index 70% rename from tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipMixed.php rename to tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipMixed.php index b82eca26..66a104e1 100644 --- a/tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipMixed.php +++ b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipMixed.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\CheckTypehintCallerTypeRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\NarrowPrivateClassMethodParamTypeRule\Fixture; use PhpParser\Node; diff --git a/tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipMultipleUsed.php b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipMultipleUsed.php similarity index 83% rename from tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipMultipleUsed.php rename to tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipMultipleUsed.php index df663df6..1919ec98 100644 --- a/tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipMultipleUsed.php +++ b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipMultipleUsed.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\CheckTypehintCallerTypeRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\NarrowPrivateClassMethodParamTypeRule\Fixture; use PhpParser\Node; use PhpParser\Node\Expr\MethodCall; diff --git a/tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipNoArgs.php b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipNoArgs.php similarity index 62% rename from tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipNoArgs.php rename to tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipNoArgs.php index c308ec73..90094439 100644 --- a/tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipNoArgs.php +++ b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipNoArgs.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\CheckTypehintCallerTypeRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\NarrowPrivateClassMethodParamTypeRule\Fixture; use PhpParser\Node; diff --git a/tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipNotFromThis.php b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipNotFromThis.php similarity index 66% rename from tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipNotFromThis.php rename to tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipNotFromThis.php index 5fc6fa71..65436953 100644 --- a/tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipNotFromThis.php +++ b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipNotFromThis.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\CheckTypehintCallerTypeRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\NarrowPrivateClassMethodParamTypeRule\Fixture; final class SkipNotFromThis { diff --git a/tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipNotPrivate.php b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipNotPrivate.php similarity index 78% rename from tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipNotPrivate.php rename to tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipNotPrivate.php index 54dcfea8..a16c0ad1 100644 --- a/tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipNotPrivate.php +++ b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipNotPrivate.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\CheckTypehintCallerTypeRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\NarrowPrivateClassMethodParamTypeRule\Fixture; use PhpParser\Node; use PhpParser\Node\Expr\MethodCall; diff --git a/tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipOptedOut.php b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipOptedOut.php similarity index 78% rename from tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipOptedOut.php rename to tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipOptedOut.php index 6c6091e5..a74a81b1 100644 --- a/tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipOptedOut.php +++ b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipOptedOut.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\CheckTypehintCallerTypeRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\NarrowPrivateClassMethodParamTypeRule\Fixture; use PHPStan\Type\MixedType; diff --git a/tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipParentNotIf.php b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipParentNotIf.php similarity index 65% rename from tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipParentNotIf.php rename to tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipParentNotIf.php index 455b9ee9..04a51b74 100644 --- a/tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipParentNotIf.php +++ b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipParentNotIf.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\CheckTypehintCallerTypeRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\NarrowPrivateClassMethodParamTypeRule\Fixture; use PhpParser\Node; diff --git a/tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipRecursive.php b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipRecursive.php similarity index 73% rename from tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipRecursive.php rename to tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipRecursive.php index 192a14c6..b0984640 100644 --- a/tests/Rules/CheckTypehintCallerTypeRule/Fixture/SkipRecursive.php +++ b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Fixture/SkipRecursive.php @@ -2,11 +2,11 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\CheckTypehintCallerTypeRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\NarrowPrivateClassMethodParamTypeRule\Fixture; use PhpParser\Node; use PhpParser\Node\Expr\MethodCall; -use Symplify\PHPStanRules\Tests\Rules\PreferredClassRule\Fixture\SomeStaticCall; +use Rector\TypePerfect\Tests\Rules\PreferredClassRule\Fixture\SomeStaticCall; class SkipRecursive { diff --git a/tests/Rules/CheckTypehintCallerTypeRule/Source/AnotherClassWithRun.php b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Source/AnotherClassWithRun.php similarity index 64% rename from tests/Rules/CheckTypehintCallerTypeRule/Source/AnotherClassWithRun.php rename to tests/Rules/NarrowPrivateClassMethodParamTypeRule/Source/AnotherClassWithRun.php index 24f6228f..0b3ba332 100644 --- a/tests/Rules/CheckTypehintCallerTypeRule/Source/AnotherClassWithRun.php +++ b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Source/AnotherClassWithRun.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\CheckTypehintCallerTypeRule\Source; +namespace Rector\TypePerfect\Tests\Rules\NarrowPrivateClassMethodParamTypeRule\Source; use PhpParser\Node; diff --git a/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Source/ConceptBase.php b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Source/ConceptBase.php new file mode 100644 index 00000000..e7db6864 --- /dev/null +++ b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/Source/ConceptBase.php @@ -0,0 +1,10 @@ +callMe(...); + + $someCalledMethod->callMe(1000); + } +} diff --git a/tests/Rules/NarrowPublicClassMethodParamTypeRule/Fixture/FirstClassCallables/SomeCalledMethod.php b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Fixture/FirstClassCallables/SomeCalledMethod.php new file mode 100644 index 00000000..3b1da8cc --- /dev/null +++ b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Fixture/FirstClassCallables/SomeCalledMethod.php @@ -0,0 +1,12 @@ + - */ -final class NarrowPublicClassMethodParamTypeByCallerTypeRuleTest extends RuleTestCase +final class NarrowPublicClassMethodParamTypeRuleTest extends RuleTestCase { /** - * @dataProvider provideData() - * * @param string[] $filePaths * @param mixed[] $expectedErrorsWithLines */ + #[DataProvider('provideData')] public function testRule(array $filePaths, array $expectedErrorsWithLines): void { $this->analyse($filePaths, $expectedErrorsWithLines); } - public function provideData(): Iterator + public static function provideData(): Iterator { yield [[__DIR__ . '/Fixture/SkipNonPublicClassMethod.php'], []]; + // skip first class callables as anything can be passed there + yield [[ + __DIR__ . '/Fixture/FirstClassCallables/CallVariadics.php', + __DIR__ . '/Fixture/FirstClassCallables/SomeCalledMethod.php', + ], []]; + // skip expected scalar type yield [[ __DIR__ . '/Fixture/SkipProperlyFilledParamType.php', @@ -122,7 +124,7 @@ public function provideData(): Iterator __DIR__ . '/Source/ExpectedType/OnlyFirstTypeCalledOutside.php', ], []]; - $argErrorMessage = sprintf(NarrowPublicClassMethodParamTypeByCallerTypeRule::ERROR_MESSAGE, 'int'); + $argErrorMessage = sprintf(NarrowPublicClassMethodParamTypeRule::ERROR_MESSAGE, 'int'); yield [[ __DIR__ . '/Fixture/PublicDoubleShot.php', __DIR__ . '/Source/FirstCaller.php', @@ -131,7 +133,7 @@ public function provideData(): Iterator // this passed from interface $argErrorMessage = sprintf( - NarrowPublicClassMethodParamTypeByCallerTypeRule::ERROR_MESSAGE, + NarrowPublicClassMethodParamTypeRule::ERROR_MESSAGE, CallByThisFromInterface::class ); yield [[ @@ -150,7 +152,7 @@ public static function getAdditionalConfigFiles(): array protected function getRule(): Rule { - return self::getContainer()->getByType(NarrowPublicClassMethodParamTypeByCallerTypeRule::class); + return self::getContainer()->getByType(NarrowPublicClassMethodParamTypeRule::class); } /** diff --git a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedClassString/FirstTypedCaller.php b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedClassString/FirstTypedCaller.php similarity index 54% rename from tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedClassString/FirstTypedCaller.php rename to tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedClassString/FirstTypedCaller.php index 87ae41d6..35c8ce08 100644 --- a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedClassString/FirstTypedCaller.php +++ b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedClassString/FirstTypedCaller.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\NarrowType\NarrowPublicClassMethodParamTypeByCallerTypeRule\Source\ExpectedClassString; +namespace Rector\TypePerfect\Tests\Rules\NarrowPublicClassMethodParamTypeRule\Source\ExpectedClassString; use PHPStan\Reflection\ClassReflection; -use Symplify\PHPStanRules\Tests\Rules\NarrowType\NarrowPublicClassMethodParamTypeByCallerTypeRule\Fixture\SkipClassStringPassed; +use Rector\TypePerfect\Tests\Rules\NarrowPublicClassMethodParamTypeRule\Fixture\SkipClassStringPassed; final class FirstTypedCaller { diff --git a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedClassString/SecondTypedCaller.php b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedClassString/SecondTypedCaller.php similarity index 54% rename from tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedClassString/SecondTypedCaller.php rename to tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedClassString/SecondTypedCaller.php index 3ddaf19e..4d4815ab 100644 --- a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedClassString/SecondTypedCaller.php +++ b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedClassString/SecondTypedCaller.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\NarrowType\NarrowPublicClassMethodParamTypeByCallerTypeRule\Source\ExpectedClassString; +namespace Rector\TypePerfect\Tests\Rules\NarrowPublicClassMethodParamTypeRule\Source\ExpectedClassString; use PHPStan\Reflection\ClassReflection; -use Symplify\PHPStanRules\Tests\Rules\NarrowType\NarrowPublicClassMethodParamTypeByCallerTypeRule\Fixture\SkipClassStringPassed; +use Rector\TypePerfect\Tests\Rules\NarrowPublicClassMethodParamTypeRule\Fixture\SkipClassStringPassed; final class SecondTypedCaller { diff --git a/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedClassType/FirstClassTypedCaller.php b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedClassType/FirstClassTypedCaller.php new file mode 100644 index 00000000..8ad53ce6 --- /dev/null +++ b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedClassType/FirstClassTypedCaller.php @@ -0,0 +1,17 @@ +callMeWithClassType($knownType); + } +} diff --git a/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedClassType/SecondClassTypedCaller.php b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedClassType/SecondClassTypedCaller.php new file mode 100644 index 00000000..222edca0 --- /dev/null +++ b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedClassType/SecondClassTypedCaller.php @@ -0,0 +1,17 @@ +callMeWithClassType($knownType); + } +} diff --git a/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedNodeApi/CallWithProperty.php b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedNodeApi/CallWithProperty.php new file mode 100644 index 00000000..44abed42 --- /dev/null +++ b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedNodeApi/CallWithProperty.php @@ -0,0 +1,17 @@ +callNode($property); + } + +} diff --git a/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedThisType/CallByThis.php b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedThisType/CallByThis.php new file mode 100644 index 00000000..e78ad816 --- /dev/null +++ b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedThisType/CallByThis.php @@ -0,0 +1,15 @@ +run($this); + } +} diff --git a/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedThisType/CallByThisFromInterface.php b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedThisType/CallByThisFromInterface.php new file mode 100644 index 00000000..eb90be0c --- /dev/null +++ b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedThisType/CallByThisFromInterface.php @@ -0,0 +1,16 @@ +run($this); + } +} diff --git a/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedType/FirstTypedCaller.php b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedType/FirstTypedCaller.php new file mode 100644 index 00000000..9eacb9d4 --- /dev/null +++ b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedType/FirstTypedCaller.php @@ -0,0 +1,15 @@ +callMeTwice(100); + } +} diff --git a/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedType/OnlyFirstTypeCalledOutside.php b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedType/OnlyFirstTypeCalledOutside.php new file mode 100644 index 00000000..a3e116a3 --- /dev/null +++ b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedType/OnlyFirstTypeCalledOutside.php @@ -0,0 +1,16 @@ +run(new stdClass()); + } +} diff --git a/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedType/SecondTypedCaller.php b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedType/SecondTypedCaller.php new file mode 100644 index 00000000..cc0e2dfe --- /dev/null +++ b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedType/SecondTypedCaller.php @@ -0,0 +1,15 @@ +callMeTwice(100); + } +} diff --git a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedUnion/CallUnionArrayType.php b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedUnion/CallUnionArrayType.php similarity index 70% rename from tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedUnion/CallUnionArrayType.php rename to tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedUnion/CallUnionArrayType.php index f6e620ef..813720b1 100644 --- a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedUnion/CallUnionArrayType.php +++ b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedUnion/CallUnionArrayType.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\NarrowType\NarrowPublicClassMethodParamTypeByCallerTypeRule\Source\ExpectedNodeApi; +namespace Rector\TypePerfect\Tests\Rules\NarrowPublicClassMethodParamTypeRule\Source\ExpectedUnion; use PhpParser\Node; -use Symplify\PHPStanRules\Tests\Rules\NarrowType\NarrowPublicClassMethodParamTypeByCallerTypeRule\Fixture\SkipEqualUnionType; +use Rector\TypePerfect\Tests\Rules\NarrowPublicClassMethodParamTypeRule\Fixture\SkipEqualUnionType; final class CallUnionTypeArrayType { diff --git a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedUnion/CallUnionType.php b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedUnion/CallUnionType.php similarity index 60% rename from tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedUnion/CallUnionType.php rename to tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedUnion/CallUnionType.php index fd0997b2..b3b11a0f 100644 --- a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedUnion/CallUnionType.php +++ b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedUnion/CallUnionType.php @@ -2,11 +2,11 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\NarrowType\NarrowPublicClassMethodParamTypeByCallerTypeRule\Source\ExpectedNodeApi; +namespace Rector\TypePerfect\Tests\Rules\NarrowPublicClassMethodParamTypeRule\Source\ExpectedUnion; use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Expr\StaticCall; -use Symplify\PHPStanRules\Tests\Rules\NarrowType\NarrowPublicClassMethodParamTypeByCallerTypeRule\Fixture\SkipEqualUnionType; +use Rector\TypePerfect\Tests\Rules\NarrowPublicClassMethodParamTypeRule\Fixture\SkipEqualUnionType; final class CallUnionType { diff --git a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedUnion/CallUnionTypeFlipped.php b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedUnion/CallUnionTypeFlipped.php similarity index 60% rename from tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedUnion/CallUnionTypeFlipped.php rename to tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedUnion/CallUnionTypeFlipped.php index 3d11e4b7..a65c98bb 100644 --- a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedUnion/CallUnionTypeFlipped.php +++ b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedUnion/CallUnionTypeFlipped.php @@ -2,11 +2,11 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\NarrowType\NarrowPublicClassMethodParamTypeByCallerTypeRule\Source\ExpectedNodeApi; +namespace Rector\TypePerfect\Tests\Rules\NarrowPublicClassMethodParamTypeRule\Source\ExpectedUnion; use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Expr\StaticCall; -use Symplify\PHPStanRules\Tests\Rules\NarrowType\NarrowPublicClassMethodParamTypeByCallerTypeRule\Fixture\SkipEqualUnionType; +use Rector\TypePerfect\Tests\Rules\NarrowPublicClassMethodParamTypeRule\Fixture\SkipEqualUnionType; final class CallUnionTypeFlipped { diff --git a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedUnion/CallUnionTypeTernaryIfElse.php b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedUnion/CallUnionTypeTernaryIfElse.php similarity index 61% rename from tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedUnion/CallUnionTypeTernaryIfElse.php rename to tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedUnion/CallUnionTypeTernaryIfElse.php index 06b448a2..5643966a 100644 --- a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedUnion/CallUnionTypeTernaryIfElse.php +++ b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedUnion/CallUnionTypeTernaryIfElse.php @@ -2,11 +2,11 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\NarrowType\NarrowPublicClassMethodParamTypeByCallerTypeRule\Source\ExpectedNodeApi; +namespace Rector\TypePerfect\Tests\Rules\NarrowPublicClassMethodParamTypeRule\Source\ExpectedUnion; use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Expr\StaticCall; -use Symplify\PHPStanRules\Tests\Rules\NarrowType\NarrowPublicClassMethodParamTypeByCallerTypeRule\Fixture\SkipEqualUnionType; +use Rector\TypePerfect\Tests\Rules\NarrowPublicClassMethodParamTypeRule\Fixture\SkipEqualUnionType; final class CallUnionTypeTernaryIfElse { diff --git a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedUnion/CallUnionTypeTernaryIfElseFlipped.php b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedUnion/CallUnionTypeTernaryIfElseFlipped.php similarity index 62% rename from tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedUnion/CallUnionTypeTernaryIfElseFlipped.php rename to tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedUnion/CallUnionTypeTernaryIfElseFlipped.php index 44354627..2ac613fa 100644 --- a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedUnion/CallUnionTypeTernaryIfElseFlipped.php +++ b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/ExpectedUnion/CallUnionTypeTernaryIfElseFlipped.php @@ -2,11 +2,11 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\NarrowType\NarrowPublicClassMethodParamTypeByCallerTypeRule\Source\ExpectedNodeApi; +namespace Rector\TypePerfect\Tests\Rules\NarrowPublicClassMethodParamTypeRule\Source\ExpectedUnion; use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Expr\StaticCall; -use Symplify\PHPStanRules\Tests\Rules\NarrowType\NarrowPublicClassMethodParamTypeByCallerTypeRule\Fixture\SkipEqualUnionType; +use Rector\TypePerfect\Tests\Rules\NarrowPublicClassMethodParamTypeRule\Fixture\SkipEqualUnionType; final class CallUnionTypeTernaryIfElseFlipped { diff --git a/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/FirstCaller.php b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/FirstCaller.php new file mode 100644 index 00000000..81565e00 --- /dev/null +++ b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/FirstCaller.php @@ -0,0 +1,15 @@ +callMeTwice(100); + } +} diff --git a/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/MixedAndString/FirstCaller.php b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/MixedAndString/FirstCaller.php new file mode 100644 index 00000000..abf52f56 --- /dev/null +++ b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/MixedAndString/FirstCaller.php @@ -0,0 +1,15 @@ +resolve('string'); + } +} diff --git a/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/MixedAndString/SecondCaller.php b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/MixedAndString/SecondCaller.php new file mode 100644 index 00000000..c087c8d7 --- /dev/null +++ b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/MixedAndString/SecondCaller.php @@ -0,0 +1,15 @@ +resolve($mixedValue); + } +} diff --git a/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/MixedAndString/ThirdCaller.php b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/MixedAndString/ThirdCaller.php new file mode 100644 index 00000000..532bda8b --- /dev/null +++ b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/MixedAndString/ThirdCaller.php @@ -0,0 +1,15 @@ +resolve(1000); + } +} diff --git a/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/NullableParam/FirstNullable.php b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/NullableParam/FirstNullable.php new file mode 100644 index 00000000..b6668616 --- /dev/null +++ b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/NullableParam/FirstNullable.php @@ -0,0 +1,16 @@ +callNode($node); + } +} diff --git a/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/NullableParam/SecondNullable.php b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/NullableParam/SecondNullable.php new file mode 100644 index 00000000..2ace4328 --- /dev/null +++ b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/NullableParam/SecondNullable.php @@ -0,0 +1,16 @@ +callNode($node); + } +} diff --git a/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/PassMeAsType.php b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/PassMeAsType.php new file mode 100644 index 00000000..ee1a0d09 --- /dev/null +++ b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/PassMeAsType.php @@ -0,0 +1,10 @@ +callMeTwice(100); + } +} diff --git a/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/SomeInterface.php b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/SomeInterface.php new file mode 100644 index 00000000..ee3221b0 --- /dev/null +++ b/tests/Rules/NarrowPublicClassMethodParamTypeRule/Source/SomeInterface.php @@ -0,0 +1,8 @@ +callMeWithClassType($knownType); - } -} diff --git a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedClassType/SecondClassTypedCaller.php b/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedClassType/SecondClassTypedCaller.php deleted file mode 100644 index 2115fb45..00000000 --- a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedClassType/SecondClassTypedCaller.php +++ /dev/null @@ -1,17 +0,0 @@ -callMeWithClassType($knownType); - } -} diff --git a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedNodeApi/CallWithProperty.php b/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedNodeApi/CallWithProperty.php deleted file mode 100644 index 953fc231..00000000 --- a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedNodeApi/CallWithProperty.php +++ /dev/null @@ -1,17 +0,0 @@ -callNode($property); - } - -} diff --git a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedThisType/CallByThis.php b/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedThisType/CallByThis.php deleted file mode 100644 index 25550ad7..00000000 --- a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedThisType/CallByThis.php +++ /dev/null @@ -1,15 +0,0 @@ -run($this); - } -} diff --git a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedThisType/CallByThisFromInterface.php b/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedThisType/CallByThisFromInterface.php deleted file mode 100644 index 43c47ccb..00000000 --- a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedThisType/CallByThisFromInterface.php +++ /dev/null @@ -1,16 +0,0 @@ -run($this); - } -} diff --git a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedType/FirstTypedCaller.php b/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedType/FirstTypedCaller.php deleted file mode 100644 index d8e8f8f0..00000000 --- a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedType/FirstTypedCaller.php +++ /dev/null @@ -1,15 +0,0 @@ -callMeTwice(100); - } -} diff --git a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedType/OnlyFirstTypeCalledOutside.php b/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedType/OnlyFirstTypeCalledOutside.php deleted file mode 100644 index 6f87ec43..00000000 --- a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedType/OnlyFirstTypeCalledOutside.php +++ /dev/null @@ -1,16 +0,0 @@ -run(new stdClass()); - } -} diff --git a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedType/SecondTypedCaller.php b/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedType/SecondTypedCaller.php deleted file mode 100644 index f3e4b63b..00000000 --- a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/ExpectedType/SecondTypedCaller.php +++ /dev/null @@ -1,15 +0,0 @@ -callMeTwice(100); - } -} diff --git a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/FirstCaller.php b/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/FirstCaller.php deleted file mode 100644 index 96b2d77d..00000000 --- a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/FirstCaller.php +++ /dev/null @@ -1,15 +0,0 @@ -callMeTwice(100); - } -} diff --git a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/MixedAndString/FirstCaller.php b/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/MixedAndString/FirstCaller.php deleted file mode 100644 index 34668e2a..00000000 --- a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/MixedAndString/FirstCaller.php +++ /dev/null @@ -1,15 +0,0 @@ -resolve('string'); - } -} diff --git a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/MixedAndString/SecondCaller.php b/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/MixedAndString/SecondCaller.php deleted file mode 100644 index 45aebda1..00000000 --- a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/MixedAndString/SecondCaller.php +++ /dev/null @@ -1,15 +0,0 @@ -resolve($mixedValue); - } -} diff --git a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/MixedAndString/ThirdCaller.php b/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/MixedAndString/ThirdCaller.php deleted file mode 100644 index 7a45e1d0..00000000 --- a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/MixedAndString/ThirdCaller.php +++ /dev/null @@ -1,15 +0,0 @@ -resolve(1000); - } -} diff --git a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/NullableParam/FirstNullable.php b/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/NullableParam/FirstNullable.php deleted file mode 100644 index c1fae48d..00000000 --- a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/NullableParam/FirstNullable.php +++ /dev/null @@ -1,16 +0,0 @@ -callNode($node); - } -} diff --git a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/NullableParam/SecondNullable.php b/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/NullableParam/SecondNullable.php deleted file mode 100644 index 45ebf77a..00000000 --- a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/NullableParam/SecondNullable.php +++ /dev/null @@ -1,16 +0,0 @@ -callNode($node); - } -} diff --git a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/PassMeAsType.php b/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/PassMeAsType.php deleted file mode 100644 index 68b73bff..00000000 --- a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/PassMeAsType.php +++ /dev/null @@ -1,10 +0,0 @@ -callMeTwice(100); - } -} diff --git a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/SomeInterface.php b/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/SomeInterface.php deleted file mode 100644 index 2cc7e62f..00000000 --- a/tests/Rules/NarrowType/NarrowPublicClassMethodParamTypeByCallerTypeRule/Source/SomeInterface.php +++ /dev/null @@ -1,8 +0,0 @@ - - */ -final class NoAbstractMethodRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SomeAbstractMethod.php', [[NoAbstractMethodRule::ERROR_MESSAGE, 9]]]; - yield [__DIR__ . '/Fixture/SkipNonAbstractMethod.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoAbstractMethodRule::class); - } -} diff --git a/tests/Rules/NoAbstractMethodRule/config/configured_rule.neon b/tests/Rules/NoAbstractMethodRule/config/configured_rule.neon deleted file mode 100644 index c6a8bd0d..00000000 --- a/tests/Rules/NoAbstractMethodRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\NoAbstractMethodRule diff --git a/tests/Rules/NoArrayAccessOnObjectRule/Fixture/ArrayAccessOnNestedObject.php b/tests/Rules/NoArrayAccessOnObjectRule/Fixture/ArrayAccessOnNestedObject.php index c929dad1..7145d2fa 100644 --- a/tests/Rules/NoArrayAccessOnObjectRule/Fixture/ArrayAccessOnNestedObject.php +++ b/tests/Rules/NoArrayAccessOnObjectRule/Fixture/ArrayAccessOnNestedObject.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\NoArrayAccessOnObjectRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\NoArrayAccessOnObjectRule\Fixture; -use Symplify\PHPStanRules\Tests\Rules\NoArrayAccessOnObjectRule\Source\ChildOfSomeClassWithArrayAccess; +use Rector\TypePerfect\Tests\Rules\NoArrayAccessOnObjectRule\Source\ChildOfSomeClassWithArrayAccess; final class ArrayAccessOnNestedObject { diff --git a/tests/Rules/NoArrayAccessOnObjectRule/Fixture/ArrayAccessOnObject.php b/tests/Rules/NoArrayAccessOnObjectRule/Fixture/ArrayAccessOnObject.php index 35e692ba..62cf5c58 100644 --- a/tests/Rules/NoArrayAccessOnObjectRule/Fixture/ArrayAccessOnObject.php +++ b/tests/Rules/NoArrayAccessOnObjectRule/Fixture/ArrayAccessOnObject.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\NoArrayAccessOnObjectRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\NoArrayAccessOnObjectRule\Fixture; -use Symplify\PHPStanRules\Tests\Rules\NoArrayAccessOnObjectRule\Source\SomeClassWithArrayAccess; +use Rector\TypePerfect\Tests\Rules\NoArrayAccessOnObjectRule\Source\SomeClassWithArrayAccess; final class ArrayAccessOnObject { diff --git a/tests/Rules/NoArrayAccessOnObjectRule/Fixture/SkipIterator.php b/tests/Rules/NoArrayAccessOnObjectRule/Fixture/SkipIterator.php new file mode 100644 index 00000000..8e349448 --- /dev/null +++ b/tests/Rules/NoArrayAccessOnObjectRule/Fixture/SkipIterator.php @@ -0,0 +1,15 @@ + - */ final class NoArrayAccessOnObjectRuleTest extends RuleTestCase { /** - * @dataProvider provideData() * @param mixed[] $expectedErrorMessagesWithLines */ + #[DataProvider('provideData')] public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void { $this->analyse([$filePath], $expectedErrorMessagesWithLines); } - public function provideData(): Iterator + public static function provideData(): Iterator { yield [__DIR__ . '/Fixture/ArrayAccessOnObject.php', [[NoArrayAccessOnObjectRule::ERROR_MESSAGE, 14]]]; yield [__DIR__ . '/Fixture/ArrayAccessOnNestedObject.php', [[NoArrayAccessOnObjectRule::ERROR_MESSAGE, 14]]]; + yield [__DIR__ . '/Fixture/SkipIterator.php', []]; yield [__DIR__ . '/Fixture/SkipOnArray.php', []]; yield [__DIR__ . '/Fixture/SkipSplFixedArray.php', []]; yield [__DIR__ . '/Fixture/SkipXml.php', []]; diff --git a/tests/Rules/NoArrayAccessOnObjectRule/Source/ChildOfSomeClassWithArrayAccess.php b/tests/Rules/NoArrayAccessOnObjectRule/Source/ChildOfSomeClassWithArrayAccess.php index 4d59b53d..a04d76d4 100644 --- a/tests/Rules/NoArrayAccessOnObjectRule/Source/ChildOfSomeClassWithArrayAccess.php +++ b/tests/Rules/NoArrayAccessOnObjectRule/Source/ChildOfSomeClassWithArrayAccess.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\NoArrayAccessOnObjectRule\Source; +namespace Rector\TypePerfect\Tests\Rules\NoArrayAccessOnObjectRule\Source; class ChildOfSomeClassWithArrayAccess extends SomeClassWithArrayAccess { diff --git a/tests/Rules/NoArrayAccessOnObjectRule/Source/SomeClassWithArrayAccess.php b/tests/Rules/NoArrayAccessOnObjectRule/Source/SomeClassWithArrayAccess.php index eb776a6a..5cfb79b3 100644 --- a/tests/Rules/NoArrayAccessOnObjectRule/Source/SomeClassWithArrayAccess.php +++ b/tests/Rules/NoArrayAccessOnObjectRule/Source/SomeClassWithArrayAccess.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\NoArrayAccessOnObjectRule\Source; +namespace Rector\TypePerfect\Tests\Rules\NoArrayAccessOnObjectRule\Source; use ArrayAccess; diff --git a/tests/Rules/NoArrayAccessOnObjectRule/Source/SomeClassWithSplFixedArray.php b/tests/Rules/NoArrayAccessOnObjectRule/Source/SomeClassWithSplFixedArray.php index cf2bcbe7..d1e7a245 100644 --- a/tests/Rules/NoArrayAccessOnObjectRule/Source/SomeClassWithSplFixedArray.php +++ b/tests/Rules/NoArrayAccessOnObjectRule/Source/SomeClassWithSplFixedArray.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\NoArrayAccessOnObjectRule\Source; +namespace Rector\TypePerfect\Tests\Rules\NoArrayAccessOnObjectRule\Source; use SplFixedArray; diff --git a/tests/Rules/NoArrayAccessOnObjectRule/config/configured_rule.neon b/tests/Rules/NoArrayAccessOnObjectRule/config/configured_rule.neon index ecd30f06..0e1c1ff3 100644 --- a/tests/Rules/NoArrayAccessOnObjectRule/config/configured_rule.neon +++ b/tests/Rules/NoArrayAccessOnObjectRule/config/configured_rule.neon @@ -1,5 +1,5 @@ includes: - - ../../../config/included_services.neon + - ../../../../config/services.neon rules: - - Symplify\PHPStanRules\Rules\NoArrayAccessOnObjectRule + - Rector\TypePerfect\Rules\NoArrayAccessOnObjectRule diff --git a/tests/Rules/NoArrayStringObjectReturnRule/Fixture/ArrayStringObjectReturn.php b/tests/Rules/NoArrayStringObjectReturnRule/Fixture/ArrayStringObjectReturn.php deleted file mode 100644 index d5ba1227..00000000 --- a/tests/Rules/NoArrayStringObjectReturnRule/Fixture/ArrayStringObjectReturn.php +++ /dev/null @@ -1,28 +0,0 @@ - - */ - private $values; - - public function run() - { - return $this->getValues(); - } - - /** - * @return array - */ - private function getValues() - { - return $this->values; - } -} diff --git a/tests/Rules/NoArrayStringObjectReturnRule/Fixture/ParamArrayStringObject.php b/tests/Rules/NoArrayStringObjectReturnRule/Fixture/ParamArrayStringObject.php deleted file mode 100644 index 86a7d1d1..00000000 --- a/tests/Rules/NoArrayStringObjectReturnRule/Fixture/ParamArrayStringObject.php +++ /dev/null @@ -1,18 +0,0 @@ - $values - */ - public function run(array $values) - { - return $values; - } -} diff --git a/tests/Rules/NoArrayStringObjectReturnRule/Fixture/SkipArrayFilter.php b/tests/Rules/NoArrayStringObjectReturnRule/Fixture/SkipArrayFilter.php deleted file mode 100644 index db6263da..00000000 --- a/tests/Rules/NoArrayStringObjectReturnRule/Fixture/SkipArrayFilter.php +++ /dev/null @@ -1,18 +0,0 @@ -getItems(), function (object $entity) { - return $entity instanceof MarkerInterface; - }); - } -} diff --git a/tests/Rules/NoArrayStringObjectReturnRule/Fixture/SkipNonStringKey.php b/tests/Rules/NoArrayStringObjectReturnRule/Fixture/SkipNonStringKey.php deleted file mode 100644 index 590cfb08..00000000 --- a/tests/Rules/NoArrayStringObjectReturnRule/Fixture/SkipNonStringKey.php +++ /dev/null @@ -1,28 +0,0 @@ - - */ - private $values; - - public function run() - { - return $this->getValues(); - } - - /** - * @return array - */ - private function getValues() - { - return $this->values; - } -} diff --git a/tests/Rules/NoArrayStringObjectReturnRule/Fixture/SkipPhpDocTagCompare.php b/tests/Rules/NoArrayStringObjectReturnRule/Fixture/SkipPhpDocTagCompare.php deleted file mode 100644 index f8923d30..00000000 --- a/tests/Rules/NoArrayStringObjectReturnRule/Fixture/SkipPhpDocTagCompare.php +++ /dev/null @@ -1,22 +0,0 @@ -callPrivateMethod($classReflection, 'getResolvedPhpDoc', []); - if (! $resolvedPhpDocBlock instanceof ResolvedPhpDocBlock) { - return false; - } - - return $resolvedPhpDocBlock->getExtendsTags() !== []; - } -} diff --git a/tests/Rules/NoArrayStringObjectReturnRule/Fixture/WithoutPropertyArrayStringObjectReturn.php b/tests/Rules/NoArrayStringObjectReturnRule/Fixture/WithoutPropertyArrayStringObjectReturn.php deleted file mode 100644 index e654c4d8..00000000 --- a/tests/Rules/NoArrayStringObjectReturnRule/Fixture/WithoutPropertyArrayStringObjectReturn.php +++ /dev/null @@ -1,23 +0,0 @@ -getValues(); - } - - /** - * @return array - */ - private function getValues() - { - // ... - } -} diff --git a/tests/Rules/NoArrayStringObjectReturnRule/NoArrayStringObjectReturnRuleTest.php b/tests/Rules/NoArrayStringObjectReturnRule/NoArrayStringObjectReturnRuleTest.php deleted file mode 100644 index b62722d7..00000000 --- a/tests/Rules/NoArrayStringObjectReturnRule/NoArrayStringObjectReturnRuleTest.php +++ /dev/null @@ -1,56 +0,0 @@ - - */ -final class NoArrayStringObjectReturnRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/ArrayStringObjectReturn.php', [ - [NoArrayStringObjectReturnRule::ERROR_MESSAGE, 18], - [NoArrayStringObjectReturnRule::ERROR_MESSAGE, 26], - ]]; - - yield [ - __DIR__ . '/Fixture/WithoutPropertyArrayStringObjectReturn.php', - [[NoArrayStringObjectReturnRule::ERROR_MESSAGE, 13]], - ]; - - yield [__DIR__ . '/Fixture/ParamArrayStringObject.php', [[NoArrayStringObjectReturnRule::ERROR_MESSAGE, 16]]]; - - yield [__DIR__ . '/Fixture/SkipNonStringKey.php', []]; - yield [__DIR__ . '/Fixture/SkipArrayFilter.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoArrayStringObjectReturnRule::class); - } -} diff --git a/tests/Rules/NoArrayStringObjectReturnRule/Source/FakeUnitOfWork.php b/tests/Rules/NoArrayStringObjectReturnRule/Source/FakeUnitOfWork.php deleted file mode 100644 index b91519f5..00000000 --- a/tests/Rules/NoArrayStringObjectReturnRule/Source/FakeUnitOfWork.php +++ /dev/null @@ -1,15 +0,0 @@ - - */ - public function getItems(): array - { - } -} diff --git a/tests/Rules/NoArrayStringObjectReturnRule/Source/MarkerInterface.php b/tests/Rules/NoArrayStringObjectReturnRule/Source/MarkerInterface.php deleted file mode 100644 index 2cc8e210..00000000 --- a/tests/Rules/NoArrayStringObjectReturnRule/Source/MarkerInterface.php +++ /dev/null @@ -1,9 +0,0 @@ -name = $name; - } - - public static function createFromName(string $name) - { - return new self($name); - } - - public function getName(): string - { - return $this->name; - } -} diff --git a/tests/Rules/NoClassWithStaticMethodWithoutStaticNameRule/NoClassWithStaticMethodWithoutStaticNameRuleTest.php b/tests/Rules/NoClassWithStaticMethodWithoutStaticNameRule/NoClassWithStaticMethodWithoutStaticNameRuleTest.php deleted file mode 100644 index b112ff19..00000000 --- a/tests/Rules/NoClassWithStaticMethodWithoutStaticNameRule/NoClassWithStaticMethodWithoutStaticNameRuleTest.php +++ /dev/null @@ -1,48 +0,0 @@ - - */ -final class NoClassWithStaticMethodWithoutStaticNameRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - $errorMessage = NoClassWithStaticMethodWithoutStaticNameRule::ERROR_MESSAGE; - yield [__DIR__ . '/Fixture/ClassWithMethod.php', [[$errorMessage, 7]]]; - - yield [__DIR__ . '/Fixture/SkipEventSubscriber.php', []]; - yield [__DIR__ . '/Fixture/SkipEventSubscriberWithAnotherStaticMethod.php', []]; - yield [__DIR__ . '/Fixture/SkipValueObjectFactory.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoClassWithStaticMethodWithoutStaticNameRule::class); - } -} diff --git a/tests/Rules/NoClassWithStaticMethodWithoutStaticNameRule/config/configured_rule.neon b/tests/Rules/NoClassWithStaticMethodWithoutStaticNameRule/config/configured_rule.neon deleted file mode 100644 index 35ff4814..00000000 --- a/tests/Rules/NoClassWithStaticMethodWithoutStaticNameRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\NoClassWithStaticMethodWithoutStaticNameRule diff --git a/tests/Rules/NoConstructorInTestRule/Fixture/Test1/SkipTestWithoutConstructTest.php b/tests/Rules/NoConstructorInTestRule/Fixture/Test1/SkipTestWithoutConstructTest.php deleted file mode 100644 index 63bd0bae..00000000 --- a/tests/Rules/NoConstructorInTestRule/Fixture/Test1/SkipTestWithoutConstructTest.php +++ /dev/null @@ -1,15 +0,0 @@ -obj = new stdClass; - } -} diff --git a/tests/Rules/NoConstructorInTestRule/Fixture/Test2/SomeTest.php b/tests/Rules/NoConstructorInTestRule/Fixture/Test2/SomeTest.php deleted file mode 100644 index d3048de4..00000000 --- a/tests/Rules/NoConstructorInTestRule/Fixture/Test2/SomeTest.php +++ /dev/null @@ -1,15 +0,0 @@ -obj = new stdClass; - } -} diff --git a/tests/Rules/NoConstructorInTestRule/NoConstructorInTestRuleTest.php b/tests/Rules/NoConstructorInTestRule/NoConstructorInTestRuleTest.php deleted file mode 100644 index 5f7afdf4..00000000 --- a/tests/Rules/NoConstructorInTestRule/NoConstructorInTestRuleTest.php +++ /dev/null @@ -1,44 +0,0 @@ - - */ -final class NoConstructorInTestRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/Test1/SkipTestWithoutConstructTest.php', []]; - yield [__DIR__ . '/Fixture/Test2/SomeTest.php', [[NoConstructorInTestRule::ERROR_MESSAGE, 11]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoConstructorInTestRule::class); - } -} diff --git a/tests/Rules/NoConstructorInTestRule/config/configured_rule.neon b/tests/Rules/NoConstructorInTestRule/config/configured_rule.neon deleted file mode 100644 index 819a0606..00000000 --- a/tests/Rules/NoConstructorInTestRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\NoConstructorInTestRule diff --git a/tests/Rules/NoDefaultExceptionRule/Fixture/ThrowGenericException.php b/tests/Rules/NoDefaultExceptionRule/Fixture/ThrowGenericException.php deleted file mode 100644 index 96ccbb8c..00000000 --- a/tests/Rules/NoDefaultExceptionRule/Fixture/ThrowGenericException.php +++ /dev/null @@ -1,15 +0,0 @@ - - */ -final class NoDefaultExceptionRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - /** - * @return Iterator> - */ - public function provideData(): Iterator - { - $errorMessage = sprintf(NoDefaultExceptionRule::ERROR_MESSAGE, RuntimeException::class); - yield [__DIR__ . '/Fixture/ThrowGenericException.php', [[$errorMessage, 13]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoDefaultExceptionRule::class); - } -} diff --git a/tests/Rules/NoDefaultExceptionRule/config/configured_rule.neon b/tests/Rules/NoDefaultExceptionRule/config/configured_rule.neon deleted file mode 100644 index 03d6e25b..00000000 --- a/tests/Rules/NoDefaultExceptionRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\NoDefaultExceptionRule diff --git a/tests/Rules/NoDuplicatedShortClassNameRule/Fixture/Nested/OneMoreNested/SameShortName.php b/tests/Rules/NoDuplicatedShortClassNameRule/Fixture/Nested/OneMoreNested/SameShortName.php deleted file mode 100644 index 4503cae3..00000000 --- a/tests/Rules/NoDuplicatedShortClassNameRule/Fixture/Nested/OneMoreNested/SameShortName.php +++ /dev/null @@ -1,10 +0,0 @@ - - */ -final class NoDuplicatedShortClassNameRuleTest extends RuleTestCase -{ - /** - * @param string[] $filePaths - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(array $filePaths, array $expectedErrorMessagesWithLines): void - { - $this->analyse($filePaths, $expectedErrorMessagesWithLines); - } - - /** - * @return Iterator - */ - public function provideData(): Iterator - { - // might be same, but skipped for shallow nesting - see config file - yield [ - [ - __DIR__ . '/Fixture/SkipAlreadyExistingShortName.php', - __DIR__ . '/Source/SkipAlreadyExistingShortName.php', - ], - [], - ]; - - $errorMessage = sprintf( - NoDuplicatedShortClassNameRule::ERROR_MESSAGE, - 'SameShortName', - implode( - '", "', - [SameShortName::class, - \Symplify\PHPStanRules\Tests\Rules\NoDuplicatedShortClassNameRule\Fixture\Nested\OneMoreNested\SameShortName::class, - ] - ) - ); - - yield [ - [ - __DIR__ . '/Fixture/Nested/SameShortName.php', - __DIR__ . '/Fixture/Nested/OneMoreNested/SameShortName.php', - ], - [[$errorMessage, 7]], - ]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoDuplicatedShortClassNameRule::class); - } -} diff --git a/tests/Rules/NoDuplicatedShortClassNameRule/Source/SkipAlreadyExistingShortName.php b/tests/Rules/NoDuplicatedShortClassNameRule/Source/SkipAlreadyExistingShortName.php deleted file mode 100644 index c13c8858..00000000 --- a/tests/Rules/NoDuplicatedShortClassNameRule/Source/SkipAlreadyExistingShortName.php +++ /dev/null @@ -1,10 +0,0 @@ -$value(); - } -} diff --git a/tests/Rules/NoDynamicNameRule/Fixture/DynamicPropertyFetch.php b/tests/Rules/NoDynamicNameRule/Fixture/DynamicPropertyFetch.php deleted file mode 100644 index f6ed6c91..00000000 --- a/tests/Rules/NoDynamicNameRule/Fixture/DynamicPropertyFetch.php +++ /dev/null @@ -1,12 +0,0 @@ -$value; - } -} diff --git a/tests/Rules/NoDynamicNameRule/Fixture/DynamicStaticMethodCallName.php b/tests/Rules/NoDynamicNameRule/Fixture/DynamicStaticMethodCallName.php deleted file mode 100644 index 3c137a47..00000000 --- a/tests/Rules/NoDynamicNameRule/Fixture/DynamicStaticMethodCallName.php +++ /dev/null @@ -1,13 +0,0 @@ - - */ -final class NoDynamicNameRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/DynamicConstantName.php', [[NoDynamicNameRule::ERROR_MESSAGE, 10]]]; - yield [__DIR__ . '/Fixture/DynamicMethodCallName.php', [[NoDynamicNameRule::ERROR_MESSAGE, 11]]]; - yield [__DIR__ . '/Fixture/DynamicStaticMethodCallName.php', [[NoDynamicNameRule::ERROR_MESSAGE, 11]]]; - yield [__DIR__ . '/Fixture/DynamicFuncCallName.php', [[NoDynamicNameRule::ERROR_MESSAGE, 11]]]; - - yield [__DIR__ . '/Fixture/DynamicPropertyFetch.php', [[NoDynamicNameRule::ERROR_MESSAGE, 10]]]; - yield [__DIR__ . '/Fixture/DynamicClassOnStaticPropertyFetch.php', [[NoDynamicNameRule::ERROR_MESSAGE, 10]]]; - - yield [__DIR__ . '/Fixture/SkipObjectClassOnPhp8.php', []]; - yield [__DIR__ . '/Fixture/SkipInvokable.php', []]; - yield [__DIR__ . '/Fixture/SkipClosure.php', []]; - yield [__DIR__ . '/Fixture/SkipCallable.php', []]; - yield [__DIR__ . '/Fixture/SkipNullableClosure.php', []]; - yield [__DIR__ . '/Fixture/SkipImmediatelyInvokedFunctionExpression.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoDynamicNameRule::class); - } -} diff --git a/tests/Rules/NoDynamicNameRule/Source/SomeInvokableClass.php b/tests/Rules/NoDynamicNameRule/Source/SomeInvokableClass.php deleted file mode 100644 index 670950b5..00000000 --- a/tests/Rules/NoDynamicNameRule/Source/SomeInvokableClass.php +++ /dev/null @@ -1,13 +0,0 @@ -connection::literal(); - } -} diff --git a/tests/Rules/NoDynamicPropertyOnStaticCallRule/Fixture/DynamicPropertyCall.php b/tests/Rules/NoDynamicPropertyOnStaticCallRule/Fixture/DynamicPropertyCall.php deleted file mode 100644 index 02dc2cda..00000000 --- a/tests/Rules/NoDynamicPropertyOnStaticCallRule/Fixture/DynamicPropertyCall.php +++ /dev/null @@ -1,13 +0,0 @@ -connection::literal; - } -} diff --git a/tests/Rules/NoDynamicPropertyOnStaticCallRule/Fixture/SkipAbstractClassCall.php b/tests/Rules/NoDynamicPropertyOnStaticCallRule/Fixture/SkipAbstractClassCall.php deleted file mode 100644 index 4217659e..00000000 --- a/tests/Rules/NoDynamicPropertyOnStaticCallRule/Fixture/SkipAbstractClassCall.php +++ /dev/null @@ -1,17 +0,0 @@ -foo::class; - } -} diff --git a/tests/Rules/NoDynamicPropertyOnStaticCallRule/NoDynamicPropertyOnStaticCallRulePhp80Test.php b/tests/Rules/NoDynamicPropertyOnStaticCallRule/NoDynamicPropertyOnStaticCallRulePhp80Test.php deleted file mode 100644 index 83451899..00000000 --- a/tests/Rules/NoDynamicPropertyOnStaticCallRule/NoDynamicPropertyOnStaticCallRulePhp80Test.php +++ /dev/null @@ -1,46 +0,0 @@ - - */ -final class NoDynamicPropertyOnStaticCallRulePhp80Test extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - /** - * @return Iterator> - */ - public function provideData(): Iterator - { - yield [__DIR__ . '/FixturePhp8/SkipObjectClass.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoDynamicPropertyOnStaticCallRule::class); - } -} diff --git a/tests/Rules/NoDynamicPropertyOnStaticCallRule/NoDynamicPropertyOnStaticCallRuleTest.php b/tests/Rules/NoDynamicPropertyOnStaticCallRule/NoDynamicPropertyOnStaticCallRuleTest.php deleted file mode 100644 index 07341c24..00000000 --- a/tests/Rules/NoDynamicPropertyOnStaticCallRule/NoDynamicPropertyOnStaticCallRuleTest.php +++ /dev/null @@ -1,49 +0,0 @@ - - */ -final class NoDynamicPropertyOnStaticCallRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/DynamicMethodCall.php', [[NoDynamicPropertyOnStaticCallRule::ERROR_MESSAGE, 11]]]; - yield [__DIR__ . '/Fixture/DynamicPropertyCall.php', [[NoDynamicPropertyOnStaticCallRule::ERROR_MESSAGE, 11]]]; - yield [__DIR__ . '/Fixture/SkipNonDynamicPropertyCall.php', []]; - yield [__DIR__ . '/Fixture/SkipNonDynamicMethodCall.php', []]; - yield [__DIR__ . '/Fixture/SkipSelfStatic.php', []]; - yield [__DIR__ . '/Fixture/SkipAbstractClassCall.php', []]; - yield [__DIR__ . '/Fixture/SkipUnionTypes.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoDynamicPropertyOnStaticCallRule::class); - } -} diff --git a/tests/Rules/NoDynamicPropertyOnStaticCallRule/Source/AbstractSomeClass.php b/tests/Rules/NoDynamicPropertyOnStaticCallRule/Source/AbstractSomeClass.php deleted file mode 100644 index fb102ab6..00000000 --- a/tests/Rules/NoDynamicPropertyOnStaticCallRule/Source/AbstractSomeClass.php +++ /dev/null @@ -1,10 +0,0 @@ - - */ -final class NoEmptyClassRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipAttribute.php', []]; - yield [__DIR__ . '/Fixture/SkipMarkerInterface.php', []]; - yield [__DIR__ . '/Fixture/SkipException.php', []]; - yield [__DIR__ . '/Fixture/SkipWithCommentInterface.php', []]; - yield [__DIR__ . '/Fixture/SkipWithContent.php', []]; - yield [__DIR__ . '/Fixture/SkipWithCommentAbove.php', []]; - yield [__DIR__ . '/Fixture/SkipFinalChildOfAbstract.php', []]; - yield [__DIR__ . '/Fixture/SkipEmptyClassWithImplements.php', []]; - - yield [__DIR__ . '/Fixture/SomeEmptyClass.php', [[NoEmptyClassRule::ERROR_MESSAGE, 7]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoEmptyClassRule::class); - } -} diff --git a/tests/Rules/NoEmptyClassRule/Source/AbstractAnother.php b/tests/Rules/NoEmptyClassRule/Source/AbstractAnother.php deleted file mode 100644 index d0f3aaa1..00000000 --- a/tests/Rules/NoEmptyClassRule/Source/AbstractAnother.php +++ /dev/null @@ -1,10 +0,0 @@ -nothing(strlen('fooo')); - } - - private function nothing($value) - { - return $value; - } -} diff --git a/tests/Rules/NoFuncCallInMethodCallRule/Fixture/SkipGetCwd.php b/tests/Rules/NoFuncCallInMethodCallRule/Fixture/SkipGetCwd.php deleted file mode 100644 index d5a7045e..00000000 --- a/tests/Rules/NoFuncCallInMethodCallRule/Fixture/SkipGetCwd.php +++ /dev/null @@ -1,18 +0,0 @@ -nothing(getcwd()); - } - - private function nothing($value) - { - return $value; - } -} diff --git a/tests/Rules/NoFuncCallInMethodCallRule/Fixture/SkipNamespacedFunction.php b/tests/Rules/NoFuncCallInMethodCallRule/Fixture/SkipNamespacedFunction.php deleted file mode 100644 index c3c9d622..00000000 --- a/tests/Rules/NoFuncCallInMethodCallRule/Fixture/SkipNamespacedFunction.php +++ /dev/null @@ -1,19 +0,0 @@ -process(some_function()); - } - - private function process(string $ref) - { - } -} diff --git a/tests/Rules/NoFuncCallInMethodCallRule/NoFuncCallInMethodCallRuleTest.php b/tests/Rules/NoFuncCallInMethodCallRule/NoFuncCallInMethodCallRuleTest.php deleted file mode 100644 index 316762d2..00000000 --- a/tests/Rules/NoFuncCallInMethodCallRule/NoFuncCallInMethodCallRuleTest.php +++ /dev/null @@ -1,47 +0,0 @@ - - */ -final class NoFuncCallInMethodCallRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - $errorMessage = sprintf(NoFuncCallInMethodCallRule::ERROR_MESSAGE, 'strlen'); - yield [__DIR__ . '/Fixture/FunctionCallNestedToMethodCall.php', [[$errorMessage, 11]]]; - - yield [__DIR__ . '/Fixture/SkipGetCwd.php', []]; - yield [__DIR__ . '/Fixture/SkipNamespacedFunction.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoFuncCallInMethodCallRule::class); - } -} diff --git a/tests/Rules/NoFuncCallInMethodCallRule/Source/Namespaced.php b/tests/Rules/NoFuncCallInMethodCallRule/Source/Namespaced.php deleted file mode 100644 index ff3e94ab..00000000 --- a/tests/Rules/NoFuncCallInMethodCallRule/Source/Namespaced.php +++ /dev/null @@ -1,9 +0,0 @@ - - */ -final class NoInlineStringRegexRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/InlineMatchRegex.php', [[NoInlineStringRegexRule::ERROR_MESSAGE, 11]]]; - yield [ - __DIR__ . '/Fixture/NetteUtilsStringsInlineMatchRegex.php', - [[NoInlineStringRegexRule::ERROR_MESSAGE, 13]], - ]; - - yield [__DIR__ . '/Fixture/SkipVariable.php', []]; - yield [__DIR__ . '/Fixture/SkipSingleLetter.php', []]; - yield [__DIR__ . '/Fixture/SkipConstRegex.php', []]; - yield [__DIR__ . '/Fixture/SkipNetteUtilsStringsConstRegex.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoInlineStringRegexRule::class); - } -} diff --git a/tests/Rules/NoInlineStringRegexRule/config/configured_rule.neon b/tests/Rules/NoInlineStringRegexRule/config/configured_rule.neon deleted file mode 100644 index 06c63f38..00000000 --- a/tests/Rules/NoInlineStringRegexRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\NoInlineStringRegexRule diff --git a/tests/Rules/NoIssetOnObjectRule/Fixture/IssetOnObject.php b/tests/Rules/NoIssetOnObjectRule/Fixture/IssetOnObject.php index 588062ed..7eab7594 100644 --- a/tests/Rules/NoIssetOnObjectRule/Fixture/IssetOnObject.php +++ b/tests/Rules/NoIssetOnObjectRule/Fixture/IssetOnObject.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\NoIssetOnObjectRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\NoIssetOnObjectRule\Fixture; use stdClass; diff --git a/tests/Rules/NoIssetOnObjectRule/Fixture/SkipIssetOnArray.php b/tests/Rules/NoIssetOnObjectRule/Fixture/SkipIssetOnArray.php index 21f45a81..dd5e83ca 100644 --- a/tests/Rules/NoIssetOnObjectRule/Fixture/SkipIssetOnArray.php +++ b/tests/Rules/NoIssetOnObjectRule/Fixture/SkipIssetOnArray.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\NoIssetOnObjectRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\NoIssetOnObjectRule\Fixture; final class SkipIssetOnArray { diff --git a/tests/Rules/NoIssetOnObjectRule/Fixture/SkipIssetOnArrayNestedOnObject.php b/tests/Rules/NoIssetOnObjectRule/Fixture/SkipIssetOnArrayNestedOnObject.php index 68437522..8204a8a0 100644 --- a/tests/Rules/NoIssetOnObjectRule/Fixture/SkipIssetOnArrayNestedOnObject.php +++ b/tests/Rules/NoIssetOnObjectRule/Fixture/SkipIssetOnArrayNestedOnObject.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\NoIssetOnObjectRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\NoIssetOnObjectRule\Fixture; use PhpParser\Node\Expr\MethodCall; diff --git a/tests/Rules/NoIssetOnObjectRule/NoIssetOnObjectRuleTest.php b/tests/Rules/NoIssetOnObjectRule/NoIssetOnObjectRuleTest.php index db2fe251..481158a2 100644 --- a/tests/Rules/NoIssetOnObjectRule/NoIssetOnObjectRuleTest.php +++ b/tests/Rules/NoIssetOnObjectRule/NoIssetOnObjectRuleTest.php @@ -2,28 +2,26 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\NoIssetOnObjectRule; +namespace Rector\TypePerfect\Tests\Rules\NoIssetOnObjectRule; use Iterator; use PHPStan\Rules\Rule; use PHPStan\Testing\RuleTestCase; -use Symplify\PHPStanRules\Rules\NoIssetOnObjectRule; +use PHPUnit\Framework\Attributes\DataProvider; +use Rector\TypePerfect\Rules\NoIssetOnObjectRule; -/** - * @extends RuleTestCase - */ final class NoIssetOnObjectRuleTest extends RuleTestCase { /** - * @dataProvider provideData() * @param mixed[] $expectedErrorMessagesWithLines */ + #[DataProvider('provideData')] public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void { $this->analyse([$filePath], $expectedErrorMessagesWithLines); } - public function provideData(): Iterator + public static function provideData(): Iterator { yield [__DIR__ . '/Fixture/IssetOnObject.php', [[NoIssetOnObjectRule::ERROR_MESSAGE, 17]]]; diff --git a/tests/Rules/NoIssetOnObjectRule/config/configured_rule.neon b/tests/Rules/NoIssetOnObjectRule/config/configured_rule.neon index 753ee29d..92b3382d 100644 --- a/tests/Rules/NoIssetOnObjectRule/config/configured_rule.neon +++ b/tests/Rules/NoIssetOnObjectRule/config/configured_rule.neon @@ -1,5 +1,5 @@ includes: - - ../../../config/included_services.neon + - ../../../../config/services.neon rules: - - Symplify\PHPStanRules\Rules\NoIssetOnObjectRule + - Rector\TypePerfect\Rules\NoIssetOnObjectRule diff --git a/tests/Rules/NoMethodTagInClassDocblockRule/Fixture/ClassWithMethodTag.php b/tests/Rules/NoMethodTagInClassDocblockRule/Fixture/ClassWithMethodTag.php deleted file mode 100644 index 949d78f9..00000000 --- a/tests/Rules/NoMethodTagInClassDocblockRule/Fixture/ClassWithMethodTag.php +++ /dev/null @@ -1,12 +0,0 @@ - - */ -final class NoMethodTagInClassDocblockRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipClassWithNoMethodTag.php', []]; - yield [__DIR__ . '/Fixture/SkipEnum.php', []]; - - yield [__DIR__ . '/Fixture/ClassWithMethodTag.php', [[NoMethodTagInClassDocblockRule::ERROR_MESSAGE, 10]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoMethodTagInClassDocblockRule::class); - } -} diff --git a/tests/Rules/NoMethodTagInClassDocblockRule/config/configured_rule.neon b/tests/Rules/NoMethodTagInClassDocblockRule/config/configured_rule.neon deleted file mode 100644 index 8716b704..00000000 --- a/tests/Rules/NoMethodTagInClassDocblockRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\NoMethodTagInClassDocblockRule diff --git a/tests/Rules/NoMissingDirPathRule/Fixture/FileMissing.php b/tests/Rules/NoMissingDirPathRule/Fixture/FileMissing.php deleted file mode 100644 index 6910d282..00000000 --- a/tests/Rules/NoMissingDirPathRule/Fixture/FileMissing.php +++ /dev/null @@ -1,13 +0,0 @@ -assertFileExists(__DIR__ . '/../PotentialFile.php'); - $this->assertFileNotExists(__DIR__ . '/../../PotentialFile.php'); - - if (method_exists($this, 'assertFileDoesNotExist')) { - $this->assertFileDoesNotExist(__DIR__ . '/temp/file.php'); - } else { - $this->assertFileNotExists(__DIR__ . '/temp/file.php'); - } - - $possibleFile = __DIR__ . '/Whatever'; - } -} diff --git a/tests/Rules/NoMissingDirPathRule/Fixture/SkipBracketPathFromSymfonyConfigImport.php b/tests/Rules/NoMissingDirPathRule/Fixture/SkipBracketPathFromSymfonyConfigImport.php deleted file mode 100644 index f3bede11..00000000 --- a/tests/Rules/NoMissingDirPathRule/Fixture/SkipBracketPathFromSymfonyConfigImport.php +++ /dev/null @@ -1,13 +0,0 @@ - - */ -final class NoMissingDirPathRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - $message = sprintf(NoMissingDirPathRule::ERROR_MESSAGE, '/not_here.php'); - yield [__DIR__ . '/Fixture/FileMissing.php', [[$message, 11]]]; - - yield [__DIR__ . '/Fixture/SkipBracketPathFromSymfonyConfigImport.php', []]; - yield [__DIR__ . '/Fixture/SkipConcat.php', []]; - yield [__DIR__ . '/Fixture/SkipVendorAutoload.php', []]; - yield [__DIR__ . '/Fixture/SkipVendorAutoload.php', []]; - yield [__DIR__ . '/Fixture/SkipAssertMethod.php', []]; - yield [__DIR__ . '/Fixture/SkipFnMatch.php', []]; - yield [__DIR__ . '/Fixture/SkipFileExistsFuncCall.php', []]; - yield [__DIR__ . '/Fixture/SkipFileExistsFuncCallOneLayerAbove.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoMissingDirPathRule::class); - } -} diff --git a/tests/Rules/NoMissingDirPathRule/config/configured_rule.neon b/tests/Rules/NoMissingDirPathRule/config/configured_rule.neon deleted file mode 100644 index fa682f0c..00000000 --- a/tests/Rules/NoMissingDirPathRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\NoMissingDirPathRule diff --git a/tests/Rules/Explicit/NoMixedMethodCallerRule/Fixture/MagicMethodName.php b/tests/Rules/NoMixedMethodCallerRule/Fixture/MagicMethodName.php similarity index 63% rename from tests/Rules/Explicit/NoMixedMethodCallerRule/Fixture/MagicMethodName.php rename to tests/Rules/NoMixedMethodCallerRule/Fixture/MagicMethodName.php index b57f9062..24634dca 100644 --- a/tests/Rules/Explicit/NoMixedMethodCallerRule/Fixture/MagicMethodName.php +++ b/tests/Rules/NoMixedMethodCallerRule/Fixture/MagicMethodName.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\Explicit\NoMixedMethodCallerRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\NoMixedMethodCallerRule\Fixture; final class MagicMethodName { diff --git a/tests/Rules/NoMixedMethodCallerRule/Fixture/SkipKnownCallerType.php b/tests/Rules/NoMixedMethodCallerRule/Fixture/SkipKnownCallerType.php new file mode 100644 index 00000000..297d2526 --- /dev/null +++ b/tests/Rules/NoMixedMethodCallerRule/Fixture/SkipKnownCallerType.php @@ -0,0 +1,15 @@ +call(); + } +} diff --git a/tests/Rules/NoMixedMethodCallerRule/Fixture/SkipMockObject.php b/tests/Rules/NoMixedMethodCallerRule/Fixture/SkipMockObject.php new file mode 100644 index 00000000..58168a73 --- /dev/null +++ b/tests/Rules/NoMixedMethodCallerRule/Fixture/SkipMockObject.php @@ -0,0 +1,19 @@ +createMock(MagicMethodName::class); + + $mock + ->method('run') + ->willReturn(true); + } +} diff --git a/tests/Rules/Explicit/NoMixedMethodCallerRule/Fixture/UnknownCallerType.php b/tests/Rules/NoMixedMethodCallerRule/Fixture/UnknownCallerType.php similarity index 62% rename from tests/Rules/Explicit/NoMixedMethodCallerRule/Fixture/UnknownCallerType.php rename to tests/Rules/NoMixedMethodCallerRule/Fixture/UnknownCallerType.php index adbf92c7..5a01e193 100644 --- a/tests/Rules/Explicit/NoMixedMethodCallerRule/Fixture/UnknownCallerType.php +++ b/tests/Rules/NoMixedMethodCallerRule/Fixture/UnknownCallerType.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\Explicit\NoMixedMethodCallerRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\NoMixedMethodCallerRule\Fixture; final class UnknownCallerType { diff --git a/tests/Rules/Explicit/NoMixedMethodCallerRule/NoMixedMethodCallerRuleTest.php b/tests/Rules/NoMixedMethodCallerRule/NoMixedMethodCallerRuleTest.php similarity index 78% rename from tests/Rules/Explicit/NoMixedMethodCallerRule/NoMixedMethodCallerRuleTest.php rename to tests/Rules/NoMixedMethodCallerRule/NoMixedMethodCallerRuleTest.php index 76b1a815..a6e64ebf 100644 --- a/tests/Rules/Explicit/NoMixedMethodCallerRule/NoMixedMethodCallerRuleTest.php +++ b/tests/Rules/NoMixedMethodCallerRule/NoMixedMethodCallerRuleTest.php @@ -2,30 +2,29 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\Explicit\NoMixedMethodCallerRule; +namespace Rector\TypePerfect\Tests\Rules\NoMixedMethodCallerRule; use Iterator; use PHPStan\Rules\Rule; use PHPStan\Testing\RuleTestCase; -use Symplify\PHPStanRules\Rules\Explicit\NoMixedMethodCallerRule; +use PHPUnit\Framework\Attributes\DataProvider; +use Rector\TypePerfect\Rules\NoMixedMethodCallerRule; -/** - * @extends RuleTestCase - */ final class NoMixedMethodCallerRuleTest extends RuleTestCase { /** - * @dataProvider provideData() * @param mixed[]|array> $expectedErrorsWithLines */ + #[DataProvider('provideData')] public function testRule(string $filePath, array $expectedErrorsWithLines): void { $this->analyse([$filePath], $expectedErrorsWithLines); } - public function provideData(): Iterator + public static function provideData(): Iterator { yield [__DIR__ . '/Fixture/SkipKnownCallerType.php', []]; + yield [__DIR__ . '/Fixture/SkipMockObject.php', []]; $errorMessage = sprintf(NoMixedMethodCallerRule::ERROR_MESSAGE, '$someType'); yield [__DIR__ . '/Fixture/MagicMethodName.php', [[$errorMessage, 11]]]; diff --git a/tests/Rules/Explicit/NoMixedMethodCallerRule/Source/KnownType.php b/tests/Rules/NoMixedMethodCallerRule/Source/KnownType.php similarity index 53% rename from tests/Rules/Explicit/NoMixedMethodCallerRule/Source/KnownType.php rename to tests/Rules/NoMixedMethodCallerRule/Source/KnownType.php index 0a8907b4..75536c75 100644 --- a/tests/Rules/Explicit/NoMixedMethodCallerRule/Source/KnownType.php +++ b/tests/Rules/NoMixedMethodCallerRule/Source/KnownType.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\Explicit\NoMixedMethodCallerRule\Source; +namespace Rector\TypePerfect\Tests\Rules\NoMixedMethodCallerRule\Source; final class KnownType { diff --git a/tests/Rules/NoMixedMethodCallerRule/config/configured_rule.neon b/tests/Rules/NoMixedMethodCallerRule/config/configured_rule.neon new file mode 100644 index 00000000..b42e7224 --- /dev/null +++ b/tests/Rules/NoMixedMethodCallerRule/config/configured_rule.neon @@ -0,0 +1,5 @@ +includes: + - ../../../../config/services.neon + +rules: + - Rector\TypePerfect\Rules\NoMixedMethodCallerRule diff --git a/tests/Rules/NoMixedPropertyFetcherRule/Fixture/DynamicName.php b/tests/Rules/NoMixedPropertyFetcherRule/Fixture/DynamicName.php new file mode 100644 index 00000000..2e460975 --- /dev/null +++ b/tests/Rules/NoMixedPropertyFetcherRule/Fixture/DynamicName.php @@ -0,0 +1,13 @@ +{$name}; + } +} diff --git a/tests/Rules/NoMixedPropertyFetcherRule/Fixture/SkipDynamicNameWithKnownType.php b/tests/Rules/NoMixedPropertyFetcherRule/Fixture/SkipDynamicNameWithKnownType.php new file mode 100644 index 00000000..c3812a18 --- /dev/null +++ b/tests/Rules/NoMixedPropertyFetcherRule/Fixture/SkipDynamicNameWithKnownType.php @@ -0,0 +1,15 @@ +{$name}; + } +} diff --git a/tests/Rules/NoMixedPropertyFetcherRule/Fixture/SkipKnownFetcherType.php b/tests/Rules/NoMixedPropertyFetcherRule/Fixture/SkipKnownFetcherType.php new file mode 100644 index 00000000..48ec8acc --- /dev/null +++ b/tests/Rules/NoMixedPropertyFetcherRule/Fixture/SkipKnownFetcherType.php @@ -0,0 +1,15 @@ +name; + } +} diff --git a/tests/Rules/Explicit/NoMixedPropertyFetcherRule/Fixture/UnknownPropertyFetcher.php b/tests/Rules/NoMixedPropertyFetcherRule/Fixture/UnknownPropertyFetcher.php similarity index 62% rename from tests/Rules/Explicit/NoMixedPropertyFetcherRule/Fixture/UnknownPropertyFetcher.php rename to tests/Rules/NoMixedPropertyFetcherRule/Fixture/UnknownPropertyFetcher.php index 7e40c237..ef906f07 100644 --- a/tests/Rules/Explicit/NoMixedPropertyFetcherRule/Fixture/UnknownPropertyFetcher.php +++ b/tests/Rules/NoMixedPropertyFetcherRule/Fixture/UnknownPropertyFetcher.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\Explicit\NoMixedPropertyFetcherRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\NoMixedPropertyFetcherRule\Fixture; final class UnknownPropertyFetcher { diff --git a/tests/Rules/Explicit/NoMixedPropertyFetcherRule/NoMixedPropertyFetcherRuleTest.php b/tests/Rules/NoMixedPropertyFetcherRule/NoMixedPropertyFetcherRuleTest.php similarity index 80% rename from tests/Rules/Explicit/NoMixedPropertyFetcherRule/NoMixedPropertyFetcherRuleTest.php rename to tests/Rules/NoMixedPropertyFetcherRule/NoMixedPropertyFetcherRuleTest.php index ad18b940..33f29bc2 100644 --- a/tests/Rules/Explicit/NoMixedPropertyFetcherRule/NoMixedPropertyFetcherRuleTest.php +++ b/tests/Rules/NoMixedPropertyFetcherRule/NoMixedPropertyFetcherRuleTest.php @@ -2,34 +2,32 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\Explicit\NoMixedPropertyFetcherRule; +namespace Rector\TypePerfect\Tests\Rules\NoMixedPropertyFetcherRule; use Iterator; use PHPStan\Rules\Rule; use PHPStan\Testing\RuleTestCase; -use Symplify\PHPStanRules\Rules\Explicit\NoMixedPropertyFetcherRule; +use PHPUnit\Framework\Attributes\DataProvider; +use Rector\TypePerfect\Rules\NoMixedPropertyFetcherRule; -/** - * @extends RuleTestCase - */ final class NoMixedPropertyFetcherRuleTest extends RuleTestCase { /** - * @dataProvider provideData() * @param mixed[]|array> $expectedErrorsWithLines */ + #[DataProvider('provideData')] public function testRule(string $filePath, array $expectedErrorsWithLines): void { $this->analyse([$filePath], $expectedErrorsWithLines); } - public function provideData(): Iterator + public static function provideData(): Iterator { yield [__DIR__ . '/Fixture/SkipDynamicNameWithKnownType.php', []]; yield [__DIR__ . '/Fixture/SkipKnownFetcherType.php', []]; $message = sprintf(NoMixedPropertyFetcherRule::ERROR_MESSAGE, '$unknownType'); - yield [__DIR__ . '/Fixture/DynamicName.php', [[$message, 13]]]; + yield [__DIR__ . '/Fixture/DynamicName.php', [[$message, 11]]]; $message = sprintf(NoMixedPropertyFetcherRule::ERROR_MESSAGE, '$unknownType'); yield [__DIR__ . '/Fixture/UnknownPropertyFetcher.php', [[$message, 11]]]; diff --git a/tests/Rules/NoMixedPropertyFetcherRule/Source/KnownType.php b/tests/Rules/NoMixedPropertyFetcherRule/Source/KnownType.php new file mode 100644 index 00000000..2655c864 --- /dev/null +++ b/tests/Rules/NoMixedPropertyFetcherRule/Source/KnownType.php @@ -0,0 +1,10 @@ + - */ -final class NoMultiArrayAssignRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/MultiArrayAssign.php', [[NoMultiArrayAssignRule::ERROR_MESSAGE, 13]]]; - yield [__DIR__ . '/Fixture/MultiSingleNestedArrayAssign.php', [[NoMultiArrayAssignRule::ERROR_MESSAGE, 13]]]; - yield [__DIR__ . '/Fixture/MultiArrayAssignWithVariableDim.php', [[NoMultiArrayAssignRule::ERROR_MESSAGE, 13]]]; - - yield [__DIR__ . '/Fixture/SkipDifferntArrayAssign.php', []]; - yield [__DIR__ . '/Fixture/SkipEmptyDimAssign.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoMultiArrayAssignRule::class); - } -} diff --git a/tests/Rules/NoMultiArrayAssignRule/config/configured_rule.neon b/tests/Rules/NoMultiArrayAssignRule/config/configured_rule.neon deleted file mode 100644 index 9b66cbc2..00000000 --- a/tests/Rules/NoMultiArrayAssignRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\NoMultiArrayAssignRule diff --git a/tests/Rules/NoNestedFuncCallRule/Fixture/NestedFuncCall.php b/tests/Rules/NoNestedFuncCallRule/Fixture/NestedFuncCall.php deleted file mode 100644 index e6e6b3d4..00000000 --- a/tests/Rules/NoNestedFuncCallRule/Fixture/NestedFuncCall.php +++ /dev/null @@ -1,13 +0,0 @@ - - */ -final class NoNestedFuncCallRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/NestedYourself.php', [[NoNestedFuncCallRule::ERROR_MESSAGE, 11]]]; - yield [__DIR__ . '/Fixture/NestedFuncCall.php', [[NoNestedFuncCallRule::ERROR_MESSAGE, 11]]]; - - yield [__DIR__ . '/Fixture/SkipNonNested.php', []]; - yield [__DIR__ . '/Fixture/SkipCount.php', []]; - yield [__DIR__ . '/Fixture/SkipAssert.php', []]; - yield [__DIR__ . '/Fixture/SkipUsort.php', []]; - yield [__DIR__ . '/Fixture/SkipNestedArrayFilter.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoNestedFuncCallRule::class); - } -} diff --git a/tests/Rules/NoNestedFuncCallRule/config/configured_rule.neon b/tests/Rules/NoNestedFuncCallRule/config/configured_rule.neon deleted file mode 100644 index 809f72fb..00000000 --- a/tests/Rules/NoNestedFuncCallRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\NoNestedFuncCallRule diff --git a/tests/Rules/NoNullableArrayPropertyRule/Fixture/NullableArrayProperty.php b/tests/Rules/NoNullableArrayPropertyRule/Fixture/NullableArrayProperty.php deleted file mode 100644 index ccc484fc..00000000 --- a/tests/Rules/NoNullableArrayPropertyRule/Fixture/NullableArrayProperty.php +++ /dev/null @@ -1,11 +0,0 @@ - - */ -final class NoNullableArrayPropertyRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipNoType.php', []]; - yield [__DIR__ . '/Fixture/SkipNotNullable.php', []]; - yield [__DIR__ . '/Fixture/SkipNotArray.php', []]; - yield [__DIR__ . '/Fixture/SkipClassNameProperty.php', []]; - yield [__DIR__ . '/Fixture/NullableArrayProperty.php', [[NoNullableArrayPropertyRule::ERROR_MESSAGE, 9]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoNullableArrayPropertyRule::class); - } -} diff --git a/tests/Rules/NoNullableArrayPropertyRule/config/configured_rule.neon b/tests/Rules/NoNullableArrayPropertyRule/config/configured_rule.neon deleted file mode 100644 index f982c7bc..00000000 --- a/tests/Rules/NoNullableArrayPropertyRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\NoNullableArrayPropertyRule diff --git a/tests/Rules/NoParentMethodCallOnNoOverrideProcessRule/Fixture/OverrideWithSameParamsAndArgs.php b/tests/Rules/NoParentMethodCallOnNoOverrideProcessRule/Fixture/OverrideWithSameParamsAndArgs.php deleted file mode 100644 index b008afe6..00000000 --- a/tests/Rules/NoParentMethodCallOnNoOverrideProcessRule/Fixture/OverrideWithSameParamsAndArgs.php +++ /dev/null @@ -1,15 +0,0 @@ - - */ -final class NoParentMethodCallOnNoOverrideProcessRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipParentWithArgs.php', []]; - yield [__DIR__ . '/Fixture/SkipNotCallParentMethod.php', []]; - yield [__DIR__ . '/Fixture/SkipParentMethodCallOverride.php', []]; - yield [__DIR__ . '/Fixture/SkipParentMethodCallInsideExpression.php', []]; - yield [__DIR__ . '/Fixture/SkipParentMethodCallFromDifferentMethodName.php', []]; - - yield [ - __DIR__ . '/Fixture/ParentMethodCallNoOverride.php', - [[NoParentMethodCallOnNoOverrideProcessRule::ERROR_MESSAGE, 11]], - ]; - - yield [ - __DIR__ . '/Fixture/OverrideWithSameParamsAndArgs.php', - [[NoParentMethodCallOnNoOverrideProcessRule::ERROR_MESSAGE, 11]], - ]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoParentMethodCallOnNoOverrideProcessRule::class); - } -} diff --git a/tests/Rules/NoParentMethodCallOnNoOverrideProcessRule/Source/AnotherParentClassWithParams.php b/tests/Rules/NoParentMethodCallOnNoOverrideProcessRule/Source/AnotherParentClassWithParams.php deleted file mode 100644 index 4962444c..00000000 --- a/tests/Rules/NoParentMethodCallOnNoOverrideProcessRule/Source/AnotherParentClassWithParams.php +++ /dev/null @@ -1,12 +0,0 @@ -run('.php'); - } -} diff --git a/tests/Rules/NoProtectedElementInFinalClassRule/Fixture/SkipInterface.php b/tests/Rules/NoProtectedElementInFinalClassRule/Fixture/SkipInterface.php deleted file mode 100644 index be910c6c..00000000 --- a/tests/Rules/NoProtectedElementInFinalClassRule/Fixture/SkipInterface.php +++ /dev/null @@ -1,10 +0,0 @@ - - */ -final class NoProtectedElementInFinalClassRuleTest extends RuleTestCase -{ - /** - * @param string[] $filePaths - * @param mixed[] $expectedErrorMessagesWithLines - * @dataProvider provideData() - */ - public function testRule(array $filePaths, array $expectedErrorMessagesWithLines): void - { - $this->analyse($filePaths, $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [[__DIR__ . '/Fixture/SkipInterface.php'], []]; - yield [[__DIR__ . '/Fixture/SkipTrait.php'], []]; - yield [[__DIR__ . '/Fixture/SkipNotFinalClass.php'], []]; - - yield [[__DIR__ . '/Fixture/SkipMicroKernelProtectedMethod.php'], []]; - yield [[__DIR__ . '/Fixture/SkipKernelProtectedMethod.php'], []]; - - yield [ - [__DIR__ . '/Fixture/SomeFinalClassWithProtectedProperty.php'], - [[NoProtectedElementInFinalClassRule::ERROR_MESSAGE, 9]], - ]; - - yield [ - [__DIR__ . '/Fixture/SomeFinalClassWithProtectedMethod.php'], - [[NoProtectedElementInFinalClassRule::ERROR_MESSAGE, 9]], - ]; - - yield [ - [__DIR__ . '/Fixture/SomeFinalClassWithProtectedPropertyAndProtectedMethod.php'], - [ - [NoProtectedElementInFinalClassRule::ERROR_MESSAGE, 9], - [NoProtectedElementInFinalClassRule::ERROR_MESSAGE, 11], - ], - ]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoProtectedElementInFinalClassRule::class); - } -} diff --git a/tests/Rules/NoProtectedElementInFinalClassRule/Source/ClassUsingTraitWithProtectedAbstractMethod.php b/tests/Rules/NoProtectedElementInFinalClassRule/Source/ClassUsingTraitWithProtectedAbstractMethod.php deleted file mode 100644 index 820ac176..00000000 --- a/tests/Rules/NoProtectedElementInFinalClassRule/Source/ClassUsingTraitWithProtectedAbstractMethod.php +++ /dev/null @@ -1,10 +0,0 @@ -args[1]; - $some = &$arg->value; - } -} diff --git a/tests/Rules/NoReferenceRule/Fixture/FunctionWithReference.php b/tests/Rules/NoReferenceRule/Fixture/FunctionWithReference.php deleted file mode 100644 index cdd88fec..00000000 --- a/tests/Rules/NoReferenceRule/Fixture/FunctionWithReference.php +++ /dev/null @@ -1,9 +0,0 @@ -run([&$argument]); - } - - private function run(array $array) - { - } -} diff --git a/tests/Rules/NoReferenceRule/Fixture/SkipParentMethodWithReference.php b/tests/Rules/NoReferenceRule/Fixture/SkipParentMethodWithReference.php deleted file mode 100644 index 597703d2..00000000 --- a/tests/Rules/NoReferenceRule/Fixture/SkipParentMethodWithReference.php +++ /dev/null @@ -1,14 +0,0 @@ - - */ -final class NoReferenceRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/MethodWithReference.php', [[NoReferenceRule::ERROR_MESSAGE, 9]]]; - yield [__DIR__ . '/Fixture/FunctionWithReference.php', [[NoReferenceRule::ERROR_MESSAGE, 7]]]; - yield [__DIR__ . '/Fixture/VariableReference.php', [[NoReferenceRule::ERROR_MESSAGE, 11]]]; - yield [__DIR__ . '/Fixture/ReferenceArgument.php', [[NoReferenceRule::ERROR_MESSAGE, 11]]]; - yield [__DIR__ . '/Fixture/AssignReference.php', [[NoReferenceRule::ERROR_MESSAGE, 14]]]; - - yield [__DIR__ . '/Fixture/SkipUseInReference.php', []]; - yield [__DIR__ . '/Fixture/SkipParentMethodWithReference.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoReferenceRule::class); - } -} diff --git a/tests/Rules/NoReferenceRule/Source/AbstractSomeParentClassWithReference.php b/tests/Rules/NoReferenceRule/Source/AbstractSomeParentClassWithReference.php deleted file mode 100644 index 35001a16..00000000 --- a/tests/Rules/NoReferenceRule/Source/AbstractSomeParentClassWithReference.php +++ /dev/null @@ -1,12 +0,0 @@ - 'Yes', - self::NO => 'No', - ]; - } -} diff --git a/tests/Rules/NoReturnArrayVariableListRule/Fixture/ReturnVariables.php b/tests/Rules/NoReturnArrayVariableListRule/Fixture/ReturnVariables.php deleted file mode 100644 index a0267e1f..00000000 --- a/tests/Rules/NoReturnArrayVariableListRule/Fixture/ReturnVariables.php +++ /dev/null @@ -1,14 +0,0 @@ - - */ -final class NoReturnArrayVariableListRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/ReturnVariables.php', [[NoReturnArrayVariableListRule::ERROR_MESSAGE, 11]]]; - - yield [__DIR__ . '/Fixture/Enum/SkipEnum.php', []]; - yield [__DIR__ . '/Fixture/SkipReturnOne.php', []]; - yield [__DIR__ . '/Fixture/SkipNews.php', []]; - yield [__DIR__ . '/Fixture/ValueObject/SkipValueObject.php', []]; - yield [__DIR__ . '/Fixture/SkipParentMethod.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoReturnArrayVariableListRule::class); - } -} diff --git a/tests/Rules/NoReturnArrayVariableListRule/config/configured_rule.neon b/tests/Rules/NoReturnArrayVariableListRule/config/configured_rule.neon deleted file mode 100644 index 176c5712..00000000 --- a/tests/Rules/NoReturnArrayVariableListRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\NoReturnArrayVariableListRule diff --git a/tests/Rules/NoReturnFalseInNonBoolClassMethodRule/Fixture/ReturnFalseOnly.php b/tests/Rules/NoReturnFalseInNonBoolClassMethodRule/Fixture/ReturnFalseOnly.php new file mode 100644 index 00000000..734de54a --- /dev/null +++ b/tests/Rules/NoReturnFalseInNonBoolClassMethodRule/Fixture/ReturnFalseOnly.php @@ -0,0 +1,17 @@ +analyse([$filePath], $expectedErrorMessagesWithLines); + } + + public static function provideData(): Iterator + { + yield [ + __DIR__ . '/Fixture/ReturnFalseOnly.php', + [[NoReturnFalseInNonBoolClassMethodRule::ERROR_MESSAGE, 9]], + ]; + + yield [__DIR__ . '/Fixture/SkipReturnBool.php', []]; + } + + /** + * @return string[] + */ + public static function getAdditionalConfigFiles(): array + { + return [ + __DIR__ . '/config/configured_rule.neon', + ]; + } + + protected function getRule(): Rule + { + return self::getContainer()->getByType(NoReturnFalseInNonBoolClassMethodRule::class); + } +} diff --git a/tests/Rules/NoReturnFalseInNonBoolClassMethodRule/config/configured_rule.neon b/tests/Rules/NoReturnFalseInNonBoolClassMethodRule/config/configured_rule.neon new file mode 100644 index 00000000..a5b478e4 --- /dev/null +++ b/tests/Rules/NoReturnFalseInNonBoolClassMethodRule/config/configured_rule.neon @@ -0,0 +1,2 @@ +rules: + - Rector\TypePerfect\Rules\NoReturnFalseInNonBoolClassMethodRule diff --git a/tests/Rules/NoReturnSetterMethodRule/Fixture/SkipEmptyReturn.php b/tests/Rules/NoReturnSetterMethodRule/Fixture/SkipEmptyReturn.php deleted file mode 100644 index 921e3f2d..00000000 --- a/tests/Rules/NoReturnSetterMethodRule/Fixture/SkipEmptyReturn.php +++ /dev/null @@ -1,19 +0,0 @@ -name === 'hey') { - return; - } - - $this->name = $name; - } -} diff --git a/tests/Rules/NoReturnSetterMethodRule/Fixture/SkipSetUp.php b/tests/Rules/NoReturnSetterMethodRule/Fixture/SkipSetUp.php deleted file mode 100644 index c1c27201..00000000 --- a/tests/Rules/NoReturnSetterMethodRule/Fixture/SkipSetUp.php +++ /dev/null @@ -1,13 +0,0 @@ -name = $name; - } -} diff --git a/tests/Rules/NoReturnSetterMethodRule/Fixture/SomeSetterClass.php b/tests/Rules/NoReturnSetterMethodRule/Fixture/SomeSetterClass.php deleted file mode 100644 index 1f3c43ff..00000000 --- a/tests/Rules/NoReturnSetterMethodRule/Fixture/SomeSetterClass.php +++ /dev/null @@ -1,13 +0,0 @@ - - */ -final class NoReturnSetterMethodRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorsWithLines - */ - public function testRule(string $filePath, array $expectedErrorsWithLines): void - { - $this->analyse([$filePath], $expectedErrorsWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SomeSetterClass.php', [[NoReturnSetterMethodRule::ERROR_MESSAGE, 9]]]; - - yield [__DIR__ . '/Fixture/SkipEmptyReturn.php', []]; - yield [__DIR__ . '/Fixture/SkipVoidSetter.php', []]; - yield [__DIR__ . '/Fixture/SkipSetUp.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoReturnSetterMethodRule::class); - } -} diff --git a/tests/Rules/NoReturnSetterMethodRule/config/configured_rule.neon b/tests/Rules/NoReturnSetterMethodRule/config/configured_rule.neon deleted file mode 100644 index 21f69cee..00000000 --- a/tests/Rules/NoReturnSetterMethodRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\NoReturnSetterMethodRule diff --git a/tests/Rules/NoStaticPropertyRule/Fixture/SkipContainerArrayCache.php b/tests/Rules/NoStaticPropertyRule/Fixture/SkipContainerArrayCache.php deleted file mode 100644 index 49ab7fd4..00000000 --- a/tests/Rules/NoStaticPropertyRule/Fixture/SkipContainerArrayCache.php +++ /dev/null @@ -1,31 +0,0 @@ - - */ - public static $arrayContainers = []; - - public function getContainers(): array - { - return self::$containers; - } - - public function getArrayContainers(): array - { - return self::$arrayContainers; - } -} diff --git a/tests/Rules/NoStaticPropertyRule/Fixture/SkipContainerCache.php b/tests/Rules/NoStaticPropertyRule/Fixture/SkipContainerCache.php deleted file mode 100644 index 1a004d12..00000000 --- a/tests/Rules/NoStaticPropertyRule/Fixture/SkipContainerCache.php +++ /dev/null @@ -1,21 +0,0 @@ -customFileNames; - } -} diff --git a/tests/Rules/NoStaticPropertyRule/Fixture/SkipNullableContainerCache.php b/tests/Rules/NoStaticPropertyRule/Fixture/SkipNullableContainerCache.php deleted file mode 100644 index 525dace9..00000000 --- a/tests/Rules/NoStaticPropertyRule/Fixture/SkipNullableContainerCache.php +++ /dev/null @@ -1,21 +0,0 @@ - - */ - public static $containers = []; - - public function getContainers(): array - { - return self::$containers; - } -} diff --git a/tests/Rules/NoStaticPropertyRule/Fixture/SkipStaticContainerPHPStan.php b/tests/Rules/NoStaticPropertyRule/Fixture/SkipStaticContainerPHPStan.php deleted file mode 100644 index c66c66d4..00000000 --- a/tests/Rules/NoStaticPropertyRule/Fixture/SkipStaticContainerPHPStan.php +++ /dev/null @@ -1,20 +0,0 @@ - - */ - private static $containersByConfig = []; - - private function getServiceContainer(string $config): Container - { - if (isset(self::$containersByConfig[$config])) { - return self::$containersByConfig[$config]; - } - - self::$containersByConfig[$config] = $container; - } -} diff --git a/tests/Rules/NoStaticPropertyRule/Fixture/SkipStaticKernel.php b/tests/Rules/NoStaticPropertyRule/Fixture/SkipStaticKernel.php deleted file mode 100644 index 84efc4f5..00000000 --- a/tests/Rules/NoStaticPropertyRule/Fixture/SkipStaticKernel.php +++ /dev/null @@ -1,20 +0,0 @@ -nonStaticFileNames; - } - - public static function getCustomFileNames(): array - { - return self::$customFileNames; - } -} diff --git a/tests/Rules/NoStaticPropertyRule/NoStaticPropertyRuleTest.php b/tests/Rules/NoStaticPropertyRule/NoStaticPropertyRuleTest.php deleted file mode 100644 index 8eab443b..00000000 --- a/tests/Rules/NoStaticPropertyRule/NoStaticPropertyRuleTest.php +++ /dev/null @@ -1,59 +0,0 @@ - - */ -final class NoStaticPropertyRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipStaticPropertyInAbstractTestCase.php', []]; - yield [__DIR__ . '/Fixture/SkipStaticIntersectionOffsetContainer.php', []]; - yield [__DIR__ . '/Fixture/SkipStaticKernel.php', []]; - yield [__DIR__ . '/Fixture/SkipStaticContainerPHPStan.php', []]; - yield [__DIR__ . '/Fixture/SkipStaticContainerArrayPHPStan.php', []]; - - yield [__DIR__ . '/Fixture/SkipNonStaticProperty.php', []]; - yield [__DIR__ . '/Fixture/SkipContainerArrayCache.php', []]; - yield [__DIR__ . '/Fixture/SkipContainerCache.php', []]; - yield [__DIR__ . '/Fixture/SkipNullableContainerCache.php', []]; - yield [__DIR__ . '/Fixture/SkipContainerArrayCache.php', []]; - - yield [ - __DIR__ . '/Fixture/SomeStaticProperty.php', - [[NoStaticPropertyRule::ERROR_MESSAGE, 14], [NoStaticPropertyRule::ERROR_MESSAGE, 19]], - ]; - yield [__DIR__ . '/Fixture/SomeStaticPropertyWithoutModifier.php', [[NoStaticPropertyRule::ERROR_MESSAGE, 19]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoStaticPropertyRule::class); - } -} diff --git a/tests/Rules/NoStaticPropertyRule/config/configured_rule.neon b/tests/Rules/NoStaticPropertyRule/config/configured_rule.neon deleted file mode 100644 index 50781fcc..00000000 --- a/tests/Rules/NoStaticPropertyRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\NoStaticPropertyRule diff --git a/tests/Rules/NoVoidGetterMethodRule/Fixture/SkipAbstractGetter.php b/tests/Rules/NoVoidGetterMethodRule/Fixture/SkipAbstractGetter.php deleted file mode 100644 index de011697..00000000 --- a/tests/Rules/NoVoidGetterMethodRule/Fixture/SkipAbstractGetter.php +++ /dev/null @@ -1,10 +0,0 @@ - - */ -final class NoVoidGetterMethodRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorsWithLines - */ - public function testRule(string $filePath, array $expectedErrorsWithLines): void - { - $this->analyse([$filePath], $expectedErrorsWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SomeGetterVoid.php', [[NoVoidGetterMethodRule::ERROR_MESSAGE, 9]]]; - yield [__DIR__ . '/Fixture/SomeGetterWithNoReturn.php', [[NoVoidGetterMethodRule::ERROR_MESSAGE, 9]]]; - - yield [__DIR__ . '/Fixture/SkipAbstractGetter.php', []]; - yield [__DIR__ . '/Fixture/SkipIfElseReturn.php', []]; - yield [__DIR__ . '/Fixture/SkipGetterWithReturn.php', []]; - yield [__DIR__ . '/Fixture/SkipSetter.php', []]; - yield [__DIR__ . '/Fixture/SkipYielder.php', []]; - yield [__DIR__ . '/Fixture/SkipInterfaceContractGetter.php', []]; - yield [__DIR__ . '/Fixture/SkipNoThrows.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoVoidGetterMethodRule::class); - } -} diff --git a/tests/Rules/NoVoidGetterMethodRule/config/configured_rule.neon b/tests/Rules/NoVoidGetterMethodRule/config/configured_rule.neon deleted file mode 100644 index 2d48f314..00000000 --- a/tests/Rules/NoVoidGetterMethodRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\NoVoidGetterMethodRule diff --git a/tests/Rules/PHPUnit/NoRightPHPUnitAssertScalarRule/Fixture/FlippedAssertWithConstFetch.php b/tests/Rules/PHPUnit/NoRightPHPUnitAssertScalarRule/Fixture/FlippedAssertWithConstFetch.php deleted file mode 100644 index 8391711c..00000000 --- a/tests/Rules/PHPUnit/NoRightPHPUnitAssertScalarRule/Fixture/FlippedAssertWithConstFetch.php +++ /dev/null @@ -1,19 +0,0 @@ -assertSame($value, self::SOME_VALUE); - } -} diff --git a/tests/Rules/PHPUnit/NoRightPHPUnitAssertScalarRule/Fixture/SkipCorrectAssert.php b/tests/Rules/PHPUnit/NoRightPHPUnitAssertScalarRule/Fixture/SkipCorrectAssert.php deleted file mode 100644 index 256821d3..00000000 --- a/tests/Rules/PHPUnit/NoRightPHPUnitAssertScalarRule/Fixture/SkipCorrectAssert.php +++ /dev/null @@ -1,16 +0,0 @@ -assertSame(10, $value); - } -} diff --git a/tests/Rules/PHPUnit/NoRightPHPUnitAssertScalarRule/Fixture/SomeBoolAssert.php b/tests/Rules/PHPUnit/NoRightPHPUnitAssertScalarRule/Fixture/SomeBoolAssert.php deleted file mode 100644 index 5171eabf..00000000 --- a/tests/Rules/PHPUnit/NoRightPHPUnitAssertScalarRule/Fixture/SomeBoolAssert.php +++ /dev/null @@ -1,16 +0,0 @@ -assertSame($value, false); - } -} diff --git a/tests/Rules/PHPUnit/NoRightPHPUnitAssertScalarRule/Fixture/SomeFlippedAssert.php b/tests/Rules/PHPUnit/NoRightPHPUnitAssertScalarRule/Fixture/SomeFlippedAssert.php deleted file mode 100644 index 2ce4b53c..00000000 --- a/tests/Rules/PHPUnit/NoRightPHPUnitAssertScalarRule/Fixture/SomeFlippedAssert.php +++ /dev/null @@ -1,16 +0,0 @@ -assertSame($value, 10); - } -} diff --git a/tests/Rules/PHPUnit/NoRightPHPUnitAssertScalarRule/NoRightPHPUnitAssertScalarRuleTest.php b/tests/Rules/PHPUnit/NoRightPHPUnitAssertScalarRule/NoRightPHPUnitAssertScalarRuleTest.php deleted file mode 100644 index 03be2bd7..00000000 --- a/tests/Rules/PHPUnit/NoRightPHPUnitAssertScalarRule/NoRightPHPUnitAssertScalarRuleTest.php +++ /dev/null @@ -1,41 +0,0 @@ - - */ -final class NoRightPHPUnitAssertScalarRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipCorrectAssert.php', []]; - - yield [__DIR__ . '/Fixture/SomeFlippedAssert.php', [[NoRightPHPUnitAssertScalarRule::ERROR_MESSAGE, 14]]]; - yield [ - __DIR__ . '/Fixture/FlippedAssertWithConstFetch.php', - [[NoRightPHPUnitAssertScalarRule::ERROR_MESSAGE, 17]], ]; - yield [__DIR__ . '/Fixture/SomeBoolAssert.php', [[NoRightPHPUnitAssertScalarRule::ERROR_MESSAGE, 14]]]; - } - - protected function getRule(): Rule - { - return new NoRightPHPUnitAssertScalarRule(); - } -} diff --git a/tests/Rules/PreferredAttributeOverAnnotationRule/Fixture/SkipAttributeRoute.php b/tests/Rules/PreferredAttributeOverAnnotationRule/Fixture/SkipAttributeRoute.php deleted file mode 100644 index 3825db20..00000000 --- a/tests/Rules/PreferredAttributeOverAnnotationRule/Fixture/SkipAttributeRoute.php +++ /dev/null @@ -1,13 +0,0 @@ - - */ -final class PreferredAttributeOverAnnotationRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipAttributeRoute.php', []]; - - $errorMessage = sprintf(PreferredAttributeOverAnnotationRule::ERROR_MESSAGE, Route::class); - - yield [__DIR__ . '/Fixture/SomeAnnotatedController.php', [[$errorMessage, 14]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(PreferredAttributeOverAnnotationRule::class); - } -} diff --git a/tests/Rules/PreferredAttributeOverAnnotationRule/config/configured_rule.neon b/tests/Rules/PreferredAttributeOverAnnotationRule/config/configured_rule.neon deleted file mode 100644 index 3e9915e4..00000000 --- a/tests/Rules/PreferredAttributeOverAnnotationRule/config/configured_rule.neon +++ /dev/null @@ -1,10 +0,0 @@ -includes: - - ../../../config/included_services.neon - -services: - - - class: Symplify\PHPStanRules\Rules\PreferredAttributeOverAnnotationRule - tags: [phpstan.rules.rule] - arguments: - annotations: - - Symfony\Component\Routing\Annotation\Route diff --git a/tests/Rules/PreferredClassRule/Fixture/ClassExtendingOld.php b/tests/Rules/PreferredClassRule/Fixture/ClassExtendingOld.php deleted file mode 100644 index a3cf9d82..00000000 --- a/tests/Rules/PreferredClassRule/Fixture/ClassExtendingOld.php +++ /dev/null @@ -1,11 +0,0 @@ - - */ -final class PreferredClassRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - $errorMessage = sprintf(PreferredClassRule::ERROR_MESSAGE, NativeDateTime::class, DateTime::class); - yield [__DIR__ . '/Fixture/ClassUsingOld.php', [[$errorMessage, 13]]]; - yield [__DIR__ . '/Fixture/ClassExtendingOld.php', [[$errorMessage, 9]]]; - yield [__DIR__ . '/Fixture/ClassMethodParameterUsingOld.php', [[$errorMessage, 11]]]; - yield [__DIR__ . '/Fixture/SomeStaticCall.php', [[$errorMessage, 13]]]; - - $errorMessage = sprintf( - PreferredClassRule::ERROR_MESSAGE, - AbstractNotWhatYouWant::class, - SkipPreferredExtendingTheOldOne::class - ); - yield [__DIR__ . '/Fixture/InstanceOfName.php', [[$errorMessage, 13]]]; - - yield [__DIR__ . '/Fixture/SkipPreferredExtendingTheOldOne.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(PreferredClassRule::class); - } -} diff --git a/tests/Rules/PreferredClassRule/Source/AbstractNotWhatYouWant.php b/tests/Rules/PreferredClassRule/Source/AbstractNotWhatYouWant.php deleted file mode 100644 index e0bfb566..00000000 --- a/tests/Rules/PreferredClassRule/Source/AbstractNotWhatYouWant.php +++ /dev/null @@ -1,10 +0,0 @@ -obj = new stdClass; - } - - public function testFoo() - { - $this->obj->x = true; - $this->assertTrue($this->obj->x); - } -} diff --git a/tests/Rules/PreferredRawDataInTestDataProviderRule/Fixture/SkipUseRawDataForTestDataProviderTest.php.inc b/tests/Rules/PreferredRawDataInTestDataProviderRule/Fixture/SkipUseRawDataForTestDataProviderTest.php.inc deleted file mode 100644 index a972a49f..00000000 --- a/tests/Rules/PreferredRawDataInTestDataProviderRule/Fixture/SkipUseRawDataForTestDataProviderTest.php.inc +++ /dev/null @@ -1,34 +0,0 @@ -obj = new stdClass; - } - - public function provideFoo() - { - return [ - [[true]] - ]; - } - - /** - * @dataProvider provideFoo - */ - public function testFoo($value) - { - $this->obj->x = $value; - $this->assertTrue($this->obj->x); - } -} diff --git a/tests/Rules/PreferredRawDataInTestDataProviderRule/Fixture/UseDataFromSetupInTestDataProviderTest.php.inc b/tests/Rules/PreferredRawDataInTestDataProviderRule/Fixture/UseDataFromSetupInTestDataProviderTest.php.inc deleted file mode 100644 index 7f647978..00000000 --- a/tests/Rules/PreferredRawDataInTestDataProviderRule/Fixture/UseDataFromSetupInTestDataProviderTest.php.inc +++ /dev/null @@ -1,30 +0,0 @@ -data = true; - } - - public function provideFoo() - { - yield [$this->data]; - } - - /** - * @dataProvider provideFoo - */ - public function testFoo($value) - { - $this->assertTrue($value); - } -} diff --git a/tests/Rules/PreferredRawDataInTestDataProviderRule/PreferredRawDataInTestDataProviderRuleTest.php b/tests/Rules/PreferredRawDataInTestDataProviderRule/PreferredRawDataInTestDataProviderRuleTest.php deleted file mode 100644 index f2e13f58..00000000 --- a/tests/Rules/PreferredRawDataInTestDataProviderRule/PreferredRawDataInTestDataProviderRuleTest.php +++ /dev/null @@ -1,49 +0,0 @@ - - */ -final class PreferredRawDataInTestDataProviderRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipNoDataProviderTest.php', []]; - yield [__DIR__ . '/Fixture/SkipUseRawDataForTestDataProviderTest.php.inc', []]; - - yield [ - __DIR__ . '/Fixture/UseDataFromSetupInTestDataProviderTest.php.inc', - [[PreferredRawDataInTestDataProviderRule::ERROR_MESSAGE, 18]], - ]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(PreferredRawDataInTestDataProviderRule::class); - } -} diff --git a/tests/Rules/PreferredRawDataInTestDataProviderRule/config/configured_rule.neon b/tests/Rules/PreferredRawDataInTestDataProviderRule/config/configured_rule.neon deleted file mode 100644 index 7417a25b..00000000 --- a/tests/Rules/PreferredRawDataInTestDataProviderRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\PreferredRawDataInTestDataProviderRule diff --git a/tests/Rules/PrefixAbstractClassRule/Fixture/AbstractSomeAbstractClass.php b/tests/Rules/PrefixAbstractClassRule/Fixture/AbstractSomeAbstractClass.php deleted file mode 100644 index 094febaa..00000000 --- a/tests/Rules/PrefixAbstractClassRule/Fixture/AbstractSomeAbstractClass.php +++ /dev/null @@ -1,9 +0,0 @@ - - */ -final class PrefixAbstractClassRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipAnonymousClass.php', []]; - yield [__DIR__ . '/Fixture/SkipInterface.php', []]; - yield [__DIR__ . '/Fixture/AbstractSomeAbstractClass.php', []]; - - $errorMessage = sprintf(PrefixAbstractClassRule::ERROR_MESSAGE, 'SomeAbstractClass'); - yield [__DIR__ . '/Fixture/SomeAbstractClass.php', [[$errorMessage, 7]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(PrefixAbstractClassRule::class); - } -} diff --git a/tests/Rules/PrefixAbstractClassRule/config/configured_rule.neon b/tests/Rules/PrefixAbstractClassRule/config/configured_rule.neon deleted file mode 100644 index 18f6bc07..00000000 --- a/tests/Rules/PrefixAbstractClassRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\PrefixAbstractClassRule diff --git a/tests/Rules/PreventDuplicateClassMethodRule/Fixture/DifferentMethodName1.php b/tests/Rules/PreventDuplicateClassMethodRule/Fixture/DifferentMethodName1.php deleted file mode 100644 index c587f4ce..00000000 --- a/tests/Rules/PreventDuplicateClassMethodRule/Fixture/DifferentMethodName1.php +++ /dev/null @@ -1,16 +0,0 @@ -x = $x; - } -} diff --git a/tests/Rules/PreventDuplicateClassMethodRule/Fixture/Entity/SkipCar.php b/tests/Rules/PreventDuplicateClassMethodRule/Fixture/Entity/SkipCar.php deleted file mode 100644 index 88d7bff9..00000000 --- a/tests/Rules/PreventDuplicateClassMethodRule/Fixture/Entity/SkipCar.php +++ /dev/null @@ -1,18 +0,0 @@ -x = $x; - } -} diff --git a/tests/Rules/PreventDuplicateClassMethodRule/Fixture/SkipAnotherConstruct.php b/tests/Rules/PreventDuplicateClassMethodRule/Fixture/SkipAnotherConstruct.php deleted file mode 100644 index 1d5970a9..00000000 --- a/tests/Rules/PreventDuplicateClassMethodRule/Fixture/SkipAnotherConstruct.php +++ /dev/null @@ -1,13 +0,0 @@ -anotherMethod(); - } -} diff --git a/tests/Rules/PreventDuplicateClassMethodRule/Fixture/SkipConstruct.php b/tests/Rules/PreventDuplicateClassMethodRule/Fixture/SkipConstruct.php deleted file mode 100644 index b91d263a..00000000 --- a/tests/Rules/PreventDuplicateClassMethodRule/Fixture/SkipConstruct.php +++ /dev/null @@ -1,13 +0,0 @@ - - */ -final class PreventDuplicateClassMethodRuleTest extends RuleTestCase -{ - /** - * @param string[] $filePaths - * @param mixed[] $expectedErrorMessagesWithLines - * @dataProvider provideData() - */ - public function testRule(array $filePaths, array $expectedErrorMessagesWithLines): void - { - $this->analyse($filePaths, $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [[__DIR__ . '/Fixture/ValueObject/SkipChair.php', __DIR__ . '/Fixture/ValueObject/SkipTable.php'], []]; - yield [[__DIR__ . '/Fixture/Entity/SkipApple.php', __DIR__ . '/Fixture/Entity/SkipCar.php'], []]; - - yield [[__DIR__ . '/Fixture/SkipInterface.php'], []]; - yield [[__DIR__ . '/Fixture/SkipConstruct.php', __DIR__ . '/Fixture/SkipAnotherConstruct.php'], []]; - yield [[__DIR__ . '/Fixture/SkipTest.php', __DIR__ . '/Fixture/SkipAnotherTest.php'], []]; - - yield [[__DIR__ . '/Fixture/SkipNodeType.php'], []]; - yield [[__DIR__ . '/Fixture/SkipDoubleStmt.php'], []]; - - yield [[ - __DIR__ . '/Fixture/SkipClassWithTrait.php', - __DIR__ . '/Fixture/SkipTraitUsingTrait.php', - __DIR__ . '/Fixture/SkipSomeTrait.php', - ], []]; - - yield [[ - __DIR__ . '/Fixture/SkipSomeTrait.php', - __DIR__ . '/Fixture/SkipClassUseTrait1.php', - __DIR__ . '/Fixture/SkipClassUseTrait2.php', - ], []]; - - $errorMessage = sprintf( - PreventDuplicateClassMethodRule::ERROR_MESSAGE, - 'sleep', - 'go', - DifferentMethodName1::class - ); - - yield [[ - __DIR__ . '/Fixture/DifferentMethodName1.php', - __DIR__ . '/Fixture/DifferentMethodName2.php', - ], [[$errorMessage, 9]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(PreventDuplicateClassMethodRule::class); - } -} diff --git a/tests/Rules/PreventDuplicateClassMethodRule/config/configured_rule.neon b/tests/Rules/PreventDuplicateClassMethodRule/config/configured_rule.neon deleted file mode 100644 index 16c38249..00000000 --- a/tests/Rules/PreventDuplicateClassMethodRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\PreventDuplicateClassMethodRule diff --git a/tests/Rules/PreventParentMethodVisibilityOverrideRule/Fixture/ClassWithOverridingVisibility.php b/tests/Rules/PreventParentMethodVisibilityOverrideRule/Fixture/ClassWithOverridingVisibility.php deleted file mode 100644 index cc9e78ec..00000000 --- a/tests/Rules/PreventParentMethodVisibilityOverrideRule/Fixture/ClassWithOverridingVisibility.php +++ /dev/null @@ -1,12 +0,0 @@ - - */ -final class PreventParentMethodVisibilityOverrideRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - /** - * @return Iterator> - */ - public function provideData(): Iterator - { - $errorMessage = sprintf(PreventParentMethodVisibilityOverrideRule::ERROR_MESSAGE, 'run', 'protected'); - yield [__DIR__ . '/Fixture/ClassWithOverridingVisibility.php', [[$errorMessage, 9]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(PreventParentMethodVisibilityOverrideRule::class); - } -} diff --git a/tests/Rules/PreventParentMethodVisibilityOverrideRule/config/configured_rule.neon b/tests/Rules/PreventParentMethodVisibilityOverrideRule/config/configured_rule.neon deleted file mode 100644 index a8f51950..00000000 --- a/tests/Rules/PreventParentMethodVisibilityOverrideRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\PreventParentMethodVisibilityOverrideRule diff --git a/tests/Rules/Privatization/NoPublicPropertyByTypeRule/Fixture/SkipNoPublicProperties.php b/tests/Rules/Privatization/NoPublicPropertyByTypeRule/Fixture/SkipNoPublicProperties.php deleted file mode 100644 index 06b85d6e..00000000 --- a/tests/Rules/Privatization/NoPublicPropertyByTypeRule/Fixture/SkipNoPublicProperties.php +++ /dev/null @@ -1,11 +0,0 @@ - - */ -final class NoPublicPropertyByTypeRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - /** - * @return Iterator> - */ - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipNoPublicProperties.php', []]; - yield [__DIR__ . '/Fixture/SkipNoTypeMatch.php', []]; - yield [__DIR__ . '/Fixture/SomePublicProperties.php', [[NoPublicPropertyByTypeRule::ERROR_MESSAGE, 8]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(NoPublicPropertyByTypeRule::class); - } -} diff --git a/tests/Rules/Privatization/NoPublicPropertyByTypeRule/Source/NoPublicPropertiesInterface.php b/tests/Rules/Privatization/NoPublicPropertyByTypeRule/Source/NoPublicPropertiesInterface.php deleted file mode 100644 index 511c148b..00000000 --- a/tests/Rules/Privatization/NoPublicPropertyByTypeRule/Source/NoPublicPropertiesInterface.php +++ /dev/null @@ -1,9 +0,0 @@ - - */ -final class RegexSuffixInRegexConstantRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - /** - * @return Iterator> - */ - public function provideData(): Iterator - { - $errorMessage = sprintf(RegexSuffixInRegexConstantRule::ERROR_MESSAGE, 'SOME_NAME'); - - yield [__DIR__ . '/Fixture/DifferentSuffix.php', [[$errorMessage, 15]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(RegexSuffixInRegexConstantRule::class); - } -} diff --git a/tests/Rules/RegexSuffixInRegexConstantRule/config/configured_rule.neon b/tests/Rules/RegexSuffixInRegexConstantRule/config/configured_rule.neon deleted file mode 100644 index 472dba51..00000000 --- a/tests/Rules/RegexSuffixInRegexConstantRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\RegexSuffixInRegexConstantRule diff --git a/tests/Rules/RequireAttributeNameRule/Fixture/MissingName.php b/tests/Rules/RequireAttributeNameRule/Fixture/MissingName.php deleted file mode 100644 index c0f10f7e..00000000 --- a/tests/Rules/RequireAttributeNameRule/Fixture/MissingName.php +++ /dev/null @@ -1,15 +0,0 @@ - - */ -final class RequireAttributeNameRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorsWithLines - */ - public function testRule(string $filePath, array $expectedErrorsWithLines): void - { - $this->analyse([$filePath], $expectedErrorsWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/MissingName.php', [[RequireAttributeNameRule::ERROR_MESSAGE, 11]]]; - yield [__DIR__ . '/Fixture/SkipCorrectName.php', []]; - yield [__DIR__ . '/Fixture/SkipDefaultName.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(RequireAttributeNameRule::class); - } -} diff --git a/tests/Rules/RequireAttributeNameRule/config/configured_rule.neon b/tests/Rules/RequireAttributeNameRule/config/configured_rule.neon deleted file mode 100644 index 5d8751d9..00000000 --- a/tests/Rules/RequireAttributeNameRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\RequireAttributeNameRule diff --git a/tests/Rules/Explicit/RequireSpecificReturnTypeOverAbstractRule/Fixture/SkipSomeContract.php b/tests/Rules/RequireSpecificReturnTypeOverAbstractRule/Fixture/SkipSomeContract.php similarity index 51% rename from tests/Rules/Explicit/RequireSpecificReturnTypeOverAbstractRule/Fixture/SkipSomeContract.php rename to tests/Rules/RequireSpecificReturnTypeOverAbstractRule/Fixture/SkipSomeContract.php index 3d234be9..46263b23 100644 --- a/tests/Rules/Explicit/RequireSpecificReturnTypeOverAbstractRule/Fixture/SkipSomeContract.php +++ b/tests/Rules/RequireSpecificReturnTypeOverAbstractRule/Fixture/SkipSomeContract.php @@ -2,11 +2,11 @@ declare(strict_types=1); -namespace Symplify\PHPStanRules\Tests\Rules\Explicit\RequireSpecificReturnTypeOverAbstractRule\Fixture; +namespace Rector\TypePerfect\Tests\Rules\RequireSpecificReturnTypeOverAbstractRule\Fixture; use PHPStan\Rules\Cast\EchoRule; use PHPStan\Rules\Rule; -use Symplify\PHPStanRules\Tests\Rules\Explicit\RequireSpecificReturnTypeOverAbstractRule\Source\SomeContract; +use Rector\TypePerfect\Tests\Rules\RequireSpecificReturnTypeOverAbstractRule\Source\SomeContract; final class SkipSomeContract implements SomeContract { diff --git a/tests/Rules/RequireSpecificReturnTypeOverAbstractRule/Fixture/SkipSpecificReturnType.php b/tests/Rules/RequireSpecificReturnTypeOverAbstractRule/Fixture/SkipSpecificReturnType.php new file mode 100644 index 00000000..80be9c9d --- /dev/null +++ b/tests/Rules/RequireSpecificReturnTypeOverAbstractRule/Fixture/SkipSpecificReturnType.php @@ -0,0 +1,15 @@ + @@ -16,15 +17,15 @@ final class RequireSpecificReturnTypeOverAbstractRuleTest extends RuleTestCase { /** - * @dataProvider provideData() * @param mixed[] $expectedErrorMessagesWithLines */ + #[DataProvider('provideData')] public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void { $this->analyse([$filePath], $expectedErrorMessagesWithLines); } - public function provideData(): Iterator + public static function provideData(): Iterator { yield [__DIR__ . '/Fixture/SkipSpecificReturnType.php', []]; yield [__DIR__ . '/Fixture/SkipSomeContract.php', []]; diff --git a/tests/Rules/RequireSpecificReturnTypeOverAbstractRule/Source/AbstractControl.php b/tests/Rules/RequireSpecificReturnTypeOverAbstractRule/Source/AbstractControl.php new file mode 100644 index 00000000..1187d92d --- /dev/null +++ b/tests/Rules/RequireSpecificReturnTypeOverAbstractRule/Source/AbstractControl.php @@ -0,0 +1,9 @@ +a content)#'; - - public function run() - { - $matches = Strings::match('a content', self::REGEX); - if ($matches) { - echo 'a statement before'; - echo $matches['c']; - } - } -} diff --git a/tests/Rules/RequireStringRegexMatchKeyRule/RequireStringRegexMatchKeyRuleTest.php b/tests/Rules/RequireStringRegexMatchKeyRule/RequireStringRegexMatchKeyRuleTest.php deleted file mode 100644 index 3f5a9b44..00000000 --- a/tests/Rules/RequireStringRegexMatchKeyRule/RequireStringRegexMatchKeyRuleTest.php +++ /dev/null @@ -1,51 +0,0 @@ - - */ -final class RequireStringRegexMatchKeyRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipNotUsed.php', []]; - yield [__DIR__ . '/Fixture/SkipStringDim.php', []]; - - yield [__DIR__ . '/Fixture/NumericDim.php', [[RequireStringRegexMatchKeyRule::ERROR_MESSAGE, 15]]]; - yield [__DIR__ . '/Fixture/NumericDimDirectNext.php', [[RequireStringRegexMatchKeyRule::ERROR_MESSAGE, 15]]]; - yield [__DIR__ . '/Fixture/NumericDimInsideIfCond.php', [[RequireStringRegexMatchKeyRule::ERROR_MESSAGE, 15]]]; - yield [ - __DIR__ . '/Fixture/NumericDimOtherNameMultipleValues.php', - [[RequireStringRegexMatchKeyRule::ERROR_MESSAGE, 15]], ]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(RequireStringRegexMatchKeyRule::class); - } -} diff --git a/tests/Rules/RequireStringRegexMatchKeyRule/config/configured_rule.neon b/tests/Rules/RequireStringRegexMatchKeyRule/config/configured_rule.neon deleted file mode 100644 index 087ba221..00000000 --- a/tests/Rules/RequireStringRegexMatchKeyRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\RequireStringRegexMatchKeyRule diff --git a/tests/Rules/RequireThisCallOnLocalMethodRule/Fixture/CallLocalMethod.php b/tests/Rules/RequireThisCallOnLocalMethodRule/Fixture/CallLocalMethod.php deleted file mode 100644 index b9d31d2a..00000000 --- a/tests/Rules/RequireThisCallOnLocalMethodRule/Fixture/CallLocalMethod.php +++ /dev/null @@ -1,17 +0,0 @@ - - */ -final class RequireThisCallOnLocalMethodRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipCallParentMethodStatically.php', []]; - yield [__DIR__ . '/Fixture/SkipCallLocalStaticMethod.php', []]; - yield [__DIR__ . '/Fixture/CallLocalMethod.php', [[RequireThisCallOnLocalMethodRule::ERROR_MESSAGE, 11]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(RequireThisCallOnLocalMethodRule::class); - } -} diff --git a/tests/Rules/RequireThisCallOnLocalMethodRule/config/configured_rule.neon b/tests/Rules/RequireThisCallOnLocalMethodRule/config/configured_rule.neon deleted file mode 100644 index 1ca55fc7..00000000 --- a/tests/Rules/RequireThisCallOnLocalMethodRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\RequireThisCallOnLocalMethodRule diff --git a/tests/Rules/RequireThisOnParentMethodCallRule/Fixture/CallParentMethodStatically.php b/tests/Rules/RequireThisOnParentMethodCallRule/Fixture/CallParentMethodStatically.php deleted file mode 100644 index bbaded95..00000000 --- a/tests/Rules/RequireThisOnParentMethodCallRule/Fixture/CallParentMethodStatically.php +++ /dev/null @@ -1,14 +0,0 @@ - - */ -final class RequireThisOnParentMethodCallRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipCallParentMethodStaticallySameMethod.php', []]; - yield [__DIR__ . '/Fixture/SkipCallParentMethodStaticallyWhenMethodOverriden.php', []]; - - yield [ - __DIR__ . '/Fixture/CallParentMethodStatically.php', - [[RequireThisOnParentMethodCallRule::ERROR_MESSAGE, 11], [ - RequireThisOnParentMethodCallRule::ERROR_MESSAGE, - 12, - ]], - ]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(RequireThisOnParentMethodCallRule::class); - } -} diff --git a/tests/Rules/RequireThisOnParentMethodCallRule/config/configured_rule.neon b/tests/Rules/RequireThisOnParentMethodCallRule/config/configured_rule.neon deleted file mode 100644 index 8081362c..00000000 --- a/tests/Rules/RequireThisOnParentMethodCallRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\RequireThisOnParentMethodCallRule diff --git a/tests/Rules/RequiredAbstractClassKeywordRule/Fixture/AbstractClass.php b/tests/Rules/RequiredAbstractClassKeywordRule/Fixture/AbstractClass.php deleted file mode 100644 index 84ca2b68..00000000 --- a/tests/Rules/RequiredAbstractClassKeywordRule/Fixture/AbstractClass.php +++ /dev/null @@ -1,9 +0,0 @@ - - */ -final class RequiredAbstractClassKeywordRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/AbstractClass.php', []]; - yield [__DIR__ . '/Fixture/SkipSomeClass.php', []]; - - yield [ - __DIR__ . '/Fixture/AbstractPrefixOnNonAbstractClass.php', - [[RequiredAbstractClassKeywordRule::ERROR_MESSAGE, 7]], - ]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(RequiredAbstractClassKeywordRule::class); - } -} diff --git a/tests/Rules/RequiredAbstractClassKeywordRule/config/configured_rule.neon b/tests/Rules/RequiredAbstractClassKeywordRule/config/configured_rule.neon deleted file mode 100644 index 02aa1f1b..00000000 --- a/tests/Rules/RequiredAbstractClassKeywordRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\RequiredAbstractClassKeywordRule diff --git a/tests/Rules/SeeAnnotationToTestRule/Fixture/RuleWithSee.php b/tests/Rules/SeeAnnotationToTestRule/Fixture/RuleWithSee.php deleted file mode 100644 index 6d7ce2b6..00000000 --- a/tests/Rules/SeeAnnotationToTestRule/Fixture/RuleWithSee.php +++ /dev/null @@ -1,24 +0,0 @@ - - */ -final class SeeAnnotationToTestRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - $errorMessage = sprintf(SeeAnnotationToTestRule::ERROR_MESSAGE, RuleWithoutSee::class); - yield [__DIR__ . '/Fixture/RuleWithoutSee.php', [[$errorMessage, 12]]]; - - $errorMessage = sprintf(SeeAnnotationToTestRule::ERROR_MESSAGE, RuleWithSeeRandom::class); - yield [__DIR__ . '/Fixture/RuleWithSeeRandom.php', [[$errorMessage, 15]]]; - - yield [__DIR__ . '/Fixture/SkipDeprecatedRuleWithoutSee.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(SeeAnnotationToTestRule::class); - } -} diff --git a/tests/Rules/SeeAnnotationToTestRule/config/configured_rule.neon b/tests/Rules/SeeAnnotationToTestRule/config/configured_rule.neon deleted file mode 100644 index 6de88d79..00000000 --- a/tests/Rules/SeeAnnotationToTestRule/config/configured_rule.neon +++ /dev/null @@ -1,10 +0,0 @@ -includes: - - ../../../config/included_services.neon - -services: - - - class: Symplify\PHPStanRules\Rules\SeeAnnotationToTestRule - tags: [phpstan.rules.rule] - arguments: - requiredSeeTypes: - - PHPStan\Rules\Rule diff --git a/tests/Rules/Spotter/IfElseToMatchSpotterRule/Fixture/EmptyArrayAssign.php b/tests/Rules/Spotter/IfElseToMatchSpotterRule/Fixture/EmptyArrayAssign.php deleted file mode 100644 index c3e95fe2..00000000 --- a/tests/Rules/Spotter/IfElseToMatchSpotterRule/Fixture/EmptyArrayAssign.php +++ /dev/null @@ -1,23 +0,0 @@ -user * 5 === 250) { - $defaults[$alert] = 2; - } else { - $defaults[$alert] = 0; - } - - return $defaults; - } -} diff --git a/tests/Rules/Spotter/IfElseToMatchSpotterRule/Fixture/SkipMultiStmts.php b/tests/Rules/Spotter/IfElseToMatchSpotterRule/Fixture/SkipMultiStmts.php deleted file mode 100644 index 1600730b..00000000 --- a/tests/Rules/Spotter/IfElseToMatchSpotterRule/Fixture/SkipMultiStmts.php +++ /dev/null @@ -1,19 +0,0 @@ - - */ -final class IfElseToMatchSpotterRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipComplexValue.php', []]; - yield [__DIR__ . '/Fixture/SkipAlmostMatching.php', []]; - - yield [__DIR__ . '/Fixture/IncludeNonEmpty.php', [[IfElseToMatchSpotterRule::ERROR_MESSAGE, 13]]]; - yield [__DIR__ . '/Fixture/EmptyArrayAssign.php', [[IfElseToMatchSpotterRule::ERROR_MESSAGE, 13]]]; - yield [__DIR__ . '/Fixture/MatchingIfCandidate.php', [[IfElseToMatchSpotterRule::ERROR_MESSAGE, 11]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(IfElseToMatchSpotterRule::class); - } -} diff --git a/tests/Rules/Spotter/IfElseToMatchSpotterRule/config/configured_rule.neon b/tests/Rules/Spotter/IfElseToMatchSpotterRule/config/configured_rule.neon deleted file mode 100644 index dc0d3c75..00000000 --- a/tests/Rules/Spotter/IfElseToMatchSpotterRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\Spotter\IfElseToMatchSpotterRule diff --git a/tests/Rules/Spotter/SwitchToMatchSpotterRule/Fixture/ReturnAndException.php b/tests/Rules/Spotter/SwitchToMatchSpotterRule/Fixture/ReturnAndException.php deleted file mode 100644 index 3bf38fcf..00000000 --- a/tests/Rules/Spotter/SwitchToMatchSpotterRule/Fixture/ReturnAndException.php +++ /dev/null @@ -1,18 +0,0 @@ - - */ -final class SwitchToMatchSpotterRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipNoDefault.php', []]; - yield [__DIR__ . '/Fixture/SimpleSwitch.php', [[SwitchToMatchSpotterRule::ERROR_MESSAGE, 11]]]; - yield [__DIR__ . '/Fixture/ReturnAndException.php', [[SwitchToMatchSpotterRule::ERROR_MESSAGE, 11]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(SwitchToMatchSpotterRule::class); - } -} diff --git a/tests/Rules/Spotter/SwitchToMatchSpotterRule/config/configured_rule.neon b/tests/Rules/Spotter/SwitchToMatchSpotterRule/config/configured_rule.neon deleted file mode 100644 index e48eec5d..00000000 --- a/tests/Rules/Spotter/SwitchToMatchSpotterRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\Spotter\SwitchToMatchSpotterRule diff --git a/tests/Rules/SuffixInterfaceRule/Fixture/InterfaceWithoutSuffix.php b/tests/Rules/SuffixInterfaceRule/Fixture/InterfaceWithoutSuffix.php deleted file mode 100644 index ebf69647..00000000 --- a/tests/Rules/SuffixInterfaceRule/Fixture/InterfaceWithoutSuffix.php +++ /dev/null @@ -1,10 +0,0 @@ - - */ -final class SuffixInterfaceRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipCorrectlyNameInterface.php', []]; - yield [__DIR__ . '/Fixture/InterfaceWithoutSuffix.php', [[SuffixInterfaceRule::ERROR_MESSAGE, 7]]]; - yield [__DIR__ . '/Fixture/NotAnInterface.php', [[SuffixInterfaceRule::ERROR_MESSAGE, 7]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(SuffixInterfaceRule::class); - } -} diff --git a/tests/Rules/SuffixInterfaceRule/config/configured_rule.neon b/tests/Rules/SuffixInterfaceRule/config/configured_rule.neon deleted file mode 100644 index 20006c41..00000000 --- a/tests/Rules/SuffixInterfaceRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\SuffixInterfaceRule diff --git a/tests/Rules/SuffixTraitRule/Fixture/SkipCorrectlyNameTrait.php b/tests/Rules/SuffixTraitRule/Fixture/SkipCorrectlyNameTrait.php deleted file mode 100644 index ac276b7f..00000000 --- a/tests/Rules/SuffixTraitRule/Fixture/SkipCorrectlyNameTrait.php +++ /dev/null @@ -1,10 +0,0 @@ - - */ -final class SuffixTraitRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SkipCorrectlyNameTrait.php', []]; - - yield [__DIR__ . '/Fixture/TraitWithoutSuffix.php', [[SuffixTraitRule::ERROR_MESSAGE, 7]]]; - yield [__DIR__ . '/Fixture/SomeNotTrait.php', [[SuffixTraitRule::ERROR_MESSAGE, 7]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(SuffixTraitRule::class); - } -} diff --git a/tests/Rules/SuffixTraitRule/config/configured_rule.neon b/tests/Rules/SuffixTraitRule/config/configured_rule.neon deleted file mode 100644 index 86aad411..00000000 --- a/tests/Rules/SuffixTraitRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\SuffixTraitRule diff --git a/tests/Rules/UppercaseConstantRule/Fixture/ConstantLower.php b/tests/Rules/UppercaseConstantRule/Fixture/ConstantLower.php deleted file mode 100644 index e0942c48..00000000 --- a/tests/Rules/UppercaseConstantRule/Fixture/ConstantLower.php +++ /dev/null @@ -1,10 +0,0 @@ - - */ -final class UppercaseConstantRuleTest extends RuleTestCase -{ - /** - * @dataProvider provideData() - * @param mixed[] $expectedErrorMessagesWithLines - */ - public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void - { - $this->analyse([$filePath], $expectedErrorMessagesWithLines); - } - - /** - * @return Iterator|string>> - */ - public function provideData(): Iterator - { - $errorMessage = sprintf(UppercaseConstantRule::ERROR_MESSAGE, 'SMall'); - yield [__DIR__ . '/Fixture/ConstantLower.php', [[$errorMessage, 9]]]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - return self::getContainer()->getByType(UppercaseConstantRule::class); - } -} diff --git a/tests/Rules/UppercaseConstantRule/config/configured_rule.neon b/tests/Rules/UppercaseConstantRule/config/configured_rule.neon deleted file mode 100644 index 510e5da4..00000000 --- a/tests/Rules/UppercaseConstantRule/config/configured_rule.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../../config/included_services.neon - -rules: - - Symplify\PHPStanRules\Rules\UppercaseConstantRule diff --git a/tests/config/included_services.neon b/tests/config/included_services.neon index 4b7a0068..6291a434 100644 --- a/tests/config/included_services.neon +++ b/tests/config/included_services.neon @@ -1,3 +1,2 @@ includes: - - ../../config/services/services.neon - - ../../../../packages/astral/config/services.neon + - ../../config/services.neon