1<?php 2/** 3 * Squiz_Sniffs_ControlStructures_InlineControlStructureSniff. 4 * 5 * PHP version 5 6 * 7 * @category PHP 8 * @package PHP_CodeSniffer 9 * @author Greg Sherwood <gsherwood@squiz.net> 10 * @author Marc McIntyre <mmcintyre@squiz.net> 11 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600) 12 * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence 13 * @link http://pear.php.net/package/PHP_CodeSniffer 14 */ 15 16/** 17 * Squiz_Sniffs_ControlStructures_InlineIfDeclarationSniff. 18 * 19 * Tests the spacing of shorthand IF statements. 20 * 21 * @category PHP 22 * @package PHP_CodeSniffer 23 * @author Greg Sherwood <gsherwood@squiz.net> 24 * @author Marc McIntyre <mmcintyre@squiz.net> 25 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600) 26 * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence 27 * @version Release: @package_version@ 28 * @link http://pear.php.net/package/PHP_CodeSniffer 29 */ 30class Squiz_Sniffs_ControlStructures_InlineIfDeclarationSniff implements PHP_CodeSniffer_Sniff 31{ 32 33 34 /** 35 * Returns an array of tokens this test wants to listen for. 36 * 37 * @return array 38 */ 39 public function register() 40 { 41 return array(T_INLINE_THEN); 42 43 }//end register() 44 45 46 /** 47 * Processes this sniff, when one of its tokens is encountered. 48 * 49 * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. 50 * @param int $stackPtr The position of the current token in the 51 * stack passed in $tokens. 52 * 53 * @return void 54 */ 55 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) 56 { 57 $tokens = $phpcsFile->getTokens(); 58 59 $openBracket = null; 60 $closeBracket = null; 61 if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { 62 $parens = $tokens[$stackPtr]['nested_parenthesis']; 63 $openBracket = array_pop($parens); 64 $closeBracket = $tokens[$openBracket]['parenthesis_closer']; 65 } 66 67 // Find the beginning of the statement. If we don't find a 68 // semicolon (end of statement) or comma (end of array value) 69 // then assume the content before the closing parenthesis is the end. 70 $else = $phpcsFile->findNext(T_INLINE_ELSE, ($stackPtr + 1)); 71 $statementEnd = $phpcsFile->findNext(array(T_SEMICOLON, T_COMMA), ($else + 1), $closeBracket); 72 if ($statementEnd === false) { 73 $statementEnd = $phpcsFile->findPrevious(T_WHITESPACE, ($closeBracket - 1), null, true); 74 } 75 76 // Make sure it's all on the same line. 77 if ($tokens[$statementEnd]['line'] !== $tokens[$stackPtr]['line']) { 78 $error = 'Inline shorthand IF statement must be declared on a single line'; 79 $phpcsFile->addError($error, $stackPtr, 'NotSingleLine'); 80 return; 81 } 82 83 // Make sure there are spaces around the question mark. 84 $contentBefore = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); 85 $contentAfter = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); 86 if ($tokens[$contentBefore]['code'] !== T_CLOSE_PARENTHESIS) { 87 $error = 'Inline shorthand IF statement requires brackets around comparison'; 88 $phpcsFile->addError($error, $stackPtr, 'NoBrackets'); 89 } 90 91 $spaceBefore = ($tokens[$stackPtr]['column'] - ($tokens[$contentBefore]['column'] + $tokens[$contentBefore]['length'])); 92 if ($spaceBefore !== 1) { 93 $error = 'Inline shorthand IF statement requires 1 space before THEN; %s found'; 94 $data = array($spaceBefore); 95 $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingBeforeThen', $data); 96 if ($fix === true) { 97 if ($spaceBefore === 0) { 98 $phpcsFile->fixer->addContentBefore($stackPtr, ' '); 99 } else { 100 $phpcsFile->fixer->replaceToken(($stackPtr - 1), ' '); 101 } 102 } 103 } 104 105 // If there is no content between the ? and the : operators, then they are 106 // trying to replicate an elvis operator, even though PHP doesn't have one. 107 // In this case, we want no spaces between the two operators so ?: looks like 108 // an operator itself. 109 $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); 110 if ($tokens[$next]['code'] === T_INLINE_ELSE) { 111 $inlineElse = $next; 112 if ($inlineElse !== ($stackPtr + 1)) { 113 $error = 'Inline shorthand IF statement without THEN statement requires 0 spaces between THEN and ELSE'; 114 $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ElvisSpacing'); 115 if ($fix === true) { 116 $phpcsFile->fixer->replaceToken(($stackPtr + 1), ''); 117 } 118 } 119 } else { 120 $spaceAfter = (($tokens[$contentAfter]['column']) - ($tokens[$stackPtr]['column'] + 1)); 121 if ($spaceAfter !== 1) { 122 $error = 'Inline shorthand IF statement requires 1 space after THEN; %s found'; 123 $data = array($spaceAfter); 124 $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingAfterThen', $data); 125 if ($spaceAfter === 0) { 126 $phpcsFile->fixer->addContent($stackPtr, ' '); 127 } else { 128 $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); 129 } 130 } 131 132 // Make sure the ELSE has the correct spacing. 133 $inlineElse = $phpcsFile->findNext(T_INLINE_ELSE, ($stackPtr + 1), $statementEnd, false); 134 $contentBefore = $phpcsFile->findPrevious(T_WHITESPACE, ($inlineElse - 1), null, true); 135 $spaceBefore = ($tokens[$inlineElse]['column'] - ($tokens[$contentBefore]['column'] + $tokens[$contentBefore]['length'])); 136 if ($spaceBefore !== 1) { 137 $error = 'Inline shorthand IF statement requires 1 space before ELSE; %s found'; 138 $data = array($spaceBefore); 139 $fix = $phpcsFile->addFixableError($error, $inlineElse, 'SpacingBeforeElse', $data); 140 if ($fix === true) { 141 if ($spaceBefore === 0) { 142 $phpcsFile->fixer->addContentBefore($inlineElse, ' '); 143 } else { 144 $phpcsFile->fixer->replaceToken(($inlineElse - 1), ' '); 145 } 146 } 147 } 148 }//end if 149 150 $contentAfter = $phpcsFile->findNext(T_WHITESPACE, ($inlineElse + 1), null, true); 151 $spaceAfter = (($tokens[$contentAfter]['column']) - ($tokens[$inlineElse]['column'] + 1)); 152 if ($spaceAfter !== 1) { 153 $error = 'Inline shorthand IF statement requires 1 space after ELSE; %s found'; 154 $data = array($spaceAfter); 155 $fix = $phpcsFile->addFixableError($error, $inlineElse, 'SpacingAfterElse', $data); 156 if ($spaceAfter === 0) { 157 $phpcsFile->fixer->addContent($inlineElse, ' '); 158 } else { 159 $phpcsFile->fixer->replaceToken(($inlineElse + 1), ' '); 160 } 161 } 162 163 }//end process() 164 165 166}//end class 167