Skip to content

Commit

Permalink
Enhancement: Implement NoParameterPassedByReferenceRule
Browse files Browse the repository at this point in the history
  • Loading branch information
localheinz committed Feb 17, 2025
1 parent 4de8c33 commit 32b3d0a
Show file tree
Hide file tree
Showing 31 changed files with 784 additions and 0 deletions.
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ This package provides the following rules for use with [`phpstan/phpstan`](https
- [`Ergebnis\PHPStan\Rules\Classes\NoExtendsRule`](https://github.com/ergebnis/phpstan-rules#classesnoextendsrule)
- [`Ergebnis\PHPStan\Rules\Classes\PHPUnit\Framework\TestCaseWithSuffixRule`](https://github.com/ergebnis/phpstan-rules#classesphpunitframeworktestcasewithsuffixrule)
- [`Ergebnis\PHPStan\Rules\Closures\NoNullableReturnTypeDeclarationRule`](https://github.com/ergebnis/phpstan-rules#closuresnonullablereturntypedeclarationrule)
- [`Ergebnis\PHPStan\Rules\Closures\NoParameterPassedByReferenceRule`](https://github.com/ergebnis/phpstan-rules#closuresnoparameterpassedbyreferencerule)
- [`Ergebnis\PHPStan\Rules\Closures\NoParameterWithNullableTypeDeclarationRule`](https://github.com/ergebnis/phpstan-rules#closuresnoparameterwithnullabletypedeclarationrule)
- [`Ergebnis\PHPStan\Rules\Closures\NoParameterWithNullDefaultValueRule`](https://github.com/ergebnis/phpstan-rules#closuresnoparameterwithnulldefaultvaluerule)
- [`Ergebnis\PHPStan\Rules\Expressions\NoCompactRule`](https://github.com/ergebnis/phpstan-rules#expressionsnocompactrule)
Expand All @@ -56,11 +57,13 @@ This package provides the following rules for use with [`phpstan/phpstan`](https
- [`Ergebnis\PHPStan\Rules\Expressions\NoIssetRule`](https://github.com/ergebnis/phpstan-rules#expressionsnoissetrule)
- [`Ergebnis\PHPStan\Rules\Files\DeclareStrictTypesRule`](https://github.com/ergebnis/phpstan-rules#filesdeclarestricttypesrule)
- [`Ergebnis\PHPStan\Rules\Functions\NoNullableReturnTypeDeclarationRule`](https://github.com/ergebnis/phpstan-rules#functionsnonullablereturntypedeclarationrule)
- [`Ergebnis\PHPStan\Rules\Functions\NoParameterPassedByReferenceRule`](https://github.com/ergebnis/phpstan-rules#functionsnoparameterpassedbyreferencerule)
- [`Ergebnis\PHPStan\Rules\Functions\NoParameterWithNullableTypeDeclarationRule`](https://github.com/ergebnis/phpstan-rules#functionsnoparameterwithnullabletypedeclarationrule)
- [`Ergebnis\PHPStan\Rules\Functions\NoParameterWithNullDefaultValueRule`](https://github.com/ergebnis/phpstan-rules#functionsnoparameterwithnulldefaultvaluerule)
- [`Ergebnis\PHPStan\Rules\Methods\FinalInAbstractClassRule`](https://github.com/ergebnis/phpstan-rules#methodsfinalinabstractclassrule)
- [`Ergebnis\PHPStan\Rules\Methods\NoConstructorParameterWithDefaultValueRule`](https://github.com/ergebnis/phpstan-rules#methodsnoconstructorparameterwithdefaultvaluerule)
- [`Ergebnis\PHPStan\Rules\Methods\NoNullableReturnTypeDeclarationRule`](https://github.com/ergebnis/phpstan-rules#methodsnonullablereturntypedeclarationrule)
- [`Ergebnis\PHPStan\Rules\Methods\NoParameterPassedByReferenceRule`](https://github.com/ergebnis/phpstan-rules#methodsnoparameterpassedbyreferencerule)
- [`Ergebnis\PHPStan\Rules\Methods\NoParameterWithContainerTypeDeclarationRule`](https://github.com/ergebnis/phpstan-rules#methodsnoparameterwithcontainertypedeclarationrule)
- [`Ergebnis\PHPStan\Rules\Methods\NoParameterWithNullableTypeDeclarationRule`](https://github.com/ergebnis/phpstan-rules#methodsnoparameterwithnullabletypedeclarationrule)
- [`Ergebnis\PHPStan\Rules\Methods\NoParameterWithNullDefaultValueRule`](https://github.com/ergebnis/phpstan-rules#methodsnoparameterwithnulldefaultvaluerule)
Expand Down Expand Up @@ -183,6 +186,21 @@ parameters:
enabled: false
```

#### `Closures\NoParameterPassedByReferenceRule`

This rule reports an error when a closure has a parameter that is [passed by reference](https://www.php.net/manual/en/language.references.pass.php).

##### Disabling the rule

You can set the `enabled` parameter to `false` to disable this rule.

```neon
parameters:
ergebnis:
noParameterPassedByReference:
enabled: false
```

#### `Closures\NoParameterWithNullableTypeDeclarationRule`

This rule reports an error when a closure has a parameter with a nullable type declaration.
Expand Down Expand Up @@ -309,6 +327,21 @@ parameters:
enabled: false
```

#### `Functions\NoParameterPassedByReferenceRule`

This rule reports an error when a function has a parameter that is [passed by reference](https://www.php.net/manual/en/language.references.pass.php).

##### Disabling the rule

You can set the `enabled` parameter to `false` to disable this rule.

```neon
parameters:
ergebnis:
noParameterPassedByReference:
enabled: false
```

#### `Functions\NoParameterWithNullableTypeDeclarationRule`

This rule reports an error when a function has a parameter with a nullable type declaration.
Expand Down Expand Up @@ -381,6 +414,21 @@ parameters:
enabled: false
```

#### `Methods\NoParameterPassedByReferenceRule`

This rule reports an error when a method has a parameter that is [passed by reference](https://www.php.net/manual/en/language.references.pass.php).

##### Disabling the rule

You can set the `enabled` parameter to `false` to disable this rule.

```neon
parameters:
ergebnis:
noParameterPassedByReference:
enabled: false
```

#### `Methods\NoNullableReturnTypeDeclarationRule`

This rule reports an error when a method declared in
Expand Down
20 changes: 20 additions & 0 deletions rules.neon
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ conditionalTags:
phpstan.rules.rule: %ergebnis.testCaseWithSuffix.enabled%
Ergebnis\PHPStan\Rules\Closures\NoNullableReturnTypeDeclarationRule:
phpstan.rules.rule: %ergebnis.noNullableReturnTypeDeclaration.enabled%
Ergebnis\PHPStan\Rules\Closures\NoParameterPassedByReferenceRule:
phpstan.rules.rule: %ergebnis.noParameterPassedByReference.enabled%
Ergebnis\PHPStan\Rules\Closures\NoParameterWithNullableTypeDeclarationRule:
phpstan.rules.rule: %ergebnis.noParameterWithNullableTypeDeclaration.enabled%
Ergebnis\PHPStan\Rules\Expressions\NoCompactRule:
Expand All @@ -21,6 +23,8 @@ conditionalTags:
phpstan.rules.rule: %ergebnis.declareStrictTypes.enabled%
Ergebnis\PHPStan\Rules\Functions\NoNullableReturnTypeDeclarationRule:
phpstan.rules.rule: %ergebnis.noNullableReturnTypeDeclaration.enabled%
Ergebnis\PHPStan\Rules\Functions\NoParameterPassedByReferenceRule:
phpstan.rules.rule: %ergebnis.noParameterPassedByReference.enabled%
Ergebnis\PHPStan\Rules\Functions\NoParameterWithNullableTypeDeclarationRule:
phpstan.rules.rule: %ergebnis.noParameterWithNullableTypeDeclaration.enabled%
Ergebnis\PHPStan\Rules\Functions\NoParameterWithNullDefaultValueRule:
Expand All @@ -31,6 +35,8 @@ conditionalTags:
phpstan.rules.rule: %ergebnis.noConstructorParameterWithDefaultValue.enabled%
Ergebnis\PHPStan\Rules\Methods\NoNullableReturnTypeDeclarationRule:
phpstan.rules.rule: %ergebnis.noNullableReturnTypeDeclaration.enabled%
Ergebnis\PHPStan\Rules\Methods\NoParameterPassedByReferenceRule:
phpstan.rules.rule: %ergebnis.noParameterPassedByReference.enabled%
Ergebnis\PHPStan\Rules\Methods\NoParameterWithContainerTypeDeclarationRule:
phpstan.rules.rule: %ergebnis.noParameterWithContainerTypeDeclaration.enabled%
Ergebnis\PHPStan\Rules\Methods\NoParameterWithNullableTypeDeclarationRule:
Expand Down Expand Up @@ -67,6 +73,8 @@ parameters:
enabled: true
noNullableReturnTypeDeclaration:
enabled: true
noParameterPassedByReference:
enabled: true
noParameterWithContainerTypeDeclaration:
enabled: true
interfacesImplementedByContainers:
Expand Down Expand Up @@ -118,6 +126,9 @@ parametersSchema:
noNullableReturnTypeDeclaration: structure([
enabled: bool(),
])
noParameterPassedByReference: structure([
enabled: bool(),
])
noParameterWithContainerTypeDeclaration: structure([
enabled: bool(),
interfacesImplementedByContainers: listOf(string())
Expand Down Expand Up @@ -161,6 +172,9 @@ services:
-
class: Ergebnis\PHPStan\Rules\Closures\NoNullableReturnTypeDeclarationRule

-
class: Ergebnis\PHPStan\Rules\Closures\NoParameterPassedByReferenceRule

-
class: Ergebnis\PHPStan\Rules\Closures\NoParameterWithNullableTypeDeclarationRule

Expand All @@ -182,6 +196,9 @@ services:
-
class: Ergebnis\PHPStan\Rules\Functions\NoNullableReturnTypeDeclarationRule

-
class: Ergebnis\PHPStan\Rules\Functions\NoParameterPassedByReferenceRule

-
class: Ergebnis\PHPStan\Rules\Functions\NoParameterWithNullableTypeDeclarationRule

Expand All @@ -197,6 +214,9 @@ services:
-
class: Ergebnis\PHPStan\Rules\Methods\NoNullableReturnTypeDeclarationRule

-
class: Ergebnis\PHPStan\Rules\Methods\NoParameterPassedByReferenceRule

-
class: Ergebnis\PHPStan\Rules\Methods\NoParameterWithContainerTypeDeclarationRule
arguments:
Expand Down
64 changes: 64 additions & 0 deletions src/Closures/NoParameterPassedByReferenceRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php

declare(strict_types=1);

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

namespace Ergebnis\PHPStan\Rules\Closures;

use Ergebnis\PHPStan\Rules\ErrorIdentifier;
use PhpParser\Node;
use PHPStan\Analyser;
use PHPStan\Rules;

/**
* @implements Rules\Rule<Node\Expr\Closure>
*/
final class NoParameterPassedByReferenceRule implements Rules\Rule
{
public function getNodeType(): string
{
return Node\Expr\Closure::class;
}

public function processNode(
Node $node,
Analyser\Scope $scope
): array {
if (0 === \count($node->params)) {
return [];
}

$parametersPassedByReference = \array_values(\array_filter($node->params, static function (Node\Param $parameter): bool {
return $parameter->byRef;
}));

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

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

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

$message = \sprintf(
'Closure has parameter $%s that is passed by reference.',
$parameterName,
);

return Rules\RuleErrorBuilder::message($message)
->identifier(ErrorIdentifier::noParameterPassedByReference()->toString())
->build();
}, $parametersPassedByReference);
}
}
5 changes: 5 additions & 0 deletions src/ErrorIdentifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ public static function noIsset(): self
return new self('noIsset');
}

public static function noParameterPassedByReference(): self
{
return new self('noParameterPassedByReference');
}

public static function noParameterWithContainerTypeDeclaration(): self
{
return new self('noParameterWithContainerTypeDeclaration');
Expand Down
67 changes: 67 additions & 0 deletions src/Functions/NoParameterPassedByReferenceRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

declare(strict_types=1);

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

namespace Ergebnis\PHPStan\Rules\Functions;

use Ergebnis\PHPStan\Rules\ErrorIdentifier;
use PhpParser\Node;
use PHPStan\Analyser;
use PHPStan\Rules;

/**
* @implements Rules\Rule<Node\Stmt\Function_>
*/
final class NoParameterPassedByReferenceRule implements Rules\Rule
{
public function getNodeType(): string
{
return Node\Stmt\Function_::class;
}

public function processNode(
Node $node,
Analyser\Scope $scope
): array {
if (0 === \count($node->params)) {
return [];
}

$parametersPassedByReference = \array_values(\array_filter($node->params, static function (Node\Param $parameter): bool {
return $parameter->byRef;
}));

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

$functionName = $node->namespacedName;

return \array_map(static function (Node\Param $parameterPassedByReference) use ($functionName): Rules\RuleError {
/** @var Node\Expr\Variable $variable */
$variable = $parameterPassedByReference->var;

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

$message = \sprintf(
'Function %s() has parameter $%s that is passed by reference.',
$functionName,
$parameterName,
);

return Rules\RuleErrorBuilder::message($message)
->identifier(ErrorIdentifier::noParameterWithNullDefaultValue()->toString())
->build();
}, $parametersPassedByReference);
}
}
Loading

0 comments on commit 32b3d0a

Please sign in to comment.