Source for file MultipleStatementAlignmentSniff.php
Documentation is available at MultipleStatementAlignmentSniff.php
* Checks alignment of assignments.
* If there are multiple adjacent assignments, it will check that the equals signs of
* each assignment are aligned. It will display a warning to advise that the signs should be aligned.
* @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\Generic\Sniffs\Formatting;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Util\Tokens;
class MultipleStatementAlignmentSniff implements Sniff
* A list of tokenizers this sniff supports.
public $supportedTokenizers = array (
* If true, an error will be thrown; otherwise a warning.
* The maximum amount of padding before the alignment is ignored.
* If the amount of padding required to align this assignment with the
* surrounding assignments exceeds this number, the assignment will be
* ignored and no errors or warnings will be thrown.
public $maxPadding = 1000;
* Returns an array of tokens this test wants to listen for.
public function register ()
$tokens = Tokens ::$assignmentTokens;
unset ($tokens[T_DOUBLE_ARROW ]);
* Processes this test, 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 ();
// Ignore assignments used in a condition, like an IF or FOR.
if (isset ($tokens[$stackPtr]['nested_parenthesis']) === true ) {
foreach ($tokens[$stackPtr]['nested_parenthesis'] as $start => $end) {
if (isset ($tokens[$start]['parenthesis_owner']) === true ) {
$lastAssign = $this->checkAlignment ($phpcsFile, $stackPtr);
return ($lastAssign + 1 );
* Processes this test, 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 checkAlignment ($phpcsFile, $stackPtr)
$tokens = $phpcsFile->getTokens ();
$lastLine = $tokens[$stackPtr]['line'];
$find = Tokens ::$assignmentTokens;
unset ($find[T_DOUBLE_ARROW ]);
for ($assign = $stackPtr; $assign < $phpcsFile->numTokens; $assign++ ) {
if (isset ($find[$tokens[$assign]['code']]) === false ) {
// A blank line indicates that the assignment block has ended.
if (isset (Tokens ::$emptyTokens[$tokens[$assign]['code']]) === false ) {
if (($tokens[$assign]['line'] - $tokens[$lastCode]['line']) > 1 ) {
if ($tokens[$assign]['conditions'] === $tokens[$stackPtr]['conditions']) {
if ($lastSemi !== null && $prevAssign !== null && $lastSemi > $prevAssign) {
// This statement did not have an assignment operator in it.
// Statement is in a different context, so the block is over.
} else if ($assign !== $stackPtr && $tokens[$assign]['line'] === $lastLine) {
// Skip multiple assignments on the same line. We only need to
// try and align the first assignment.
if ($assign !== $stackPtr) {
// Has to be nested inside the same conditions as the first assignment.
if ($tokens[$assign]['conditions'] !== $tokens[$stackPtr]['conditions']) {
// Make sure it is not assigned inside a condition (eg. IF, FOR).
if (isset ($tokens[$assign]['nested_parenthesis']) === true ) {
foreach ($tokens[$assign]['nested_parenthesis'] as $start => $end) {
if (isset ($tokens[$start]['parenthesis_owner']) === true ) {
$var = $phpcsFile->findPrevious (
// Make sure we wouldn't break our max padding length if we
// aligned with this statement, or they wouldn't break the max
// padding length if they aligned with us.
$varEnd = $tokens[($var + 1 )]['column'];
$assignLen = $tokens[$assign]['length'];
if ($assign !== $stackPtr) {
if (($varEnd + 1 ) > $assignments[$prevAssign]['assign_col']) {
$assignColumn = ($varEnd + 1 );
$padding = ($assignments[$prevAssign]['assign_col'] - $varEnd + $assignments[$prevAssign]['assign_len'] - $assignLen);
if ($padding > $this->maxPadding) {
$assignColumn = ($varEnd + $padding);
if (($assignColumn + $assignLen) > ($assignments[$maxPadding]['assign_col'] + $assignments[$maxPadding]['assign_len'])) {
$newPadding = ($varEnd - $assignments[$maxPadding]['var_end'] + $assignLen - $assignments[$maxPadding]['assign_len'] + 1 );
if ($newPadding > $this->maxPadding) {
// New alignment settings for previous assignments.
foreach ($assignments as $i => $data) {
$newPadding = ($varEnd - $data['var_end'] + $assignLen - $data['assign_len'] + 1 );
$assignments[$i]['expected'] = $newPadding;
$assignments[$i]['assign_col'] = ($data['var_end'] + $newPadding);
$assignColumn = ($varEnd + 1 );
} else if ($padding > $assignments[$maxPadding]['expected']) {
$assignColumn = ($varEnd + 1 );
if ($tokens[($var + 1 )]['code'] === T_WHITESPACE ) {
$found = $tokens[($var + 1 )]['length'];
// This means a newline was found.
$assignments[$assign] = array (
'assign_len' => $assignLen,
'assign_col' => $assignColumn,
$lastLine = $tokens[$assign]['line'];
if (empty ($assignments) === true ) {
$numAssignments = count($assignments);
foreach ($assignments as $assignment => $data) {
if ($data['found'] === $data['expected']) {
$expectedText = $data['expected']. ' space';
if ($data['expected'] !== 1 ) {
if ($data['found'] === null ) {
$foundText = 'a new line';
$foundText = $data['found']. ' space';
if ($data['found'] !== 1 ) {
if ($numAssignments === 1 ) {
$error = 'Equals sign not aligned correctly; expected %s but found %s';
$error = 'Equals sign not aligned with surrounding assignments; expected %s but found %s';
if ($this->error === true ) {
$fix = $phpcsFile->addFixableError ($error, $assignment, $type, $errorData);
$fix = $phpcsFile->addFixableWarning ($error, $assignment, $type. 'Warning', $errorData);
if ($fix === true && $data['found'] !== null ) {
if ($data['found'] === 0 ) {
$phpcsFile->fixer ->addContentBefore ($assignment, $newContent);
$phpcsFile->fixer ->replaceToken (($assignment - 1 ), $newContent);
if ($numAssignments > 1 ) {
if ($errorGenerated === true ) {
$phpcsFile->recordMetric ($stackPtr, 'Adjacent assignments aligned', 'no');
$phpcsFile->recordMetric ($stackPtr, 'Adjacent assignments aligned', 'yes');
return $this->checkAlignment ($phpcsFile, $stopped);
Documentation generated on Mon, 11 Mar 2019 15:27:38 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.
|