Skip to content

New Sniff: Forbidden classes #11

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

Merged
merged 2 commits into from
Mar 5, 2021
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ with some noticeable exceptions/differences/extensions based on best-practices a
- Use Null Coalesce Operator ``$foo = $bar ?? $baz``
- Prefer early exit over nesting conditions or using else
- Always use fully-qualified global functions (without needing `use function` statements)
- Forbids the use of `\DateTime`

For full reference of enforcements, go through ``src/Unleashed/ruleset.xml`` where each sniff is briefly described.

Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
],
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
"dev-master": "3.0.x-dev"
}
},
"support" : {
Expand Down
74 changes: 74 additions & 0 deletions src/Unleashed/Sniffs/PHP/ForbiddenClassesSniff.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php

declare(strict_types=1);

namespace Unleashed\Sniffs\PHP;

use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Sniffs\Sniff;
use SlevomatCodingStandard\Helpers\NamespaceHelper;
use SlevomatCodingStandard\Helpers\ReferencedNameHelper;
use SlevomatCodingStandard\Helpers\TokenHelper;

final class ForbiddenClassesSniff implements Sniff
{
public const FORBIDDEN = 'Forbidden';

/**
* A list of fully-qualified class, interface, or trait names
*
* @var string[]
*/
public $forbiddenClasses = [
// phpcs:disable Unleashed.PHP.ForbiddenClasses.Forbidden
\DateTime::class,
// phpcs:enable
];

/**
* If true, an error will be thrown; otherwise a warning
*
* @var bool
*/
public $error = true;

/**
* Returns an array of tokens this test wants to listen for.
*
* @inheritDoc
*/
public function register(): array
{
return [\T_OPEN_TAG];
}

/**
* @inheritDoc
*/
public function process(File $phpcsFile, $stackPtr)
{
if (TokenHelper::findPrevious($phpcsFile, T_OPEN_TAG, $stackPtr - 1) !== null) {
return;
}

$referencedNames = ReferencedNameHelper::getAllReferencedNames($phpcsFile, $stackPtr);

foreach ($referencedNames as $referencedName) {
$pointer = $referencedName->getStartPointer();
$name = $referencedName->getNameAsReferencedInFile();

$fullyQualifiedName = NamespaceHelper::resolveClassName($phpcsFile, $name, $pointer);

if (! \in_array($fullyQualifiedName, $this->forbiddenClasses, true)) {
continue;
}

$error = \sprintf('The use of "%s" is forbidden', $fullyQualifiedName);
if ($this->error) {
$phpcsFile->addError($error, $pointer, self::FORBIDDEN);
} else {
$phpcsFile->addWarning($error, $pointer, self::FORBIDDEN);
}
}
}
}
7 changes: 7 additions & 0 deletions src/Unleashed/ruleset.xml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,13 @@
</property>
</properties>
</rule>
<rule ref="Unleashed.PHP.ForbiddenClasses">
<properties>
<property name="forbiddenClasses" type="array">
<element value="\DateTime"/>
</property>
</properties>
</rule>
<!-- Forbid useless inline string concatenation -->
<rule ref="Generic.Strings.UnnecessaryStringConcat">
<!-- But multiline is useful for readability -->
Expand Down
3 changes: 2 additions & 1 deletion tests/expected_report.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ tests/input/EarlyReturn.php 6 0
tests/input/example-class.php 38 0
tests/input/forbidden-comments.php 14 0
tests/input/forbidden-functions.php 13 0
tests/input/ForbiddenClasses.php 7 0
tests/input/fully-qualified-and-fallbacks.php 1 0
tests/input/fully-qualified-without-namespace.php 3 0
tests/input/inline_type_hint_assertions.php 7 0
Expand Down Expand Up @@ -47,7 +48,7 @@ tests/input/use-ordering.php 9 0
tests/input/useless-semicolon.php 2 0
tests/input/UselessConditions.php 23 0
----------------------------------------------------------------------
A TOTAL OF 411 ERRORS AND 8 WARNINGS WERE FOUND IN 43 FILES
A TOTAL OF 418 ERRORS AND 8 WARNINGS WERE FOUND IN 44 FILES
----------------------------------------------------------------------
PHPCBF CAN FIX 334 OF THESE SNIFF VIOLATIONS AUTOMATICALLY
----------------------------------------------------------------------
Expand Down
22 changes: 22 additions & 0 deletions tests/fixed/ForbiddenClasses.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace Test;

use DateTime as Date;

class ForbiddenClasses extends Date implements Date
{
use Date;

public function foo(): void
{
$x = new Date();
$y = new \DateTime();

if ($x instanceof Date) {
echo Date::ISO8601;
}
}
}
2 changes: 1 addition & 1 deletion tests/fixed/duplicate-assignment-variable.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@

$foo = $bar = new stdClass();

$baz = $baz = new DateTime();
$baz = $baz = new DateTimeImmutable();
22 changes: 22 additions & 0 deletions tests/input/ForbiddenClasses.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace Test;

use DateTime as Date;

class ForbiddenClasses extends Date implements Date
{
use Date;

public function foo(): void
{
$x = new Date();
$y = new \DateTime();

if ($x instanceof Date) {
echo Date::ISO8601;
}
}
}
2 changes: 1 addition & 1 deletion tests/input/duplicate-assignment-variable.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@

$foo = $bar = new stdClass();

$baz = $baz = new DateTime();
$baz = $baz = new DateTimeImmutable();
35 changes: 30 additions & 5 deletions tests/php-compatibility.patch
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,33 @@ index 71be9a5..f9492c7 100644
// @see https://github.com/php/php-src/blob/PHP-7.4/Zend/zend_compile.c "zend_try_compile_special_func"
'array_key_exists' => true,
'array_slice' => true,
diff --git a/src/Unleashed/Sniffs/PHP/ForbiddenClassesSniff.php b/src/Unleashed/Sniffs/PHP/ForbiddenClassesSniff.php
index 80a42a6..dd2fcb7 100644
--- a/src/Unleashed/Sniffs/PHP/ForbiddenClassesSniff.php
+++ b/src/Unleashed/Sniffs/PHP/ForbiddenClassesSniff.php
@@ -19,7 +19,7 @@ final class ForbiddenClassesSniff implements Sniff
*
* @var string[]
*/
- public $forbiddenClasses = [
+ public array $forbiddenClasses = [
// phpcs:disable Unleashed.PHP.ForbiddenClasses.Forbidden
\DateTime::class,
// phpcs:enable
@@ -27,10 +27,8 @@ final class ForbiddenClassesSniff implements Sniff

/**
* If true, an error will be thrown; otherwise a warning
- *
- * @var bool
*/
- public $error = true;
+ public bool $error = true;

/**
* Returns an array of tokens this test wants to listen for.
diff --git a/tests/expected_report.txt b/tests/expected_report.txt
index c07423b..9b0ebf0 100644
index cc0cd5a..c3ebeb0 100644
--- a/tests/expected_report.txt
+++ b/tests/expected_report.txt
@@ -11,11 +11,11 @@ tests/input/concatenation_spacing.php 49 0
Expand All @@ -59,8 +84,8 @@ index c07423b..9b0ebf0 100644
+tests/input/example-class.php 41 0
tests/input/forbidden-comments.php 14 0
tests/input/forbidden-functions.php 13 0
tests/input/fully-qualified-and-fallbacks.php 1 0
@@ -40,16 +40,16 @@ tests/input/strict-functions.php 4 0
tests/input/ForbiddenClasses.php 7 0
@@ -41,16 +41,16 @@ tests/input/strict-functions.php 4 0
tests/input/test-case.php 7 0
tests/input/trailing_comma_on_array.php 1 0
tests/input/traits-uses.php 12 0
Expand All @@ -72,8 +97,8 @@ index c07423b..9b0ebf0 100644
tests/input/useless-semicolon.php 2 0
tests/input/UselessConditions.php 23 0
----------------------------------------------------------------------
-A TOTAL OF 411 ERRORS AND 8 WARNINGS WERE FOUND IN 43 FILES
+A TOTAL OF 416 ERRORS AND 8 WARNINGS WERE FOUND IN 43 FILES
-A TOTAL OF 418 ERRORS AND 8 WARNINGS WERE FOUND IN 44 FILES
+A TOTAL OF 423 ERRORS AND 8 WARNINGS WERE FOUND IN 44 FILES
----------------------------------------------------------------------
-PHPCBF CAN FIX 334 OF THESE SNIFF VIOLATIONS AUTOMATICALLY
+PHPCBF CAN FIX 339 OF THESE SNIFF VIOLATIONS AUTOMATICALLY
Expand Down