├── .github ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── ci.yml ├── .license ├── GlueStreamSpecific ├── Sniffs │ └── Classes │ │ ├── AbstractStringInConstantOnlySniff.php │ │ └── DependencyProviderStringInConstantOnlySniff.php └── ruleset.xml ├── LICENSE ├── README.md ├── Spryker ├── Sniffs │ ├── AbstractSniffs │ │ ├── AbstractApiClassDetectionSprykerSniff.php │ │ ├── AbstractClassDetectionSprykerSniff.php │ │ ├── AbstractMethodAnnotationSniff.php │ │ └── AbstractSprykerSniff.php │ ├── Arrays │ │ └── DisallowImplicitArrayCreationSniff.php │ ├── Classes │ │ ├── ClassFileNameSniff.php │ │ ├── MethodArgumentDefaultValueSniff.php │ │ ├── MethodDeclarationSniff.php │ │ ├── MethodTypeHintSniff.php │ │ ├── PropertyDefaultValueSniff.php │ │ ├── ReturnTypeHintSniff.php │ │ └── SelfAccessorSniff.php │ ├── Commenting │ │ ├── AttributesSniff.php │ │ ├── DisallowArrayTypeHintSyntaxSniff.php │ │ ├── DocBlockApiAnnotationSniff.php │ │ ├── DocBlockConstSniff.php │ │ ├── DocBlockConstructorSniff.php │ │ ├── DocBlockInheritSniff.php │ │ ├── DocBlockNoEmptySniff.php │ │ ├── DocBlockNoInlineAlignmentSniff.php │ │ ├── DocBlockParamAllowDefaultValueSniff.php │ │ ├── DocBlockParamArraySniff.php │ │ ├── DocBlockParamNotJustNullSniff.php │ │ ├── DocBlockParamSniff.php │ │ ├── DocBlockPipeSpacingSniff.php │ │ ├── DocBlockReturnNullSniff.php │ │ ├── DocBlockReturnNullableTypeSniff.php │ │ ├── DocBlockReturnSelfSniff.php │ │ ├── DocBlockReturnTagSniff.php │ │ ├── DocBlockReturnVoidSniff.php │ │ ├── DocBlockSniff.php │ │ ├── DocBlockStructureSniff.php │ │ ├── DocBlockTagGroupingSniff.php │ │ ├── DocBlockTagIterableSniff.php │ │ ├── DocBlockTagOrderSniff.php │ │ ├── DocBlockTagSniff.php │ │ ├── DocBlockTestGroupAnnotation2Sniff.php │ │ ├── DocBlockTestGroupAnnotationSniff.php │ │ ├── DocBlockThrowsSniff.php │ │ ├── DocBlockTypeOrderSniff.php │ │ ├── DocBlockVarNotJustNullSniff.php │ │ ├── DocBlockVarSniff.php │ │ ├── DocCommentSniff.php │ │ ├── FileDocBlockSniff.php │ │ ├── FullyQualifiedClassNameInDocBlockSniff.php │ │ ├── InlineDocBlockSniff.php │ │ ├── SprykerAnnotationSniff.php │ │ ├── SprykerConstantsSniff.php │ │ └── TypeHintSniff.php │ ├── ControlStructures │ │ ├── ConditionalExpressionOrderSniff.php │ │ ├── ControlStructureSpacingSniff.php │ │ ├── DisallowCloakingCheckSniff.php │ │ ├── ElseIfDeclarationSniff.php │ │ └── NoInlineAssignmentSniff.php │ ├── DependencyProvider │ │ └── FacadeNotInBridgeReturnedSniff.php │ ├── Factory │ │ ├── CreateVsGetMethodsSniff.php │ │ ├── NoPrivateMethodsSniff.php │ │ └── OneNewPerMethodSniff.php │ ├── Formatting │ │ ├── ArrayDeclarationSniff.php │ │ └── MethodSignatureParametersLineBreakMethodSniff.php │ ├── Internal │ │ ├── SprykerBridgeSniff.php │ │ ├── SprykerDisallowFunctionsSniff.php │ │ ├── SprykerFacadeSniff.php │ │ ├── SprykerNoDemoshopSniff.php │ │ └── SprykerPreferStaticOverSelfSniff.php │ ├── MethodAnnotation │ │ ├── ConfigMethodAnnotationSniff.php │ │ ├── EntityManagerMethodAnnotationSniff.php │ │ ├── FacadeMethodAnnotationSniff.php │ │ ├── FactoryMethodAnnotationSniff.php │ │ ├── QueryContainerMethodAnnotationSniff.php │ │ └── RepositoryMethodAnnotationSniff.php │ ├── Namespaces │ │ ├── FunctionNamespaceSniff.php │ │ ├── SprykerNamespaceSniff.php │ │ ├── SprykerNoCrossNamespaceSniff.php │ │ ├── SprykerNoPyzSniff.php │ │ ├── UseStatementSniff.php │ │ └── UseWithAliasingSniff.php │ ├── PHP │ │ ├── DeclareStrictTypesAfterFileDocSniff.php │ │ ├── DisallowFunctionsSniff.php │ │ ├── DisallowTrailingCommaInSingleLineSniff.php │ │ ├── ExitSniff.php │ │ ├── NoIsNullSniff.php │ │ ├── NotEqualSniff.php │ │ ├── PhpSapiConstantSniff.php │ │ ├── PreferCastOverFunctionSniff.php │ │ ├── RemoveFunctionAliasSniff.php │ │ ├── ShortCastSniff.php │ │ └── SingleQuoteSniff.php │ ├── Testing │ │ ├── AssertPrimitivesSniff.php │ │ ├── ExpectExceptionSniff.php │ │ └── MockSniff.php │ └── WhiteSpace │ │ ├── CommaSpacingSniff.php │ │ ├── ConcatenationSpacingSniff.php │ │ ├── DocBlockSpacingSniff.php │ │ ├── EmptyEnclosingLineSniff.php │ │ ├── EmptyLinesSniff.php │ │ ├── FunctionSpacingSniff.php │ │ ├── ImplicitCastSpacingSniff.php │ │ ├── MemberVarSpacingSniff.php │ │ ├── MethodSpacingSniff.php │ │ ├── NamespaceSpacingSniff.php │ │ ├── ObjectAttributeSpacingSniff.php │ │ └── TernarySpacingSniff.php ├── Tools │ ├── SniffsAndTests.php │ └── Tokenizer.php ├── Traits │ ├── BasicsTrait.php │ ├── BridgeTrait.php │ ├── CommentingTrait.php │ ├── NamespaceTrait.php │ ├── SignatureTrait.php │ └── UseStatementsTrait.php └── ruleset.xml ├── SprykerStrict ├── Sniffs │ └── TypeHints │ │ ├── ParameterTypeHintSniff.php │ │ ├── PropertyTypeHintSniff.php │ │ └── ReturnTypeHintSniff.php └── ruleset.xml ├── bin ├── tokenize ├── tokenize.bat └── tokenize.php ├── composer.json ├── docs ├── README.md ├── generate.php └── sniffs.md ├── phpcs.xml ├── phpstan.neon └── tests ├── Spryker └── Sniffs │ ├── AllSniffTest.php │ ├── Commenting │ ├── DisallowArrayTypeHintSyntaxSniffTest.php │ ├── DocBlockConstSniffTest.php │ ├── DocBlockParamAllowDefaultValueSniffTest.php │ ├── DocBlockParamArraySniffTest.php │ ├── DocBlockReturnNullSniffTest.php │ ├── DocBlockReturnNullableTypeSniffTest.php │ ├── DocBlockReturnTagSniffTest.php │ ├── DocBlockReturnVoidSniffTest.php │ ├── DocBlockThrowsSniffTest.php │ ├── DocBlockVarSniffTest.php │ ├── FullyQualifiedClassNameInDocBlockSniffTest.php │ ├── InlineDocBlockSniffTest.php │ └── TypeHintSniffTest.php │ ├── ControlStructures │ └── DisallowCloakingCheckSniffTest.php │ ├── Formatting │ └── MethodSignatureParametersLineBreakMethodSniffTest.php │ ├── Internal │ └── SprykerPreferStaticOverSelfSniffTest.php │ ├── Namespaces │ └── UseStatementSniffTest.php │ ├── PHP │ └── DeclareStrictTypesAfterFileDocSniffTest.php │ └── WhiteSpace │ ├── EmptyEnclosingLineSniffTest.php │ └── EmptyLinesSniffTest.php ├── TestCase.php ├── _data ├── All │ ├── after.php │ └── before.php ├── DeclareStrictTypesAfterFileDoc │ ├── after.php │ └── before.php ├── DisallowArrayTypeHintSyntax │ ├── after.php │ └── before.php ├── DisallowCloakingCheck │ ├── after.php │ └── before.php ├── DocBlockConst │ ├── after.php │ └── before.php ├── DocBlockParamAllowDefaultValue │ ├── after.php │ └── before.php ├── DocBlockParamArray │ ├── after.php │ └── before.php ├── DocBlockReturnNull │ ├── after.php │ └── before.php ├── DocBlockReturnNullableType │ ├── after.php │ └── before.php ├── DocBlockReturnTag │ ├── after.php │ └── before.php ├── DocBlockReturnVoid │ ├── after.php │ └── before.php ├── DocBlockThrows │ ├── after.php │ └── before.php ├── DocBlockVar │ ├── after.php │ └── before.php ├── EmptyEnclosingLine │ ├── after.php │ └── before.php ├── EmptyLines │ ├── after.php │ └── before.php ├── FullyQualifiedClassNameInDocBlock │ ├── after.php │ └── before.php ├── InlineDocBlock │ ├── after.php │ └── before.php ├── MethodSignatureParametersLineBreakMethod │ ├── after.php │ └── before.php ├── SprykerPreferStaticOverSelf │ ├── after.php │ └── before.php ├── TypeHint │ ├── after.php │ └── before.php └── UseStatement │ ├── after.php │ └── before.php ├── bootstrap.php ├── generate.php ├── old ├── bootstrap.php └── files │ ├── Architecture │ ├── WhitespaceComma.php │ ├── WhitespaceCommaBefore.php │ └── WhitespaceCommaPass.php │ ├── Commenting │ ├── DocBlockApiAnnotationMissingInFacade.php │ ├── DocBlockApiDocBlockMissingInFacade.php │ ├── DocBlockApiIgnoreClassPass.php │ ├── DocBlockApiPass.php │ └── DocBlockSingleLinePass.php │ └── Namespaces │ ├── UseInAlphabeticalOrderPass.php │ └── UseWithLeadingBackslashFail.php └── xmllint.sh /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## PR Description 2 | Add a meaningful description here that will let us know what you want to fix with this PR or what functionality you want to add. 3 | 4 | ## Steps before you submit a PR 5 | - Please add tests for the code you add if it's possible. 6 | - Please check out our contribution guide: https://docs.spryker.com/docs/dg/dev/code-contribution-guide.html 7 | - Add a `contribution-license-agreement.txt` file with the following content: 8 | `I hereby agree to Spryker\'s Contribution License Agreement in https://github.com/spryker/code-sniffer/blob/HASH_OF_COMMIT_YOU_ARE_BASING_YOUR_BRANCH_FROM_MASTER_BRANCH/CONTRIBUTING.md.` 9 | 10 | This is a mandatory step to make sure you are aware of the license agreement and agree to it. `HASH_OF_COMMIT_YOU_ARE_BASING_YOUR_BRANCH_FROM_MASTER_BRANCH` is a hash of the commit you are basing your branch from the master branch. You can take it from commits list of master branch before you submit a PR. 11 | 12 | ## Checklist 13 | - [x] I agree with the Code Contribution License Agreement in CONTRIBUTING.md 14 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: 7 | - master 8 | workflow_dispatch: 9 | 10 | jobs: 11 | validation: 12 | runs-on: ubuntu-22.04 13 | strategy: 14 | fail-fast: false 15 | matrix: 16 | php-version: 17 | - '8.1' 18 | - '8.3' 19 | 20 | steps: 21 | - name: Setup PHP 22 | uses: shivammathur/setup-php@v2 23 | with: 24 | php-version: ${{ matrix.php-version }} 25 | extensions: mbstring, intl, pdo_mysql 26 | 27 | - uses: actions/checkout@v3 28 | 29 | - name: Get Composer Cache Directory 30 | id: composer-cache 31 | run: | 32 | echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT 33 | 34 | - uses: actions/cache@v3 35 | with: 36 | path: ${{ steps.composer-cache.outputs.dir }} 37 | key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} 38 | restore-keys: | 39 | ${{ runner.os }}-composer- 40 | 41 | - name: Validate composer.json and composer.lock 42 | run: composer validate 43 | 44 | - name: Composer install 45 | run: composer install --optimize-autoloader 46 | 47 | - name: Run tests 48 | run: composer test 49 | 50 | - name: PHPStan checks 51 | run: composer stan 52 | 53 | - name: CodeStyle checks 54 | run: composer cs-check 55 | 56 | prefer-lowest: 57 | runs-on: ubuntu-22.04 58 | strategy: 59 | fail-fast: false 60 | matrix: 61 | php-version: 62 | - '8.1' 63 | 64 | steps: 65 | - name: Setup PHP 66 | uses: shivammathur/setup-php@v2 67 | with: 68 | php-version: ${{ matrix.php-version }} 69 | extensions: mbstring, intl, pdo_mysql 70 | 71 | - uses: actions/checkout@v3 72 | 73 | - name: Get Composer Cache Directory 74 | id: composer-cache 75 | run: | 76 | echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT 77 | 78 | - uses: actions/cache@v3 79 | with: 80 | path: ${{ steps.composer-cache.outputs.dir }} 81 | key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} 82 | restore-keys: | 83 | ${{ runner.os }}-composer- 84 | 85 | - name: Validate composer.json and composer.lock 86 | run: composer validate 87 | 88 | xml-validation: 89 | runs-on: ubuntu-22.04 90 | steps: 91 | - name: Install xmllint tool 92 | run: | 93 | sudo apt-get update 94 | sudo apt-get install -y libxml2-utils 95 | 96 | - name: Setup PHP 97 | uses: shivammathur/setup-php@v2 98 | with: 99 | php-version: '8.2' 100 | 101 | - uses: actions/checkout@v3 102 | 103 | - name: Get Composer Cache Directory 104 | id: composer-cache 105 | run: | 106 | echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT 107 | 108 | - uses: actions/cache@v3 109 | with: 110 | path: ${{ steps.composer-cache.outputs.dir }} 111 | key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} 112 | restore-keys: | 113 | ${{ runner.os }}-composer- 114 | 115 | - name: Composer install 116 | run: composer install --optimize-autoloader 117 | 118 | - name: XML checks 119 | run: composer xml 120 | -------------------------------------------------------------------------------- /.license: -------------------------------------------------------------------------------- 1 | /** 2 | * MIT License 3 | * For full license information, please view the LICENSE file that was distributed with this source code. 4 | */ 5 | -------------------------------------------------------------------------------- /GlueStreamSpecific/Sniffs/Classes/AbstractStringInConstantOnlySniff.php: -------------------------------------------------------------------------------- 1 | findNext(T_CONSTANT_ENCAPSED_STRING, $stackPtr); 31 | $tokens = $phpcsFile->getTokens(); 32 | 33 | if (!$this->isRuleApplicable($phpcsFile)) { 34 | return; 35 | } 36 | 37 | if (!$tokenIndex) { 38 | return; 39 | } 40 | 41 | if ($tokens[$tokenIndex]['level'] === 1) { 42 | return; 43 | } 44 | 45 | $error = '%s string should be introduced as a class or module constant.'; 46 | $data = [ 47 | $tokens[$stackPtr]['content'], 48 | ]; 49 | $phpcsFile->addError($error, $stackPtr, 'NoMatch', $data); 50 | } 51 | 52 | /** 53 | * @param \PHP_CodeSniffer\Files\File $phpCsFile 54 | * 55 | * @return bool 56 | */ 57 | abstract protected function isRuleApplicable(File $phpCsFile): bool; 58 | } 59 | -------------------------------------------------------------------------------- /GlueStreamSpecific/Sniffs/Classes/DependencyProviderStringInConstantOnlySniff.php: -------------------------------------------------------------------------------- 1 | getClassName($phpCsFile); 22 | $hasCorrectSuffix = (substr($className, -18) === 'DependencyProvider'); 23 | 24 | return $hasCorrectSuffix; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /GlueStreamSpecific/ruleset.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Glue specific Coding Standard (experimental). 5 | 6 | All sniffs in ./Sniffs will be auto loaded 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016-present Spryker Systems GmbH 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 | -------------------------------------------------------------------------------- /Spryker/Sniffs/Arrays/DisallowImplicitArrayCreationSniff.php: -------------------------------------------------------------------------------- 1 | getFilename(); 25 | if ($this->hasLegacyImplicitCreation($fileName)) { 26 | return; 27 | } 28 | 29 | parent::process($phpcsFile, $stackPtr); 30 | } 31 | 32 | /** 33 | * @param string $fileName 34 | * 35 | * @return bool 36 | */ 37 | protected function hasLegacyImplicitCreation(string $fileName): bool 38 | { 39 | if (strpos($fileName, DIRECTORY_SEPARATOR . 'config_') !== false || strpos($fileName, DIRECTORY_SEPARATOR . 'config.') !== false) { 40 | return true; 41 | } 42 | if (strpos($fileName, DIRECTORY_SEPARATOR . 'cronjobs' . DIRECTORY_SEPARATOR) !== false) { 43 | return true; 44 | } 45 | 46 | return false; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Spryker/Sniffs/Classes/ClassFileNameSniff.php: -------------------------------------------------------------------------------- 1 | 22 | * @author Marc McIntyre 23 | * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600) 24 | * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence 25 | * @version Release: @package_version@ 26 | * @link http://pear.php.net/package/PHP_CodeSniffer 27 | */ 28 | class ClassFileNameSniff extends AbstractSprykerSniff 29 | { 30 | /** 31 | * @inheritDoc 32 | */ 33 | public function register(): array 34 | { 35 | return [ 36 | T_CLASS, 37 | T_INTERFACE, 38 | ]; 39 | } 40 | 41 | /** 42 | * @inheritDoc 43 | */ 44 | public function process(File $phpcsFile, $stackPtr): void 45 | { 46 | $fullPath = basename($phpcsFile->getFilename()); 47 | $fileName = substr($fullPath, 0, strrpos($fullPath, '.') ?: 0); 48 | if ($fileName === '') { 49 | // No filename probably means STDIN, so we can't do this check. 50 | return; 51 | } 52 | 53 | $tokens = $phpcsFile->getTokens(); 54 | 55 | $previous = $phpcsFile->findPrevious([T_CLASS, T_INTERFACE], $stackPtr - 1); 56 | if ($previous) { 57 | // Probably more than a single declaration per file, we only check first one then. 58 | return; 59 | } 60 | $declaredNameIndex = $phpcsFile->findNext(T_STRING, $stackPtr); 61 | if ($tokens[$declaredNameIndex]['content'] === $fileName) { 62 | return; 63 | } 64 | $error = '%s name "%s" doesn\'t match filename, expected "%s"'; 65 | $data = [ 66 | ucfirst($tokens[$stackPtr]['content']), 67 | $tokens[$declaredNameIndex]['content'], 68 | $fileName, 69 | ]; 70 | $phpcsFile->addError($error, $stackPtr, 'NoMatch', $data); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /Spryker/Sniffs/Classes/MethodTypeHintSniff.php: -------------------------------------------------------------------------------- 1 | getTokens(); 35 | 36 | $openParenthesisIndex = $phpcsFile->findNext(T_OPEN_PARENTHESIS, $stackPtr + 1); 37 | $closeParenthesisIndex = $tokens[$openParenthesisIndex]['parenthesis_closer']; 38 | 39 | $colonIndex = $phpcsFile->findNext(Tokens::$emptyTokens, $closeParenthesisIndex + 1, null, true); 40 | if (!$colonIndex) { 41 | return; 42 | } 43 | 44 | $startIndex = $phpcsFile->findNext(Tokens::$emptyTokens, $colonIndex + 1, $colonIndex + 3, true); 45 | if (!$startIndex) { 46 | return; 47 | } 48 | 49 | $lastIndex = null; 50 | $j = $startIndex; 51 | $extractedUseStatement = ''; 52 | while (true) { 53 | if (!$this->isGivenKind([T_NS_SEPARATOR, T_STRING, T_RETURN_TYPE], $tokens[$j])) { 54 | break; 55 | } 56 | 57 | $lastIndex = $j; 58 | $extractedUseStatement .= $tokens[$j]['content']; 59 | ++$j; 60 | } 61 | 62 | if ($lastIndex === null) { 63 | return; 64 | } 65 | 66 | $extractedClassName = ltrim($extractedUseStatement, '\\'); 67 | if ($extractedClassName !== $this->getCurrentClassName($phpcsFile)) { 68 | return; 69 | } 70 | 71 | $fix = $phpcsFile->addFixableError('Own class/interface should be referred to as "self".', $startIndex, 'WrongSelf'); 72 | if (!$fix) { 73 | return; 74 | } 75 | 76 | $phpcsFile->fixer->replaceToken($startIndex, 'self'); 77 | } 78 | 79 | /** 80 | * @param \PHP_CodeSniffer\Files\File $phpCsFile 81 | * 82 | * @return string 83 | */ 84 | protected function getCurrentClassName(File $phpCsFile): string 85 | { 86 | $fullClassName = parent::getClassName($phpCsFile); 87 | 88 | return substr($fullClassName, strrpos($fullClassName, '\\') + 1); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Spryker/Sniffs/Classes/PropertyDefaultValueSniff.php: -------------------------------------------------------------------------------- 1 | findPrevious(T_WHITESPACE, $stackPtr - 1, null, true); 34 | if (!$visibilityIndex) { 35 | return; 36 | } 37 | 38 | $tokens = $phpcsFile->getTokens(); 39 | if (!$this->isGivenKind([T_PUBLIC, T_PRIVATE, T_PROTECTED, T_ABSTRACT], $tokens[$visibilityIndex])) { 40 | return; 41 | } 42 | 43 | $semicolonIndex = $phpcsFile->findNext(T_SEMICOLON, $stackPtr + 1); 44 | if (!$semicolonIndex || $semicolonIndex === $stackPtr + 1) { 45 | return; 46 | } 47 | 48 | $defaultValueIndex = $phpcsFile->findPrevious(T_WHITESPACE, $semicolonIndex - 1, $stackPtr + 1, true); 49 | if (!$defaultValueIndex || $tokens[$defaultValueIndex]['code'] !== T_NULL) { 50 | return; 51 | } 52 | 53 | $fix = $phpcsFile->addFixableError('Unnecessary default value for `' . $tokens[$stackPtr]['content'] . '`', $defaultValueIndex, 'Unnecessary'); 54 | if (!$fix) { 55 | return; 56 | } 57 | 58 | $phpcsFile->fixer->beginChangeset(); 59 | for ($i = $stackPtr + 1; $i < $semicolonIndex; $i++) { 60 | $phpcsFile->fixer->replaceToken($i, ''); 61 | } 62 | $phpcsFile->fixer->endChangeset(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Spryker/Sniffs/Commenting/AttributesSniff.php: -------------------------------------------------------------------------------- 1 | findNext(Tokens::$emptyTokens, $stackPointer + 1, null, true); 35 | if (!$nextIndex) { 36 | return; 37 | } 38 | 39 | $tokens = $phpCsFile->getTokens(); 40 | 41 | if ($tokens[$nextIndex]['code'] === T_NS_SEPARATOR) { 42 | return; 43 | } 44 | 45 | $phpCsFile->addError('FQCN expected for attribute', $nextIndex, 'ExpectedFQCN'); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Spryker/Sniffs/Commenting/DocBlockConstructorSniff.php: -------------------------------------------------------------------------------- 1 | getTokens(); 38 | 39 | $nextIndex = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true); 40 | if ($tokens[$nextIndex]['content'] !== '__construct' && $tokens[$nextIndex]['content'] !== '__destruct') { 41 | return; 42 | } 43 | 44 | $docBlockEndIndex = $this->findRelatedDocBlock($phpcsFile, $stackPtr); 45 | if (!$docBlockEndIndex) { 46 | return; 47 | } 48 | 49 | $tokens = $phpcsFile->getTokens(); 50 | 51 | $docBlockStartIndex = $tokens[$docBlockEndIndex]['comment_opener']; 52 | 53 | $firstLineIndex = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $docBlockStartIndex, $docBlockEndIndex); 54 | if (!$firstLineIndex || $tokens[$firstLineIndex]['line'] !== $tokens[$docBlockStartIndex]['line'] + 1) { 55 | return; 56 | } 57 | 58 | if (!preg_match('/^\w+ (constructor|destructor)\.$/i', $tokens[$firstLineIndex]['content'])) { 59 | return; 60 | } 61 | 62 | $fix = $phpcsFile->addFixableError('Doc Block has unneeded header line.', $firstLineIndex, 'UnneededNoise'); 63 | if (!$fix) { 64 | return; 65 | } 66 | 67 | $phpcsFile->fixer->beginChangeset(); 68 | 69 | $phpcsFile->fixer->replaceToken($firstLineIndex, ''); 70 | 71 | $index = $firstLineIndex; 72 | while ($tokens[$index - 1]['line'] === $tokens[$firstLineIndex]['line']) { 73 | $index--; 74 | $phpcsFile->fixer->replaceToken($index, ''); 75 | } 76 | $index = $firstLineIndex; 77 | while ($tokens[$index + 1]['line'] === $tokens[$firstLineIndex]['line']) { 78 | $index++; 79 | $phpcsFile->fixer->replaceToken($index, ''); 80 | } 81 | 82 | $phpcsFile->fixer->endChangeset(); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /Spryker/Sniffs/Commenting/DocBlockNoEmptySniff.php: -------------------------------------------------------------------------------- 1 | getTokens(); 34 | 35 | if (empty($tokens[$stackPtr]['comment_closer'])) { 36 | return; 37 | } 38 | 39 | $endIndex = $tokens[$stackPtr]['comment_closer']; 40 | 41 | $this->assertNonEmptyDocBlock($phpcsFile, $stackPtr, $endIndex); 42 | $this->assertNoEmptyTag($phpcsFile, $stackPtr, $endIndex); 43 | } 44 | 45 | /** 46 | * @param \PHP_CodeSniffer\Files\File $phpcsFile 47 | * @param int $stackPtr 48 | * @param int $endIndex 49 | * 50 | * @return void 51 | */ 52 | protected function assertNonEmptyDocBlock(File $phpcsFile, int $stackPtr, int $endIndex): void 53 | { 54 | $nextIndex = $phpcsFile->findNext([T_WHITESPACE, T_DOC_COMMENT_WHITESPACE, T_DOC_COMMENT_STAR], $stackPtr + 1, $endIndex - 1, true); 55 | if ($nextIndex) { 56 | return; 57 | } 58 | 59 | $fix = $phpcsFile->addFixableError('There should be no empty docblocks.', $stackPtr, 'Superfluous'); 60 | if ($fix) { 61 | for ($i = $stackPtr; $i <= $endIndex; $i++) { 62 | $phpcsFile->fixer->replaceToken($i, ''); 63 | } 64 | } 65 | } 66 | 67 | /** 68 | * @param \PHP_CodeSniffer\Files\File $phpcsFile 69 | * @param int $stackPtr 70 | * @param int $endIndex 71 | * 72 | * @return void 73 | */ 74 | protected function assertNoEmptyTag(File $phpcsFile, int $stackPtr, int $endIndex): void 75 | { 76 | $tokens = $phpcsFile->getTokens(); 77 | 78 | $index = $stackPtr; 79 | while ($index < $endIndex) { 80 | $nextIndex = $phpcsFile->findNext([T_DOC_COMMENT_STRING], $index + 1, $endIndex); 81 | if (!$nextIndex) { 82 | return; 83 | } 84 | $index = $nextIndex; 85 | 86 | if (empty($tokens[$index]['content']) || $tokens[$index]['content'] !== '@') { 87 | continue; 88 | } 89 | 90 | $fix = $phpcsFile->addFixableError('Empty Doc Block Tag', $index, 'Empty'); 91 | if (!$fix) { 92 | continue; 93 | } 94 | 95 | $phpcsFile->fixer->replaceToken($index, ''); 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Spryker/Sniffs/Commenting/DocBlockNoInlineAlignmentSniff.php: -------------------------------------------------------------------------------- 1 | getTokens(); 35 | 36 | if ($tokens[$stackPtr]['code'] === T_DOC_COMMENT_STRING) { 37 | $this->checkDescription($phpcsFile, $stackPtr); 38 | } 39 | if ($tokens[$stackPtr]['code'] === T_DOC_COMMENT_TAG) { 40 | $this->checkTag($phpcsFile, $stackPtr); 41 | } 42 | } 43 | 44 | /** 45 | * @param \PHP_CodeSniffer\Files\File $phpcsFile 46 | * @param int $stackPtr 47 | * 48 | * @return void 49 | */ 50 | protected function checkTag(File $phpcsFile, int $stackPtr): void 51 | { 52 | $tokens = $phpcsFile->getTokens(); 53 | 54 | $followingWhitespace = (int)$phpcsFile->findNext(T_DOC_COMMENT_WHITESPACE, $stackPtr + 1, $stackPtr + 2); 55 | if (!$followingWhitespace || $tokens[$followingWhitespace]['line'] !== $tokens[$stackPtr]['line']) { 56 | return; 57 | } 58 | 59 | // Skip for file doc blocks 60 | $namespaceStatement = $this->getNamespaceStatement($phpcsFile); 61 | if (!$namespaceStatement || $stackPtr < $namespaceStatement['start']) { 62 | return; 63 | } 64 | 65 | $content = $tokens[$followingWhitespace]['content']; 66 | if (strpos($content, ' ') === false || $content === ' ') { 67 | return; 68 | } 69 | 70 | $fix = $phpcsFile->addFixableError('There should be no additional whitespace around doc block tag types.', $stackPtr, 'WhitespaceAroundTypes'); 71 | if ($fix) { 72 | $phpcsFile->fixer->replaceToken($followingWhitespace, ' '); 73 | } 74 | } 75 | 76 | /** 77 | * @param \PHP_CodeSniffer\Files\File $phpcsFile 78 | * @param int $stackPtr 79 | * 80 | * @return void 81 | */ 82 | protected function checkDescription(File $phpcsFile, int $stackPtr): void 83 | { 84 | $tokens = $phpcsFile->getTokens(); 85 | 86 | $content = $tokens[$stackPtr]['content']; 87 | 88 | if (!preg_match('/\s\s+/', $content)) { 89 | return; 90 | } 91 | 92 | $fix = $phpcsFile->addFixableError('There should be no inline alignment in doc blocks descriptions.', $stackPtr, 'DocBlockInlineAlignment'); 93 | if ($fix) { 94 | $newContent = preg_replace('/\s\s+/', ' ', $content); 95 | $phpcsFile->fixer->replaceToken($stackPtr, $newContent); 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Spryker/Sniffs/Commenting/DocBlockParamNotJustNullSniff.php: -------------------------------------------------------------------------------- 1 | getTokens(); 42 | 43 | $docBlockEndIndex = $this->findRelatedDocBlock($phpCsFile, $stackPointer); 44 | 45 | if (!$docBlockEndIndex) { 46 | return; 47 | } 48 | 49 | $methodSignature = $this->getMethodSignature($phpCsFile, $stackPointer); 50 | if (!$methodSignature) { 51 | return; 52 | } 53 | 54 | $docBlockStartIndex = $tokens[$docBlockEndIndex]['comment_opener']; 55 | 56 | $paramCount = 0; 57 | for ($i = $docBlockStartIndex + 1; $i < $docBlockEndIndex; $i++) { 58 | if ($tokens[$i]['type'] !== 'T_DOC_COMMENT_TAG') { 59 | continue; 60 | } 61 | if (!in_array($tokens[$i]['content'], ['@param'], true)) { 62 | continue; 63 | } 64 | 65 | if (empty($methodSignature[$paramCount])) { 66 | continue; 67 | } 68 | $paramCount++; 69 | 70 | $classNameIndex = $i + 2; 71 | 72 | if ($tokens[$classNameIndex]['type'] !== 'T_DOC_COMMENT_STRING') { 73 | // Let another sniffer take care of the missing type 74 | continue; 75 | } 76 | 77 | $content = $tokens[$classNameIndex]['content']; 78 | 79 | $appendix = ''; 80 | $spaceIndex = strpos($content, ' '); 81 | if ($spaceIndex) { 82 | $appendix = substr($content, $spaceIndex); 83 | $content = substr($content, 0, $spaceIndex); 84 | } 85 | if (!$content || $content !== 'null') { 86 | continue; 87 | } 88 | 89 | $phpCsFile->addError('"null" as only param type does not make sense', $classNameIndex, 'NotJustNull'); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /Spryker/Sniffs/Commenting/DocBlockPipeSpacingSniff.php: -------------------------------------------------------------------------------- 1 | getTokens(); 34 | 35 | $content = $tokens[$stackPtr]['content']; 36 | 37 | $description = ''; 38 | $hint = $content; 39 | if (strpos($hint, ' ') !== false) { 40 | [$hint, $description] = explode(' ', $content, 2); 41 | } 42 | 43 | // Bugfix for https://github.com/squizlabs/PHP_CodeSniffer/issues/2613 44 | $trailingWhitespace = ''; 45 | if (!$description && $this->isInlineDocBlock($phpcsFile, $stackPtr) && preg_match('#(\s+)$#', $content, $matches)) { 46 | $trailingWhitespace = $matches[1]; 47 | } 48 | 49 | if (strpos($hint, '|') === false) { 50 | return; 51 | } 52 | 53 | $pieces = explode('|', $hint); 54 | 55 | $hints = []; 56 | foreach ($pieces as $piece) { 57 | $hints[] = trim($piece); 58 | } 59 | 60 | $desc = ltrim($description); 61 | 62 | while ($desc && mb_substr($desc, 0, 1) === '|') { 63 | $desc = ltrim(mb_substr($desc, 1)); 64 | 65 | $pos = mb_strpos($desc, ' '); 66 | if ($pos > 0) { 67 | $hints[] = trim(mb_substr($desc, 0, $pos)); 68 | $desc = ltrim(mb_substr($desc, $pos)); 69 | } else { 70 | $hints[] = $desc; 71 | $desc = ''; 72 | } 73 | } 74 | 75 | if ($desc !== '') { 76 | $desc = ' ' . $desc; 77 | } 78 | 79 | $newContent = implode('|', $hints) . $desc . $trailingWhitespace; 80 | 81 | if ($newContent !== $content) { 82 | $fix = $phpcsFile->addFixableError('There should be no space around pipes in doc blocks.', $stackPtr, 'InvalidSpaceAroundPipes'); 83 | if ($fix) { 84 | $phpcsFile->fixer->replaceToken($stackPtr, $newContent); 85 | } 86 | } 87 | } 88 | 89 | /** 90 | * @param \PHP_CodeSniffer\Files\File $phpcsFile 91 | * @param int $stackPtr 92 | * 93 | * @return bool 94 | */ 95 | protected function isInlineDocBlock(File $phpcsFile, int $stackPtr): bool 96 | { 97 | $tokens = $phpcsFile->getTokens(); 98 | 99 | $closeIndex = $phpcsFile->findNext(T_DOC_COMMENT_CLOSE_TAG, $stackPtr + 1); 100 | if (!$closeIndex) { 101 | return false; 102 | } 103 | 104 | $line = $tokens[$stackPtr]['line']; 105 | $closingLine = $tokens[$closeIndex]['line']; 106 | 107 | return $line === $closingLine; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /Spryker/Sniffs/Commenting/DocBlockReturnTagSniff.php: -------------------------------------------------------------------------------- 1 | getTokens(); 40 | 41 | if ($tokens[$stackPtr]['content'] !== '@return') { 42 | return; 43 | } 44 | 45 | $nextIndex = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $stackPtr + 1, $stackPtr + 3); 46 | if (!$nextIndex) { 47 | return; 48 | } 49 | 50 | $this->assertDescription($phpcsFile, $nextIndex, $stackPtr); 51 | } 52 | 53 | /** 54 | * @param \PHP_CodeSniffer\Files\File $phpcsFile 55 | * @param int $nextIndex 56 | * @param int $stackPtr 57 | * 58 | * @return void 59 | */ 60 | protected function assertDescription(File $phpcsFile, int $nextIndex, int $stackPtr): void 61 | { 62 | $tokens = $phpcsFile->getTokens(); 63 | 64 | $content = $tokens[$nextIndex]['content']; 65 | /** @var \PHPStan\PhpDocParser\Ast\PhpDoc\InvalidTagValueNode|\PHPStan\PhpDocParser\Ast\PhpDoc\TypelessParamTagValueNode|\PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode $valueNode */ 66 | $valueNode = static::getValueNode($tokens[$stackPtr]['content'], $content); 67 | if ($valueNode instanceof InvalidTagValueNode || $valueNode instanceof TypelessParamTagValueNode) { 68 | return; 69 | } 70 | 71 | $returnTypes = $this->valueNodeParts($valueNode); 72 | $typeString = $this->renderUnionTypes($returnTypes); 73 | 74 | if (strpos($content, $typeString) !== 0) { 75 | return; 76 | } 77 | 78 | $description = mb_substr($content, mb_strlen($typeString) + 1); 79 | if (!$description || strpos($description, '$') !== 0) { 80 | return; 81 | } 82 | 83 | $phpcsFile->addError('Description for return annotation must not start with `$`/variable. Use normal sentence instead.', $nextIndex, 'Invalid'); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Spryker/Sniffs/Commenting/DocBlockStructureSniff.php: -------------------------------------------------------------------------------- 1 | getTokens(); 39 | 40 | if ($tokens[$stackPtr]['content'] !== '/**') { 41 | $error = sprintf('Expected `/**`, got `%s`', $tokens[$stackPtr]['content']); 42 | $fix = $phpcsFile->addFixableError($error, $stackPtr, 'InvalidOpening'); 43 | if ($fix) { 44 | $phpcsFile->fixer->beginChangeset(); 45 | $phpcsFile->fixer->replaceToken($stackPtr, '/**'); 46 | $phpcsFile->fixer->endChangeset(); 47 | } 48 | } 49 | 50 | $closingTagIndex = $tokens[$stackPtr]['comment_closer']; 51 | 52 | if ($tokens[$closingTagIndex]['content'] !== '*/') { 53 | $error = sprintf('Expected `*/`, got `%s`', $tokens[$closingTagIndex]['content']); 54 | $fix = $phpcsFile->addFixableError($error, $closingTagIndex, 'InvalidClosing'); 55 | if ($fix) { 56 | $phpcsFile->fixer->beginChangeset(); 57 | $phpcsFile->fixer->replaceToken($closingTagIndex, '*/'); 58 | $phpcsFile->fixer->endChangeset(); 59 | } 60 | } 61 | 62 | if ($tokens[$closingTagIndex]['line'] === $tokens[$stackPtr]['line']) { 63 | return; 64 | } 65 | 66 | $nextIndex = $phpcsFile->findNext(T_DOC_COMMENT_WHITESPACE, $stackPtr + 1, $closingTagIndex, true); 67 | if (!$nextIndex) { 68 | return; 69 | } 70 | 71 | if ($tokens[$nextIndex]['type'] === 'T_DOC_COMMENT_STAR') { 72 | return; 73 | } 74 | 75 | $fix = $phpcsFile->addFixableError('Doc block beginning invalid.', $stackPtr, 'Invalid'); 76 | if (!$fix) { 77 | return; 78 | } 79 | 80 | $phpcsFile->fixer->beginChangeset(); 81 | 82 | $level = $tokens[$stackPtr]['level']; 83 | 84 | $index = $nextIndex; 85 | while ($index > $stackPtr + 1) { 86 | $index--; 87 | $phpcsFile->fixer->replaceToken($index, ''); 88 | } 89 | 90 | $phpcsFile->fixer->addNewline($stackPtr); 91 | $phpcsFile->fixer->addContent($stackPtr, str_repeat(' ', $level * 4)); 92 | $phpcsFile->fixer->addContent($stackPtr, ' * '); 93 | 94 | $phpcsFile->fixer->endChangeset(); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /Spryker/Sniffs/Commenting/DocBlockTagIterableSniff.php: -------------------------------------------------------------------------------- 1 | . Also nesting, e.g. type>. 17 | */ 18 | class DocBlockTagIterableSniff implements Sniff 19 | { 20 | use CommentingTrait; 21 | 22 | /** 23 | * @inheritDoc 24 | */ 25 | public function register(): array 26 | { 27 | return [ 28 | T_DOC_COMMENT_TAG, 29 | ]; 30 | } 31 | 32 | /** 33 | * @inheritDoc 34 | */ 35 | public function process(File $phpcsFile, $stackPtr): void 36 | { 37 | $tokens = $phpcsFile->getTokens(); 38 | 39 | $content = $tokens[$stackPtr]['content']; 40 | 41 | $tag = $content; 42 | if (strpos($tag, ' ') !== false) { 43 | [$tag, $description] = explode(' ', $content, 2); 44 | } 45 | 46 | if (!preg_match('#^@(?:[a-z]+-)?(?:param|return|var)\b#i', $tag)) { 47 | return; 48 | } 49 | 50 | $possibleTextIndex = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $stackPtr + 1, $stackPtr + 3, false, null, true); 51 | if (!$possibleTextIndex) { 52 | return; 53 | } 54 | 55 | $this->assertType($phpcsFile, $possibleTextIndex, $tag); 56 | } 57 | 58 | /** 59 | * @param \PHP_CodeSniffer\Files\File $phpcsFile 60 | * @param int $stackPtr 61 | * @param string $tag 62 | * 63 | * @return void 64 | */ 65 | protected function assertType(File $phpcsFile, int $stackPtr, string $tag): void 66 | { 67 | $tokens = $phpcsFile->getTokens(); 68 | 69 | $content = $tokens[$stackPtr]['content']; 70 | if (!$this->containsIterableSyntax([$content])) { 71 | return; 72 | } 73 | 74 | preg_match('#^(\w+)<(.+)>\s*(.*)$#', $content, $matches); 75 | if (!$matches) { 76 | return; 77 | } 78 | 79 | $type = $matches[1]; 80 | $definition = $matches[2]; 81 | $appendix = $matches[3]; 82 | 83 | $correctDefinition = $this->assertDefinition($definition); 84 | 85 | if ($definition === $correctDefinition) { 86 | return; 87 | } 88 | 89 | $message = sprintf('Definition of tag `%s` is not expected `%s`, but `%s`.', $tag, $correctDefinition, $definition); 90 | $fix = $phpcsFile->addFixableError($message, $stackPtr, 'Definition'); 91 | if (!$fix) { 92 | return; 93 | } 94 | 95 | $phpcsFile->fixer->beginChangeset(); 96 | 97 | $fixedTag = $type . '<' . $correctDefinition . '>'; 98 | if ($appendix) { 99 | $fixedTag .= ' ' . trim($appendix); 100 | } 101 | 102 | $phpcsFile->fixer->replaceToken($stackPtr, $fixedTag); 103 | 104 | $phpcsFile->fixer->endChangeset(); 105 | } 106 | 107 | /** 108 | * @param string $definition 109 | * 110 | * @return string 111 | */ 112 | protected function assertDefinition(string $definition): string 113 | { 114 | return (string)preg_replace_callback('#,([^ ])#', function ($matches) { 115 | return ', ' . $matches[1]; 116 | }, $definition); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /Spryker/Sniffs/Commenting/DocBlockTagSniff.php: -------------------------------------------------------------------------------- 1 | getTokens(); 45 | 46 | $content = $tokens[$stackPtr]['content']; 47 | 48 | $description = ''; 49 | $tag = $content; 50 | if (strpos($tag, ' ') !== false) { 51 | [$tag, $description] = explode(' ', $content, 2); 52 | } 53 | 54 | if (!preg_match('#^@[a-z]+.+$#i', $tag)) { 55 | $phpcsFile->addError('Invalid tag `' . $tag . '`', $stackPtr, 'Invalid'); 56 | 57 | return; 58 | } 59 | 60 | $this->assertInheritDocCasing($phpcsFile, $stackPtr, $tag, $description); 61 | } 62 | 63 | /** 64 | * @param \PHP_CodeSniffer\Files\File $phpcsFile 65 | * @param int $stackPtr 66 | * @param string $tag 67 | * @param string $description 68 | * 69 | * @return void 70 | */ 71 | protected function assertInheritDocCasing(File $phpcsFile, int $stackPtr, string $tag, string $description): void 72 | { 73 | if ($tag === static::INHERIT_DOC_FULL) { 74 | return; 75 | } 76 | 77 | $fixedTag = str_ireplace(static::INHERIT_DOC_FULL_INVALID, static::INHERIT_DOC_FULL, $tag); 78 | 79 | if ($fixedTag === $tag) { 80 | return; 81 | } 82 | 83 | $message = sprintf('Casing of tag `%s` is not expected casing `%s`.', $tag, static::INHERIT_DOC_FULL); 84 | $fix = $phpcsFile->addFixableWarning($message, $stackPtr, 'Casing'); 85 | if (!$fix) { 86 | return; 87 | } 88 | 89 | $phpcsFile->fixer->beginChangeset(); 90 | 91 | if ($description) { 92 | $fixedTag .= ' ' . $description; 93 | } 94 | 95 | $phpcsFile->fixer->replaceToken($stackPtr, $fixedTag); 96 | 97 | $phpcsFile->fixer->endChangeset(); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /Spryker/Sniffs/Commenting/DocBlockVarNotJustNullSniff.php: -------------------------------------------------------------------------------- 1 | getTokens(); 38 | 39 | $previousIndex = $phpCsFile->findPrevious(Tokens::$emptyTokens, $stackPointer - 1, null, true); 40 | if ($previousIndex && $tokens[$previousIndex]['code'] === T_STATIC) { 41 | $previousIndex = $phpCsFile->findPrevious(Tokens::$emptyTokens, $previousIndex - 1, null, true); 42 | } 43 | 44 | if (!$this->isGivenKind([T_PUBLIC, T_PROTECTED, T_PRIVATE], $tokens[$previousIndex])) { 45 | return; 46 | } 47 | 48 | $docBlockEndIndex = $this->findRelatedDocBlock($phpCsFile, $stackPointer); 49 | 50 | if (!$docBlockEndIndex) { 51 | return; 52 | } 53 | 54 | $docBlockStartIndex = $tokens[$docBlockEndIndex]['comment_opener']; 55 | 56 | $varIndex = null; 57 | for ($i = $docBlockStartIndex + 1; $i < $docBlockEndIndex; $i++) { 58 | if ($tokens[$i]['type'] !== 'T_DOC_COMMENT_TAG') { 59 | continue; 60 | } 61 | if (!in_array($tokens[$i]['content'], ['@var'], true)) { 62 | continue; 63 | } 64 | 65 | $varIndex = $i; 66 | } 67 | 68 | if (!$varIndex) { 69 | return; 70 | } 71 | 72 | $typeIndex = $varIndex + 2; 73 | 74 | $content = $tokens[$typeIndex]['content']; 75 | $spaceIndex = strpos($content, ' '); 76 | if ($spaceIndex) { 77 | $content = substr($content, 0, $spaceIndex); 78 | } 79 | 80 | if (!$content) { 81 | return; 82 | } 83 | 84 | if ($content !== 'null') { 85 | return; 86 | } 87 | 88 | $phpCsFile->addError('Doc Block type `' . $content . '` for annotation @var not enough.', $stackPointer, 'VarTypeIncorrect'); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Spryker/Sniffs/ControlStructures/ConditionalExpressionOrderSniff.php: -------------------------------------------------------------------------------- 1 | getTokens(); 36 | 37 | $prevIndex = $phpCsFile->findPrevious(Tokens::$emptyTokens, ($stackPointer - 1), null, true); 38 | if (!in_array($tokens[$prevIndex]['code'], [T_TRUE, T_FALSE, T_NULL, T_LNUMBER, T_CONSTANT_ENCAPSED_STRING])) { 39 | return; 40 | } 41 | 42 | $prevIndex = $phpCsFile->findPrevious(Tokens::$emptyTokens, ($prevIndex - 1), null, true); 43 | if (!$prevIndex) { 44 | return; 45 | } 46 | if ($this->isGivenKind(Tokens::$arithmeticTokens, $tokens[$prevIndex])) { 47 | return; 48 | } 49 | if ($this->isGivenKind([T_STRING_CONCAT], $tokens[$prevIndex])) { 50 | return; 51 | } 52 | 53 | $error = 'Usage of Yoda conditions is not allowed. Switch the expression order.'; 54 | $prevContent = $tokens[$prevIndex]['content']; 55 | 56 | if ( 57 | !$this->isGivenKind(Tokens::$assignmentTokens, $tokens[$prevIndex]) 58 | && !$this->isGivenKind(Tokens::$booleanOperators, $tokens[$prevIndex]) 59 | && $prevContent !== '(' 60 | ) { 61 | // Not fixable 62 | $phpCsFile->addError($error, $stackPointer, 'YodaNotAllowed'); 63 | 64 | return; 65 | } 66 | 67 | //TODO 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Spryker/Sniffs/ControlStructures/ElseIfDeclarationSniff.php: -------------------------------------------------------------------------------- 1 | getTokens(); 34 | 35 | $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); 36 | if ($tokens[$next]['code'] === T_IF) { 37 | $phpcsFile->recordMetric($stackPtr, 'Use of ELSE IF or ELSEIF', 'else if'); 38 | $error = 'Usage of `else if` is not allowed, use `elseif` instead'; 39 | $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotAllowed'); 40 | 41 | if ($fix === true) { 42 | $phpcsFile->fixer->beginChangeset(); 43 | $phpcsFile->fixer->replaceToken($stackPtr, 'elseif'); 44 | for ($i = ($stackPtr + 1); $i <= $next; $i++) { 45 | $phpcsFile->fixer->replaceToken($i, ''); 46 | } 47 | 48 | $phpcsFile->fixer->endChangeset(); 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Spryker/Sniffs/Internal/SprykerNoDemoshopSniff.php: -------------------------------------------------------------------------------- 1 | isDemoshopCode($phpcsFile)) { 37 | return; 38 | } 39 | 40 | $file = $phpcsFile->getFilename(); 41 | $content = file_get_contents($file); 42 | if (!$content) { 43 | return; 44 | } 45 | 46 | if (!preg_match('/\* @project\b/', $content)) { 47 | return; 48 | } 49 | 50 | $phpcsFile->addError('No internal "project only" code should be merged into Spryker suite/demoshop.', $stackPtr, 'InvalidContent'); 51 | } 52 | 53 | /** 54 | * @param \PHP_CodeSniffer\Files\File $phpCsFile 55 | * 56 | * @return bool 57 | */ 58 | protected function isDemoshopCode(File $phpCsFile): bool 59 | { 60 | if (static::$isDemoshop !== null) { 61 | return static::$isDemoshop; 62 | } 63 | 64 | $positionSprykerCore = strpos($phpCsFile->getFilename(), '/src/'); 65 | if (!$positionSprykerCore) { 66 | return false; 67 | } 68 | 69 | $file = substr($phpCsFile->getFilename(), 0, $positionSprykerCore) . '/composer.json'; 70 | if (!is_file($file)) { 71 | static::$isDemoshop = false; 72 | 73 | return static::$isDemoshop; 74 | } 75 | 76 | $content = file_get_contents($file); 77 | if (!$content) { 78 | return false; 79 | } 80 | 81 | static::$isDemoshop = (bool)preg_match('#"name":\s*"(spryker/demoshop|spryker-shop/suite|spryker-shop/suite-b2c|spryker-shop/suite-b2b)"#', $content, $matches); 82 | 83 | return static::$isDemoshop; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Spryker/Sniffs/Internal/SprykerPreferStaticOverSelfSniff.php: -------------------------------------------------------------------------------- 1 | isCore($phpCsFile)) { 36 | return; 37 | } 38 | 39 | $this->assertStatic($phpCsFile, $stackPointer); 40 | } 41 | 42 | /** 43 | * @param \PHP_CodeSniffer\Files\File $phpCsFile 44 | * @param int $stackPointer 45 | * 46 | * @return void 47 | */ 48 | protected function assertStatic(File $phpCsFile, int $stackPointer): void 49 | { 50 | $tokens = $phpCsFile->getTokens(); 51 | 52 | // We skip for interface methods 53 | if (empty($tokens[$stackPointer]['scope_opener']) || empty($tokens[$stackPointer]['scope_closer'])) { 54 | return; 55 | } 56 | 57 | $scopeOpener = $tokens[$stackPointer]['scope_opener']; 58 | $scopeCloser = $tokens[$stackPointer]['scope_closer']; 59 | 60 | for ($i = $scopeOpener; $i < $scopeCloser; $i++) { 61 | // We don't want to detect throws from nested scopes, so we'll just 62 | // skip those. 63 | if (in_array($tokens[$i]['code'], [T_FN, T_CLOSURE], true)) { 64 | $i = $tokens[$i]['scope_closer']; 65 | 66 | continue; 67 | } 68 | 69 | if ($tokens[$i]['code'] !== T_SELF) { 70 | continue; 71 | } 72 | 73 | $nextIndex = $phpCsFile->findNext(Tokens::$emptyTokens, $i + 1, null, true); 74 | if (!$nextIndex || $tokens[$nextIndex]['code'] !== T_DOUBLE_COLON) { 75 | continue; 76 | } 77 | 78 | $fix = $phpCsFile->addFixableError('Please use static:: instead of self::', $i, 'StaticVsSelf'); 79 | if (!$fix) { 80 | return; 81 | } 82 | 83 | $phpCsFile->fixer->beginChangeset(); 84 | $phpCsFile->fixer->replaceToken($i, 'static'); 85 | $phpCsFile->fixer->endChangeset(); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /Spryker/Sniffs/MethodAnnotation/ConfigMethodAnnotationSniff.php: -------------------------------------------------------------------------------- 1 | getModule($phpCsFile) . 'Config'; 34 | } 35 | 36 | /** 37 | * @param \PHP_CodeSniffer\Files\File $phpCsFile 38 | * @param int $stackPointer 39 | * 40 | * @return bool 41 | */ 42 | protected function getSnifferIsApplicable(File $phpCsFile, int $stackPointer): bool 43 | { 44 | if ($this->isProvider($phpCsFile)) { 45 | return true; 46 | } 47 | 48 | if ($this->isCollectionType($phpCsFile, $stackPointer)) { 49 | return true; 50 | } 51 | 52 | if ($this->isFactory($phpCsFile, $stackPointer)) { 53 | return true; 54 | } 55 | 56 | if ($this->isPlugin($phpCsFile, $stackPointer)) { 57 | return true; 58 | } 59 | 60 | if ($this->isType($phpCsFile, $stackPointer)) { 61 | return true; 62 | } 63 | 64 | return false; 65 | } 66 | 67 | /** 68 | * @param \PHP_CodeSniffer\Files\File $phpCsFile 69 | * @param string $namespacePart 70 | * 71 | * @return string 72 | */ 73 | protected function getMethodAnnotationFileName(File $phpCsFile, string $namespacePart): string 74 | { 75 | $className = $this->getClassName($phpCsFile); 76 | $classNameParts = explode('\\', $className); 77 | $classNameParts = array_slice($classNameParts, 0, 3); 78 | $classNameParts[0] = $namespacePart; 79 | array_push($classNameParts, $this->getMethodFileAddedName($phpCsFile)); 80 | 81 | return '\\' . implode('\\', $classNameParts); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Spryker/Sniffs/MethodAnnotation/EntityManagerMethodAnnotationSniff.php: -------------------------------------------------------------------------------- 1 | getModule($phpCsFile) . 'EntityManagerInterface'; 34 | } 35 | 36 | /** 37 | * @param \PHP_CodeSniffer\Files\File $phpCsFile 38 | * @param int $stackPointer 39 | * 40 | * @return bool 41 | */ 42 | protected function getSnifferIsApplicable(File $phpCsFile, int $stackPointer): bool 43 | { 44 | if ($this->isFacade($phpCsFile, $stackPointer)) { 45 | return true; 46 | } 47 | 48 | if ($this->isFactory($phpCsFile, $stackPointer)) { 49 | return true; 50 | } 51 | 52 | return false; 53 | } 54 | 55 | /** 56 | * @param \PHP_CodeSniffer\Files\File $phpCsFile 57 | * @param string $namespacePart 58 | * 59 | * @return string 60 | */ 61 | protected function getMethodAnnotationFileName(File $phpCsFile, string $namespacePart): string 62 | { 63 | $className = $this->getClassName($phpCsFile); 64 | $classNameParts = explode('\\', $className); 65 | $classNameParts = array_slice($classNameParts, 0, 3); 66 | $classNameParts[0] = $namespacePart; 67 | array_push($classNameParts, static::LAYER_PERSISTENCE); 68 | array_push($classNameParts, $this->getMethodFileAddedName($phpCsFile)); 69 | 70 | return '\\' . implode('\\', $classNameParts); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /Spryker/Sniffs/MethodAnnotation/FacadeMethodAnnotationSniff.php: -------------------------------------------------------------------------------- 1 | getModule($phpCsFile) . 'FacadeInterface'; 34 | } 35 | 36 | /** 37 | * @param \PHP_CodeSniffer\Files\File $phpCsFile 38 | * @param int $stackPointer 39 | * 40 | * @return bool 41 | */ 42 | protected function getSnifferIsApplicable(File $phpCsFile, int $stackPointer): bool 43 | { 44 | if ($this->isController($phpCsFile, $stackPointer)) { 45 | return true; 46 | } 47 | 48 | if ($this->isCollectionType($phpCsFile, $stackPointer)) { 49 | return true; 50 | } 51 | 52 | if ($this->isConsole($phpCsFile, $stackPointer)) { 53 | return true; 54 | } 55 | 56 | if ($this->isCommunicationFactory($phpCsFile, $stackPointer)) { 57 | return true; 58 | } 59 | 60 | if ($this->isPlugin($phpCsFile, $stackPointer)) { 61 | return true; 62 | } 63 | 64 | if ($this->isType($phpCsFile, $stackPointer)) { 65 | return true; 66 | } 67 | 68 | return false; 69 | } 70 | 71 | /** 72 | * @param \PHP_CodeSniffer\Files\File $phpCsFile 73 | * @param string $namespacePart 74 | * 75 | * @return string 76 | */ 77 | protected function getMethodAnnotationFileName(File $phpCsFile, string $namespacePart): string 78 | { 79 | $className = $this->getClassName($phpCsFile); 80 | $classNameParts = explode('\\', $className); 81 | $classNameParts = array_slice($classNameParts, 0, 3); 82 | $classNameParts[0] = $namespacePart; 83 | array_push($classNameParts, static::LAYER_BUSINESS); 84 | array_push($classNameParts, $this->getMethodFileAddedName($phpCsFile)); 85 | 86 | return '\\' . implode('\\', $classNameParts); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /Spryker/Sniffs/MethodAnnotation/FactoryMethodAnnotationSniff.php: -------------------------------------------------------------------------------- 1 | getModule($phpCsFile) . $this->getLayer($phpCsFile) . 'Factory'; 34 | } 35 | 36 | /** 37 | * @param \PHP_CodeSniffer\Files\File $phpCsFile 38 | * @param int $stackPointer 39 | * 40 | * @return bool 41 | */ 42 | protected function getSnifferIsApplicable(File $phpCsFile, int $stackPointer): bool 43 | { 44 | if ($this->isController($phpCsFile, $stackPointer)) { 45 | return true; 46 | } 47 | 48 | if ($this->isCollectionType($phpCsFile, $stackPointer)) { 49 | return true; 50 | } 51 | 52 | if ($this->isConsole($phpCsFile, $stackPointer)) { 53 | return true; 54 | } 55 | 56 | if ($this->isFacade($phpCsFile, $stackPointer)) { 57 | return true; 58 | } 59 | 60 | if ($this->isPlugin($phpCsFile, $stackPointer)) { 61 | return true; 62 | } 63 | 64 | if ($this->isType($phpCsFile, $stackPointer)) { 65 | return true; 66 | } 67 | 68 | if ($this->isQueryContainer($phpCsFile, $stackPointer)) { 69 | return true; 70 | } 71 | 72 | if ($this->isRepository($phpCsFile, $stackPointer)) { 73 | return true; 74 | } 75 | 76 | if ($this->isEntityManager($phpCsFile, $stackPointer)) { 77 | return true; 78 | } 79 | 80 | return false; 81 | } 82 | 83 | /** 84 | * @param \PHP_CodeSniffer\Files\File $phpCsFile 85 | * @param string $namespacePart 86 | * 87 | * @return string 88 | */ 89 | protected function getMethodAnnotationFileName(File $phpCsFile, string $namespacePart): string 90 | { 91 | $className = $this->getClassName($phpCsFile); 92 | $classNameParts = explode('\\', $className); 93 | $classNameParts = array_slice($classNameParts, 0, 3); 94 | $classNameParts[0] = $namespacePart; 95 | array_push($classNameParts, $this->getLayer($phpCsFile)); 96 | array_push($classNameParts, $this->getMethodFileAddedName($phpCsFile)); 97 | 98 | return '\\' . implode('\\', $classNameParts); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /Spryker/Sniffs/MethodAnnotation/QueryContainerMethodAnnotationSniff.php: -------------------------------------------------------------------------------- 1 | getModule($phpCsFile) . 'QueryContainerInterface'; 34 | } 35 | 36 | /** 37 | * @param \PHP_CodeSniffer\Files\File $phpCsFile 38 | * @param int $stackPointer 39 | * 40 | * @return bool 41 | */ 42 | protected function getSnifferIsApplicable(File $phpCsFile, int $stackPointer): bool 43 | { 44 | return false; 45 | } 46 | 47 | /** 48 | * @param \PHP_CodeSniffer\Files\File $phpCsFile 49 | * @param string $namespacePart 50 | * 51 | * @return string 52 | */ 53 | protected function getMethodAnnotationFileName(File $phpCsFile, string $namespacePart): string 54 | { 55 | $className = $this->getClassName($phpCsFile); 56 | $classNameParts = explode('\\', $className); 57 | $classNameParts = array_slice($classNameParts, 0, 3); 58 | $classNameParts[0] = $namespacePart; 59 | array_push($classNameParts, static::LAYER_PERSISTENCE); 60 | array_push($classNameParts, $this->getMethodFileAddedName($phpCsFile)); 61 | 62 | return '\\' . implode('\\', $classNameParts); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Spryker/Sniffs/MethodAnnotation/RepositoryMethodAnnotationSniff.php: -------------------------------------------------------------------------------- 1 | getModule($phpCsFile) . 'RepositoryInterface'; 34 | } 35 | 36 | /** 37 | * @param \PHP_CodeSniffer\Files\File $phpCsFile 38 | * @param int $stackPointer 39 | * 40 | * @return bool 41 | */ 42 | protected function getSnifferIsApplicable(File $phpCsFile, int $stackPointer): bool 43 | { 44 | if ($this->isController($phpCsFile, $stackPointer)) { 45 | return true; 46 | } 47 | 48 | if ($this->isCollectionType($phpCsFile, $stackPointer)) { 49 | return true; 50 | } 51 | 52 | if ($this->isConsole($phpCsFile, $stackPointer)) { 53 | return true; 54 | } 55 | 56 | if ($this->isFacade($phpCsFile, $stackPointer)) { 57 | return true; 58 | } 59 | 60 | if ($this->isFactory($phpCsFile, $stackPointer)) { 61 | return true; 62 | } 63 | 64 | if ($this->isType($phpCsFile, $stackPointer)) { 65 | return true; 66 | } 67 | 68 | return false; 69 | } 70 | 71 | /** 72 | * @param \PHP_CodeSniffer\Files\File $phpCsFile 73 | * @param string $namespacePart 74 | * 75 | * @return string 76 | */ 77 | protected function getMethodAnnotationFileName(File $phpCsFile, string $namespacePart): string 78 | { 79 | $className = $this->getClassName($phpCsFile); 80 | $classNameParts = explode('\\', $className); 81 | $classNameParts = array_slice($classNameParts, 0, 3); 82 | $classNameParts[0] = $namespacePart; 83 | array_push($classNameParts, static::LAYER_PERSISTENCE); 84 | array_push($classNameParts, $this->getMethodFileAddedName($phpCsFile)); 85 | 86 | return '\\' . implode('\\', $classNameParts); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /Spryker/Sniffs/Namespaces/FunctionNamespaceSniff.php: -------------------------------------------------------------------------------- 1 | getTokens(); 32 | 33 | $tokenContent = $tokens[$stackPtr]['content']; 34 | 35 | $openingBrace = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); 36 | if (!$openingBrace || $tokens[$openingBrace]['type'] !== 'T_OPEN_PARENTHESIS') { 37 | return; 38 | } 39 | 40 | $separatorIndex = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); 41 | if (!$separatorIndex || $tokens[$separatorIndex]['type'] !== 'T_NS_SEPARATOR') { 42 | return; 43 | } 44 | 45 | // We check that this is a function but not new operator 46 | $newIndex = $phpcsFile->findPrevious([T_WHITESPACE, T_NS_SEPARATOR], ($stackPtr - 1), null, true); 47 | if (!$newIndex || in_array($tokens[$newIndex]['code'], [T_NEW, T_ATTRIBUTE], true)) { 48 | return; 49 | } 50 | 51 | // We skip for non trivial cases 52 | $previous = $phpcsFile->findPrevious(T_WHITESPACE, ($separatorIndex - 1), null, true); 53 | if (!$previous || $tokens[$previous]['type'] === 'T_STRING') { 54 | return; 55 | } 56 | 57 | $error = 'Function name ' . $tokenContent . '() found, should not be \ prefixed.'; 58 | $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NamespaceInvalid'); 59 | if ($fix) { 60 | $phpcsFile->fixer->replaceToken($separatorIndex, ''); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Spryker/Sniffs/Namespaces/SprykerNamespaceSniff.php: -------------------------------------------------------------------------------- 1 | getNamespaceStatement($phpcsFile); 56 | if (!$namespaceStatement) { 57 | return; 58 | } 59 | 60 | $filename = $fullFilename = $phpcsFile->getFilename(); 61 | if ($this->isRoot) { 62 | $filename = $this->normalizeFilename($fullFilename); 63 | } 64 | $start = '/'; 65 | if ($fullFilename !== $filename) { 66 | $start = '^'; 67 | } 68 | 69 | $pattern = '#' . $start . $this->rootDir . '/(' . $this->namespace . ')/(.+)#'; 70 | if ($this->isRoot) { 71 | $pattern = '#' . $start . $this->rootDir . '/(.+)#'; 72 | } 73 | 74 | preg_match($pattern, $filename, $matches); 75 | if (!$matches) { 76 | return; 77 | } 78 | 79 | if ($this->isRoot) { 80 | $extractedPath = $this->namespace . '/' . $matches[1]; 81 | } else { 82 | $extractedPath = $matches[1] . '/' . $matches[2]; 83 | } 84 | $pathWithoutFilename = substr($extractedPath, 0, strrpos($extractedPath, DIRECTORY_SEPARATOR) ?: 0); 85 | 86 | $namespace = $namespaceStatement['namespace']; 87 | $pathToNamespace = str_replace(DIRECTORY_SEPARATOR, '\\', $pathWithoutFilename); 88 | if ($namespace === $pathToNamespace) { 89 | return; 90 | } 91 | 92 | $error = sprintf('Namespace `%s` does not fit to folder structure `%s`', $namespace, $pathToNamespace); 93 | $phpcsFile->addError($error, $namespaceStatement['start'], 'NamespaceFolderMismatch'); 94 | } 95 | 96 | /** 97 | * Removes the current working directory (root) if possible. 98 | * 99 | * @param string $getFilename 100 | * 101 | * @return string 102 | */ 103 | protected function normalizeFilename(string $getFilename): string 104 | { 105 | return str_replace(getcwd() . DIRECTORY_SEPARATOR, '', $getFilename); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /Spryker/Sniffs/Namespaces/SprykerNoCrossNamespaceSniff.php: -------------------------------------------------------------------------------- 1 | > 33 | */ 34 | protected const INVALID_PAIRS = [ 35 | [ 36 | 'from' => self::NAMESPACE_YVES, 37 | 'to' => self::NAMESPACE_ZED, 38 | ], 39 | [ 40 | 'from' => self::NAMESPACE_ZED, 41 | 'to' => self::NAMESPACE_YVES, 42 | ], 43 | ]; 44 | 45 | /** 46 | * @inheritDoc 47 | */ 48 | public function register(): array 49 | { 50 | return [T_CLASS, T_INTERFACE, T_TRAIT]; 51 | } 52 | 53 | /** 54 | * @inheritDoc 55 | */ 56 | public function process(File $phpcsFile, $stackPtr): void 57 | { 58 | $className = $this->getClassName($phpcsFile); 59 | $namespaces = []; 60 | foreach (static::INVALID_PAIRS as $pair) { 61 | $namespaces[] = $pair['from']; 62 | } 63 | $namespaces = implode('|', $namespaces); 64 | 65 | if (!preg_match('#^\w+\\\\(' . $namespaces . ')\\\\#', $className, $matches)) { 66 | return; 67 | } 68 | 69 | if (strpos($className, 'PyzTest') === 0) { 70 | return; 71 | } 72 | 73 | $useStatements = $this->getUseStatements($phpcsFile); 74 | foreach ($useStatements as $useStatement) { 75 | $this->checkUseStatement($phpcsFile, $useStatement, $matches[1]); 76 | } 77 | } 78 | 79 | /** 80 | * @param \PHP_CodeSniffer\Files\File $phpcsFile 81 | * @param array $useStatement 82 | * @param string $applicationLayer Zed, Yves, ... 83 | * 84 | * @return void 85 | */ 86 | protected function checkUseStatement(File $phpcsFile, array $useStatement, string $applicationLayer): void 87 | { 88 | $className = $useStatement['fullName']; 89 | 90 | $pairsToCheck = static::INVALID_PAIRS; 91 | foreach ($pairsToCheck as $pair) { 92 | if ($pair['from'] !== $applicationLayer) { 93 | continue; 94 | } 95 | 96 | if (!preg_match('#^\w+\\\\' . $pair['to'] . '\\\\#', $className, $matches)) { 97 | continue; 98 | } 99 | 100 | $phpcsFile->addError( 101 | sprintf( 102 | 'No %s namespace allowed in %s files.', 103 | $pair['to'], 104 | $pair['from'], 105 | ), 106 | $useStatement['start'], 107 | 'InvalidCrossNamespace', 108 | ); 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /Spryker/Sniffs/Namespaces/SprykerNoPyzSniff.php: -------------------------------------------------------------------------------- 1 | isSprykerNamespace($phpcsFile)) { 40 | return; 41 | } 42 | 43 | $useStatements = $this->getUseStatements($phpcsFile); 44 | foreach ($useStatements as $useStatement) { 45 | $namespace = $this->extractNamespace($useStatement['fullName']); 46 | if ($namespace !== static::NAMESPACE_PROJECT) { 47 | continue; 48 | } 49 | 50 | $phpcsFile->addError(sprintf('No %s namespace allowed in core files.', static::NAMESPACE_PROJECT), $useStatement['start'], 'InvalidPyzInSpryker'); 51 | } 52 | } 53 | 54 | /** 55 | * @param string $fullClassName 56 | * 57 | * @return string 58 | */ 59 | protected function extractNamespace(string $fullClassName): string 60 | { 61 | $namespaces = explode('\\', $fullClassName, 2); 62 | 63 | return $namespaces[0]; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Spryker/Sniffs/Namespaces/UseWithAliasingSniff.php: -------------------------------------------------------------------------------- 1 | getTokens(); 35 | 36 | $content = $tokens[$stackPtr]['content']; 37 | if ($content === 'as') { 38 | return; 39 | } 40 | 41 | if (!empty($tokens[$stackPtr]['conditions']) || !empty($tokens[$stackPtr]['nested_parenthesis'])) { 42 | // Let Squiz.ControlStructures.ForEachLoopDeclaration handle this 43 | return; 44 | } 45 | 46 | $newContent = strtolower($content); 47 | 48 | $fix = $phpcsFile->addFixableError(sprintf('Alias keyword `%s` should be `%s`', $content, $newContent), $stackPtr, 'InvalidAliasKeyword'); 49 | if (!$fix) { 50 | return; 51 | } 52 | 53 | $phpcsFile->fixer->replaceToken($stackPtr, $newContent); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Spryker/Sniffs/PHP/DisallowTrailingCommaInSingleLineSniff.php: -------------------------------------------------------------------------------- 1 | 22 | */ 23 | protected $closingTokens = [ 24 | T_CLOSE_PARENTHESIS, 25 | T_CLOSE_SQUARE_BRACKET, 26 | ]; 27 | 28 | /** 29 | * @inheritDoc 30 | */ 31 | public function register(): array 32 | { 33 | return [ 34 | T_COMMA, 35 | ]; 36 | } 37 | 38 | /** 39 | * @inheritDoc 40 | */ 41 | public function process(File $phpcsFile, $commaIndex): void 42 | { 43 | $tokens = $phpcsFile->getTokens(); 44 | 45 | $nextIndex = $phpcsFile->findNext(T_WHITESPACE, ($commaIndex + 1), null, true); 46 | if (!$nextIndex || $tokens[$nextIndex]['line'] !== $tokens[$commaIndex]['line']) { 47 | return; 48 | } 49 | 50 | if (!in_array($tokens[$nextIndex]['code'], $this->closingTokens, true)) { 51 | return; 52 | } 53 | 54 | $fix = $phpcsFile->addFixableError( 55 | 'Trailing comma in single line is disallowed.', 56 | $commaIndex, 57 | 'TrailingCommaDisallowed', 58 | ); 59 | 60 | if (!$fix) { 61 | return; 62 | } 63 | 64 | $phpcsFile->fixer->beginChangeset(); 65 | $phpcsFile->fixer->replaceToken($commaIndex, ''); 66 | $phpcsFile->fixer->endChangeset(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Spryker/Sniffs/PHP/ExitSniff.php: -------------------------------------------------------------------------------- 1 | 22 | */ 23 | public static $aliases = [ 24 | 'die' => 'exit', 25 | ]; 26 | 27 | /** 28 | * @inheritDoc 29 | */ 30 | public function register(): array 31 | { 32 | return [T_EXIT]; 33 | } 34 | 35 | /** 36 | * @inheritDoc 37 | */ 38 | public function process(File $phpcsFile, $stackPtr): void 39 | { 40 | $this->checkExitUsage($phpcsFile, $stackPtr); 41 | } 42 | 43 | /** 44 | * @param \PHP_CodeSniffer\Files\File $phpcsFile 45 | * @param int $stackPtr 46 | * 47 | * @return void 48 | */ 49 | protected function checkExitUsage(File $phpcsFile, int $stackPtr): void 50 | { 51 | $wrongTokens = [T_FUNCTION, T_OBJECT_OPERATOR, T_NEW, T_DOUBLE_COLON]; 52 | 53 | $tokens = $phpcsFile->getTokens(); 54 | 55 | $tokenContent = $tokens[$stackPtr]['content']; 56 | $key = strtolower($tokenContent); 57 | if (isset(static::$aliases[$key])) { 58 | $this->fixAlias($phpcsFile, $stackPtr, $key); 59 | } 60 | 61 | $openingBrace = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); 62 | if (!$openingBrace || $tokens[$openingBrace]['type'] !== 'T_OPEN_PARENTHESIS') { 63 | return; 64 | } 65 | 66 | if ($tokens[$openingBrace]['parenthesis_closer'] > $openingBrace + 1) { 67 | return; 68 | } 69 | 70 | $error = $key . '() without integer exit code argument is not allowed.'; 71 | $phpcsFile->addError($error, $stackPtr, 'Invalid'); 72 | } 73 | 74 | /** 75 | * @param \PHP_CodeSniffer\Files\File $phpcsFile 76 | * @param int $stackPtr 77 | * @param string $before 78 | * 79 | * @return void 80 | */ 81 | protected function fixAlias(File $phpcsFile, int $stackPtr, string $before): void 82 | { 83 | $after = static::$aliases[$before]; 84 | $fix = $phpcsFile->addFixableError($before . '() should be ' . $after . '()', $stackPtr, 'Alias'); 85 | if (!$fix) { 86 | return; 87 | } 88 | 89 | $phpcsFile->fixer->replaceToken($stackPtr, $after); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /Spryker/Sniffs/PHP/NotEqualSniff.php: -------------------------------------------------------------------------------- 1 | . 15 | */ 16 | class NotEqualSniff implements Sniff 17 | { 18 | /** 19 | * @var array 20 | */ 21 | public static $matching = [ 22 | '<>' => '!=', 23 | ]; 24 | 25 | /** 26 | * @inheritDoc 27 | */ 28 | public function register(): array 29 | { 30 | return [T_IS_NOT_EQUAL]; 31 | } 32 | 33 | /** 34 | * @inheritDoc 35 | */ 36 | public function process(File $phpcsFile, $stackPtr): void 37 | { 38 | $tokens = $phpcsFile->getTokens(); 39 | 40 | $content = $tokens[$stackPtr]['content']; 41 | $key = strtolower($content); 42 | 43 | if (!isset(static::$matching[$key])) { 44 | return; 45 | } 46 | 47 | $fix = $phpcsFile->addFixableError($content . ' found, expected ' . static::$matching[$key], $stackPtr, 'NotEqualInvalid'); 48 | if ($fix) { 49 | $phpcsFile->fixer->replaceToken($stackPtr, static::$matching[$key]); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Spryker/Sniffs/PHP/PhpSapiConstantSniff.php: -------------------------------------------------------------------------------- 1 | getTokens(); 37 | 38 | $wrongTokens = [T_FUNCTION, T_OBJECT_OPERATOR, T_NEW, T_DOUBLE_COLON]; 39 | 40 | $tokenContent = $tokens[$stackPtr]['content']; 41 | if (strtolower($tokenContent) !== 'php_sapi_name') { 42 | return; 43 | } 44 | 45 | $previous = (int)$phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); 46 | if (!$previous || in_array($tokens[$previous]['code'], $wrongTokens)) { 47 | return; 48 | } 49 | 50 | $openingBrace = (int)$phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); 51 | if (!$openingBrace || $tokens[$openingBrace]['type'] !== 'T_OPEN_PARENTHESIS') { 52 | return; 53 | } 54 | 55 | $closingBrace = (int)$phpcsFile->findNext(T_WHITESPACE, ($openingBrace + 1), null, true); 56 | if (!$closingBrace || $tokens[$closingBrace]['type'] !== 'T_CLOSE_PARENTHESIS') { 57 | return; 58 | } 59 | 60 | $error = $tokenContent . '() found, should be const ' . static::PHP_SAPI . '.'; 61 | $fix = $phpcsFile->addFixableError($error, $stackPtr, 'MethodVsConst'); 62 | if ($fix) { 63 | $phpcsFile->fixer->replaceToken($stackPtr, static::PHP_SAPI); 64 | for ($i = $openingBrace; $i <= $closingBrace; ++$i) { 65 | $phpcsFile->fixer->replaceToken($i, ''); 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Spryker/Sniffs/PHP/PreferCastOverFunctionSniff.php: -------------------------------------------------------------------------------- 1 | 20 | */ 21 | protected static $matching = [ 22 | 'strval' => 'string', 23 | 'intval' => 'int', 24 | 'floatval' => 'float', 25 | 'boolval' => 'bool', 26 | ]; 27 | 28 | /** 29 | * @inheritDoc 30 | */ 31 | public function register(): array 32 | { 33 | return [T_STRING]; 34 | } 35 | 36 | /** 37 | * @inheritDoc 38 | */ 39 | public function process(File $phpcsFile, $stackPtr): void 40 | { 41 | $wrongTokens = [T_FUNCTION, T_OBJECT_OPERATOR, T_NEW, T_DOUBLE_COLON]; 42 | 43 | $tokens = $phpcsFile->getTokens(); 44 | 45 | $tokenContent = $tokens[$stackPtr]['content']; 46 | $key = strtolower($tokenContent); 47 | if (!isset(static::$matching[$key])) { 48 | return; 49 | } 50 | 51 | $previous = (int)$phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); 52 | if (!$previous || in_array($tokens[$previous]['code'], $wrongTokens)) { 53 | return; 54 | } 55 | 56 | $openingBraceIndex = (int)$phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); 57 | if (!$openingBraceIndex || $tokens[$openingBraceIndex]['type'] !== 'T_OPEN_PARENTHESIS') { 58 | return; 59 | } 60 | 61 | $closingBraceIndex = $tokens[$openingBraceIndex]['parenthesis_closer']; 62 | 63 | // We must ignore when commas are encountered 64 | if ($this->contains($phpcsFile, 'T_COMMA', $openingBraceIndex + 1, $closingBraceIndex - 1)) { 65 | return; 66 | } 67 | 68 | $error = $tokenContent . '() found, should be ' . static::$matching[$key] . ' cast.'; 69 | 70 | $fix = $phpcsFile->addFixableError($error, $stackPtr, 'MethodVsCast'); 71 | if ($fix) { 72 | $this->fixContent($phpcsFile, $stackPtr, $key, $openingBraceIndex, $closingBraceIndex); 73 | } 74 | } 75 | 76 | /** 77 | * @param \PHP_CodeSniffer\Files\File $phpcsFile 78 | * @param int $stackPtr 79 | * @param string $key 80 | * @param int $openingBraceIndex 81 | * @param int $closingBraceIndex 82 | * 83 | * @return void 84 | */ 85 | protected function fixContent( 86 | File $phpcsFile, 87 | int $stackPtr, 88 | string $key, 89 | int $openingBraceIndex, 90 | int $closingBraceIndex 91 | ): void { 92 | $needsBrackets = $this->needsBrackets($phpcsFile, $openingBraceIndex, $closingBraceIndex); 93 | 94 | $cast = '(' . static::$matching[$key] . ')'; 95 | 96 | $phpcsFile->fixer->replaceToken($stackPtr, $cast); 97 | if (!$needsBrackets) { 98 | $phpcsFile->fixer->replaceToken($openingBraceIndex, ''); 99 | $phpcsFile->fixer->replaceToken($closingBraceIndex, ''); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /Spryker/Sniffs/PHP/RemoveFunctionAliasSniff.php: -------------------------------------------------------------------------------- 1 | 22 | */ 23 | public static $matching = [ 24 | 'is_integer' => 'is_int', 25 | 'is_long' => 'is_int', 26 | 'is_real' => 'is_float', 27 | 'is_double' => 'is_float', 28 | 'is_writeable' => 'is_writable', 29 | 'join' => 'implode', 30 | 'key_exists' => 'array_key_exists', // Deprecated function 31 | 'sizeof' => 'count', 32 | 'strchr' => 'strstr', 33 | 'ini_alter' => 'ini_set', 34 | 'fputs' => 'fwrite', 35 | 'die' => 'exit', 36 | 'chop' => 'rtrim', 37 | 'print' => 'echo', 38 | ]; 39 | 40 | /** 41 | * @inheritDoc 42 | */ 43 | public function register(): array 44 | { 45 | return [T_STRING]; 46 | } 47 | 48 | /** 49 | * @inheritDoc 50 | */ 51 | public function process(File $phpcsFile, $stackPtr): void 52 | { 53 | $this->checkFixableAliases($phpcsFile, $stackPtr); 54 | } 55 | 56 | /** 57 | * @param \PHP_CodeSniffer\Files\File $phpcsFile 58 | * @param int $stackPtr 59 | * 60 | * @return void 61 | */ 62 | protected function checkFixableAliases(File $phpcsFile, int $stackPtr): void 63 | { 64 | $wrongTokens = [T_FUNCTION, T_OBJECT_OPERATOR, T_NEW, T_DOUBLE_COLON]; 65 | 66 | $tokens = $phpcsFile->getTokens(); 67 | 68 | $tokenContent = $tokens[$stackPtr]['content']; 69 | $key = strtolower($tokenContent); 70 | if (!isset(static::$matching[$key])) { 71 | return; 72 | } 73 | 74 | $previous = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); 75 | if (!$previous || in_array($tokens[$previous]['code'], $wrongTokens)) { 76 | return; 77 | } 78 | 79 | $openingBrace = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); 80 | if (!$openingBrace || $tokens[$openingBrace]['type'] !== 'T_OPEN_PARENTHESIS') { 81 | return; 82 | } 83 | 84 | $error = 'Function name ' . $tokenContent . '() found, should be ' . static::$matching[$key] . '().'; 85 | $fix = $phpcsFile->addFixableError($error, $stackPtr, 'LongInvalid'); 86 | if ($fix) { 87 | $phpcsFile->fixer->replaceToken($stackPtr, static::$matching[$key]); 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Spryker/Sniffs/PHP/ShortCastSniff.php: -------------------------------------------------------------------------------- 1 | 20 | */ 21 | public static $matching = [ 22 | '(boolean)' => '(bool)', 23 | '(integer)' => '(int)', 24 | ]; 25 | 26 | /** 27 | * @inheritDoc 28 | */ 29 | public function register(): array 30 | { 31 | return [T_BOOL_CAST, T_INT_CAST, T_BOOLEAN_NOT]; 32 | } 33 | 34 | /** 35 | * @inheritDoc 36 | */ 37 | public function process(File $phpcsFile, $stackPtr): void 38 | { 39 | $tokens = $phpcsFile->getTokens(); 40 | 41 | if ($tokens[$stackPtr]['content'] === '!') { 42 | $prevIndex = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); 43 | if (!$prevIndex || $tokens[$prevIndex]['content'] !== '!') { 44 | return; 45 | } 46 | 47 | $fix = $phpcsFile->addFixableError('`!!` cast not allowed, use `(bool)`', $stackPtr, 'DoubleNotInvalid'); 48 | if ($fix) { 49 | $phpcsFile->fixer->replaceToken($prevIndex, ''); 50 | $phpcsFile->fixer->replaceToken($stackPtr, '(bool)'); 51 | } 52 | 53 | return; 54 | } 55 | 56 | $content = $tokens[$stackPtr]['content']; 57 | $key = strtolower($content); 58 | 59 | if (!isset(static::$matching[$key])) { 60 | return; 61 | } 62 | 63 | $fix = $phpcsFile->addFixableError($content . ' found, expected ' . static::$matching[$key], $stackPtr, 'LongInvalid'); 64 | if ($fix) { 65 | $phpcsFile->fixer->replaceToken($stackPtr, static::$matching[$key]); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Spryker/Sniffs/PHP/SingleQuoteSniff.php: -------------------------------------------------------------------------------- 1 | 7 | * Dariusz Rumiński 8 | * 9 | * This source file is subject to the MIT license that is bundled 10 | * with this source code in the file LICENSE. 11 | */ 12 | 13 | /** 14 | * MIT License 15 | * For full license information, please view the LICENSE file that was distributed with this source code. 16 | */ 17 | 18 | namespace Spryker\Sniffs\PHP; 19 | 20 | use PHP_CodeSniffer\Files\File; 21 | use PHP_CodeSniffer\Util\Tokens; 22 | use Spryker\Sniffs\AbstractSniffs\AbstractSprykerSniff; 23 | 24 | /** 25 | * Converts double quotes to single quotes for simple strings. 26 | * 27 | * @author Gregor Harlan 28 | * @author Mark Scherer 29 | */ 30 | class SingleQuoteSniff extends AbstractSprykerSniff 31 | { 32 | /** 33 | * @inheritDoc 34 | */ 35 | public function register(): array 36 | { 37 | return [T_CONSTANT_ENCAPSED_STRING]; 38 | } 39 | 40 | /** 41 | * @inheritDoc 42 | */ 43 | public function process(File $phpcsFile, $stackPtr): void 44 | { 45 | $tokens = $phpcsFile->getTokens(); 46 | 47 | // Skip for complex multiline 48 | $prevIndex = $phpcsFile->findPrevious(Tokens::$emptyTokens, $stackPtr - 1, null, true); 49 | if ($prevIndex && $tokens[$prevIndex]['code'] === T_CONSTANT_ENCAPSED_STRING) { 50 | return; 51 | } 52 | 53 | $content = $tokens[$stackPtr]['content']; 54 | if ( 55 | $content[0] === '"' 56 | && strpos($content, "'") === false 57 | && strpos($content, "\n") === false 58 | // regex: odd number of backslashes, not followed by double quote or dollar 59 | && !preg_match('/(?addFixableError( 62 | 'Use single instead of double quotes for simple strings.', 63 | $stackPtr, 64 | 'UseSingleQuote', 65 | ); 66 | if ($fix) { 67 | $content = substr($content, 1, -1); 68 | $content = str_replace(['\\"', '\\$'], ['"', '$'], $content); 69 | $phpcsFile->fixer->replaceToken($stackPtr, '\'' . $content . '\''); 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Spryker/Sniffs/WhiteSpace/CommaSpacingSniff.php: -------------------------------------------------------------------------------- 1 | getTokens(); 35 | 36 | $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); 37 | if (!$next) { 38 | return; 39 | } 40 | $this->checkNext($phpcsFile, $stackPtr, $next); 41 | 42 | $previous = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); 43 | if (!$previous) { 44 | return; 45 | } 46 | 47 | if ($tokens[$previous]['code'] !== T_WHITESPACE && ($previous !== $stackPtr - 1)) { 48 | if ($tokens[$previous]['code'] === T_COMMA) { 49 | return; 50 | } 51 | 52 | $error = 'Space before comma, expected none, though'; 53 | $fix = $phpcsFile->addFixableError($error, $next, 'InvalidCommaBefore'); 54 | if ($fix) { 55 | $phpcsFile->fixer->replaceToken($previous + 1, ''); 56 | } 57 | } 58 | } 59 | 60 | /** 61 | * @param \PHP_CodeSniffer\Files\File $phpcsFile 62 | * @param int $stackPtr 63 | * @param int $next 64 | * 65 | * @return void 66 | */ 67 | public function checkNext(File $phpcsFile, int $stackPtr, int $next): void 68 | { 69 | $tokens = $phpcsFile->getTokens(); 70 | 71 | // Closing inline array should not have a comma before 72 | if ($tokens[$next]['code'] === T_CLOSE_SHORT_ARRAY && $tokens[$next]['line'] === $tokens[$stackPtr]['line']) { 73 | $error = 'Invalid comma before closing inline array end `]`.'; 74 | $fix = $phpcsFile->addFixableError($error, $next, 'InvalidCommaInline'); 75 | if ($fix) { 76 | $phpcsFile->fixer->replaceToken($stackPtr, ''); 77 | } 78 | 79 | return; 80 | } 81 | 82 | if ($tokens[$next]['code'] !== T_WHITESPACE && ($next !== $stackPtr + 2)) { 83 | // Last character in a line is ok. 84 | if ($tokens[$next]['line'] !== $tokens[$stackPtr]['line']) { 85 | return; 86 | } 87 | 88 | // Closing inline array is also ignored 89 | if (in_array($tokens[$next]['code'], [T_CLOSE_SHORT_ARRAY, T_CLOSE_PARENTHESIS], true)) { 90 | return; 91 | } 92 | 93 | $error = 'Missing space after comma'; 94 | $fix = $phpcsFile->addFixableError($error, $next, 'MissingCommaAfter'); 95 | if ($fix) { 96 | $phpcsFile->fixer->addContent($stackPtr, ' '); 97 | } 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /Spryker/Sniffs/WhiteSpace/DocBlockSpacingSniff.php: -------------------------------------------------------------------------------- 1 | getTokens(); 35 | 36 | $line = $tokens[$stackPtr]['line']; 37 | $beginningOfLine = $stackPtr; 38 | while (!empty($tokens[$beginningOfLine - 1]) && $tokens[$beginningOfLine - 1]['line'] === $line) { 39 | $beginningOfLine--; 40 | } 41 | $previousIndex = $phpcsFile->findPrevious(T_WHITESPACE, ($beginningOfLine - 1), null, true); 42 | 43 | if (!$previousIndex || $tokens[$previousIndex]['code'] !== T_DOC_COMMENT_CLOSE_TAG) { 44 | return; 45 | } 46 | 47 | if ($tokens[$previousIndex]['line'] >= $line - 1) { 48 | return; 49 | } 50 | 51 | $error = 'Additional newline detected between doc block and code'; 52 | $fix = $phpcsFile->addFixableError($error, $previousIndex, 'InvalidSpacing'); 53 | if (!$fix) { 54 | return; 55 | } 56 | 57 | $phpcsFile->fixer->beginChangeset(); 58 | $index = $previousIndex + 1; 59 | 60 | while ($index < $beginningOfLine - 1) { 61 | $phpcsFile->fixer->replaceToken($index, ''); 62 | $index++; 63 | } 64 | 65 | $phpcsFile->fixer->endChangeset(); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Spryker/Sniffs/WhiteSpace/EmptyLinesSniff.php: -------------------------------------------------------------------------------- 1 | 23 | */ 24 | public $supportedTokenizers = [ 25 | 'PHP', 26 | 'JS', 27 | 'CSS', 28 | ]; 29 | 30 | /** 31 | * @inheritDoc 32 | */ 33 | public function register(): array 34 | { 35 | return [T_WHITESPACE]; 36 | } 37 | 38 | /** 39 | * @inheritDoc 40 | */ 41 | public function process(File $phpcsFile, $stackPtr): void 42 | { 43 | $this->assertMaximumOneEmptyLineBetweenContent($phpcsFile, $stackPtr); 44 | } 45 | 46 | /** 47 | * @param \PHP_CodeSniffer\Files\File $phpcsFile 48 | * @param int $stackPtr 49 | * 50 | * @return void 51 | */ 52 | protected function assertMaximumOneEmptyLineBetweenContent(File $phpcsFile, int $stackPtr): void 53 | { 54 | $tokens = $phpcsFile->getTokens(); 55 | 56 | if ( 57 | $tokens[$stackPtr]['content'] === $phpcsFile->eolChar 58 | && isset($tokens[($stackPtr + 1)]) 59 | && $tokens[($stackPtr + 1)]['content'] === $phpcsFile->eolChar 60 | && isset($tokens[($stackPtr + 2)]) 61 | && $tokens[($stackPtr + 2)]['content'] === $phpcsFile->eolChar 62 | ) { 63 | $error = 'Found more than a single empty line between content'; 64 | $fix = $phpcsFile->addFixableError($error, ($stackPtr + 2), 'EmptyLines'); 65 | if ($fix) { 66 | $phpcsFile->fixer->replaceToken($stackPtr + 2, ''); 67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Spryker/Sniffs/WhiteSpace/ImplicitCastSpacingSniff.php: -------------------------------------------------------------------------------- 1 | getTokens(); 33 | 34 | if ($tokens[$stackPtr]['code'] === T_INC || $tokens[$stackPtr]['code'] === T_DEC) { 35 | $this->processIncDec($phpcsFile, $stackPtr); 36 | 37 | return; 38 | } 39 | 40 | $nextIndex = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); 41 | 42 | if ($nextIndex - $stackPtr === 1) { 43 | return; 44 | } 45 | 46 | $fix = $phpcsFile->addFixableError('No whitespace should be between ' . $tokens[$stackPtr]['content'] . ' and variable.', $stackPtr, 'WhitespaceBetweenContentVariable'); 47 | if ($fix && $phpcsFile->fixer->enabled) { 48 | $phpcsFile->fixer->beginChangeset(); 49 | $phpcsFile->fixer->replaceToken($stackPtr + 1, ''); 50 | $phpcsFile->fixer->endChangeset(); 51 | } 52 | } 53 | 54 | /** 55 | * @param \PHP_CodeSniffer\Files\File $phpcsFile 56 | * @param int $stackPtr 57 | * 58 | * @return void 59 | */ 60 | protected function processIncDec(File $phpcsFile, int $stackPtr): void 61 | { 62 | $tokens = $phpcsFile->getTokens(); 63 | 64 | $nextIndex = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); 65 | if ($tokens[$nextIndex]['code'] === T_VARIABLE) { 66 | if ($nextIndex - $stackPtr === 1) { 67 | return; 68 | } 69 | 70 | $fix = $phpcsFile->addFixableError('No whitespace should be between incrementor and variable.', $stackPtr, 'WhitespaceBeforeVariable'); 71 | if ($fix) { 72 | $phpcsFile->fixer->beginChangeset(); 73 | $phpcsFile->fixer->replaceToken($stackPtr + 1, ''); 74 | $phpcsFile->fixer->endChangeset(); 75 | } 76 | 77 | return; 78 | } 79 | 80 | $prevIndex = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); 81 | if ($tokens[$prevIndex]['code'] === T_VARIABLE) { 82 | if ($stackPtr - $prevIndex === 1) { 83 | return; 84 | } 85 | 86 | $fix = $phpcsFile->addFixableError('No whitespace should be between variable and incrementor.', $stackPtr, 'WhitespaceAfterVariable'); 87 | if ($fix) { 88 | $phpcsFile->fixer->beginChangeset(); 89 | $phpcsFile->fixer->replaceToken($stackPtr - 1, ''); 90 | $phpcsFile->fixer->endChangeset(); 91 | } 92 | 93 | return; 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /Spryker/Sniffs/WhiteSpace/MemberVarSpacingSniff.php: -------------------------------------------------------------------------------- 1 | getTokens(); 27 | 28 | $endIndex = $phpcsFile->findNext(T_SEMICOLON, $stackPtr + 1); 29 | if (!$endIndex) { 30 | return; 31 | } 32 | $nextIndex = $phpcsFile->findNext(T_WHITESPACE, $endIndex + 1, null, true); 33 | if (!$nextIndex) { 34 | return; 35 | } 36 | 37 | if ($tokens[$nextIndex]['line'] - $tokens[$endIndex]['line'] === 2) { 38 | return; 39 | } 40 | 41 | // If next token is end of class, we also skip 42 | if ($tokens[$nextIndex]['code'] === T_CLOSE_CURLY_BRACKET) { 43 | return; 44 | } 45 | 46 | $found = $tokens[$nextIndex]['line'] - $tokens[$endIndex]['line'] - 1; 47 | $error = 'Expected 1 blank line after member var; %s found'; 48 | $data = [$found]; 49 | 50 | $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Incorrect', $data); 51 | if (!$fix) { 52 | return; 53 | } 54 | 55 | if ($tokens[$nextIndex]['line'] - $tokens[$endIndex]['line'] < 2) { 56 | $phpcsFile->fixer->beginChangeset(); 57 | $phpcsFile->fixer->addNewline($endIndex); 58 | $phpcsFile->fixer->endChangeset(); 59 | 60 | return; 61 | } 62 | 63 | $phpcsFile->fixer->replaceToken($endIndex + 1, ''); 64 | } 65 | 66 | /** 67 | * @inheritDoc 68 | */ 69 | protected function processVariable(File $phpcsFile, $stackPtr) 70 | { 71 | // We don't care about normal variables. 72 | } 73 | 74 | /** 75 | * @inheritDoc 76 | */ 77 | protected function processVariableInString(File $phpcsFile, $stackPtr) 78 | { 79 | // We don't care about normal variables. 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /Spryker/Sniffs/WhiteSpace/NamespaceSpacingSniff.php: -------------------------------------------------------------------------------- 1 | getTokens(); 35 | 36 | $beforeIndex = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); 37 | if (!$beforeIndex) { 38 | return; 39 | } 40 | $beforeLine = $tokens[$beforeIndex]['line']; 41 | 42 | if ($beforeLine === $tokens[$stackPtr]['line'] - 2) { 43 | return; 44 | } 45 | 46 | $error = 'There must be one blank line before the namespace declaration'; 47 | $fix = $phpcsFile->addFixableError($error, $stackPtr, 'BlankLineBefore'); 48 | if (!$fix) { 49 | return; 50 | } 51 | 52 | if ($beforeLine < $tokens[$stackPtr]['line'] - 2) { 53 | $phpcsFile->fixer->beginChangeset(); 54 | $phpcsFile->fixer->replaceToken($stackPtr - 1, ''); 55 | $phpcsFile->fixer->endChangeset(); 56 | 57 | return; 58 | } 59 | 60 | $phpcsFile->fixer->beginChangeset(); 61 | $phpcsFile->fixer->addNewline($beforeIndex); 62 | $phpcsFile->fixer->endChangeset(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Spryker/Sniffs/WhiteSpace/ObjectAttributeSpacingSniff.php: -------------------------------------------------------------------------------- 1 | getTokens(); 35 | 36 | // Make sure there is no space before. 37 | $previousToken = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); 38 | 39 | if ($stackPtr - $previousToken !== 1 && $tokens[$previousToken]['line'] === $tokens[$stackPtr]['line']) { 40 | $error = 'Expected no space before object operator `' . $tokens[$stackPtr]['content'] . '`'; 41 | $fix = $phpcsFile->addFixableError($error, $stackPtr - 1, 'TooMany'); 42 | if ($fix) { 43 | $phpcsFile->fixer->replaceToken($stackPtr - 1, ''); 44 | } 45 | } 46 | 47 | // Make sure there is no space after. 48 | $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); 49 | 50 | if ($nextToken - $stackPtr !== 1 && $tokens[$nextToken]['line'] === $tokens[$stackPtr]['line']) { 51 | $error = 'Expected no space after object operator `' . $tokens[$stackPtr]['content'] . '`'; 52 | $fix = $phpcsFile->addFixableError($error, $stackPtr + 1, 'TooMany'); 53 | if ($fix) { 54 | $phpcsFile->fixer->replaceToken($stackPtr + 1, ''); 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Spryker/Sniffs/WhiteSpace/TernarySpacingSniff.php: -------------------------------------------------------------------------------- 1 | 23 | */ 24 | public $supportedTokenizers = [ 25 | 'PHP', 26 | ]; 27 | 28 | /** 29 | * @inheritDoc 30 | */ 31 | public function register(): array 32 | { 33 | return [ 34 | T_INLINE_THEN, 35 | ]; 36 | } 37 | 38 | /** 39 | * @inheritDoc 40 | */ 41 | public function process(File $phpcsFile, $stackPtr): void 42 | { 43 | $tokens = $phpcsFile->getTokens(); 44 | 45 | $nextIndex = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); 46 | if (!$nextIndex || $nextIndex - 1 === $stackPtr || $tokens[$nextIndex]['code'] !== T_INLINE_ELSE) { 47 | return; 48 | } 49 | 50 | if ($tokens[$nextIndex - 1]['code'] !== T_WHITESPACE) { 51 | return; 52 | } 53 | 54 | $fix = $phpcsFile->addFixableError('Additional whitespace found between short ternary', $stackPtr, 'InvalidWhitespace'); 55 | if (!$fix) { 56 | return; 57 | } 58 | 59 | $phpcsFile->fixer->beginChangeset(); 60 | $phpcsFile->fixer->replaceToken($nextIndex - 1, ''); 61 | $phpcsFile->fixer->endChangeset(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Spryker/Tools/SniffsAndTests.php: -------------------------------------------------------------------------------- 1 | 19 | */ 20 | protected static $orgs = [ 21 | 'Spryker', 22 | 'SprykerStrict', 23 | //'GlueStreamSpecific', 24 | ]; 25 | 26 | /** 27 | * @param string $path Path 28 | * 29 | * @return array> 30 | */ 31 | public function untested(string $path): array 32 | { 33 | $path = rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; 34 | 35 | $sniffs = []; 36 | 37 | foreach (static::$orgs as $org) { 38 | $directoryIterator = new RecursiveDirectoryIterator($path . $org); 39 | $recursiveIterator = new RecursiveIteratorIterator($directoryIterator); 40 | $regexIterator = new RegexIterator($recursiveIterator, '#^.+/(\w+)/Sniffs/(\w+)/(\w+)Sniff\.php$#', RecursiveRegexIterator::GET_MATCH); 41 | 42 | foreach ($regexIterator as $match) { 43 | $org = $match[1]; 44 | $type = $match[2]; 45 | $name = $match[3]; 46 | $testFile = $path . 'tests' . DIRECTORY_SEPARATOR . $org . 'Sniffs' . DIRECTORY_SEPARATOR . $type . DIRECTORY_SEPARATOR . $name . 'SniffTest.php'; 47 | $hasTest = file_exists($testFile); 48 | if ($hasTest) { 49 | continue; 50 | } 51 | 52 | $key = $org . '.' . $type . '.' . $name; 53 | $sniffs[$key] = [ 54 | 'hasTest' => $hasTest, 55 | ]; 56 | } 57 | } 58 | 59 | return $sniffs; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Spryker/Traits/BasicsTrait.php: -------------------------------------------------------------------------------- 1 | |string|int $search 17 | * @param array $token 18 | * 19 | * @return bool 20 | */ 21 | protected function isGivenKind($search, array $token): bool 22 | { 23 | $kind = (array)$search; 24 | 25 | if (in_array($token['code'], $kind, true)) { 26 | return true; 27 | } 28 | if (in_array($token['type'], $kind, true)) { 29 | return true; 30 | } 31 | 32 | return false; 33 | } 34 | 35 | /** 36 | * @param \PHP_CodeSniffer\Files\File $phpcsFile 37 | * 38 | * @return array> 39 | */ 40 | protected function getNamespaceStatement(File $phpcsFile): array 41 | { 42 | $tokens = $phpcsFile->getTokens(); 43 | 44 | $namespaceIndex = $phpcsFile->findNext(T_NAMESPACE, 0); 45 | if (!$namespaceIndex) { 46 | return []; 47 | } 48 | 49 | $endIndex = $phpcsFile->findNext([T_SEMICOLON, T_OPEN_CURLY_BRACKET], $namespaceIndex + 1); 50 | if (!$endIndex) { 51 | return []; 52 | } 53 | 54 | $namespace = ''; 55 | $namespaceStartIndex = $phpcsFile->findNext(Tokens::$emptyTokens, $namespaceIndex + 1, null, true); 56 | $namespaceEndIndex = $phpcsFile->findPrevious(Tokens::$emptyTokens, $endIndex - 1, null, true); 57 | for ($i = $namespaceStartIndex; $i <= $namespaceEndIndex; $i++) { 58 | $namespace .= $tokens[$i]['content']; 59 | } 60 | 61 | return [ 62 | 'start' => $namespaceIndex, 63 | 'namespace' => $namespace, 64 | 'end' => $endIndex, 65 | ]; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Spryker/Traits/NamespaceTrait.php: -------------------------------------------------------------------------------- 1 | getTokens(); 28 | 29 | // Ignore USE keywords inside closures. 30 | $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); 31 | if ($tokens[$next]['code'] === T_OPEN_PARENTHESIS) { 32 | return true; 33 | } 34 | 35 | // Ignore USE keywords for traits. 36 | if ($phpcsFile->hasCondition($stackPtr, [T_CLASS, T_TRAIT]) === true) { 37 | return true; 38 | } 39 | 40 | return false; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Spryker/Traits/SignatureTrait.php: -------------------------------------------------------------------------------- 1 | > 22 | */ 23 | protected function getMethodSignature(File $phpCsFile, int $stackPtr): array 24 | { 25 | $parameters = $phpCsFile->getMethodParameters($stackPtr); 26 | $tokens = $phpCsFile->getTokens(); 27 | 28 | $arguments = []; 29 | foreach ($parameters as $parameter) { 30 | $defaultIndex = $default = null; 31 | 32 | $possibleEqualIndex = $phpCsFile->findNext([T_EQUAL], $parameter['token'] + 1, $parameter['token'] + 3); 33 | if ($possibleEqualIndex) { 34 | $whitelist = [T_CONSTANT_ENCAPSED_STRING, T_TRUE, T_FALSE, T_NULL, T_OPEN_SHORT_ARRAY, T_LNUMBER, T_DNUMBER]; 35 | $possibleDefaultValue = $phpCsFile->findNext($whitelist, $possibleEqualIndex + 1, $possibleEqualIndex + 3); 36 | if ($possibleDefaultValue) { 37 | $defaultIndex = $possibleDefaultValue; 38 | $default = null; 39 | if ($tokens[$defaultIndex]['code'] === T_CONSTANT_ENCAPSED_STRING) { 40 | $default = 'string'; 41 | } elseif ($tokens[$defaultIndex]['code'] === T_OPEN_SHORT_ARRAY) { 42 | $default = 'array'; 43 | } elseif ($tokens[$defaultIndex]['code'] === T_FALSE || $tokens[$defaultIndex]['code'] === T_TRUE) { 44 | $default = 'bool'; 45 | } elseif ($tokens[$defaultIndex]['code'] === T_LNUMBER) { 46 | $default = 'int'; 47 | } elseif ($tokens[$defaultIndex]['code'] === T_DNUMBER) { 48 | $default = 'float'; 49 | } elseif ($tokens[$defaultIndex]['code'] === T_NULL) { 50 | $default = 'null'; 51 | } 52 | } 53 | } 54 | 55 | $typehint = $parameter['type_hint']; 56 | if (substr($typehint, 0, 1) === '?') { 57 | $typehint = substr($typehint, 1); 58 | } 59 | 60 | $arguments[] = [ 61 | 'variableIndex' => $parameter['token'], 62 | 'variable' => $parameter['name'], 63 | 'typehint' => $typehint, 64 | 'typehintFull' => $parameter['type_hint'], 65 | 'nullable' => $parameter['nullable_type'], 66 | 'defaultIndex' => $defaultIndex, 67 | 'default' => $default, 68 | ]; 69 | } 70 | 71 | return $arguments; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Spryker/Traits/UseStatementsTrait.php: -------------------------------------------------------------------------------- 1 | > 19 | */ 20 | protected function getUseStatements(File $phpcsFile): array 21 | { 22 | $tokens = $phpcsFile->getTokens(); 23 | 24 | $statements = []; 25 | foreach ($tokens as $index => $token) { 26 | if ($token['code'] !== T_USE || $token['level'] > 0) { 27 | continue; 28 | } 29 | 30 | $useStatementStartIndex = $phpcsFile->findNext(Tokens::$emptyTokens, $index + 1, null, true); 31 | 32 | // Ignore function () use ($foo) {} 33 | if ($tokens[$useStatementStartIndex]['content'] === '(') { 34 | continue; 35 | } 36 | 37 | $semicolonIndex = $phpcsFile->findNext(T_SEMICOLON, $useStatementStartIndex + 1); 38 | $useStatementEndIndex = $phpcsFile->findPrevious(Tokens::$emptyTokens, $semicolonIndex - 1, null, true); 39 | 40 | $statement = ''; 41 | for ($i = $useStatementStartIndex; $i <= $useStatementEndIndex; $i++) { 42 | $statement .= $tokens[$i]['content']; 43 | } 44 | 45 | // Another sniff takes care of that, we just ignore then. 46 | if ($this->isMultipleUseStatement($statement)) { 47 | continue; 48 | } 49 | 50 | $statementParts = preg_split('/\s+as\s+/i', $statement) ?: []; 51 | 52 | if (count($statementParts) === 1) { 53 | $fullName = $statement; 54 | $statementParts = explode('\\', $fullName); 55 | $shortName = end($statementParts); 56 | $alias = null; 57 | } else { 58 | $fullName = $statementParts[0]; 59 | $alias = $statementParts[1]; 60 | $statementParts = explode('\\', $fullName); 61 | $shortName = end($statementParts); 62 | } 63 | 64 | $shortName = trim($shortName); 65 | $fullName = trim($fullName); 66 | $key = $alias ?: $shortName; 67 | 68 | $statements[$key] = [ 69 | 'alias' => $alias, 70 | 'end' => $semicolonIndex, 71 | 'statement' => $statement, 72 | 'fullName' => ltrim($fullName, '\\'), 73 | 'shortName' => $shortName, 74 | 'start' => $index, 75 | ]; 76 | } 77 | 78 | return $statements; 79 | } 80 | 81 | /** 82 | * @param string $statementContent 83 | * 84 | * @return bool 85 | */ 86 | protected function isMultipleUseStatement(string $statementContent): bool 87 | { 88 | if (strpos($statementContent, ',') !== false) { 89 | return true; 90 | } 91 | 92 | return false; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /SprykerStrict/Sniffs/TypeHints/ParameterTypeHintSniff.php: -------------------------------------------------------------------------------- 1 | isSprykerBridgeConstructor($phpcsFile, $pointer)) { 24 | return; 25 | } 26 | 27 | parent::process($phpcsFile, $pointer); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /SprykerStrict/Sniffs/TypeHints/PropertyTypeHintSniff.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SprykerStrict Coding Standard. 5 | 6 | All sniffs in ./Sniffs will be auto loaded 7 | 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 | -------------------------------------------------------------------------------- /bin/tokenize: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | canonicalize() { 4 | NAME="$1" 5 | if [ -f "$NAME" ] 6 | then 7 | DIR=$(dirname -- "$NAME") 8 | NAME=$(cd -P "$DIR" > /dev/null && pwd -P)/$(basename -- "$NAME") 9 | fi 10 | while [ -h "$NAME" ]; do 11 | DIR=$(dirname -- "$NAME") 12 | SYM=$(readlink "$NAME") 13 | NAME=$(cd "$DIR" > /dev/null && cd $(dirname -- "$SYM") > /dev/null && pwd)/$(basename -- "$SYM") 14 | done 15 | echo "$NAME" 16 | } 17 | 18 | CONSOLE=$(dirname -- "$(canonicalize "$0")") 19 | APP=$(dirname "$CONSOLE") 20 | 21 | if [ $(basename $0) != 'tokenize' ] 22 | then 23 | exec php "$CONSOLE"/tokenize.php $(basename $0) "$@" 24 | else 25 | exec php "$CONSOLE"/tokenize.php "$@" 26 | fi 27 | 28 | exit 0 29 | -------------------------------------------------------------------------------- /bin/tokenize.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | SET app=%0 4 | SET lib=%~dp0 5 | 6 | php "%lib%tokenize.php" %* 7 | 8 | echo. 9 | 10 | exit /B %ERRORLEVEL% 11 | -------------------------------------------------------------------------------- /bin/tokenize.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php -q 2 | tokenize(); 26 | echo 0; 27 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "spryker/code-sniffer", 3 | "description": "Spryker Code Sniffer Standards", 4 | "type": "phpcodesniffer-standard", 5 | "license": "MIT", 6 | "keywords": [ 7 | "framework", 8 | "codesniffer", 9 | "phpcs", 10 | "static analysis", 11 | "standards" 12 | ], 13 | "homepage": "https://spryker.com", 14 | "authors": [ 15 | { 16 | "name": "Spryker", 17 | "homepage": "https://spryker.com" 18 | } 19 | ], 20 | "require": { 21 | "php": ">=8.1", 22 | "phpstan/phpdoc-parser": "^1.33.0", 23 | "slevomat/coding-standard": "^7.2.0 || ^8.0.1", 24 | "squizlabs/php_codesniffer": "^3.6.2" 25 | }, 26 | "require-dev": { 27 | "phpstan/phpstan": "^1.0.0", 28 | "phpunit/phpunit": "^9.5" 29 | }, 30 | "autoload": { 31 | "psr-4": { 32 | "Spryker\\": "Spryker/", 33 | "SprykerStrict\\": "SprykerStrict/" 34 | } 35 | }, 36 | "autoload-dev": { 37 | "psr-4": { 38 | "Spryker\\Test\\": "tests/" 39 | }, 40 | "files": [ 41 | "vendor/squizlabs/php_codesniffer/autoload.php" 42 | ] 43 | }, 44 | "scripts": { 45 | "docs": "php docs/generate.php", 46 | "docs-listing": "phpcs -e --standard=SprykerStrict/ruleset.xml", 47 | "add-standard": "phpcs --config-set installed_paths $(pwd)", 48 | "increase-severity": "sed -i.bak 's/0<\\/severity>//' Spryker/ruleset.xml", 49 | "reset-ruleset": [ 50 | "sed -i.bak 's//0<\\/severity>/' Spryker/ruleset.xml", 51 | "rm -f Spryker/ruleset.xml.bak" 52 | ], 53 | "cs-check": "vendor/bin/phpcs --extensions=php", 54 | "cs-fix": "vendor/bin/phpcbf --extensions=php", 55 | "test": "vendor/bin/phpunit", 56 | "stan": "phpstan analyse", 57 | "xml": "tests/xmllint.sh" 58 | }, 59 | "bin": [ 60 | "bin/tokenize" 61 | ], 62 | "support": { 63 | "source": "https://github.com/spryker/code-sniffer" 64 | }, 65 | "config": { 66 | "sort-packages": true, 67 | "process-timeout": 900, 68 | "allow-plugins": { 69 | "dealerdirect/phpcodesniffer-composer-installer": true 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /docs/generate.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Spryker/ 10 | SprykerStrict/ 11 | GlueStreamSpecific/ 12 | tests/Spryker/ 13 | tests/TestCase.php 14 | docs/ 15 | bin/ 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | /Spryker/tests/files/ 28 | 29 | 30 | -------------------------------------------------------------------------------- /phpstan.neon: -------------------------------------------------------------------------------- 1 | parameters: 2 | level: 8 3 | checkGenericClassInNonGenericObjectType: false 4 | paths: 5 | - Spryker/ 6 | - SprykerStrict/ 7 | - GlueStreamSpecific/ 8 | bootstrapFiles: 9 | - '%rootDir%/../../../tests/bootstrap.php' 10 | -------------------------------------------------------------------------------- /tests/Spryker/Sniffs/AllSniffTest.php: -------------------------------------------------------------------------------- 1 | testFilePath() . 'All' . DS . 'before.php'; 23 | $after = $this->testFilePath() . 'All' . DS . 'after.php'; 24 | 25 | // Use --debug to display the errors found 26 | $errors = $this->runFullFixer($before, $after); 27 | $this->assertNotEmpty($errors); 28 | 29 | $this->runFullFixer($before, $after, null, null, true); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/Spryker/Sniffs/Commenting/DisallowArrayTypeHintSyntaxSniffTest.php: -------------------------------------------------------------------------------- 1 | assertSnifferFindsErrors(new DisallowArrayTypeHintSyntaxSniff(), 12); 21 | } 22 | 23 | /** 24 | * @return void 25 | */ 26 | public function testDocBlockThrowsFixer(): void 27 | { 28 | $this->assertSnifferCanFixErrors(new DisallowArrayTypeHintSyntaxSniff()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/Spryker/Sniffs/Commenting/DocBlockConstSniffTest.php: -------------------------------------------------------------------------------- 1 | assertSnifferFindsErrors(new DocBlockConstSniff(), 4); 21 | } 22 | 23 | /** 24 | * @return void 25 | */ 26 | public function testDocBlockConstFixer(): void 27 | { 28 | $this->assertSnifferCanFixErrors(new DocBlockConstSniff()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/Spryker/Sniffs/Commenting/DocBlockParamAllowDefaultValueSniffTest.php: -------------------------------------------------------------------------------- 1 | assertSnifferFindsErrors(new DocBlockParamAllowDefaultValueSniff(), 4); 21 | } 22 | 23 | /** 24 | * @return void 25 | */ 26 | public function testDocBlockConstFixer(): void 27 | { 28 | $this->assertSnifferCanFixErrors(new DocBlockParamAllowDefaultValueSniff()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/Spryker/Sniffs/Commenting/DocBlockParamArraySniffTest.php: -------------------------------------------------------------------------------- 1 | assertSnifferFindsErrors(new DocBlockParamArraySniff(), 2); 21 | } 22 | 23 | /** 24 | * @return void 25 | */ 26 | public function testDocBlockConstFixer(): void 27 | { 28 | $this->assertSnifferCanFixErrors(new DocBlockParamArraySniff()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/Spryker/Sniffs/Commenting/DocBlockReturnNullSniffTest.php: -------------------------------------------------------------------------------- 1 | assertSnifferFindsErrors(new DocBlockReturnNullSniff(), 1); 21 | } 22 | 23 | /** 24 | * @return void 25 | */ 26 | public function testDocBlockConstFixer(): void 27 | { 28 | $this->assertSnifferCanFixErrors(new DocBlockReturnNullSniff()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/Spryker/Sniffs/Commenting/DocBlockReturnNullableTypeSniffTest.php: -------------------------------------------------------------------------------- 1 | assertSnifferFindsErrors(new DocBlockReturnNullableTypeSniff(), 3); 21 | } 22 | 23 | /** 24 | * @return void 25 | */ 26 | public function testDocBlockConstFixer(): void 27 | { 28 | $this->assertSnifferCanFixErrors(new DocBlockReturnNullableTypeSniff()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/Spryker/Sniffs/Commenting/DocBlockReturnTagSniffTest.php: -------------------------------------------------------------------------------- 1 | assertSnifferFindsErrors(new DocBlockReturnTagSniff(), 1); 21 | } 22 | 23 | /** 24 | * @return void 25 | */ 26 | public function testDocBlockConstFixer(): void 27 | { 28 | $this->assertSnifferCanFixErrors(new DocBlockReturnTagSniff()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/Spryker/Sniffs/Commenting/DocBlockReturnVoidSniffTest.php: -------------------------------------------------------------------------------- 1 | assertSnifferFindsFixableErrors(new DocBlockReturnVoidSniff(), 3, 3); 21 | } 22 | 23 | /** 24 | * @return void 25 | */ 26 | public function testDocBlockReturnVoidFixer(): void 27 | { 28 | $this->assertSnifferCanFixErrors(new DocBlockReturnVoidSniff(), 3); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/Spryker/Sniffs/Commenting/DocBlockThrowsSniffTest.php: -------------------------------------------------------------------------------- 1 | assertSnifferFindsErrors(new DocBlockThrowsSniff(), 6); 21 | } 22 | 23 | /** 24 | * @return void 25 | */ 26 | public function testDocBlockThrowsFixer(): void 27 | { 28 | $this->assertSnifferCanFixErrors(new DocBlockThrowsSniff(), 6); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/Spryker/Sniffs/Commenting/DocBlockVarSniffTest.php: -------------------------------------------------------------------------------- 1 | assertSnifferFindsErrors(new DocBlockVarSniff(), 1); 21 | } 22 | 23 | /** 24 | * @return void 25 | */ 26 | public function testDocBlockConstFixer(): void 27 | { 28 | $this->assertSnifferCanFixErrors(new DocBlockVarSniff()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/Spryker/Sniffs/Commenting/FullyQualifiedClassNameInDocBlockSniffTest.php: -------------------------------------------------------------------------------- 1 | assertSnifferFindsErrors(new FullyQualifiedClassNameInDocBlockSniff(), 11); 21 | } 22 | 23 | /** 24 | * @return void 25 | */ 26 | public function testDocBlockConstFixer(): void 27 | { 28 | $this->assertSnifferCanFixErrors(new FullyQualifiedClassNameInDocBlockSniff()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/Spryker/Sniffs/Commenting/InlineDocBlockSniffTest.php: -------------------------------------------------------------------------------- 1 | assertSnifferFindsErrors(new InlineDocBlockSniff(), 1); 21 | } 22 | 23 | /** 24 | * @return void 25 | */ 26 | public function testDocBlockConstFixer(): void 27 | { 28 | $this->assertSnifferCanFixErrors(new InlineDocBlockSniff()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/Spryker/Sniffs/Commenting/TypeHintSniffTest.php: -------------------------------------------------------------------------------- 1 | assertSnifferFindsErrors(new TypeHintSniff(), 10); 21 | } 22 | 23 | /** 24 | * @return void 25 | */ 26 | public function testDocBlockThrowsFixer(): void 27 | { 28 | $this->assertSnifferCanFixErrors(new TypeHintSniff()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/Spryker/Sniffs/ControlStructures/DisallowCloakingCheckSniffTest.php: -------------------------------------------------------------------------------- 1 | assertSnifferFindsErrors(new DisallowCloakingCheckSniff(), 10); 21 | } 22 | 23 | /** 24 | * @return void 25 | */ 26 | public function testDocBlockThrowsFixer(): void 27 | { 28 | $this->assertSnifferCanFixErrors(new DisallowCloakingCheckSniff()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/Spryker/Sniffs/Formatting/MethodSignatureParametersLineBreakMethodSniffTest.php: -------------------------------------------------------------------------------- 1 | assertSnifferFindsFixableErrors(new MethodSignatureParametersLineBreakMethodSniff(), 7, 7); 21 | } 22 | 23 | /** 24 | * @return void 25 | */ 26 | public function testMethodSignatureParametersLineBreakMethodFixer(): void 27 | { 28 | $this->assertSnifferCanFixErrors(new MethodSignatureParametersLineBreakMethodSniff()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/Spryker/Sniffs/Internal/SprykerPreferStaticOverSelfSniffTest.php: -------------------------------------------------------------------------------- 1 | assertSnifferFindsErrors(new SprykerPreferStaticOverSelfSniff(), 2); 21 | } 22 | 23 | /** 24 | * @return void 25 | */ 26 | public function testDocBlockConstFixer(): void 27 | { 28 | $this->assertSnifferCanFixErrors(new SprykerPreferStaticOverSelfSniff()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/Spryker/Sniffs/Namespaces/UseStatementSniffTest.php: -------------------------------------------------------------------------------- 1 | assertSnifferFindsErrors(new UseStatementSniff(), 1); 21 | } 22 | 23 | /** 24 | * @return void 25 | */ 26 | public function testDocBlockConstFixer(): void 27 | { 28 | $this->assertSnifferCanFixErrors(new UseStatementSniff()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/Spryker/Sniffs/PHP/DeclareStrictTypesAfterFileDocSniffTest.php: -------------------------------------------------------------------------------- 1 | assertSnifferFindsErrors(new DeclareStrictTypesAfterFileDocSniff(), 2); 21 | } 22 | 23 | /** 24 | * @return void 25 | */ 26 | public function testEmptyEnclosingLineFixer(): void 27 | { 28 | $this->assertSnifferCanFixErrors(new DeclareStrictTypesAfterFileDocSniff()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/Spryker/Sniffs/WhiteSpace/EmptyEnclosingLineSniffTest.php: -------------------------------------------------------------------------------- 1 | assertSnifferFindsErrors(new EmptyEnclosingLineSniff(), 2); 21 | } 22 | 23 | /** 24 | * @return void 25 | */ 26 | public function testEmptyEnclosingLineFixer(): void 27 | { 28 | $this->assertSnifferCanFixErrors(new EmptyEnclosingLineSniff()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/Spryker/Sniffs/WhiteSpace/EmptyLinesSniffTest.php: -------------------------------------------------------------------------------- 1 | assertSnifferFindsErrors(new EmptyLinesSniff(), 6); 21 | } 22 | 23 | /** 24 | * @return void 25 | */ 26 | public function testEmptyEnclosingLineFixer(): void 27 | { 28 | $this->assertSnifferCanFixErrors(new EmptyLinesSniff()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/_data/All/after.php: -------------------------------------------------------------------------------- 1 | $y) { 19 | } 20 | if ($y > $z) { 21 | } 22 | } 23 | 24 | /** 25 | * @return void 26 | */ 27 | public function tooMuchWhitespace() 28 | { 29 | if ($x > $y) { 30 | } 31 | if ($y > $z) { 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/_data/All/before.php: -------------------------------------------------------------------------------- 1 | $y) { 10 | } 11 | if ($y> $z) { 12 | } 13 | } 14 | 15 | public function tooMuchWhitespace() 16 | { 17 | if ($x > $y) { 18 | } 19 | if ($y > $z) { 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/_data/DeclareStrictTypesAfterFileDoc/after.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | protected $prop; 11 | 12 | /** 13 | * @var \ArrayObject Some description. 14 | */ 15 | protected $propWithDescription; 16 | 17 | /** 18 | * @param array $var 19 | * 20 | * @return array 21 | */ 22 | protected function getSimpleInts(array $var): array 23 | { 24 | return $this->foo(); 25 | } 26 | 27 | /** 28 | * @param \ArrayObject $var Some comment. 29 | * 30 | * @return \ArrayObject 31 | */ 32 | protected function getSimpleStringCollection($var) 33 | { 34 | return $this->foo(); 35 | } 36 | 37 | /** 38 | * @return \ArrayObject|array 39 | */ 40 | protected function getArrayObjectOrArray() 41 | { 42 | return $this->foo(); 43 | } 44 | 45 | /** 46 | * @return \ArrayObject|array 47 | */ 48 | protected function getArrayObjectOfStringsOrArrayOfInts() 49 | { 50 | return $this->foo(); 51 | } 52 | 53 | /** 54 | * @return \ArrayObject|null 55 | */ 56 | protected function getSimpleStringCollectionOrNull(): ?\ArrayObject 57 | { 58 | return $this->foo(); 59 | } 60 | 61 | /** 62 | * @return \Iterator 63 | */ 64 | protected function getSimpleIntCollection(): Iterator 65 | { 66 | return $this->foo(); 67 | } 68 | 69 | /** 70 | * @return \Iterator> 71 | */ 72 | protected function createEventResourceQueryContainerPluginIterator(): Iterator 73 | { 74 | return new EventResourceQueryContainerPluginIterator(); 75 | } 76 | 77 | /** 78 | * @return void 79 | */ 80 | protected function inlineDocBlock() 81 | { 82 | /** @var \ArrayObject $bar */ 83 | $bar = $this->foo(); 84 | 85 | /** 86 | * @var \ArrayObject $bar 87 | */ 88 | $bar = $this->foo(); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /tests/_data/DisallowArrayTypeHintSyntax/before.php: -------------------------------------------------------------------------------- 1 | foo(); 25 | } 26 | 27 | /** 28 | * @param \ArrayObject|string[] $var Some comment. 29 | * 30 | * @return \ArrayObject|string[] 31 | */ 32 | protected function getSimpleStringCollection($var) 33 | { 34 | return $this->foo(); 35 | } 36 | 37 | /** 38 | * @return \ArrayObject|array 39 | */ 40 | protected function getArrayObjectOrArray() 41 | { 42 | return $this->foo(); 43 | } 44 | 45 | /** 46 | * @return \ArrayObject|int[] 47 | */ 48 | protected function getArrayObjectOfStringsOrArrayOfInts() 49 | { 50 | return $this->foo(); 51 | } 52 | 53 | /** 54 | * @return \ArrayObject|string[]|null 55 | */ 56 | protected function getSimpleStringCollectionOrNull(): ?\ArrayObject 57 | { 58 | return $this->foo(); 59 | } 60 | 61 | /** 62 | * @return \Iterator|int[] 63 | */ 64 | protected function getSimpleIntCollection(): Iterator 65 | { 66 | return $this->foo(); 67 | } 68 | 69 | /** 70 | * @return \Iterator|\Generated\Shared\Transfer\EventEntityTransfer[][] 71 | */ 72 | protected function createEventResourceQueryContainerPluginIterator(): Iterator 73 | { 74 | return new EventResourceQueryContainerPluginIterator(); 75 | } 76 | 77 | /** 78 | * @return void 79 | */ 80 | protected function inlineDocBlock() 81 | { 82 | /** @var \ArrayObject|string[] $bar */ 83 | $bar = $this->foo(); 84 | 85 | /** 86 | * @var \ArrayObject|string[] $bar 87 | */ 88 | $bar = $this->foo(); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /tests/_data/DisallowCloakingCheck/after.php: -------------------------------------------------------------------------------- 1 | ok()) { 17 | } 18 | 19 | if ( 20 | $this->foo('x', 'y') 21 | || $this->ok() 22 | ) { 23 | } 24 | 25 | $foo->_if((bool)$filterByCompanyBusinessUnitIds); 26 | 27 | if (!isset($this->prop)) { 28 | } 29 | 30 | $x = (bool)$this->prop; 31 | 32 | return (bool)$x; 33 | } 34 | 35 | public function simplify() 36 | { 37 | if (empty($iso2Code) === false) {} 38 | if (isset($iso2Code) === true) {} 39 | } 40 | 41 | public function complex($successTable) 42 | { 43 | return [ 44 | 'renderSuccessTable' => empty($successTable->getData()) !== true, 45 | ]; 46 | } 47 | 48 | public function ok() 49 | { 50 | $x = []; 51 | if (!empty($x['y'])) { 52 | } 53 | } 54 | 55 | public function ignoreForNow() 56 | { 57 | $y = 'y'; 58 | $x = []; 59 | if (!isset($x->{$y})) {} 60 | 61 | if (!isset($xmlProcess->events)) {} 62 | 63 | if (!isset($this->_joinData->relation)) {} 64 | 65 | if (empty($_SESSION)) {} 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /tests/_data/DisallowCloakingCheck/before.php: -------------------------------------------------------------------------------- 1 | ok())) { 17 | } 18 | 19 | if ( 20 | !empty($this->foo('x', 'y')) 21 | || $this->ok() 22 | ) { 23 | } 24 | 25 | $foo->_if(!empty($filterByCompanyBusinessUnitIds)); 26 | 27 | if (!isset($this->prop)) { 28 | } 29 | 30 | $x = !empty($this->prop); 31 | 32 | return !empty($x); 33 | } 34 | 35 | public function simplify() 36 | { 37 | if (empty($iso2Code) === false) {} 38 | if (isset($iso2Code) === true) {} 39 | } 40 | 41 | public function complex($successTable) 42 | { 43 | return [ 44 | 'renderSuccessTable' => empty($successTable->getData()) !== true, 45 | ]; 46 | } 47 | 48 | public function ok() 49 | { 50 | $x = []; 51 | if (!empty($x['y'])) { 52 | } 53 | } 54 | 55 | public function ignoreForNow() 56 | { 57 | $y = 'y'; 58 | $x = []; 59 | if (!isset($x->{$y})) {} 60 | 61 | if (!isset($xmlProcess->events)) {} 62 | 63 | if (!isset($this->_joinData->relation)) {} 64 | 65 | if (empty($_SESSION)) {} 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /tests/_data/DocBlockConst/after.php: -------------------------------------------------------------------------------- 1 | |string 34 | */ 35 | public const CONST_COMPLEX = 'complex case'; 36 | 37 | /** 38 | * @var array 39 | */ 40 | public const CONST_COMPLEX_MISS = 'complex case missing string'; 41 | } 42 | -------------------------------------------------------------------------------- /tests/_data/DocBlockConst/before.php: -------------------------------------------------------------------------------- 1 | |string 28 | */ 29 | public const CONST_COMPLEX = 'complex case'; 30 | 31 | /** 32 | * @var array 33 | */ 34 | public const CONST_COMPLEX_MISS = 'complex case missing string'; 35 | } 36 | -------------------------------------------------------------------------------- /tests/_data/DocBlockParamAllowDefaultValue/after.php: -------------------------------------------------------------------------------- 1 | >|null $array 27 | * @return void 28 | */ 29 | public function generics(array $array = null): void 30 | { 31 | } 32 | 33 | /** 34 | * @param iterable<\Generated\Shared\Transfer\SalesPaymentTransfer> $x 35 | * 36 | * @return array<\Orm\Zed\Payment\Persistence\SpySalesPayment> 37 | */ 38 | public function iterableTest(iterable $x = []): array 39 | { 40 | return $x; 41 | } 42 | 43 | /** 44 | * @param \ArrayObject|iterable $itemTransfers 45 | * 46 | * @return array 47 | */ 48 | protected function getCountryIso2Codes(iterable $itemTransfers): array 49 | { 50 | return array_unique($itemTransfers); 51 | } 52 | 53 | /** 54 | * @param class-string<\Propel\Runtime\Map\TableMap> $tableMapClass The name of the table map to add 55 | * 56 | * @return void 57 | */ 58 | public function registerTableMapClass(string $tableMapClass): void 59 | { 60 | } 61 | 62 | /** 63 | * @param string|null $value The value to convert. 64 | * 65 | * @return string|null 66 | */ 67 | public function toPHP(mixed $value): mixed { 68 | return $value; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /tests/_data/DocBlockParamAllowDefaultValue/before.php: -------------------------------------------------------------------------------- 1 | > $array 27 | * @return void 28 | */ 29 | public function generics(array $array = null): void 30 | { 31 | } 32 | 33 | /** 34 | * @param iterable<\Generated\Shared\Transfer\SalesPaymentTransfer> $x 35 | * 36 | * @return array<\Orm\Zed\Payment\Persistence\SpySalesPayment> 37 | */ 38 | public function iterableTest(iterable $x = []): array 39 | { 40 | return $x; 41 | } 42 | 43 | /** 44 | * @param \ArrayObject $itemTransfers 45 | * 46 | * @return array 47 | */ 48 | protected function getCountryIso2Codes(iterable $itemTransfers): array 49 | { 50 | return array_unique($itemTransfers); 51 | } 52 | 53 | /** 54 | * @param class-string<\Propel\Runtime\Map\TableMap> $tableMapClass The name of the table map to add 55 | * 56 | * @return void 57 | */ 58 | public function registerTableMapClass(string $tableMapClass): void 59 | { 60 | } 61 | 62 | /** 63 | * @param string|null $value The value to convert. 64 | * 65 | * @return string|null 66 | */ 67 | public function toPHP(mixed $value): mixed { 68 | return $value; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /tests/_data/DocBlockParamArray/after.php: -------------------------------------------------------------------------------- 1 | $array 9 | * @param iterable $iterable 10 | * @return void 11 | */ 12 | public function fixMe(array $array, iterable $iterable): void 13 | { 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/_data/DocBlockParamArray/before.php: -------------------------------------------------------------------------------- 1 | |array $array 9 | * @param iterable|iterable $iterable 10 | * @return void 11 | */ 12 | public function fixMe(array $array, iterable $iterable): void 13 | { 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/_data/DocBlockReturnNull/after.php: -------------------------------------------------------------------------------- 1 | foo()) { 21 | return null; 22 | } 23 | 24 | return new static(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/_data/DocBlockReturnNull/before.php: -------------------------------------------------------------------------------- 1 | foo()) { 21 | return null; 22 | } 23 | 24 | return new static(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/_data/DocBlockReturnNullableType/after.php: -------------------------------------------------------------------------------- 1 | >|null 54 | */ 55 | public function array(): ?array 56 | { 57 | return []; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /tests/_data/DocBlockReturnNullableType/before.php: -------------------------------------------------------------------------------- 1 | > 54 | */ 55 | public function array(): ?array 56 | { 57 | return []; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /tests/_data/DocBlockReturnTag/after.php: -------------------------------------------------------------------------------- 1 | |string|null> 9 | */ 10 | public function allGood(): array 11 | { 12 | return [ 13 | ]; 14 | } 15 | 16 | /** 17 | * @return array|string|null> Some comment with $someVar. 18 | */ 19 | public function allGoodComment(): array 20 | { 21 | return [ 22 | ]; 23 | } 24 | 25 | /** 26 | * @return array|string $x 27 | */ 28 | public function fixMe(): array 29 | { 30 | return [ 31 | ]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/_data/DocBlockReturnTag/before.php: -------------------------------------------------------------------------------- 1 | |string|null> 9 | */ 10 | public function allGood(): array 11 | { 12 | return [ 13 | ]; 14 | } 15 | 16 | /** 17 | * @return array|string|null> Some comment with $someVar. 18 | */ 19 | public function allGoodComment(): array 20 | { 21 | return [ 22 | ]; 23 | } 24 | 25 | /** 26 | * @return array|string $x 27 | */ 28 | public function fixMe(): array 29 | { 30 | return [ 31 | ]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/_data/DocBlockReturnVoid/after.php: -------------------------------------------------------------------------------- 1 | anotherVoidOne(); 33 | } 34 | 35 | /** 36 | * @return \Closure 37 | */ 38 | public function foo(): Closure 39 | { 40 | /** 41 | * @return void 42 | */ 43 | $bar = static function (): void { 44 | }; 45 | 46 | return $bar; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /tests/_data/DocBlockReturnVoid/before.php: -------------------------------------------------------------------------------- 1 | anotherVoidOne(); 30 | } 31 | 32 | /** 33 | * @return \Closure 34 | */ 35 | public function foo(): Closure 36 | { 37 | /** 38 | * @return void 39 | */ 40 | $bar = static function (): void { 41 | }; 42 | 43 | return $bar; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /tests/_data/DocBlockThrows/after.php: -------------------------------------------------------------------------------- 1 | $value === true ? throw new DomainException() : null; 31 | 32 | $bar = static function (): void { 33 | throw new RuntimeException(); 34 | }; 35 | 36 | throw new LogicException(); 37 | } 38 | 39 | /** 40 | * @throws \Foo\Bar\SomeException 41 | * @throws \Foo\Baz\Exception 42 | * @return void 43 | */ 44 | public function complex(): void 45 | { 46 | if ($x) { 47 | throw new SomeException(); 48 | } else { 49 | throw new SomeAliasedException(); 50 | } 51 | } 52 | 53 | /** 54 | * @throws \BadMethodCallException 55 | * @return void 56 | */ 57 | public function someException() 58 | { 59 | if ($this->something()) { 60 | throw new \BadMethodCallException(); 61 | } 62 | } 63 | 64 | /** 65 | * @throws \League\OAuth2\Server\Exception\OAuthServerException 66 | * @return void 67 | */ 68 | public function staticCall(): void 69 | { 70 | throw OAuthServerException::accessDenied('baz'); 71 | 72 | new Parser(); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /tests/_data/DocBlockThrows/before.php: -------------------------------------------------------------------------------- 1 | $value === true ? throw new DomainException() : null; 29 | 30 | $bar = static function (): void { 31 | throw new RuntimeException(); 32 | }; 33 | 34 | throw new LogicException(); 35 | } 36 | 37 | /** 38 | * @return void 39 | */ 40 | public function complex(): void 41 | { 42 | if ($x) { 43 | throw new SomeException(); 44 | } else { 45 | throw new SomeAliasedException(); 46 | } 47 | } 48 | 49 | /** 50 | * @return void 51 | */ 52 | public function someException() 53 | { 54 | if ($this->something()) { 55 | throw new \BadMethodCallException(); 56 | } 57 | } 58 | 59 | /** 60 | * @return void 61 | */ 62 | public function staticCall(): void 63 | { 64 | throw OAuthServerException::accessDenied('baz'); 65 | 66 | new Parser(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /tests/_data/DocBlockVar/after.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | protected $foo = []; 18 | 19 | /** 20 | * Stack of warnings. 21 | * 22 | * @var list 23 | */ 24 | protected $warnings = []; 25 | 26 | /** 27 | * The left parts of the join condition 28 | * 29 | * @var list 30 | */ 31 | protected $left = []; 32 | } 33 | -------------------------------------------------------------------------------- /tests/_data/DocBlockVar/before.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | protected $foo = []; 18 | 19 | /** 20 | * Stack of warnings. 21 | * 22 | * @var list 23 | */ 24 | protected $warnings = []; 25 | 26 | /** 27 | * The left parts of the join condition 28 | * 29 | * @var list 30 | */ 31 | protected $left = []; 32 | } 33 | -------------------------------------------------------------------------------- /tests/_data/EmptyEnclosingLine/after.php: -------------------------------------------------------------------------------- 1 | |\BarBaz|null $input X 46 | * @return (\Foo\Bar|BarBaz)[] 47 | */ 48 | public function tooComplex($input = null) 49 | { 50 | return $input; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /tests/_data/FullyQualifiedClassNameInDocBlock/before.php: -------------------------------------------------------------------------------- 1 | |BarBaz|null $input X 46 | * @return (\Foo\Bar|BarBaz)[] 47 | */ 48 | public function tooComplex($input = null) 49 | { 50 | return $input; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /tests/_data/InlineDocBlock/after.php: -------------------------------------------------------------------------------- 1 | > $_indices 14 | */ 15 | $_indices = []; 16 | 17 | /* 18 | * This is not a docblock; 19 | * But a multiline comment 20 | */ 21 | $foo = $_indices['x']; 22 | 23 | /** @var string|null $bar */ 24 | $bar = $_indices['y']; 25 | 26 | /** @var string $foo */ 27 | $foo = $_indices['z']; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tests/_data/InlineDocBlock/before.php: -------------------------------------------------------------------------------- 1 | > $_indices 14 | */ 15 | $_indices = []; 16 | 17 | /* 18 | * This is not a docblock; 19 | * But a multiline comment 20 | */ 21 | $foo = $_indices['x']; 22 | 23 | /** @var string|null $bar */ 24 | $bar = $_indices['y']; 25 | 26 | /* @var string $foo */ 27 | $foo = $_indices['z']; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tests/_data/MethodSignatureParametersLineBreakMethod/after.php: -------------------------------------------------------------------------------- 1 | null, // breaks code, needs to be refactored to class prop 28 | ]; 29 | 30 | return new static($defaults); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/_data/SprykerPreferStaticOverSelf/before.php: -------------------------------------------------------------------------------- 1 | null, // breaks code, needs to be refactored to class prop 28 | ]; 29 | 30 | return new static($defaults); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/_data/TypeHint/after.php: -------------------------------------------------------------------------------- 1 | |string|null>|string|null>|string|null 14 | */ 15 | protected $arrays; 16 | 17 | /** 18 | * @return string[]|null 19 | */ 20 | public function one(): ?array 21 | { 22 | return []; 23 | } 24 | 25 | /** 26 | * @param (string|int)[] $test 27 | * 28 | * @return string[]|int[] 29 | */ 30 | public function second(array $test): array 31 | { 32 | return []; 33 | } 34 | 35 | /** 36 | * @param \ArrayObject|int[] $array 37 | * 38 | * @return \ArrayAccess|array $array 39 | */ 40 | public function third(array $array): array 41 | { 42 | return []; 43 | } 44 | 45 | /** 46 | * @param \Collection|int[] $array 47 | * 48 | * @return \Collection|array $array 49 | */ 50 | public function collection(array $array): array 51 | { 52 | return []; 53 | } 54 | 55 | /** 56 | * @param \Propel\Runtime\Collection\ObjectCollection|iterable<\Orm\Zed\Sales\Persistence\SpySalesShipment> $col 57 | * 58 | * @return \Propel\Runtime\Collection\Collection|\Propel\Runtime\Collection\ObjectCollection<\Propel\Runtime\ActiveRecord\ActiveRecordInterface> 59 | */ 60 | protected function complex($col) 61 | { 62 | /** @var \Propel\Runtime\Collection\ObjectCollection<\Orm\Zed\SalesReturn\Persistence\SpySalesReturn> $salesReturnEntityCollection */ 63 | $salesReturnEntityCollection = $this->runQuery(); 64 | 65 | /** @var \ArrayObject<\Generated\Shared\Transfer\ShipmentGroupTransfer> $shipmentGroupCollection */ 66 | $shipmentGroupCollection = $options[static::OPTION_SHIPMENT_GROUPS]; 67 | 68 | return $salesReturnEntityCollection->getXyz(); 69 | } 70 | 71 | /** 72 | * @param \Propel\Runtime\Collection|array|string|int $x 73 | * 74 | * @return \Propel\Runtime\Collection|\ArrayObject<\Foo>|array|string|int 75 | */ 76 | protected function sortMultiple($x) 77 | { 78 | return $x; 79 | } 80 | 81 | /** 82 | * @return \Generator> 83 | */ 84 | public function mergeGenerics(): Generator 85 | { 86 | yield $this->x(); 87 | } 88 | 89 | /** 90 | * @param \Propel\Runtime\Collection\ObjectCollection<\Orm\Zed\ProductImage\Persistence\SpyProductImageSet> $productImageSetEntities 91 | * 92 | * @return array<\Generated\Shared\Transfer\ProductImageSetTransfer> 93 | */ 94 | protected function complexGeneric(ObjectCollection $productImageSetEntities): array 95 | { 96 | return []; 97 | } 98 | 99 | /** 100 | * @param \ArrayObject $options 101 | * @return array 102 | */ 103 | public function merge($options): array 104 | { 105 | return []; 106 | } 107 | 108 | /** 109 | * @return array|string|null>|string 110 | */ 111 | public function complexUnion(): array 112 | { 113 | return []; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /tests/_data/UseStatement/after.php: -------------------------------------------------------------------------------- 1 |