Skip to content

Sniffs from other standards

Coder's Drupal ruleset includes sniffs from PHP_CodeSniffer's own standards (Generic, PEAR, PSR2, Squiz and Zend) and from the Slevomat Coding Standard. The VariableAnalysis sniff is part of the DrupalPractice ruleset, on the DrupalPractice standard page.

Generic

Sniff Handled by
Generic.Arrays.DisallowLongArraySyntax Mago array-style
Generic.CodeAnalysis.EmptyPHPStatement drupal/empty-php-tags, Mago no-noop
Generic.CodeAnalysis.UselessOverridingMethod Mago no-redundant-method-override, partly
Generic.ControlStructures.InlineControlStructure Mago block-statement
Generic.Files.ByteOrderMark drupal/byte-order-mark
Generic.Files.LineEndings mago format
Generic.Formatting.DisallowMultipleStatements mago format
Generic.Formatting.SpaceAfterCast drupal/comment-in-expression, mago format
Generic.Functions.FunctionCallArgumentSpacing mago format
Generic.NamingConventions.ConstructorName drupal/old-style-constructor, mago analyze (non-existent-method), partly
Generic.NamingConventions.InterfaceNameSuffix Mago interface-name
Generic.NamingConventions.TraitNameSuffix Mago trait-name
Generic.NamingConventions.UpperCaseConstantName Mago constant-name, drupal/define-name
Generic.PHP.DeprecatedFunctions mago analyze (deprecated-function)
Generic.PHP.DisallowShortOpenTag drupal/short-echo-tag, Mago no-short-opening-tag
Generic.PHP.LowerCaseKeyword mago format, Mago lowercase-keyword
Generic.PHP.UpperCaseConstant mago format, drupal/literal-constant-case
Generic.Strings.UnnecessaryStringConcat Mago no-redundant-string-concat
Generic.WhiteSpace.DisallowTabIndent mago format, drupal/tab-character
Generic.WhiteSpace.LanguageConstructSpacing mago format, drupal/comment-in-expression, partly

Generic.Arrays.DisallowLongArraySyntax

Mago's rule, on by default, with a safe fix.

Generic.CodeAnalysis.EmptyPHPStatement

Codes Handled by
EmptyPHPOpenCloseTagsDetected drupal/empty-php-tags
SemicolonWithoutCodeDetected Mago no-noop

Generic.CodeAnalysis.UselessOverridingMethod

Mago's no-redundant-method-override reports only an override without parameters, and only when the parent call writes the method name in the same case. It compares a spread argument with a variadic parameter the wrong way round, so it misses an override that passes its parameters through, and reports one that spreads an array parameter, such as parent::foo(...$items).

Generic.ControlStructures.InlineControlStructure

Mago's rule reports a body without braces, with no fix. The formatter doesn't add braces. It moves the body to a line of its own. The rule also reports a loop or if whose body is a lone ;, such as while (next($items));, which Coder skips.

Generic.Formatting.SpaceAfterCast

Codes Handled by
CommentFound drupal/comment-in-expression
NoSpace, TooMuchSpace mago format

Generic.NamingConventions.ConstructorName

Codes Handled by
OldStyle drupal/old-style-constructor
OldStyleCall mago analyze (non-existent-method), partly
  • OldStyleCall: A call such as parent::Base() in a constructor. mago analyze reports the call that fails on PHP 8, when the parent doesn't have a method of that name. A call to a parent method of that name that exists works, and drupal/old-style-constructor reports that method where it's declared, unless the parent class also has __construct(). A parent class outside the scanned paths isn't reported.

Generic.NamingConventions.InterfaceNameSuffix

With interface-name = { psr = true }. Coder ignores case in the suffix, so it accepts Foointerface; Mago wants Interface. Mago also reports an interface name that isn't in class case, which Coder reports under Drupal.NamingConventions.ValidClassName.

Generic.NamingConventions.TraitNameSuffix

