1<?php 2/** 3 * Generic_Sniffs_Files_EndFileNewlineSniff. 4 * 5 * PHP version 5 6 * 7 * @category PHP 8 * @package PHP_CodeSniffer 9 * @author Greg Sherwood <gsherwood@squiz.net> 10 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600) 11 * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence 12 * @link http://pear.php.net/package/PHP_CodeSniffer 13 */ 14 15/** 16 * Generic_Sniffs_Files_EndFileNewlineSniff. 17 * 18 * Ensures the file ends with a newline character. 19 * 20 * @category PHP 21 * @package PHP_CodeSniffer 22 * @author Greg Sherwood <gsherwood@squiz.net> 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 */ 28class PSR2_Sniffs_Files_EndFileNewlineSniff implements PHP_CodeSniffer_Sniff 29{ 30 31 32 /** 33 * Returns an array of tokens this test wants to listen for. 34 * 35 * @return array 36 */ 37 public function register() 38 { 39 return array(T_OPEN_TAG); 40 41 }//end register() 42 43 44 /** 45 * Processes this sniff, when one of its tokens is encountered. 46 * 47 * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. 48 * @param int $stackPtr The position of the current token in 49 * the stack passed in $tokens. 50 * 51 * @return void 52 */ 53 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) 54 { 55 if ($phpcsFile->findNext(T_INLINE_HTML, ($stackPtr + 1)) !== false) { 56 return ($phpcsFile->numTokens + 1); 57 } 58 59 // Skip to the end of the file. 60 $tokens = $phpcsFile->getTokens(); 61 $lastToken = ($phpcsFile->numTokens - 1); 62 63 if ($tokens[$lastToken]['content'] === '') { 64 $lastToken--; 65 } 66 67 // Hard-coding the expected \n in this sniff as it is PSR-2 specific and 68 // PSR-2 enforces the use of unix style newlines. 69 if (substr($tokens[$lastToken]['content'], -1) !== "\n") { 70 $error = 'Expected 1 newline at end of file; 0 found'; 71 $fix = $phpcsFile->addFixableError($error, $lastToken, 'NoneFound'); 72 if ($fix === true) { 73 $phpcsFile->fixer->addNewline($lastToken); 74 } 75 76 $phpcsFile->recordMetric($stackPtr, 'Number of newlines at EOF', '0'); 77 return ($phpcsFile->numTokens + 1); 78 } 79 80 // Go looking for the last non-empty line. 81 $lastLine = $tokens[$lastToken]['line']; 82 if ($tokens[$lastToken]['code'] === T_WHITESPACE 83 || $tokens[$lastToken]['code'] === T_DOC_COMMENT_WHITESPACE 84 ) { 85 $lastCode = $phpcsFile->findPrevious(array(T_WHITESPACE, T_DOC_COMMENT_WHITESPACE), ($lastToken - 1), null, true); 86 } else { 87 $lastCode = $lastToken; 88 } 89 90 $lastCodeLine = $tokens[$lastCode]['line']; 91 $blankLines = ($lastLine - $lastCodeLine + 1); 92 $phpcsFile->recordMetric($stackPtr, 'Number of newlines at EOF', $blankLines); 93 94 if ($blankLines > 1) { 95 $error = 'Expected 1 blank line at end of file; %s found'; 96 $data = array($blankLines); 97 $fix = $phpcsFile->addFixableError($error, $lastCode, 'TooMany', $data); 98 99 if ($fix === true) { 100 $phpcsFile->fixer->beginChangeset(); 101 $phpcsFile->fixer->replaceToken($lastCode, rtrim($tokens[$lastCode]['content'])); 102 for ($i = ($lastCode + 1); $i < $lastToken; $i++) { 103 $phpcsFile->fixer->replaceToken($i, ''); 104 } 105 106 $phpcsFile->fixer->replaceToken($lastToken, $phpcsFile->eolChar); 107 $phpcsFile->fixer->endChangeset(); 108 } 109 } 110 111 // Skip the rest of the file. 112 return ($phpcsFile->numTokens + 1); 113 114 }//end process() 115 116 117}//end class 118