New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PHP 8 support #477
PHP 8 support #477
Conversation
Related: phpspec/phpspec#1314 |
I’d like to get #476 merged which would then simplify this a lot 👍 |
That would he lovely! We can remove a lot of Thank you. |
Ok I merged it. I actually started a branch like this one but the complexity got too much for me so I did that other change :) If you can rebase that looks good For debugging in php8 I had similar issues and resorted to running in 7.4 for debug just to figure out where calls were coming from |
Maybe split out the changes that are to get the existing suite paying, from changes to support new features (eg mixed hint) The latter would need additional tests etc |
Thanks a lot @ciaranmcnulty . I sent PR #478 to enable builds. We can either remove workarounds for PHP <7.2 first, and then work on PHP 8 fixes, or the other way around. |
@@ -45,7 +45,7 @@ class ClassMirror | |||
* | |||
* @throws \Prophecy\Exception\InvalidArgumentException | |||
*/ | |||
public function reflect(ReflectionClass $class = null, array $interfaces) | |||
public function reflect(ReflectionClass $class = null, array $interfaces = array()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would rather change that to ?ReflectionClass $class, array $interfaces
, to avoid changing the signature
@@ -250,7 +250,19 @@ private function isNullable(ReflectionParameter $parameter) | |||
private function getParameterClassName(ReflectionParameter $parameter) | |||
{ | |||
try { | |||
return $parameter->getClass() ? $parameter->getClass()->getName() : null; | |||
if (!method_exists($parameter, 'getType')) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The min version is now PHP 7.2, so this is never true.
if (!$type || $type->isBuiltin()) { | ||
return null; | ||
} | ||
if (!method_exists($type, 'getName')) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather add a check for instanceof ReflectionNamedType
, which will be needed anyway when adding the compatibility with union types.
@@ -222,11 +222,11 @@ private function getTypeHint(ReflectionParameter $parameter) | |||
return $className; | |||
} | |||
|
|||
if (true === $parameter->isArray()) { | |||
if (version_compare(PHP_VERSION, '8', '<') && true === $parameter->isArray()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest using \PHP_VERSION_ID < 80000
instead, which can be resolved at compile time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aha so that's the reason
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah (not that qualifying the call is important for that. Relying on constant fallback will delay it until runtime)
return 'array'; | ||
} | ||
|
||
if (version_compare(PHP_VERSION, '5.4', '>=') && true === $parameter->isCallable()) { | ||
if (true === $parameter->isCallable()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't we have a version check here too according to the commit message ?
please also rebase this PR now that code for PHP < 7.2 has been removed. |
Thanks a lot for the great feedback. I will rebase/update code with new minimum PHP version in mind and other changes. I used |
This pattern [emits a deprecation notice in PHP 8](https://php.watch/versions/8.0/deprecate-required-param-after-optional). First parameter to `\Prophecy\Doubler\Generator\ClassMirror::reflect()` is now marked nullable because PHP 7.2 is the new minimum PHP version.
…ay` deprecations `ReflectionParameter::isCallable()` and `ReflectionParameter::isArray()` are [deprecated in PHP 8](https://php.watch/versions/8.0/deprecated-reflectionparameter-methods). They are now replaced with `ReflectionParameter::getType()` calls.
[`ReflectionParameter::getClass()` is deprecated in PHP 8](https://php.watch/versions/8.0/deprecated-reflectionparameter-methods) It is now replaced with a combination of `ReflectionParameter::getType()` and `ReflectionParameter::getClass`.
…w nullability on it PHP 8's new [`mixed` type](https://php.watch/versions/8.0/mixed-type#nullable) cannot be used as a nullable type, and needs special handling.
@stof I rebased and made some changes in the code, and with PHP 7.2 as the minimum, I could remove a lot of code. It would be great if you could take a look. |
*/ | ||
public function reflect(ReflectionClass $class = null, array $interfaces) | ||
public function reflect(?ReflectionClass $class, array $interfaces) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a major breaking change because the class is non-final. Please revert.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This weirdly does not seem to cause any issue https://3v4l.org/roQB8 #lolphp
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, it's because the 2nd param is required, so PHP treats them all as required, and null is specially implemented.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@GrahamCampbell did you delete a comment? It's not an issue for callers because they have no way of taking advantage of the optionality
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeh, I replaced with with the comment that the 1st param was not really optional anyway
return $type->getName(); | ||
} | ||
|
||
return null; | ||
} catch (\ReflectionException $e) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't need this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's true @Ayesh the try/catch is because getClass
can throw, getName
does not
I this this PR is ready for merge now. It gets the ball rolling at least, even if it is not complete (just like the phpspec PR). |
Thanks, @Ayesh! |
Work in progress to bring PHP 8 support for prophecy.
Majority of the errors were deprecation notices. I fixed the optional-before-required errors and deprecation of
ReflectionParameter
methodsgetClass
,isCallable
, andisArray
with branching code that checksgetType
is available, and then uses it instead of the shorthand now-deprecated functions.I'm not completely sure about the fixes related to the new
mixed
type.After these changes, there are only 4 errors/failures remaining from PHPUnit:
I cannot get xdebug to work with PHP nightly builds, so these errors do not contain any backtraces. Any insights would be appreciated.
I tried to skip some of the tests (such as
#2
above) with@require PHP <= 8
annotations for the test because the deprecated behavior is exactly what's this test is asserting.ReflectionParameter::export
method is deprecated, and removed in PHP 8, which causes#3
above.