Skip to content

Commit 5115077

Browse files
committed
Adding support for DateTime and DateTimeImmutable
An additional rule is added to detect instantiation of DateTime or DateTimeImmutable (instead of Safe\DateTime or any other subclass)
1 parent 7148201 commit 5115077

File tree

4 files changed

+107
-0
lines changed

4 files changed

+107
-0
lines changed

src/Rules/UseSafeClassesRule.php

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
4+
namespace TheCodingMachine\Safe\PHPStan\Rules;
5+
6+
use PhpParser\Node;
7+
use PHPStan\Analyser\Scope;
8+
use PHPStan\Reflection\FunctionReflection;
9+
use PHPStan\Reflection\MethodReflection;
10+
use PHPStan\Rules\Rule;
11+
use PHPStan\ShouldNotHappenException;
12+
use TheCodingMachine\Safe\PHPStan\Utils\ClassListLoader;
13+
use TheCodingMachine\Safe\PHPStan\Utils\FunctionListLoader;
14+
use PhpParser\Node\Arg;
15+
use PhpParser\Node\Expr;
16+
use PhpParser\Node\Scalar;
17+
18+
/**
19+
* This rule checks that no "unsafe" classes are instantiated in code.
20+
*/
21+
class UseSafeClassesRule implements Rule
22+
{
23+
public function getNodeType(): string
24+
{
25+
return Node\Expr\New_::class;
26+
}
27+
28+
/**
29+
* @param Node\Expr\New_ $node
30+
* @param \PHPStan\Analyser\Scope $scope
31+
* @return string[]
32+
*/
33+
public function processNode(Node $node, Scope $scope): array
34+
{
35+
$classNode = $node->class;
36+
if (!$classNode instanceof Node\Name) {
37+
return [];
38+
}
39+
40+
$className = $classNode->toString();
41+
$unsafeClasses = ClassListLoader::getClassList();
42+
43+
if (isset($unsafeClasses[$className])) {
44+
return ["Class $className is unsafe to use. Its methods can return FALSE instead of throwing an exception. Please add 'use Safe\\$className;' at the beginning of the file to use the variant provided by the 'thecodingmachine/safe' library."];
45+
}
46+
47+
return [];
48+
}
49+
}

src/Utils/ClassListLoader.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
4+
namespace TheCodingMachine\Safe\PHPStan\Utils;
5+
6+
use PHPStan\Analyser\Scope;
7+
use PHPStan\Reflection\FunctionReflection;
8+
use PHPStan\Reflection\MethodReflection;
9+
10+
class ClassListLoader
11+
{
12+
private static $classes = [
13+
'DateTime' => 'DateTime',
14+
'DateTimeImmutable' => 'DateTimeImmutable',
15+
];
16+
17+
/**
18+
* @return string[]
19+
*/
20+
public static function getClassList(): array
21+
{
22+
return self::$classes;
23+
}
24+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
namespace TheCodingMachine\Safe\PHPStan\Rules;
4+
5+
use PHPStan\Testing\RuleTestCase;
6+
use TheCodingMachine\Safe\PHPStan\Type\Php\ReplaceSafeFunctionsDynamicReturnTypeExtension;
7+
8+
class UseSafeClassesRuleTest extends RuleTestCase
9+
{
10+
protected function getRule(): \PHPStan\Rules\Rule
11+
{
12+
return new UseSafeClassesRule();
13+
}
14+
15+
public function testDateTime()
16+
{
17+
$this->analyse([__DIR__ . '/data/datetime.php'], [
18+
[
19+
"Class DateTime is unsafe to use. Its methods can return FALSE instead of throwing an exception. Please add 'use Safe\DateTime;' at the beginning of the file to use the variant provided by the 'thecodingmachine/safe' library.",
20+
3,
21+
],
22+
[
23+
"Class DateTimeImmutable is unsafe to use. Its methods can return FALSE instead of throwing an exception. Please add 'use Safe\DateTimeImmutable;' at the beginning of the file to use the variant provided by the 'thecodingmachine/safe' library.",
24+
4,
25+
],
26+
]);
27+
}
28+
}

tests/Rules/data/datetime.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?php
2+
3+
$date = new DateTime();
4+
$dateImmutable = new DateTimeImmutable();
5+
$safeDate = new Safe\DateTime();
6+
$safeDateImmutable = new Safe\DateTimeImmutable();

0 commit comments

Comments
 (0)