diff --git a/Neos.Flow/Classes/Reflection/ReflectionService.php b/Neos.Flow/Classes/Reflection/ReflectionService.php index e7f786c605..26af03a16e 100644 --- a/Neos.Flow/Classes/Reflection/ReflectionService.php +++ b/Neos.Flow/Classes/Reflection/ReflectionService.php @@ -1321,10 +1321,8 @@ protected function reflectClassMethod(string $className, MethodReflection $metho } $returnType = $method->getDeclaredReturnType(); - $applyLeadingSlashIfNeeded = static function (string $type): string { - if (!in_array($type, ['self', 'parent', 'static', 'null', 'callable', 'void', 'never', 'iterable', 'object', 'resource', 'mixed']) - && !TypeHandling::isSimpleType($type) - ) { + $applyLeadingSlashIfNeeded = function (string $type): string { + if (!str_starts_with($type, '\\') && TypeHandling::isUserDefinedType($type)) { return '\\' . $type; } return $type; @@ -1415,8 +1413,8 @@ protected function expandType(ClassReflection $class, string $type): string return 'array<' . $this->expandType($class, $elementType) . '>' . ($isNullable ? '|null' : ''); } - // skip simple types and types with fully qualified namespaces - if ($type === 'mixed' || $type[0] === '\\' || TypeHandling::isSimpleType($type)) { + // skip non user-defined types and types with fully qualified namespaces + if ($typeWithoutNull[0] === '\\' || !TypeHandling::isUserDefinedType($typeWithoutNull)) { return TypeHandling::normalizeType($typeWithoutNull) . ($isNullable ? '|null' : ''); } @@ -1777,7 +1775,7 @@ protected function convertParameterReflectionToArray(ParameterReflection $parame } $parameterType = $this->renderParameterType($parameter->getType()); - if ($parameterType !== null && !TypeHandling::isSimpleType($parameterType)) { + if ($parameterType !== null && TypeHandling::isUserDefinedType($parameterType)) { // We use parameter type here to make class_alias usage work and return the hinted class name instead of the alias $parameterInformation[self::DATA_PARAMETER_CLASS] = $parameterType; } elseif ($parameterType === 'array') { diff --git a/Neos.Utility.ObjectHandling/Classes/TypeHandling.php b/Neos.Utility.ObjectHandling/Classes/TypeHandling.php index a134b02504..66138a477c 100644 --- a/Neos.Utility.ObjectHandling/Classes/TypeHandling.php +++ b/Neos.Utility.ObjectHandling/Classes/TypeHandling.php @@ -28,7 +28,22 @@ abstract class TypeHandling /** * A type pattern to detect literal types. */ - const LITERAL_TYPE_PATTERN = '/^(?:integer|int|float|double|boolean|bool|string)$/'; + const LITERAL_TYPE_PATTERN = '/^(?:integer|int|float|double|boolean|bool|string|true|false|null)$/'; + + /** + * A type pattern to detect scalar types. + */ + const SCALAR_TYPE_PATTERN = '/^(?:int|float|bool|string)$/'; + + /** + * @var array + */ + protected static $builtInTypes = ['null', 'array', 'object', 'resource', 'never', 'void', 'self', 'parent', 'static']; + + /** + * @var array + */ + protected static $builtInTypeAliases = ['mixed', 'iterable']; /** * @var array>> @@ -96,21 +111,100 @@ public static function normalizeType(string $type): string * * @param string $type * @return boolean + * @deprecated use isLiteralType() */ public static function isLiteral(string $type): bool + { + return self::isLiteralType($type); + } + + /** + * Returns true if the $type is a scalar type. + * + * @param string $type + * @return bool + */ + public static function isScalarType(string $type): bool + { + return preg_match(self::SCALAR_TYPE_PATTERN, $type) === 1; + } + + /** + * Returns true if the $type is a built-in type. + * + * @param string $type + * @return bool + */ + public static function isBuiltInType(string $type): bool + { + if (self::isScalarType($type)) { + return true; + } + + return in_array($type, self::$builtInTypes, true); + } + + /** + * Returns true if the $type is a literal type. + * + * @param string $type + * @return bool + */ + public static function isLiteralType(string $type): bool { return preg_match(self::LITERAL_TYPE_PATTERN, $type) === 1; } + /** + * Returns true if the $type is callable. + * + * @param string $type + * @return bool + */ + public static function isCallableType(string $type): bool + { + return $type === 'callable'; + } + + /** + * Returns true if the $type is a built-in type alias. + * + * @param string $type + * @return bool + */ + public static function isBuiltInTypeAlias(string $type): bool + { + return in_array($type, self::$builtInTypeAliases, true); + } + + /** + * Returns true if the $type is user-defined. + * + * @param string $type + * @return bool + */ + public static function isUserDefinedType(string $type): bool + { + return !self::isBuiltInType($type) + && !self::isLiteralType($type) + && !self::isCallableType($type) + && !self::isBuiltInTypeAlias($type); + } + /** * Returns true if the $type is a simple type. * * @param string $type * @return boolean + * @deprecated use isBuiltInType(), isLiteralType(), isCallableType() or isBuiltInTypeAlias() */ public static function isSimpleType(string $type): bool { - return in_array(self::normalizeType($type), ['array', 'string', 'float', 'integer', 'boolean', 'null', 'false', 'true'], true); + $normalizedType = self::normalizeType($type); + + return $normalizedType === 'array' + || self::isLiteralType($type) + || in_array($normalizedType, ['null', 'false', 'true'], true); } /**