Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancement: Implement Closures\NoParameterWithNullableTypeDeclarationRule #33

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ For a full diff see [`0.2.0...master`](https://github.com/localheinz/phpstan-rul
* added `Methods\NoParameterWithNullDefaultValueRule`, which reports an
error when a method declared on an anonymous class, a class, or an interface
has a parameter with `null` as default value ([#32](https://github.com/localheinz/phpstan-rules/pull/32)), by [@localheinz](https://github.com/localheinz)
* added `Closures\NoParameterWithNullableTypeDeclarationRule`, which reports an
error when a closure has a parameter with a nullable type declaration ([#33](https://github.com/localheinz/phpstan-rules/pull/33)), by [@localheinz](https://github.com/localheinz)

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

Expand Down
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ This package provides the following rules for use with [`phpstan/phpstan`](https
* [`Localheinz\PHPStan\Rules\Classes\AbstractOrFinalRule`](https://github.com/localheinz/phpstan-rules#classesabstractorfinalrule)
* [`Localheinz\PHPStan\Rules\Classes\FinalRule`](https://github.com/localheinz/phpstan-rules#classesfinalrule)
* [`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)
* [`Localheinz\PHPStan\Rules\Functions\NoNullableReturnTypeDeclarationRule`](https://github.com/localheinz/phpstan-rules#functionsnonullablereturntypedeclarationrule)
* [`Localheinz\PHPStan\Rules\Functions\NoParameterWithNullDefaultValueRule`](https://github.com/localheinz/phpstan-rules#functionsnoparameterwithnulldefaultvaluerule)
Expand Down Expand Up @@ -89,6 +90,17 @@ rules:
- Localheinz\PHPStan\Rules\Closures\NoNullableReturnTypeDeclarationRule
```

### `Closures\NoParameterWithNullableTypeDeclarationRule`

This rule reports an error when a closure has a parameter with a nullable type declaration.

If you want to use this rule, add it to your `phpstan.neon`:

```neon
rules:
- Localheinz\PHPStan\Rules\Closures\NoParameterWithNullableTypeDeclarationRule
```

### `Closures\NoParameterWithNullDefaultValueRule`

This rule reports an error when a closure has a parameter with `null` as default value.
Expand Down
1 change: 1 addition & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ includes:
rules:
- Localheinz\PHPStan\Rules\Classes\AbstractOrFinalRule
- Localheinz\PHPStan\Rules\Closures\NoNullableReturnTypeDeclarationRule
- Localheinz\PHPStan\Rules\Closures\NoParameterWithNullableTypeDeclarationRule
- Localheinz\PHPStan\Rules\Functions\NoNullableReturnTypeDeclarationRule
- Localheinz\PHPStan\Rules\Functions\NoParameterWithNullDefaultValueRule
- Localheinz\PHPStan\Rules\Methods\NoNullableReturnTypeDeclarationRule
Expand Down
60 changes: 60 additions & 0 deletions src/Closures/NoParameterWithNullableTypeDeclarationRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?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\Closures;

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

final class NoParameterWithNullableTypeDeclarationRule implements Rule
{
public function getNodeType(): string
{
return Node\Expr\Closure::class;
}

/**
* @param Node\Expr\Closure $node
* @param Scope $scope
*
* @return array
*/
public function processNode(Node $node, Scope $scope): array
{
if (0 === \count($node->params)) {
return [];
}

$params = \array_filter($node->params, static function (Node\Param $node): bool {
return $node->type instanceof Node\NullableType;
});

if (0 === \count($params)) {
return [];
}

return \array_map(static function (Node\Param $node): string {
/** @var Node\Expr\Variable $variable */
$variable = $node->var;

/** @var string $parameterName */
$parameterName = $variable->name;

return \sprintf(
'Parameter "$%s" of closure should not have a nullable type declaration.',
$parameterName
);
}, $params);
}
}
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\Closures\NoParameterWithNullDefaultValueRule\Success;

$foo = function (?string $bar) {
return $bar;
};
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\Closures\NoParameterWithNullDefaultValueRule\Success;

$foo = function (string $bar) {
return $bar;
};
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\Closures\NoParameterWithNullDefaultValueRule\Success;

$foo = function ($bar) {
return $bar;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

declare(strict_types=1);

namespace Localheinz\PHPStan\Rules\Test\Fixture\Closures\NoParameterWithNullDefaultValueRule\Success;

$foo = function () {
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?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\Test\Integration\Closures;

use Localheinz\PHPStan\Rules\Closures\NoParameterWithNullableTypeDeclarationRule;
use Localheinz\PHPStan\Rules\Test\Integration\AbstractTestCase;
use PHPStan\Rules\Rule;

/**
* @internal
*/
final class NoParameterWithNullableTypeDeclarationRuleTest extends AbstractTestCase
{
public function providerAnalysisSucceeds(): \Generator
{
$paths = [
'closure-with-parameter-with-type-declaration' => __DIR__ . '/../../Fixture/Closures/NoParameterWithNullableTypeDeclarationRule/Success/closure-with-parameter-with-type-declaration.php',
'closure-with-parameter-without-type-declaration' => __DIR__ . '/../../Fixture/Closures/NoParameterWithNullableTypeDeclarationRule/Success/closure-with-parameter-without-type-declaration.php',
'closure-without-parameters' => __DIR__ . '/../../Fixture/Closures/NoParameterWithNullableTypeDeclarationRule/Success/closure-without-parameters.php',
];

foreach ($paths as $description => $path) {
yield $description => [
$path,
];
}
}

public function providerAnalysisFails(): \Generator
{
$paths = [
'closure-with-parameter-with-nullable-type-declaration' => [
__DIR__ . '/../../Fixture/Closures/NoParameterWithNullableTypeDeclarationRule/Failure/closure-with-parameter-with-nullable-type-declaration.php',
[
'Parameter "$bar" of closure should not have a nullable type declaration.',
7,
],
],
];

foreach ($paths as $description => [$path, $error]) {
yield $description => [
$path,
$error,
];
}
}

protected function getRule(): Rule
{
return new NoParameterWithNullableTypeDeclarationRule();
}
}