This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace vdmg\App\scripts\githooks\StandardVdmg\PHPStan; | |
use PhpParser\Node; | |
use PHPStan\Analyser\Scope; | |
use PHPStan\Rules\Rule; | |
final class VdmgNoDuplicateNegativIfConditionRule implements Rule { | |
public function getNodeType(): string { | |
return \PhpParser\Node\Stmt::class; | |
} | |
/** | |
* @param \PhpParser\Node\Stmt $node | |
* | |
* @return string[] errors | |
*/ | |
public function processNode(Node $node, Scope $scope): array { | |
if ( | |
!($node instanceof \PhpParser\Node\Stmt\If_) | |
&& | |
!($node instanceof \PhpParser\Node\Stmt\ElseIf_) | |
) { | |
return []; | |
} | |
// init | |
$errors = []; | |
$cond = $node->cond; | |
if (!property_exists($cond, 'left')) { | |
return []; | |
} | |
if (!property_exists($cond, 'right')) { | |
return []; | |
} | |
$condType = $scope->getType($cond); | |
if ($condType instanceof \PHPStan\Type\MixedType) { | |
return []; | |
} | |
$leftType = $scope->getType($cond->left); | |
$rightType = $scope->getType($cond->right); | |
// DEBUG | |
//var_dump(get_class($cond)); | |
if ( | |
$cond instanceof \PhpParser\Node\Expr\BinaryOp\BooleanOr | |
|| | |
$cond instanceof \PhpParser\Node\Expr\BinaryOp\BooleanAnd | |
) { | |
// TODO: check also multiple conditions | |
} | |
if ($cond instanceof \PhpParser\Node\Expr\BinaryOp\NotEqual) { | |
// DEBUG | |
//var_dump(get_class($leftType)); | |
if ( | |
$rightType instanceof \PHPStan\Type\Constant\ConstantStringType | |
&& | |
$rightType->getValue() === '' | |
&& | |
( | |
$leftType instanceof \PHPStan\Type\StringType | |
|| | |
( | |
$leftType instanceof \PHPStan\Type\UnionType | |
&& | |
$leftType->getTypes()[0] instanceof \PHPStan\Type\StringType | |
&& | |
$leftType->getTypes()[1] instanceof \PHPStan\Type\NullType | |
) | |
) | |
) { | |
$errors[] = \PHPStan\Rules\RuleErrorBuilder::message( | |
'Please do not use duplicate negativ string conditions.' | |
)->line($cond->getAttribute('startLine'))->build(); | |
} | |
if ( | |
$rightType instanceof \PHPStan\Type\Constant\ConstantIntegerType | |
&& | |
$rightType->getValue() === 0 | |
&& | |
( | |
$leftType instanceof \PHPStan\Type\IntegerType | |
|| | |
( | |
$leftType instanceof \PHPStan\Type\UnionType | |
&& | |
$leftType->getTypes()[0] instanceof \PHPStan\Type\IntegerType | |
&& | |
$leftType->getTypes()[1] instanceof \PHPStan\Type\NullType | |
) | |
) | |
) { | |
$errors[] = \PHPStan\Rules\RuleErrorBuilder::message( | |
'Please do not use duplicate negativ integer conditions. Use "!==" instead if needed.' | |
)->line($cond->getAttribute('startLine'))->build(); | |
} | |
if ( | |
$rightType instanceof \PHPStan\Type\Constant\ConstantBooleanType | |
&& | |
$rightType->getValue() === false | |
&& | |
( | |
$leftType instanceof \PHPStan\Type\BooleanType | |
|| | |
( | |
$leftType instanceof \PHPStan\Type\UnionType | |
&& | |
$leftType->getTypes()[0] instanceof \PHPStan\Type\BooleanType | |
&& | |
$leftType->getTypes()[1] instanceof \PHPStan\Type\NullType | |
) | |
) | |
) { | |
$errors[] = \PHPStan\Rules\RuleErrorBuilder::message( | |
'Please do not use duplicate negativ boolean conditions.' | |
)->line($cond->getAttribute('startLine'))->build(); | |
} | |
if ( | |
$rightType instanceof \PHPStan\Type\ConstantScalarType | |
&& | |
$rightType->getValue() === null | |
&& | |
( | |
$leftType instanceof \PHPStan\Type\IntegerType | |
|| | |
$leftType instanceof \PHPStan\Type\StringType | |
|| | |
( | |
$leftType instanceof \PHPStan\Type\UnionType | |
&& | |
$leftType->getTypes()[0] instanceof \PHPStan\Type\IntegerType | |
&& | |
$leftType->getTypes()[1] instanceof \PHPStan\Type\NullType | |
) | |
|| | |
( | |
$leftType instanceof \PHPStan\Type\UnionType | |
&& | |
$leftType->getTypes()[0] instanceof \PHPStan\Type\StringType | |
&& | |
$leftType->getTypes()[1] instanceof \PHPStan\Type\NullType | |
) | |
) | |
) { | |
$errors[] = \PHPStan\Rules\RuleErrorBuilder::message( | |
'Please do not use duplicate negativ null conditions. Use "!==" instead if needed.' | |
)->line($cond->getAttribute('startLine'))->build(); | |
} | |
} | |
if ($cond instanceof \PhpParser\Node\Expr\BinaryOp\NotIdentical) { | |
if ( | |
$rightType instanceof \PHPStan\Type\Constant\ConstantStringType | |
&& | |
$rightType->getValue() === '' | |
&& | |
$leftType instanceof \PHPStan\Type\StringType | |
) { | |
$errors[] = \PHPStan\Rules\RuleErrorBuilder::message( | |
'Please do not use duplicate negativ string conditions.' | |
)->line($cond->getAttribute('startLine'))->build(); | |
} | |
if ( | |
$rightType instanceof \PHPStan\Type\Constant\ConstantBooleanType | |
&& | |
$rightType->getValue() === false | |
&& | |
$leftType instanceof \PHPStan\Type\BooleanType | |
) { | |
$errors[] = \PHPStan\Rules\RuleErrorBuilder::message( | |
'Please do not use duplicate negativ boolean conditions.' | |
)->line($cond->getAttribute('startLine'))->build(); | |
} | |
} | |
return $errors; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment