Source for file FunctionSpacingSniff.php
Documentation is available at FunctionSpacingSniff.php
* Checks the separation between methods in a class or interface.
* @author Greg Sherwood <gsherwood@squiz.net>
* @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
* @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Files\File;
class FunctionSpacingSniff implements Sniff
* The number of blank lines between functions.
* Returns an array of tokens this test wants to listen for.
public function register ()
return array (T_FUNCTION );
* Processes this sniff when one of its tokens is encountered.
* @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned.
* @param int $stackPtr The position of the current token
* in the stack passed in $tokens.
public function process (File $phpcsFile, $stackPtr)
$tokens = $phpcsFile->getTokens ();
$this->spacing = (int) $this->spacing;
Check the number of blank lines
if (isset ($tokens[$stackPtr]['scope_closer']) === false ) {
// Must be an interface method, so the closer is the semicolon.
$closer = $phpcsFile->findNext (T_SEMICOLON, $stackPtr);
$closer = $tokens[$stackPtr]['scope_closer'];
// Allow for comments on the same line as the closer.
for ($nextLineToken = ($closer + 1 ); $nextLineToken < $phpcsFile->numTokens; $nextLineToken++ ) {
if ($tokens[$nextLineToken]['line'] !== $tokens[$closer]['line']) {
if ($nextLineToken === ($phpcsFile->numTokens - 1 )) {
// We are at the end of the file.
// Don't check spacing after the function because this
// should be done by an EOF sniff.
$foundLines = $this->spacing;
$nextContent = $phpcsFile->findNext (T_WHITESPACE , $nextLineToken, null , true );
if ($nextContent === false ) {
// We are at the end of the file.
// Don't check spacing after the function because this
// should be done by an EOF sniff.
$foundLines = $this->spacing;
$foundLines += ($tokens[$nextContent]['line'] - $tokens[$nextLineToken]['line']);
if ($foundLines !== $this->spacing) {
$error = 'Expected %s blank line';
if ($this->spacing !== 1 ) {
$error .= ' after function; %s found';
$fix = $phpcsFile->addFixableError ($error, $closer, 'After', $data);
$phpcsFile->fixer ->beginChangeset ();
for ($i = $nextLineToken; $i <= $nextContent; $i++ ) {
if ($tokens[$i]['line'] === $tokens[$nextContent]['line']) {
$phpcsFile->fixer ->addContentBefore ($i, str_repeat($phpcsFile->eolChar , $this->spacing));
$phpcsFile->fixer ->replaceToken ($i, '');
$phpcsFile->fixer ->endChangeset ();
Check the number of blank lines
for ($i = $stackPtr; $i > 0; $i-- ) {
if (strpos($tokens[$i]['content'], $phpcsFile->eolChar ) === false ) {
if (is_null($prevLineToken) === true ) {
// Never found the previous line, which means
// there are 0 blank lines before the function.
$currentLine = $tokens[$stackPtr]['line'];
$prevContent = $phpcsFile->findPrevious (T_WHITESPACE , $prevLineToken, null , true );
if ($tokens[$prevContent]['code'] === T_COMMENT ) {
// Ignore comments as they can have different spacing rules, and this
// isn't a proper function comment anyway.
&& $tokens[$prevContent]['line'] === ($currentLine - 1 )
// Account for function comments.
$prevContent = $phpcsFile->findPrevious (T_WHITESPACE , ($tokens[$prevContent]['comment_opener'] - 1 ), null , true );
// Before we throw an error, check that we are not throwing an error
// for another function. We don't want to error for no blank lines after
// the previous function and no blank lines before this one as well.
$prevLine = ($tokens[$prevContent]['line'] - 1 );
while ($currentLine !== $prevLine && $currentLine > 1 && $i > 0 ) {
if (isset ($tokens[$i]['scope_condition']) === true ) {
$scopeCondition = $tokens[$i]['scope_condition'];
if ($tokens[$scopeCondition]['code'] === T_FUNCTION ) {
// Found a previous function.
} else if ($tokens[$i]['code'] === T_FUNCTION ) {
// Found another interface function.
$currentLine = $tokens[$i]['line'];
if ($currentLine === $prevLine) {
if ($tokens[($i - 1 )]['line'] < $currentLine && $tokens[($i + 1 )]['line'] > $currentLine) {
// This token is on a line by itself. If it is whitespace, the line is empty.
if ($tokens[$i]['code'] === T_WHITESPACE ) {
if ($foundLines !== $this->spacing) {
$error = 'Expected %s blank line';
if ($this->spacing !== 1 ) {
$error .= ' before function; %s found';
$fix = $phpcsFile->addFixableError ($error, $stackPtr, 'Before', $data);
if ($prevContent === 0 ) {
$nextSpace = $phpcsFile->findNext (T_WHITESPACE , ($prevContent + 1 ), $stackPtr);
if ($nextSpace === false ) {
$nextSpace = ($stackPtr - 1 );
if ($foundLines < $this->spacing) {
$padding = str_repeat($phpcsFile->eolChar , ($this->spacing - $foundLines));
$phpcsFile->fixer ->addContent ($nextSpace, $padding);
$nextContent = $phpcsFile->findNext (T_WHITESPACE , ($nextSpace + 1 ), null , true );
$phpcsFile->fixer ->beginChangeset ();
for ($i = $nextSpace; $i < ($nextContent - 1 ); $i++ ) {
$phpcsFile->fixer ->replaceToken ($i, '');
$phpcsFile->fixer ->replaceToken ($i, str_repeat($phpcsFile->eolChar , $this->spacing));
$phpcsFile->fixer ->endChangeset ();
Documentation generated on Mon, 11 Mar 2019 15:27:32 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.
|