Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add rule for PHP's @ operator #496

Merged
merged 8 commits into from
Apr 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
50 changes: 50 additions & 0 deletions src/main/php/PHPMD/Rule/CleanCode/ErrorControlOperator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php
/**
* This file is part of PHP Mess Detector.
*
* Copyright (c) Manuel Pichler <mapi@phpmd.org>.
* All rights reserved.
*
* Licensed under BSD License
* For full copyright and license information, please see the LICENSE file.
* Redistributions of files must retain the above copyright notice.
*
* @author Manuel Pichler <mapi@phpmd.org>
* @copyright Manuel Pichler. All rights reserved.
* @license https://opensource.org/licenses/bsd-license.php BSD License
* @link http://phpmd.org/
*/

namespace PHPMD\Rule\CleanCode;

use PHPMD\AbstractNode;
use PHPMD\AbstractRule;
use PHPMD\Rule\ClassAware;
use PHPMD\Rule\FunctionAware;
use PHPMD\Rule\MethodAware;

/**
* Error Control Operators Rule
*
* This rule detects usage of error control operator (@).
*
* @author Kamil Szymanaski <kamil.szymanski@gmail.com>
* @link http://php.net/manual/en/language.operators.errorcontrol.php
*/
class ErrorControlOperator extends AbstractRule implements MethodAware, FunctionAware
{
/**
* Loops trough all class or function nodes and looks for '@' sign.
ravage84 marked this conversation as resolved.
Show resolved Hide resolved
*
* @param AbstractNode $node
* @return void
*/
public function apply(AbstractNode $node)
{
foreach ($node->findChildrenOfType('UnaryExpression') as $unaryExpression) {
if ($unaryExpression->getImage() === '@') {
$this->addViolation($node, array($unaryExpression->getBeginLine()));
}
}
}
}
22 changes: 22 additions & 0 deletions src/main/resources/rulesets/cleancode.xml
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,28 @@ function createArray() {
</example>
</rule>

<rule name="ErrorControlOperator"
message="Remove error control operator '@' on line {0}."
class="PHPMD\Rule\CleanCode\ErrorControlOperator"
externalInfoUrl="http://phpmd.org/rules/cleancode.html#errorcontroloperator">
<description>
<![CDATA[
Error suppression should be avoided if possible as it doesn't just suppress the error, that
you are trying to stop, but will also suppress errors that you didn't predict would ever occur.
Consider changing error_reporting() level and/or setting up your own error handler.
]]>
</description>
<priority>1</priority>
<example>
<![CDATA[
function foo($filePath) {
ravage84 marked this conversation as resolved.
Show resolved Hide resolved
$file = @fopen($filPath); // hides exceptions
$key = @$array[$notExistingKey]; // assigns null to $key
}
]]>
</example>
</rule>

<rule name="MissingImport"
since="2.7.0"
message="Missing class import via use statement (line '{0}', column '{1}')."
Expand Down
16 changes: 15 additions & 1 deletion src/site/rst/rules/cleancode.rst
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,20 @@ Example: ::
];
}

ErrorControlOperator
====================

Since: PHPMD 2.9.0

Error suppression should be avoided if possible as it doesn't just suppress the error, that you are trying to stop, but will also suppress errors that you didn't predict would ever occur. Moreover it can slow down the execution of your code. Consider changing error_reporting() level and/or setting up your own error handler.

Example: ::

function foo($filePath) {
$file = @fopen($filPath); // hides exceptions
$key = @$array[$notExistingKey]; // assigns null to $key
}

MissingImport
=============

Expand Down Expand Up @@ -138,4 +152,4 @@ Remark
This document is based on a ruleset xml-file, that was taken from the original source of the `PMD`__ project. This means that most parts of the content on this page are the intellectual work of the PMD community and its contributors and not of the PHPMD project.

__ http://pmd.sourceforge.net/

1 change: 1 addition & 0 deletions src/site/rst/rules/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Clean Code Rules
- `DuplicateArrayKey <cleancode.html#duplicatearraykey>`_: Defining another value for the same key in an array literal overrides the previous key/value, which makes it effectively an unused code. If it's known from the beginning that the key will have different value, there is usually no point in defining first one.
- `MissingImport <cleancode.html#missingimport>`_: Importing all external classes in a file through use statements makes them clearly visible.
- `UndefinedVariable <cleancode.html#undefinedvariable>`_: Detects when a variable is used that has not been defined before.
- `ErrorControlOperator <cleancode.html#errorcontroloperator>`_: Error suppression should be avoided if possible as it doesn't just suppress the error, that you are trying to stop, but will also suppress errors that you didn't predict would ever occur. Moreover it can slow down the execution of your code. Consider changing error_reporting() level and/or setting up your own error handler.

