Skip to content

Commit

Permalink
Enhancement: Implement NoAssignByReferenceRule
Browse files Browse the repository at this point in the history
  • Loading branch information
localheinz committed Feb 18, 2025
1 parent 45d1852 commit 028c8fd
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ For a full diff see [`2.7.0...main`][2.7.0...main].
### Added

- Added `allRules` parameter to allow disabling and enabling all rules ([#913]), by [@localheinz]
- Added `Expressions\NoAssignByReferenceRule`, which reports an error when a variable is assigned by reference ([#914]), by [@localheinz]

## [`2.7.0`][2.7.0]

Expand Down Expand Up @@ -617,6 +618,7 @@ For a full diff see [`362c7ea...0.1.0`][362c7ea...0.1.0].
[#911]: https://github.com/ergebnis/phpstan-rules/pull/911
[#912]: https://github.com/ergebnis/phpstan-rules/pull/912
[#913]: https://github.com/ergebnis/phpstan-rules/pull/913
[#914]: https://github.com/ergebnis/phpstan-rules/pull/914

[@cosmastech]: https://github.com/cosmastech
[@enumag]: https://github.com/enumag
Expand Down
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ This package provides the following rules for use with [`phpstan/phpstan`](https
- [`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\NoAssignByReferenceRule`](https://github.com/ergebnis/phpstan-rules#expressionsnoassignbyreferencerule)
- [`Ergebnis\PHPStan\Rules\Expressions\NoCompactRule`](https://github.com/ergebnis/phpstan-rules#expressionsnocompactrule)
- [`Ergebnis\PHPStan\Rules\Expressions\NoErrorSuppressionRule`](https://github.com/ergebnis/phpstan-rules#expressionsnoerrorsuppressionrule)
- [`Ergebnis\PHPStan\Rules\Expressions\NoEvalRule`](https://github.com/ergebnis/phpstan-rules#expressionsnoevalrule)
Expand Down Expand Up @@ -235,6 +236,21 @@ parameters:

### Expressions

#### `Expressions\NoAssignByReferenceRule`

This rule reports an error when [a variable is assigned by reference](https://www.php.net/manual/en/language.references.whatdo.php#language.references.whatdo.assign).

##### Disabling the rule

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

```neon
parameters:
ergebnis:
noAssignByReference:
enabled: false
```

#### `Expressions\NoCompactRule`

This rule reports an error when the function [`compact()`](https://www.php.net/compact) is used.
Expand Down
10 changes: 10 additions & 0 deletions rules.neon
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ conditionalTags:
phpstan.rules.rule: %ergebnis.noParameterPassedByReference.enabled%
Ergebnis\PHPStan\Rules\Closures\NoParameterWithNullableTypeDeclarationRule:
phpstan.rules.rule: %ergebnis.noParameterWithNullableTypeDeclaration.enabled%
Ergebnis\PHPStan\Rules\Expressions\NoAssignByReferenceRule:
phpstan.rules.rule: %ergebnis.noAssignByReference.enabled%
Ergebnis\PHPStan\Rules\Expressions\NoCompactRule:
phpstan.rules.rule: %ergebnis.noCompact.enabled%
Ergebnis\PHPStan\Rules\Expressions\NoErrorSuppressionRule:
Expand Down Expand Up @@ -63,6 +65,8 @@ parameters:
enabled: %ergebnis.allRules%
finalInAbstractClass:
enabled: %ergebnis.allRules%
noAssignByReference:
enabled: %ergebnis.allRules%
noCompact:
enabled: %ergebnis.allRules%
noConstructorParameterWithDefaultValue:
Expand Down Expand Up @@ -112,6 +116,9 @@ parametersSchema:
finalInAbstractClass: structure([
enabled: bool(),
])
noAssignByReference: structure([
enabled: bool(),
])
noCompact: structure([
enabled: bool(),
])
Expand Down Expand Up @@ -189,6 +196,9 @@ services:
-
class: Ergebnis\PHPStan\Rules\Closures\NoParameterWithNullableTypeDeclarationRule

-
class: Ergebnis\PHPStan\Rules\Expressions\NoAssignByReferenceRule

-
class: Ergebnis\PHPStan\Rules\Expressions\NoCompactRule

Expand Down
5 changes: 5 additions & 0 deletions src/ErrorIdentifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ public static function noConstructorParameterWithDefaultValue(): self
return new self('noConstructorParameterWithDefaultValue');
}

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

public static function noErrorSuppression(): self
{
return new self('noErrorSuppression');
Expand Down
41 changes: 41 additions & 0 deletions src/Expressions/NoAssignByReferenceRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?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\Expressions;

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

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

public function processNode(
Node $node,
Analyser\Scope $scope
): array {
return [
Rules\RuleErrorBuilder::message('Assign by reference should not be used.')
->identifier(ErrorIdentifier::noAssignByReference()->toString())
->build(),
];
}
}
11 changes: 11 additions & 0 deletions test/Fixture/Expressions/NoAssignByReferenceRule/script.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

namespace Ergebnis\PHPStan\Rules\Test\Fixture\Expressions\NoAssignByReferenceRule;

$foo = 'bar';

$bar = $foo;

$baz = &$foo;
49 changes: 49 additions & 0 deletions test/Integration/Expressions/NoAssignByReferenceRuleTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?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\Test\Integration\Expressions;

use Ergebnis\PHPStan\Rules\Expressions;
use Ergebnis\PHPStan\Rules\Test;
use PHPStan\Rules;
use PHPStan\Testing;

/**
* @covers \Ergebnis\PHPStan\Rules\Expressions\NoAssignByReferenceRule
*
* @uses \Ergebnis\PHPStan\Rules\ErrorIdentifier
*
* @extends Testing\RuleTestCase<Expressions\NoAssignByReferenceRule>
*/
final class NoAssignByReferenceRuleTest extends Testing\RuleTestCase
{
use Test\Util\Helper;

public function testNoAssignByReferenceRule(): void
{
$this->analyse(
self::phpFilesIn(__DIR__ . '/../../Fixture/Expressions/NoAssignByReferenceRule'),
[
[
'Assign by reference should not be used.',
11,
],
],
);
}

protected function getRule(): Rules\Rule
{
return new Expressions\NoAssignByReferenceRule();
}
}
7 changes: 7 additions & 0 deletions test/Unit/ErrorIdentifierTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ public function testFinalReturnsErrorIdentifier(): void
self::assertSame('ergebnis.final', $errorIdentifier->toString());
}

public function testNoAssignByReferenceReturnsErrorIdentifier(): void
{
$errorIdentifier = ErrorIdentifier::noAssignByReference();

self::assertSame('ergebnis.noAssignByReference', $errorIdentifier->toString());
}

public function testNoCompactReturnsErrorIdentifier(): void
{
$errorIdentifier = ErrorIdentifier::noCompact();
Expand Down

0 comments on commit 028c8fd

Please sign in to comment.