Skip to content

Commit 2459c74

Browse files
committed
Added rule to use proper suffix/prefix
1 parent 38006e3 commit 2459c74

File tree

6 files changed

+176
-0
lines changed

6 files changed

+176
-0
lines changed

extension.neon

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ parameters:
77
- stubs/Money/MoneyParser.stub
88
rules:
99
- Ibexa\PHPStan\Rules\NoConfigResolverParametersInConstructorRule
10+
- Ibexa\PHPStan\Rules\RequireInterfaceInDependenciesRule
11+
- Ibexa\PHPStan\Rules\NamingConventionRule

phpstan-baseline.neon

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
parameters:
2+
ignoreErrors:
3+
-
4+
message: "#^Property Ibexa\\\\Tests\\\\PHPStan\\\\Rules\\\\Fixtures\\\\RequireInterfaceInDependenciesFixture\\:\\:\\$classWithoutInterface is never read, only written\\.$#"
5+
count: 1
6+
path: tests/rules/Fixtures/RequireInterfaceInDependenciesFixture.php
7+
8+
-
9+
message: "#^Property Ibexa\\\\Tests\\\\PHPStan\\\\Rules\\\\Fixtures\\\\RequireInterfaceInDependenciesFixture\\:\\:\\$concreteClass is never read, only written\\.$#"
10+
count: 1
11+
path: tests/rules/Fixtures/RequireInterfaceInDependenciesFixture.php
12+
13+
-
14+
message: "#^Property Ibexa\\\\Tests\\\\PHPStan\\\\Rules\\\\Fixtures\\\\RequireInterfaceInDependenciesFixture\\:\\:\\$testInterface is never read, only written\\.$#"
15+
count: 1
16+
path: tests/rules/Fixtures/RequireInterfaceInDependenciesFixture.php

phpstan.neon

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
includes:
2+
- phpstan-baseline.neon
3+
14
parameters:
25
level: 8
36
paths:

rules/NamingConventionRule.php

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<?php
2+
3+
/**
4+
* @copyright Copyright (C) Ibexa AS. All rights reserved.
5+
* @license For full copyright and license information view LICENSE file distributed with this source code.
6+
*/
7+
declare(strict_types=1);
8+
9+
namespace Ibexa\PHPStan\Rules;
10+
11+
use PhpParser\Node;
12+
use PHPStan\Analyser\Scope;
13+
use PHPStan\Rules\Rule;
14+
use PHPStan\Rules\RuleErrorBuilder;
15+
16+
/**
17+
* @implements \PHPStan\Rules\Rule<\PhpParser\Node\Stmt\ClassLike>
18+
*/
19+
final class NamingConventionRule implements Rule
20+
{
21+
public function getNodeType(): string
22+
{
23+
return Node\Stmt\ClassLike::class;
24+
}
25+
26+
public function processNode(Node $node, Scope $scope): array
27+
{
28+
if (!$this->isRelevantNode($node)) {
29+
return [];
30+
}
31+
32+
if ($node->name === null) {
33+
return [];
34+
}
35+
36+
$className = $node->name->toString();
37+
$errors = [];
38+
39+
if ($node instanceof Node\Stmt\Interface_ && substr($className, -9) !== 'Interface') {
40+
$errors[] = RuleErrorBuilder::message(
41+
sprintf(
42+
'Interface "%s" should have "Interface" suffix',
43+
$className
44+
)
45+
)->build();
46+
}
47+
48+
if ($node instanceof Node\Stmt\Trait_ && substr($className, -5) !== 'Trait') {
49+
$errors[] = RuleErrorBuilder::message(
50+
sprintf(
51+
'Trait "%s" should have "Trait" suffix',
52+
$className
53+
)
54+
)->build();
55+
}
56+
57+
if ($node instanceof Node\Stmt\Class_ && $node->isAbstract() && strpos($className, 'Abstract') !== 0) {
58+
$errors[] = RuleErrorBuilder::message(
59+
sprintf(
60+
'Abstract class "%s" should have "Abstract" prefix',
61+
$className
62+
)
63+
)->build();
64+
}
65+
66+
return $errors;
67+
}
68+
69+
private function isRelevantNode(Node $node): bool
70+
{
71+
return $node instanceof Node\Stmt\Interface_
72+
|| $node instanceof Node\Stmt\Trait_
73+
|| ($node instanceof Node\Stmt\Class_ && $node->isAbstract());
74+
}
75+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
/**
4+
* @copyright Copyright (C) Ibexa AS. All rights reserved.
5+
* @license For full copyright and license information view LICENSE file distributed with this source code.
6+
*/
7+
declare(strict_types=1);
8+
9+
namespace Ibexa\Tests\PHPStan\Rules\Fixtures;
10+
11+
interface WrongName
12+
{
13+
}
14+
15+
interface CorrectNameInterface
16+
{
17+
}
18+
19+
trait SimpleThing
20+
{
21+
}
22+
23+
trait CorrectNameTrait
24+
{
25+
}
26+
27+
abstract class SimpleClass
28+
{
29+
}
30+
31+
abstract class AbstractCorrectClass
32+
{
33+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
/**
4+
* @copyright Copyright (C) Ibexa AS. All rights reserved.
5+
* @license For full copyright and license information view LICENSE file distributed with this source code.
6+
*/
7+
declare(strict_types=1);
8+
9+
namespace Ibexa\Tests\PHPStan\Rules;
10+
11+
use Ibexa\PHPStan\Rules\NamingConventionRule;
12+
use PHPStan\Rules\Rule;
13+
use PHPStan\Testing\RuleTestCase;
14+
15+
/**
16+
* @extends \PHPStan\Testing\RuleTestCase<\Ibexa\PHPStan\Rules\NamingConventionRule>
17+
*/
18+
final class NamingConventionRuleTest extends RuleTestCase
19+
{
20+
protected function getRule(): Rule
21+
{
22+
return new NamingConventionRule();
23+
}
24+
25+
public function testRule(): void
26+
{
27+
$this->analyse(
28+
[
29+
__DIR__ . '/Fixtures/NamingConventionFixture.php',
30+
],
31+
[
32+
[
33+
'Interface "WrongName" should have "Interface" suffix',
34+
11,
35+
],
36+
[
37+
'Trait "SimpleThing" should have "Trait" suffix',
38+
19,
39+
],
40+
[
41+
'Abstract class "SimpleClass" should have "Abstract" prefix',
42+
27,
43+
],
44+
]
45+
);
46+
}
47+
}

0 commit comments

Comments
 (0)