Code Size Rules
===============
Expand Down
67 changes: 67 additions & 0 deletions src/test/php/PHPMD/Rule/CleanCode/ErrorControlOperatorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php
/**
* This file is part of PHP Mess Detector.
*
* Copyright (c) Manuel Pichler <mapi@phpmd.org>.
* All rights reserved.
*
* Licensed under BSD License
* For full copyright and license information, please see the LICENSE file.
* Redistributions of files must retain the above copyright notice.
*
* @author Manuel Pichler <mapi@phpmd.org>
* @copyright Manuel Pichler. All rights reserved.
* @license https://opensource.org/licenses/bsd-license.php BSD License
* @link http://phpmd.org/
*/

namespace PHPMD\Rule\CleanCode;

use PHPMD\AbstractTest;

/**
* Error Control Operator Test
*
* @coversDefaultClass \PHPMD\Rule\CleanCode\ErrorControlOperator
*/
class ErrorControlOperatorTest extends AbstractTest
{
/**
* Tests that the rule does not apply to unary operators in functions
*
* @return void
* @covers ::apply
*/
public function testDoesNotApplyToOtherUnaryOperatorsInFunction()
{
$rule = new ErrorControlOperator();
$rule->setReport($this->getReportWithOneViolation());
$rule->apply($this->getFunction());
}

/**
* Tests that the rule applies error control operators to functions
*
* @return void
* @covers ::apply
*/
public function testAppliesToErrorControlOperatorInFunction()
{
$rule = new ErrorControlOperator();
$rule->setReport($this->getReportMock(3));
$rule->apply($this->getFunction());
}

/**
* Tests that the rule applies error control operators to classes and methods
*
* @return void
* @covers ::apply
*/
public function testAppliedToClassesAndMethods()
{
$rule = new ErrorControlOperator();
$rule->setReport($this->getReportMock(6));
$rule->apply($this->getClass());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,15 @@ public function testRuleNotAppliesToMethodWithinNamespaceByDefault()

/**
* Get a configured DevelopmentCodeFragment rule
*
* @return DevelopmentCodeFragment
*/
private function getRule() {
private function getRule()
{
$rule = new DevelopmentCodeFragment();
$rule->addProperty('unwanted-functions', 'var_dump,print_r,debug_zval_dump,debug_print_backtrace');
$rule->addProperty('ignore-namespaces', 'false');

return $rule;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php
/**
* This file is part of PHP Mess Detector.
*
* Copyright (c) Manuel Pichler <mapi@phpmd.org>.
* All rights reserved.
*
* Licensed under BSD License
* For full copyright and license information, please see the LICENSE file.
* Redistributions of files must retain the above copyright notice.
*
* @author Manuel Pichler <mapi@phpmd.org>
* @copyright Manuel Pichler. All rights reserved.
* @license https://opensource.org/licenses/bsd-license.php BSD License
* @link http://phpmd.org/
*/

/**
* Class testAppliedToClassesAndMethods
*/
class testAppliedToClassesAndMethods
{
/**
* @var string
*/
private $baz = 'baz';

/**
* testAppliedToClassesAndMethods
*/
public function testAppliedToClassesAndMethods()
{
$foo = @$this->fooBar();
++$foo;
@!$baz = 1 / 0;
if (@is_readable(__FILE__)) {
$bar = new DateTime('now');
@$baz = $bar;
}
$this->baz = !$foo;
}

/**
* fooBar
*
* @return int
*/
private function fooBar()
{
@$foo = $this->baz / 0;
@$baz = !$foo;

return 2;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php
/**
* This file is part of PHP Mess Detector.
*
* Copyright (c) Manuel Pichler <mapi@phpmd.org>.
* All rights reserved.
*
* Licensed under BSD License
* For full copyright and license information, please see the LICENSE file.
* Redistributions of files must retain the above copyright notice.
*
* @author Manuel Pichler <mapi@phpmd.org>
* @copyright Manuel Pichler. All rights reserved.
* @license https://opensource.org/licenses/bsd-license.php BSD License
* @link http://phpmd.org/
*/

/**
* testAppliesToErrorControlOperatorInFunction
*
* @return array
*/
function testAppliesToErrorControlOperatorInFunction()
{
$foo = @debug_backtrace();
$bar = @is_dir(__FILE__);
@$average = 3 / 0;

return [$foo, $bar, $average];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php
/**
* This file is part of PHP Mess Detector.
*
* Copyright (c) Manuel Pichler <mapi@phpmd.org>.
* All rights reserved.
*
* Licensed under BSD License
* For full copyright and license information, please see the LICENSE file.
* Redistributions of files must retain the above copyright notice.
*
* @author Manuel Pichler <mapi@phpmd.org>
* @copyright Manuel Pichler. All rights reserved.
* @license https://opensource.org/licenses/bsd-license.php BSD License
* @link http://phpmd.org/
*/

/**
* testDoesNotApplyToOtherUnaryOperatorsInFunction
*
* @return bool
*/
function testDoesNotApplyToOtherUnaryOperatorsInFunction()
{
@$foo = is_dir(__DIR__);
$bar = !$foo;
++$bar;
$baz = ++$bar;

return !--$baz;
}