0.10
This release has been in the works for the past 5 months - it contains advancements on several fronts at once and I can't wait till you get your hands on it! It has the most new commits (over 500) of any PHPStan release ever, see this chart for comparison.
PHPStan 0.10 has been made possible by Auxmoney.com:
Auxmoney.com: PHPStan helps us to keep code quality on a high level and focus on the business that matters most for us. Keep going!
Also, my work on PHPStan is enabled by generous patrons over at Patreon. If PHPStan makes your life easier, consider a contribution, it'll be greatly appreciated!
Besides many new features and improvements to the core (which you can read about below), there were many improvements made over at related packages. See the release notes for phpstan-strict-rules and check out brand new package for detecting usage of @deprecated
elements - phpstan-deprecation-rules. Also, you should check out great 3rd party package from @pepakriz pepakriz/phpstan-exception-rules that enforces putting your exceptions into @throws
phpDoc tag and checks that you actually catch thrown exceptions from called functions!
Major new features
- Constant value types (#828), thanks @JanTvrdik!
- Big improvement to PHPStan's type system
- Enables recognizing not only types, but also values of expressions in cases where they're known
- For example:
- Format string for
sprintf()
can first be put into a variable and then used in a function call; the placeholders/arguments count mismatch will still be recognized - Specific types and values of accessed array offsets are now recognized (#409)
- PHPStan can recognize impossible comparisons of specific values, like
count($array) === 3
when there are only two items in the array - Results of arithmetic operations of literal values are also precisely calculated
- And many more improvements that make the analysis of your code much smarter!
- Format string for
- Typehints for built-in PHP functions (f486280, milestone link)
- Until 0.9 (including), PHPStan relied on built-in reflection which doesn't contain any typehint data at all, and is also full of inconsistencies
- PHPStan will finally tell you that you're passing wrong parameter types to PHP functions like
date
- It will also make use of documented return typehints
- The analysis can now be quite brutal - some PHP functions can return
false
in case of some rare error - this will make your analysis fail if you're on level 6 or 7. If you're overwhelmed by the number of reported errors, lower your level to 5 temporarily and fix the reported errors later.
- Type-specifying extensions (#825), thanks @lookyman!
- PHPStan can now recognize types after custom method calls like
assertInstanceOf
,assertInt
etc. - 1st party extensions for most common assertion libraries are available:
- Works with already available detections of always-true and impossible type comparisons
- Write your own type-specifying extensions for situations like
has
+nullableget
methods orsupports()
calls - see #201, #534, #634
- PHPStan can now recognize types after custom method calls like
- Improved callables support
- New check: Nonexistent and inaccessible array offsets - level 3 (d86efca)
- New check: Detect always truthy/falsey conditions - level 4 (689e956)
- Detects cases like:
if ($object) { }
if (DIRECTORY_SEPARATOR === '/' || DIRECTORY_SEPARATOR === '\\')
- New check: invalid arithmetic and binary operations - level 2 (2917336)
- Detects
$string + $string
,$int . $int
etc. - Detects non-numeric types on
+$expr
and-$expr
- Detects invalid types for
++
and--
operators - Also detects possible division by zero
- Detects
- New check: invalid casts - level 2 (4a72885)
- Detects
(string) $stdClass
or(int) $array
.
- Detects
- New check: validate types inside
@throws
phpDoc tag - level 2 (3d6904b) - #1001, thanks @Majkl578! - New check: validate types in
throw
keyword (44b4680) - #1041, thanks @pepakriz! - Concept of a benevolent union type in vein of gradual typing (8ee7c6e)
- For example array key type with mixed key will either be
int
orstring
-(int|string)
(benevolent union type is marked with additional parentheses around it) will not be reported when passed toint
andstring
even on the highest level because the code might be actually correct. But it will be reported when passed to a completely different type, likeobject
.
- For example array key type with mixed key will either be
- Changes to levels:
- Accepting types - moved partially correct union types checks from level 5 to level 6 (d514655)
- If method/property/constant surely does not exist on a union, report that on level 2 (previously reported on level 6) (9e38fd1)
- Reporting of accessing properties and methods on classes with magic methods (
__get
,__set
,__call
,__callStatic
) moved to level 1 (455fb7b)
Improvements
- Support for array access on objects with ArrayAccess interface (#620), thanks @pepakriz!
- Auto-discover
phpstan.neon{,.dist}
config files (#509), thanks @Majkl578! - Allow paths and level be specified in config (#508), thanks @Majkl578!
array_keys
,array_values
,array_merge
,array_fill
,array_fill_keys
,array_map
,array_pop
,array_shift
dynamic return type extensions (559b9d0, 40e1782, 9e97918, a063a42, 4779c7e, 5a6f3a2)- TypeSpecifier: support loose comparison with null (#833), thanks @JanTvrdik!
- Allow early terminating static calls (#822), thanks @ndench!
- Better support for accepting objects with
__toString()
as strings (043081b) - Result of
===
or!==
might be constant boolean (477b55d) - Result of
instanceof
might be constant boolean (00014ce) - Result of
is_*
functions might be a constant boolean type (f8c6ef0) - StrictComparisonOfDifferentTypesRule - check always true comparisons (off by default) (407146b) - enabled in phpstan-strict-rules
* Improve error message for command not found (#851), thanks @fain182! - sorting of file-specific
Error
entries by file name and line number (#838, #841) - thanks @Ocramius! - Implemented JSON formatter (#783), thanks @soullivaneuh!
- self, static and parent - consistent case-insensitive handling (27f084e)
- Use Composer/XdebugHandler to avoid performance penalty from Xdebug (#874), thanks @AJenbo!
- TypeSpecifier - support
instanceof parent
(af17140) reset()
dynamic return type extension (3485d8c)- Detect exception class name with wrong case in catch block (597bbed)
- Checking wrong function name case moved to strict-rules (4de98a1)
- Improved type detection in (object) cast (6231eb1)
- Fixed phpDocs interpretation when analyzing traits (9aaddbc) (#174)
- Added support for
is_scalar
type-specifying function (4abeceb) - Fixed resolving UnaryMinus type (c845439)
- Checking for invalid part of encapsed string (
"Foo $objectWithoutToString bar"
) - level 2 (5010703) - InstantiationRule - warn about incorrect case name when the class has no constructor (9a21518)
- Improved float, int and bool cast evaluation (6e2fc06)
min()
andmax()
dynamic return type extensions (58fe09f)is_subclass_of
type-specifying extension (4e1b2d8) - #889- Type-losing, although consistent behaviour of parameters passed by reference (711413f)
pathinfo()
dynamic return type extension (4d8c625)- Constant values for magic constants (b492ea8)
- Report and check return types of magic methods (71e120a)
- No need to update scope for the last node in sequence (8c3880f)
- Array with mixed key type have int|string iterable key type (0acbd53) - #956
- Improved support for anonymous classes (de7fd7d, f416740, 60a396e, 0319ed1, b29af42)
- Add API for
@deprecated
phpDoc tag (79ba741) - #690, thanks @iluuu1994! - Absolute paths in checkstyle error formatter - #550, thanks @mavimo!
- Group errors by file in checkstyle error formatter - #553, thanks @mavimo!
- Add API for
@throws
phpDoc tag - #994, thanks @pepakriz! microtime()
dynamic return type extension - #998, thanks @lookyman!- Run dynamic return extensions for all compound types (56f26a0) - #1002, thanks @CzechBoy!
strtotime()
dynamic return type extension - #1018, thanks @lookyman!- Check keys appended to arrays - level 3 (85753a3)
- AppendedArrayItemTypeRule - detect changed item type through assign ops (4b204ac)
- Annotated arrays are no longer checked, only when in properties (ad01d80) - #1032
range()
dynamic return type extension (40ece9a) - #1035, thanks @pepakriz!- Type::equals() for more efective scope merging (29b0d3a)
- Add support for non-truthy values filtering with array_filter (6c4bbce) - $877, thanks @fmasa!
- Registry: support multiple rules registered by a single class (1956c7f) - #1048, thanks @pepakriz!
- Redirect warnings and other unrelated messages to stderr (8962369) - #1040, #709, thanks @mavimo!
- Add
exclude_analyse
support for RobotLoader (0dfd9ab) - #1080, thanks @zviryatko! - do not compute elseif scope if there's no elseif nor else branch (dbb17a7)
substr_replace
dynamic return type extension (2092a46) - thanks @CzechBoy!
Bugfixes
- Scope: fix resolving
new parent(...)
expression type (3c576e0), thanks @JanTvrdik! - Closure uses passed by reference influence their type in outer scope (254a454)
- Fixed internal error when reading inheritDoc in a class with a native parent (4ab430b)
- Fixed condition filtering of ternary operator (ea47684) - #910, #914, #917
- Fixed loading autoload-file with relative path (5c32e0d) - #909
- ErrorSuppress - do not report
void
value usage (e6d3557) - #926 - Annotation methods - variadic parameter is always optional (8085989) - #936
- MixedType returns valid properties, methods and constants (eb8947d) - #935
- Prevent spreading ErrorType that causes excessive rule errors (8c9e127) - #925
- Variable assigned in a for loop condition definitely exists in the for loop body (f9a5ac4) - #894
- Fixed openssl_pkcs12_export - fifth parameter is optional (2ff582b) - #820, thanks @akondas!
- Scope knows about global variables (d062a23) - #823
- Fixed negated
is_numeric()
behaviour - cannot eliminate string (b2cbc04) - lookForAssigns for scope after while loop takes truthiness of while condition into account (05eee5a)
- Fixed detecting variadic method through func_get_args() from a trait (01035f3) - #37
- TypeCombinator - support removing array and Traversable from iterable (16ad9e5) - #992
- DOMNodeList and SimpleXMLElement are offset accessible even if they don't implement ArrayAccess (8af60f4)
- UnionType::hasMethod, hasProperty, hasConstant - filter all incompatible types (555a33c)
- With strict_types, string parameter does not accept object with
__toString()
(c379a16) - Fixed anonymous class name in trait (7ce6d92)
- NullType is offset accessible (dbaec2e) - #1051
- Fixed handling analysis with early termination in loops (ec9c04d, c32cc9c)
- Registry: fixed cache key (21f24fc) - #1074, thanks @pepakriz!
- StaticVar will always be mixed (f6f601f) - #930
- COMPILER_HALT_OFFSET undefined const false detection (ebce59a) - #353, thanks @avant1!
- Allow removing scalars from unions (2d62b9b)
BC breaks
BC breaks for extension developers
- Many changes on the Type interface thanks to cleanup, see #815, thanks @JanTvrdik!
- Removed
TrueBooleanType
andFalseBooleanType
in favour of ConstantBooleanType (#828), thanks @JanTvrdik! - You should make use of constant types - instead of checking for Scalar nodes, check for types from the
PHPStan\Type\Constant
namespace! MethodReflection::getPrototype()
can returnClassMemberReflection
, not fullMethodReflection
(8dd51d7)- Removed
ParameterReflection::isPassedByReference()
in favour ofpassedByReference()
withPassedByReference
object as typehint (80d731d) Type::describe()
hasVerbosityLevel
parameter (7d10e4f)Type::accepts()
now has$strict
parameter (c379a16)Type::accepts()
returns TrinaryLogic instead of boolean (7739f0e)- Removed
TypeCombinator::isUnionTypesEnabled()
, useRuleLevelHelper
instead (bcef526) MethodReflection
andFunctionReflection
do not longer implementParametersAcceptor
, instead they havegetVariants()
method. UseParametersAcceptorSelector
if you want to select the correct variant! (abb0eda)