Skip to content

Commit

Permalink
Implement DisallowedErrorSuppressionOperatorRule
Browse files Browse the repository at this point in the history
  • Loading branch information
paulbalandan committed Dec 14, 2024
1 parent 53a71ac commit 021857f
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

declare(strict_types=1);

/**
* This file is part of the Nexus framework.
*
* (c) John Paul E. Balandan, CPA <paulbalandan@gmail.com>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

namespace Nexus\PHPStan\Rules\CleanCode;

use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;
use PHPStan\Type\Constant\ConstantIntegerType;

/**
* @implements Rule<Node\Expr\ErrorSuppress>
*/
final class DisallowedErrorSuppressionOperatorRule implements Rule
{
public function getNodeType(): string
{
return Node\Expr\ErrorSuppress::class;
}

/**
* @param Node\Expr\ErrorSuppress $node
*/
public function processNode(Node $node, Scope $scope): array
{
if (
$node->expr instanceof Node\Expr\FuncCall
&& $node->expr->name instanceof Node\Name
&& 'trigger_error' === $node->expr->name->name
) {
$arguments = $node->expr->getArgs();

if (\count($arguments) > 1) {
$errorType = $scope->getType($arguments[1]->value);

if ($errorType instanceof ConstantIntegerType) {
$errorLevel = $errorType->getValue();

if (E_USER_DEPRECATED === $errorLevel) {
return [];
}
}
}
}

return [
RuleErrorBuilder::message('Use of the error control operator to suppress errors is not allowed.')
->identifier('nexus.errorSuppress')
->addTip('If you need to get the result and error message, use `Silencer::box()` instead.')
->addTip('If you need only the result, use `Silencer::suppress()` instead.')
->build(),
];
}
}
1 change: 1 addition & 0 deletions src/Nexus/PHPStan/extension.neon
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
rules:
- Nexus\PHPStan\Rules\CleanCode\AssignExprInCondRule
- Nexus\PHPStan\Rules\CleanCode\DisallowedErrorSuppressionOperatorRule
- Nexus\PHPStan\Rules\Constants\ClassConstantNamingRule
- Nexus\PHPStan\Rules\Functions\FunctionNamingRule
- Nexus\PHPStan\Rules\Methods\MethodNamingRule
Expand Down
5 changes: 4 additions & 1 deletion tests/AutoReview/ComposerJsonTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

namespace Nexus\Tests\AutoReview;

use Nexus\Suppression\Silencer;
use PHPUnit\Framework\Attributes\CoversNothing;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Group;
Expand Down Expand Up @@ -119,7 +120,9 @@ private function getComposer(string $path): array
));
}

$contents = @file_get_contents($realpath);
$contents = (new Silencer())->suppress(
static fn(): false|string => file_get_contents($realpath),
);

if (false === $contents) {
throw new \InvalidArgumentException(\sprintf(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

declare(strict_types=1);

/**
* This file is part of the Nexus framework.
*
* (c) John Paul E. Balandan, CPA <paulbalandan@gmail.com>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

namespace Nexus\Tests\PHPStan\Rules\CleanCode;

use Nexus\PHPStan\Rules\CleanCode\DisallowedErrorSuppressionOperatorRule;
use PHPStan\Rules\Rule;
use PHPStan\Testing\RuleTestCase;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Group;

/**
* @internal
*
* @extends RuleTestCase<DisallowedErrorSuppressionOperatorRule>
*/
#[CoversClass(DisallowedErrorSuppressionOperatorRule::class)]
#[Group('unit-test')]
final class DisallowedErrorSuppressionOperatorRuleTest extends RuleTestCase
{
public function testRule(): void
{
$tip = implode("\n", array_map(
static fn(string $tip): string => \sprintf('• %s', $tip),
[
'If you need to get the result and error message, use `Silencer::box()` instead.',
'If you need only the result, use `Silencer::suppress()` instead.',
],
));

$this->analyse([__DIR__.'/data/disallowed-error-suppression-operator.php'], [
[
'Use of the error control operator to suppress errors is not allowed.',
7,
$tip,
],
[
'Use of the error control operator to suppress errors is not allowed.',
10,
$tip,
],
[
'Use of the error control operator to suppress errors is not allowed.',
11,
$tip,
],
[
'Use of the error control operator to suppress errors is not allowed.',
12,
$tip,
],
]);
}

protected function getRule(): Rule
{
return new DisallowedErrorSuppressionOperatorRule();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Nexus\Tests\PHPStan\Rules\CleanCode;

@trigger_error('Test', E_USER_WARNING);
@trigger_error('Test 2', E_USER_DEPRECATED);

$a = @$x;
@mkdir(__DIR__);
@file_get_contents(__FILE__);
12 changes: 11 additions & 1 deletion tools/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,18 @@
"friendsofphp/php-cs-fixer": "^3.60",
"infection/infection": "^0.29.6",
"kubawerlos/php-cs-fixer-custom-fixers": "^3.21",
"nexusphp/cs-config": "^3.24"
"nexusphp/cs-config": "^3.24",
"nexusphp/framework": "1.x-dev"
},
"repositories": [
{
"type": "path",
"url": "../",
"options": {
"symlink": false
}
}
],
"autoload": {
"psr-4": {
"Nexus\\Tools\\": "src"
Expand Down
6 changes: 5 additions & 1 deletion tools/src/ComposerScripts.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

namespace Nexus\Tools;

use Nexus\Suppression\Silencer;

/**
* @internal
*/
Expand Down Expand Up @@ -66,7 +68,9 @@ private static function extractPhpstanPhar(): void

private static function updateVscodeIntelephenseEnvironmentIncludePaths(): void
{
$contents = @file_get_contents(self::VSCODE_SETTINGS_JSON);
$contents = (new Silencer())->suppress(
static fn(): false|string => file_get_contents(self::VSCODE_SETTINGS_JSON),
);

if (false === $contents) {
echo \sprintf("\033[31mFAIL\033[0m Cannot get the contents of %s as it is probably missing or unreadable.\n", self::VSCODE_SETTINGS_JSON);
Expand Down

0 comments on commit 021857f

Please sign in to comment.