Suppressing issues
Fixing the underlying problem is almost always the right answer. Sometimes it isn't: legacy code, false positives, deliberate exceptions. For those cases, Mago has two pragma comments you put in the source: @mago-expect and @mago-ignore.
Both take the form category:code, with three categories available:
lint(aliaslinter) for linter issues.analysis(aliasesanalyzer,analyser) for analyzer issues.guardfor architectural guard issues.
Multiple codes can be suppressed at once with a comma-separated list, and a (N) count shorthand handles the case where the same code fires N times on one line.
@mago-expect
Asserts that a specific issue is expected on the line that follows. The strictest of the two pragmas, and the one we recommend by default.
// @mago-expect lint:no-shorthand-ternary
$result = $value ?: 'default';
Multiple codes:
// @mago-expect lint:no-shorthand-ternary,unused-variable
$result = $value ?: 'default';
If every expected code matches an actual issue, the issues are suppressed. If any expected code fails to match, Mago reports an unfulfilled-expect warning so the pragma does not silently linger after the underlying code is fixed.
@mago-ignore
Suppresses the listed codes on the following line or block, but does not warn loudly when the code is no longer being triggered. Mago still reports an unused-pragma note so you can clean it up, but only at note level rather than warning.
// @mago-ignore lint:no-shorthand-ternary
$result = $value ?: 'default';
Multiple codes work the same way:
// @mago-ignore lint:no-shorthand-ternary,no-assign-in-condition
if ($result = $value ?: 'default') {
// Do something with $result
}
Block-level suppression
When a pragma sits on the line before a block (function, class, if, …), it covers the whole block.
// @mago-ignore analysis:missing-return-statement
function foo(): string {
if (rand(0, 1)) {
return 'foo';
}
// No return statement here.
}
The same applies for multi-code lists:
// @mago-ignore analysis:missing-return-statement,unreachable-code
function foo(): string {
if (rand(0, 1)) {
return 'foo';
echo 'This code is unreachable';
}
}
Suppressing N occurrences
When a single line (or a block covered by a scoped pragma) trips the same code several times, repeating the code is tedious:
// @mago-expect analysis:mixed-operand,mixed-operand,mixed-operand
return $a . $b . $c;
Use the (N) shorthand instead:
// @mago-expect analysis:mixed-operand(3)
return $a . $b . $c;
N must be a positive integer. code(1) is equivalent to a plain code. Malformed suffixes like (0), (abc), or unbalanced parens are treated as part of the code name and will fail to match.
The count mixes with normal comma lists:
// @mago-expect analysis:mixed-operand(2),unused-variable
Unfulfilled counts
If fewer issues match than expected, Mago reports unfulfilled-expect and the auto-fix lowers the count rather than removing the directive (which would re-enable any issues that did match):
// Before: 3 matches expected, only 2 happened.
// @mago-expect analysis:mixed-operand(3)
return $a . $b;
// After auto-fix: count drops so the 2 real matches stay suppressed.
// @mago-expect analysis:mixed-operand(2)
return $a . $b;
Line vs block semantics
For line-level pragmas, a bare code suppresses up to one occurrence; (N) raises the cap to N.
For block-level (scoped) pragmas, a bare code suppresses every matching occurrence in the block. Adding (N) caps the suppression at N matches, so the N+1-th matching issue still gets reported. Useful when you want to make sure no more issues than expected creep in.
Suppressing every issue: all
The special all code suppresses everything at once. Use sparingly: it hides any new code that gets added later too.
Within a single category:
// @mago-ignore lint:all
$result = $value ?: ($x == true ? 'yes' : 'no');
// @mago-expect analysis:all
function legacy_code(): string {
if (rand(0, 1)) {
return 'foo';
}
}
Across every category:
// @mago-ignore all
$result = eval($value) ?: 'default';
In a docblock above a block, this covers the whole block:
/**
* @mago-ignore all
*/
function legacy_code(): string {
// Every linter, analyzer, and guard issue is suppressed here.
}
Prefer specific codes whenever you can. all is a blunt instrument that masks new issues you would otherwise want to see.
Picking between expect and ignore
@mago-expectis the right default. It guarantees you hear about the suppression once the underlying issue is fixed.@mago-ignoreis the lighter option for less critical suppressions or when you accept that the pragma may quietly outlive the issue.
Examples
// Suppress a guard issue
// @mago-expect guard:disallowed-use
use App\Infrastructure\SomeForbiddenClass;
// Suppress one lint issue
// @mago-expect lint:no-shorthand-ternary
$result = $condition ?: 'default';
// Suppress issues for an entire function
// @mago-expect analysis:missing-return-statement,impossible-condition
function complexFunction(): string {
if (false) {
return 'never reached';
}
}
// Three occurrences of one code on the next line
// @mago-expect analysis:mixed-operand(3)
return $a . $b . $c;
// All lint issues on one line
// @mago-ignore lint:all
$result = $value ?: ($x == true ? 'yes' : 'no');
// Everything, for a legacy function
// @mago-ignore all
function legacyFunction(): string {
// Everything suppressed here.
}