Skip to content

Commit

Permalink
Merge pull request #68 from localheinz/feature/no-extends-rule
Browse files Browse the repository at this point in the history
Enhancement: Implement Classes\NoExtendsRule
  • Loading branch information
localheinz authored Jan 17, 2019
2 parents ab75cda + 918ae7f commit 7dfeb42
Show file tree
Hide file tree
Showing 28 changed files with 461 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ jobs:
- mkdir -p $HOME/.build/infection

script:
- vendor/bin/infection --ignore-msi-with-no-mutations --min-covered-msi=98 --min-msi=98
- vendor/bin/infection --ignore-msi-with-no-mutations --min-covered-msi=96 --min-msi=96

notifications:
email: false
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

For a full diff see [`0.6.0...master`](https://github.com/localheinz/phpstan-rules/compare/0.6.0...master).

### Added

* Added `Classes\NoExtendsRule`, which reports an error when a class extends a class that is not allowed to be extended ([#68](https://github.com/localheinz/phpstan-rules/pull/68)), by [@localheinz](https://github.com/localheinz)

## [`0.6.0`](https://github.com/localheinz/phpstan-rules/releases/tag/0.6.0)

For a full diff see [`0.5.0...0.6.0`](https://github.com/localheinz/phpstan-rules/compare/0.5.0...0.6.0).
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ cs: vendor

infection: vendor
mkdir -p .build/infection
vendor/bin/infection --ignore-msi-with-no-mutations --min-covered-msi=98 --min-msi=98
vendor/bin/infection --ignore-msi-with-no-mutations --min-covered-msi=96 --min-msi=96

stan: vendor
mkdir -p .build/phpstan
Expand Down
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ includes:
This package provides the following rules for use with [`phpstan/phpstan`](https://github.com/phpstan/phpstan):

* [`Localheinz\PHPStan\Rules\Classes\FinalRule`](https://github.com/localheinz/phpstan-rules#classesfinalrule)
* [`Localheinz\PHPStan\Rules\Classes\NoExtendsRule`](https://github.com/localheinz/phpstan-rules#classesnoextendsrule)
* [`Localheinz\PHPStan\Rules\Closures\NoNullableReturnTypeDeclarationRule`](https://github.com/localheinz/phpstan-rules#closuresnonullablereturntypedeclarationrule)
* [`Localheinz\PHPStan\Rules\Closures\NoParameterWithNullableTypeDeclarationRule`](https://github.com/localheinz/phpstan-rules#closuresnoparameterwithnullabletypedeclarationrule)
* [`Localheinz\PHPStan\Rules\Closures\NoParameterWithNullDefaultValueRule`](https://github.com/localheinz/phpstan-rules#closuresnoparameterwithnulldefaultvaluerule)
Expand Down Expand Up @@ -72,6 +73,22 @@ parameters:
- Bar\Baz\NeitherAbstractNorFinal
```

#### `Classes\NoExtendsRule`

This rule reports an error when a class extends another class.

##### Allowing classes to be extended

If you want to allow some classes to be extended, you can set the `classesAllowedToBeExtended` parameter to a list of class names:

```neon
parameters:
classesAllowedToBeExtended:
- Localheinz\PHPStan\Rules\Test\Integration\AbstractTestCase
- PHPStan\Testing\RuleTestCase
- PHPUnit\Framework\TestCase
```

### Closures

#### `Closures\NoNullableReturnTypeDeclarationRule`
Expand Down
4 changes: 4 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ includes:
- vendor/phpstan/phpstan/conf/config.levelmax.neon

parameters:
classesAllowedToBeExtended:
- Localheinz\PHPStan\Rules\Test\Integration\AbstractTestCase
- PHPStan\Testing\RuleTestCase
- PHPUnit\Framework\TestCase
excludes_analyse:
- %currentWorkingDirectory%/test/Fixture/
paths:
Expand Down
7 changes: 7 additions & 0 deletions rules.neon
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
parameters:
allowAbstractClasses: true
classesAllowedToBeExtended: []
classesNotRequiredToBeAbstractOrFinal: []

rules:
Expand All @@ -21,3 +22,9 @@ services:
classesNotRequiredToBeAbstractOrFinal: %classesNotRequiredToBeAbstractOrFinal%
tags:
- phpstan.rules.rule
-
class: Localheinz\PHPStan\Rules\Classes\NoExtendsRule
arguments:
classesAllowedToBeExtended: %classesAllowedToBeExtended%
tags:
- phpstan.rules.rule
77 changes: 77 additions & 0 deletions src/Classes/NoExtendsRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php

declare(strict_types=1);

/**
* Copyright (c) 2018 Andreas Möller
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*
* @see https://github.com/localheinz/phpstan-rules
*/

namespace Localheinz\PHPStan\Rules\Classes;

use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;

final class NoExtendsRule implements Rule
{
/**
* @var string[]
*/
private $classesAllowedToBeExtended;

/**
* @param string[] $classesAllowedToBeExtended
*/
public function __construct(array $classesAllowedToBeExtended)
{
$this->classesAllowedToBeExtended = \array_map(static function (string $classAllowedToBeExtended): string {
return $classAllowedToBeExtended;
}, $classesAllowedToBeExtended);
}

public function getNodeType(): string
{
return Node\Stmt\Class_::class;
}

/**
* @param Node\Stmt\Class_ $node
* @param Scope $scope
*
* @return array
*/
public function processNode(Node $node, Scope $scope): array
{
if (!$node->extends instanceof Node\Name) {
return [];
}

$extendedClassName = $node->extends->toString();

if (\in_array($extendedClassName, $this->classesAllowedToBeExtended, true)) {
return [];
}

if (!isset($node->namespacedName)) {
return [
\sprintf(
'Anonymous class is not allowed to extend "%s".',
$extendedClassName
),
];
}

return [
\sprintf(
'Class "%s" is not allowed to extend "%s".',
$node->namespacedName,
$extendedClassName
),
];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

declare(strict_types=1);

namespace Localheinz\PHPStan\Rules\Test\Fixture\Classes\NoExtendsRule\Failure;

final class ClassExtendingOtherClass extends OtherClass
{
}
9 changes: 9 additions & 0 deletions test/Fixture/Classes/NoExtendsRule/Failure/OtherClass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

declare(strict_types=1);

namespace Localheinz\PHPStan\Rules\Test\Fixture\Classes\NoExtendsRule\Failure;

class OtherClass
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Localheinz\PHPStan\Rules\Test\Fixture\Classes\NoExtendsRule\Failure;

$foo = new class() extends OtherClass {
public function __toString(): string
{
return 'Hmm';
}
};
9 changes: 9 additions & 0 deletions test/Fixture/Classes/NoExtendsRule/Success/ExampleClass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

declare(strict_types=1);

namespace Localheinz\PHPStan\Rules\Test\Fixture\Classes\NoExtendsRule\Success;

final class ExampleClass
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

declare(strict_types=1);

namespace Localheinz\PHPStan\Rules\Test\Fixture\Classes\NoExtendsRule\Success;

interface ExampleInterface
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

declare(strict_types=1);

namespace Localheinz\PHPStan\Rules\Test\Fixture\Classes\NoExtendsRule\Success;

interface InterfaceExtendingOtherInterface extends OtherInterface
{
}
9 changes: 9 additions & 0 deletions test/Fixture/Classes/NoExtendsRule/Success/OtherInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

declare(strict_types=1);

namespace Localheinz\PHPStan\Rules\Test\Fixture\Classes\NoExtendsRule\Success;

interface OtherInterface
{
}
12 changes: 12 additions & 0 deletions test/Fixture/Classes/NoExtendsRule/Success/anonymous-class.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Localheinz\PHPStan\Rules\Test\Fixture\Classes\NoExtendsRule\Success;

$foo = new class() {
public function __toString(): string
{
return 'Hmm';
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

declare(strict_types=1);

namespace Localheinz\PHPStan\Rules\Test\Fixture\Classes\NoExtendsRuleWithClassesAllowedToBeExtended\Failure;

final class ClassExtendingOtherClass extends OtherClass
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

declare(strict_types=1);

namespace Localheinz\PHPStan\Rules\Test\Fixture\Classes\NoExtendsRuleWithClassesAllowedToBeExtended\Failure;

class OtherClass
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Localheinz\PHPStan\Rules\Test\Fixture\Classes\NoExtendsRuleWithClassesAllowedToBeExtended\Failure;

$foo = new class() extends OtherClass {
public function __toString(): string
{
return 'Hmm';
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

declare(strict_types=1);

namespace Localheinz\PHPStan\Rules\Test\Fixture\Classes\NoExtendsRuleWithClassesAllowedToBeExtended\Success;

class ClassAllowedToBeExtended
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

declare(strict_types=1);

namespace Localheinz\PHPStan\Rules\Test\Fixture\Classes\NoExtendsRuleWithClassesAllowedToBeExtended\Success;

final class ClassExtendingClassAllowedToBeExtended extends ClassAllowedToBeExtended
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

declare(strict_types=1);

namespace Localheinz\PHPStan\Rules\Test\Fixture\Classes\NoExtendsRuleWithClassesAllowedToBeExtended\Success;

final class ExampleClass
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

declare(strict_types=1);

namespace Localheinz\PHPStan\Rules\Test\Fixture\Classes\NoExtendsRuleWithClassesAllowedToBeExtended\Success;

interface ExampleInterface
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

declare(strict_types=1);

namespace Localheinz\PHPStan\Rules\Test\Fixture\Classes\NoExtendsRuleWithClassesAllowedToBeExtended\Success;

interface InterfaceExtendingOtherInterface extends OtherInterface
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

declare(strict_types=1);

namespace Localheinz\PHPStan\Rules\Test\Fixture\Classes\NoExtendsRuleWithClassesAllowedToBeExtended\Success;

interface OtherInterface
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Localheinz\PHPStan\Rules\Test\Fixture\Classes\NoExtendsRuleWithClassesAllowedToBeExtended\Success;

$foo = new class() extends ClassAllowedToBeExtended {
public function __toString(): string
{
return 'Hmm';
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Localheinz\PHPStan\Rules\Test\Fixture\Classes\NoExtendsRuleWithClassesAllowedToBeExtended\Success;

$foo = new class() {
public function __toString(): string
{
return 'Hmm';
}
};
Loading

0 comments on commit 7dfeb42

Please sign in to comment.