With trait-name = { psr = true }. Coder ignores case in the suffix, so it accepts Footrait; Mago wants Trait. Mago also reports a trait name that isn't in class case, which Coder reports under Drupal.NamingConventions.ValidClassName.

Generic.NamingConventions.UpperCaseConstantName

Codes Handled by
ClassConstantNotUpperCase Mago constant-name
ConstantNotUpperCase drupal/define-name
  • ClassConstantNotUpperCase: Mago's constant-name also reports an upper-case name with a leading, trailing or doubled underscore, such as A__B, which Coder accepts.

Generic.PHP.DeprecatedFunctions

phpcs takes the deprecated functions from the running PHP, and the analyzer from Mago's stubs. Mago's stubs for strptime(), zip_open(), zip_close() and six zip_entry_*() functions don't have a deprecation, so the analyzer doesn't report them. The analyzer also reports a function marked @deprecated in the codebase, and a call through a variable that holds a function name.

Generic.PHP.DisallowShortOpenTag

Codes Handled by
EchoFound drupal/short-echo-tag
Found, PossibleFound Mago no-short-opening-tag
  • Found: Coder reports <? only when PHP's short_open_tag is on. Mago always reports it. Mago's fix doesn't write a space after <?php, so <?echo 1; becomes <?phpecho 1;, which doesn't parse.
  • PossibleFound: Mago always reads <? as an opening tag, so a <? in HTML text that isn't PHP code gives parse errors.

Generic.PHP.LowerCaseKeyword

The formatter lowercases keywords. lowercase-keyword fixes AND, OR, XOR and INSTANCEOF, which the formatter keeps.

Generic.WhiteSpace.DisallowTabIndent

Codes Handled by
NonIndentTabsUsed, TabsUsed mago format, drupal/tab-character
TabsUsedHeredocCloser mago format

Generic.WhiteSpace.LanguageConstructSpacing

Codes Handled by
Incorrect, IncorrectYieldFrom mago format
IncorrectSingle mago format, partly
IncorrectYieldFromWithComment drupal/comment-in-expression
  • IncorrectSingle: The formatter can break a long expression right after echo, print, include, include_once, require or require_once, which Coder reports. It also puts new alone on its line before an anonymous class with attributes.

PEAR

Sniff Handled by
PEAR.Files.IncludingFile mago format
PEAR.Functions.FunctionCallSignature mago format
PEAR.Functions.ValidDefaultValue Mago optional-param-order

PEAR.Functions.ValidDefaultValue

Mago also reports a typed parameter with a null default before a required one, such as int $a = NULL, $b. Coder skips it, because before PHP 8 that was how a type allowed NULL. PHP 8.4 deprecates it. Coder also skips ?int $a = NULL, $b, which PHP 8.1 deprecates.

PSR2

Sniff Handled by
PSR2.Classes.PropertyDeclaration mago format, drupal/property-per-statement, drupal/property-visibility, drupal/property-name
PSR2.ControlStructures.ElseIfDeclaration drupal/else-if
PSR2.ControlStructures.SwitchDeclaration mago format, drupal/case-fall-through, Mago no-redundant-block, drupal/case-semicolon, partly
PSR2.Methods.MethodDeclaration mago format, drupal/method-name-underscore
PSR2.Namespaces.NamespaceDeclaration mago format
PSR2.Namespaces.UseDeclaration mago format, Mago semantics

PSR2.Classes.PropertyDeclaration

Codes Handled by
AbstractAfterVisibility, AvizKeywordOrder, FinalAfterVisibility, ReadonlyBeforeVisibility, SpacingAfterType, StaticBeforeVisibility mago format
Multiple drupal/property-per-statement
ScopeMissing drupal/property-visibility
Underscore drupal/property-name

PSR2.ControlStructures.SwitchDeclaration

