PHPStan ignores¶
The phpstan-ignores plugin is for a project that also runs PHPStan. It lets a @phpstan-ignore
comment drop the Mago issues that report the same finding, so the line doesn't need a @mago-expect
on top.
Turning it on¶
The plugin is off by default. Turn it on in mago.toml:
[analyzer]
plugins = ["phpstan-ignores"]
// @phpstan-ignore return.type (the caller handles NULL)
return NULL; // no invalid-return-statement
Comment forms¶
The plugin reads PHPStan's forms:
@phpstan-ignorewith identifiers separated by commas, and an optional reason in parentheses after any of them. It sits at the end of the line, or above it, where it covers the next line of code;@phpstan-ignore-next-line;@phpstan-ignore-line.
PHPStan wants that code on the very next line, and calls a comment with anything in between unused.
The plugin skips blank lines and other comments, so a @mago-expect can sit between the two.
A comment over several lines covers what PHPStan covers. In a /* */ comment, the line forms count
from the comment's last line, and when the comment holds both, it only covers the next line. In a
docblock, they count from the line that holds the tag, and a @phpstan-ignore-next-line that is
the docblock's last tag covers the line after the docblock. A comment that holds a line form doesn't
read identifiers from @phpstan-ignore.
return NULL; /* The caller handles NULL.
@phpstan-ignore-line */ // covers this line, not the `return`
Which issues a comment drops¶
An identifier drops only the Mago codes listed for it by the plugin, so
@phpstan-ignore return.type still lets a missing method on the same line through. The two line
forms drop every listed code, and an identifier not listed by the plugin doesn't drop anything.
The list covers PHPStan's identifiers for argument, return and property types, argument counts,
undefined symbols, static calls to instance methods, deprecations, always-true and always-false
conditions, comparisons, isset(), empty(), ?? and type checks with a known result, operand
types, docblock types, property defaults, unreachable code, missing types, offset access, and the
values that a foreach, a call, a match, a clone or a destructuring can't take. It also covers
the deprecation identifiers of phpstan-deprecation-rules.
PHPStan identifiers lists each identifier with its Mago codes.
Not dropped:
- phpstan-drupal's identifiers, which aren't in the list;
- the
drupal/andphpunit/checks. They report after Mago runs the plugin, so a comment never drops one of them; - the issues of linter rules. See Linter rules for the ones that port a PHPStan check.
An issue counts as being on the covered line when it starts there. Unreachable code is the one
exception. PHPStan reports the first unreachable statement of a block, and Mago reports every one of
them, so a comment that ignores deadCode.unreachable also drops Mago's unevaluated-code on the
lines after it, up to the end of its block. The block ends at its closing brace or at the endif,
endforeach or other end keyword of the alternative syntax. An alternative syntax else: or
elseif, and the next case or default label of a switch, end it too. When the covered line
holds a return, throw, exit, continue or break statement, the run starts at the statement
after it. So on a line such as if ($flag): return; echo 'a';, the run starts at the echo and
ends with the if block.
$this->markTestSkipped('Blocked by a core issue.');
// @phpstan-ignore deadCode.unreachable
$result = $this->build(); // no unevaluated-code
$this->assertSame('x', $result); // none here either
Pragmas¶
Mago matches @mago-expect pragmas before the plugin runs. So a pragma next to a @phpstan-ignore
for the same issue still counts as used: it can be removed, but Mago doesn't point it out.
Linter rules¶
Some linter rules port a PHPStan check, such as phpstan-drupal's RenderCallbackRule. The plugin
runs in the analyzer, so it can't drop their issues. With the --phpstan-ignores worker argument,
these rules read @phpstan-ignore comments themselves. It's off by default, as the plugin is, and
drupal-core.mago.toml turns it on. See The worker.
The comments cover the same lines as for the plugin. @phpstan-ignore-line and
@phpstan-ignore-next-line drop the issues of these rules, and an identifier drops the issues of
the rule listed with it:
drupal/discouraged-function:discouragedFunctions.discouragedFunctionCalleddrupal/render-callback:renderCallback.expectsArrayOfCallbacks,renderCallback.expectsCallableArrayWithArguments,renderCallback.nonTrustedCallbackdrupal/symfony-yaml-parse:drupal.symfonyYamlParsedrupal/test-class-suffix:nonAbstractTestClass.NameNoSuffixTestdrupal/todo-current-issue:drupal.todoCurrentIssuedrupal/weak-hash:disallowed.function
drupal/weak-hash ports the disallowed calls of core's phpstan.neon.dist, which
phpstan-disallowed-calls reports as disallowed.function. The other rules don't read
@phpstan-ignore comments. Unlike for the plugin, the issue is dropped before Mago sees it, so a
@mago-expect for it is reported as unused.