Skip to content

Commit e338998

Browse files
authored
Merge pull request #11 from unleashedtech/forbidden-classes
New Sniff: Forbidden classes
2 parents 771bd99 + 55e6f6b commit e338998

10 files changed

+161
-9
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ with some noticeable exceptions/differences/extensions based on best-practices a
2727
- Use Null Coalesce Operator ``$foo = $bar ?? $baz``
2828
- Prefer early exit over nesting conditions or using else
2929
- Always use fully-qualified global functions (without needing `use function` statements)
30+
- Forbids the use of `\DateTime`
3031

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

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
],
1414
"extra": {
1515
"branch-alias": {
16-
"dev-master": "2.0.x-dev"
16+
"dev-master": "3.0.x-dev"
1717
}
1818
},
1919
"support" : {
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Unleashed\Sniffs\PHP;
6+
7+
use PHP_CodeSniffer\Files\File;
8+
use PHP_CodeSniffer\Sniffs\Sniff;
9+
use SlevomatCodingStandard\Helpers\NamespaceHelper;
10+
use SlevomatCodingStandard\Helpers\ReferencedNameHelper;
11+
use SlevomatCodingStandard\Helpers\TokenHelper;
12+
13+
final class ForbiddenClassesSniff implements Sniff
14+
{
15+
public const FORBIDDEN = 'Forbidden';
16+
17+
/**
18+
* A list of fully-qualified class, interface, or trait names
19+
*
20+
* @var string[]
21+
*/
22+
public $forbiddenClasses = [
23+
// phpcs:disable Unleashed.PHP.ForbiddenClasses.Forbidden
24+
\DateTime::class,
25+
// phpcs:enable
26+
];
27+
28+
/**
29+
* If true, an error will be thrown; otherwise a warning
30+
*
31+
* @var bool
32+
*/
33+
public $error = true;
34+
35+
/**
36+
* Returns an array of tokens this test wants to listen for.
37+
*
38+
* @inheritDoc
39+
*/
40+
public function register(): array
41+
{
42+
return [\T_OPEN_TAG];
43+
}
44+
45+
/**
46+
* @inheritDoc
47+
*/
48+
public function process(File $phpcsFile, $stackPtr)
49+
{
50+
if (TokenHelper::findPrevious($phpcsFile, T_OPEN_TAG, $stackPtr - 1) !== null) {
51+
return;
52+
}
53+
54+
$referencedNames = ReferencedNameHelper::getAllReferencedNames($phpcsFile, $stackPtr);
55+
56+
foreach ($referencedNames as $referencedName) {
57+
$pointer = $referencedName->getStartPointer();
58+
$name = $referencedName->getNameAsReferencedInFile();
59+
60+
$fullyQualifiedName = NamespaceHelper::resolveClassName($phpcsFile, $name, $pointer);
61+
62+
if (! \in_array($fullyQualifiedName, $this->forbiddenClasses, true)) {
63+
continue;
64+
}
65+
66+
$error = \sprintf('The use of "%s" is forbidden', $fullyQualifiedName);
67+
if ($this->error) {
68+
$phpcsFile->addError($error, $pointer, self::FORBIDDEN);
69+
} else {
70+
$phpcsFile->addWarning($error, $pointer, self::FORBIDDEN);
71+
}
72+
}
73+
}
74+
}

src/Unleashed/ruleset.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,13 @@
106106
</property>
107107
</properties>
108108
</rule>
109+
<rule ref="Unleashed.PHP.ForbiddenClasses">
110+
<properties>
111+
<property name="forbiddenClasses" type="array">
112+
<element value="\DateTime"/>
113+
</property>
114+
</properties>
115+
</rule>
109116
<!-- Forbid useless inline string concatenation -->
110117
<rule ref="Generic.Strings.UnnecessaryStringConcat">
111118
<!-- But multiline is useful for readability -->

tests/expected_report.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ tests/input/EarlyReturn.php 6 0
1818
tests/input/example-class.php 38 0
1919
tests/input/forbidden-comments.php 14 0
2020
tests/input/forbidden-functions.php 13 0
21+
tests/input/ForbiddenClasses.php 7 0
2122
tests/input/fully-qualified-and-fallbacks.php 1 0
2223
tests/input/fully-qualified-without-namespace.php 3 0
2324
tests/input/inline_type_hint_assertions.php 7 0
@@ -47,7 +48,7 @@ tests/input/use-ordering.php 9 0
4748
tests/input/useless-semicolon.php 2 0
4849
tests/input/UselessConditions.php 23 0
4950
----------------------------------------------------------------------
50-
A TOTAL OF 411 ERRORS AND 8 WARNINGS WERE FOUND IN 43 FILES
51+
A TOTAL OF 418 ERRORS AND 8 WARNINGS WERE FOUND IN 44 FILES
5152
----------------------------------------------------------------------
5253
PHPCBF CAN FIX 334 OF THESE SNIFF VIOLATIONS AUTOMATICALLY
5354
----------------------------------------------------------------------

tests/fixed/ForbiddenClasses.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Test;
6+
7+
use DateTime as Date;
8+
9+
class ForbiddenClasses extends Date implements Date
10+
{
11+
use Date;
12+
13+
public function foo(): void
14+
{
15+
$x = new Date();
16+
$y = new \DateTime();
17+
18+
if ($x instanceof Date) {
19+
echo Date::ISO8601;
20+
}
21+
}
22+
}

tests/fixed/duplicate-assignment-variable.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44

55
$foo = $bar = new stdClass();
66

7-
$baz = $baz = new DateTime();
7+
$baz = $baz = new DateTimeImmutable();

tests/input/ForbiddenClasses.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Test;
6+
7+
use DateTime as Date;
8+
9+
class ForbiddenClasses extends Date implements Date
10+
{
11+
use Date;
12+
13+
public function foo(): void
14+
{
15+
$x = new Date();
16+
$y = new \DateTime();
17+
18+
if ($x instanceof Date) {
19+
echo Date::ISO8601;
20+
}
21+
}
22+
}

tests/input/duplicate-assignment-variable.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44

55
$foo = $bar = new stdClass();
66

7-
$baz = $baz = new DateTime();
7+
$baz = $baz = new DateTimeImmutable();

tests/php-compatibility.patch

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,33 @@ index 71be9a5..f9492c7 100644
4242
// @see https://github.com/php/php-src/blob/PHP-7.4/Zend/zend_compile.c "zend_try_compile_special_func"
4343
'array_key_exists' => true,
4444
'array_slice' => true,
45+
diff --git a/src/Unleashed/Sniffs/PHP/ForbiddenClassesSniff.php b/src/Unleashed/Sniffs/PHP/ForbiddenClassesSniff.php
46+
index 80a42a6..dd2fcb7 100644
47+
--- a/src/Unleashed/Sniffs/PHP/ForbiddenClassesSniff.php
48+
+++ b/src/Unleashed/Sniffs/PHP/ForbiddenClassesSniff.php
49+
@@ -19,7 +19,7 @@ final class ForbiddenClassesSniff implements Sniff
50+
*
51+
* @var string[]
52+
*/
53+
- public $forbiddenClasses = [
54+
+ public array $forbiddenClasses = [
55+
// phpcs:disable Unleashed.PHP.ForbiddenClasses.Forbidden
56+
\DateTime::class,
57+
// phpcs:enable
58+
@@ -27,10 +27,8 @@ final class ForbiddenClassesSniff implements Sniff
59+
60+
/**
61+
* If true, an error will be thrown; otherwise a warning
62+
- *
63+
- * @var bool
64+
*/
65+
- public $error = true;
66+
+ public bool $error = true;
67+
68+
/**
69+
* Returns an array of tokens this test wants to listen for.
4570
diff --git a/tests/expected_report.txt b/tests/expected_report.txt
46-
index c07423b..9b0ebf0 100644
71+
index cc0cd5a..c3ebeb0 100644
4772
--- a/tests/expected_report.txt
4873
+++ b/tests/expected_report.txt
4974
@@ -11,11 +11,11 @@ tests/input/concatenation_spacing.php 49 0
@@ -59,8 +84,8 @@ index c07423b..9b0ebf0 100644
5984
+tests/input/example-class.php 41 0
6085
tests/input/forbidden-comments.php 14 0
6186
tests/input/forbidden-functions.php 13 0
62-
tests/input/fully-qualified-and-fallbacks.php 1 0
63-
@@ -40,16 +40,16 @@ tests/input/strict-functions.php 4 0
87+
tests/input/ForbiddenClasses.php 7 0
88+
@@ -41,16 +41,16 @@ tests/input/strict-functions.php 4 0
6489
tests/input/test-case.php 7 0
6590
tests/input/trailing_comma_on_array.php 1 0
6691
tests/input/traits-uses.php 12 0
@@ -72,8 +97,8 @@ index c07423b..9b0ebf0 100644
7297
tests/input/useless-semicolon.php 2 0
7398
tests/input/UselessConditions.php 23 0
7499
----------------------------------------------------------------------
75-
-A TOTAL OF 411 ERRORS AND 8 WARNINGS WERE FOUND IN 43 FILES
76-
+A TOTAL OF 416 ERRORS AND 8 WARNINGS WERE FOUND IN 43 FILES
100+
-A TOTAL OF 418 ERRORS AND 8 WARNINGS WERE FOUND IN 44 FILES
101+
+A TOTAL OF 423 ERRORS AND 8 WARNINGS WERE FOUND IN 44 FILES
77102
----------------------------------------------------------------------
78103
-PHPCBF CAN FIX 334 OF THESE SNIFF VIOLATIONS AUTOMATICALLY
79104
+PHPCBF CAN FIX 339 OF THESE SNIFF VIOLATIONS AUTOMATICALLY

0 commit comments

Comments
 (0)