Codes Handled by
BodyOnNextLineDEFAULT, BreakNotNewLine, caseNotLower, defaultNotLower, SpaceBeforeColonCASE, SpaceBeforeColonDEFAULT, SpacingAfterCase mago format
TerminatingComment drupal/case-fall-through
WrongOpener Mago no-redundant-block
WrongOpenercase, WrongOpenerdefault drupal/case-semicolon, partly
  • BreakNotNewLine: A keyword inside an expression, as in $x or exit();, stays where it is. phpcs reads it as the end of the case and keeps reporting it.
  • WrongOpener: case 1: {. Mago reports the braces as a redundant block.
  • WrongOpenercase: case 1;. Coder also reports case 1 ?>, which PHP accepts. Mago reports a parse error there and leaves that switch out. The other rules still report on the rest of the file, but mago lint --fix and mago format don't change a file with a parse error.
  • WrongOpenerdefault: default;. Coder also reports default ?>, which PHP accepts. Mago reports a parse error there and leaves that switch out. The other rules still report on the rest of the file, but mago lint --fix and mago format don't change a file with a parse error.

PSR2.Methods.MethodDeclaration

Codes Handled by
AbstractAfterVisibility, FinalAfterVisibility, StaticBeforeVisibility mago format
Underscore drupal/method-name-underscore

PSR2.Namespaces.UseDeclaration

Codes Handled by
MultipleDeclarations, SpaceAfterLastUse, SpaceAfterUse mago format
UseBeforeNamespace Mago semantics
  • UseBeforeNamespace: PHP refuses a use before the namespace, and Mago reports it as a semantic error.

Squiz

Sniff Handled by
Squiz.Arrays.ArrayBracketSpacing mago format
Squiz.Arrays.ArrayDeclaration mago format, nothing
Squiz.Classes.ClassFileName Mago file-name, Mago single-class-per-file, partly
Squiz.ControlStructures.ForEachLoopDeclaration mago format
Squiz.ControlStructures.ForLoopDeclaration mago format, partly
Squiz.ControlStructures.SwitchDeclaration mago format, drupal/case-label-line, drupal/empty-switch, Mago no-redundant-block, drupal/case-break-blank-line, nothing
Squiz.Functions.FunctionDeclarationArgumentSpacing mago format
Squiz.PHP.LowercasePHPFunctions mago analyze (incorrect-function-casing)
Squiz.PHP.NonExecutableCode drupal/redundant-return, mago analyze (unevaluated-code), mago analyze (useless-control-flow)
Squiz.Strings.ConcatenationSpacing mago format
Squiz.WhiteSpace.FunctionSpacing mago format, drupal/function-blank-line, partly
Squiz.WhiteSpace.OperatorSpacing mago format, partly
Squiz.WhiteSpace.ScopeKeywordSpacing mago format
Squiz.WhiteSpace.SemicolonSpacing mago format, Mago no-noop
Squiz.WhiteSpace.SuperfluousWhitespace mago format, drupal/file-start-whitespace

Squiz.Arrays.ArrayDeclaration

Codes Handled by
CommaAfterLast, NoSpaceAfterComma, NoSpaceAfterDoubleArrow, NoSpaceBeforeDoubleArrow, SpaceAfterComma, SpaceAfterDoubleArrow, SpaceAfterKeyword, SpaceBeforeComma, SpaceBeforeDoubleArrow, SpaceInEmptyArray mago format
KeySpecified, NoKeySpecified nothing
  • KeySpecified: An array over several lines whose first entry doesn't have a key and a later one has. Not ported. Core turns the code off, and the written standard's own array example, ['hello', 'world', 'foo' => 'bar'], mixes the two. Coder also takes the spread of an array element before a key, as in [...$x['k'], 'k' => 1], for an entry without a key.
  • NoKeySpecified: An array over several lines with an entry without a key after one with a key. Not ported. Core turns the code off, and the written standard's own array example, ['hello', 'world', 'foo' => 'bar'], mixes the two.

Squiz.Classes.ClassFileName

With file-name on and both rules excluding *Test.php and *TestBase.php under tests/<dir>/, as the configuration does and Coder's ruleset does. Mago reports at warning level, Coder at error. Core's own config runs Coder 8, whose sniff checks only the first class-like of a .php file.

file-name checks only a file with one class-like declaration. In a file with several, single-class-per-file reports every declaration after the first, whatever its name.

Squiz.ControlStructures.ForLoopDeclaration

Codes Handled by
NoSpaceAfterFirst, NoSpaceAfterSecond, SpacingBeforeFirst, SpacingBeforeSecond mago format
SpacingAfterFirst, SpacingAfterSecond mago format, partly
  • SpacingAfterFirst: The formatter puts each part of a long for header on its own line, and Coder reports the line break.
  • SpacingAfterSecond: The formatter puts each part of a long for header on its own line, and Coder reports the line break.

Squiz.ControlStructures.SwitchDeclaration

Codes Handled by
CaseNotLower, ContentAfterCase, ContentAfterDefault, ContentBeforeBreak, DefaultNotLower, SpacingAfterDefault mago format
ContentBeforeCase, ContentBeforeDefault mago format, drupal/case-label-line
MissingCase drupal/empty-switch
SpaceBeforeColonCase, SpaceBeforeColonDefault mago format, Mago no-redundant-block
SpacingAfterBreak drupal/case-break-blank-line
WrongOpenerCase, WrongOpenerDefault nothing
  • SpaceBeforeColonCase: The formatter removes the space before the colon. Coder also reports case 1: { under this code, and phpcbf doesn't fix it. Mago's no-redundant-block reports the braces, and doesn't have a fix either.
  • SpaceBeforeColonDefault: The formatter removes the space before the colon. Coder also reports default: { under this code, and phpcbf doesn't fix it. Mago's no-redundant-block reports the braces, and doesn't have a fix either.
  • WrongOpenerCase: case 1 ?>, which PHP accepts. Mago reports a parse error there and leaves that switch out. The other rules still report on the rest of the file, but mago lint --fix and mago format don't change a file with a parse error.
  • WrongOpenerDefault: default ?>, which PHP accepts. Mago reports a parse error there and leaves that switch out. The other rules still report on the rest of the file, but mago lint --fix and mago format don't change a file with a parse error.

Squiz.PHP.LowercasePHPFunctions

With check-name-casing = true. Reported without a fix. The analyzer skips a first-class callable such as STRLEN(...). It also reports a call to a function of the codebase whose case differs from the declaration, where Coder checks only PHP's own functions.

Squiz.PHP.NonExecutableCode

Codes Handled by
ReturnNotRequired drupal/redundant-return
Unreachable mago analyze (unevaluated-code), mago analyze (useless-control-flow)
  • Unreachable: A break; after return is useless-control-flow. The analyzer also reports code after an if and else that both exit, and code after an exit on the same line, which Coder skips.

Squiz.WhiteSpace.FunctionSpacing

Codes Handled by
After mago format
AfterLast, BeforeFirst mago format, partly
Before mago format, drupal/function-blank-line
  • AfterLast: The formatter removes the blank line between a function and the end of a block, such as if (!function_exists()) or a loop, which Coder reports.
  • Before: A function on the same line as a statement is reported without a fix. mago format splits the line, and the next mago lint --fix adds the blank line.
  • BeforeFirst: The formatter removes the blank line between the start of a block, such as if (!function_exists()) or a loop, and a function, which Coder reports.

Squiz.WhiteSpace.OperatorSpacing

Codes Handled by
NoSpaceAfter, NoSpaceBefore mago format, partly
NoSpaceAfterAmp, NoSpaceBeforeAmp, SpacingAfter, SpacingAfterAmp, SpacingBefore, SpacingBeforeAmp mago format
  • NoSpaceAfter: The formatter writes catch (A|B $e), which Coder reports.
  • NoSpaceBefore: The formatter writes catch (A|B $e), which Coder reports.

Squiz.WhiteSpace.SemicolonSpacing

The formatter puts an empty statement after a }, as in };, on a line of its own, which Coder reports. no-noop removes that statement.

Squiz.WhiteSpace.SuperfluousWhitespace

Codes Handled by
EmptyLines, EndFile, EndLine mago format
StartFile drupal/file-start-whitespace

Zend

Sniff Handled by
Zend.Files.ClosingTag mago format, Mago no-closing-tag, drupal/closing-tag-statement

Zend.Files.ClosingTag

The formatter removes a closing tag at the end of the file. When the tag ends the last statement, as in $a = 1 ?>, drupal/closing-tag-statement reports it and its fix writes the ;. Coder's ruleset skips *.tpl.php files, and so does that rule. Mago's rule and the formatter check them too.

Slevomat Coding Standard

Sniff Handled by
SlevomatCodingStandard.Classes.BackedEnumTypeSpacing mago format
SlevomatCodingStandard.Commenting.ForbiddenComments drupal/doc-comment
SlevomatCodingStandard.ControlStructures.NewWithParentheses mago format
SlevomatCodingStandard.ControlStructures.RequireNullCoalesceOperator drupal/null-coalesce
SlevomatCodingStandard.Namespaces.UnusedUses Mago no-redundant-use, drupal/doc-type-namespace, partly
SlevomatCodingStandard.Namespaces.UseDoesNotStartWithBackslash drupal/use-leading-backslash
SlevomatCodingStandard.Namespaces.UseFromSameNamespace Mago no-redundant-use, partly
SlevomatCodingStandard.PHP.ShortList drupal/short-list
SlevomatCodingStandard.TypeHints.DeclareStrictTypes mago format, drupal/file-comment
SlevomatCodingStandard.TypeHints.NullableTypeForNullDefaultValue drupal/explicit-nullable-param (below PHP 8.4), Mago explicit-nullable-param (PHP 8.4 and later)

SlevomatCodingStandard.Namespaces.UnusedUses

drupal/doc-type-namespace reports an import that only a docblock type uses by its short name. An import named only in the text of a comment, or only by its full name in a docblock, isn't reported.

SlevomatCodingStandard.Namespaces.UseFromSameNamespace

Mago also reports each name in a group import and each name after the first in a comma list. Coder skips those. Mago also reports an import whose namespace is written in another case, which Coder skips.

The fix of Mago's no-redundant-use doesn't remove the last name of a group import. A group with two names from the file's own namespace, such as use Drupal\mymod\{First, Second};, keeps Second, and both tools keep reporting it.

SlevomatCodingStandard.TypeHints.DeclareStrictTypes

Codes Handled by
IncorrectStrictTypesFormat, IncorrectWhitespaceAfterDeclare mago format
IncorrectWhitespaceBeforeDeclare mago format, drupal/file-comment

Sniffs added only by core

Core's phpcs.xml.dist runs four Slevomat sniffs left out of Coder's rulesets, and gives ForbiddenComments one more pattern. They apply to core, and to a project that copies core's configuration.

Sniff Handled by Notes
SlevomatCodingStandard.Commenting.ForbiddenAnnotations drupal/doc-comment, partly Core forbids @encode, @inheritDoc, @inheritdoc and @returns. drupal/doc-comment reports a bare @inheritdoc that opens a docblock, as Coder does. Nothing reports the other tags, or a bare @inheritdoc below a summary.
SlevomatCodingStandard.Commenting.ForbiddenComments Nothing Core's extra pattern rejects {@inheritDoc} with a capital D. Not ported.
SlevomatCodingStandard.ControlStructures.RequireShortTernaryOperator drupal/short-ternary The rule also reports a parenthesized condition, and operands that differ in quotes or comments.
SlevomatCodingStandard.Exceptions.RequireNonCapturingCatch drupal/non-capturing-catch The rule skips a function that may read the variable by a name built at run time, through compact(), get_defined_vars() or a variable variable.
SlevomatCodingStandard.PHP.TypeCast Mago deprecated-cast, partly Mago reports (integer), (boolean), (double) and the other long cast names only when php-version is 8.5 or later, where PHP deprecates them.