Skip to content
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
5 changes: 5 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 [`2.12.0...main`][2.12.0...main].

### Added

- Added `PHPStan\NoIgnoreRule`, which reports an error when a `@phpstan-ignore`, `@phpstan-ignore-line`, or `@phpstan-ignore-next-line` tag is used to suppress an error ([#1009]), by [@localheinz]

### Changed

- Required `phpstan/phpstan:^2.1.35` ([#1010]), by [@localheinz]
Expand Down Expand Up @@ -740,6 +744,7 @@ For a full diff see [`362c7ea...0.1.0`][362c7ea...0.1.0].
[#958]: https://github.com/ergebnis/phpstan-rules/pull/958
[#972]: https://github.com/ergebnis/phpstan-rules/pull/972
[#977]: https://github.com/ergebnis/phpstan-rules/pull/977
[#1009]: https://github.com/ergebnis/phpstan-rules/pull/1009
[#1010]: https://github.com/ergebnis/phpstan-rules/pull/1010

[@cosmastech]: https://github.com/cosmastech
Expand Down
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ This package provides the following rules for use with [`phpstan/phpstan`](https
- [`Ergebnis\PHPStan\Rules\Expressions\NoEvalRule`](https://github.com/ergebnis/phpstan-rules#expressionsnoevalrule)
- [`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\Files\NoPhpstanIgnoreRule`](https://github.com/ergebnis/phpstan-rules#filesnophpstanignorerule)
- [`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)
Expand Down Expand Up @@ -348,6 +349,21 @@ parameters:
enabled: false
```

#### `Files\NoPhpstanIgnoreRule`

This rule reports an error when a `@phpstan-ignore`, `@phpstan-ignore-line`, or `@phpstan-ignore-next-line` tag is used to [ignore errors reported by `phpstan/phpstan`](https://phpstan.org/user-guide/ignoring-errors#ignoring-in-code-using-phpdocs).

##### Disabling the rule

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

```neon
parameters:
ergebnis:
noPhpstanIgnore:
enabled: false
```

### Functions

#### `Functions\NoNullableReturnTypeDeclarationRule`
Expand Down
10 changes: 10 additions & 0 deletions rules.neon
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ conditionalTags:
phpstan.rules.rule: %ergebnis.noIsset.enabled%
Ergebnis\PHPStan\Rules\Files\DeclareStrictTypesRule:
phpstan.rules.rule: %ergebnis.declareStrictTypes.enabled%
Ergebnis\PHPStan\Rules\Files\NoPhpstanIgnoreRule:
phpstan.rules.rule: %ergebnis.noPhpstanIgnore.enabled%
Ergebnis\PHPStan\Rules\Functions\NoNullableReturnTypeDeclarationRule:
phpstan.rules.rule: %ergebnis.noNullableReturnTypeDeclaration.enabled%
Ergebnis\PHPStan\Rules\Functions\NoParameterPassedByReferenceRule:
Expand Down Expand Up @@ -102,6 +104,8 @@ parameters:
enabled: %ergebnis.allRules%
noParameterWithNullDefaultValue:
enabled: %ergebnis.allRules%
noPhpstanIgnore:
enabled: %ergebnis.allRules%
noReturnByReference:
enabled: %ergebnis.allRules%
noSwitch:
Expand Down Expand Up @@ -176,6 +180,9 @@ parametersSchema:
noParameterWithNullDefaultValue: structure([
enabled: bool(),
])
noPhpstanIgnore: structure([
enabled: bool(),
])
noReturnByReference: structure([
enabled: bool(),
])
Expand Down Expand Up @@ -238,6 +245,9 @@ services:
-
class: Ergebnis\PHPStan\Rules\Files\DeclareStrictTypesRule

-
class: Ergebnis\PHPStan\Rules\Files\NoPhpstanIgnoreRule

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

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

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

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

declare(strict_types=1);

/**
* Copyright (c) 2018-2026 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\Files;

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

/**
* @implements Rules\Rule<FileNode>
*/
final class NoPhpstanIgnoreRule implements Rules\Rule
{
public function getNodeType(): string
{
return FileNode::class;
}

public function processNode(
Node $node,
Analyser\Scope $scope
): array {
$errors = [];

foreach ($node->getNodes() as $nodeInFile) {
foreach ($nodeInFile->getComments() as $comment) {
foreach (\explode("\n", $comment->getText()) as $index => $line) {
if (0 === \preg_match('/@phpstan-ignore(-line|-next-line)?(?=\s|$|,)/', $line, $matches)) {
continue;
}

$tag = $matches[0];

$message = \sprintf(
'Errors reported by phpstan/phpstan should not be ignored via "%s", fix the error or use the baseline instead.',
$tag,
);

$errors[] = Rules\RuleErrorBuilder::message($message)
->identifier(ErrorIdentifier::noPhpstanIgnore()->toString())
->line($comment->getStartLine() + $index)
->nonIgnorable()
->build();
}
}
}

return $errors;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

// @phpstan-ignore variable.undefined
echo $undefined;

/* @phpstan-ignore variable.undefined */
echo $undefined;

/** @phpstan-ignore variable.undefined */
echo $undefined;

/*
* @phpstan-ignore variable.undefined
*/
echo $undefined;

echo $undefined; // @phpstan-ignore-line

echo $undefined; /* @phpstan-ignore-line */

echo $undefined;

/** @phpstan-ignore-line */

// @phpstan-ignore-next-line
echo $undefined;

/* @phpstan-ignore-next-line */
echo $undefined;

/** @phpstan-ignore-next-line */
echo $undefined;
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

// a normal comment
/* a normal block comment */

/** a normal doc comment */
echo 'Hello!';

// @phpstan-type Foo = int
/* @phpstan-param int $x */

/** @phpstan-return int */
echo 'World!';
124 changes: 124 additions & 0 deletions test/Integration/Files/NoPhpStanIgnoreRuleTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
<?php

declare(strict_types=1);

/**
* Copyright (c) 2018-2026 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\Files;

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

/**
* @covers \Ergebnis\PHPStan\Rules\Files\NoPhpstanIgnoreRule
*
* @uses \Ergebnis\PHPStan\Rules\ErrorIdentifier
*
* @extends Testing\RuleTestCase<\Ergebnis\PHPStan\Rules\Files\NoPhpstanIgnoreRule>
*/
final class NoPhpStanIgnoreRuleTest extends Testing\RuleTestCase
{
use Test\Util\Helper;

public function testNoIgnoreRule(): void
{
$this->analyse(
self::phpFilesIn(__DIR__ . '/../../Fixture/Files/NoPhpstanIgnoreRule'),
[
[
'Errors reported by phpstan/phpstan should not be ignored via "@phpstan-ignore", fix the error or use the baseline instead.',
5,
],
[
'No error with identifier variable.undefined is reported on line 6.',
6,
],
[
'Errors reported by phpstan/phpstan should not be ignored via "@phpstan-ignore", fix the error or use the baseline instead.',
8,
],
[
'No error with identifier variable.undefined is reported on line 9.',
9,
],
[
'Errors reported by phpstan/phpstan should not be ignored via "@phpstan-ignore", fix the error or use the baseline instead.',
11,
],
[
'No error with identifier variable.undefined is reported on line 12.',
12,
],
[
'Errors reported by phpstan/phpstan should not be ignored via "@phpstan-ignore", fix the error or use the baseline instead.',
15,
],
[
'No error with identifier variable.undefined is reported on line 17.',
17,
],
[
'Errors reported by phpstan/phpstan should not be ignored via "@phpstan-ignore-line", fix the error or use the baseline instead.',
19,
],
[
'No error to ignore is reported on line 19.',
19,
],
[
'Errors reported by phpstan/phpstan should not be ignored via "@phpstan-ignore-line", fix the error or use the baseline instead.',
21,
],
[
'No error to ignore is reported on line 21.',
21,
],
[
'Errors reported by phpstan/phpstan should not be ignored via "@phpstan-ignore-line", fix the error or use the baseline instead.',
25,
],
[
'No error to ignore is reported on line 25.',
25,
],
[
'Errors reported by phpstan/phpstan should not be ignored via "@phpstan-ignore-next-line", fix the error or use the baseline instead.',
27,
],
[
'No error to ignore is reported on line 28.',
28,
],
[
'Errors reported by phpstan/phpstan should not be ignored via "@phpstan-ignore-next-line", fix the error or use the baseline instead.',
30,
],
[
'No error to ignore is reported on line 31.',
31,
],
[
'Errors reported by phpstan/phpstan should not be ignored via "@phpstan-ignore-next-line", fix the error or use the baseline instead.',
33,
],
[
'No error to ignore is reported on line 34.',
34,
],
],
);
}

protected function getRule(): Rules\Rule
{
return new \Ergebnis\PHPStan\Rules\Files\NoPhpstanIgnoreRule();
}
}
7 changes: 7 additions & 0 deletions test/Unit/ErrorIdentifierTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,13 @@ public function testNoParameterWithNullableTypeDeclarationReturnsErrorIdentifier
self::assertSame('ergebnis.noParameterWithNullableTypeDeclaration', $errorIdentifier->toString());
}

public function testNoPhpstanIgnoreReturnsErrorIdentifier(): void
{
$errorIdentifier = ErrorIdentifier::noPhpstanIgnore();

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

public function testNoReturnByReferenceReturnsErrorIdentifier(): void
{
$errorIdentifier = ErrorIdentifier::noReturnByReference();
Expand Down