Skip to content

Commit

Permalink
Final constant rule
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Aug 17, 2021
1 parent 270326a commit 6be077e
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 0 deletions.
1 change: 1 addition & 0 deletions conf/config.level0.neon
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ rules:
- PHPStan\Rules\Classes\NewStaticRule
- PHPStan\Rules\Classes\NonClassAttributeClassRule
- PHPStan\Rules\Classes\TraitAttributeClassRule
- PHPStan\Rules\Constants\FinalConstantRule
- PHPStan\Rules\Exceptions\ThrowExpressionRule
- PHPStan\Rules\Functions\ArrowFunctionAttributesRule
- PHPStan\Rules\Functions\ArrowFunctionReturnNullsafeByRefRule
Expand Down
5 changes: 5 additions & 0 deletions src/Php/PhpVersion.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,9 @@ public function isInterfaceConstantImplicitlyFinal(): bool
return $this->versionId < 80100;
}

public function supportsFinalConstants(): bool
{
return $this->versionId >= 80100;
}

}
43 changes: 43 additions & 0 deletions src/Rules/Constants/FinalConstantRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Constants;

use PhpParser\Node;
use PhpParser\Node\Stmt\ClassConst;
use PHPStan\Analyser\Scope;
use PHPStan\Php\PhpVersion;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;

/** @implements Rule<ClassConst> */
class FinalConstantRule implements Rule
{

private PhpVersion $phpVersion;

public function __construct(PhpVersion $phpVersion)
{
$this->phpVersion = $phpVersion;
}

public function getNodeType(): string
{
return ClassConst::class;
}

public function processNode(Node $node, Scope $scope): array
{
if (!$node->isFinal()) {
return [];
}

if ($this->phpVersion->supportsFinalConstants()) {
return [];
}

return [
RuleErrorBuilder::message('Final class constants are supported only on PHP 8.1 and later.')->nonIgnorable()->build(),
];
}

}
57 changes: 57 additions & 0 deletions tests/PHPStan/Rules/Constants/FinalConstantRuleTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Constants;

use PHPStan\Php\PhpVersion;
use PHPStan\Rules\Rule;
use PHPStan\Testing\RuleTestCase;

/**
* @extends RuleTestCase<FinalConstantRule>
*/
class FinalConstantRuleTest extends RuleTestCase
{

/** @var int */
private $phpVersionId;

protected function getRule(): Rule
{
return new FinalConstantRule(new PhpVersion($this->phpVersionId));
}

public function dataRule(): array
{
return [
[
80000,
[
[
'Final class constants are supported only on PHP 8.1 and later.',
9,
],
],
],
[
80100,
[],
],
];
}

/**
* @dataProvider dataRule
* @param int $phpVersionId
* @param mixed[] $errors
*/
public function testRule(int $phpVersionId, array $errors): void
{
if (!self::$useStaticReflectionProvider) {
$this->markTestSkipped('Test requires static reflection.');
}

$this->phpVersionId = $phpVersionId;
$this->analyse([__DIR__ . '/data/final-constant.php'], $errors);
}

}
11 changes: 11 additions & 0 deletions tests/PHPStan/Rules/Constants/data/final-constant.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace FinalConstant;

class Foo
{

const TEST = 1;
final const BAR = 2;

}

0 comments on commit 6be077e

Please sign in to comment.