Skip to content

Commit

Permalink
Disallow assignments in if, elseif and do-while conditions
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Feb 5, 2016
1 parent 8321a69 commit f16591d
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

namespace SlevomatCodingStandard\Sniffs\ControlStructures;

class AssignmentInConditionSniff implements \PHP_CodeSniffer_Sniff
{

const CODE_ASSIGNMENT_IN_CONDITION = 'assignmentInCondition';

/**
* @return integer[]
*/
public function register()
{
return [
T_IF,
T_ELSEIF,
T_DO,
];
}

/**
* @param \PHP_CodeSniffer_File $phpcsFile
* @param integer $conditionStartPointer
*/
public function process(\PHP_CodeSniffer_File $phpcsFile, $conditionStartPointer)
{
$tokens = $phpcsFile->getTokens();
$token = $tokens[$conditionStartPointer];
if ($token['code'] === T_DO) {
$whilePointer = $phpcsFile->findNext(T_WHILE, $token['scope_closer'] + 1);
$whileToken = $tokens[$whilePointer];
$parenthesisOpener = $whileToken['parenthesis_opener'];
$parenthesisCloser = $whileToken['parenthesis_closer'];
$type = 'do-while';
} else {
$parenthesisOpener = $token['parenthesis_opener'];
$parenthesisCloser = $token['parenthesis_closer'];
$type = $token['code'] === T_IF ? 'if' : 'elseif';
}
$this->processCondition($phpcsFile, $parenthesisOpener, $parenthesisCloser, $type);
}

/**
* @param \PHP_CodeSniffer_File $phpcsFile
* @param integer $parenthesisOpener
* @param integer $parenthesisCloser
* @param string $conditionType
*/
private function processCondition(
\PHP_CodeSniffer_File $phpcsFile,
$parenthesisOpener,
$parenthesisCloser,
$conditionType
)
{
$equalsTokenPointer = $phpcsFile->findNext(T_EQUAL, $parenthesisOpener + 1, $parenthesisCloser);
if ($equalsTokenPointer !== false) {
$phpcsFile->addError(
sprintf('Assignment in %s condition is not allowed', $conditionType),
$equalsTokenPointer,
self::CODE_ASSIGNMENT_IN_CONDITION
);
}
}

}
34 changes: 34 additions & 0 deletions tests/Sniffs/ControlStructures/AssignmentInConditionSniffTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace SlevomatCodingStandard\Sniffs\ControlStructures;

class AssignmentInConditionSniffTest extends \SlevomatCodingStandard\Sniffs\TestCase
{

public function testCorrectFile()
{
$resultFile = $this->checkFile(__DIR__ . '/data/noAssignmentsInConditions.php');
$this->assertNoSniffErrorInFile($resultFile);
}

public function dataIncorrectFile()
{
$lineNumbers = [];
foreach (range(3, 6) as $lineNumber) {
$lineNumbers[$lineNumber] = [$lineNumber];
}

return $lineNumbers;
}

/**
* @dataProvider dataIncorrectFile
* @param integer $lineNumber
*/
public function testIncorrectFile($lineNumber)
{
$resultFile = $this->checkFile(__DIR__ . '/data/allAssignmentsInConditions.php');
$this->assertSniffError($resultFile, $lineNumber, AssignmentInConditionSniff::CODE_ASSIGNMENT_IN_CONDITION);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php

if ($foo = 5) { }
if ($foo) {} elseif ($foo = 5) {}
do { } while ($foo = 5);
if (($line = fgets($fp)) !== null) { }
45 changes: 45 additions & 0 deletions tests/Sniffs/ControlStructures/data/noAssignmentsInConditions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

if ($foo == 5) {

} elseif ($foo == 10) {

}

if ($foo === 5) {

} elseif ($foo === 10) {

}

if ($foo != 5) {

} elseif ($foo != 10) {

}

if ($foo !== 5) {

} elseif ($foo !== 10) {

}

while ($foo == 5) {

}

while ($foo === 5) {

}

while ($foo = 5) {

}

while (($row = $db->fetch()) !== null) {

}

do {

} while ($foo === 5);

0 comments on commit f16591d

Please sign in to comment.