From ac858e353d929aedfa15a7de1137301fac9e918b Mon Sep 17 00:00:00 2001 From: orklah Date: Wed, 19 Jan 2022 21:38:33 +0100 Subject: [PATCH] create a return type provider for mb_internal_encoding --- .../Provider/FunctionReturnTypeProvider.php | 2 + .../MbInternalEncodingReturnTypeProvider.php | 116 ++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 src/Psalm/Internal/Provider/ReturnTypeProvider/MbInternalEncodingReturnTypeProvider.php diff --git a/src/Psalm/Internal/Provider/FunctionReturnTypeProvider.php b/src/Psalm/Internal/Provider/FunctionReturnTypeProvider.php index cb8dc08aeb8..f23167ce9de 100644 --- a/src/Psalm/Internal/Provider/FunctionReturnTypeProvider.php +++ b/src/Psalm/Internal/Provider/FunctionReturnTypeProvider.php @@ -30,6 +30,7 @@ use Psalm\Internal\Provider\ReturnTypeProvider\HexdecReturnTypeProvider; use Psalm\Internal\Provider\ReturnTypeProvider\InArrayReturnTypeProvider; use Psalm\Internal\Provider\ReturnTypeProvider\IteratorToArrayReturnTypeProvider; +use Psalm\Internal\Provider\ReturnTypeProvider\MbInternalEncodingReturnTypeProvider; use Psalm\Internal\Provider\ReturnTypeProvider\MinMaxReturnTypeProvider; use Psalm\Internal\Provider\ReturnTypeProvider\MktimeReturnTypeProvider; use Psalm\Internal\Provider\ReturnTypeProvider\ParseUrlReturnTypeProvider; @@ -97,6 +98,7 @@ public function __construct() $this->registerClass(RandReturnTypeProvider::class); $this->registerClass(InArrayReturnTypeProvider::class); $this->registerClass(RoundReturnTypeProvider::class); + $this->registerClass(MbInternalEncodingReturnTypeProvider::class); } /** diff --git a/src/Psalm/Internal/Provider/ReturnTypeProvider/MbInternalEncodingReturnTypeProvider.php b/src/Psalm/Internal/Provider/ReturnTypeProvider/MbInternalEncodingReturnTypeProvider.php new file mode 100644 index 00000000000..1a5fd399bb8 --- /dev/null +++ b/src/Psalm/Internal/Provider/ReturnTypeProvider/MbInternalEncodingReturnTypeProvider.php @@ -0,0 +1,116 @@ + + */ + public static function getFunctionIds(): array + { + return ['mb_internal_encoding']; + } + + public static function getFunctionReturnType(FunctionReturnTypeProviderEvent $event): ?Union + { + $call_args = $event->getCallArgs(); + if (count($call_args) === 0) { + return Type::getString(); + } + + $statements_source = $event->getStatementsSource(); + $nodeTypeProvider = $statements_source->getNodeTypeProvider(); + $codebase = $statements_source->getCodebase(); + + $first_arg_type = $nodeTypeProvider->getType($call_args[0]->value); + if ($first_arg_type === null) { + if ($codebase->analysis_php_version_id >= 8_00_00) { + return new Union([new TString(), new TTrue()]); + } else { + return new Union([new TString(), new TBool()]); + } + } + + $has_stringable = false; + $has_tostring = false; + $has_string = false; + $has_null = false; + $has_unknown = false; + + foreach ($first_arg_type->getAtomicTypes() as $atomic_type) { + if ($atomic_type instanceof Type\Atomic\TNamedObject + && $codebase->classlikes->classImplements($atomic_type->value, 'Stringable') + ) { + $has_stringable = true; + continue; + } + + if ($atomic_type instanceof Type\Atomic\TObjectWithProperties + && isset($atomic_type->methods['__toString']) + ) { + $has_tostring = true; + continue; + } + + if ($atomic_type instanceof TString) { + $has_string = true; + continue; + } + + if ($atomic_type instanceof TNull) { + $has_null = true; + continue; + } + + $has_unknown = true; + } + + $list_return_atomics = []; + if ($has_string || $has_stringable || $has_tostring) { + if ($codebase->analysis_php_version_id >= 8_00_00) { + $list_return_atomics[] = new TTrue(); + } else { + $list_return_atomics[] = new TBool(); + } + } + + if ($has_null) { + if ($codebase->analysis_php_version_id >= 8_00_00) { + $list_return_atomics[] = new TString(); + } else { + $list_return_atomics[] = new TFalse(); + } + } + + if ($has_unknown) { + if ($codebase->analysis_php_version_id >= 8_00_00) { + $list_return_atomics[] = new TNever(); + } else { + $list_return_atomics[] = new TNull(); + } + } + + assert($list_return_atomics !== []); + return new Union($list_return_atomics); + } +}