Source for file SideEffectsSniff.php
Documentation is available at SideEffectsSniff.php
* Ensures a file declares new symbols and causes no other side effects, or executes logic with side effects, but not both.
* @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\PSR1\Sniffs\Files;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Util\Tokens;
class SideEffectsSniff implements Sniff
* Returns an array of tokens this test wants to listen for.
public function register ()
return array (T_OPEN_TAG );
* 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
public function process (File $phpcsFile, $stackPtr)
$tokens = $phpcsFile->getTokens ();
$result = $this->searchForConflict ($phpcsFile, 0 , ($phpcsFile->numTokens - 1 ), $tokens);
if ($result['symbol'] !== null && $result['effect'] !== null ) {
$error = 'A file should declare new symbols (classes, functions, constants, etc.) and cause no other side effects, or it should execute logic with side effects, but should not do both. The first symbol is defined on line %s and the first side effect is on line %s.';
$tokens[$result['symbol']]['line'],
$tokens[$result['effect']]['line'],
$phpcsFile->addWarning ($error, 0 , 'FoundWithSymbols', $data);
$phpcsFile->recordMetric ($stackPtr, 'Declarations and side effects mixed', 'yes');
$phpcsFile->recordMetric ($stackPtr, 'Declarations and side effects mixed', 'no');
// Ignore the rest of the file.
return ($phpcsFile->numTokens + 1 );
* Searches for symbol declarations and side effects.
* Returns the positions of both the first symbol declared and the first
* side effect in the file. A NULL value for either indicates nothing was
* @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned.
* @param int $start The token to start searching from.
* @param int $end The token to search to.
* @param array $tokens The stack of tokens that make up
private function searchForConflict ($phpcsFile, $start, $end, $tokens)
T_INTERFACE => T_INTERFACE ,
T_FUNCTION => T_FUNCTION ,
for ($i = $start; $i <= $end; $i++ ) {
// Ignore whitespace and comments.
if (isset (Tokens ::$emptyTokens[$tokens[$i]['code']]) === true ) {
if ($tokens[$i]['code'] === T_OPEN_TAG
|| $tokens[$i]['code'] === T_CLOSE_TAG
if (substr($tokens[$i]['content'], 0 , 2 ) === '#!') {
// Ignore entire namespace, declare, const and use statements.
if ($tokens[$i]['code'] === T_NAMESPACE
|| $tokens[$i]['code'] === T_USE
|| $tokens[$i]['code'] === T_DECLARE
|| $tokens[$i]['code'] === T_CONST
if (isset ($tokens[$i]['scope_opener']) === true ) {
$i = $tokens[$i]['scope_closer'];
$semicolon = $phpcsFile->findNext (T_SEMICOLON, ($i + 1 ));
if ($semicolon !== false ) {
// Ignore function/class prefixes.
if (isset (Tokens ::$methodPrefixes[$tokens[$i]['code']]) === true ) {
$i = $tokens[$i]['scope_closer'];
// Detect and skip over symbols.
if (isset ($symbols[$tokens[$i]['code']]) === true
&& isset ($tokens[$i]['scope_closer']) === true
if ($firstSymbol === null ) {
$i = $tokens[$i]['scope_closer'];
} else if ($tokens[$i]['code'] === T_STRING
&& strtolower($tokens[$i]['content']) === 'define'
$prev = $phpcsFile->findPrevious (T_WHITESPACE , ($i - 1 ), null , true );
if ($tokens[$prev]['code'] !== T_OBJECT_OPERATOR ) {
if ($firstSymbol === null ) {
$semicolon = $phpcsFile->findNext (T_SEMICOLON, ($i + 1 ));
if ($semicolon !== false ) {
// Conditional statements are allowed in symbol files as long as the
// contents is only a symbol definition. So don't count these as effects
if (isset ($conditions[$tokens[$i]['code']]) === true ) {
if (isset ($tokens[$i]['scope_opener']) === false ) {
// Probably an "else if", so just ignore.
$result = $this->searchForConflict (
($tokens[$i]['scope_opener'] + 1 ),
($tokens[$i]['scope_closer'] - 1 ),
if ($result['symbol'] !== null ) {
if ($firstSymbol === null ) {
$firstSymbol = $result['symbol'];
if ($result['effect'] !== null ) {
$firstEffect = $result['effect'];
if ($firstEffect === null ) {
$firstEffect = $result['effect'];
$i = $tokens[$i]['scope_closer'];
if ($firstEffect === null ) {
if ($firstSymbol !== null ) {
// We have a conflict we have to report, so no point continuing.
'symbol' => $firstSymbol,
'effect' => $firstEffect,
}//end searchForConflict()
Documentation generated on Mon, 11 Mar 2019 15:27:46 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.
|