add phpstan strict

This commit is contained in:
Clemens Schwaighofer
2023-02-28 06:39:36 +09:00
parent 710a48abcd
commit 537bc0a477
64 changed files with 4493 additions and 6 deletions

View File

@@ -1,6 +1,13 @@
{
"require-dev": {
"phpstan/phpstan": "^1.10",
"phan/phan": "^5.4"
"phan/phan": "^5.4",
"phpstan/extension-installer": "^1.2",
"phpstan/phpstan-strict-rules": "^1.5"
},
"config": {
"allow-plugins": {
"phpstan/extension-installer": true
}
}
}

95
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "fcdf8646822d333e75d48519c50c689a",
"content-hash": "7bfba596d1c7c3885f4d4aeea97c4926",
"packages": [],
"packages-dev": [
{
@@ -610,6 +610,50 @@
},
"time": "2022-10-14T12:47:21+00:00"
},
{
"name": "phpstan/extension-installer",
"version": "1.2.0",
"source": {
"type": "git",
"url": "https://github.com/phpstan/extension-installer.git",
"reference": "f06dbb052ddc394e7896fcd1cfcd533f9f6ace40"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/extension-installer/zipball/f06dbb052ddc394e7896fcd1cfcd533f9f6ace40",
"reference": "f06dbb052ddc394e7896fcd1cfcd533f9f6ace40",
"shasum": ""
},
"require": {
"composer-plugin-api": "^2.0",
"php": "^7.2 || ^8.0",
"phpstan/phpstan": "^1.8.0"
},
"require-dev": {
"composer/composer": "^2.0",
"php-parallel-lint/php-parallel-lint": "^1.2.0",
"phpstan/phpstan-strict-rules": "^0.11 || ^0.12 || ^1.0"
},
"type": "composer-plugin",
"extra": {
"class": "PHPStan\\ExtensionInstaller\\Plugin"
},
"autoload": {
"psr-4": {
"PHPStan\\ExtensionInstaller\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Composer plugin for automatic installation of PHPStan extensions",
"support": {
"issues": "https://github.com/phpstan/extension-installer/issues",
"source": "https://github.com/phpstan/extension-installer/tree/1.2.0"
},
"time": "2022-10-17T12:59:16+00:00"
},
{
"name": "phpstan/phpstan",
"version": "1.10.2",
@@ -669,6 +713,55 @@
],
"time": "2023-02-23T14:36:46+00:00"
},
{
"name": "phpstan/phpstan-strict-rules",
"version": "1.5.0",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-strict-rules.git",
"reference": "b7dd96a5503919a43b3cd06a2dced9d4252492f2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/b7dd96a5503919a43b3cd06a2dced9d4252492f2",
"reference": "b7dd96a5503919a43b3cd06a2dced9d4252492f2",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0",
"phpstan/phpstan": "^1.10"
},
"require-dev": {
"nikic/php-parser": "^4.13.0",
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/phpstan-deprecation-rules": "^1.1",
"phpstan/phpstan-phpunit": "^1.0",
"phpunit/phpunit": "^9.5"
},
"type": "phpstan-extension",
"extra": {
"phpstan": {
"includes": [
"rules.neon"
]
}
},
"autoload": {
"psr-4": {
"PHPStan\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Extra strict and opinionated rules for PHPStan",
"support": {
"issues": "https://github.com/phpstan/phpstan-strict-rules/issues",
"source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.5.0"
},
"time": "2023-02-21T10:17:10+00:00"
},
{
"name": "psr/container",
"version": "2.0.2",

View File

@@ -6,6 +6,20 @@ parameters:
level: 8 # max is now 9
checkMissingCallableSignature: true
treatPhpDocTypesAsCertain: false
strictRules:
allRules: false
disallowedLooseComparison: false
booleansInConditions: false
uselessCast: true
requireParentConstructorCall: false
disallowedConstructs: false
overwriteVariablesWithLoop: false
closureUsesThis: false
matchingInheritedMethodNames: false
numericOperandsInArithmeticOperators: false
strictCalls: false
switchConditionsMatchingType: false
noVariableVariables: false
paths:
- %currentWorkingDirectory%/www
bootstrapFiles:
@@ -30,6 +44,9 @@ parameters:
- www/admin/error_test.php
# admin synlink files
- www/admin/edit_*.php
- www/admin/config.php
# frotend symlink
- www/frontend/*config.php
# ignore admin header stuff
# - www/includes/admin_header.php # ignore the admin include stuff
- www/includes/admin_footer.php # ignore the admin include stuff
@@ -43,6 +60,8 @@ parameters:
- www/log
- www/media
- www/tmp
# File uploader
- www/lib/FileUpload
# ignore composer
- www/vendor
# ignore errores with

View File

@@ -10,6 +10,7 @@ return array(
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
'8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php',
'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
'9b38cf48e83f5d8f60375221cd213eee' => $vendorDir . '/phpstan/phpstan/bootstrap.php',
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php',
'2b9d0f43f9552984cfa82fee95491826' => $vendorDir . '/sabre/event/lib/coroutine.php',
@@ -17,5 +18,4 @@ return array(
'a1cce3d26cc15c00fcd0b3354bd72c88' => $vendorDir . '/sabre/event/lib/Promise/functions.php',
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
'6714be961f4a45ae8b9a99d5d55c5d07' => $vendorDir . '/tysonandre/var_representation_polyfill/src/var_representation.php',
'9b38cf48e83f5d8f60375221cd213eee' => $vendorDir . '/phpstan/phpstan/bootstrap.php',
);

View File

@@ -21,6 +21,8 @@ return array(
'Psr\\Log\\' => array($vendorDir . '/psr/log/src'),
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
'Phan\\' => array($vendorDir . '/phan/phan/src/Phan'),
'PHPStan\\ExtensionInstaller\\' => array($vendorDir . '/phpstan/extension-installer/src'),
'PHPStan\\' => array($vendorDir . '/phpstan/phpstan-strict-rules/src'),
'Microsoft\\PhpParser\\' => array($vendorDir . '/microsoft/tolerant-php-parser/src'),
'Composer\\XdebugHandler\\' => array($vendorDir . '/composer/xdebug-handler/src'),
'Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'),

View File

@@ -11,6 +11,7 @@ class ComposerStaticInitdd705c6e8ab22e0d642372dec7767718
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
'8825ede83f2f289127722d4e842cf7e8' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/bootstrap.php',
'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php',
'9b38cf48e83f5d8f60375221cd213eee' => __DIR__ . '/..' . '/phpstan/phpstan/bootstrap.php',
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
'b6b991a57620e2fb6b2f66f03fe9ddc2' => __DIR__ . '/..' . '/symfony/string/Resources/functions.php',
'2b9d0f43f9552984cfa82fee95491826' => __DIR__ . '/..' . '/sabre/event/lib/coroutine.php',
@@ -18,7 +19,6 @@ class ComposerStaticInitdd705c6e8ab22e0d642372dec7767718
'a1cce3d26cc15c00fcd0b3354bd72c88' => __DIR__ . '/..' . '/sabre/event/lib/Promise/functions.php',
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
'6714be961f4a45ae8b9a99d5d55c5d07' => __DIR__ . '/..' . '/tysonandre/var_representation_polyfill/src/var_representation.php',
'9b38cf48e83f5d8f60375221cd213eee' => __DIR__ . '/..' . '/phpstan/phpstan/bootstrap.php',
);
public static $prefixLengthsPsr4 = array (
@@ -51,6 +51,8 @@ class ComposerStaticInitdd705c6e8ab22e0d642372dec7767718
'Psr\\Log\\' => 8,
'Psr\\Container\\' => 14,
'Phan\\' => 5,
'PHPStan\\ExtensionInstaller\\' => 27,
'PHPStan\\' => 8,
),
'M' =>
array (
@@ -131,6 +133,14 @@ class ComposerStaticInitdd705c6e8ab22e0d642372dec7767718
array (
0 => __DIR__ . '/..' . '/phan/phan/src/Phan',
),
'PHPStan\\ExtensionInstaller\\' =>
array (
0 => __DIR__ . '/..' . '/phpstan/extension-installer/src',
),
'PHPStan\\' =>
array (
0 => __DIR__ . '/..' . '/phpstan/phpstan-strict-rules/src',
),
'Microsoft\\PhpParser\\' =>
array (
0 => __DIR__ . '/..' . '/microsoft/tolerant-php-parser/src',

View File

@@ -633,6 +633,53 @@
},
"install-path": "../phpdocumentor/type-resolver"
},
{
"name": "phpstan/extension-installer",
"version": "1.2.0",
"version_normalized": "1.2.0.0",
"source": {
"type": "git",
"url": "https://github.com/phpstan/extension-installer.git",
"reference": "f06dbb052ddc394e7896fcd1cfcd533f9f6ace40"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/extension-installer/zipball/f06dbb052ddc394e7896fcd1cfcd533f9f6ace40",
"reference": "f06dbb052ddc394e7896fcd1cfcd533f9f6ace40",
"shasum": ""
},
"require": {
"composer-plugin-api": "^2.0",
"php": "^7.2 || ^8.0",
"phpstan/phpstan": "^1.8.0"
},
"require-dev": {
"composer/composer": "^2.0",
"php-parallel-lint/php-parallel-lint": "^1.2.0",
"phpstan/phpstan-strict-rules": "^0.11 || ^0.12 || ^1.0"
},
"time": "2022-10-17T12:59:16+00:00",
"type": "composer-plugin",
"extra": {
"class": "PHPStan\\ExtensionInstaller\\Plugin"
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"PHPStan\\ExtensionInstaller\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Composer plugin for automatic installation of PHPStan extensions",
"support": {
"issues": "https://github.com/phpstan/extension-installer/issues",
"source": "https://github.com/phpstan/extension-installer/tree/1.2.0"
},
"install-path": "../phpstan/extension-installer"
},
{
"name": "phpstan/phpstan",
"version": "1.10.2",
@@ -695,6 +742,58 @@
],
"install-path": "../phpstan/phpstan"
},
{
"name": "phpstan/phpstan-strict-rules",
"version": "1.5.0",
"version_normalized": "1.5.0.0",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-strict-rules.git",
"reference": "b7dd96a5503919a43b3cd06a2dced9d4252492f2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/b7dd96a5503919a43b3cd06a2dced9d4252492f2",
"reference": "b7dd96a5503919a43b3cd06a2dced9d4252492f2",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0",
"phpstan/phpstan": "^1.10"
},
"require-dev": {
"nikic/php-parser": "^4.13.0",
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/phpstan-deprecation-rules": "^1.1",
"phpstan/phpstan-phpunit": "^1.0",
"phpunit/phpunit": "^9.5"
},
"time": "2023-02-21T10:17:10+00:00",
"type": "phpstan-extension",
"extra": {
"phpstan": {
"includes": [
"rules.neon"
]
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"PHPStan\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Extra strict and opinionated rules for PHPStan",
"support": {
"issues": "https://github.com/phpstan/phpstan-strict-rules/issues",
"source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.5.0"
},
"install-path": "../phpstan/phpstan-strict-rules"
},
{
"name": "psr/container",
"version": "2.0.2",
@@ -1786,7 +1885,9 @@
"phpdocumentor/reflection-common",
"phpdocumentor/reflection-docblock",
"phpdocumentor/type-resolver",
"phpstan/extension-installer",
"phpstan/phpstan",
"phpstan/phpstan-strict-rules",
"psr/container",
"psr/log",
"sabre/event",

View File

@@ -3,7 +3,7 @@
'name' => '__root__',
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'reference' => 'da67d1bde3260de1ef8d778f5d75f4e2c60de869',
'reference' => 'f564c27319dd258010ae5ce4cfb55a40817a3d9f',
'type' => 'library',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@@ -13,7 +13,7 @@
'__root__' => array(
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'reference' => 'da67d1bde3260de1ef8d778f5d75f4e2c60de869',
'reference' => 'f564c27319dd258010ae5ce4cfb55a40817a3d9f',
'type' => 'library',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@@ -109,6 +109,15 @@
'aliases' => array(),
'dev_requirement' => true,
),
'phpstan/extension-installer' => array(
'pretty_version' => '1.2.0',
'version' => '1.2.0.0',
'reference' => 'f06dbb052ddc394e7896fcd1cfcd533f9f6ace40',
'type' => 'composer-plugin',
'install_path' => __DIR__ . '/../phpstan/extension-installer',
'aliases' => array(),
'dev_requirement' => true,
),
'phpstan/phpstan' => array(
'pretty_version' => '1.10.2',
'version' => '1.10.2.0',
@@ -118,6 +127,15 @@
'aliases' => array(),
'dev_requirement' => true,
),
'phpstan/phpstan-strict-rules' => array(
'pretty_version' => '1.5.0',
'version' => '1.5.0.0',
'reference' => 'b7dd96a5503919a43b3cd06a2dced9d4252492f2',
'type' => 'phpstan-extension',
'install_path' => __DIR__ . '/../phpstan/phpstan-strict-rules',
'aliases' => array(),
'dev_requirement' => true,
),
'psr/container' => array(
'pretty_version' => '2.0.2',
'version' => '2.0.2.0',

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Ondřej Mirtes
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,77 @@
# PHPStan Extension Installer
[![Build](https://github.com/phpstan/extension-installer/workflows/Build/badge.svg)](https://github.com/phpstan/extension-installer/actions)
[![Latest Stable Version](https://poser.pugx.org/phpstan/extension-installer/v/stable)](https://packagist.org/packages/phpstan/extension-installer)
[![License](https://poser.pugx.org/phpstan/extension-installer/license)](https://packagist.org/packages/phpstan/extension-installer)
Composer plugin for automatic installation of [PHPStan](https://phpstan.org/) extensions.
# Motivation
```diff
diff --git a/phpstan.neon b/phpstan.neon
index db4e3df32e..2ca30fa20a 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -1,12 +1,3 @@
-includes:
- - vendor/phpstan/phpstan-doctrine/extension.neon
- - vendor/phpstan/phpstan-doctrine/rules.neon
- - vendor/phpstan/phpstan-nette/extension.neon
- - vendor/phpstan/phpstan-nette/rules.neon
- - vendor/phpstan/phpstan-phpunit/extension.neon
- - vendor/phpstan/phpstan-phpunit/rules.neon
- - vendor/phpstan/phpstan-strict-rules/rules.neon
-
parameters:
autoload_directories:
- %rootDir%/../../../build/SlevomatSniffs
diff --git a/composer.json b/composer.json
index 1b578dd624..f6ebf6e477 100644
--- a/composer.json
+++ b/composer.json
@@ -142,6 +142,7 @@
"jakub-onderka/php-parallel-lint": "1.0.0",
"justinrainbow/json-schema": "5.2.8",
"ondrejmirtes/mocktainer": "0.8",
+ "phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^0.11.7",
"phpstan/phpstan-doctrine": "^0.11.3",
"phpstan/phpstan-nette": "^0.11.1",
```
## Usage
```bash
composer require --dev phpstan/extension-installer
```
Starting from Composer 2.2.0 you'll get the following question:
```
phpstan/extension-installer contains a Composer plugin which is currently not in your allow-plugins config. See https://getcomposer.org/allow-plugins
Do you trust "phpstan/extension-installer" to execute code and wish to enable it now? (writes "allow-plugins" to composer.json) [y,n,d,?]
```
Answer with `y` to allow the plugin.
## Instructions for extension developers
It's best (but optional) to set the extension's composer package [type](https://getcomposer.org/doc/04-schema.md#type) to `phpstan-extension` for this plugin to be able to recognize it and to be [discoverable on Packagist](https://packagist.org/explore/?type=phpstan-extension).
Add `phpstan` key in the extension `composer.json`'s `extra` section:
```json
{
"extra": {
"phpstan": {
"includes": [
"extension.neon"
]
}
}
}
```
## Limitations
The extension installer depends on Composer script events, therefore you cannot use `--no-scripts` flag.

View File

@@ -0,0 +1,12 @@
{
"require-dev": {
"consistence-community/coding-standard": "^3.10",
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
"slevomat/coding-standard": "^7.0"
},
"config": {
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
}
}
}

View File

@@ -0,0 +1,322 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "4485bbedba7bcc71ace5f69dbb9b6c47",
"packages": [],
"packages-dev": [
{
"name": "consistence-community/coding-standard",
"version": "3.11.1",
"source": {
"type": "git",
"url": "https://github.com/consistence-community/coding-standard.git",
"reference": "4632fead8c9ee8f50044fcbce9f66c797b34c0df"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/consistence-community/coding-standard/zipball/4632fead8c9ee8f50044fcbce9f66c797b34c0df",
"reference": "4632fead8c9ee8f50044fcbce9f66c797b34c0df",
"shasum": ""
},
"require": {
"php": ">=7.4",
"slevomat/coding-standard": "~7.0",
"squizlabs/php_codesniffer": "~3.6.0"
},
"replace": {
"consistence/coding-standard": "3.10.*"
},
"require-dev": {
"phing/phing": "2.16.4",
"php-parallel-lint/php-parallel-lint": "1.3.0",
"phpunit/phpunit": "9.5.4"
},
"type": "library",
"autoload": {
"psr-4": {
"Consistence\\": [
"Consistence"
]
},
"classmap": [
"Consistence"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Vašek Purchart",
"email": "me@vasekpurchart.cz",
"homepage": "http://vasekpurchart.cz"
}
],
"description": "Consistence - Coding Standard - PHP Code Sniffer rules",
"keywords": [
"Coding Standard",
"PHPCodeSniffer",
"codesniffer",
"coding",
"cs",
"phpcs",
"ruleset",
"sniffer",
"standard"
],
"support": {
"issues": "https://github.com/consistence-community/coding-standard/issues",
"source": "https://github.com/consistence-community/coding-standard/tree/3.11.1"
},
"time": "2021-05-03T18:13:22+00:00"
},
{
"name": "dealerdirect/phpcodesniffer-composer-installer",
"version": "v0.7.2",
"source": {
"type": "git",
"url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git",
"reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
"reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.0 || ^2.0",
"php": ">=5.3",
"squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0"
},
"require-dev": {
"composer/composer": "*",
"php-parallel-lint/php-parallel-lint": "^1.3.1",
"phpcompatibility/php-compatibility": "^9.0"
},
"type": "composer-plugin",
"extra": {
"class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin"
},
"autoload": {
"psr-4": {
"Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Franck Nijhof",
"email": "franck.nijhof@dealerdirect.com",
"homepage": "http://www.frenck.nl",
"role": "Developer / IT Manager"
},
{
"name": "Contributors",
"homepage": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors"
}
],
"description": "PHP_CodeSniffer Standards Composer Installer Plugin",
"homepage": "http://www.dealerdirect.com",
"keywords": [
"PHPCodeSniffer",
"PHP_CodeSniffer",
"code quality",
"codesniffer",
"composer",
"installer",
"phpcbf",
"phpcs",
"plugin",
"qa",
"quality",
"standard",
"standards",
"style guide",
"stylecheck",
"tests"
],
"support": {
"issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues",
"source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer"
},
"time": "2022-02-04T12:51:07+00:00"
},
{
"name": "phpstan/phpdoc-parser",
"version": "1.5.1",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
"reference": "981cc368a216c988e862a75e526b6076987d1b50"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/981cc368a216c988e862a75e526b6076987d1b50",
"reference": "981cc368a216c988e862a75e526b6076987d1b50",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^1.5",
"phpstan/phpstan-strict-rules": "^1.0",
"phpunit/phpunit": "^9.5",
"symfony/process": "^5.2"
},
"type": "library",
"autoload": {
"psr-4": {
"PHPStan\\PhpDocParser\\": [
"src/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
"source": "https://github.com/phpstan/phpdoc-parser/tree/1.5.1"
},
"time": "2022-05-05T11:32:40+00:00"
},
{
"name": "slevomat/coding-standard",
"version": "7.2.1",
"source": {
"type": "git",
"url": "https://github.com/slevomat/coding-standard.git",
"reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/slevomat/coding-standard/zipball/aff06ae7a84e4534bf6f821dc982a93a5d477c90",
"reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90",
"shasum": ""
},
"require": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7",
"php": "^7.2 || ^8.0",
"phpstan/phpdoc-parser": "^1.5.1",
"squizlabs/php_codesniffer": "^3.6.2"
},
"require-dev": {
"phing/phing": "2.17.3",
"php-parallel-lint/php-parallel-lint": "1.3.2",
"phpstan/phpstan": "1.4.10|1.7.1",
"phpstan/phpstan-deprecation-rules": "1.0.0",
"phpstan/phpstan-phpunit": "1.0.0|1.1.1",
"phpstan/phpstan-strict-rules": "1.2.3",
"phpunit/phpunit": "7.5.20|8.5.21|9.5.20"
},
"type": "phpcodesniffer-standard",
"extra": {
"branch-alias": {
"dev-master": "7.x-dev"
}
},
"autoload": {
"psr-4": {
"SlevomatCodingStandard\\": "SlevomatCodingStandard"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.",
"support": {
"issues": "https://github.com/slevomat/coding-standard/issues",
"source": "https://github.com/slevomat/coding-standard/tree/7.2.1"
},
"funding": [
{
"url": "https://github.com/kukulich",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard",
"type": "tidelift"
}
],
"time": "2022-05-25T10:58:12+00:00"
},
{
"name": "squizlabs/php_codesniffer",
"version": "3.6.2",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
"reference": "5e4e71592f69da17871dba6e80dd51bce74a351a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/5e4e71592f69da17871dba6e80dd51bce74a351a",
"reference": "5e4e71592f69da17871dba6e80dd51bce74a351a",
"shasum": ""
},
"require": {
"ext-simplexml": "*",
"ext-tokenizer": "*",
"ext-xmlwriter": "*",
"php": ">=5.4.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
},
"bin": [
"bin/phpcs",
"bin/phpcbf"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.x-dev"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Greg Sherwood",
"role": "lead"
}
],
"description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
"homepage": "https://github.com/squizlabs/PHP_CodeSniffer",
"keywords": [
"phpcs",
"standards"
],
"support": {
"issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues",
"source": "https://github.com/squizlabs/PHP_CodeSniffer",
"wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki"
},
"time": "2021-12-12T21:44:58+00:00"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": [],
"plugin-api-version": "2.3.0"
}

View File

@@ -0,0 +1,32 @@
{
"name": "phpstan/extension-installer",
"type": "composer-plugin",
"description": "Composer plugin for automatic installation of PHPStan extensions",
"license": [
"MIT"
],
"require": {
"php": "^7.2 || ^8.0",
"composer-plugin-api": "^2.0",
"phpstan/phpstan": "^1.8.0"
},
"require-dev": {
"composer/composer": "^2.0",
"php-parallel-lint/php-parallel-lint": "^1.2.0",
"phpstan/phpstan-strict-rules": "^0.11 || ^0.12 || ^1.0"
},
"config": {
"sort-packages": true,
"allow-plugins": {
"ocramius/package-versions": true
}
},
"extra": {
"class": "PHPStan\\ExtensionInstaller\\Plugin"
},
"autoload": {
"psr-4": {
"PHPStan\\ExtensionInstaller\\": "src/"
}
}
}

View File

@@ -0,0 +1,26 @@
<?php declare(strict_types = 1);
namespace PHPStan\ExtensionInstaller;
/**
* This is a stub class: it is in place only for scenarios where Composer
* is run with a `--no-scripts` flag, in which scenarios this stub class
* is not being replaced.
*
* If you are reading this docBlock inside your `vendor/` dir, then this means
* that phpstan/extension-installer didn't correctly install.
*
* @internal
*/
final class GeneratedConfig
{
public const EXTENSIONS = [];
public const NOT_INSTALLED = [];
private function __construct()
{
}
}

View File

@@ -0,0 +1,159 @@
<?php declare(strict_types = 1);
namespace PHPStan\ExtensionInstaller;
use Composer\Composer;
use Composer\EventDispatcher\EventSubscriberInterface;
use Composer\IO\IOInterface;
use Composer\Plugin\PluginInterface;
use Composer\Script\Event;
use Composer\Script\ScriptEvents;
use Composer\Util\Filesystem;
use function array_keys;
use function dirname;
use function file_exists;
use function file_put_contents;
use function getcwd;
use function in_array;
use function is_file;
use function ksort;
use function md5;
use function md5_file;
use function sprintf;
use function strpos;
use function var_export;
use const DIRECTORY_SEPARATOR;
final class Plugin implements PluginInterface, EventSubscriberInterface
{
/** @var string */
private static $generatedFileTemplate = <<<'PHP'
<?php declare(strict_types = 1);
namespace PHPStan\ExtensionInstaller;
/**
* This class is generated by phpstan/extension-installer.
* @internal
*/
final class GeneratedConfig
{
public const EXTENSIONS = %s;
public const NOT_INSTALLED = %s;
private function __construct()
{
}
}
PHP;
public function activate(Composer $composer, IOInterface $io): void
{
// noop
}
public function deactivate(Composer $composer, IOInterface $io): void
{
// noop
}
public function uninstall(Composer $composer, IOInterface $io): void
{
// noop
}
/**
* @return array<string, string>
*/
public static function getSubscribedEvents(): array
{
return [
ScriptEvents::POST_INSTALL_CMD => 'process',
ScriptEvents::POST_UPDATE_CMD => 'process',
];
}
public function process(Event $event): void
{
$io = $event->getIO();
if (!file_exists(__DIR__)) {
$io->write('<info>phpstan/extension-installer:</info> Package not found (probably scheduled for removal); extensions installation skipped.');
return;
}
$composer = $event->getComposer();
$installationManager = $composer->getInstallationManager();
$generatedConfigFilePath = __DIR__ . '/GeneratedConfig.php';
$oldGeneratedConfigFileHash = null;
if (is_file($generatedConfigFilePath)) {
$oldGeneratedConfigFileHash = md5_file($generatedConfigFilePath);
}
$notInstalledPackages = [];
$installedPackages = [];
$data = [];
$fs = new Filesystem();
foreach ($composer->getRepositoryManager()->getLocalRepository()->getPackages() as $package) {
if (
$package->getType() !== 'phpstan-extension'
&& !isset($package->getExtra()['phpstan'])
) {
if (
strpos($package->getName(), 'phpstan') !== false
&& !in_array($package->getName(), [
'phpstan/phpstan',
'phpstan/phpstan-shim',
'phpstan/phpdoc-parser',
'phpstan/extension-installer',
], true)
) {
$notInstalledPackages[$package->getName()] = $package->getFullPrettyVersion();
}
continue;
}
$installPath = $installationManager->getInstallPath($package);
$absoluteInstallPath = $fs->isAbsolutePath($installPath)
? $installPath
: getcwd() . DIRECTORY_SEPARATOR . $installPath;
$data[$package->getName()] = [
'install_path' => $absoluteInstallPath,
'relative_install_path' => $fs->findShortestPath(dirname($generatedConfigFilePath), $absoluteInstallPath, true),
'extra' => $package->getExtra()['phpstan'] ?? null,
'version' => $package->getFullPrettyVersion(),
];
$installedPackages[$package->getName()] = true;
}
ksort($data);
ksort($installedPackages);
ksort($notInstalledPackages);
$generatedConfigFileContents = sprintf(self::$generatedFileTemplate, var_export($data, true), var_export($notInstalledPackages, true));
file_put_contents($generatedConfigFilePath, $generatedConfigFileContents);
$io->write('<info>phpstan/extension-installer:</info> Extensions installed');
if ($oldGeneratedConfigFileHash === md5($generatedConfigFileContents)) {
return;
}
foreach (array_keys($installedPackages) as $name) {
$io->write(sprintf('> <info>%s:</info> installed', $name));
}
foreach (array_keys($notInstalledPackages) as $name) {
$io->write(sprintf('> <comment>%s:</comment> not supported', $name));
}
}
}

View File

@@ -0,0 +1,27 @@
root = true
[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
trim_trailing_whitespace = true
[*.{php,phpt}]
indent_style = tab
indent_size = 4
[*.xml]
indent_style = tab
indent_size = 4
[*.neon]
indent_style = tab
indent_size = 4
[*.{yaml,yml}]
indent_style = space
indent_size = 2
[composer.json]
indent_style = tab
indent_size = 4

View File

@@ -0,0 +1,22 @@
MIT License
Copyright (c) 2016 Ondřej Mirtes
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,98 @@
# Extra strict and opinionated rules for PHPStan
[![Build](https://github.com/phpstan/phpstan-strict-rules/workflows/Build/badge.svg)](https://github.com/phpstan/phpstan-strict-rules/actions)
[![Latest Stable Version](https://poser.pugx.org/phpstan/phpstan-strict-rules/v/stable)](https://packagist.org/packages/phpstan/phpstan-strict-rules)
[![License](https://poser.pugx.org/phpstan/phpstan-strict-rules/license)](https://packagist.org/packages/phpstan/phpstan-strict-rules)
[PHPStan](https://phpstan.org/) focuses on finding bugs in your code. But in PHP there's a lot of leeway in how stuff can be written. This repository contains additional rules that revolve around strictly and strongly typed code with no loose casting for those who want additional safety in extremely defensive programming:
* Require booleans in `if`, `elseif`, ternary operator, after `!`, and on both sides of `&&` and `||`.
* Require numeric operands or arrays in `+` and numeric operands in `-`/`*`/`/`/`**`/`%`.
* Require numeric operand in `$var++`, `$var--`, `++$var`and `--$var`.
* These functions contain a `$strict` parameter for better type safety, it must be set to `true`:
* `in_array` (3rd parameter)
* `array_search` (3rd parameter)
* `array_keys` (3rd parameter; only if the 2nd parameter `$search_value` is provided)
* `base64_decode` (2nd parameter)
* Variables assigned in `while` loop condition and `for` loop initial assignment cannot be used after the loop.
* Variables set in foreach that's always looped thanks to non-empty arrays cannot be used after the loop.
* Types in `switch` condition and `case` value must match. PHP compares them loosely by default and that can lead to unexpected results.
* Check that statically declared methods are called statically.
* Disallow `empty()` - it's a very loose comparison (see [manual](https://php.net/empty)), it's recommended to use more strict one.
* Disallow short ternary operator (`?:`) - implies weak comparison, it's recommended to use null coalesce operator (`??`) or ternary operator with strict condition.
* Disallow variable variables (`$$foo`, `$this->$method()` etc.)
* Disallow overwriting variables with foreach key and value variables
* Always true `instanceof`, type-checking `is_*` functions and strict comparisons `===`/`!==`. These checks can be turned off by setting `checkAlwaysTrueInstanceof`/`checkAlwaysTrueCheckTypeFunctionCall`/`checkAlwaysTrueStrictComparison` to false.
* Correct case for referenced and called function names.
* Correct case for inherited and implemented method names.
* Contravariance for parameter types and covariance for return types in inherited methods (also known as Liskov substitution principle - LSP)
* Check LSP even for static methods
* Require calling parent constructor
* Disallow usage of backtick operator (`` $ls = `ls -la` ``)
* Closure should use `$this` directly instead of using `$this` variable indirectly
Additional rules are coming in subsequent releases!
## Installation
To use this extension, require it in [Composer](https://getcomposer.org/):
```
composer require --dev phpstan/phpstan-strict-rules
```
If you also install [phpstan/extension-installer](https://github.com/phpstan/extension-installer) then you're all set!
<details>
<summary>Manual installation</summary>
If you don't want to use `phpstan/extension-installer`, include rules.neon in your project's PHPStan config:
```
includes:
- vendor/phpstan/phpstan-strict-rules/rules.neon
```
</details>
## Disabling rules
You can disable rules using configuration parameters:
```neon
parameters:
strictRules:
disallowedLooseComparison: false
booleansInConditions: false
uselessCast: false
requireParentConstructorCall: false
disallowedConstructs: false
overwriteVariablesWithLoop: false
closureUsesThis: false
matchingInheritedMethodNames: false
numericOperandsInArithmeticOperators: false
strictCalls: false
switchConditionsMatchingType: false
noVariableVariables: false
```
## Enabling rules one-by-one
If you don't want to start using all the available strict rules at once but only one or two, you can!
You can disable all rules from the included `rules.neon` with:
```neon
parameters:
strictRules:
allRules: false
```
Then you can re-enable individual rules with configuration parameters:
```neon
parameters:
strictRules:
allRules: false
booleansInConditions: true
```

View File

@@ -0,0 +1,12 @@
{
"require-dev": {
"consistence-community/coding-standard": "^3.10",
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
"slevomat/coding-standard": "^7.0"
},
"config": {
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
}
}
}

View File

@@ -0,0 +1,322 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "4485bbedba7bcc71ace5f69dbb9b6c47",
"packages": [],
"packages-dev": [
{
"name": "consistence-community/coding-standard",
"version": "3.11.1",
"source": {
"type": "git",
"url": "https://github.com/consistence-community/coding-standard.git",
"reference": "4632fead8c9ee8f50044fcbce9f66c797b34c0df"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/consistence-community/coding-standard/zipball/4632fead8c9ee8f50044fcbce9f66c797b34c0df",
"reference": "4632fead8c9ee8f50044fcbce9f66c797b34c0df",
"shasum": ""
},
"require": {
"php": ">=7.4",
"slevomat/coding-standard": "~7.0",
"squizlabs/php_codesniffer": "~3.6.0"
},
"replace": {
"consistence/coding-standard": "3.10.*"
},
"require-dev": {
"phing/phing": "2.16.4",
"php-parallel-lint/php-parallel-lint": "1.3.0",
"phpunit/phpunit": "9.5.4"
},
"type": "library",
"autoload": {
"psr-4": {
"Consistence\\": [
"Consistence"
]
},
"classmap": [
"Consistence"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Vašek Purchart",
"email": "me@vasekpurchart.cz",
"homepage": "http://vasekpurchart.cz"
}
],
"description": "Consistence - Coding Standard - PHP Code Sniffer rules",
"keywords": [
"Coding Standard",
"PHPCodeSniffer",
"codesniffer",
"coding",
"cs",
"phpcs",
"ruleset",
"sniffer",
"standard"
],
"support": {
"issues": "https://github.com/consistence-community/coding-standard/issues",
"source": "https://github.com/consistence-community/coding-standard/tree/3.11.1"
},
"time": "2021-05-03T18:13:22+00:00"
},
{
"name": "dealerdirect/phpcodesniffer-composer-installer",
"version": "v0.7.2",
"source": {
"type": "git",
"url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git",
"reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
"reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.0 || ^2.0",
"php": ">=5.3",
"squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0"
},
"require-dev": {
"composer/composer": "*",
"php-parallel-lint/php-parallel-lint": "^1.3.1",
"phpcompatibility/php-compatibility": "^9.0"
},
"type": "composer-plugin",
"extra": {
"class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin"
},
"autoload": {
"psr-4": {
"Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Franck Nijhof",
"email": "franck.nijhof@dealerdirect.com",
"homepage": "http://www.frenck.nl",
"role": "Developer / IT Manager"
},
{
"name": "Contributors",
"homepage": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors"
}
],
"description": "PHP_CodeSniffer Standards Composer Installer Plugin",
"homepage": "http://www.dealerdirect.com",
"keywords": [
"PHPCodeSniffer",
"PHP_CodeSniffer",
"code quality",
"codesniffer",
"composer",
"installer",
"phpcbf",
"phpcs",
"plugin",
"qa",
"quality",
"standard",
"standards",
"style guide",
"stylecheck",
"tests"
],
"support": {
"issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues",
"source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer"
},
"time": "2022-02-04T12:51:07+00:00"
},
{
"name": "phpstan/phpdoc-parser",
"version": "1.5.1",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
"reference": "981cc368a216c988e862a75e526b6076987d1b50"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/981cc368a216c988e862a75e526b6076987d1b50",
"reference": "981cc368a216c988e862a75e526b6076987d1b50",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^1.5",
"phpstan/phpstan-strict-rules": "^1.0",
"phpunit/phpunit": "^9.5",
"symfony/process": "^5.2"
},
"type": "library",
"autoload": {
"psr-4": {
"PHPStan\\PhpDocParser\\": [
"src/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
"source": "https://github.com/phpstan/phpdoc-parser/tree/1.5.1"
},
"time": "2022-05-05T11:32:40+00:00"
},
{
"name": "slevomat/coding-standard",
"version": "7.2.1",
"source": {
"type": "git",
"url": "https://github.com/slevomat/coding-standard.git",
"reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/slevomat/coding-standard/zipball/aff06ae7a84e4534bf6f821dc982a93a5d477c90",
"reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90",
"shasum": ""
},
"require": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7",
"php": "^7.2 || ^8.0",
"phpstan/phpdoc-parser": "^1.5.1",
"squizlabs/php_codesniffer": "^3.6.2"
},
"require-dev": {
"phing/phing": "2.17.3",
"php-parallel-lint/php-parallel-lint": "1.3.2",
"phpstan/phpstan": "1.4.10|1.7.1",
"phpstan/phpstan-deprecation-rules": "1.0.0",
"phpstan/phpstan-phpunit": "1.0.0|1.1.1",
"phpstan/phpstan-strict-rules": "1.2.3",
"phpunit/phpunit": "7.5.20|8.5.21|9.5.20"
},
"type": "phpcodesniffer-standard",
"extra": {
"branch-alias": {
"dev-master": "7.x-dev"
}
},
"autoload": {
"psr-4": {
"SlevomatCodingStandard\\": "SlevomatCodingStandard"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.",
"support": {
"issues": "https://github.com/slevomat/coding-standard/issues",
"source": "https://github.com/slevomat/coding-standard/tree/7.2.1"
},
"funding": [
{
"url": "https://github.com/kukulich",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard",
"type": "tidelift"
}
],
"time": "2022-05-25T10:58:12+00:00"
},
{
"name": "squizlabs/php_codesniffer",
"version": "3.6.2",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
"reference": "5e4e71592f69da17871dba6e80dd51bce74a351a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/5e4e71592f69da17871dba6e80dd51bce74a351a",
"reference": "5e4e71592f69da17871dba6e80dd51bce74a351a",
"shasum": ""
},
"require": {
"ext-simplexml": "*",
"ext-tokenizer": "*",
"ext-xmlwriter": "*",
"php": ">=5.4.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
},
"bin": [
"bin/phpcs",
"bin/phpcbf"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.x-dev"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Greg Sherwood",
"role": "lead"
}
],
"description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
"homepage": "https://github.com/squizlabs/PHP_CodeSniffer",
"keywords": [
"phpcs",
"standards"
],
"support": {
"issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues",
"source": "https://github.com/squizlabs/PHP_CodeSniffer",
"wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki"
},
"time": "2021-12-12T21:44:58+00:00"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": [],
"plugin-api-version": "2.3.0"
}

View File

@@ -0,0 +1,44 @@
{
"name": "phpstan/phpstan-strict-rules",
"type": "phpstan-extension",
"description": "Extra strict and opinionated rules for PHPStan",
"license": [
"MIT"
],
"require": {
"php": "^7.2 || ^8.0",
"phpstan/phpstan": "^1.10"
},
"require-dev": {
"nikic/php-parser": "^4.13.0",
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/phpstan-deprecation-rules": "^1.1",
"phpstan/phpstan-phpunit": "^1.0",
"phpunit/phpunit": "^9.5"
},
"config": {
"platform": {
"php": "7.4.6"
},
"sort-packages": true
},
"extra": {
"phpstan": {
"includes": [
"rules.neon"
]
}
},
"autoload": {
"psr-4": {
"PHPStan\\": "src/"
}
},
"autoload-dev": {
"classmap": [
"tests/"
]
},
"minimum-stability": "dev",
"prefer-stable": true
}

View File

@@ -0,0 +1,478 @@
parameters:
ignoreErrors:
-
message: "#^Class PHPStan\\\\Rules\\\\BooleansInConditions\\\\BooleanInBooleanNotRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
count: 1
path: src/Rules/BooleansInConditions/BooleanInBooleanNotRule.php
-
message: "#^Parameter \\#1 \\$node \\(PhpParser\\\\Node\\\\Expr\\\\BooleanNot\\) of method PHPStan\\\\Rules\\\\BooleansInConditions\\\\BooleanInBooleanNotRule\\:\\:processNode\\(\\) should be contravariant with parameter \\$node \\(PhpParser\\\\Node\\) of method PHPStan\\\\Rules\\\\Rule\\<PhpParser\\\\Node\\>\\:\\:processNode\\(\\)$#"
count: 1
path: src/Rules/BooleansInConditions/BooleanInBooleanNotRule.php
-
message: "#^Class PHPStan\\\\Rules\\\\BooleansInConditions\\\\BooleanInElseIfConditionRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
count: 1
path: src/Rules/BooleansInConditions/BooleanInElseIfConditionRule.php
-
message: "#^Parameter \\#1 \\$node \\(PhpParser\\\\Node\\\\Stmt\\\\ElseIf_\\) of method PHPStan\\\\Rules\\\\BooleansInConditions\\\\BooleanInElseIfConditionRule\\:\\:processNode\\(\\) should be contravariant with parameter \\$node \\(PhpParser\\\\Node\\) of method PHPStan\\\\Rules\\\\Rule\\<PhpParser\\\\Node\\>\\:\\:processNode\\(\\)$#"
count: 1
path: src/Rules/BooleansInConditions/BooleanInElseIfConditionRule.php
-
message: "#^Class PHPStan\\\\Rules\\\\BooleansInConditions\\\\BooleanInIfConditionRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
count: 1
path: src/Rules/BooleansInConditions/BooleanInIfConditionRule.php
-
message: "#^Parameter \\#1 \\$node \\(PhpParser\\\\Node\\\\Stmt\\\\If_\\) of method PHPStan\\\\Rules\\\\BooleansInConditions\\\\BooleanInIfConditionRule\\:\\:processNode\\(\\) should be contravariant with parameter \\$node \\(PhpParser\\\\Node\\) of method PHPStan\\\\Rules\\\\Rule\\<PhpParser\\\\Node\\>\\:\\:processNode\\(\\)$#"
count: 1
path: src/Rules/BooleansInConditions/BooleanInIfConditionRule.php
-
message: "#^Class PHPStan\\\\Rules\\\\BooleansInConditions\\\\BooleanInTernaryOperatorRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
count: 1
path: src/Rules/BooleansInConditions/BooleanInTernaryOperatorRule.php
-
message: "#^Parameter \\#1 \\$node \\(PhpParser\\\\Node\\\\Expr\\\\Ternary\\) of method PHPStan\\\\Rules\\\\BooleansInConditions\\\\BooleanInTernaryOperatorRule\\:\\:processNode\\(\\) should be contravariant with parameter \\$node \\(PhpParser\\\\Node\\) of method PHPStan\\\\Rules\\\\Rule\\<PhpParser\\\\Node\\>\\:\\:processNode\\(\\)$#"
count: 1
path: src/Rules/BooleansInConditions/BooleanInTernaryOperatorRule.php
-
message: "#^Class PHPStan\\\\Rules\\\\Cast\\\\UselessCastRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
count: 1
path: src/Rules/Cast/UselessCastRule.php
-
message: "#^Parameter \\#1 \\$node \\(PhpParser\\\\Node\\\\Expr\\\\Cast\\) of method PHPStan\\\\Rules\\\\Cast\\\\UselessCastRule\\:\\:processNode\\(\\) should be contravariant with parameter \\$node \\(PhpParser\\\\Node\\) of method PHPStan\\\\Rules\\\\Rule\\<PhpParser\\\\Node\\>\\:\\:processNode\\(\\)$#"
count: 1
path: src/Rules/Cast/UselessCastRule.php
-
message: "#^Class PHPStan\\\\Rules\\\\Classes\\\\RequireParentConstructCallRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
count: 1
path: src/Rules/Classes/RequireParentConstructCallRule.php
-
message: "#^Parameter \\#1 \\$node \\(PhpParser\\\\Node\\\\Stmt\\\\ClassMethod\\) of method PHPStan\\\\Rules\\\\Classes\\\\RequireParentConstructCallRule\\:\\:processNode\\(\\) should be contravariant with parameter \\$node \\(PhpParser\\\\Node\\) of method PHPStan\\\\Rules\\\\Rule\\<PhpParser\\\\Node\\>\\:\\:processNode\\(\\)$#"
count: 1
path: src/Rules/Classes/RequireParentConstructCallRule.php
-
message: "#^Class PHPStan\\\\Rules\\\\DisallowedConstructs\\\\DisallowedBacktickRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
count: 1
path: src/Rules/DisallowedConstructs/DisallowedBacktickRule.php
-
message: "#^Parameter \\#1 \\$node \\(PhpParser\\\\Node\\\\Expr\\\\Empty_\\) of method PHPStan\\\\Rules\\\\DisallowedConstructs\\\\DisallowedBacktickRule\\:\\:processNode\\(\\) should be contravariant with parameter \\$node \\(PhpParser\\\\Node\\) of method PHPStan\\\\Rules\\\\Rule\\<PhpParser\\\\Node\\>\\:\\:processNode\\(\\)$#"
count: 1
path: src/Rules/DisallowedConstructs/DisallowedBacktickRule.php
-
message: "#^Class PHPStan\\\\Rules\\\\DisallowedConstructs\\\\DisallowedEmptyRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
count: 1
path: src/Rules/DisallowedConstructs/DisallowedEmptyRule.php
-
message: "#^Parameter \\#1 \\$node \\(PhpParser\\\\Node\\\\Expr\\\\Empty_\\) of method PHPStan\\\\Rules\\\\DisallowedConstructs\\\\DisallowedEmptyRule\\:\\:processNode\\(\\) should be contravariant with parameter \\$node \\(PhpParser\\\\Node\\) of method PHPStan\\\\Rules\\\\Rule\\<PhpParser\\\\Node\\>\\:\\:processNode\\(\\)$#"
count: 1
path: src/Rules/DisallowedConstructs/DisallowedEmptyRule.php
-
message: "#^Class PHPStan\\\\Rules\\\\DisallowedConstructs\\\\DisallowedImplicitArrayCreationRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
count: 1
path: src/Rules/DisallowedConstructs/DisallowedImplicitArrayCreationRule.php
-
message: "#^Parameter \\#1 \\$node \\(PhpParser\\\\Node\\\\Expr\\\\Assign\\) of method PHPStan\\\\Rules\\\\DisallowedConstructs\\\\DisallowedImplicitArrayCreationRule\\:\\:processNode\\(\\) should be contravariant with parameter \\$node \\(PhpParser\\\\Node\\) of method PHPStan\\\\Rules\\\\Rule\\<PhpParser\\\\Node\\>\\:\\:processNode\\(\\)$#"
count: 1
path: src/Rules/DisallowedConstructs/DisallowedImplicitArrayCreationRule.php
-
message: "#^Class PHPStan\\\\Rules\\\\ForeachLoop\\\\OverwriteVariablesWithForeachRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
count: 1
path: src/Rules/ForeachLoop/OverwriteVariablesWithForeachRule.php
-
message: "#^Parameter \\#1 \\$node \\(PhpParser\\\\Node\\\\Stmt\\\\Foreach_\\) of method PHPStan\\\\Rules\\\\ForeachLoop\\\\OverwriteVariablesWithForeachRule\\:\\:processNode\\(\\) should be contravariant with parameter \\$node \\(PhpParser\\\\Node\\) of method PHPStan\\\\Rules\\\\Rule\\<PhpParser\\\\Node\\>\\:\\:processNode\\(\\)$#"
count: 1
path: src/Rules/ForeachLoop/OverwriteVariablesWithForeachRule.php
-
message: "#^Class PHPStan\\\\Rules\\\\Operators\\\\OperandsInArithmeticAdditionRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
count: 1
path: src/Rules/Operators/OperandsInArithmeticAdditionRule.php
-
message: "#^Class PHPStan\\\\Rules\\\\Operators\\\\OperandsInArithmeticDivisionRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
count: 1
path: src/Rules/Operators/OperandsInArithmeticDivisionRule.php
-
message: "#^Class PHPStan\\\\Rules\\\\Operators\\\\OperandsInArithmeticExponentiationRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
count: 1
path: src/Rules/Operators/OperandsInArithmeticExponentiationRule.php
-
message: "#^Class PHPStan\\\\Rules\\\\Operators\\\\OperandsInArithmeticModuloRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
count: 1
path: src/Rules/Operators/OperandsInArithmeticModuloRule.php
-
message: "#^Class PHPStan\\\\Rules\\\\Operators\\\\OperandsInArithmeticMultiplicationRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
count: 1
path: src/Rules/Operators/OperandsInArithmeticMultiplicationRule.php
-
message: "#^Class PHPStan\\\\Rules\\\\Operators\\\\OperandsInArithmeticSubtractionRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
count: 1
path: src/Rules/Operators/OperandsInArithmeticSubtractionRule.php
-
message: "#^Class PHPStan\\\\Rules\\\\StrictCalls\\\\DynamicCallOnStaticMethodsRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
count: 1
path: src/Rules/StrictCalls/DynamicCallOnStaticMethodsRule.php
-
message: "#^Parameter \\#1 \\$node \\(PhpParser\\\\Node\\\\Expr\\\\MethodCall\\) of method PHPStan\\\\Rules\\\\StrictCalls\\\\DynamicCallOnStaticMethodsRule\\:\\:processNode\\(\\) should be contravariant with parameter \\$node \\(PhpParser\\\\Node\\) of method PHPStan\\\\Rules\\\\Rule\\<PhpParser\\\\Node\\>\\:\\:processNode\\(\\)$#"
count: 1
path: src/Rules/StrictCalls/DynamicCallOnStaticMethodsRule.php
-
message: "#^Class PHPStan\\\\Rules\\\\StrictCalls\\\\StrictFunctionCallsRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
count: 1
path: src/Rules/StrictCalls/StrictFunctionCallsRule.php
-
message: "#^Parameter \\#1 \\$node \\(PhpParser\\\\Node\\\\Expr\\\\FuncCall\\) of method PHPStan\\\\Rules\\\\StrictCalls\\\\StrictFunctionCallsRule\\:\\:processNode\\(\\) should be contravariant with parameter \\$node \\(PhpParser\\\\Node\\) of method PHPStan\\\\Rules\\\\Rule\\<PhpParser\\\\Node\\>\\:\\:processNode\\(\\)$#"
count: 1
path: src/Rules/StrictCalls/StrictFunctionCallsRule.php
-
message: "#^Class PHPStan\\\\Rules\\\\VariableVariables\\\\VariableMethodCallRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
count: 1
path: src/Rules/VariableVariables/VariableMethodCallRule.php
-
message: "#^Parameter \\#1 \\$node \\(PhpParser\\\\Node\\\\Expr\\\\MethodCall\\) of method PHPStan\\\\Rules\\\\VariableVariables\\\\VariableMethodCallRule\\:\\:processNode\\(\\) should be contravariant with parameter \\$node \\(PhpParser\\\\Node\\) of method PHPStan\\\\Rules\\\\Rule\\<PhpParser\\\\Node\\>\\:\\:processNode\\(\\)$#"
count: 1
path: src/Rules/VariableVariables/VariableMethodCallRule.php
-
message: "#^Class PHPStan\\\\Rules\\\\VariableVariables\\\\VariablePropertyFetchRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
count: 1
path: src/Rules/VariableVariables/VariablePropertyFetchRule.php
-
message: "#^Parameter \\#1 \\$node \\(PhpParser\\\\Node\\\\Expr\\\\PropertyFetch\\) of method PHPStan\\\\Rules\\\\VariableVariables\\\\VariablePropertyFetchRule\\:\\:processNode\\(\\) should be contravariant with parameter \\$node \\(PhpParser\\\\Node\\) of method PHPStan\\\\Rules\\\\Rule\\<PhpParser\\\\Node\\>\\:\\:processNode\\(\\)$#"
count: 1
path: src/Rules/VariableVariables/VariablePropertyFetchRule.php
-
message: "#^Class PHPStan\\\\Rules\\\\VariableVariables\\\\VariableStaticMethodCallRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
count: 1
path: src/Rules/VariableVariables/VariableStaticMethodCallRule.php
-
message: "#^Parameter \\#1 \\$node \\(PhpParser\\\\Node\\\\Expr\\\\StaticCall\\) of method PHPStan\\\\Rules\\\\VariableVariables\\\\VariableStaticMethodCallRule\\:\\:processNode\\(\\) should be contravariant with parameter \\$node \\(PhpParser\\\\Node\\) of method PHPStan\\\\Rules\\\\Rule\\<PhpParser\\\\Node\\>\\:\\:processNode\\(\\)$#"
count: 1
path: src/Rules/VariableVariables/VariableStaticMethodCallRule.php
-
message: "#^Class PHPStan\\\\Rules\\\\VariableVariables\\\\VariableStaticPropertyFetchRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
count: 1
path: src/Rules/VariableVariables/VariableStaticPropertyFetchRule.php
-
message: "#^Parameter \\#1 \\$node \\(PhpParser\\\\Node\\\\Expr\\\\StaticPropertyFetch\\) of method PHPStan\\\\Rules\\\\VariableVariables\\\\VariableStaticPropertyFetchRule\\:\\:processNode\\(\\) should be contravariant with parameter \\$node \\(PhpParser\\\\Node\\) of method PHPStan\\\\Rules\\\\Rule\\<PhpParser\\\\Node\\>\\:\\:processNode\\(\\)$#"
count: 1
path: src/Rules/VariableVariables/VariableStaticPropertyFetchRule.php
-
message: "#^Class PHPStan\\\\Rules\\\\VariableVariables\\\\VariableVariablesRule implements generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#"
count: 1
path: src/Rules/VariableVariables/VariableVariablesRule.php
-
message: "#^Parameter \\#1 \\$node \\(PhpParser\\\\Node\\\\Expr\\\\Variable\\) of method PHPStan\\\\Rules\\\\VariableVariables\\\\VariableVariablesRule\\:\\:processNode\\(\\) should be contravariant with parameter \\$node \\(PhpParser\\\\Node\\) of method PHPStan\\\\Rules\\\\Rule\\<PhpParser\\\\Node\\>\\:\\:processNode\\(\\)$#"
count: 1
path: src/Rules/VariableVariables/VariableVariablesRule.php
-
message: "#^Class PHPStan\\\\Rules\\\\BooleansInConditions\\\\BooleanInBooleanNotRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#"
count: 1
path: tests/Rules/BooleansInConditions/BooleanInBooleanNotRuleTest.php
-
message: "#^Method PHPStan\\\\Rules\\\\BooleansInConditions\\\\BooleanInBooleanNotRuleTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#"
count: 1
path: tests/Rules/BooleansInConditions/BooleanInBooleanNotRuleTest.php
-
message: "#^Class PHPStan\\\\Rules\\\\BooleansInConditions\\\\BooleanInElseIfConditionRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#"
count: 1
path: tests/Rules/BooleansInConditions/BooleanInElseIfConditionRuleTest.php
-
message: "#^Method PHPStan\\\\Rules\\\\BooleansInConditions\\\\BooleanInElseIfConditionRuleTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#"
count: 1
path: tests/Rules/BooleansInConditions/BooleanInElseIfConditionRuleTest.php
-
message: "#^Class PHPStan\\\\Rules\\\\BooleansInConditions\\\\BooleanInIfConditionRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#"
count: 1
path: tests/Rules/BooleansInConditions/BooleanInIfConditionRuleTest.php
-
message: "#^Method PHPStan\\\\Rules\\\\BooleansInConditions\\\\BooleanInIfConditionRuleTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#"
count: 1
path: tests/Rules/BooleansInConditions/BooleanInIfConditionRuleTest.php
-
message: "#^Class PHPStan\\\\Rules\\\\BooleansInConditions\\\\BooleanInTernaryOperatorRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#"
count: 1
path: tests/Rules/BooleansInConditions/BooleanInTernaryOperatorRuleTest.php
-
message: "#^Method PHPStan\\\\Rules\\\\BooleansInConditions\\\\BooleanInTernaryOperatorRuleTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#"
count: 1
path: tests/Rules/BooleansInConditions/BooleanInTernaryOperatorRuleTest.php
-
message: "#^Class PHPStan\\\\Rules\\\\Cast\\\\UselessCastRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#"
count: 1
path: tests/Rules/Cast/UselessCastRuleTest.php
-
message: "#^Method PHPStan\\\\Rules\\\\Cast\\\\UselessCastRuleTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#"
count: 1
path: tests/Rules/Cast/UselessCastRuleTest.php
-
message: "#^Class PHPStan\\\\Rules\\\\Classes\\\\RequireParentConstructCallRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#"
count: 1
path: tests/Rules/Classes/RequireParentConstructCallRuleTest.php
-
message: "#^Method PHPStan\\\\Rules\\\\Classes\\\\RequireParentConstructCallRuleTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#"
count: 1
path: tests/Rules/Classes/RequireParentConstructCallRuleTest.php
-
message: "#^Class PHPStan\\\\Rules\\\\DisallowedConstructs\\\\DisallowedBacktickRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#"
count: 1
path: tests/Rules/DisallowedConstructs/DisallowedBacktickRuleTest.php
-
message: "#^Method PHPStan\\\\Rules\\\\DisallowedConstructs\\\\DisallowedBacktickRuleTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#"
count: 1
path: tests/Rules/DisallowedConstructs/DisallowedBacktickRuleTest.php
-
message: "#^Class PHPStan\\\\Rules\\\\DisallowedConstructs\\\\DisallowedEmptyRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#"
count: 1
path: tests/Rules/DisallowedConstructs/DisallowedEmptyRuleTest.php
-
message: "#^Method PHPStan\\\\Rules\\\\DisallowedConstructs\\\\DisallowedEmptyRuleTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#"
count: 1
path: tests/Rules/DisallowedConstructs/DisallowedEmptyRuleTest.php
-
message: "#^Class PHPStan\\\\Rules\\\\DisallowedConstructs\\\\DisallowedImplicitArrayCreationRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#"
count: 1
path: tests/Rules/DisallowedConstructs/DisallowedImplicitArrayCreationRuleTest.php
-
message: "#^Method PHPStan\\\\Rules\\\\DisallowedConstructs\\\\DisallowedImplicitArrayCreationRuleTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#"
count: 1
path: tests/Rules/DisallowedConstructs/DisallowedImplicitArrayCreationRuleTest.php
-
message: "#^Class PHPStan\\\\Rules\\\\ForeachLoop\\\\OverwriteVariablesWithForeachRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#"
count: 1
path: tests/Rules/ForeachLoop/OverwriteVariablesWithForeachRuleTest.php
-
message: "#^Method PHPStan\\\\Rules\\\\ForeachLoop\\\\OverwriteVariablesWithForeachRuleTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#"
count: 1
path: tests/Rules/ForeachLoop/OverwriteVariablesWithForeachRuleTest.php
-
message: "#^Class PHPStan\\\\Rules\\\\Methods\\\\WrongCaseOfInheritedMethodRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#"
count: 1
path: tests/Rules/Methods/WrongCaseOfInheritedMethodRuleTest.php
-
message: "#^Method PHPStan\\\\Rules\\\\Methods\\\\WrongCaseOfInheritedMethodRuleTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#"
count: 1
path: tests/Rules/Methods/WrongCaseOfInheritedMethodRuleTest.php
-
message: "#^Class PHPStan\\\\Rules\\\\Operators\\\\OperandInArithmeticIncrementOrDecrementRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#"
count: 1
path: tests/Rules/Operators/OperandInArithmeticIncrementOrDecrementRuleTest.php
-
message: "#^Method PHPStan\\\\Rules\\\\Operators\\\\OperandInArithmeticIncrementOrDecrementRuleTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#"
count: 1
path: tests/Rules/Operators/OperandInArithmeticIncrementOrDecrementRuleTest.php
-
message: "#^Method PHPStan\\\\Rules\\\\Operators\\\\OperandInArithmeticIncrementOrDecrementRuleTest\\:\\:createRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#"
count: 1
path: tests/Rules/Operators/OperandInArithmeticIncrementOrDecrementRuleTest.php
-
message: "#^Method PHPStan\\\\Rules\\\\Operators\\\\OperandInArithmeticPostDecrementRuleTest\\:\\:createRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#"
count: 1
path: tests/Rules/Operators/OperandInArithmeticPostDecrementRuleTest.php
-
message: "#^Method PHPStan\\\\Rules\\\\Operators\\\\OperandInArithmeticPostIncrementRuleTest\\:\\:createRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#"
count: 1
path: tests/Rules/Operators/OperandInArithmeticPostIncrementRuleTest.php
-
message: "#^Method PHPStan\\\\Rules\\\\Operators\\\\OperandInArithmeticPreDecrementRuleTest\\:\\:createRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#"
count: 1
path: tests/Rules/Operators/OperandInArithmeticPreDecrementRuleTest.php
-
message: "#^Method PHPStan\\\\Rules\\\\Operators\\\\OperandInArithmeticPreIncrementRuleTest\\:\\:createRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#"
count: 1
path: tests/Rules/Operators/OperandInArithmeticPreIncrementRuleTest.php
-
message: "#^Class PHPStan\\\\Rules\\\\Operators\\\\OperandsInArithmeticAdditionRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#"
count: 1
path: tests/Rules/Operators/OperandsInArithmeticAdditionRuleTest.php
-
message: "#^Method PHPStan\\\\Rules\\\\Operators\\\\OperandsInArithmeticAdditionRuleTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#"
count: 1
path: tests/Rules/Operators/OperandsInArithmeticAdditionRuleTest.php
-
message: "#^Class PHPStan\\\\Rules\\\\Operators\\\\OperandsInArithmeticDivisionRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#"
count: 1
path: tests/Rules/Operators/OperandsInArithmeticDivisionRuleTest.php
-
message: "#^Method PHPStan\\\\Rules\\\\Operators\\\\OperandsInArithmeticDivisionRuleTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#"
count: 1
path: tests/Rules/Operators/OperandsInArithmeticDivisionRuleTest.php
-
message: "#^Class PHPStan\\\\Rules\\\\Operators\\\\OperandsInArithmeticExponentiationRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#"
count: 1
path: tests/Rules/Operators/OperandsInArithmeticExponentiationRuleTest.php
-
message: "#^Method PHPStan\\\\Rules\\\\Operators\\\\OperandsInArithmeticExponentiationRuleTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#"
count: 1
path: tests/Rules/Operators/OperandsInArithmeticExponentiationRuleTest.php
-
message: "#^Class PHPStan\\\\Rules\\\\Operators\\\\OperandsInArithmeticModuloRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#"
count: 1
path: tests/Rules/Operators/OperandsInArithmeticModuloRuleTest.php
-
message: "#^Method PHPStan\\\\Rules\\\\Operators\\\\OperandsInArithmeticModuloRuleTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#"
count: 1
path: tests/Rules/Operators/OperandsInArithmeticModuloRuleTest.php
-
message: "#^Class PHPStan\\\\Rules\\\\Operators\\\\OperandsInArithmeticMultiplicationRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#"
count: 1
path: tests/Rules/Operators/OperandsInArithmeticMultiplicationRuleTest.php
-
message: "#^Method PHPStan\\\\Rules\\\\Operators\\\\OperandsInArithmeticMultiplicationRuleTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#"
count: 1
path: tests/Rules/Operators/OperandsInArithmeticMultiplicationRuleTest.php
-
message: "#^Class PHPStan\\\\Rules\\\\Operators\\\\OperandsInArithmeticSubtractionRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#"
count: 1
path: tests/Rules/Operators/OperandsInArithmeticSubtractionRuleTest.php
-
message: "#^Method PHPStan\\\\Rules\\\\Operators\\\\OperandsInArithmeticSubtractionRuleTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#"
count: 1
path: tests/Rules/Operators/OperandsInArithmeticSubtractionRuleTest.php
-
message: "#^Class PHPStan\\\\Rules\\\\StrictCalls\\\\DynamicCallOnStaticMethodsRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#"
count: 1
path: tests/Rules/StrictCalls/DynamicCallOnStaticMethodsRuleTest.php
-
message: "#^Method PHPStan\\\\Rules\\\\StrictCalls\\\\DynamicCallOnStaticMethodsRuleTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#"
count: 1
path: tests/Rules/StrictCalls/DynamicCallOnStaticMethodsRuleTest.php
-
message: "#^Class PHPStan\\\\Rules\\\\StrictCalls\\\\StrictFunctionCallsRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#"
count: 1
path: tests/Rules/StrictCalls/StrictFunctionCallsRuleTest.php
-
message: "#^Method PHPStan\\\\Rules\\\\StrictCalls\\\\StrictFunctionCallsRuleTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#"
count: 1
path: tests/Rules/StrictCalls/StrictFunctionCallsRuleTest.php
-
message: "#^Class PHPStan\\\\Rules\\\\VariableVariables\\\\VariableMethodCallRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#"
count: 1
path: tests/Rules/VariableVariables/VariableMethodCallRuleTest.php
-
message: "#^Method PHPStan\\\\Rules\\\\VariableVariables\\\\VariableMethodCallRuleTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#"
count: 1
path: tests/Rules/VariableVariables/VariableMethodCallRuleTest.php
-
message: "#^Class PHPStan\\\\Rules\\\\VariableVariables\\\\VariablePropertyFetchRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#"
count: 1
path: tests/Rules/VariableVariables/VariablePropertyFetchRuleTest.php
-
message: "#^Method PHPStan\\\\Rules\\\\VariableVariables\\\\VariablePropertyFetchRuleTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#"
count: 1
path: tests/Rules/VariableVariables/VariablePropertyFetchRuleTest.php
-
message: "#^Class PHPStan\\\\Rules\\\\VariableVariables\\\\VariableStaticMethodCallRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#"
count: 1
path: tests/Rules/VariableVariables/VariableStaticMethodCallRuleTest.php
-
message: "#^Method PHPStan\\\\Rules\\\\VariableVariables\\\\VariableStaticMethodCallRuleTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#"
count: 1
path: tests/Rules/VariableVariables/VariableStaticMethodCallRuleTest.php
-
message: "#^Class PHPStan\\\\Rules\\\\VariableVariables\\\\VariableStaticPropertyFetchRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#"
count: 1
path: tests/Rules/VariableVariables/VariableStaticPropertyFetchRuleTest.php
-
message: "#^Method PHPStan\\\\Rules\\\\VariableVariables\\\\VariableStaticPropertyFetchRuleTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#"
count: 1
path: tests/Rules/VariableVariables/VariableStaticPropertyFetchRuleTest.php
-
message: "#^Class PHPStan\\\\Rules\\\\VariableVariables\\\\VariableVariablesRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#"
count: 1
path: tests/Rules/VariableVariables/VariableVariablesRuleTest.php
-
message: "#^Method PHPStan\\\\Rules\\\\VariableVariables\\\\VariableVariablesRuleTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#"
count: 1
path: tests/Rules/VariableVariables/VariableVariablesRuleTest.php

View File

@@ -0,0 +1,263 @@
parameters:
polluteScopeWithLoopInitialAssignments: false
polluteScopeWithAlwaysIterableForeach: false
checkAlwaysTrueCheckTypeFunctionCall: true
checkAlwaysTrueInstanceof: true
checkAlwaysTrueStrictComparison: true
checkAlwaysTrueLooseComparison: true
checkDynamicProperties: %featureToggles.bleedingEdge%
checkExplicitMixedMissingReturn: true
checkFunctionNameCase: true
checkInternalClassCaseSensitivity: true
reportMaybesInMethodSignatures: true
reportStaticMethodSignatures: true
reportMaybesInPropertyPhpDocTypes: true
reportWrongPhpDocTypeInVarTag: %featureToggles.bleedingEdge%
featureToggles:
illegalConstructorMethodCall: %featureToggles.bleedingEdge%
strictRules:
allRules: true
disallowedLooseComparison: [%strictRules.allRules%, %featureToggles.bleedingEdge%]
booleansInConditions: %strictRules.allRules%
uselessCast: %strictRules.allRules%
requireParentConstructorCall: %strictRules.allRules%
disallowedConstructs: %strictRules.allRules%
overwriteVariablesWithLoop: %strictRules.allRules%
closureUsesThis: %strictRules.allRules%
matchingInheritedMethodNames: %strictRules.allRules%
numericOperandsInArithmeticOperators: %strictRules.allRules%
strictCalls: %strictRules.allRules%
switchConditionsMatchingType: %strictRules.allRules%
noVariableVariables: %strictRules.allRules%
parametersSchema:
strictRules: structure([
allRules: anyOf(bool(), arrayOf(bool())),
disallowedLooseComparison: anyOf(bool(), arrayOf(bool())),
booleansInConditions: anyOf(bool(), arrayOf(bool()))
uselessCast: anyOf(bool(), arrayOf(bool()))
requireParentConstructorCall: anyOf(bool(), arrayOf(bool()))
disallowedConstructs: anyOf(bool(), arrayOf(bool()))
overwriteVariablesWithLoop: anyOf(bool(), arrayOf(bool()))
closureUsesThis: anyOf(bool(), arrayOf(bool()))
matchingInheritedMethodNames: anyOf(bool(), arrayOf(bool()))
numericOperandsInArithmeticOperators: anyOf(bool(), arrayOf(bool()))
strictCalls: anyOf(bool(), arrayOf(bool()))
switchConditionsMatchingType: anyOf(bool(), arrayOf(bool()))
noVariableVariables: anyOf(bool(), arrayOf(bool()))
])
conditionalTags:
PHPStan\Rules\DisallowedConstructs\DisallowedLooseComparisonRule:
phpstan.rules.rule: %strictRules.disallowedLooseComparison%
PHPStan\Rules\BooleansInConditions\BooleanInBooleanAndRule:
phpstan.rules.rule: %strictRules.booleansInConditions%
PHPStan\Rules\BooleansInConditions\BooleanInBooleanNotRule:
phpstan.rules.rule: %strictRules.booleansInConditions%
PHPStan\Rules\BooleansInConditions\BooleanInBooleanOrRule:
phpstan.rules.rule: %strictRules.booleansInConditions%
PHPStan\Rules\BooleansInConditions\BooleanInElseIfConditionRule:
phpstan.rules.rule: %strictRules.booleansInConditions%
PHPStan\Rules\BooleansInConditions\BooleanInIfConditionRule:
phpstan.rules.rule: %strictRules.booleansInConditions%
PHPStan\Rules\BooleansInConditions\BooleanInTernaryOperatorRule:
phpstan.rules.rule: %strictRules.booleansInConditions%
PHPStan\Rules\Cast\UselessCastRule:
phpstan.rules.rule: %strictRules.uselessCast%
PHPStan\Rules\Classes\RequireParentConstructCallRule:
phpstan.rules.rule: %strictRules.requireParentConstructorCall%
PHPStan\Rules\DisallowedConstructs\DisallowedBacktickRule:
phpstan.rules.rule: %strictRules.disallowedConstructs%
PHPStan\Rules\DisallowedConstructs\DisallowedEmptyRule:
phpstan.rules.rule: %strictRules.disallowedConstructs%
PHPStan\Rules\DisallowedConstructs\DisallowedImplicitArrayCreationRule:
phpstan.rules.rule: %strictRules.disallowedConstructs%
PHPStan\Rules\DisallowedConstructs\DisallowedShortTernaryRule:
phpstan.rules.rule: %strictRules.disallowedConstructs%
PHPStan\Rules\ForeachLoop\OverwriteVariablesWithForeachRule:
phpstan.rules.rule: %strictRules.overwriteVariablesWithLoop%
PHPStan\Rules\ForLoop\OverwriteVariablesWithForLoopInitRule:
phpstan.rules.rule: %strictRules.overwriteVariablesWithLoop%
PHPStan\Rules\Functions\ClosureUsesThisRule:
phpstan.rules.rule: %strictRules.closureUsesThis%
PHPStan\Rules\Methods\WrongCaseOfInheritedMethodRule:
phpstan.rules.rule: %strictRules.matchingInheritedMethodNames%
PHPStan\Rules\Operators\OperandInArithmeticPostDecrementRule:
phpstan.rules.rule: %strictRules.numericOperandsInArithmeticOperators%
PHPStan\Rules\Operators\OperandInArithmeticPostIncrementRule:
phpstan.rules.rule: %strictRules.numericOperandsInArithmeticOperators%
PHPStan\Rules\Operators\OperandInArithmeticPreDecrementRule:
phpstan.rules.rule: %strictRules.numericOperandsInArithmeticOperators%
PHPStan\Rules\Operators\OperandInArithmeticPreIncrementRule:
phpstan.rules.rule: %strictRules.numericOperandsInArithmeticOperators%
PHPStan\Rules\Operators\OperandsInArithmeticAdditionRule:
phpstan.rules.rule: %strictRules.numericOperandsInArithmeticOperators%
PHPStan\Rules\Operators\OperandsInArithmeticDivisionRule:
phpstan.rules.rule: %strictRules.numericOperandsInArithmeticOperators%
PHPStan\Rules\Operators\OperandsInArithmeticExponentiationRule:
phpstan.rules.rule: %strictRules.numericOperandsInArithmeticOperators%
PHPStan\Rules\Operators\OperandsInArithmeticModuloRule:
phpstan.rules.rule: %strictRules.numericOperandsInArithmeticOperators%
PHPStan\Rules\Operators\OperandsInArithmeticMultiplicationRule:
phpstan.rules.rule: %strictRules.numericOperandsInArithmeticOperators%
PHPStan\Rules\Operators\OperandsInArithmeticSubtractionRule:
phpstan.rules.rule: %strictRules.numericOperandsInArithmeticOperators%
PHPStan\Rules\StrictCalls\DynamicCallOnStaticMethodsRule:
phpstan.rules.rule: %strictRules.strictCalls%
PHPStan\Rules\StrictCalls\DynamicCallOnStaticMethodsCallableRule:
phpstan.rules.rule: %strictRules.strictCalls%
PHPStan\Rules\StrictCalls\StrictFunctionCallsRule:
phpstan.rules.rule: %strictRules.strictCalls%
PHPStan\Rules\SwitchConditions\MatchingTypeInSwitchCaseConditionRule:
phpstan.rules.rule: %strictRules.switchConditionsMatchingType%
PHPStan\Rules\VariableVariables\VariableMethodCallRule:
phpstan.rules.rule: %strictRules.noVariableVariables%
PHPStan\Rules\VariableVariables\VariableMethodCallableRule:
phpstan.rules.rule: %strictRules.noVariableVariables%
PHPStan\Rules\VariableVariables\VariableStaticMethodCallRule:
phpstan.rules.rule: %strictRules.noVariableVariables%
PHPStan\Rules\VariableVariables\VariableStaticMethodCallableRule:
phpstan.rules.rule: %strictRules.noVariableVariables%
PHPStan\Rules\VariableVariables\VariableStaticPropertyFetchRule:
phpstan.rules.rule: %strictRules.noVariableVariables%
PHPStan\Rules\VariableVariables\VariableVariablesRule:
phpstan.rules.rule: %strictRules.noVariableVariables%
PHPStan\Rules\VariableVariables\VariablePropertyFetchRule:
phpstan.rules.rule: %strictRules.noVariableVariables%
services:
-
class: PHPStan\Rules\BooleansInConditions\BooleanRuleHelper
-
class: PHPStan\Rules\Operators\OperatorRuleHelper
-
class: PHPStan\Rules\VariableVariables\VariablePropertyFetchRule
arguments:
universalObjectCratesClasses: %universalObjectCratesClasses%
-
class: PHPStan\Rules\DisallowedConstructs\DisallowedLooseComparisonRule
-
class: PHPStan\Rules\BooleansInConditions\BooleanInBooleanAndRule
-
class: PHPStan\Rules\BooleansInConditions\BooleanInBooleanNotRule
-
class: PHPStan\Rules\BooleansInConditions\BooleanInBooleanOrRule
-
class: PHPStan\Rules\BooleansInConditions\BooleanInElseIfConditionRule
-
class: PHPStan\Rules\BooleansInConditions\BooleanInIfConditionRule
-
class: PHPStan\Rules\BooleansInConditions\BooleanInTernaryOperatorRule
-
class: PHPStan\Rules\Cast\UselessCastRule
arguments:
treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain%
-
class: PHPStan\Rules\Classes\RequireParentConstructCallRule
-
class: PHPStan\Rules\DisallowedConstructs\DisallowedBacktickRule
-
class: PHPStan\Rules\DisallowedConstructs\DisallowedEmptyRule
-
class: PHPStan\Rules\DisallowedConstructs\DisallowedImplicitArrayCreationRule
-
class: PHPStan\Rules\DisallowedConstructs\DisallowedShortTernaryRule
-
class: PHPStan\Rules\ForeachLoop\OverwriteVariablesWithForeachRule
-
class: PHPStan\Rules\ForLoop\OverwriteVariablesWithForLoopInitRule
-
class: PHPStan\Rules\Functions\ClosureUsesThisRule
-
class: PHPStan\Rules\Methods\WrongCaseOfInheritedMethodRule
-
class: PHPStan\Rules\Operators\OperandInArithmeticPostDecrementRule
-
class: PHPStan\Rules\Operators\OperandInArithmeticPostIncrementRule
-
class: PHPStan\Rules\Operators\OperandInArithmeticPreDecrementRule
-
class: PHPStan\Rules\Operators\OperandInArithmeticPreIncrementRule
-
class: PHPStan\Rules\Operators\OperandsInArithmeticAdditionRule
arguments:
bleedingEdge: %featureToggles.bleedingEdge%
-
class: PHPStan\Rules\Operators\OperandsInArithmeticDivisionRule
arguments:
bleedingEdge: %featureToggles.bleedingEdge%
-
class: PHPStan\Rules\Operators\OperandsInArithmeticExponentiationRule
arguments:
bleedingEdge: %featureToggles.bleedingEdge%
-
class: PHPStan\Rules\Operators\OperandsInArithmeticModuloRule
arguments:
bleedingEdge: %featureToggles.bleedingEdge%
-
class: PHPStan\Rules\Operators\OperandsInArithmeticMultiplicationRule
arguments:
bleedingEdge: %featureToggles.bleedingEdge%
-
class: PHPStan\Rules\Operators\OperandsInArithmeticSubtractionRule
arguments:
bleedingEdge: %featureToggles.bleedingEdge%
-
class: PHPStan\Rules\StrictCalls\DynamicCallOnStaticMethodsRule
-
class: PHPStan\Rules\StrictCalls\DynamicCallOnStaticMethodsCallableRule
-
class: PHPStan\Rules\StrictCalls\StrictFunctionCallsRule
-
class: PHPStan\Rules\SwitchConditions\MatchingTypeInSwitchCaseConditionRule
-
class: PHPStan\Rules\VariableVariables\VariableMethodCallRule
-
class: PHPStan\Rules\VariableVariables\VariableMethodCallableRule
-
class: PHPStan\Rules\VariableVariables\VariableStaticMethodCallRule
-
class: PHPStan\Rules\VariableVariables\VariableStaticMethodCallableRule
-
class: PHPStan\Rules\VariableVariables\VariableStaticPropertyFetchRule
-
class: PHPStan\Rules\VariableVariables\VariableVariablesRule

View File

@@ -0,0 +1,55 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\BooleansInConditions;
use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Node\BooleanAndNode;
use PHPStan\Rules\Rule;
use PHPStan\Type\VerbosityLevel;
use function sprintf;
/**
* @implements Rule<BooleanAndNode>
*/
class BooleanInBooleanAndRule implements Rule
{
/** @var BooleanRuleHelper */
private $helper;
public function __construct(BooleanRuleHelper $helper)
{
$this->helper = $helper;
}
public function getNodeType(): string
{
return BooleanAndNode::class;
}
public function processNode(Node $node, Scope $scope): array
{
$originalNode = $node->getOriginalNode();
$messages = [];
if (!$this->helper->passesAsBoolean($scope, $originalNode->left)) {
$leftType = $scope->getType($originalNode->left);
$messages[] = sprintf(
'Only booleans are allowed in &&, %s given on the left side.',
$leftType->describe(VerbosityLevel::typeOnly())
);
}
$rightScope = $node->getRightScope();
if (!$this->helper->passesAsBoolean($rightScope, $originalNode->right)) {
$rightType = $rightScope->getType($originalNode->right);
$messages[] = sprintf(
'Only booleans are allowed in &&, %s given on the right side.',
$rightType->describe(VerbosityLevel::typeOnly())
);
}
return $messages;
}
}

View File

@@ -0,0 +1,48 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\BooleansInConditions;
use PhpParser\Node;
use PhpParser\Node\Expr\BooleanNot;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Type\VerbosityLevel;
use function sprintf;
class BooleanInBooleanNotRule implements Rule
{
/** @var BooleanRuleHelper */
private $helper;
public function __construct(BooleanRuleHelper $helper)
{
$this->helper = $helper;
}
public function getNodeType(): string
{
return BooleanNot::class;
}
/**
* @param BooleanNot $node
* @return string[] errors
*/
public function processNode(Node $node, Scope $scope): array
{
if ($this->helper->passesAsBoolean($scope, $node->expr)) {
return [];
}
$expressionType = $scope->getType($node->expr);
return [
sprintf(
'Only booleans are allowed in a negated boolean, %s given.',
$expressionType->describe(VerbosityLevel::typeOnly())
),
];
}
}

View File

@@ -0,0 +1,55 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\BooleansInConditions;
use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Node\BooleanOrNode;
use PHPStan\Rules\Rule;
use PHPStan\Type\VerbosityLevel;
use function sprintf;
/**
* @implements Rule<BooleanOrNode>
*/
class BooleanInBooleanOrRule implements Rule
{
/** @var BooleanRuleHelper */
private $helper;
public function __construct(BooleanRuleHelper $helper)
{
$this->helper = $helper;
}
public function getNodeType(): string
{
return BooleanOrNode::class;
}
public function processNode(Node $node, Scope $scope): array
{
$originalNode = $node->getOriginalNode();
$messages = [];
if (!$this->helper->passesAsBoolean($scope, $originalNode->left)) {
$leftType = $scope->getType($originalNode->left);
$messages[] = sprintf(
'Only booleans are allowed in ||, %s given on the left side.',
$leftType->describe(VerbosityLevel::typeOnly())
);
}
$rightScope = $node->getRightScope();
if (!$this->helper->passesAsBoolean($rightScope, $originalNode->right)) {
$rightType = $rightScope->getType($originalNode->right);
$messages[] = sprintf(
'Only booleans are allowed in ||, %s given on the right side.',
$rightType->describe(VerbosityLevel::typeOnly())
);
}
return $messages;
}
}

View File

@@ -0,0 +1,48 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\BooleansInConditions;
use PhpParser\Node;
use PhpParser\Node\Stmt\ElseIf_;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Type\VerbosityLevel;
use function sprintf;
class BooleanInElseIfConditionRule implements Rule
{
/** @var BooleanRuleHelper */
private $helper;
public function __construct(BooleanRuleHelper $helper)
{
$this->helper = $helper;
}
public function getNodeType(): string
{
return ElseIf_::class;
}
/**
* @param ElseIf_ $node
* @return string[] errors
*/
public function processNode(Node $node, Scope $scope): array
{
if ($this->helper->passesAsBoolean($scope, $node->cond)) {
return [];
}
$conditionExpressionType = $scope->getType($node->cond);
return [
sprintf(
'Only booleans are allowed in an elseif condition, %s given.',
$conditionExpressionType->describe(VerbosityLevel::typeOnly())
),
];
}
}

View File

@@ -0,0 +1,48 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\BooleansInConditions;
use PhpParser\Node;
use PhpParser\Node\Stmt\If_;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Type\VerbosityLevel;
use function sprintf;
class BooleanInIfConditionRule implements Rule
{
/** @var BooleanRuleHelper */
private $helper;
public function __construct(BooleanRuleHelper $helper)
{
$this->helper = $helper;
}
public function getNodeType(): string
{
return If_::class;
}
/**
* @param If_ $node
* @return string[] errors
*/
public function processNode(Node $node, Scope $scope): array
{
if ($this->helper->passesAsBoolean($scope, $node->cond)) {
return [];
}
$conditionExpressionType = $scope->getType($node->cond);
return [
sprintf(
'Only booleans are allowed in an if condition, %s given.',
$conditionExpressionType->describe(VerbosityLevel::typeOnly())
),
];
}
}

View File

@@ -0,0 +1,52 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\BooleansInConditions;
use PhpParser\Node;
use PhpParser\Node\Expr\Ternary;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Type\VerbosityLevel;
use function sprintf;
class BooleanInTernaryOperatorRule implements Rule
{
/** @var BooleanRuleHelper */
private $helper;
public function __construct(BooleanRuleHelper $helper)
{
$this->helper = $helper;
}
public function getNodeType(): string
{
return Ternary::class;
}
/**
* @param Ternary $node
* @return string[] errors
*/
public function processNode(Node $node, Scope $scope): array
{
if ($node->if === null) {
return []; // elvis ?:
}
if ($this->helper->passesAsBoolean($scope, $node->cond)) {
return [];
}
$conditionExpressionType = $scope->getType($node->cond);
return [
sprintf(
'Only booleans are allowed in a ternary operator condition, %s given.',
$conditionExpressionType->describe(VerbosityLevel::typeOnly())
),
];
}
}

View File

@@ -0,0 +1,45 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\BooleansInConditions;
use PhpParser\Node\Expr;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\RuleLevelHelper;
use PHPStan\Type\ErrorType;
use PHPStan\Type\MixedType;
use PHPStan\Type\Type;
class BooleanRuleHelper
{
/** @var RuleLevelHelper */
private $ruleLevelHelper;
public function __construct(RuleLevelHelper $ruleLevelHelper)
{
$this->ruleLevelHelper = $ruleLevelHelper;
}
public function passesAsBoolean(Scope $scope, Expr $expr): bool
{
$type = $scope->getType($expr);
if ($type instanceof MixedType) {
return !$type->isExplicitMixed();
}
$typeToCheck = $this->ruleLevelHelper->findTypeToCheck(
$scope,
$expr,
'',
static function (Type $type): bool {
return $type->isBoolean()->yes();
}
);
$foundType = $typeToCheck->getType();
if ($foundType instanceof ErrorType) {
return true;
}
return $foundType->isBoolean()->yes();
}
}

View File

@@ -0,0 +1,74 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Cast;
use PhpParser\Node;
use PhpParser\Node\Expr\Cast;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleError;
use PHPStan\Rules\RuleErrorBuilder;
use PHPStan\Type\ErrorType;
use PHPStan\Type\GeneralizePrecision;
use PHPStan\Type\VerbosityLevel;
use function sprintf;
class UselessCastRule implements Rule
{
/** @var bool */
private $treatPhpDocTypesAsCertain;
public function __construct(bool $treatPhpDocTypesAsCertain)
{
$this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain;
}
public function getNodeType(): string
{
return Cast::class;
}
/**
* @param Cast $node
* @return RuleError[] errors
*/
public function processNode(Node $node, Scope $scope): array
{
$castType = $scope->getType($node);
if ($castType instanceof ErrorType) {
return [];
}
$castType = $castType->generalize(GeneralizePrecision::lessSpecific());
if ($this->treatPhpDocTypesAsCertain) {
$expressionType = $scope->getType($node->expr);
} else {
$expressionType = $scope->getNativeType($node->expr);
}
if ($castType->isSuperTypeOf($expressionType)->yes()) {
$addTip = function (RuleErrorBuilder $ruleErrorBuilder) use ($scope, $node, $castType): RuleErrorBuilder {
if (!$this->treatPhpDocTypesAsCertain) {
return $ruleErrorBuilder;
}
$expressionTypeWithoutPhpDoc = $scope->getNativeType($node->expr);
if ($castType->isSuperTypeOf($expressionTypeWithoutPhpDoc)->yes()) {
return $ruleErrorBuilder;
}
return $ruleErrorBuilder->tip('Because the type is coming from a PHPDoc, you can turn off this check by setting <fg=cyan>treatPhpDocTypesAsCertain: false</> in your <fg=cyan>%configurationFile%</>.');
};
return [
$addTip(RuleErrorBuilder::message(sprintf(
'Casting to %s something that\'s already %s.',
$castType->describe(VerbosityLevel::typeOnly()),
$expressionType->describe(VerbosityLevel::typeOnly())
)))->build(),
];
}
return [];
}
}

View File

@@ -0,0 +1,157 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Classes;
use PhpParser\Node;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt\ClassMethod;
use PHPStan\Analyser\Scope;
use PHPStan\BetterReflection\Reflection\Adapter\ReflectionClass;
use PHPStan\BetterReflection\Reflection\Adapter\ReflectionEnum;
use PHPStan\Rules\Rule;
use PHPStan\ShouldNotHappenException;
use function property_exists;
use function sprintf;
class RequireParentConstructCallRule implements Rule
{
public function getNodeType(): string
{
return ClassMethod::class;
}
/**
* @param ClassMethod $node
* @return string[]
*/
public function processNode(Node $node, Scope $scope): array
{
if (!$scope->isInClass()) {
throw new ShouldNotHappenException();
}
if ($scope->isInTrait()) {
return [];
}
if ($node->name->name !== '__construct') {
return [];
}
if ($node->isAbstract()) {
return [];
}
$classReflection = $scope->getClassReflection()->getNativeReflection();
if ($classReflection->isInterface() || $classReflection->isAnonymous()) {
return [];
}
if ($this->callsParentConstruct($node)) {
if ($classReflection->getParentClass() === false) {
return [
sprintf(
'%s::__construct() calls parent constructor but does not extend any class.',
$classReflection->getName()
),
];
}
if ($this->getParentConstructorClass($classReflection) === false) {
return [
sprintf(
'%s::__construct() calls parent constructor but parent does not have one.',
$classReflection->getName()
),
];
}
} else {
$parentClass = $this->getParentConstructorClass($classReflection);
if ($parentClass !== false) {
return [
sprintf(
'%s::__construct() does not call parent constructor from %s.',
$classReflection->getName(),
$parentClass->getName()
),
];
}
}
return [];
}
private function callsParentConstruct(Node $parserNode): bool
{
if (!property_exists($parserNode, 'stmts')) {
return false;
}
foreach ($parserNode->stmts as $statement) {
if ($statement instanceof Node\Stmt\Expression) {
$statement = $statement->expr;
}
$statement = $this->ignoreErrorSuppression($statement);
if ($statement instanceof StaticCall) {
if (
$statement->class instanceof Name
&& ((string) $statement->class === 'parent')
&& $statement->name instanceof Node\Identifier
&& $statement->name->name === '__construct'
) {
return true;
}
} else {
if ($this->callsParentConstruct($statement)) {
return true;
}
}
}
return false;
}
/**
* @param ReflectionClass|ReflectionEnum $classReflection
* @return ReflectionClass|false
*/
private function getParentConstructorClass($classReflection)
{
while ($classReflection->getParentClass() !== false) {
$constructor = $classReflection->getParentClass()->hasMethod('__construct') ? $classReflection->getParentClass()->getMethod('__construct') : null;
$constructorWithClassName = $classReflection->getParentClass()->hasMethod($classReflection->getParentClass()->getName()) ? $classReflection->getParentClass()->getMethod($classReflection->getParentClass()->getName()) : null;
if (
(
$constructor !== null
&& $constructor->getDeclaringClass()->getName() === $classReflection->getParentClass()->getName()
&& !$constructor->isAbstract()
&& !$constructor->isPrivate()
) || (
$constructorWithClassName !== null
&& $constructorWithClassName->getDeclaringClass()->getName() === $classReflection->getParentClass()->getName()
&& !$constructorWithClassName->isAbstract()
)
) {
return $classReflection->getParentClass();
}
$classReflection = $classReflection->getParentClass();
}
return false;
}
private function ignoreErrorSuppression(Node $statement): Node
{
if ($statement instanceof Node\Expr\ErrorSuppress) {
return $statement->expr;
}
return $statement;
}
}

View File

@@ -0,0 +1,30 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\DisallowedConstructs;
use PhpParser\Node;
use PhpParser\Node\Expr\Empty_;
use PhpParser\Node\Expr\ShellExec;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
class DisallowedBacktickRule implements Rule
{
public function getNodeType(): string
{
return ShellExec::class;
}
/**
* @param Empty_ $node
* @return string[]
*/
public function processNode(Node $node, Scope $scope): array
{
return [
'Backtick operator is not allowed. Use shell_exec() instead.',
];
}
}

View File

@@ -0,0 +1,29 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\DisallowedConstructs;
use PhpParser\Node;
use PhpParser\Node\Expr\Empty_;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
class DisallowedEmptyRule implements Rule
{
public function getNodeType(): string
{
return Empty_::class;
}
/**
* @param Empty_ $node
* @return string[]
*/
public function processNode(Node $node, Scope $scope): array
{
return [
'Construct empty() is not allowed. Use more strict comparison.',
];
}
}

View File

@@ -0,0 +1,61 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\DisallowedConstructs;
use PhpParser\Node;
use PhpParser\Node\Expr\ArrayDimFetch;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\Variable;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use function is_string;
use function sprintf;
class DisallowedImplicitArrayCreationRule implements Rule
{
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 [];
}
$node = $node->var;
while ($node instanceof ArrayDimFetch) {
$node = $node->var;
}
if (!$node instanceof Variable) {
return [];
}
if (!is_string($node->name)) {
return [];
}
$certainty = $scope->hasVariableType($node->name);
if ($certainty->no()) {
return [
sprintf('Implicit array creation is not allowed - variable $%s does not exist.', $node->name),
];
}
if ($certainty->maybe()) {
return [
sprintf('Implicit array creation is not allowed - variable $%s might not exist.', $node->name),
];
}
return [];
}
}

View File

@@ -0,0 +1,44 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\DisallowedConstructs;
use PhpParser\Node;
use PhpParser\Node\Expr\BinaryOp;
use PhpParser\Node\Expr\BinaryOp\Equal;
use PhpParser\Node\Expr\BinaryOp\NotEqual;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;
/**
* @implements Rule<BinaryOp>
*/
class DisallowedLooseComparisonRule implements Rule
{
public function getNodeType(): string
{
return BinaryOp::class;
}
public function processNode(Node $node, Scope $scope): array
{
if ($node instanceof Equal) {
return [
RuleErrorBuilder::message(
'Loose comparison via "==" is not allowed.'
)->tip('Use strict comparison via "===" instead.')->build(),
];
}
if ($node instanceof NotEqual) {
return [
RuleErrorBuilder::message(
'Loose comparison via "!=" is not allowed.'
)->tip('Use strict comparison via "!==" instead.')->build(),
];
}
return [];
}
}

View File

@@ -0,0 +1,32 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\DisallowedConstructs;
use PhpParser\Node;
use PhpParser\Node\Expr\Ternary;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
/**
* @implements Rule<Ternary>
*/
class DisallowedShortTernaryRule implements Rule
{
public function getNodeType(): string
{
return Ternary::class;
}
public function processNode(Node $node, Scope $scope): array
{
if ($node->if !== null) {
return [];
}
return [
'Short ternary operator is not allowed. Use null coalesce operator if applicable or consider using long ternary.',
];
}
}

View File

@@ -0,0 +1,77 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\ForLoop;
use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Stmt\For_;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use function is_string;
use function sprintf;
/**
* @implements Rule<For_>
*/
class OverwriteVariablesWithForLoopInitRule implements Rule
{
public function getNodeType(): string
{
return For_::class;
}
/**
* @param For_ $node
* @return string[]
*/
public function processNode(Node $node, Scope $scope): array
{
$errors = [];
foreach ($node->init as $expr) {
if (!($expr instanceof Assign)) {
continue;
}
foreach ($this->checkValueVar($scope, $expr->var) as $error) {
$errors[] = $error;
}
}
return $errors;
}
/**
* @return string[]
*/
private function checkValueVar(Scope $scope, Expr $expr): array
{
$errors = [];
if (
$expr instanceof Node\Expr\Variable
&& is_string($expr->name)
&& $scope->hasVariableType($expr->name)->yes()
) {
$errors[] = sprintf('For loop initial assignment overwrites variable $%s.', $expr->name);
}
if (
$expr instanceof Node\Expr\List_
|| $expr instanceof Node\Expr\Array_
) {
foreach ($expr->items as $item) {
if ($item === null) {
continue;
}
foreach ($this->checkValueVar($scope, $item->value) as $error) {
$errors[] = $error;
}
}
}
return $errors;
}
}

View File

@@ -0,0 +1,75 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\ForeachLoop;
use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Stmt\Foreach_;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use function is_string;
use function sprintf;
class OverwriteVariablesWithForeachRule implements Rule
{
public function getNodeType(): string
{
return Node\Stmt\Foreach_::class;
}
/**
* @param Foreach_ $node
* @return string[]
*/
public function processNode(Node $node, Scope $scope): array
{
$errors = [];
if (
$node->keyVar instanceof Node\Expr\Variable
&& is_string($node->keyVar->name)
&& $scope->hasVariableType($node->keyVar->name)->yes()
) {
$errors[] = sprintf('Foreach overwrites $%s with its key variable.', $node->keyVar->name);
}
foreach ($this->checkValueVar($scope, $node->valueVar) as $error) {
$errors[] = $error;
}
return $errors;
}
/**
* @return string[]
*/
private function checkValueVar(Scope $scope, Expr $expr): array
{
$errors = [];
if (
$expr instanceof Node\Expr\Variable
&& is_string($expr->name)
&& $scope->hasVariableType($expr->name)->yes()
) {
$errors[] = sprintf('Foreach overwrites $%s with its value variable.', $expr->name);
}
if (
$expr instanceof Node\Expr\List_
|| $expr instanceof Node\Expr\Array_
) {
foreach ($expr->items as $item) {
if ($item === null) {
continue;
}
foreach ($this->checkValueVar($scope, $item->value) as $error) {
$errors[] = $error;
}
}
}
return $errors;
}
}

View File

@@ -0,0 +1,51 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Functions;
use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;
use PHPStan\Type\ThisType;
use function is_string;
use function sprintf;
/**
* @implements Rule<Node\Expr\Closure>
*/
class ClosureUsesThisRule implements Rule
{
public function getNodeType(): string
{
return Node\Expr\Closure::class;
}
public function processNode(Node $node, Scope $scope): array
{
if ($node->static) {
return [];
}
if ($scope->isInClosureBind()) {
return [];
}
$messages = [];
foreach ($node->uses as $closureUse) {
$varType = $scope->getType($closureUse->var);
if (!is_string($closureUse->var->name)) {
continue;
}
if (!$varType instanceof ThisType) {
continue;
}
$messages[] = RuleErrorBuilder::message(sprintf('Anonymous function uses $this assigned to variable $%s. Use $this directly in the function body.', $closureUse->var->name))
->line($closureUse->getLine())
->build();
}
return $messages;
}
}

View File

@@ -0,0 +1,87 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Methods;
use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Node\InClassMethodNode;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Rules\Rule;
use function sprintf;
/**
* @implements Rule<InClassMethodNode>
*/
class WrongCaseOfInheritedMethodRule implements Rule
{
public function getNodeType(): string
{
return InClassMethodNode::class;
}
public function processNode(
Node $node,
Scope $scope
): array
{
$methodReflection = $node->getMethodReflection();
$declaringClass = $methodReflection->getDeclaringClass();
$messages = [];
if ($declaringClass->getParentClass() !== null) {
$parentMessage = $this->findMethod(
$declaringClass,
$declaringClass->getParentClass(),
$methodReflection->getName()
);
if ($parentMessage !== null) {
$messages[] = $parentMessage;
}
}
foreach ($declaringClass->getInterfaces() as $interface) {
$interfaceMessage = $this->findMethod(
$declaringClass,
$interface,
$methodReflection->getName()
);
if ($interfaceMessage === null) {
continue;
}
/** @var string $interfaceMessage */
$interfaceMessage = $interfaceMessage;
$messages[] = $interfaceMessage;
}
return $messages;
}
private function findMethod(
ClassReflection $declaringClass,
ClassReflection $classReflection,
string $methodName
): ?string
{
if (!$classReflection->hasNativeMethod($methodName)) {
return null;
}
$parentMethod = $classReflection->getNativeMethod($methodName);
if ($parentMethod->getName() === $methodName) {
return null;
}
return sprintf(
'Method %s::%s() does not match %s method name: %s::%s().',
$declaringClass->getDisplayName(),
$methodName,
$classReflection->isInterface() ? 'interface' : 'parent',
$classReflection->getDisplayName(),
$parentMethod->getName()
);
}
}

View File

@@ -0,0 +1,57 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Operators;
use PhpParser\Node;
use PhpParser\Node\Expr\PostDec;
use PhpParser\Node\Expr\PostInc;
use PhpParser\Node\Expr\PreDec;
use PhpParser\Node\Expr\PreInc;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Type\VerbosityLevel;
use function sprintf;
/**
* @phpstan-template TNodeType of PreInc|PreDec|PostInc|PostDec
* @phpstan-implements Rule<TNodeType>
*/
abstract class OperandInArithmeticIncrementOrDecrementRule implements Rule
{
/** @var OperatorRuleHelper */
private $helper;
public function __construct(OperatorRuleHelper $helper)
{
$this->helper = $helper;
}
/**
* @param PreInc|PreDec|PostInc|PostDec $node
* @return string[] errors
*/
public function processNode(Node $node, Scope $scope): array
{
$messages = [];
$varType = $scope->getType($node->var);
if (
($node instanceof PreInc || $node instanceof PostInc)
&& !$this->helper->isValidForIncrement($scope, $node->var)
|| ($node instanceof PreDec || $node instanceof PostDec)
&& !$this->helper->isValidForDecrement($scope, $node->var)
) {
$messages[] = sprintf(
'Only numeric types are allowed in %s, %s given.',
$this->describeOperation(),
$varType->describe(VerbosityLevel::typeOnly())
);
}
return $messages;
}
abstract protected function describeOperation(): string;
}

View File

@@ -0,0 +1,23 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Operators;
use PhpParser\Node\Expr\PostDec;
/**
* @phpstan-extends OperandInArithmeticIncrementOrDecrementRule<PostDec>
*/
class OperandInArithmeticPostDecrementRule extends OperandInArithmeticIncrementOrDecrementRule
{
public function getNodeType(): string
{
return PostDec::class;
}
protected function describeOperation(): string
{
return 'post-decrement';
}
}

View File

@@ -0,0 +1,23 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Operators;
use PhpParser\Node\Expr\PostInc;
/**
* @phpstan-extends OperandInArithmeticIncrementOrDecrementRule<PostInc>
*/
class OperandInArithmeticPostIncrementRule extends OperandInArithmeticIncrementOrDecrementRule
{
public function getNodeType(): string
{
return PostInc::class;
}
protected function describeOperation(): string
{
return 'post-increment';
}
}

View File

@@ -0,0 +1,23 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Operators;
use PhpParser\Node\Expr\PreDec;
/**
* @phpstan-extends OperandInArithmeticIncrementOrDecrementRule<PreDec>
*/
class OperandInArithmeticPreDecrementRule extends OperandInArithmeticIncrementOrDecrementRule
{
public function getNodeType(): string
{
return PreDec::class;
}
protected function describeOperation(): string
{
return 'pre-decrement';
}
}

View File

@@ -0,0 +1,23 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Operators;
use PhpParser\Node\Expr\PreInc;
/**
* @phpstan-extends OperandInArithmeticIncrementOrDecrementRule<PreInc>
*/
class OperandInArithmeticPreIncrementRule extends OperandInArithmeticIncrementOrDecrementRule
{
public function getNodeType(): string
{
return PreInc::class;
}
protected function describeOperation(): string
{
return 'pre-increment';
}
}

View File

@@ -0,0 +1,73 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Operators;
use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\AssignOp\Plus as AssignOpPlus;
use PhpParser\Node\Expr\BinaryOp\Plus as BinaryOpPlus;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Type\VerbosityLevel;
use function count;
use function sprintf;
class OperandsInArithmeticAdditionRule implements Rule
{
/** @var OperatorRuleHelper */
private $helper;
/** @var bool */
private $bleedingEdge;
public function __construct(OperatorRuleHelper $helper, bool $bleedingEdge)
{
$this->helper = $helper;
$this->bleedingEdge = $bleedingEdge;
}
public function getNodeType(): string
{
return Expr::class;
}
/**
* @return string[] errors
*/
public function processNode(Node $node, Scope $scope): array
{
if ($node instanceof BinaryOpPlus) {
$left = $node->left;
$right = $node->right;
} elseif ($node instanceof AssignOpPlus && $this->bleedingEdge) {
$left = $node->var;
$right = $node->expr;
} else {
return [];
}
$leftType = $scope->getType($left);
$rightType = $scope->getType($right);
if (count($leftType->getArrays()) > 0 && count($rightType->getArrays()) > 0) {
return [];
}
$messages = [];
if (!$this->helper->isValidForArithmeticOperation($scope, $left)) {
$messages[] = sprintf(
'Only numeric types are allowed in +, %s given on the left side.',
$leftType->describe(VerbosityLevel::typeOnly())
);
}
if (!$this->helper->isValidForArithmeticOperation($scope, $right)) {
$messages[] = sprintf(
'Only numeric types are allowed in +, %s given on the right side.',
$rightType->describe(VerbosityLevel::typeOnly())
);
}
return $messages;
}
}

View File

@@ -0,0 +1,69 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Operators;
use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\AssignOp\Div as AssignOpDiv;
use PhpParser\Node\Expr\BinaryOp\Div as BinaryOpDiv;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Type\VerbosityLevel;
use function sprintf;
class OperandsInArithmeticDivisionRule implements Rule
{
/** @var OperatorRuleHelper */
private $helper;
/** @var bool */
private $bleedingEdge;
public function __construct(OperatorRuleHelper $helper, bool $bleedingEdge)
{
$this->helper = $helper;
$this->bleedingEdge = $bleedingEdge;
}
public function getNodeType(): string
{
return Expr::class;
}
/**
* @return string[] errors
*/
public function processNode(Node $node, Scope $scope): array
{
if ($node instanceof BinaryOpDiv) {
$left = $node->left;
$right = $node->right;
} elseif ($node instanceof AssignOpDiv && $this->bleedingEdge) {
$left = $node->var;
$right = $node->expr;
} else {
return [];
}
$messages = [];
$leftType = $scope->getType($left);
if (!$this->helper->isValidForArithmeticOperation($scope, $left)) {
$messages[] = sprintf(
'Only numeric types are allowed in /, %s given on the left side.',
$leftType->describe(VerbosityLevel::typeOnly())
);
}
$rightType = $scope->getType($right);
if (!$this->helper->isValidForArithmeticOperation($scope, $right)) {
$messages[] = sprintf(
'Only numeric types are allowed in /, %s given on the right side.',
$rightType->describe(VerbosityLevel::typeOnly())
);
}
return $messages;
}
}

View File

@@ -0,0 +1,69 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Operators;
use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\AssignOp\Pow as AssignOpPow;
use PhpParser\Node\Expr\BinaryOp\Pow as BinaryOpPow;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Type\VerbosityLevel;
use function sprintf;
class OperandsInArithmeticExponentiationRule implements Rule
{
/** @var OperatorRuleHelper */
private $helper;
/** @var bool */
private $bleedingEdge;
public function __construct(OperatorRuleHelper $helper, bool $bleedingEdge)
{
$this->helper = $helper;
$this->bleedingEdge = $bleedingEdge;
}
public function getNodeType(): string
{
return Expr::class;
}
/**
* @return string[] errors
*/
public function processNode(Node $node, Scope $scope): array
{
if ($node instanceof BinaryOpPow) {
$left = $node->left;
$right = $node->right;
} elseif ($node instanceof AssignOpPow && $this->bleedingEdge) {
$left = $node->var;
$right = $node->expr;
} else {
return [];
}
$messages = [];
$leftType = $scope->getType($left);
if (!$this->helper->isValidForArithmeticOperation($scope, $left)) {
$messages[] = sprintf(
'Only numeric types are allowed in **, %s given on the left side.',
$leftType->describe(VerbosityLevel::typeOnly())
);
}
$rightType = $scope->getType($right);
if (!$this->helper->isValidForArithmeticOperation($scope, $right)) {
$messages[] = sprintf(
'Only numeric types are allowed in **, %s given on the right side.',
$rightType->describe(VerbosityLevel::typeOnly())
);
}
return $messages;
}
}

View File

@@ -0,0 +1,69 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Operators;
use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\AssignOp\Mod as AssignOpMod;
use PhpParser\Node\Expr\BinaryOp\Mod as BinaryOpMod;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Type\VerbosityLevel;
use function sprintf;
class OperandsInArithmeticModuloRule implements Rule
{
/** @var OperatorRuleHelper */
private $helper;
/** @var bool */
private $bleedingEdge;
public function __construct(OperatorRuleHelper $helper, bool $bleedingEdge)
{
$this->helper = $helper;
$this->bleedingEdge = $bleedingEdge;
}
public function getNodeType(): string
{
return Expr::class;
}
/**
* @return string[] errors
*/
public function processNode(Node $node, Scope $scope): array
{
if ($node instanceof BinaryOpMod) {
$left = $node->left;
$right = $node->right;
} elseif ($node instanceof AssignOpMod && $this->bleedingEdge) {
$left = $node->var;
$right = $node->expr;
} else {
return [];
}
$messages = [];
$leftType = $scope->getType($left);
if (!$this->helper->isValidForArithmeticOperation($scope, $left)) {
$messages[] = sprintf(
'Only numeric types are allowed in %%, %s given on the left side.',
$leftType->describe(VerbosityLevel::typeOnly())
);
}
$rightType = $scope->getType($right);
if (!$this->helper->isValidForArithmeticOperation($scope, $right)) {
$messages[] = sprintf(
'Only numeric types are allowed in %%, %s given on the right side.',
$rightType->describe(VerbosityLevel::typeOnly())
);
}
return $messages;
}
}

View File

@@ -0,0 +1,69 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Operators;
use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\AssignOp\Mul as AssignOpMul;
use PhpParser\Node\Expr\BinaryOp\Mul as BinaryOpMul;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Type\VerbosityLevel;
use function sprintf;
class OperandsInArithmeticMultiplicationRule implements Rule
{
/** @var OperatorRuleHelper */
private $helper;
/** @var bool */
private $bleedingEdge;
public function __construct(OperatorRuleHelper $helper, bool $bleedingEdge)
{
$this->helper = $helper;
$this->bleedingEdge = $bleedingEdge;
}
public function getNodeType(): string
{
return Expr::class;
}
/**
* @return string[] errors
*/
public function processNode(Node $node, Scope $scope): array
{
if ($node instanceof BinaryOpMul) {
$left = $node->left;
$right = $node->right;
} elseif ($node instanceof AssignOpMul && $this->bleedingEdge) {
$left = $node->var;
$right = $node->expr;
} else {
return [];
}
$messages = [];
$leftType = $scope->getType($left);
if (!$this->helper->isValidForArithmeticOperation($scope, $left)) {
$messages[] = sprintf(
'Only numeric types are allowed in *, %s given on the left side.',
$leftType->describe(VerbosityLevel::typeOnly())
);
}
$rightType = $scope->getType($right);
if (!$this->helper->isValidForArithmeticOperation($scope, $right)) {
$messages[] = sprintf(
'Only numeric types are allowed in *, %s given on the right side.',
$rightType->describe(VerbosityLevel::typeOnly())
);
}
return $messages;
}
}

View File

@@ -0,0 +1,69 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Operators;
use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\AssignOp\Minus as AssignOpMinus;
use PhpParser\Node\Expr\BinaryOp\Minus as BinaryOpMinus;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Type\VerbosityLevel;
use function sprintf;
class OperandsInArithmeticSubtractionRule implements Rule
{
/** @var OperatorRuleHelper */
private $helper;
/** @var bool */
private $bleedingEdge;
public function __construct(OperatorRuleHelper $helper, bool $bleedingEdge)
{
$this->helper = $helper;
$this->bleedingEdge = $bleedingEdge;
}
public function getNodeType(): string
{
return Expr::class;
}
/**
* @return string[] errors
*/
public function processNode(Node $node, Scope $scope): array
{
if ($node instanceof BinaryOpMinus) {
$left = $node->left;
$right = $node->right;
} elseif ($node instanceof AssignOpMinus && $this->bleedingEdge) {
$left = $node->var;
$right = $node->expr;
} else {
return [];
}
$messages = [];
$leftType = $scope->getType($left);
if (!$this->helper->isValidForArithmeticOperation($scope, $left)) {
$messages[] = sprintf(
'Only numeric types are allowed in -, %s given on the left side.',
$leftType->describe(VerbosityLevel::typeOnly())
);
}
$rightType = $scope->getType($right);
if (!$this->helper->isValidForArithmeticOperation($scope, $right)) {
$messages[] = sprintf(
'Only numeric types are allowed in -, %s given on the right side.',
$rightType->describe(VerbosityLevel::typeOnly())
);
}
return $messages;
}
}

View File

@@ -0,0 +1,95 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Operators;
use PhpParser\Node\Expr;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\RuleLevelHelper;
use PHPStan\Type\Accessory\AccessoryNumericStringType;
use PHPStan\Type\BenevolentUnionType;
use PHPStan\Type\ErrorType;
use PHPStan\Type\FloatType;
use PHPStan\Type\IntegerType;
use PHPStan\Type\IntersectionType;
use PHPStan\Type\MixedType;
use PHPStan\Type\StringType;
use PHPStan\Type\Type;
use PHPStan\Type\UnionType;
class OperatorRuleHelper
{
/** @var RuleLevelHelper */
private $ruleLevelHelper;
public function __construct(RuleLevelHelper $ruleLevelHelper)
{
$this->ruleLevelHelper = $ruleLevelHelper;
}
public function isValidForArithmeticOperation(Scope $scope, Expr $expr): bool
{
$type = $scope->getType($expr);
if ($type instanceof MixedType) {
return true;
}
// already reported by PHPStan core
if ($type->toNumber() instanceof ErrorType) {
return true;
}
return $this->isSubtypeOfNumber($scope, $expr);
}
public function isValidForIncrement(Scope $scope, Expr $expr): bool
{
$type = $scope->getType($expr);
if ($type instanceof MixedType) {
return true;
}
if ($type->isString()->yes()) {
// Because `$a = 'a'; $a++;` is valid
return true;
}
return $this->isSubtypeOfNumber($scope, $expr);
}
public function isValidForDecrement(Scope $scope, Expr $expr): bool
{
$type = $scope->getType($expr);
if ($type instanceof MixedType) {
return true;
}
return $this->isSubtypeOfNumber($scope, $expr);
}
private function isSubtypeOfNumber(Scope $scope, Expr $expr): bool
{
$acceptedType = new UnionType([new IntegerType(), new FloatType(), new IntersectionType([new StringType(), new AccessoryNumericStringType()])]);
$type = $this->ruleLevelHelper->findTypeToCheck(
$scope,
$expr,
'',
static function (Type $type) use ($acceptedType): bool {
return $acceptedType->isSuperTypeOf($type)->yes();
}
)->getType();
if ($type instanceof ErrorType) {
return true;
}
$isSuperType = $acceptedType->isSuperTypeOf($type);
if ($type instanceof BenevolentUnionType) {
return !$isSuperType->no();
}
return $isSuperType->yes();
}
}

View File

@@ -0,0 +1,65 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\StrictCalls;
use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Node\MethodCallableNode;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleLevelHelper;
use PHPStan\Type\ErrorType;
use PHPStan\Type\Type;
use function sprintf;
/**
* @implements Rule<MethodCallableNode>
*/
class DynamicCallOnStaticMethodsCallableRule implements Rule
{
/** @var RuleLevelHelper */
private $ruleLevelHelper;
public function __construct(RuleLevelHelper $ruleLevelHelper)
{
$this->ruleLevelHelper = $ruleLevelHelper;
}
public function getNodeType(): string
{
return MethodCallableNode::class;
}
public function processNode(Node $node, Scope $scope): array
{
if (!$node->getName() instanceof Node\Identifier) {
return [];
}
$name = $node->getName()->name;
$type = $this->ruleLevelHelper->findTypeToCheck(
$scope,
$node->getVar(),
'',
static function (Type $type) use ($name): bool {
return $type->canCallMethods()->yes() && $type->hasMethod($name)->yes();
}
)->getType();
if ($type instanceof ErrorType || !$type->canCallMethods()->yes() || !$type->hasMethod($name)->yes()) {
return [];
}
$methodReflection = $type->getMethod($name, $scope);
if ($methodReflection->isStatic()) {
return [sprintf(
'Dynamic call to static method %s::%s().',
$methodReflection->getDeclaringClass()->getDisplayName(),
$methodReflection->getName()
)];
}
return [];
}
}

View File

@@ -0,0 +1,66 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\StrictCalls;
use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleLevelHelper;
use PHPStan\Type\ErrorType;
use PHPStan\Type\Type;
use function sprintf;
class DynamicCallOnStaticMethodsRule implements Rule
{
/** @var RuleLevelHelper */
private $ruleLevelHelper;
public function __construct(RuleLevelHelper $ruleLevelHelper)
{
$this->ruleLevelHelper = $ruleLevelHelper;
}
public function getNodeType(): string
{
return MethodCall::class;
}
/**
* @param MethodCall $node
* @return string[]
*/
public function processNode(Node $node, Scope $scope): array
{
if (!$node->name instanceof Node\Identifier) {
return [];
}
$name = $node->name->name;
$type = $this->ruleLevelHelper->findTypeToCheck(
$scope,
$node->var,
'',
static function (Type $type) use ($name): bool {
return $type->canCallMethods()->yes() && $type->hasMethod($name)->yes();
}
)->getType();
if ($type instanceof ErrorType || !$type->canCallMethods()->yes() || !$type->hasMethod($name)->yes()) {
return [];
}
$methodReflection = $type->getMethod($name, $scope);
if ($methodReflection->isStatic()) {
return [sprintf(
'Dynamic call to static method %s::%s().',
$methodReflection->getDeclaringClass()->getDisplayName(),
$methodReflection->getName()
)];
}
return [];
}
}

View File

@@ -0,0 +1,77 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\StrictCalls;
use PhpParser\Node;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Name;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Rules\Rule;
use PHPStan\Type\Constant\ConstantBooleanType;
use function array_key_exists;
use function sprintf;
use function strtolower;
class StrictFunctionCallsRule implements Rule
{
/** @var int[] */
private $functionArguments = [
'in_array' => 2,
'array_search' => 2,
'base64_decode' => 1,
'array_keys' => 2,
];
/** @var ReflectionProvider */
private $reflectionProvider;
public function __construct(ReflectionProvider $reflectionProvider)
{
$this->reflectionProvider = $reflectionProvider;
}
public function getNodeType(): string
{
return FuncCall::class;
}
/**
* @param FuncCall $node
* @return string[] errors
*/
public function processNode(Node $node, Scope $scope): array
{
if (!$node->name instanceof Name) {
return [];
}
$functionName = $this->reflectionProvider->resolveFunctionName($node->name, $scope);
if ($functionName === null) {
return [];
}
$functionName = strtolower($functionName);
if (!array_key_exists($functionName, $this->functionArguments)) {
return [];
}
if ($functionName === 'array_keys' && !array_key_exists(1, $node->getArgs())) {
return [];
}
$argumentPosition = $this->functionArguments[$functionName];
if (!array_key_exists($argumentPosition, $node->getArgs())) {
return [sprintf('Call to function %s() requires parameter #%d to be set.', $functionName, $argumentPosition + 1)];
}
$argumentType = $scope->getType($node->getArgs()[$argumentPosition]->value);
$trueType = new ConstantBooleanType(true);
if (!$trueType->isSuperTypeOf($argumentType)->yes()) {
return [sprintf('Call to function %s() requires parameter #%d to be true.', $functionName, $argumentPosition + 1)];
}
return [];
}
}

View File

@@ -0,0 +1,58 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\SwitchConditions;
use PhpParser\Node;
use PhpParser\Node\Stmt\Switch_;
use PhpParser\PrettyPrinter\Standard;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;
use PHPStan\Type\VerbosityLevel;
use function sprintf;
/**
* @implements Rule<Switch_>
*/
class MatchingTypeInSwitchCaseConditionRule implements Rule
{
/** @var Standard */
private $printer;
public function __construct(Standard $printer)
{
$this->printer = $printer;
}
public function getNodeType(): string
{
return Switch_::class;
}
public function processNode(Node $node, Scope $scope): array
{
$messages = [];
$conditionType = $scope->getType($node->cond);
foreach ($node->cases as $case) {
if ($case->cond === null) {
continue;
}
$caseType = $scope->getType($case->cond);
if (!$conditionType->isSuperTypeOf($caseType)->no()) {
continue;
}
$messages[] = RuleErrorBuilder::message(sprintf(
'Switch condition type (%s) does not match case condition %s (%s).',
$conditionType->describe(VerbosityLevel::value()),
$this->printer->prettyPrintExpr($case->cond),
$caseType->describe(VerbosityLevel::typeOnly())
))->line($case->getLine())->build();
}
return $messages;
}
}

View File

@@ -0,0 +1,38 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\VariableVariables;
use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Type\VerbosityLevel;
use function sprintf;
class VariableMethodCallRule implements Rule
{
public function getNodeType(): string
{
return Node\Expr\MethodCall::class;
}
/**
* @param MethodCall $node
* @return string[]
*/
public function processNode(Node $node, Scope $scope): array
{
if ($node->name instanceof Node\Identifier) {
return [];
}
return [
sprintf(
'Variable method call on %s.',
$scope->getType($node->var)->describe(VerbosityLevel::typeOnly())
),
];
}
}

View File

@@ -0,0 +1,37 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\VariableVariables;
use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Node\MethodCallableNode;
use PHPStan\Rules\Rule;
use PHPStan\Type\VerbosityLevel;
use function sprintf;
/**
* @implements Rule<MethodCallableNode>
*/
class VariableMethodCallableRule implements Rule
{
public function getNodeType(): string
{
return MethodCallableNode::class;
}
public function processNode(Node $node, Scope $scope): array
{
if ($node->getName() instanceof Node\Identifier) {
return [];
}
return [
sprintf(
'Variable method call on %s.',
$scope->getType($node->getVar())->describe(VerbosityLevel::typeOnly())
),
];
}
}

View File

@@ -0,0 +1,86 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\VariableVariables;
use PhpParser\Node;
use PhpParser\Node\Expr\PropertyFetch;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Rules\Rule;
use PHPStan\Type\VerbosityLevel;
use function sprintf;
class VariablePropertyFetchRule implements Rule
{
/** @var ReflectionProvider */
private $reflectionProvider;
/** @var string[] */
private $universalObjectCratesClasses;
/**
* @param string[] $universalObjectCratesClasses
*/
public function __construct(ReflectionProvider $reflectionProvider, array $universalObjectCratesClasses)
{
$this->reflectionProvider = $reflectionProvider;
$this->universalObjectCratesClasses = $universalObjectCratesClasses;
}
public function getNodeType(): string
{
return Node\Expr\PropertyFetch::class;
}
/**
* @param PropertyFetch $node
* @return string[]
*/
public function processNode(Node $node, Scope $scope): array
{
if ($node->name instanceof Node\Identifier) {
return [];
}
$fetchedOnType = $scope->getType($node->var);
foreach ($fetchedOnType->getObjectClassNames() as $referencedClass) {
if (!$this->reflectionProvider->hasClass($referencedClass)) {
continue;
}
if ($this->isUniversalObjectCrate($this->reflectionProvider->getClass($referencedClass))) {
return [];
}
}
return [
sprintf(
'Variable property access on %s.',
$fetchedOnType->describe(VerbosityLevel::typeOnly())
),
];
}
private function isUniversalObjectCrate(
ClassReflection $classReflection
): bool
{
foreach ($this->universalObjectCratesClasses as $className) {
if (!$this->reflectionProvider->hasClass($className)) {
continue;
}
if (
$classReflection->getName() === $className
|| $classReflection->isSubclassOf($className)
) {
return true;
}
}
return false;
}
}

View File

@@ -0,0 +1,44 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\VariableVariables;
use PhpParser\Node;
use PhpParser\Node\Expr\StaticCall;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Type\VerbosityLevel;
use function sprintf;
class VariableStaticMethodCallRule implements Rule
{
public function getNodeType(): string
{
return Node\Expr\StaticCall::class;
}
/**
* @param StaticCall $node
* @return string[]
*/
public function processNode(Node $node, Scope $scope): array
{
if ($node->name instanceof Node\Identifier) {
return [];
}
if ($node->class instanceof Node\Name) {
$methodCalledOn = $scope->resolveName($node->class);
} else {
$methodCalledOn = $scope->getType($node->class)->describe(VerbosityLevel::typeOnly());
}
return [
sprintf(
'Variable static method call on %s.',
$methodCalledOn
),
];
}
}

View File

@@ -0,0 +1,43 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\VariableVariables;
use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Node\StaticMethodCallableNode;
use PHPStan\Rules\Rule;
use PHPStan\Type\VerbosityLevel;
use function sprintf;
/**
* @implements Rule<StaticMethodCallableNode>
*/
class VariableStaticMethodCallableRule implements Rule
{
public function getNodeType(): string
{
return StaticMethodCallableNode::class;
}
public function processNode(Node $node, Scope $scope): array
{
if ($node->getName() instanceof Node\Identifier) {
return [];
}
if ($node->getClass() instanceof Node\Name) {
$methodCalledOn = $scope->resolveName($node->getClass());
} else {
$methodCalledOn = $scope->getType($node->getClass())->describe(VerbosityLevel::typeOnly());
}
return [
sprintf(
'Variable static method call on %s.',
$methodCalledOn
),
];
}
}

View File

@@ -0,0 +1,44 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\VariableVariables;
use PhpParser\Node;
use PhpParser\Node\Expr\StaticPropertyFetch;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Type\VerbosityLevel;
use function sprintf;
class VariableStaticPropertyFetchRule implements Rule
{
public function getNodeType(): string
{
return Node\Expr\StaticPropertyFetch::class;
}
/**
* @param StaticPropertyFetch $node
* @return string[]
*/
public function processNode(Node $node, Scope $scope): array
{
if ($node->name instanceof Node\Identifier) {
return [];
}
if ($node->class instanceof Node\Name) {
$propertyAccessedOn = $scope->resolveName($node->class);
} else {
$propertyAccessedOn = $scope->getType($node->class)->describe(VerbosityLevel::typeOnly());
}
return [
sprintf(
'Variable static property access on %s.',
$propertyAccessedOn
),
];
}
}

View File

@@ -0,0 +1,34 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\VariableVariables;
use PhpParser\Node;
use PhpParser\Node\Expr\Variable;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use function is_string;
class VariableVariablesRule implements Rule
{
public function getNodeType(): string
{
return Node\Expr\Variable::class;
}
/**
* @param Variable $node
* @return string[]
*/
public function processNode(Node $node, Scope $scope): array
{
if (is_string($node->name)) {
return [];
}
return [
'Variable variables are not allowed.',
];
}
}