From 1ff9e3f367e44060193abea01f55f9440a912a3e Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Fri, 14 Mar 2025 09:19:37 +0100 Subject: [PATCH 1/7] Implement TypeSpecifierContext->getReturnType() --- src/Analyser/TypeSpecifier.php | 36 ++++++++++++++++----------- src/Analyser/TypeSpecifierContext.php | 15 +++++++++++ 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/src/Analyser/TypeSpecifier.php b/src/Analyser/TypeSpecifier.php index 1ef2230e45..62ee6867e5 100644 --- a/src/Analyser/TypeSpecifier.php +++ b/src/Analyser/TypeSpecifier.php @@ -333,21 +333,6 @@ public function specifyTypesInCondition( } } - if ( - !$context->null() - && $expr->right instanceof FuncCall - && count($expr->right->getArgs()) >= 3 - && $expr->right->name instanceof Name - && in_array(strtolower((string) $expr->right->name), ['preg_match'], true) - && IntegerRangeType::fromInterval(0, null)->isSuperTypeOf($leftType)->yes() - ) { - return $this->specifyTypesInCondition( - $scope, - new Expr\BinaryOp\NotIdentical($expr->right, new ConstFetch(new Name('false'))), - $context, - )->setRootExpr($expr); - } - if ( !$context->null() && $expr->right instanceof FuncCall @@ -468,6 +453,27 @@ public function specifyTypesInCondition( } } + if ( + !$context->null() + && $expr->left instanceof Node\Scalar + && $expr->right instanceof Expr\FuncCall + && $expr->right->name instanceof Name + && in_array(strtolower((string) $expr->right->name), ['preg_match'], true) + ) { + if (!$scope instanceof MutatingScope) { + throw new ShouldNotHappenException(); + } + $newScope = $scope->filterBySpecifiedTypes($result); + $callType = $newScope->getType($expr->right); + $newContext = $context->newWithReturnType($callType); + + $result = $result->unionWith($this->specifyTypesInCondition( + $scope, + $expr->right, + $newContext, + )->setRootExpr($expr)); + } + return $result; } elseif ($expr instanceof Node\Expr\BinaryOp\Greater) { diff --git a/src/Analyser/TypeSpecifierContext.php b/src/Analyser/TypeSpecifierContext.php index fe09aa861c..f8f9c63891 100644 --- a/src/Analyser/TypeSpecifierContext.php +++ b/src/Analyser/TypeSpecifierContext.php @@ -3,6 +3,7 @@ namespace PHPStan\Analyser; use PHPStan\ShouldNotHappenException; +use PHPStan\Type\Type; /** * @api @@ -21,6 +22,8 @@ final class TypeSpecifierContext /** @var self[] */ private static array $registry; + private ?Type $returnType = null; + private function __construct(private ?int $value) { } @@ -89,4 +92,16 @@ public function null(): bool return $this->value === null; } + public function newWithReturnType(Type $type): self + { + $new = self::create($this->value); + $new->returnType = $type; + return $new; + } + + public function getReturnType(): ?Type + { + return $this->returnType; + } + } From bab39b2c1f6e7bd14a41a82cd7e3c7bb6cab6cd0 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Fri, 14 Mar 2025 10:26:41 +0100 Subject: [PATCH 2/7] Refactor code into StrlenTypeSpecifyingExtension --- conf/config.neon | 1186 +++++++++++++++++ src/Analyser/TypeSpecifier.php | 28 +- .../Php/StrlenTypeSpecifyingExtension.php | 67 + tests/PHPStan/Analyser/nsrt/narrow-cast.php | 4 +- 4 files changed, 1256 insertions(+), 29 deletions(-) create mode 100644 src/Type/Php/StrlenTypeSpecifyingExtension.php diff --git a/conf/config.neon b/conf/config.neon index 65cda918e7..04a6362c41 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -250,3 +250,1189 @@ services: # like #[PHPStan\DependencyInjection\AutowiredService] or #[PHPStan\DependencyInjection\GenerateFactory] # non-autowired services are now registered in services.neon + - + class: PHPStan\Rules\Properties\PropertyDescriptor + + - + class: PHPStan\Rules\Properties\PropertyReflectionFinder + + - + class: PHPStan\Rules\Pure\FunctionPurityCheck + + - + class: PHPStan\Rules\RuleLevelHelper + arguments: + checkNullables: %checkNullables% + checkThisOnly: %checkThisOnly% + checkUnionTypes: %checkUnionTypes% + checkExplicitMixed: %checkExplicitMixed% + checkImplicitMixed: %checkImplicitMixed% + checkBenevolentUnionTypes: %checkBenevolentUnionTypes% + discoveringSymbolsTip: %tips.discoveringSymbols% + + - + class: PHPStan\Rules\UnusedFunctionParametersCheck + arguments: + reportExactLine: %featureToggles.reportPreciseLineForUnusedFunctionParameter% + + - + class: PHPStan\Rules\TooWideTypehints\TooWideParameterOutTypeCheck + + - + class: PHPStan\Type\FileTypeMapper + arguments: + phpParser: @defaultAnalysisParser + + stubFileTypeMapper: + class: PHPStan\Type\FileTypeMapper + arguments: + phpParser: @stubParser + autowired: false + + - + class: PHPStan\Type\TypeAliasResolver + factory: PHPStan\Type\UsefulTypeAliasResolver + arguments: + globalTypeAliases: %typeAliases% + + - + class: PHPStan\Type\TypeAliasResolverProvider + factory: PHPStan\Type\LazyTypeAliasResolverProvider + + - + class: PHPStan\Type\BitwiseFlagHelper + + - + class: PHPStan\Type\Php\AbsFunctionDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ArgumentBasedFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ArrayChangeKeyCaseFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ArrayIntersectKeyFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ArrayChunkFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ArrayColumnHelper + + - + class: PHPStan\Type\Php\ArrayColumnFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ArrayCombineFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ArrayCurrentDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ArrayFillFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ArrayFillKeysFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ArrayFilterFunctionReturnTypeHelper + + - + class: PHPStan\Type\Php\ArrayFilterFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ArrayFlipFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ArrayFindFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ArrayFindKeyFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ArrayKeyDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ArrayKeyExistsFunctionTypeSpecifyingExtension + tags: + - phpstan.typeSpecifier.functionTypeSpecifyingExtension + + - + class: PHPStan\Type\Php\ArrayKeyFirstDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ArrayKeyLastDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ArrayKeysFunctionDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ArrayMapFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ArrayMergeFunctionDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ArrayNextDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ArrayPopFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ArrayRandFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ArrayReduceFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ArrayReplaceFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ArrayReverseFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ArrayShiftFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ArraySliceFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ArraySpliceFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ArraySearchFunctionDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ArraySearchFunctionTypeSpecifyingExtension + tags: + - phpstan.typeSpecifier.functionTypeSpecifyingExtension + + - + class: PHPStan\Type\Php\ArrayValuesFunctionDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ArraySumFunctionDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\AssertThrowTypeExtension + tags: + - phpstan.dynamicFunctionThrowTypeExtension + + - + class: PHPStan\Type\Php\BackedEnumFromMethodDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicStaticMethodReturnTypeExtension + + - + class: PHPStan\Type\Php\Base64DecodeDynamicFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\BcMathStringOrNullReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ClosureBindDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicStaticMethodReturnTypeExtension + + - + class: PHPStan\Type\Php\ClosureBindToDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + + - + class: PHPStan\Type\Php\ClosureFromCallableDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicStaticMethodReturnTypeExtension + + - + class: PHPStan\Type\Php\CompactFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + arguments: + checkMaybeUndefinedVariables: %checkMaybeUndefinedVariables% + + - + class: PHPStan\Type\Php\ConstantFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ConstantHelper + + - + class: PHPStan\Type\Php\CountFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\CountCharsFunctionDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\CountFunctionTypeSpecifyingExtension + tags: + - phpstan.typeSpecifier.functionTypeSpecifyingExtension + + - + class: PHPStan\Type\Php\CurlGetinfoFunctionDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\DateFunctionReturnTypeHelper + + - + class: PHPStan\Type\Php\DateFormatFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\DateFormatMethodReturnTypeExtension + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + + - + class: PHPStan\Type\Php\DateFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\DateIntervalConstructorThrowTypeExtension + tags: + - phpstan.dynamicStaticMethodThrowTypeExtension + + - + class: PHPStan\Type\Php\DateIntervalDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicStaticMethodReturnTypeExtension + + - + class: PHPStan\Type\Php\DateTimeCreateDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\DateTimeDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\DateTimeModifyReturnTypeExtension + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + arguments: + dateTimeClass: DateTime + + - + class: PHPStan\Type\Php\DateTimeModifyReturnTypeExtension + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + arguments: + dateTimeClass: DateTimeImmutable + + - + class: PHPStan\Type\Php\DateTimeConstructorThrowTypeExtension + tags: + - phpstan.dynamicStaticMethodThrowTypeExtension + + - + class: PHPStan\Type\Php\DateTimeModifyMethodThrowTypeExtension + tags: + - phpstan.dynamicMethodThrowTypeExtension + + - + class: PHPStan\Type\Php\DateTimeSubMethodThrowTypeExtension + tags: + - phpstan.dynamicMethodThrowTypeExtension + + - + class: PHPStan\Type\Php\DateTimeZoneConstructorThrowTypeExtension + tags: + - phpstan.dynamicStaticMethodThrowTypeExtension + + - + class: PHPStan\Type\Php\DsMapDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + + - + class: PHPStan\Type\Php\DsMapDynamicMethodThrowTypeExtension + tags: + - phpstan.dynamicMethodThrowTypeExtension + + - + class: PHPStan\Type\Php\DioStatDynamicFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ExplodeFunctionDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\FilterFunctionReturnTypeHelper + + - + class: PHPStan\Type\Php\FilterInputDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\FilterVarDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\FilterVarArrayDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\GetCalledClassDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\GetClassDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\GetDebugTypeFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\GetDefinedVarsFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\GetParentClassDynamicFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\GettypeFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\GettimeofdayDynamicFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + - + class: PHPStan\Type\Php\HashFunctionsReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\HighlightStringDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\IntdivThrowTypeExtension + tags: + - phpstan.dynamicFunctionThrowTypeExtension + + - + class: PHPStan\Type\Php\IniGetReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\JsonThrowTypeExtension + tags: + - phpstan.dynamicFunctionThrowTypeExtension + + - + class: PHPStan\Type\Php\OpenSslEncryptParameterOutTypeExtension + tags: + - phpstan.functionParameterOutTypeExtension + + - + class: PHPStan\Type\Php\ParseStrParameterOutTypeExtension + tags: + - phpstan.functionParameterOutTypeExtension + + - + class: PHPStan\Type\Php\PregMatchTypeSpecifyingExtension + tags: + - phpstan.typeSpecifier.functionTypeSpecifyingExtension + + - + class: PHPStan\Type\Php\PregMatchParameterOutTypeExtension + tags: + - phpstan.functionParameterOutTypeExtension + + - + class: PHPStan\Type\Php\PregReplaceCallbackClosureTypeExtension + tags: + - phpstan.functionParameterClosureTypeExtension + + - + class: PHPStan\Type\Php\RegexArrayShapeMatcher + + - + class: PHPStan\Type\Regex\RegexGroupParser + + - + class: PHPStan\Type\Regex\RegexExpressionHelper + + - + class: PHPStan\Type\Php\ReflectionClassConstructorThrowTypeExtension + tags: + - phpstan.dynamicStaticMethodThrowTypeExtension + + - + class: PHPStan\Type\Php\ReflectionFunctionConstructorThrowTypeExtension + tags: + - phpstan.dynamicStaticMethodThrowTypeExtension + + - + class: PHPStan\Type\Php\ReflectionMethodConstructorThrowTypeExtension + tags: + - phpstan.dynamicStaticMethodThrowTypeExtension + + - + class: PHPStan\Type\Php\ReflectionPropertyConstructorThrowTypeExtension + tags: + - phpstan.dynamicStaticMethodThrowTypeExtension + + - + class: PHPStan\Type\Php\StrContainingTypeSpecifyingExtension + tags: + - phpstan.typeSpecifier.functionTypeSpecifyingExtension + + - + class: PHPStan\Type\Php\SimpleXMLElementClassPropertyReflectionExtension + tags: + - phpstan.broker.propertiesClassReflectionExtension + + - + class: PHPStan\Type\Php\SimpleXMLElementConstructorThrowTypeExtension + tags: + - phpstan.dynamicStaticMethodThrowTypeExtension + + - + class: PHPStan\Type\Php\StatDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + - phpstan.broker.dynamicMethodReturnTypeExtension + + - + class: PHPStan\Type\Php\MethodExistsTypeSpecifyingExtension + tags: + - phpstan.typeSpecifier.functionTypeSpecifyingExtension + + - + class: PHPStan\Type\Php\PropertyExistsTypeSpecifyingExtension + tags: + - phpstan.typeSpecifier.functionTypeSpecifyingExtension + + - + class: PHPStan\Type\Php\MinMaxFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\NumberFormatFunctionDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\PathinfoFunctionDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\PregFilterFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\PregSplitDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ReflectionClassIsSubclassOfTypeSpecifyingExtension + tags: + - phpstan.typeSpecifier.methodTypeSpecifyingExtension + + - + class: PHPStan\Type\Php\ReplaceFunctionsDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ArrayPointerFunctionsDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\LtrimFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\MbFunctionsReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\MbConvertEncodingFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\MbSubstituteCharacterDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\MbStrlenFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\MicrotimeFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\HrtimeFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ImplodeFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\NonEmptyStringFunctionsReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\SetTypeFunctionTypeSpecifyingExtension + tags: + - phpstan.typeSpecifier.functionTypeSpecifyingExtension + + - + class: PHPStan\Type\Php\StrCaseFunctionsReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\StrlenTypeSpecifyingExtension + tags: + - phpstan.typeSpecifier.functionTypeSpecifyingExtension + + - + class: PHPStan\Type\Php\StrlenFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\StrIncrementDecrementFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\StrPadFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\StrRepeatFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\SubstrDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\ThrowableReturnTypeExtension + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + + - + class: PHPStan\Type\Php\ParseUrlFunctionDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\TriggerErrorDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\TrimFunctionDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\VersionCompareFunctionDynamicReturnTypeExtension + arguments: + configPhpVersion: %phpVersion% + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\PowFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\RoundFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\StrtotimeFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\RandomIntFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\RangeFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\AssertFunctionTypeSpecifyingExtension + tags: + - phpstan.typeSpecifier.functionTypeSpecifyingExtension + + - + class: PHPStan\Type\Php\ClassExistsFunctionTypeSpecifyingExtension + tags: + - phpstan.typeSpecifier.functionTypeSpecifyingExtension + + - + class: PHPStan\Type\Php\ClassImplementsFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\DefineConstantTypeSpecifyingExtension + tags: + - phpstan.typeSpecifier.functionTypeSpecifyingExtension + + - + class: PHPStan\Type\Php\DefinedConstantTypeSpecifyingExtension + tags: + - phpstan.typeSpecifier.functionTypeSpecifyingExtension + + - + class: PHPStan\Type\Php\FunctionExistsFunctionTypeSpecifyingExtension + tags: + - phpstan.typeSpecifier.functionTypeSpecifyingExtension + + - + class: PHPStan\Type\Php\InArrayFunctionTypeSpecifyingExtension + tags: + - phpstan.typeSpecifier.functionTypeSpecifyingExtension + + - + class: PHPStan\Type\Php\IsArrayFunctionTypeSpecifyingExtension + tags: + - phpstan.typeSpecifier.functionTypeSpecifyingExtension + + - + class: PHPStan\Type\Php\IsCallableFunctionTypeSpecifyingExtension + tags: + - phpstan.typeSpecifier.functionTypeSpecifyingExtension + + - + class: PHPStan\Type\Php\IsIterableFunctionTypeSpecifyingExtension + tags: + - phpstan.typeSpecifier.functionTypeSpecifyingExtension + + - + class: PHPStan\Type\Php\IsSubclassOfFunctionTypeSpecifyingExtension + tags: + - phpstan.typeSpecifier.functionTypeSpecifyingExtension + + - + class: PHPStan\Type\Php\IteratorToArrayFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\IsAFunctionTypeSpecifyingExtension + tags: + - phpstan.typeSpecifier.functionTypeSpecifyingExtension + + - + class: PHPStan\Type\Php\IsAFunctionTypeSpecifyingHelper + + - + class: PHPStan\Type\Php\CtypeDigitFunctionTypeSpecifyingExtension + tags: + - phpstan.typeSpecifier.functionTypeSpecifyingExtension + + - + class: PHPStan\Type\Php\JsonThrowOnErrorDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\TypeSpecifyingFunctionsDynamicReturnTypeExtension + arguments: + treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain% + universalObjectCratesClasses: %universalObjectCratesClasses% + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\SimpleXMLElementAsXMLMethodReturnTypeExtension + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + + - + class: PHPStan\Type\Php\SimpleXMLElementXpathMethodReturnTypeExtension + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + + - + class: PHPStan\Type\Php\StrSplitFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\StrTokFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\SprintfFunctionDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\SscanfFunctionDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\StrvalFamilyFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\StrWordCountFunctionDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + + - + class: PHPStan\Type\Php\XMLReaderOpenReturnTypeExtension + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + - phpstan.broker.dynamicStaticMethodReturnTypeExtension + + - + class: PHPStan\Type\Php\ReflectionGetAttributesMethodReturnTypeExtension + arguments: + className: ReflectionClass + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + + - + class: PHPStan\Type\Php\ReflectionGetAttributesMethodReturnTypeExtension + arguments: + className: ReflectionClassConstant + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + + - + class: PHPStan\Type\Php\ReflectionGetAttributesMethodReturnTypeExtension + arguments: + className: ReflectionFunctionAbstract + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + + - + class: PHPStan\Type\Php\ReflectionGetAttributesMethodReturnTypeExtension + arguments: + className: ReflectionParameter + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + + - + class: PHPStan\Type\Php\ReflectionGetAttributesMethodReturnTypeExtension + arguments: + className: ReflectionProperty + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + + - + class: PHPStan\Type\Php\DatePeriodConstructorReturnTypeExtension + tags: + - phpstan.broker.dynamicStaticMethodReturnTypeExtension + + - + class: PHPStan\Type\PHPStan\ClassNameUsageLocationCreateIdentifierDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + - + class: PHPStan\Type\ClosureTypeFactory + arguments: + parser: @currentPhpVersionPhpParser + + - + class: PHPStan\Type\Constant\OversizedArrayBuilder + + - + class: PHPStan\Rules\Functions\PrintfHelper + + exceptionTypeResolver: + class: PHPStan\Rules\Exceptions\ExceptionTypeResolver + factory: @PHPStan\Rules\Exceptions\DefaultExceptionTypeResolver + + typeSpecifier: + class: PHPStan\Analyser\TypeSpecifier + factory: @typeSpecifierFactory::create + + typeSpecifierFactory: + class: PHPStan\Analyser\TypeSpecifierFactory + + relativePathHelper: + class: PHPStan\File\RelativePathHelper + factory: PHPStan\File\FuzzyRelativePathHelper + arguments: + currentWorkingDirectory: %currentWorkingDirectory% + analysedPaths: %analysedPaths% + fallbackRelativePathHelper: @parentDirectoryRelativePathHelper + + simpleRelativePathHelper: + class: PHPStan\File\RelativePathHelper + factory: PHPStan\File\SimpleRelativePathHelper + arguments: + currentWorkingDirectory: %currentWorkingDirectory% + autowired: false + + parentDirectoryRelativePathHelper: + class: PHPStan\File\ParentDirectoryRelativePathHelper + arguments: + parentDirectory: %currentWorkingDirectory% + autowired: false + + cacheStorage: + class: PHPStan\Cache\FileCacheStorage + arguments: + directory: %tmpDir%/cache/PHPStan + autowired: no + + currentPhpVersionRichParser: + class: PHPStan\Parser\RichParser + arguments: + parser: @currentPhpVersionPhpParser + autowired: no + + currentPhpVersionSimpleParser: + class: PHPStan\Parser\CleaningParser + arguments: + wrappedParser: @currentPhpVersionSimpleDirectParser + autowired: no + + currentPhpVersionSimpleDirectParser: + class: PHPStan\Parser\SimpleParser + arguments: + parser: @currentPhpVersionPhpParser + autowired: no + + defaultAnalysisParser: + class: PHPStan\Parser\CachedParser + arguments: + originalParser: @pathRoutingParser + cachedNodesByStringCountMax: %cache.nodesByStringCountMax% + autowired: false + + phpParserDecorator: + class: PHPStan\Parser\PhpParserDecorator + arguments: + wrappedParser: @defaultAnalysisParser + autowired: false + + currentPhpVersionLexer: + class: PhpParser\Lexer + factory: @PHPStan\Parser\LexerFactory::create() + autowired: false + + currentPhpVersionPhpParser: + factory: @currentPhpVersionPhpParserFactory::create() + autowired: false + + currentPhpVersionPhpParserFactory: + class: PHPStan\Parser\PhpParserFactory + arguments: + lexer: @currentPhpVersionLexer + autowired: false + + registry: + class: PHPStan\Rules\LazyRegistry + autowired: + - PHPStan\Rules\Registry + + stubPhpDocProvider: + class: PHPStan\PhpDoc\StubPhpDocProvider + arguments: + parser: @stubParser + fileTypeMapper: @stubFileTypeMapper + + # Reflection providers + + reflectionProviderFactory: + class: PHPStan\Reflection\ReflectionProvider\ReflectionProviderFactory + arguments: + staticReflectionProvider: @betterReflectionProvider + + reflectionProvider: + factory: @PHPStan\Reflection\ReflectionProvider\ReflectionProviderFactory::create + autowired: + - PHPStan\Reflection\ReflectionProvider + + betterReflectionSourceLocator: + class: PHPStan\BetterReflection\SourceLocator\Type\SourceLocator + factory: @PHPStan\Reflection\BetterReflection\BetterReflectionSourceLocatorFactory::create + autowired: false + + originalBetterReflectionReflector: + class: PHPStan\BetterReflection\Reflector\DefaultReflector + arguments: + sourceLocator: @betterReflectionSourceLocator + + betterReflectionReflector: + class: PHPStan\Reflection\BetterReflection\Reflector\MemoizingReflector + arguments: + reflector: @originalBetterReflectionReflector + autowired: false + + nodeScopeResolverReflector: + factory: @betterReflectionReflector + autowired: false + + betterReflectionProvider: + class: PHPStan\Reflection\BetterReflection\BetterReflectionProvider + arguments: + reflector: @betterReflectionReflector + universalObjectCratesClasses: %universalObjectCratesClasses% + autowired: false + + - + class: PHPStan\Reflection\BetterReflection\BetterReflectionSourceLocatorFactory + arguments: + parser: @phpParserDecorator + php8Parser: @php8PhpParser + scanFiles: %scanFiles% + scanDirectories: %scanDirectories% + analysedPaths: %analysedPaths% + composerAutoloaderProjectPaths: %composerAutoloaderProjectPaths% + analysedPathsFromConfig: %analysedPathsFromConfig% + playgroundMode: %sourceLocatorPlaygroundMode% + + - + implement: PHPStan\Reflection\BetterReflection\BetterReflectionProviderFactory + arguments: + universalObjectCratesClasses: %universalObjectCratesClasses% + + - + class: PHPStan\Reflection\BetterReflection\SourceStubber\PhpStormStubsSourceStubberFactory + arguments: + phpParser: @php8PhpParser + + - + factory: @PHPStan\Reflection\BetterReflection\SourceStubber\PhpStormStubsSourceStubberFactory::create() + autowired: + - PHPStan\BetterReflection\SourceLocator\SourceStubber\PhpStormStubsSourceStubber + + - + factory: @PHPStan\Reflection\BetterReflection\SourceStubber\ReflectionSourceStubberFactory::create() + autowired: + - PHPStan\BetterReflection\SourceLocator\SourceStubber\ReflectionSourceStubber + + - + class: PHPStan\Reflection\BetterReflection\SourceStubber\ReflectionSourceStubberFactory + + - + class: PHPStan\Reflection\Deprecation\DeprecationProvider + + php8Lexer: + class: PhpParser\Lexer\Emulative + factory: @PHPStan\Parser\LexerFactory::createEmulative() + autowired: false + + php8PhpParser: + class: PhpParser\Parser\Php8 + arguments: + lexer: @php8Lexer + autowired: false + + php8Parser: + class: PHPStan\Parser\SimpleParser + arguments: + parser: @php8PhpParser + autowired: false + + pathRoutingParser: + class: PHPStan\Parser\PathRoutingParser + arguments: + currentPhpVersionRichParser: @currentPhpVersionRichParser + currentPhpVersionSimpleParser: @currentPhpVersionSimpleParser + php8Parser: @php8Parser + autowired: false + + freshStubParser: + class: PHPStan\Parser\StubParser + arguments: + parser: @php8PhpParser + autowired: false + + stubParser: + class: PHPStan\Parser\CachedParser + arguments: + originalParser: @freshStubParser + cachedNodesByStringCountMax: %cache.nodesByStringCountMax% + autowired: false + + phpstanDiagnoseExtension: + class: PHPStan\Diagnose\PHPStanDiagnoseExtension + arguments: + composerAutoloaderProjectPaths: %composerAutoloaderProjectPaths% + allConfigFiles: %allConfigFiles% + configPhpVersion: %phpVersion% + autowired: false + + # Error formatters + + - + class: PHPStan\Command\ErrorFormatter\CiDetectedErrorFormatter + autowired: + - PHPStan\Command\ErrorFormatter\CiDetectedErrorFormatter + + errorFormatter.raw: + class: PHPStan\Command\ErrorFormatter\RawErrorFormatter + + errorFormatter.table: + class: PHPStan\Command\ErrorFormatter\TableErrorFormatter + arguments: + simpleRelativePathHelper: @simpleRelativePathHelper + showTipsOfTheDay: %tipsOfTheDay% + editorUrl: %editorUrl% + editorUrlTitle: %editorUrlTitle% + + errorFormatter.checkstyle: + class: PHPStan\Command\ErrorFormatter\CheckstyleErrorFormatter + arguments: + relativePathHelper: @simpleRelativePathHelper + + errorFormatter.json: + class: PHPStan\Command\ErrorFormatter\JsonErrorFormatter + arguments: + pretty: false + + errorFormatter.junit: + class: PHPStan\Command\ErrorFormatter\JunitErrorFormatter + arguments: + relativePathHelper: @simpleRelativePathHelper + + errorFormatter.prettyJson: + class: PHPStan\Command\ErrorFormatter\JsonErrorFormatter + arguments: + pretty: true + + errorFormatter.gitlab: + class: PHPStan\Command\ErrorFormatter\GitlabErrorFormatter + arguments: + relativePathHelper: @simpleRelativePathHelper + + errorFormatter.github: + class: PHPStan\Command\ErrorFormatter\GithubErrorFormatter + arguments: + relativePathHelper: @simpleRelativePathHelper + + errorFormatter.teamcity: + class: PHPStan\Command\ErrorFormatter\TeamcityErrorFormatter + arguments: + relativePathHelper: @simpleRelativePathHelper diff --git a/src/Analyser/TypeSpecifier.php b/src/Analyser/TypeSpecifier.php index 62ee6867e5..84a6ef4602 100644 --- a/src/Analyser/TypeSpecifier.php +++ b/src/Analyser/TypeSpecifier.php @@ -333,31 +333,6 @@ public function specifyTypesInCondition( } } - if ( - !$context->null() - && $expr->right instanceof FuncCall - && count($expr->right->getArgs()) === 1 - && $expr->right->name instanceof Name - && in_array(strtolower((string) $expr->right->name), ['strlen', 'mb_strlen'], true) - && $leftType->isInteger()->yes() - ) { - if ( - $context->true() && (IntegerRangeType::createAllGreaterThanOrEqualTo(1 - $offset)->isSuperTypeOf($leftType)->yes()) - || ($context->false() && (new ConstantIntegerType(1 - $offset))->isSuperTypeOf($leftType)->yes()) - ) { - $argType = $scope->getType($expr->right->getArgs()[0]->value); - if ($argType->isString()->yes()) { - $accessory = new AccessoryNonEmptyStringType(); - - if (IntegerRangeType::createAllGreaterThanOrEqualTo(2 - $offset)->isSuperTypeOf($leftType)->yes()) { - $accessory = new AccessoryNonFalsyStringType(); - } - - $result = $result->unionWith($this->create($expr->right->getArgs()[0]->value, $accessory, $context, $scope)->setRootExpr($expr)); - } - } - } - if ($leftType instanceof ConstantIntegerType) { if ($expr->right instanceof Expr\PostInc) { $result = $result->unionWith($this->createRangeTypes( @@ -455,10 +430,9 @@ public function specifyTypesInCondition( if ( !$context->null() - && $expr->left instanceof Node\Scalar && $expr->right instanceof Expr\FuncCall && $expr->right->name instanceof Name - && in_array(strtolower((string) $expr->right->name), ['preg_match'], true) + && in_array(strtolower((string) $expr->right->name), ['preg_match', 'strlen', 'mb_strlen'], true) ) { if (!$scope instanceof MutatingScope) { throw new ShouldNotHappenException(); diff --git a/src/Type/Php/StrlenTypeSpecifyingExtension.php b/src/Type/Php/StrlenTypeSpecifyingExtension.php new file mode 100644 index 0000000000..9ca9da98ad --- /dev/null +++ b/src/Type/Php/StrlenTypeSpecifyingExtension.php @@ -0,0 +1,67 @@ +typeSpecifier = $typeSpecifier; + } + + public function isFunctionSupported(FunctionReflection $functionReflection, FuncCall $node, TypeSpecifierContext $context): bool + { + return in_array(strtolower($functionReflection->getName()), ['strlen', 'mb_strlen'], true) && !$context->null(); + } + + public function specifyTypes(FunctionReflection $functionReflection, FuncCall $node, Scope $scope, TypeSpecifierContext $context): SpecifiedTypes + { + $args = $node->getArgs(); + if ( + count($args) < 1 + || $context->getReturnType() === null + ) { + return new SpecifiedTypes(); + } + + $argType = $scope->getType($args[0]->value); + if (!$argType->isString()->yes()) { + return new SpecifiedTypes(); + } + + $returnType = $context->getReturnType(); + if ( + $context->true() && IntegerRangeType::createAllGreaterThanOrEqualTo(1)->isSuperTypeOf($returnType)->yes() + || ($context->false() && (new ConstantIntegerType(0))->isSuperTypeOf($returnType)->yes()) + ) { + $accessory = new AccessoryNonEmptyStringType(); + if (IntegerRangeType::createAllGreaterThanOrEqualTo(2)->isSuperTypeOf($returnType)->yes()) { + $accessory = new AccessoryNonFalsyStringType(); + } + + return $this->typeSpecifier->create($args[0]->value, $accessory, $context, $scope)->setRootExpr($node); + } + + return new SpecifiedTypes(); + } + +} diff --git a/tests/PHPStan/Analyser/nsrt/narrow-cast.php b/tests/PHPStan/Analyser/nsrt/narrow-cast.php index 5687c0b23a..b86b3781b2 100644 --- a/tests/PHPStan/Analyser/nsrt/narrow-cast.php +++ b/tests/PHPStan/Analyser/nsrt/narrow-cast.php @@ -7,9 +7,9 @@ /** @param array $arr */ function doFoo(string $x, array $arr): void { if ((bool) strlen($x)) { - assertType('string', $x); // could be non-empty-string + assertType('non-empty-string', $x); } else { - assertType('string', $x); + assertType("''", $x); } assertType('string', $x); From 9aa1111f6184941d38fe57e1204145a91824fa78 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Fri, 14 Mar 2025 11:38:07 +0100 Subject: [PATCH 3/7] Discard changes to tests/PHPStan/Analyser/nsrt/narrow-cast.php --- tests/PHPStan/Analyser/nsrt/narrow-cast.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/PHPStan/Analyser/nsrt/narrow-cast.php b/tests/PHPStan/Analyser/nsrt/narrow-cast.php index b86b3781b2..5687c0b23a 100644 --- a/tests/PHPStan/Analyser/nsrt/narrow-cast.php +++ b/tests/PHPStan/Analyser/nsrt/narrow-cast.php @@ -7,9 +7,9 @@ /** @param array $arr */ function doFoo(string $x, array $arr): void { if ((bool) strlen($x)) { - assertType('non-empty-string', $x); + assertType('string', $x); // could be non-empty-string } else { - assertType("''", $x); + assertType('string', $x); } assertType('string', $x); From 4bf13c3fff3b2497f05fb4546c6512906e9570ed Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Fri, 14 Mar 2025 11:51:23 +0100 Subject: [PATCH 4/7] Remove TypeSpecifierContext caching --- src/Analyser/TypeSpecifierContext.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Analyser/TypeSpecifierContext.php b/src/Analyser/TypeSpecifierContext.php index f8f9c63891..4c32f56e89 100644 --- a/src/Analyser/TypeSpecifierContext.php +++ b/src/Analyser/TypeSpecifierContext.php @@ -19,9 +19,6 @@ final class TypeSpecifierContext public const CONTEXT_FALSEY = self::CONTEXT_FALSE | self::CONTEXT_FALSEY_BUT_NOT_FALSE; public const CONTEXT_BITMASK = 0b1111; - /** @var self[] */ - private static array $registry; - private ?Type $returnType = null; private function __construct(private ?int $value) @@ -30,8 +27,7 @@ private function __construct(private ?int $value) private static function create(?int $value): self { - self::$registry[$value] ??= new self($value); - return self::$registry[$value]; + return new self($value); } public static function createTrue(): self From c64cedc6fb20ef63a7452b0e79beb24835ced07a Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Sat, 15 Mar 2025 09:54:41 +0100 Subject: [PATCH 5/7] fix --- .../Php/StrlenTypeSpecifyingExtension.php | 5 ++ tests/PHPStan/Analyser/nsrt/strlen-never.php | 50 +++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 tests/PHPStan/Analyser/nsrt/strlen-never.php diff --git a/src/Type/Php/StrlenTypeSpecifyingExtension.php b/src/Type/Php/StrlenTypeSpecifyingExtension.php index 9ca9da98ad..4d5ebfa53e 100644 --- a/src/Type/Php/StrlenTypeSpecifyingExtension.php +++ b/src/Type/Php/StrlenTypeSpecifyingExtension.php @@ -14,6 +14,7 @@ use PHPStan\Type\Constant\ConstantIntegerType; use PHPStan\Type\FunctionTypeSpecifyingExtension; use PHPStan\Type\IntegerRangeType; +use PHPStan\Type\NeverType; use function count; use function in_array; use function strtolower; @@ -49,6 +50,10 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n } $returnType = $context->getReturnType(); + if ($returnType instanceof NeverType) { + return $this->typeSpecifier->create($args[0]->value, $returnType, $context->negate(), $scope); + } + if ( $context->true() && IntegerRangeType::createAllGreaterThanOrEqualTo(1)->isSuperTypeOf($returnType)->yes() || ($context->false() && (new ConstantIntegerType(0))->isSuperTypeOf($returnType)->yes()) diff --git a/tests/PHPStan/Analyser/nsrt/strlen-never.php b/tests/PHPStan/Analyser/nsrt/strlen-never.php new file mode 100644 index 0000000000..7f68b0a397 --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/strlen-never.php @@ -0,0 +1,50 @@ += 0) { + assertType('non-empty-string', $nonES); + } else { + assertType('*NEVER*', $nonES); + } +} + + +function doBar(string $m): void +{ + if (strlen($m) >= 1) { + if (strlen($m) <= 0) { + assertType('*NEVER*', $m); + } + } +} + From dd4018e0fb45e44fc3193825b6434da7f482a890 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 17 Jul 2025 18:24:59 +0200 Subject: [PATCH 6/7] Update config.neon --- conf/config.neon | 1186 ---------------------------------------------- 1 file changed, 1186 deletions(-) diff --git a/conf/config.neon b/conf/config.neon index 04a6362c41..65cda918e7 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -250,1189 +250,3 @@ services: # like #[PHPStan\DependencyInjection\AutowiredService] or #[PHPStan\DependencyInjection\GenerateFactory] # non-autowired services are now registered in services.neon - - - class: PHPStan\Rules\Properties\PropertyDescriptor - - - - class: PHPStan\Rules\Properties\PropertyReflectionFinder - - - - class: PHPStan\Rules\Pure\FunctionPurityCheck - - - - class: PHPStan\Rules\RuleLevelHelper - arguments: - checkNullables: %checkNullables% - checkThisOnly: %checkThisOnly% - checkUnionTypes: %checkUnionTypes% - checkExplicitMixed: %checkExplicitMixed% - checkImplicitMixed: %checkImplicitMixed% - checkBenevolentUnionTypes: %checkBenevolentUnionTypes% - discoveringSymbolsTip: %tips.discoveringSymbols% - - - - class: PHPStan\Rules\UnusedFunctionParametersCheck - arguments: - reportExactLine: %featureToggles.reportPreciseLineForUnusedFunctionParameter% - - - - class: PHPStan\Rules\TooWideTypehints\TooWideParameterOutTypeCheck - - - - class: PHPStan\Type\FileTypeMapper - arguments: - phpParser: @defaultAnalysisParser - - stubFileTypeMapper: - class: PHPStan\Type\FileTypeMapper - arguments: - phpParser: @stubParser - autowired: false - - - - class: PHPStan\Type\TypeAliasResolver - factory: PHPStan\Type\UsefulTypeAliasResolver - arguments: - globalTypeAliases: %typeAliases% - - - - class: PHPStan\Type\TypeAliasResolverProvider - factory: PHPStan\Type\LazyTypeAliasResolverProvider - - - - class: PHPStan\Type\BitwiseFlagHelper - - - - class: PHPStan\Type\Php\AbsFunctionDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ArgumentBasedFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ArrayChangeKeyCaseFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ArrayIntersectKeyFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ArrayChunkFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ArrayColumnHelper - - - - class: PHPStan\Type\Php\ArrayColumnFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ArrayCombineFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ArrayCurrentDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ArrayFillFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ArrayFillKeysFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ArrayFilterFunctionReturnTypeHelper - - - - class: PHPStan\Type\Php\ArrayFilterFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ArrayFlipFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ArrayFindFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ArrayFindKeyFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ArrayKeyDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ArrayKeyExistsFunctionTypeSpecifyingExtension - tags: - - phpstan.typeSpecifier.functionTypeSpecifyingExtension - - - - class: PHPStan\Type\Php\ArrayKeyFirstDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ArrayKeyLastDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ArrayKeysFunctionDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ArrayMapFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ArrayMergeFunctionDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ArrayNextDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ArrayPopFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ArrayRandFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ArrayReduceFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ArrayReplaceFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ArrayReverseFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ArrayShiftFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ArraySliceFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ArraySpliceFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ArraySearchFunctionDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ArraySearchFunctionTypeSpecifyingExtension - tags: - - phpstan.typeSpecifier.functionTypeSpecifyingExtension - - - - class: PHPStan\Type\Php\ArrayValuesFunctionDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ArraySumFunctionDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\AssertThrowTypeExtension - tags: - - phpstan.dynamicFunctionThrowTypeExtension - - - - class: PHPStan\Type\Php\BackedEnumFromMethodDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicStaticMethodReturnTypeExtension - - - - class: PHPStan\Type\Php\Base64DecodeDynamicFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\BcMathStringOrNullReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ClosureBindDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicStaticMethodReturnTypeExtension - - - - class: PHPStan\Type\Php\ClosureBindToDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicMethodReturnTypeExtension - - - - class: PHPStan\Type\Php\ClosureFromCallableDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicStaticMethodReturnTypeExtension - - - - class: PHPStan\Type\Php\CompactFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - arguments: - checkMaybeUndefinedVariables: %checkMaybeUndefinedVariables% - - - - class: PHPStan\Type\Php\ConstantFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ConstantHelper - - - - class: PHPStan\Type\Php\CountFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\CountCharsFunctionDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\CountFunctionTypeSpecifyingExtension - tags: - - phpstan.typeSpecifier.functionTypeSpecifyingExtension - - - - class: PHPStan\Type\Php\CurlGetinfoFunctionDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\DateFunctionReturnTypeHelper - - - - class: PHPStan\Type\Php\DateFormatFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\DateFormatMethodReturnTypeExtension - tags: - - phpstan.broker.dynamicMethodReturnTypeExtension - - - - class: PHPStan\Type\Php\DateFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\DateIntervalConstructorThrowTypeExtension - tags: - - phpstan.dynamicStaticMethodThrowTypeExtension - - - - class: PHPStan\Type\Php\DateIntervalDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicStaticMethodReturnTypeExtension - - - - class: PHPStan\Type\Php\DateTimeCreateDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\DateTimeDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\DateTimeModifyReturnTypeExtension - tags: - - phpstan.broker.dynamicMethodReturnTypeExtension - arguments: - dateTimeClass: DateTime - - - - class: PHPStan\Type\Php\DateTimeModifyReturnTypeExtension - tags: - - phpstan.broker.dynamicMethodReturnTypeExtension - arguments: - dateTimeClass: DateTimeImmutable - - - - class: PHPStan\Type\Php\DateTimeConstructorThrowTypeExtension - tags: - - phpstan.dynamicStaticMethodThrowTypeExtension - - - - class: PHPStan\Type\Php\DateTimeModifyMethodThrowTypeExtension - tags: - - phpstan.dynamicMethodThrowTypeExtension - - - - class: PHPStan\Type\Php\DateTimeSubMethodThrowTypeExtension - tags: - - phpstan.dynamicMethodThrowTypeExtension - - - - class: PHPStan\Type\Php\DateTimeZoneConstructorThrowTypeExtension - tags: - - phpstan.dynamicStaticMethodThrowTypeExtension - - - - class: PHPStan\Type\Php\DsMapDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicMethodReturnTypeExtension - - - - class: PHPStan\Type\Php\DsMapDynamicMethodThrowTypeExtension - tags: - - phpstan.dynamicMethodThrowTypeExtension - - - - class: PHPStan\Type\Php\DioStatDynamicFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ExplodeFunctionDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\FilterFunctionReturnTypeHelper - - - - class: PHPStan\Type\Php\FilterInputDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\FilterVarDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\FilterVarArrayDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\GetCalledClassDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\GetClassDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\GetDebugTypeFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\GetDefinedVarsFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\GetParentClassDynamicFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\GettypeFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\GettimeofdayDynamicFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - class: PHPStan\Type\Php\HashFunctionsReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\HighlightStringDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\IntdivThrowTypeExtension - tags: - - phpstan.dynamicFunctionThrowTypeExtension - - - - class: PHPStan\Type\Php\IniGetReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\JsonThrowTypeExtension - tags: - - phpstan.dynamicFunctionThrowTypeExtension - - - - class: PHPStan\Type\Php\OpenSslEncryptParameterOutTypeExtension - tags: - - phpstan.functionParameterOutTypeExtension - - - - class: PHPStan\Type\Php\ParseStrParameterOutTypeExtension - tags: - - phpstan.functionParameterOutTypeExtension - - - - class: PHPStan\Type\Php\PregMatchTypeSpecifyingExtension - tags: - - phpstan.typeSpecifier.functionTypeSpecifyingExtension - - - - class: PHPStan\Type\Php\PregMatchParameterOutTypeExtension - tags: - - phpstan.functionParameterOutTypeExtension - - - - class: PHPStan\Type\Php\PregReplaceCallbackClosureTypeExtension - tags: - - phpstan.functionParameterClosureTypeExtension - - - - class: PHPStan\Type\Php\RegexArrayShapeMatcher - - - - class: PHPStan\Type\Regex\RegexGroupParser - - - - class: PHPStan\Type\Regex\RegexExpressionHelper - - - - class: PHPStan\Type\Php\ReflectionClassConstructorThrowTypeExtension - tags: - - phpstan.dynamicStaticMethodThrowTypeExtension - - - - class: PHPStan\Type\Php\ReflectionFunctionConstructorThrowTypeExtension - tags: - - phpstan.dynamicStaticMethodThrowTypeExtension - - - - class: PHPStan\Type\Php\ReflectionMethodConstructorThrowTypeExtension - tags: - - phpstan.dynamicStaticMethodThrowTypeExtension - - - - class: PHPStan\Type\Php\ReflectionPropertyConstructorThrowTypeExtension - tags: - - phpstan.dynamicStaticMethodThrowTypeExtension - - - - class: PHPStan\Type\Php\StrContainingTypeSpecifyingExtension - tags: - - phpstan.typeSpecifier.functionTypeSpecifyingExtension - - - - class: PHPStan\Type\Php\SimpleXMLElementClassPropertyReflectionExtension - tags: - - phpstan.broker.propertiesClassReflectionExtension - - - - class: PHPStan\Type\Php\SimpleXMLElementConstructorThrowTypeExtension - tags: - - phpstan.dynamicStaticMethodThrowTypeExtension - - - - class: PHPStan\Type\Php\StatDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - phpstan.broker.dynamicMethodReturnTypeExtension - - - - class: PHPStan\Type\Php\MethodExistsTypeSpecifyingExtension - tags: - - phpstan.typeSpecifier.functionTypeSpecifyingExtension - - - - class: PHPStan\Type\Php\PropertyExistsTypeSpecifyingExtension - tags: - - phpstan.typeSpecifier.functionTypeSpecifyingExtension - - - - class: PHPStan\Type\Php\MinMaxFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\NumberFormatFunctionDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\PathinfoFunctionDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\PregFilterFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\PregSplitDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ReflectionClassIsSubclassOfTypeSpecifyingExtension - tags: - - phpstan.typeSpecifier.methodTypeSpecifyingExtension - - - - class: PHPStan\Type\Php\ReplaceFunctionsDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ArrayPointerFunctionsDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\LtrimFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\MbFunctionsReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\MbConvertEncodingFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\MbSubstituteCharacterDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\MbStrlenFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\MicrotimeFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\HrtimeFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ImplodeFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\NonEmptyStringFunctionsReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\SetTypeFunctionTypeSpecifyingExtension - tags: - - phpstan.typeSpecifier.functionTypeSpecifyingExtension - - - - class: PHPStan\Type\Php\StrCaseFunctionsReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\StrlenTypeSpecifyingExtension - tags: - - phpstan.typeSpecifier.functionTypeSpecifyingExtension - - - - class: PHPStan\Type\Php\StrlenFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\StrIncrementDecrementFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\StrPadFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\StrRepeatFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\SubstrDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\ThrowableReturnTypeExtension - tags: - - phpstan.broker.dynamicMethodReturnTypeExtension - - - - class: PHPStan\Type\Php\ParseUrlFunctionDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\TriggerErrorDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\TrimFunctionDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\VersionCompareFunctionDynamicReturnTypeExtension - arguments: - configPhpVersion: %phpVersion% - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\PowFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\RoundFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\StrtotimeFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\RandomIntFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\RangeFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\AssertFunctionTypeSpecifyingExtension - tags: - - phpstan.typeSpecifier.functionTypeSpecifyingExtension - - - - class: PHPStan\Type\Php\ClassExistsFunctionTypeSpecifyingExtension - tags: - - phpstan.typeSpecifier.functionTypeSpecifyingExtension - - - - class: PHPStan\Type\Php\ClassImplementsFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\DefineConstantTypeSpecifyingExtension - tags: - - phpstan.typeSpecifier.functionTypeSpecifyingExtension - - - - class: PHPStan\Type\Php\DefinedConstantTypeSpecifyingExtension - tags: - - phpstan.typeSpecifier.functionTypeSpecifyingExtension - - - - class: PHPStan\Type\Php\FunctionExistsFunctionTypeSpecifyingExtension - tags: - - phpstan.typeSpecifier.functionTypeSpecifyingExtension - - - - class: PHPStan\Type\Php\InArrayFunctionTypeSpecifyingExtension - tags: - - phpstan.typeSpecifier.functionTypeSpecifyingExtension - - - - class: PHPStan\Type\Php\IsArrayFunctionTypeSpecifyingExtension - tags: - - phpstan.typeSpecifier.functionTypeSpecifyingExtension - - - - class: PHPStan\Type\Php\IsCallableFunctionTypeSpecifyingExtension - tags: - - phpstan.typeSpecifier.functionTypeSpecifyingExtension - - - - class: PHPStan\Type\Php\IsIterableFunctionTypeSpecifyingExtension - tags: - - phpstan.typeSpecifier.functionTypeSpecifyingExtension - - - - class: PHPStan\Type\Php\IsSubclassOfFunctionTypeSpecifyingExtension - tags: - - phpstan.typeSpecifier.functionTypeSpecifyingExtension - - - - class: PHPStan\Type\Php\IteratorToArrayFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\IsAFunctionTypeSpecifyingExtension - tags: - - phpstan.typeSpecifier.functionTypeSpecifyingExtension - - - - class: PHPStan\Type\Php\IsAFunctionTypeSpecifyingHelper - - - - class: PHPStan\Type\Php\CtypeDigitFunctionTypeSpecifyingExtension - tags: - - phpstan.typeSpecifier.functionTypeSpecifyingExtension - - - - class: PHPStan\Type\Php\JsonThrowOnErrorDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\TypeSpecifyingFunctionsDynamicReturnTypeExtension - arguments: - treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain% - universalObjectCratesClasses: %universalObjectCratesClasses% - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\SimpleXMLElementAsXMLMethodReturnTypeExtension - tags: - - phpstan.broker.dynamicMethodReturnTypeExtension - - - - class: PHPStan\Type\Php\SimpleXMLElementXpathMethodReturnTypeExtension - tags: - - phpstan.broker.dynamicMethodReturnTypeExtension - - - - class: PHPStan\Type\Php\StrSplitFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\StrTokFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\SprintfFunctionDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\SscanfFunctionDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\StrvalFamilyFunctionReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\StrWordCountFunctionDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension - - - - class: PHPStan\Type\Php\XMLReaderOpenReturnTypeExtension - tags: - - phpstan.broker.dynamicMethodReturnTypeExtension - - phpstan.broker.dynamicStaticMethodReturnTypeExtension - - - - class: PHPStan\Type\Php\ReflectionGetAttributesMethodReturnTypeExtension - arguments: - className: ReflectionClass - tags: - - phpstan.broker.dynamicMethodReturnTypeExtension - - - - class: PHPStan\Type\Php\ReflectionGetAttributesMethodReturnTypeExtension - arguments: - className: ReflectionClassConstant - tags: - - phpstan.broker.dynamicMethodReturnTypeExtension - - - - class: PHPStan\Type\Php\ReflectionGetAttributesMethodReturnTypeExtension - arguments: - className: ReflectionFunctionAbstract - tags: - - phpstan.broker.dynamicMethodReturnTypeExtension - - - - class: PHPStan\Type\Php\ReflectionGetAttributesMethodReturnTypeExtension - arguments: - className: ReflectionParameter - tags: - - phpstan.broker.dynamicMethodReturnTypeExtension - - - - class: PHPStan\Type\Php\ReflectionGetAttributesMethodReturnTypeExtension - arguments: - className: ReflectionProperty - tags: - - phpstan.broker.dynamicMethodReturnTypeExtension - - - - class: PHPStan\Type\Php\DatePeriodConstructorReturnTypeExtension - tags: - - phpstan.broker.dynamicStaticMethodReturnTypeExtension - - - - class: PHPStan\Type\PHPStan\ClassNameUsageLocationCreateIdentifierDynamicReturnTypeExtension - tags: - - phpstan.broker.dynamicMethodReturnTypeExtension - - - class: PHPStan\Type\ClosureTypeFactory - arguments: - parser: @currentPhpVersionPhpParser - - - - class: PHPStan\Type\Constant\OversizedArrayBuilder - - - - class: PHPStan\Rules\Functions\PrintfHelper - - exceptionTypeResolver: - class: PHPStan\Rules\Exceptions\ExceptionTypeResolver - factory: @PHPStan\Rules\Exceptions\DefaultExceptionTypeResolver - - typeSpecifier: - class: PHPStan\Analyser\TypeSpecifier - factory: @typeSpecifierFactory::create - - typeSpecifierFactory: - class: PHPStan\Analyser\TypeSpecifierFactory - - relativePathHelper: - class: PHPStan\File\RelativePathHelper - factory: PHPStan\File\FuzzyRelativePathHelper - arguments: - currentWorkingDirectory: %currentWorkingDirectory% - analysedPaths: %analysedPaths% - fallbackRelativePathHelper: @parentDirectoryRelativePathHelper - - simpleRelativePathHelper: - class: PHPStan\File\RelativePathHelper - factory: PHPStan\File\SimpleRelativePathHelper - arguments: - currentWorkingDirectory: %currentWorkingDirectory% - autowired: false - - parentDirectoryRelativePathHelper: - class: PHPStan\File\ParentDirectoryRelativePathHelper - arguments: - parentDirectory: %currentWorkingDirectory% - autowired: false - - cacheStorage: - class: PHPStan\Cache\FileCacheStorage - arguments: - directory: %tmpDir%/cache/PHPStan - autowired: no - - currentPhpVersionRichParser: - class: PHPStan\Parser\RichParser - arguments: - parser: @currentPhpVersionPhpParser - autowired: no - - currentPhpVersionSimpleParser: - class: PHPStan\Parser\CleaningParser - arguments: - wrappedParser: @currentPhpVersionSimpleDirectParser - autowired: no - - currentPhpVersionSimpleDirectParser: - class: PHPStan\Parser\SimpleParser - arguments: - parser: @currentPhpVersionPhpParser - autowired: no - - defaultAnalysisParser: - class: PHPStan\Parser\CachedParser - arguments: - originalParser: @pathRoutingParser - cachedNodesByStringCountMax: %cache.nodesByStringCountMax% - autowired: false - - phpParserDecorator: - class: PHPStan\Parser\PhpParserDecorator - arguments: - wrappedParser: @defaultAnalysisParser - autowired: false - - currentPhpVersionLexer: - class: PhpParser\Lexer - factory: @PHPStan\Parser\LexerFactory::create() - autowired: false - - currentPhpVersionPhpParser: - factory: @currentPhpVersionPhpParserFactory::create() - autowired: false - - currentPhpVersionPhpParserFactory: - class: PHPStan\Parser\PhpParserFactory - arguments: - lexer: @currentPhpVersionLexer - autowired: false - - registry: - class: PHPStan\Rules\LazyRegistry - autowired: - - PHPStan\Rules\Registry - - stubPhpDocProvider: - class: PHPStan\PhpDoc\StubPhpDocProvider - arguments: - parser: @stubParser - fileTypeMapper: @stubFileTypeMapper - - # Reflection providers - - reflectionProviderFactory: - class: PHPStan\Reflection\ReflectionProvider\ReflectionProviderFactory - arguments: - staticReflectionProvider: @betterReflectionProvider - - reflectionProvider: - factory: @PHPStan\Reflection\ReflectionProvider\ReflectionProviderFactory::create - autowired: - - PHPStan\Reflection\ReflectionProvider - - betterReflectionSourceLocator: - class: PHPStan\BetterReflection\SourceLocator\Type\SourceLocator - factory: @PHPStan\Reflection\BetterReflection\BetterReflectionSourceLocatorFactory::create - autowired: false - - originalBetterReflectionReflector: - class: PHPStan\BetterReflection\Reflector\DefaultReflector - arguments: - sourceLocator: @betterReflectionSourceLocator - - betterReflectionReflector: - class: PHPStan\Reflection\BetterReflection\Reflector\MemoizingReflector - arguments: - reflector: @originalBetterReflectionReflector - autowired: false - - nodeScopeResolverReflector: - factory: @betterReflectionReflector - autowired: false - - betterReflectionProvider: - class: PHPStan\Reflection\BetterReflection\BetterReflectionProvider - arguments: - reflector: @betterReflectionReflector - universalObjectCratesClasses: %universalObjectCratesClasses% - autowired: false - - - - class: PHPStan\Reflection\BetterReflection\BetterReflectionSourceLocatorFactory - arguments: - parser: @phpParserDecorator - php8Parser: @php8PhpParser - scanFiles: %scanFiles% - scanDirectories: %scanDirectories% - analysedPaths: %analysedPaths% - composerAutoloaderProjectPaths: %composerAutoloaderProjectPaths% - analysedPathsFromConfig: %analysedPathsFromConfig% - playgroundMode: %sourceLocatorPlaygroundMode% - - - - implement: PHPStan\Reflection\BetterReflection\BetterReflectionProviderFactory - arguments: - universalObjectCratesClasses: %universalObjectCratesClasses% - - - - class: PHPStan\Reflection\BetterReflection\SourceStubber\PhpStormStubsSourceStubberFactory - arguments: - phpParser: @php8PhpParser - - - - factory: @PHPStan\Reflection\BetterReflection\SourceStubber\PhpStormStubsSourceStubberFactory::create() - autowired: - - PHPStan\BetterReflection\SourceLocator\SourceStubber\PhpStormStubsSourceStubber - - - - factory: @PHPStan\Reflection\BetterReflection\SourceStubber\ReflectionSourceStubberFactory::create() - autowired: - - PHPStan\BetterReflection\SourceLocator\SourceStubber\ReflectionSourceStubber - - - - class: PHPStan\Reflection\BetterReflection\SourceStubber\ReflectionSourceStubberFactory - - - - class: PHPStan\Reflection\Deprecation\DeprecationProvider - - php8Lexer: - class: PhpParser\Lexer\Emulative - factory: @PHPStan\Parser\LexerFactory::createEmulative() - autowired: false - - php8PhpParser: - class: PhpParser\Parser\Php8 - arguments: - lexer: @php8Lexer - autowired: false - - php8Parser: - class: PHPStan\Parser\SimpleParser - arguments: - parser: @php8PhpParser - autowired: false - - pathRoutingParser: - class: PHPStan\Parser\PathRoutingParser - arguments: - currentPhpVersionRichParser: @currentPhpVersionRichParser - currentPhpVersionSimpleParser: @currentPhpVersionSimpleParser - php8Parser: @php8Parser - autowired: false - - freshStubParser: - class: PHPStan\Parser\StubParser - arguments: - parser: @php8PhpParser - autowired: false - - stubParser: - class: PHPStan\Parser\CachedParser - arguments: - originalParser: @freshStubParser - cachedNodesByStringCountMax: %cache.nodesByStringCountMax% - autowired: false - - phpstanDiagnoseExtension: - class: PHPStan\Diagnose\PHPStanDiagnoseExtension - arguments: - composerAutoloaderProjectPaths: %composerAutoloaderProjectPaths% - allConfigFiles: %allConfigFiles% - configPhpVersion: %phpVersion% - autowired: false - - # Error formatters - - - - class: PHPStan\Command\ErrorFormatter\CiDetectedErrorFormatter - autowired: - - PHPStan\Command\ErrorFormatter\CiDetectedErrorFormatter - - errorFormatter.raw: - class: PHPStan\Command\ErrorFormatter\RawErrorFormatter - - errorFormatter.table: - class: PHPStan\Command\ErrorFormatter\TableErrorFormatter - arguments: - simpleRelativePathHelper: @simpleRelativePathHelper - showTipsOfTheDay: %tipsOfTheDay% - editorUrl: %editorUrl% - editorUrlTitle: %editorUrlTitle% - - errorFormatter.checkstyle: - class: PHPStan\Command\ErrorFormatter\CheckstyleErrorFormatter - arguments: - relativePathHelper: @simpleRelativePathHelper - - errorFormatter.json: - class: PHPStan\Command\ErrorFormatter\JsonErrorFormatter - arguments: - pretty: false - - errorFormatter.junit: - class: PHPStan\Command\ErrorFormatter\JunitErrorFormatter - arguments: - relativePathHelper: @simpleRelativePathHelper - - errorFormatter.prettyJson: - class: PHPStan\Command\ErrorFormatter\JsonErrorFormatter - arguments: - pretty: true - - errorFormatter.gitlab: - class: PHPStan\Command\ErrorFormatter\GitlabErrorFormatter - arguments: - relativePathHelper: @simpleRelativePathHelper - - errorFormatter.github: - class: PHPStan\Command\ErrorFormatter\GithubErrorFormatter - arguments: - relativePathHelper: @simpleRelativePathHelper - - errorFormatter.teamcity: - class: PHPStan\Command\ErrorFormatter\TeamcityErrorFormatter - arguments: - relativePathHelper: @simpleRelativePathHelper From 5ae6cc0c9e3a7ca243dafb2214b5a87989880a48 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 17 Jul 2025 18:26:20 +0200 Subject: [PATCH 7/7] Update StrlenTypeSpecifyingExtension.php --- src/Type/Php/StrlenTypeSpecifyingExtension.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Type/Php/StrlenTypeSpecifyingExtension.php b/src/Type/Php/StrlenTypeSpecifyingExtension.php index 4d5ebfa53e..a491b5d671 100644 --- a/src/Type/Php/StrlenTypeSpecifyingExtension.php +++ b/src/Type/Php/StrlenTypeSpecifyingExtension.php @@ -8,6 +8,7 @@ use PHPStan\Analyser\TypeSpecifier; use PHPStan\Analyser\TypeSpecifierAwareExtension; use PHPStan\Analyser\TypeSpecifierContext; +use PHPStan\DependencyInjection\AutowiredService; use PHPStan\Reflection\FunctionReflection; use PHPStan\Type\Accessory\AccessoryNonEmptyStringType; use PHPStan\Type\Accessory\AccessoryNonFalsyStringType; @@ -19,6 +20,7 @@ use function in_array; use function strtolower; +#[AutowiredService] final class StrlenTypeSpecifyingExtension implements FunctionTypeSpecifyingExtension, TypeSpecifierAwareExtension {