-**PhanPluginPrintfIncompatibleSpecifier**:`Formatstring{STRING_LITERAL}referstoargument#{INDEX}indifferentways:{DETAILS}`(e.g.`"%1$s of #%1$d"`.Maybeanoffbyoneerror.)
ThisisusefulforcasesPhandoesn'tcover(e.g.[Issue#449](https://github.com/phan/phan/issues/449) or [Issue #277](https://github.com/phan/phan/issues/277)).
Thispluginwarnsaboutusingphpdocannotationssuchas`@param`inblockcomments(`/*`) instead of phpdoc comments(`/**`).
This also warns about using `#` instead of `//` for line comments, because `#[` is used for php 8.0 attributes and will cause confusion.
- **PhanPluginPHPDocInWrongComment**: `Saw possible phpdoc annotation in ordinary block comment {COMMENT}. PHPDoc comments should start with "/**", not "/*"`
- **PhanPluginPHPDocHashComment**: `Saw comment starting with # in {COMMENT} - consider using // instead to avoid confusion with php 8.0 #[ attributes`
#### InvalidVariableIssetPlugin.php
Warns about invalid uses of `isset`. This README documentation may be inaccurate for this plugin.
- **PhanPluginInvalidVariableIsset** : Forces all uses of `isset` to be on arrays or variables.
E.g. it will warn about `isset(foo()['key'])`, because foo() is not a variable or an array access.
- **PhanUndeclaredVariable**: Warns if `$array` is undeclared in `isset($array[$key])`
#### NoAssertPlugin.php
Discourages the usage of assert() in the analyzed project.
See https://secure.php.net/assert
- **PhanPluginNoAssert**: `assert() is discouraged. Although phan supports using assert() for type annotations, PHP's documentation recommends assertions only for debugging, and assert() has surprising behaviors.`
#### NotFullyQualifiedUsagePlugin.php
Encourages the usage of fully qualified global functions and constants (slightly faster, especially for functions such as `strlen`, `count`, etc.)
- **PhanPluginNotFullyQualifiedFunctionCall**: `Expected function call to {FUNCTION}() to be fully qualified or have a use statement but none were found in namespace {NAMESPACE}`
- **PhanPluginNotFullyQualifiedOptimizableFunctionCall**: `Expected function call to {FUNCTION}() to be fully qualified or have a use statement but none were found in namespace {NAMESPACE} (opcache can optimize fully qualified calls to this function in recent php versions)`
- **PhanPluginNotFullyQualifiedGlobalConstant**: `Expected usage of {CONST} to be fully qualified or have a use statement but none were found in namespace {NAMESPACE}`
#### NumericalComparisonPlugin.php
Enforces that loose equality is used for numeric operands (e.g. `2 == 2.0`), and that strict equality is used for non-numeric operands (e.g. `"2" === "2e0"` is false).
- **PhanPluginNumericalComparison**: `nonnumerical values compared by the operators '==' or '!=='; numerical values compared by the operators '===' or '!=='`
#### StrictLiteralComparisonPlugin.php
Enforces that strict equality is used for comparisons to constant/literal integers or strings.
This is used to avoid surprising behaviors such as `0 == 'a'`, `"10" == "1e1"`, etc.
*Following the advice of this plugin may subtly break existing code (e.g. break implicit null/false checks, or code relying on these unexpected behaviors).*
- **PhanPluginComparisonNotStrictForScalar**: `Expected strict equality check when comparing {TYPE} to {TYPE} in {CODE}`
Also see [`StrictComparisonPlugin`](#StrictComparisonPlugin.php) and [`NumericalComparisonPlugin`](#NumericalComparisonPlugin.php).
#### PHPUnitNotDeadCodePlugin.php
Marks unit tests and dataProviders of subclasses of PHPUnit\Framework\TestCase as referenced.
Avoids false positives when `--dead-code-detection` is enabled.
(Does not emit any issue types)
#### SleepCheckerPlugin.php
Warn about returning non-arrays in [`__sleep`](https://secure.php.net/__sleep),
as well as about returning array values with invalid property names in `__sleep`.
- **SleepCheckerInvalidReturnStatement`**: `__sleep must return an array of strings. This is definitely not an array.`
- **SleepCheckerInvalidReturnType**: `__sleep is returning {TYPE}, expected string[]`
- **SleepCheckerInvalidPropNameType**: `__sleep is returning an array with a value of type {TYPE}, expected string`
- **SleepCheckerInvalidPropName**: `__sleep is returning an array that includes {PROPERTY}, which cannot be found`
- **SleepCheckerMagicPropName**: `__sleep is returning an array that includes {PROPERTY}, which is a magic property`
- **SleepCheckerDynamicPropName**: `__sleep is returning an array that includes {PROPERTY}, which is a dynamically added property (but not a declared property)`
- **SleepCheckerPropertyMissingTransient**: `Property {PROPERTY} that is not serialized by __sleep should be annotated with @transient or @phan-transient`,
#### UnknownElementTypePlugin.php
Warns about elements containing unknown types (function/method/closure return types, parameter types)
- **PhanPluginUnknownMethodReturnType**: `Method {METHOD} has no declared or inferred return type`
- **PhanPluginUnknownMethodParamType**: `Method {METHOD} has no declared or inferred parameter type for ${PARAMETER}`
- **PhanPluginUnknownFunctionReturnType**: `Function {FUNCTION} has no declared or inferred return type`
- **PhanPluginUnknownFunctionParamType**: `Function {FUNCTION} has no declared or inferred parameter type for ${PARAMETER}`
- **PhanPluginUnknownClosureReturnType**: `Closure {FUNCTION} has no declared or inferred return type`
- **PhanPluginUnknownClosureParamType**: `Closure {FUNCTION} has no declared or inferred parameter type for ${PARAMETER}`
- **PhanPluginUnknownPropertyType**: `Property {PROPERTY} has an initial type that cannot be inferred`
#### DuplicateExpressionPlugin.php
This plugin checks for duplicate expressions in a statement
that are likely to be a bug. (e.g. `expr1 == expr`)
This will significantly increase the memory used by Phan, but that's rarely an issue in small projects.
- **PhanPluginDuplicateExpressionAssignment**: `Both sides of the assignment {OPERATOR} are the same: {CODE}`
- **PhanPluginDuplicateExpressionBinaryOp**: `Both sides of the binary operator {OPERATOR} are the same: {CODE}`
- **PhanPluginDuplicateConditionalTernaryDuplication**: `"X ? X : Y" can usually be simplified to "X ?: Y". The duplicated expression X was {CODE}`
- **PhanPluginDuplicateConditionalNullCoalescing**: `"isset(X) ? X : Y" can usually be simplified to "X ?? Y" in PHP 7. The duplicated expression X was {CODE}`
- **PhanPluginBothLiteralsBinaryOp**: `Suspicious usage of a binary operator where both operands are literals. Expression: {CODE} {OPERATOR} {CODE} (result is {CODE})` (e.g. warns about `null == 'a literal` in `$x ?? null == 'a literal'`)
- **PhanPluginDuplicateConditionalUnnecessary**: `"X ? Y : Y" results in the same expression Y no matter what X evaluates to. Y was {CODE}`
- **PhanPluginDuplicateCatchStatementBody**: `The implementation of catch({CODE}) and catch({CODE}) are identical, and can be combined if the application only needs to supports php 7.1 and newer`
- **PhanPluginDuplicateAdjacentStatement**: `Statement {CODE} is a duplicate of the statement on the above line. Suppress this issue instance if there's a good reason for this.`
Note that equivalent catch statements may be deliberate or a coding style choice, and this plugin does not check for TODOs.
#### WhitespacePlugin.php
This plugin checks for unexpected whitespace in PHP files.
- **PhanPluginWhitespaceCarriageReturn**: `The first occurrence of a carriage return ("\r") was seen here. Running "dos2unix" can fix that.`
- **PhanPluginWhitespaceTab**: `The first occurrence of a tab was seen here. Running "expand" can fix that.`
- **PhanPluginWhitespaceTrailing**: `The first occurrence of trailing whitespace was seen here.`
#### InlineHTMLPlugin.php
This plugin checks for unexpected inline HTML.
This can be limited to a subset of files with an `inline_html_whitelist_regex` - e.g. `@^(src/|lib/)@`.
Files can be excluded with `inline_html_blacklist_regex`, e.g. `@(^src/templates/)|(\.html$)@`
- **PhanPluginInlineHTML**: `Saw inline HTML between the first and last token: {STRING_LITERAL}`
- **PhanPluginInlineHTMLLeading**: `Saw inline HTML at the start of the file: {STRING_LITERAL}`
- **PhanPluginInlineHTMLTrailing**: `Saw inline HTML at the end of the file: {STRING_LITERAL}`
#### SuspiciousParamOrderPlugin.php
This plugin guesses if arguments to a function call are out of order, based on heuristics on the name in the expression (e.g. variable name).
This will only warn if the argument types are compatible with the alternate parameters being suggested.
This may be useful when analyzing methods with long parameter lists.
E.g. warns about invoking `function example($first, $second, $third)` as `example($mySecond, $myThird, $myFirst)`
- **PhanPluginSuspiciousParamOrder**: `Suspicious order for arguments named {DETAILS} - These are being passed to parameters {DETAILS} of {FUNCTION} defined at {FILE}:{LINE}`
- **PhanPluginSuspiciousParamOrderInternal**: `Suspicious order for arguments named {DETAILS} - These are being passed to parameters {DETAILS}`
#### PossiblyStaticMethodPlugin.php
Checks if a method can be made static without causing any errors.
- **PhanPluginPossiblyStaticPublicMethod**: `Public method {METHOD} can be static` (Also exists for Private and Protected)
- **PhanPluginPossiblyStaticClosure**: `{FUNCTION} can be static`
Warnings may need to be completely disabled due to the large number of method declarations in a typical codebase:
- Warnings are not emitted for methods that override methods in the parent class.
- Warnings are not emitted for methods that are overridden in child classes.
- Warnings can be suppressed based on the method FQSEN with `plugin_config => [..., 'possibly_static_method_ignore_regex' => (a PCRE regex)]`
#### PHPDocToRealTypesPlugin.php
This plugin suggests real types that can be used instead of phpdoc types.
Currently, this just checks param and return types.
Some of the suggestions made by this plugin will cause inheritance errors.
This doesn't suggest changes if classes have subclasses (but this check doesn't work when inheritance involves traits).
`PHPDOC_TO_REAL_TYPES_IGNORE_INHERITANCE=1` can be used to force this to check **all** methods and emit issues.
This also supports `--automatic-fix` to add the types to the real type signatures.
- **PhanPluginCanUseReturnType**: `Can use {TYPE} as a return type of {METHOD}`
- **PhanPluginCanUseNullableReturnType**: `Can use {TYPE} as a return type of {METHOD}` (useful if there is a minimum php version of 7.1)
- **PhanPluginCanUsePHP71Void**: `Can use php 7.1's void as a return type of {METHOD}` (useful if there is a minimum php version of 7.1)
This supports `--automatic-fix`.
- `PHPDocRedundantPlugin` will be useful for cleaning up redundant phpdoc after real types were added.
- `PreferNamespaceUsePlugin` can be used to convert types from fully qualified types back to unqualified types ()
#### PHPDocRedundantPlugin.php
This plugin warns about function/method/closure phpdoc that does nothing but repeat the information in the type signature.
E.g. this will warn about `/** @return void */ function () : void {}` and `/** */`, but not `/** @return void description of what it does or other annotations */`
This supports `--automatic-fix`
- **PhanPluginRedundantFunctionComment**: `Redundant doc comment on function {FUNCTION}(). Either add a description or remove the comment: {COMMENT}`
- **PhanPluginRedundantMethodComment**: `Redundant doc comment on method {METHOD}(). Either add a description or remove the comment: {COMMENT}`
- **PhanPluginRedundantClosureComment**: `Redundant doc comment on closure {FUNCTION}. Either add a description or remove the comment: {COMMENT}`
- **PhanPluginRedundantReturnComment**: `Redundant @return {TYPE} on function {FUNCTION}. Either add a description or remove the @return annotation: {COMMENT}`
#### PreferNamespaceUsePlugin.php
This plugin suggests using `ClassName` instead of `\My\Ns\ClassName` when there is a `use My\Ns\ClassName` annotation (or for uses in namespace `\My\Ns`)
Currently, this only checks **real** (not phpdoc) param/return annotations.
- **PhanPluginPreferNamespaceUseParamType**: `Could write param type of ${PARAMETER} of {FUNCTION} as {TYPE} instead of {TYPE}`
- **PhanPluginPreferNamespaceUseReturnType**: `Could write return type of {FUNCTION} as {TYPE} instead of {TYPE}`
##### StrictComparisonPlugin.php
This plugin warns about non-strict comparisons. It warns about the following issue types:
1. Using `in_array` and `array_search` without explicitly passing true or false to `$strict`.
2. Using equality or comparison operators when both sides are possible objects.
- **PhanPluginComparisonNotStrictInCall**: `Expected {FUNCTION} to be called with a third argument for {PARAMETER} (either true or false)`
- **PhanPluginComparisonObjectEqualityNotStrict**: `Saw a weak equality check on possible object types {TYPE} and {TYPE} in {CODE}`
- **PhanPluginComparisonObjectOrdering**: `Saw a weak equality check on possible object types {TYPE} and {TYPE} in {CODE}`
##### EmptyMethodAndFunctionPlugin.php
This plugin looks for empty methods/functions.
Note that this is not emitted for empty statement lists in functions or methods that are overrides, are overridden, or are deprecated.
- **PhanEmptyClosure**: `Empty closure`
- **PhanEmptyFunction**: `Empty function {FUNCTION}`
- **PhanEmptyPublicMethod**: `Empty public method {METHOD}`
#### DollarDollarPlugin.php
Checks for complex variable access expressions `$$x`, which may be hard to read, and make the variable accesses hard/impossible to analyze.
- **PhanPluginDollarDollar**: Warns about the use of $$x, ${(expr)}, etc.
### DeprecateAliasPlugin.php
Makes Phan analyze aliases of global functions (e.g. `join()`, `sizeof()`) as if they were deprecated.
Supports `--automatic-fix`.
#### PHP53CompatibilityPlugin.php
Catches common incompatibilities from PHP 5.3 to 5.6.
**This plugin does not aim to be comprehensive - read the guides on https://www.php.net/manual/en/appendices.php if you need to migrate from php versions older than 5.6**
`InvokePHPNativeSyntaxCheckPlugin` with `'php_native_syntax_check_binaries' => [PHP_BINARY, '/path/to/php53']` in the `'plugin_config'` is a better but slower way to check that syntax used does not cause errors in PHP 5.3.
`backward_compatibility_checks` should also be enabled if migrating a project from php 5 to php 7.
Emitted issue types:
- **PhanPluginCompatibilityShortArray**: `Short arrays ({CODE}) require support for php 5.4+`
- **PhanPluginCompatibilityArgumentUnpacking**: `Argument unpacking ({CODE}) requires support for php 5.6+`
- **PhanPluginCompatibilityVariadicParam**: `Variadic functions ({CODE}) require support for php 5.6+`
#### DuplicateConstantPlugin.php
Checks for duplicate constant names for calls to `define()` or `const X =` within the same statement list.
- **PhanPluginDuplicateConstant**: `Constant {CONST} was previously declared at line {LINE} - the previous declaration will be used instead`
#### AvoidableGetterPlugin.php
This plugin checks for uses of getters on `$this` that can be avoided inside of a class.
(E.g. calling `$this->getFoo()` when the property `$this->foo` is accessible, and there are no known overrides of the getter)
- **PhanPluginAvoidableGetter**: `Can replace {METHOD} with {PROPERTY}`
- **PhanPluginAvoidableGetterInTrait**: `Can replace {METHOD} with {PROPERTY}`
Note that switching to properties makes the code slightly faster,
but may break code outside of the library that overrides those getters,
or hurt the readability of code.
This will also remove runtime type checks that were enforced by the getter's return type.
#### ConstantVariablePlugin.php
This plugin warns about using variables when they probably have only one possible scalar value (or the only inferred type is `null`).
This may catch some logic errors such as `echo($result === null ? json_encode($result) : 'default')`, or indicate places where it may or may not be clearer to use the constant itself.
Most of the reported issues will likely not be worth fixing, or be false positives due to references/loops.
- **PhanPluginConstantVariableBool**: `Variable ${VARIABLE} is probably constant with a value of {TYPE}`
- **PhanPluginConstantVariableNull**: `Variable ${VARIABLE} is probably constant with a value of {TYPE}`
- **PhanPluginConstantVariableScalar**: `Variable ${VARIABLE} is probably constant with a value of {TYPE}`
#### ShortArrayPlugin.php
This suggests using shorter array syntaxes if supported by the `minimum_target_php_version`.
- **PhanPluginLongArray**: `Should use [] instead of array()`
- **PhanPluginLongArrayList**: `Should use [] instead of list()`
#### RemoveDebugStatementPlugin.php
This suggests removing debugging output statements such as `echo`, `print`, `printf`, fwrite(STDERR)`, `var_export()`, inline html, etc.
This is only useful in applications or libraries that print output in only a few places, as a sanity check that debugging statements are not accidentally left in code.
- **PhanPluginRemoveDebugEcho**: `Saw output expression/statement in {CODE}`
- **PhanPluginRemoveDebugCall**: `Saw call to {FUNCTION} for debugging`
Suppression comments can use the issue name `PhanPluginRemoveDebugAny` to suppress all issue types emitted by this plugin.
#### AddNeverReturnTypePlugin.php
This plugin checks if a function or method will not return (and has no overrides).
If the function doesn't have a return type of never.
then this plugin will emit an issue.
Closures and short error functions are currently not checked
- **PhanPluginNeverReturnMethod**: `Method {METHOD} never returns and has a return type of {TYPE}, but phpdoc type {TYPE} could be used instead`
- **PhanPluginNeverReturnFunction**: `Function {FUNCTION} never returns and has a return type of {TYPE}, but phpdoc type {TYPE} could be used instead`
### 4. Demo plugins:
These files demonstrate plugins for Phan.
#### DemoPlugin.php
Look at this class's documentation if you want an example to base your plugin off of.
Generates the following issue types under the types:
- **DemoPluginClassName**: a declared class isn't called 'Class'
- **DemoPluginFunctionName**: a declared function isn't called `function`
- **DemoPluginMethodName**: a declared method isn't called `function`
PHP's default checks(`php -l` would catch the class/function name types.)
- **DemoPluginInstanceof**: codebase contains `(expr) instanceof object` (usually invalid, and `is_object()` should be used instead. That would actually be a check for `class object`).
### 5. Third party plugins
- https://github.com/Drenso/PhanExtensions is a third party project with several plugins to do the following:
- Analyze Symfony doc comment annotations.
- Mark elements in inline doc comments (which Phan doesn't parse) as referencing types from `use statements` as not dead code.
- https://github.com/TysonAndre/PhanTypoCheck checks all tokens of PHP files for typos, including within string literals.
It is also able to analyze calls to `gettext()`.
### 6. Self-analysis plugins:
#### PhanSelfCheckPlugin.php
This plugin checks for invalid calls to `PluginV2::emitIssue`, `Issue::maybeEmit()`, etc.
This is useful for developing Phan and Phan plugins.
- **PhanPluginTooFewArgumentsForIssue**: `Too few arguments for issue {STRING_LITERAL}: expected {COUNT}, got {COUNT}`
- **PhanPluginTooManyArgumentsForIssue**: `Too many arguments for issue {STRING_LITERAL}: expected {COUNT}, got {COUNT}`
- **PhanPluginUnknownIssueType**: `Unknown issue type {STRING_LITERAL} in a call to {METHOD}(). (may be a false positive - check if the version of Phan running PhanSelfCheckPlugin is the same version that the analyzed codebase is using)`