├── .gitignore ├── .travis.yml ├── LICENSE ├── README-ptbr.md ├── README.md ├── composer.json ├── docker-compose.yml ├── lib └── LeroyMerlin │ ├── custom-slevomat-coding-standard.xml │ └── ruleset.xml ├── phpcs.xml.dist └── tests ├── expected ├── LowCaseTypes.php ├── PSR12 │ └── Functions │ │ └── ReturnTypeDeclaration.php ├── Slevomat │ ├── Arrays │ │ ├── MultiLineArrayEndBracketPlacement.php │ │ ├── SingleLineArrayWhitespace.php │ │ └── TrailingArrayComma.php │ ├── Classes │ │ ├── ClassConstantVisibility.php │ │ ├── ClassMemberSpacing.php │ │ ├── ClassStructure.php │ │ ├── ConstantSpacing.php │ │ ├── EmptyLinesAroundClassBraces.php │ │ ├── ModernClassNameReference.php │ │ ├── ParentCallSpacing.php │ │ ├── PropertySpacing.php │ │ └── RequireMultiLineMethodSignature.php │ ├── Commenting │ │ ├── DeprecatedAnnotationDeclaration.php │ │ ├── DisallowOneLinePropertyDocComment.php │ │ ├── EmptyComment.php │ │ ├── ForbiddenAnnotations.php │ │ ├── ForbiddenComments.php │ │ └── InlineDocCommentDeclaration.php │ ├── ControlStructures │ │ ├── EarlyExit.php │ │ ├── JumpStatementsSpacing.php │ │ ├── LanguageConstructWithParentheses.php │ │ ├── NewWithParentheses.php │ │ ├── RequireMultiLineTernaryOperator.php │ │ ├── RequireNullCoalesceOperator.php │ │ ├── RequireShortTernaryOperator.php │ │ ├── RequireTernaryOperator.php │ │ └── RequireYodaComparison.php │ ├── Exceptions │ │ ├── DeadCatch.php │ │ └── ReferenceThrowableOnly.php │ ├── Functions │ │ ├── ArrowFunctionDeclaration.php │ │ ├── RequireMultiLineCall.php │ │ ├── RequireSingleLineCall.php │ │ ├── UnusedInheritedVariablePassedToClosure.php │ │ ├── UnusedParameter.php │ │ └── UselessParameterDefaultValue.php │ ├── Namespaces │ │ ├── DisallowGroupUse.php │ │ ├── MultipleUsesPerLine.php │ │ ├── ReferenceUsedNamesOnly.php │ │ ├── RequireOneNamespaceInFile.php │ │ ├── UnusedUses.php │ │ ├── UseDoesNotStartWithBackslash.php │ │ ├── UseFromSameNamespace.php │ │ └── UselessAlias.php │ ├── Operators │ │ ├── DisallowEqualOperators.php │ │ └── RequireCombinedAssignmentOperator.php │ ├── PHP │ │ ├── ShortList.php │ │ ├── TypeCast.php │ │ ├── UselessParentheses.php │ │ └── UselessSemicolon.php │ ├── TypeHints │ │ ├── DisallowMixedTypeHint.php │ │ ├── LongTypeHints.php │ │ ├── NullTypeHintOnLastPosition.php │ │ ├── NullableTypeForNullDefaultValue.php │ │ ├── ParameterTypeHint.php │ │ ├── ParameterTypeHintSpacing.php │ │ ├── PropertyTypeHint.php │ │ ├── ReturnTypeHint.php │ │ └── UselessConstantTypeHint.php │ ├── Variables │ │ ├── DuplicateAssignmentToVariable.php │ │ └── UselessVariable.php │ └── Whitespaces │ │ └── DuplicateSpaces.php ├── array_indentation.php ├── concatenation_spacing.php ├── forbidden-comments.php ├── forbidden-functions.php ├── namespaces-spacing.php ├── new_with_parentheses.php ├── not_spacing.php ├── null_coalesce_operator.php └── semicolon_spacing.php ├── expected_report.txt └── input ├── LowCaseTypes.php ├── PSR12 └── Functions │ └── ReturnTypeDeclaration.php ├── Slevomat ├── Arrays │ ├── MultiLineArrayEndBracketPlacement.php │ ├── SingleLineArrayWhitespace.php │ └── TrailingArrayComma.php ├── Classes │ ├── ClassConstantVisibility.php │ ├── ClassMemberSpacing.php │ ├── ClassStructure.php │ ├── ConstantSpacing.php │ ├── EmptyLinesAroundClassBraces.php │ ├── ModernClassNameReference.php │ ├── ParentCallSpacing.php │ ├── PropertySpacing.php │ └── RequireMultiLineMethodSignature.php ├── Commenting │ ├── DeprecatedAnnotationDeclaration.php │ ├── DisallowOneLinePropertyDocComment.php │ ├── EmptyComment.php │ ├── ForbiddenAnnotations.php │ ├── ForbiddenComments.php │ └── InlineDocCommentDeclaration.php ├── ControlStructures │ ├── EarlyExit.php │ ├── JumpStatementsSpacing.php │ ├── LanguageConstructWithParentheses.php │ ├── NewWithParentheses.php │ ├── RequireMultiLineTernaryOperator.php │ ├── RequireNullCoalesceOperator.php │ ├── RequireShortTernaryOperator.php │ ├── RequireTernaryOperator.php │ └── RequireYodaComparison.php ├── Exceptions │ ├── DeadCatch.php │ └── ReferenceThrowableOnly.php ├── Functions │ ├── ArrowFunctionDeclaration.php │ ├── RequireMultiLineCall.php │ ├── RequireSingleLineCall.php │ ├── UnusedInheritedVariablePassedToClosure.php │ ├── UnusedParameter.php │ └── UselessParameterDefaultValue.php ├── Namespaces │ ├── DisallowGroupUse.php │ ├── MultipleUsesPerLine.php │ ├── ReferenceUsedNamesOnly.php │ ├── RequireOneNamespaceInFile.php │ ├── UnusedUses.php │ ├── UseDoesNotStartWithBackslash.php │ ├── UseFromSameNamespace.php │ └── UselessAlias.php ├── Operators │ ├── DisallowEqualOperators.php │ └── RequireCombinedAssignmentOperator.php ├── PHP │ ├── ShortList.php │ ├── TypeCast.php │ ├── UselessParentheses.php │ └── UselessSemicolon.php ├── TypeHints │ ├── DisallowMixedTypeHint.php │ ├── LongTypeHints.php │ ├── NullTypeHintOnLastPosition.php │ ├── NullableTypeForNullDefaultValue.php │ ├── ParameterTypeHint.php │ ├── ParameterTypeHintSpacing.php │ ├── PropertyTypeHint.php │ ├── ReturnTypeHint.php │ └── UselessConstantTypeHint.php ├── Variables │ ├── DuplicateAssignmentToVariable.php │ └── UselessVariable.php └── Whitespaces │ └── DuplicateSpaces.php ├── array_indentation.php ├── concatenation_spacing.php ├── forbidden-comments.php ├── forbidden-functions.php ├── namespaces-spacing.php ├── new_with_parentheses.php ├── not_spacing.php ├── null_coalesce_operator.php └── semicolon_spacing.php /.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | composer.lock 3 | phpcs.xml 4 | .phpcs-cache 5 | phpcs.log 6 | tests/fixed/* 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: xenial 2 | sudo: false 3 | language: php 4 | 5 | php: 6 | - 7.2 7 | - 7.3 8 | - 7.4 9 | - nightly 10 | 11 | cache: 12 | directories: 13 | - $HOME/.composer/cache 14 | 15 | before_install: 16 | - mv ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini{,.disabled} || echo "xdebug not available" 17 | - composer self-update 18 | 19 | install: travis_retry composer update --prefer-dist 20 | 21 | script: 22 | - composer test 23 | 24 | stages: 25 | - Test 26 | - Apply fixes 27 | 28 | jobs: 29 | allow_failures: 30 | - php: 7.4 31 | - php: nightly 32 | 33 | include: 34 | - stage: Apply fixes 35 | script: composer apply-rules 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Leroy Merlin Brasil 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README-ptbr.md: -------------------------------------------------------------------------------- 1 | # php-coding-standard 2 | 3 | Esta biblioteca contém os padrões de codificação para projetos em PHP a serem desenvolvidos na Leroy Merlin Brasil. 4 | 5 | Os padrões são configurados através do [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer). 6 | Essa ferramenta utiliza classes especiais chamadas `Sniffs`, que definem os padrões que não são aceitos e realiza a verificação nos arquivos php. 7 | 8 | ## Como utilizar 9 | 10 | ### Instalação 11 | 12 | Instale no seu projeto através do composer: 13 | 14 | ```bash 15 | composer require --dev leroy-merlin-br/coding-standard 16 | ``` 17 | 18 | ### Configuração 19 | 1. Crie o arquivo de configuração no seu repositório: `phpcs.xml`. 20 | 2. Defina a rule `LeroyMerlin`: 21 | 22 | ```xml 23 | 24 | 25 | 26 | 27 | ``` 28 | 29 | Você também pode customizar as regras do _php-coding-standard_ para se adequar melhor ao seu projeto. 30 | Novos sniffs podem ser adicionados e também é possível sobrescrever as regras existentes. 31 | 32 | No exemplo abaixo a configuração da biblioteca é sobrescrita para que a rule `CamelCapsMethodName` não seja aplicada em arquivos específicos: 33 | 34 | ```xml 35 | 36 | tests/Data/*Data.php 37 | Kameleon/Offer/ConvertPeriodDatesTrait.php 38 | Kameleon/Offer/Banner/Banner.php 39 | Kameleon/Product/Product.php 40 | Kameleon/Product/ConjugatedProduct.php 41 | Kameleon/Offers/Banner.php 42 | Kameleon/User/AbstractUser.php 43 | Kameleon/User/Idb/Idb.php 44 | 45 | ``` 46 | 47 | Para maiores detalhes, consulte a [documentação do PhpCS](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Annotated-Ruleset). 48 | 49 | ### Usando o coding-standard 50 | 51 | O melhor jeito de utilizar o _php-coding-standard_ é integrá-lo automaticamente na pipeline de CI e no hook de pré-commit do git. 52 | 53 | A pipeline de CI garantirá que códigos fora do padrão não sejam mergeados em produção. 54 | Já ao utilizá-la no pré-commit, a ferramenta é capaz de avisar o desenvolvedor dos problemas antes de eles serem commitados. 55 | 56 | #### Usando no pré-commit 57 | 58 | Caso você não saiba customizar os [hooks do git](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks), uma maneira simples de usar o _php-coding-standard_ pode ser feita instalando a ferramenta [GrumPHP](https://github.com/phpro/grumphp). 59 | O GrumPHP permite que o desenvolvedor escreva um simples arquivo YML na raiz do projeto para configurar os hooks. 60 | 61 | 1. Instale o GrumPHP: 62 | ```bash 63 | composer require --dev phpro/grumphp 64 | ``` 65 | 3. Defina um arquivo `grump.yml` na raiz do projeto com a seguinte configuração: 66 | ```yml 67 | grumphp: 68 | git_hook_variables: 69 | EXEC_GRUMPHP_COMMAND: 'docker-compose run --rm -e COLUMNS=$COLUMNS -e LINES=$LINES -e TERM=$TERM -T ' 70 | stop_on_failure: true 71 | process_timeout: 120 72 | tasks: 73 | phpcs: 74 | standard: [ path/to/phpcs.xml ] # aqui você referencia o arquivo gerado durante a configuração 75 | fixer: 76 | enabled: true 77 | fix_by_default: true 78 | ``` 79 | 80 | **Observação:** O GrumPHP ainda permite a configuração de outras ferramentas úteis para garantir a qualidade de código e do projeto como: analisadores estáticos, testes automatizados, padronização de mensagens de commits, scripts utilitários em shell, etc. 81 | Vale a pena conferir as [possibilidades](https://github.com/phpro/grumphp/blob/master/doc/tasks.md) na documentação do projeto. 82 | 83 | #### Integração contínua e uso manual 84 | 85 | Caso seja necessário, você pode rodar o `phpcs` manualmente através do comando: 86 | ```bash 87 | vendor/bin/phpcs path/to/dir/or/file.php 88 | ``` 89 | 90 | Mas reforço que também é interessante ter este comando configurando na pipeline de CI do seu projeto. 91 | 92 | ## Diretrizes de contribuição 93 | 94 | Novos sniffs podem ser adicionados nos arquivos de configuração. 95 | 96 | O XML `LeroyMerlin/ruleset.xml` é o arquivo principal e sniffs podem ser adicionados nele. 97 | Mas também podem ser adicionados em outros arquivos. 98 | 99 | Para importar as rules de um arquivo: 100 | ```xml 101 | 102 | ``` 103 | 104 | Priorize separar os sniffs por contexto, assim como foi feita a separação dos sniffs da Slevomat. 105 | Assim fica mais fácil de manter a biblioteca e consultar as regras existentes. 106 | 107 | #### Configuração do Ruleset 108 | 109 | Ao adicionar uma nova regra, **sempre** escreva um comentário acima dela descrevendo de maneira simples o que o sniff verifica: 110 | ```xml 111 | 112 | 113 | 114 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | ``` 126 | 127 | #### Manutenção dos Testes 128 | 129 | Para executar os testes: 130 | ```bash 131 | composer test 132 | ``` 133 | 134 | Atualmente esses testes funcionam de maneira muito simples: a biblioteca consulta o diretório `tests/input` e gera um relatório de erros. 135 | Posteriormente esse relatório é comparado com o relatório esperado em `tests/expected_report.txt` e caso os dois não estejam iguais, é retornado o erro. 136 | 137 | Futuramente podemos evoluir os testes para serem mais assertivos: uma ideia interessante é a de gerar os relatórios de erros e warnings para cada teste e verificar se os sniffs esperados foram lançados para cada caso. 138 | 139 | No momento em que escrevo essa documentação(29/04/2022) não possuímos a cobertura completa dos padrões. 140 | 141 | Possuímos alguns testes legados agrupando várias ideias diferentes na raiz da pasta `tests/input`. 142 | Mas seria melhor se esses testes agissem da maneira mais específica possível, cobrindo cada sniff instalado na biblioteca. 143 | 144 | Tal iniciativa foi feita para os Sniffs da Slevomat, mas ainda falta organizar os testes presentes no arquivo `LeroyMerlin/ruleset.xml`. 145 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # php-coding-standard 2 | 3 | The coding standard for PHP projects on LMBR. 4 | 5 | You can check a version of the [documentation written in Brazilian Portuguese](./README-ptbr.md). -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "leroy-merlin-br/coding-standard", 3 | "description": "The coding standard for PHP projects on LMBR", 4 | "type": "phpcodesniffer-standard", 5 | "license": "MIT", 6 | "keywords": [ 7 | "leroy-merlin", 8 | "php", 9 | "coding", 10 | "standard", 11 | "cs", 12 | "code", 13 | "style", 14 | "sniffer", 15 | "rules", 16 | "sniffs", 17 | "checks" 18 | ], 19 | "authors": [ 20 | { 21 | "name": "Boitatá", 22 | "email": "boitata@leroymerlin.com.br" 23 | } 24 | ], 25 | "require": { 26 | "php": ">=7.4", 27 | "dealerdirect/phpcodesniffer-composer-installer": "^0.7.2", 28 | "slevomat/coding-standard": "^7.0.18", 29 | "squizlabs/php_codesniffer": "^3.6.2" 30 | }, 31 | "config": { 32 | "sort-packages": true, 33 | "allow-plugins": { 34 | "dealerdirect/phpcodesniffer-composer-installer": true 35 | } 36 | }, 37 | "scripts": { 38 | "test": "phpcs tests/input --report=summary --report-file=phpcs.log; diff tests/expected_report.txt phpcs.log", 39 | "copy-input": "cp -r tests/input/. tests/fixed", 40 | "apply-rules": [ 41 | "@copy-input", 42 | "phpcbf tests/fixed; diff tests/fixed tests/expected" 43 | ] 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | php: 4 | image: '639548217638.dkr.ecr.us-east-1.amazonaws.com/kameleon:v0.0.1-base-7.4-apache' 5 | volumes: 6 | - .:/var/www/html 7 | -------------------------------------------------------------------------------- /lib/LeroyMerlin/custom-slevomat-coding-standard.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | The custom slevomat coding standard for PHP projects on LMBR 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | warning 138 | 139 | 140 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | warning 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 217 | 218 | warning 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | warning 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 241 | 242 | 243 | 244 | 245 | 246 | warning 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | warning 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | -------------------------------------------------------------------------------- /lib/LeroyMerlin/ruleset.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | The coding standard for PHP projects on LMBR 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | -------------------------------------------------------------------------------- /phpcs.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | lib 15 | 16 | -------------------------------------------------------------------------------- /tests/expected/LowCaseTypes.php: -------------------------------------------------------------------------------- 1 | 'abc'], [3 => 'def'], 9 | ]; 10 | -------------------------------------------------------------------------------- /tests/expected/Slevomat/Arrays/SingleLineArrayWhitespace.php: -------------------------------------------------------------------------------- 1 | 'value', 9 | 'key2' => 'value', 10 | ]; 11 | -------------------------------------------------------------------------------- /tests/expected/Slevomat/Classes/ClassConstantVisibility.php: -------------------------------------------------------------------------------- 1 | 0 ? 10 : 20; 10 | } 11 | 12 | function bar(): int 13 | { 14 | if (1 > 0) { 15 | return 10; 16 | } 17 | 18 | if (10 < 20) { 19 | return 20; 20 | } 21 | 22 | if (20 > 0) { 23 | return 30; 24 | } 25 | 26 | return 40; 27 | } 28 | -------------------------------------------------------------------------------- /tests/expected/Slevomat/ControlStructures/JumpStatementsSpacing.php: -------------------------------------------------------------------------------- 1 | 10; $i++) { 10 | if (0 === $i % 7) { 11 | $logic = 'insert code here'; 12 | 13 | continue; 14 | } 15 | 16 | if (8 < $i && 11 > $i) { 17 | $logic = 'stop execution'; 18 | 19 | break; 20 | } 21 | } 22 | 23 | return $logic ?? 'bar'; 24 | } 25 | -------------------------------------------------------------------------------- /tests/expected/Slevomat/ControlStructures/LanguageConstructWithParentheses.php: -------------------------------------------------------------------------------- 1 | $number % 2 === 0); 8 | -------------------------------------------------------------------------------- /tests/expected/Slevomat/Functions/RequireMultiLineCall.php: -------------------------------------------------------------------------------- 1 | >= 2; 13 | $g ^= 2; 14 | $h %= 2; 15 | -------------------------------------------------------------------------------- /tests/expected/Slevomat/PHP/ShortList.php: -------------------------------------------------------------------------------- 1 | a; 22 | $x = $this->$$parameter; 23 | $x = $this->{'a'}; 24 | $x = $$parameter; 25 | $x = $this->${'a'}[0]->$$b[1][2]::$c[3][4][5]->{" $d"}; 26 | $x = $this->${'a'}[0]->$$b[1][2]::$c[3][4][5]->{" $d"}(); 27 | $x = $this->${'a'}[0]->$$b[1][2]::$c[3][4][5]->{" $d"}()()()(); 28 | $x = !$this->${'a'}[0]->$$b[1][2]::$c[3][4][5]->{" $d"}()()()(); 29 | $x = isset($xxx); 30 | $x = !isset($xxx); 31 | $x = empty($xxx); 32 | $x = !empty($xxx); 33 | $x = !in_array($foo, ['bar', 'foo']); 34 | $x = intval($foo); 35 | } 36 | } 37 | 38 | $x = null !== $y ? true : false; 39 | $a = $b ? 1 : 0; 40 | $c = $d ? 1 : 0; 41 | 42 | switch (true) { 43 | case $boo: 44 | case true === $boo: 45 | case $boo ? true : false: 46 | case $boo ? true : false: 47 | } 48 | 49 | function () { 50 | return [ 51 | 'a' => 'aa', 52 | ]; 53 | }; 54 | 55 | $x += 1; 56 | 57 | $x = $y + $yy - $z; 58 | $x = $y * $yy / $z; 59 | $x = 100 / 50 * 100; 60 | $x = $a + $b * 3; 61 | $x = $b + 100 - $c; 62 | $x = $b * 100 / $c; 63 | 64 | function () { 65 | return [ 66 | 'a' => 'aa' . 'bb', 67 | ]; 68 | }; 69 | -------------------------------------------------------------------------------- /tests/expected/Slevomat/PHP/UselessSemicolon.php: -------------------------------------------------------------------------------- 1 | 19 | */ 20 | public $b; 21 | 22 | /** 23 | * @var mixed&(int|float) 24 | */ 25 | public $c; 26 | 27 | /** 28 | * @var mixed|(float&int) 29 | */ 30 | public $d; 31 | 32 | /** 33 | * @var mixed[][][] 34 | */ 35 | public array $e; 36 | 37 | /** 38 | * @var (int|mixed)[][][] 39 | */ 40 | public array $f; 41 | 42 | /** 43 | * @var mixed|(\Foo&bool)[] 44 | */ 45 | public $g; 46 | 47 | /** 48 | * @var \Foo<\Boo> 49 | */ 50 | public Foo $h; 51 | } 52 | 53 | class CallableType 54 | { 55 | /** 56 | * @return callable(mixed $bool): mixed 57 | */ 58 | public function returnsCallable(): callable 59 | { 60 | } 61 | } 62 | 63 | /** @var array{int, mixed} $arrayShape1 */ 64 | $arrayShape1 = []; 65 | 66 | /** @var array{foo: mixed} $arrayShape2 */ 67 | $arrayShape2 = []; 68 | -------------------------------------------------------------------------------- /tests/expected/Slevomat/TypeHints/LongTypeHints.php: -------------------------------------------------------------------------------- 1 | 73 | */ 74 | public $b; 75 | 76 | /** 77 | * @var string&(int|float) 78 | */ 79 | public $c; 80 | 81 | /** 82 | * @var string|(float&int) 83 | */ 84 | public $d; 85 | 86 | /** 87 | * @var bool[][][] 88 | */ 89 | public array $e; 90 | 91 | /** 92 | * @var (int|bool)[][][] 93 | */ 94 | public array $f; 95 | 96 | /** 97 | * @var int|(string&bool)[] 98 | */ 99 | public $g; 100 | 101 | /** 102 | * @var \Foo<\Boo> 103 | */ 104 | public Foo $h; 105 | } 106 | 107 | class CallableType 108 | { 109 | /** 110 | * @return callable(bool $bool): (int|float) 111 | */ 112 | public function returnsCallable(): callable 113 | { 114 | } 115 | } 116 | 117 | /** 118 | * @return bool - true - if some cond 119 | * false - if some other cond 120 | */ 121 | function multilineDescription(): bool 122 | { 123 | } 124 | 125 | /** @var array{int, bool} $arrayShape1 */ 126 | $arrayShape1 = []; 127 | 128 | /** @var array{foo: int, bar: bool} $arrayShape2 */ 129 | $arrayShape2 = []; 130 | -------------------------------------------------------------------------------- /tests/expected/Slevomat/TypeHints/NullTypeHintOnLastPosition.php: -------------------------------------------------------------------------------- 1 | &bool)[]|null 72 | */ 73 | public $d; 74 | 75 | /** 76 | * @var \Foo<(int|null), (bool|null)> 77 | */ 78 | public Foo $e; 79 | 80 | /** 81 | * @var \Foo<\Foo<(int|null)>> 82 | */ 83 | public Foo $f; 84 | } 85 | 86 | class CallableType 87 | { 88 | /** 89 | * @return callable((bool|null) $bool): (int|null) 90 | */ 91 | public function returnsCallable(): callable 92 | { 93 | } 94 | } 95 | 96 | /** @var array{int, (int|null), (bool|null)} $arrayShape1 */ 97 | $arrayShape1 = []; 98 | 99 | /** @var array{foo: (int|null)} $arrayShape2 */ 100 | $arrayShape2 = []; 101 | 102 | class Conditional 103 | { 104 | /** 105 | * @return (Conditional1 is Conditional2 ? (Conditional3|null) : false) 106 | */ 107 | public function withConditional() 108 | { 109 | } 110 | 111 | /** 112 | * @return ($parameter is Conditional2 ? (Conditional3|null) : false) 113 | */ 114 | public function withConditionalParameter($parameter) 115 | { 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /tests/expected/Slevomat/TypeHints/NullableTypeForNullDefaultValue.php: -------------------------------------------------------------------------------- 1 | $int; 17 | 18 | interface Foo 19 | { 20 | public function doFoo(?int $int = null): void; 21 | } 22 | 23 | class FooBar extends Anything 24 | { 25 | public function invalid(?bool $bool = null): void 26 | { 27 | } 28 | 29 | public function myself(?self $self = null): void 30 | { 31 | } 32 | 33 | public function array(?array $array = null): void 34 | { 35 | } 36 | 37 | public function parent(?parent $parent = null): void 38 | { 39 | } 40 | 41 | public function callable(?callable $callable = null): void 42 | { 43 | } 44 | 45 | public function withNullableParamBefore(?float $float, ?Baz $param1 = null): void 46 | { 47 | } 48 | 49 | public function withParamAfter(?bool $param2 = null, ?array &...$ellipsis): void 50 | { 51 | } 52 | 53 | public function reference(?float &$ref = null): void 54 | { 55 | } 56 | 57 | public function weirdDefinition(?float &$ref = null): void 58 | { 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /tests/expected/Slevomat/TypeHints/ParameterTypeHint.php: -------------------------------------------------------------------------------- 1 | $a 84 | */ 85 | public function genericWithoutItemsSpecification(Generic $a): void 86 | { 87 | } 88 | 89 | /** 90 | * @param array[] &\Traversable $a 91 | */ 92 | public function traversableIntersection($a): void 93 | { 94 | } 95 | 96 | /** 97 | * @param \Traversable &array[] $a 98 | */ 99 | public function traversableIntersectionDifferentOrder($a): void 100 | { 101 | } 102 | 103 | public function traversableNull(?Traversable $a): void 104 | { 105 | } 106 | 107 | public function objectParameter(object $a): void 108 | { 109 | } 110 | 111 | /** 112 | * @param array|array $a 113 | */ 114 | public function unionWithSameBase(array $a): void 115 | { 116 | } 117 | 118 | /** 119 | * @param array|array|array $a 120 | */ 121 | public function unionWithSameBaseAndMoreTypes(array $a): void 122 | { 123 | } 124 | 125 | /** 126 | * @param array|bool[] $a 127 | */ 128 | public function unionWithSameBaseToo(array $a): void 129 | { 130 | } 131 | 132 | /** 133 | * @param array|array|array|null $a 134 | */ 135 | public function unionWithSameNullableBase(?array $a): void 136 | { 137 | } 138 | 139 | public function nullable(?int $a): void 140 | { 141 | } 142 | 143 | /** 144 | * @param mixed[]|array $a 145 | */ 146 | public function traversableArray(array $a): void 147 | { 148 | } 149 | 150 | public function oneLineDocComment(string $a): void 151 | { 152 | } 153 | 154 | /** @param true $a */ 155 | public function constTrue(bool $a): void 156 | { 157 | } 158 | 159 | /** @param FALSE $a */ 160 | public function constFalse(bool $a): void 161 | { 162 | } 163 | 164 | /** @param 0 $a */ 165 | public function constInteger(int $a): void 166 | { 167 | } 168 | 169 | /** @param 0.0 $a */ 170 | public function constFloat(float $a): void 171 | { 172 | } 173 | 174 | /** @param 'foo' $a */ 175 | public function constString(string $a): void 176 | { 177 | } 178 | 179 | /** @param 'foo'|null $a */ 180 | public function constNullableString(?string $a): void 181 | { 182 | } 183 | 184 | /** @param 'foo'|'bar' $a */ 185 | public function constUnionString(string $a): void 186 | { 187 | } 188 | 189 | /** @param class-string $a */ 190 | public function classString(string $a): void 191 | { 192 | } 193 | 194 | /** @param mixed $a */ 195 | public function mixedType($a): void 196 | { 197 | } 198 | 199 | /** @param mixed|null $a */ 200 | public function nullableMixedType($a): void 201 | { 202 | } 203 | 204 | /** 205 | * @param string[] $a 206 | */ 207 | public function uselessSuppressOfUselessAnnotation(array $a): void 208 | { 209 | } 210 | 211 | /** 212 | * @param string[] $a 213 | */ 214 | public function uselessSuppressOfMissingTraversableTypeHintSpecification(array $a): void 215 | { 216 | } 217 | 218 | /** 219 | * @phpstan-param class-string $a 220 | */ 221 | public function uselessSuppressOfMissingAnyTypeHintWithTypeHint(string $a): void 222 | { 223 | } 224 | 225 | /** 226 | * @phpstan-param class-string $a 227 | */ 228 | public function uselessSuppressOfMissingNativeTypeHintWithTypeHint(string $a): void 229 | { 230 | } 231 | 232 | /** 233 | * @param scalar $a 234 | */ 235 | public function uselessSuppressOfMissingNativeTypeHint($a): void 236 | { 237 | } 238 | 239 | public function uselessAnnotationWithShortNullable(?int $a): void 240 | { 241 | } 242 | 243 | private function noTypeHintNoAnnotation($a): void 244 | { 245 | } 246 | } 247 | -------------------------------------------------------------------------------- /tests/expected/Slevomat/TypeHints/ParameterTypeHintSpacing.php: -------------------------------------------------------------------------------- 1 | $a; 18 | 19 | fn (int|false $a, null|string $b) => $a; 20 | -------------------------------------------------------------------------------- /tests/expected/Slevomat/TypeHints/PropertyTypeHint.php: -------------------------------------------------------------------------------- 1 | 102 | */ 103 | public function genericWithoutItemsSpecification(): Generic 104 | { 105 | return new Generic(); 106 | } 107 | 108 | /** 109 | * @return array[]&\Traversable 110 | */ 111 | public function traversableIntersection() 112 | { 113 | return new ArrayIterator(); 114 | } 115 | 116 | /** 117 | * @return \Traversable&array[] 118 | */ 119 | public function traversableIntersectionDifferentOrder() 120 | { 121 | return new ArrayIterator(); 122 | } 123 | 124 | public function traversableNull(): ?Traversable 125 | { 126 | return new ArrayIterator(); 127 | } 128 | 129 | public function returnsObject(): object 130 | { 131 | return new stdClass(); 132 | } 133 | 134 | public function nullable(): ?int 135 | { 136 | } 137 | 138 | /** 139 | * @return mixed[]|array 140 | */ 141 | public function traversableArray(): array 142 | { 143 | } 144 | 145 | public function oneLineDocComment(): string 146 | { 147 | return 'hi'; 148 | } 149 | 150 | /** @return true */ 151 | public function constTrue(): bool 152 | { 153 | } 154 | 155 | /** @return FALSE */ 156 | public function constFalse(): bool 157 | { 158 | } 159 | 160 | /** @return 0 */ 161 | public function constInteger(): int 162 | { 163 | } 164 | 165 | /** @return 0.0 */ 166 | public function constFloat(): float 167 | { 168 | } 169 | 170 | /** @return 'foo' */ 171 | public function constString(): string 172 | { 173 | } 174 | 175 | /** @return 'foo'|null */ 176 | public function constNullableString(): ?string 177 | { 178 | } 179 | 180 | /** @return 'foo'|'bar' */ 181 | public function constUnionString(): string 182 | { 183 | } 184 | 185 | /** @return class-string */ 186 | public function classString(): string 187 | { 188 | } 189 | 190 | /** @return static */ 191 | public function staticReference() 192 | { 193 | } 194 | 195 | /** @return mixed */ 196 | public function returnsMixed() 197 | { 198 | } 199 | 200 | /** @return mixed|null */ 201 | public function returnsNullableMixed() 202 | { 203 | } 204 | 205 | /** 206 | * @return void 207 | */ 208 | public function voidButReturnsValue() 209 | { 210 | return true; 211 | } 212 | 213 | /** 214 | * @return no-return 215 | */ 216 | public function noReturnTypeHint(): void 217 | { 218 | } 219 | 220 | public function uselessAnnotationWithShortNullable(): ?int 221 | { 222 | return 0; 223 | } 224 | 225 | /** 226 | * @return (Conditional is Conditional2 ? array : iterable) 227 | */ 228 | public function withConditional(): array 229 | { 230 | return []; 231 | } 232 | 233 | private function noTypeHintNoAnnotation() 234 | { 235 | return true; 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /tests/expected/Slevomat/TypeHints/UselessConstantTypeHint.php: -------------------------------------------------------------------------------- 1 | > 1; 53 | }; 54 | 55 | function () { 56 | return $m . 1; 57 | }; 58 | 59 | function sameVariableInDifferentScope() 60 | { 61 | return array_map(function () { 62 | return $n + 1; 63 | }, []); 64 | } 65 | 66 | function moreVariableOneWithoutAssigment() 67 | { 68 | $o++; 69 | 70 | return 10; 71 | } 72 | 73 | function assigmentAsFunctionParametr() 74 | { 75 | doSomething($p = 0); 76 | 77 | return $p; 78 | } 79 | 80 | function assigmentAfterAssignment() 81 | { 82 | doSomething($qq = $q = 0); 83 | 84 | return $q; 85 | } 86 | 87 | function afterIfStatement(float $seconds): string 88 | { 89 | if ($seconds < 1) { 90 | return round($seconds * 1000, 2) . 'ms'; 91 | } 92 | 93 | return round($seconds, 2) . 's'; 94 | } 95 | 96 | return null; 97 | -------------------------------------------------------------------------------- /tests/expected/Slevomat/Whitespaces/DuplicateSpaces.php: -------------------------------------------------------------------------------- 1 | [ 14 | '2' => 2, 15 | 1 => '1', 16 | ], 17 | 4 => [ 18 | 7, 19 | 8, 20 | 9, 21 | ], 22 | ]; 23 | -------------------------------------------------------------------------------- /tests/expected/concatenation_spacing.php: -------------------------------------------------------------------------------- 1 | 1, 19 | 'bar' => 2, 20 | 'baz' => 3, 21 | ]; 22 | -------------------------------------------------------------------------------- /tests/expected/namespaces-spacing.php: -------------------------------------------------------------------------------- 1 | sub(new DateInterval('P1D')) 17 | ->format(DATE_RFC3339) 18 | ); 19 | -------------------------------------------------------------------------------- /tests/expected/new_with_parentheses.php: -------------------------------------------------------------------------------- 1 | foo = 'Foo'; 13 | $foo = new $classNamesInObject->foo(); 14 | 15 | $whitespaceBetweenClassNameAndParentheses = new stdClass(); 16 | 17 | $x = [ 18 | new stdClass(), 19 | ]; 20 | 21 | $y = [new stdClass()]; 22 | 23 | $z = new stdClass() ?: new stdClass(); 24 | 25 | $q = $q ?: new stdClass(); 26 | $e = $e ?? new stdClass(); 27 | -------------------------------------------------------------------------------- /tests/expected/not_spacing.php: -------------------------------------------------------------------------------- 1 | 0) { 8 | echo 1; 9 | } elseif (!$test === 0) { 10 | echo 0; 11 | } else { 12 | echo -1; 13 | } 14 | 15 | while (!true) { 16 | echo 1; 17 | } 18 | 19 | do { 20 | echo 1; 21 | } while (!true); 22 | -------------------------------------------------------------------------------- /tests/expected/null_coalesce_operator.php: -------------------------------------------------------------------------------- 1 | select() 8 | ->from() 9 | ->where(); 10 | -------------------------------------------------------------------------------- /tests/expected_report.txt: -------------------------------------------------------------------------------- 1 | 2 | PHP CODE SNIFFER REPORT SUMMARY 3 | ------------------------------------------------------------------------------------------------ 4 | FILE ERRORS WARNINGS 5 | ------------------------------------------------------------------------------------------------ 6 | tests/input/array_indentation.php 10 0 7 | tests/input/concatenation_spacing.php 21 0 8 | tests/input/forbidden-comments.php 6 0 9 | tests/input/forbidden-functions.php 3 0 10 | tests/input/LowCaseTypes.php 5 0 11 | tests/input/namespaces-spacing.php 6 0 12 | tests/input/new_with_parentheses.php 29 0 13 | tests/input/not_spacing.php 10 0 14 | tests/input/null_coalesce_operator.php 5 0 15 | tests/input/semicolon_spacing.php 4 0 16 | tests/input/PSR12/Functions/ReturnTypeDeclaration.php 1 1 17 | tests/input/Slevomat/Arrays/MultiLineArrayEndBracketPlacement.php 1 0 18 | tests/input/Slevomat/Arrays/SingleLineArrayWhitespace.php 2 0 19 | tests/input/Slevomat/Arrays/TrailingArrayComma.php 1 0 20 | tests/input/Slevomat/Classes/ClassConstantVisibility.php 4 2 21 | tests/input/Slevomat/Classes/ClassMemberSpacing.php 7 4 22 | tests/input/Slevomat/Classes/ClassStructure.php 124 39 23 | tests/input/Slevomat/Classes/ConstantSpacing.php 4 0 24 | tests/input/Slevomat/Classes/EmptyLinesAroundClassBraces.php 7 1 25 | tests/input/Slevomat/Classes/ModernClassNameReference.php 12 1 26 | tests/input/Slevomat/Classes/ParentCallSpacing.php 9 1 27 | tests/input/Slevomat/Classes/PropertySpacing.php 62 4 28 | tests/input/Slevomat/Classes/RequireMultiLineMethodSignature.php 11 2 29 | tests/input/Slevomat/Commenting/DeprecatedAnnotationDeclaration.php 2 0 30 | tests/input/Slevomat/Commenting/DisallowOneLinePropertyDocComment.php 5 0 31 | tests/input/Slevomat/Commenting/EmptyComment.php 2 0 32 | tests/input/Slevomat/Commenting/ForbiddenAnnotations.php 3 0 33 | tests/input/Slevomat/Commenting/ForbiddenComments.php 4 0 34 | tests/input/Slevomat/Commenting/InlineDocCommentDeclaration.php 1 0 35 | tests/input/Slevomat/ControlStructures/EarlyExit.php 6 2 36 | tests/input/Slevomat/ControlStructures/JumpStatementsSpacing.php 4 1 37 | tests/input/Slevomat/ControlStructures/LanguageConstructWithParentheses.php 20 10 38 | tests/input/Slevomat/ControlStructures/NewWithParentheses.php 8 1 39 | tests/input/Slevomat/ControlStructures/RequireMultiLineTernaryOperator.php 1 0 40 | tests/input/Slevomat/ControlStructures/RequireNullCoalesceOperator.php 5 0 41 | tests/input/Slevomat/ControlStructures/RequireShortTernaryOperator.php 2 0 42 | tests/input/Slevomat/ControlStructures/RequireTernaryOperator.php 3 0 43 | tests/input/Slevomat/ControlStructures/RequireYodaComparison.php 5 0 44 | tests/input/Slevomat/Exceptions/DeadCatch.php 1 1 45 | tests/input/Slevomat/Exceptions/ReferenceThrowableOnly.php 0 1 46 | tests/input/Slevomat/Functions/ArrowFunctionDeclaration.php 3 0 47 | tests/input/Slevomat/Functions/RequireMultiLineCall.php 6 2 48 | tests/input/Slevomat/Functions/RequireSingleLineCall.php 5 2 49 | tests/input/Slevomat/Functions/UnusedInheritedVariablePassedToClosure.php 2 0 50 | tests/input/Slevomat/Functions/UnusedParameter.php 2 1 51 | tests/input/Slevomat/Functions/UselessParameterDefaultValue.php 2 1 52 | tests/input/Slevomat/Namespaces/DisallowGroupUse.php 6 0 53 | tests/input/Slevomat/Namespaces/MultipleUsesPerLine.php 8 0 54 | tests/input/Slevomat/Namespaces/ReferenceUsedNamesOnly.php 2 0 55 | tests/input/Slevomat/Namespaces/RequireOneNamespaceInFile.php 2 0 56 | tests/input/Slevomat/Namespaces/UnusedUses.php 2 1 57 | tests/input/Slevomat/Namespaces/UseDoesNotStartWithBackslash.php 4 0 58 | tests/input/Slevomat/Namespaces/UseFromSameNamespace.php 2 0 59 | tests/input/Slevomat/Namespaces/UselessAlias.php 8 0 60 | tests/input/Slevomat/Operators/DisallowEqualOperators.php 3 5 61 | tests/input/Slevomat/Operators/RequireCombinedAssignmentOperator.php 8 0 62 | tests/input/Slevomat/PHP/ShortList.php 4 0 63 | tests/input/Slevomat/PHP/TypeCast.php 13 0 64 | tests/input/Slevomat/PHP/UselessParentheses.php 13 43 65 | tests/input/Slevomat/PHP/UselessSemicolon.php 6 0 66 | tests/input/Slevomat/TypeHints/DisallowMixedTypeHint.php 31 18 67 | tests/input/Slevomat/TypeHints/LongTypeHints.php 99 12 68 | tests/input/Slevomat/TypeHints/NullableTypeForNullDefaultValue.php 60 15 69 | tests/input/Slevomat/TypeHints/NullTypeHintOnLastPosition.php 78 7 70 | tests/input/Slevomat/TypeHints/ParameterTypeHint.php 66 79 71 | tests/input/Slevomat/TypeHints/ParameterTypeHintSpacing.php 48 6 72 | tests/input/Slevomat/TypeHints/PropertyTypeHint.php 16 0 73 | tests/input/Slevomat/TypeHints/ReturnTypeHint.php 37 39 74 | tests/input/Slevomat/TypeHints/UselessConstantTypeHint.php 3 0 75 | tests/input/Slevomat/Variables/DuplicateAssignmentToVariable.php 2 0 76 | tests/input/Slevomat/Variables/UselessVariable.php 40 10 77 | tests/input/Slevomat/Whitespaces/DuplicateSpaces.php 2 0 78 | ------------------------------------------------------------------------------------------------ 79 | A TOTAL OF 999 ERRORS AND 312 WARNINGS WERE FOUND IN 72 FILES 80 | ------------------------------------------------------------------------------------------------ 81 | PHPCBF CAN FIX 895 OF THESE SNIFF VIOLATIONS AUTOMATICALLY 82 | ------------------------------------------------------------------------------------------------ 83 | 84 | 85 | -------------------------------------------------------------------------------- /tests/input/LowCaseTypes.php: -------------------------------------------------------------------------------- 1 | 'abc'], [3 => 'def'], 8 | ]; 9 | -------------------------------------------------------------------------------- /tests/input/Slevomat/Arrays/SingleLineArrayWhitespace.php: -------------------------------------------------------------------------------- 1 | 'value', 9 | 'key2' => 'value' 10 | ]; 11 | -------------------------------------------------------------------------------- /tests/input/Slevomat/Classes/ClassConstantVisibility.php: -------------------------------------------------------------------------------- 1 | 0) { 10 | return 10; 11 | } else { 12 | return 20; 13 | } 14 | } 15 | 16 | function bar(): int 17 | { 18 | if (1 > 0) { 19 | return 10; 20 | } elseif (10 < 20) { 21 | return 20; 22 | } elseif (20 > 0) { 23 | return 30; 24 | } else { 25 | return 40; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tests/input/Slevomat/ControlStructures/JumpStatementsSpacing.php: -------------------------------------------------------------------------------- 1 | 10; $i++) { 10 | if (0 === $i % 7) { 11 | $logic = 'insert code here'; 12 | continue; 13 | } 14 | 15 | if (8 < $i && 11 > $i) { 16 | $logic = 'stop execution'; 17 | break; 18 | } 19 | } 20 | 21 | return $logic ?? 'bar'; 22 | } -------------------------------------------------------------------------------- /tests/input/Slevomat/ControlStructures/LanguageConstructWithParentheses.php: -------------------------------------------------------------------------------- 1 | $number % 2 === 0); 8 | -------------------------------------------------------------------------------- /tests/input/Slevomat/Functions/RequireMultiLineCall.php: -------------------------------------------------------------------------------- 1 | true; 12 | -------------------------------------------------------------------------------- /tests/input/Slevomat/Operators/RequireCombinedAssignmentOperator.php: -------------------------------------------------------------------------------- 1 | > 2; 13 | $g = $g ^ 2; 14 | $h = $h % 2; 15 | -------------------------------------------------------------------------------- /tests/input/Slevomat/PHP/ShortList.php: -------------------------------------------------------------------------------- 1 | a); 23 | $x = ($this->$$parameter); 24 | $x = ($this->{'a'}); 25 | $x = ($$parameter); 26 | $x = ($this->${'a'}[0]->$$b[1][2]::$c[3][4][5]->{" $d"}); 27 | $x = ($this->${'a'}[0]->$$b[1][2]::$c[3][4][5]->{" $d"}()); 28 | $x = ($this->${'a'}[0]->$$b[1][2]::$c[3][4][5]->{" $d"}()()()()); 29 | $x = (!$this->${'a'}[0]->$$b[1][2]::$c[3][4][5]->{" $d"}()()()()); 30 | $x = (isset($xxx)); 31 | $x = (!isset($xxx)); 32 | $x = (empty($xxx)); 33 | $x = (!empty($xxx)); 34 | $x = ! (in_array($foo, ['bar', 'foo'])); 35 | $x = (intval($foo)); 36 | } 37 | 38 | } 39 | 40 | $x = ($y !== null) ? true : false; 41 | $a = ($b) ? 1 : 0; 42 | $c = ( $d ) ? 1 : 0; 43 | 44 | switch (true) { 45 | case ($boo): 46 | case ($boo === true): 47 | case ($boo ? true : false): 48 | case ($boo) ? true : false: 49 | } 50 | 51 | function () { 52 | return [ 53 | 'a' => ('aa'), 54 | ]; 55 | }; 56 | 57 | $x = ($x + 1); 58 | 59 | $x = ($y + $yy) - $z; 60 | $x = ($y * $yy) / $z; 61 | $x = ((100 / 50) * 100); 62 | $x = ($a + $b * 3); 63 | $x = $b + (100 - $c); 64 | $x = $b * (100 / $c); 65 | 66 | function () { 67 | return [ 68 | 'a' => ('aa' . 'bb'), 69 | ]; 70 | }; 71 | -------------------------------------------------------------------------------- /tests/input/Slevomat/PHP/UselessSemicolon.php: -------------------------------------------------------------------------------- 1 | */ 17 | public $b; 18 | 19 | /** @var mixed&(integer|float) */ 20 | public $c; 21 | 22 | /** @var mixed|(float&integer) */ 23 | public $d; 24 | 25 | /** @var mixed[][][] */ 26 | public $e; 27 | 28 | /** @var (integer|mixed)[][][] */ 29 | public $f; 30 | 31 | /** @var mixed|(\Foo&boolean)[] */ 32 | public $g; 33 | 34 | /** @var \Foo<\Boo> */ 35 | public $h; 36 | 37 | } 38 | 39 | class CallableType 40 | { 41 | /** 42 | * @return callable(mixed $bool): mixed 43 | */ 44 | public function returnsCallable() 45 | { 46 | } 47 | } 48 | 49 | /** @var array{int, mixed} $arrayShape1 */ 50 | $arrayShape1 = []; 51 | 52 | /** @var array{foo: mixed} $arrayShape2 */ 53 | $arrayShape2 = []; 54 | -------------------------------------------------------------------------------- /tests/input/Slevomat/TypeHints/LongTypeHints.php: -------------------------------------------------------------------------------- 1 | */ 82 | public $b; 83 | 84 | /** @var string&(integer|float) */ 85 | public $c; 86 | 87 | /** @var string|(float&integer) */ 88 | public $d; 89 | 90 | /** @var boolean[][][] */ 91 | public $e; 92 | 93 | /** @var (integer|boolean)[][][] */ 94 | public $f; 95 | 96 | /** @var integer|(string&boolean)[] */ 97 | public $g; 98 | 99 | /** @var \Foo<\Boo> */ 100 | public $h; 101 | 102 | } 103 | 104 | class CallableType 105 | { 106 | 107 | /** 108 | * @return callable(boolean $bool): (integer|float) 109 | */ 110 | public function returnsCallable() 111 | { 112 | 113 | } 114 | 115 | } 116 | 117 | /** 118 | * @return boolean - true - if some cond 119 | * false - if some other cond 120 | */ 121 | function multilineDescription() 122 | { 123 | } 124 | 125 | /** @var array{integer, boolean} $arrayShape1 */ 126 | $arrayShape1 = []; 127 | 128 | /** @var array{foo: integer, bar: boolean} $arrayShape2 */ 129 | $arrayShape2 = []; 130 | -------------------------------------------------------------------------------- /tests/input/Slevomat/TypeHints/NullTypeHintOnLastPosition.php: -------------------------------------------------------------------------------- 1 | &bool)[] */ 81 | public $d; 82 | 83 | /** @var \Foo<(null|int), (null|bool)> */ 84 | public $e; 85 | 86 | /** @var \Foo<\Foo> */ 87 | public $f; 88 | } 89 | 90 | class CallableType 91 | { 92 | /** 93 | * @return callable((null|bool) $bool): (null|int) 94 | */ 95 | public function returnsCallable() 96 | { 97 | 98 | } 99 | } 100 | 101 | /** @var array{int, (null|int), (null|bool)} $arrayShape1 */ 102 | $arrayShape1 = []; 103 | 104 | /** @var array{foo: (null|int)} $arrayShape2 */ 105 | $arrayShape2 = []; 106 | 107 | class Conditional 108 | { 109 | 110 | /** 111 | * @return (Conditional1 is Conditional2 ? (null|Conditional3) : false) 112 | */ 113 | public function withConditional() 114 | { 115 | } 116 | 117 | /** 118 | * @return ($parameter is Conditional2 ? (null|Conditional3) : false) 119 | */ 120 | public function withConditionalParameter($parameter) 121 | { 122 | } 123 | 124 | } 125 | -------------------------------------------------------------------------------- /tests/input/Slevomat/TypeHints/NullableTypeForNullDefaultValue.php: -------------------------------------------------------------------------------- 1 | $int; 17 | 18 | interface Foo 19 | { 20 | 21 | public function doFoo(int $int = null); 22 | 23 | } 24 | 25 | class FooBar extends Anything 26 | { 27 | 28 | public function invalid(bool $bool = null) 29 | { 30 | 31 | } 32 | 33 | public function myself(self $self = null) 34 | { 35 | 36 | } 37 | 38 | public function array(array $array = null) 39 | { 40 | 41 | } 42 | 43 | public function parent(parent $parent = null) 44 | { 45 | 46 | } 47 | 48 | public function callable(callable $callable = null) 49 | { 50 | 51 | } 52 | 53 | public function withNullableParamBefore(?float $float, \Foo\Bar\Baz $param1 = null) 54 | { 55 | 56 | } 57 | 58 | public function withParamAfter(bool $param2 = null, ?array & ... $ellipsis) 59 | { 60 | 61 | } 62 | 63 | public function reference(float & $ref = null) 64 | { 65 | 66 | } 67 | 68 | public function weirdDefinition(float&$ref=null) 69 | { 70 | 71 | } 72 | } -------------------------------------------------------------------------------- /tests/input/Slevomat/TypeHints/ParameterTypeHint.php: -------------------------------------------------------------------------------- 1 | $a 117 | */ 118 | public function genericWithoutItemsSpecification(\Generic $a) 119 | { 120 | 121 | } 122 | 123 | /** 124 | * @param array[]&\Traversable $a 125 | */ 126 | public function traversableIntersection($a) 127 | { 128 | } 129 | 130 | /** 131 | * @param \Traversable&array[] $a 132 | */ 133 | public function traversableIntersectionDifferentOrder($a) 134 | { 135 | } 136 | 137 | /** 138 | * @param null|\Traversable $a 139 | */ 140 | public function traversableNull($a) 141 | { 142 | } 143 | 144 | /** 145 | * @param object $a 146 | */ 147 | public function objectParameter($a) 148 | { 149 | } 150 | 151 | /** 152 | * @param array|array $a 153 | */ 154 | public function unionWithSameBase($a) 155 | { 156 | } 157 | 158 | /** 159 | * @param array|array|array $a 160 | */ 161 | public function unionWithSameBaseAndMoreTypes($a) 162 | { 163 | } 164 | 165 | /** 166 | * @param array|bool[] $a 167 | */ 168 | public function unionWithSameBaseToo($a) 169 | { 170 | } 171 | 172 | /** 173 | * @param array|array|array|null $a 174 | */ 175 | public function unionWithSameNullableBase($a) 176 | { 177 | } 178 | 179 | /** 180 | * @param ?int $a 181 | */ 182 | public function nullable($a) 183 | { 184 | } 185 | 186 | /** 187 | * @param mixed[]|array $a 188 | */ 189 | public function traversableArray($a) 190 | { 191 | } 192 | 193 | /** @param string $a */ 194 | public function oneLineDocComment(string $a) 195 | { 196 | } 197 | 198 | /** @param true $a */ 199 | public function constTrue($a) 200 | { 201 | } 202 | 203 | /** @param FALSE $a */ 204 | public function constFalse($a) 205 | { 206 | } 207 | 208 | /** @param 0 $a */ 209 | public function constInteger($a) 210 | { 211 | } 212 | 213 | /** @param 0.0 $a */ 214 | public function constFloat($a) 215 | { 216 | } 217 | 218 | /** @param 'foo' $a */ 219 | public function constString($a) 220 | { 221 | } 222 | 223 | /** @param 'foo'|null $a */ 224 | public function constNullableString($a) 225 | { 226 | } 227 | 228 | /** @param 'foo'|'bar' $a */ 229 | public function constUnionString($a) 230 | { 231 | } 232 | 233 | /** @param class-string $a */ 234 | public function classString($a) 235 | { 236 | } 237 | 238 | /** @param mixed $a */ 239 | public function mixedType($a) 240 | { 241 | } 242 | 243 | /** @param mixed|null $a */ 244 | public function nullableMixedType($a) 245 | { 246 | } 247 | 248 | /** 249 | * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.UselessAnnotation 250 | * @param string[] $a 251 | */ 252 | public function uselessSuppressOfUselessAnnotation(array $a) 253 | { 254 | } 255 | 256 | /** 257 | * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingTraversableTypeHintSpecification 258 | * @param string[] $a 259 | */ 260 | public function uselessSuppressOfMissingTraversableTypeHintSpecification(array $a) 261 | { 262 | } 263 | 264 | /** 265 | * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingAnyTypeHint 266 | * @phpstan-param class-string $a 267 | */ 268 | public function uselessSuppressOfMissingAnyTypeHintWithTypeHint(string $a) 269 | { 270 | } 271 | 272 | /** 273 | * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint 274 | * @phpstan-param class-string $a 275 | */ 276 | public function uselessSuppressOfMissingNativeTypeHintWithTypeHint(string $a) 277 | { 278 | } 279 | 280 | /** 281 | * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint 282 | * @param scalar $a 283 | */ 284 | public function uselessSuppressOfMissingNativeTypeHint($a) 285 | { 286 | } 287 | 288 | /** 289 | * @param ?int $a 290 | */ 291 | public function uselessAnnotationWithShortNullable(?int $a) 292 | { 293 | } 294 | } 295 | -------------------------------------------------------------------------------- /tests/input/Slevomat/TypeHints/ParameterTypeHintSpacing.php: -------------------------------------------------------------------------------- 1 | $a; 21 | 22 | fn (int|false $a, null|string $b) => $a; 23 | -------------------------------------------------------------------------------- /tests/input/Slevomat/TypeHints/PropertyTypeHint.php: -------------------------------------------------------------------------------- 1 | 126 | */ 127 | public function genericWithoutItemsSpecification(): \Generic 128 | { 129 | return new \Generic; 130 | } 131 | 132 | /** 133 | * @return array[]&\Traversable 134 | */ 135 | public function traversableIntersection() 136 | { 137 | return new \ArrayIterator(); 138 | } 139 | 140 | /** 141 | * @return \Traversable&array[] 142 | */ 143 | public function traversableIntersectionDifferentOrder() 144 | { 145 | return new \ArrayIterator(); 146 | } 147 | 148 | /** 149 | * @return null|\Traversable 150 | */ 151 | public function traversableNull() 152 | { 153 | return new \ArrayIterator(); 154 | } 155 | 156 | /** 157 | * @return object 158 | */ 159 | public function returnsObject() 160 | { 161 | return new \stdClass(); 162 | } 163 | 164 | /** 165 | * @return ?int 166 | */ 167 | public function nullable() 168 | { 169 | } 170 | 171 | /** 172 | * @return mixed[]|array 173 | */ 174 | public function traversableArray() 175 | { 176 | } 177 | 178 | /** @return string */ 179 | public function oneLineDocComment(): string 180 | { 181 | return 'hi'; 182 | } 183 | 184 | /** @return true */ 185 | public function constTrue() 186 | { 187 | } 188 | 189 | /** @return FALSE */ 190 | public function constFalse() 191 | { 192 | } 193 | 194 | /** @return 0 */ 195 | public function constInteger() 196 | { 197 | } 198 | 199 | /** @return 0.0 */ 200 | public function constFloat() 201 | { 202 | } 203 | 204 | /** @return 'foo' */ 205 | public function constString() 206 | { 207 | } 208 | 209 | /** @return 'foo'|null */ 210 | public function constNullableString() 211 | { 212 | } 213 | 214 | /** @return 'foo'|'bar' */ 215 | public function constUnionString() 216 | { 217 | } 218 | 219 | /** @return class-string */ 220 | public function classString() 221 | { 222 | } 223 | 224 | /** @return static */ 225 | public function staticReference() 226 | { 227 | } 228 | 229 | /** @return mixed */ 230 | public function returnsMixed() 231 | { 232 | } 233 | 234 | /** @return mixed|null */ 235 | public function returnsNullableMixed() 236 | { 237 | } 238 | 239 | /** 240 | * @return void 241 | */ 242 | public function voidButReturnsValue() 243 | { 244 | return true; 245 | } 246 | 247 | /** 248 | * @return no-return 249 | */ 250 | public function noReturnTypeHint() 251 | { 252 | } 253 | 254 | /** 255 | * @return ?int 256 | */ 257 | public function uselessAnnotationWithShortNullable(): ?int 258 | { 259 | return 0; 260 | } 261 | 262 | /** 263 | * @return (Conditional is Conditional2 ? array : iterable) 264 | */ 265 | public function withConditional(): array 266 | { 267 | return []; 268 | } 269 | } 270 | -------------------------------------------------------------------------------- /tests/input/Slevomat/TypeHints/UselessConstantTypeHint.php: -------------------------------------------------------------------------------- 1 | >= 1; 64 | return $l; 65 | }; 66 | 67 | function () { 68 | $m .= 1; 69 | return $m; 70 | }; 71 | 72 | function sameVariableInDifferentScope() { 73 | $n = array_map(function () { 74 | return $n + 1; 75 | }, []); 76 | 77 | return $n; 78 | } 79 | 80 | function moreVariableOneWithoutAssigment() { 81 | $o++; 82 | $o = 10; 83 | 84 | return $o; 85 | } 86 | 87 | function assigmentAsFunctionParametr() { 88 | doSomething($p = 0); 89 | return $p; 90 | } 91 | 92 | function assigmentAfterAssignment() { 93 | doSomething($qq = $q = 0); 94 | return $q; 95 | } 96 | 97 | function afterIfStatement(float $seconds): string 98 | { 99 | if ($seconds < 1) { 100 | return round($seconds * 1000, 2) . 'ms'; 101 | } 102 | 103 | $r = round($seconds, 2) . 's'; 104 | return $r; 105 | } 106 | 107 | $z = null; 108 | return $z; 109 | -------------------------------------------------------------------------------- /tests/input/Slevomat/Whitespaces/DuplicateSpaces.php: -------------------------------------------------------------------------------- 1 | [ 14 | '2' => 2, 15 | 1 => '1', 16 | ], 17 | 4 => [ 18 | 7, 19 | 8, 20 | 9, 21 | ], 22 | ]; 23 | -------------------------------------------------------------------------------- /tests/input/concatenation_spacing.php: -------------------------------------------------------------------------------- 1 | 1, 18 | 'bar' => 2, 19 | 'baz' => 3, 20 | ]; 21 | -------------------------------------------------------------------------------- /tests/input/namespaces-spacing.php: -------------------------------------------------------------------------------- 1 | sub(new DateInterval('P1D')) 12 | ->format(DATE_RFC3339) 13 | ); 14 | -------------------------------------------------------------------------------- /tests/input/new_with_parentheses.php: -------------------------------------------------------------------------------- 1 | foo = 'Foo'; 12 | $foo = new $classNamesInObject->foo; 13 | 14 | $whitespaceBetweenClassNameAndParentheses = new stdClass ; 15 | 16 | $x = [ 17 | new stdClass, 18 | ]; 19 | 20 | $y = [new stdClass]; 21 | 22 | $z = new stdClass ? new stdClass : new stdClass; 23 | 24 | $q = $q ?: new stdClass; 25 | $e = $e ?? new stdClass; 26 | -------------------------------------------------------------------------------- /tests/input/not_spacing.php: -------------------------------------------------------------------------------- 1 | 0) { 8 | echo 1; 9 | } elseif ( !$test === 0) { 10 | echo 0; 11 | } else { 12 | echo -1; 13 | } 14 | 15 | while ( ! true) { 16 | echo 1; 17 | } 18 | 19 | do { 20 | echo 1; 21 | } while ( ! true); 22 | -------------------------------------------------------------------------------- /tests/input/null_coalesce_operator.php: -------------------------------------------------------------------------------- 1 | select() 9 | ->from() 10 | ->where() 11 | ; 12 | --------------------------------------------------------------------------------