1.0.0
PHPStan 1.0 is here and I'm really excited about it! Read the accompanying article on PHPStan's blog and also check out the merchandise we're selling for limited time (until November 22nd). It includes white and blue PHPStan t-shirts, PHPStan stickers, and also something very special: Rule level badges that you can pin to your clothes to show off that you care about code quality 😊
Major new features 🚀
- Level 9 with checkExplicitMixed (phpstan/phpstan-src@e5bbb52)
- Consistent remembering and forgetting returned values (phpstan/phpstan-src@d4edc59)
- Precise try-catch-finally analysis (phpstan/phpstan-src@4588e73)
- Validate overriding methods in stubs (phpstan/phpstan-src@c98d0a4)
- Nicer type descriptions usable in PHPDocs (phpstan/phpstan-src@03341cc, phpstan/phpstan-src@51d7431)
New rules
- Level 0
- Check leading and trailing file whitespace and BOM (phpstan/phpstan-src@6905d66)
- Check overriding constants (phpstan/phpstan-src@89acb0d)
- Check classes extending
@final
classes (phpstan/phpstan-src@dffd2c2), https://github.com/phpstan/phpstan/discussions/5343 - Check that function-scoped template type is in a parameter (phpstan/phpstan-src@18bdd34)
- Check overriding properties (phpstan/phpstan-src@0f4885a), #4281
- Level 1
- Rule for checking null-coalescing
??
operator issues (#36), thanks @leongersen!
- Rule for checking null-coalescing
- Level 2
- Detect wrong usage of
@var
PHPDoc tag (phpstan/phpstan-src@5886053) - Rules for accessing private class elements through
static::
(phpstan/phpstan-src@d8e8953, phpstan/phpstan-src@bad2607, phpstan/phpstan-src@270326a) - Class constants - incompatible PHPDoc types (phpstan/phpstan-src@780a54c)
- Cross-check generic interface implementations (phpstan/phpstan-src@284af50), #5222
- Detect wrong usage of
- Level 3
- Check that function with
@throws void
does not have an explicit throw point (phpstan/phpstan-src@8b3382a) - Check array deconstruction (phpstan/phpstan-src@aae34d9), #3267
- Check that function with
- Level 4
- Detect unused and write-only/read-only private properties, methods, and constants
- Rule for checking additional issues like always-defined/never-defined properties, array offsets etc. in
isset()
(phpstan/phpstan-src@25b61d9) empty()
rule (phpstan/phpstan-src@601460c), #970- While loop - detect always true and always false conditions (phpstan/phpstan-src@217fac3, phpstan/phpstan-src@fb3f83e)
- Do-while loop - detect always true and always false conditions (phpstan/phpstan-src@e81ccd4)
- Report dead catch with exception that is not thrown in the try block (phpstan/phpstan-src@ce9299c)
- Rule for detecting overwriting exit points in finally (phpstan/phpstan-src@3f712be)
- Level 5
- Check callable parameter types for
array_map()
andarray_filter()
calls (#555), #5609, #5356, #1954, thanks @BackEndTea! implode()
function rule (#679), thanks @staabm!- Check
DateTime
instantiation (#380), thanks @b1rdex! random_int()
dynamic return type extension and parameters rule (#99), thanks @cs278!
- Check callable parameter types for
- Level 6
- Detect unresolvable return type after generic function call (phpstan/phpstan-src@9070c5b), #2581
- Inspect types for missing typehints recursively (phpstan/phpstan-src@2f456b9), #5148
BC breaks for end-users
- Level
max
is now level 9. Feel free to updatemax
to8
if your code isn't ready. - Description of some types was updated to match the syntax in PHPDocs. This includes
numeric-string
(it was previously described asstring&numeric
), and also array shapes. - Removed
baselineNeon
error formatter, use--generate-baseline
CLI option instead (phpstan/phpstan-src@492cfbc) - Removed
polluteCatchScopeWithTryAssignments
config parameter (phpstan/phpstan-src@8933c7e) - Removed deprecated
autoload_files
parameter - use Discovering Symbols instead (phpstan/phpstan-src@7a21246) - Removed deprecated
autoload_directories
parameter - use Discovering Symbols instead (phpstan/phpstan-src@f67b48a) - Removed
bootstrap
parameter - usebootstrapFiles
instead (phpstan/phpstan-src@1baa294) - Moved
implicitThrows
configuration parameter toexceptions.implicitThrows
(phpstan/phpstan-src@96b7c48) - Removed
--paths-file
CLI option (phpstan/phpstan-src@5670cf2), #5756 - Removed
dump-deps
command (phpstan/phpstan-src@9c7017c) - Deprecated
excludes_analyse
option, useexcludePaths
instead (phpstan/phpstan-src@d25c5e5)
The following are interesting only if you create a custom ruleset in your configuration file:
- Removed
DeadCatchRule
, replaced byCatchWithUnthrownExceptionRule
(phpstan/phpstan-src@4dba60b) - Removed
VariableCertaintyInIssetRule
, replaced byIssetRule
(phpstan/phpstan-src@2e858de) - Removed
MissingClosureNativeReturnTypehintRule
, no longer needed thanks to type inference (phpstan/phpstan-src@1c34d8d) - Rename rules with typos (phpstan/phpstan-src@003ab1a)
BC breaks for extension developers
- Extensions are checked with rules for correct usage of PHPStan internals according to backward compatibility promise.
- Thanks to upgrading
nikic/php-parser
to version 4.13.0, you should now use->getArgs()
instead of->args
wherever possible.
* Helpful message about this change is also included in PHPStan itself: phpstan/phpstan-src@c836a42 PHPStan\Parser\Parser
service is no longer autowired. You need to choose the right instance for your needs and register it in thearguments
section of your service that needs the parser in the configuration. The Parser services you can choose from are:@defaultAnalysisParser
- the best choice if you're parsing files that are among the analysed files@currentPhpVersionSimpleDirectParser
- the closest choice to default behaviour from previous PHPStan versions- Read more about this here.
- Helpful message about this change is also included in PHPStan itself: phpstan/phpstan-src@038c7a5
- Removed
CompoundTypeHelper
(phpstan/phpstan-src@145c4e3) - Removed
CommentHelper
(phpstan/phpstan-src@ebad6f6) - Removed
DependencyDumper
(phpstan/phpstan-src@9c7017c) - Removed
PHPStan\Reflection\Generic\ResolvedFunctionVariant
, replaced byPHPStan\Reflection\ResolvedFunctionVariant
(phpstan/phpstan-src@1cc6c81) - Removed
ClassReflection::getNativeMethods()
, usegetNativeReflection()
instead (phpstan/phpstan-src@d2c1446) - Removed
PhpPropertyReflection::hasPhpDoc()
, replaced byhasPhpDocType()
(phpstan/phpstan-src@bedd5be) NodeDependencies
no longer iterable (phpstan/phpstan-src@f76875a)- Renamed
TestCase
toPHPStanTestCase
(#634), thanks @frankdejonge! StaticType
andThisType
- requireClassReflection
in constructor (phpstan/phpstan-src@7aabc84)PHPStanTestCase
- extensions can no longer be provided by overriding methods fromPHPStanTestCase
. UsegetAdditionalConfigFiles()
instead. (phpstan/phpstan-src@65efd93, phpstan/phpstan-src@239291a)- Removed some unused internal helper methods from Broker (phpstan/phpstan-src@d578151)
- Changed return types of various methods that had
|false
to|null
(phpstan/phpstan-src@629ccf6) - Type generalization precision is now a required argument (phpstan/phpstan-src@6568103)
- Some constructor parameters are now required (phpstan/phpstan-src@1f4062f)
- Deprecated
BrokerAwareExtension
(phpstan/phpstan-src@db2f7fb) - Deprecated
PHPStanTestCase::createBroker()
. UsecreateReflectionProvider()
instead. (phpstan/phpstan-src@1e5cf58) - Deprecated
PHPStan\Broker\Broker
. UsePHPStan\Reflection\ReflectionProvider
instead. (phpstan/phpstan-src@c775594) - Deprecated
PHPStan\Broker\Broker::getInstance()
. UsePHPStan\Reflection\ReflectionProviderStaticAccessor
instead. (phpstan/phpstan-src@4e7d60d) - Cannot create
IntersectionType
with less than two types (phpstan/phpstan-src@f7d232a) - Removed
ReflectionWithFilename
, useClassReflection|FunctionReflection
instead (phpstan/phpstan-src@3738fcd)
Improvements 🔧
- Performance optimizations
- use is_file() over file_exists(), which is faster (#724), thanks @staabm!
- faster IgnoredError->shouldIgnore() (#736), thanks @staabm!
- faster
FileHelper::normalizePath()
(#735), thanks @staabm! - faster
TypeCombinator::compareTypesInUnion()
(#742), thanks @voku! - faster
TypeCombinator::union()
(#743), thanks @voku! - faster
TypeCombinator::union()
v2 (#747), thanks @voku! - faster
TypeCombinator::intersect()
(#747), thanks @voku! - faster
TypeCombinator::remove()
(#746), thanks @voku! - TypeCombinator - call count() less often (phpstan/phpstan-src@f3c054b)
- TypeCombinator - eliminate same types before normalization (phpstan/phpstan-src@ac6a102)
- This caused bad memory leak (phpstan/phpstan-src@25cb765)
- Improve memory consumption (phpstan/phpstan-src@d781e34)
- FileExcluder: Improve performance of isExcludedFromAnalysing (#728), thanks @dktapps!
- Changing analysedPaths does not regenerate the DI container (phpstan/phpstan-src@27df5cf), #5825
- Do not clear old containers in worker processes (#733), #5825, thanks @dktapps!
- Always populate
analysedPathsFromConfig
(phpstan/phpstan-src@9f5f911), #5850
- Teach
IssetRule
everything whatVariableCertaintyInIssetRule
does (phpstan/phpstan-src@9689fbd), #970 MissingReturnRule
- make the error non-ignorable for native typehints (phpstan/phpstan-src@9ecefd5)get_class()
returnsfalse
for mixed argument types (phpstan/phpstan-src@e86742d), #4741- Require specifying template types for
RecursiveIterator
,RecursiveArrayIterator
,WeakMap
(phpstan/phpstan-src@0b92888) - Rewrite OptimizedDirectorySourceLocator to use PhpFileCleaner from Composer (phpstan/phpstan-src@b7bd0a9)
- Detect stub file added multiple times (phpstan/phpstan-src@4a82eec)
- Type inference of
new $string
leads toobject
, notmixed
(phpstan/phpstan-src@78a9f05) - Basic support for
interface-string
andtrait-string
(phpstan/phpstan-src@d0ef5d4) - Change message 'typehint' to 'type' and 'typehint type' to 'type'. (#270), thanks @Danack!
- IgnoredErrorHelper does not produce warnings, only errors (phpstan/phpstan-src@915fa2e)
- Support general array and array shape as template type bound (#673), thanks @drupol!
- TypeSpecifierContext - Do not create multiple equivalent objects (#677), thanks @jlherren!
- Distinguish circular type aliases from invalid type definitions (#678), thanks @jiripudil!
- more precise
SpecifiedTypes
phpdocs (#682), thanks @staabm - Resolve
PHP_INT_MAX
as positive integer (#684), thanks @herndlm! config.platform.php
in project'scomposer.json
is respected and overrides the current runtime PHP version (phpstan/phpstan-src@d235195)- Check LogicalOr and LogicalAnd constant conditions (phpstan/phpstan-src@40a76e8, phpstan/phpstan-src@ae9a558)
- Tip about template bound type when combined with a native type (phpstan/phpstan-src@5314a6b)
- define: case_insensitive is ignored, case-insensitive constants are no longer supported (#589), thanks @mglaman!
- NativeFunctionReflection deprecated support (#713), thanks @mglaman!
- ReturnTypeWillChange attribute class is always defined (phpstan/phpstan-src@c721459)
- Intersect array key type with
int|string
(phpstan/phpstan-src@724c8ba), #3753 - Inspect prefixed PHPDocs for invalid types recursively (phpstan/phpstan-src@003d235), #3723
- Inspect unresolvable types in PHPDoc recursively (phpstan/phpstan-src@1de5de8), #3753
- NameResolver -
preserveOriginalNames
set to true (phpstan/phpstan-src@2a9d1be) - Fixed PHP 8.1 deprecations (phpstan/phpstan-src@4e5ed5d, phpstan/phpstan-src@fd99879, phpstan/phpstan-src@9d0e070, phpstan/phpstan-src@458a8fb, phpstan/phpstan-src@50a7141)
- Analyser: do not report
E_DEPRECATED
(phpstan/phpstan-src@1a43385) - All FunctionReflection implementations have getFileName() (phpstan/phpstan-src@5ddca42)
Bugfixes 🐛
- MethodCall with Expr name adds an implicit throw point (phpstan/phpstan-src@84b0934)
- Fixed InterRangeType multiplication/division of maximas by a negative constant (#670), thanks @staabm!
Throwable::toString()
can throw an exception (phpstan/phpstan-src@18adc8c)- Fixed
new $object
with a template type (phpstan/phpstan-src@956a7f4) - Respect treatPhpDocAsCertain in IssetCheck (#674), thanks @VincentLanglet!
- Function that returns
never
is always an explicit throw point (phpstan/phpstan-src@c362fc5), #5627 - ObjectType - make class line part of the cache key (phpstan/phpstan-src@be27584), #5639
- eval function can throw exception (#676), thanks @canvural!
- Updated BetterReflection with trait fixes (phpstan/phpstan-src@1e717d7)
- Process do-while loop condition even if the loop always terminates (phpstan/phpstan-src@0837be4)
- Process attribute arguments recursively (phpstan/phpstan-src@0cfeb1b), #5651
- Set the correct method visibility when entering the method in regard to trait adaptation (phpstan/phpstan-src@c524c4e), #4516
- Fix unreachable code after do-while loop (phpstan/phpstan-src@d484ea8), #4370
- sprintf format string needs to be sanitized first (phpstan/phpstan-src@a2bdfd1), #5669
- Property assignment invalidates all remembered method values on an object (phpstan/phpstan-src@5f91da6), #5501
- Fix array_splice bugs (phpstan/phpstan-src@6754df5), #4743, #5017
- TypeCombinator - fix segfault (phpstan/phpstan-src@ac5fe1b), #5692
- Fixed integer range minus bugs (#690), thanks @staabm!
- Make array_map() accept null as first argument (phpstan/phpstan-src@84bafe7)
- RuleLevelHelper::findTypeToCheck - make null-safe shortcircuiting optional (#687), thanks @olsavmic!
- IntegerRangeMath: cover more maxima cases (#702), thanks @staabm!
- Update react/child-process (phpstan/phpstan-src@ca3aad0), #5709
- Variadic parameters in PHP8 can have int|string key (#725), thanks @canvural!
- Fix CompileCommand renaming PhpStormStubsMap on Windows (#732), thanks @dktapps!
+
-operator withnon-empty-array
should lead tonon-empty-array
(#739), thanks @staabm!
Function signature fixes 🤖
- Rename
$cmp_function
parameters to$callback
(phpstan/phpstan-src@27a5d0f) - Fix ext-ds.stub (#675), thanks @enumag!
- ext-ds: `Sequence::copy()! (phpstan/phpstan-src@2b51392), #5638
- mb_ereg_replace and mb_ereg_replace_callback can return null (#681), thanks @hbrecht!
- Update functionMap for SoapClient methods (#683) (#683), thanks @hbrecht!
- more precise func_* types (#697), thanks @staabm!
- use more precise types in file IO functions (#695), thanks @staabm!
- Added xdebug 3.1 functions "xdebug_notify" & "xdebug_connect_to_client" (#699), thanks @marc-mabe!
- Fix signature of ReflectionClass::setStaticPropertyValue() (#691), thanks @jlherren!
- mysqli_stmt_param_count() returns a non-negative int (#692), thanks @morozov!
- preg_match_all can return null (phpstan/phpstan-src@0d025e7)
- Add stub for mysqli_stmt properties (#700), thanks @morozov!
- Remove specific configuration for array_fill() with PHP 8 (#701), thanks @steevanb!
- SimpleXMLElement probably iterates over
static
(phpstan/phpstan-src@4653d15), #5700 exit()
status should be in the range 0 to 254 (#707), thanks @staabm!- functionMap: fix callable signature for sapi_windows_set_ctrl_handler() (#708), thanks @dktapps!
- More precise dirname signature (#712), thanks @staabm!
- More precise chunk_split signature (#711), thanks @staabm!
- More precise array_ unshift signature (#710), thanks @staabm!
- Document possible return type for PDO::lastInsertId() (#719), thanks @greg0ire!
- More precise json_* signature (#720), #5809, thanks @staabm!
- Implement ArrayAccess in ext-ds (#723), thanks @simPod!
- mysqli::fetch_fields does not return false (#731), thanks @kamil-tekiela!
- functionMap: fixed incorrect signatures for igbinary_serialize() and igbinary_unserialize() In particular, igbinary_serialize() may return null on error. (#737), thanks @staabm!