Skip to content

Reflection compliance #1600

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

Closed
wants to merge 67 commits into from
Closed

Conversation

thekid
Copy link
Contributor

@thekid thekid commented Jan 19, 2014

This pull request aims at achieving a greater level of compliance with the original PHP reflection API. It uses these behaviour tests to verify the Reflection classes' functionality.

These bugs are fixed:

Furthermore, these issues are addressed:

  • Support for parent and self as parameter type hints
  • Missing ReflectionFunction::inNamespace(), isDeprecated(), getExtension(), getExtensionName()
  • ReflectionFunction::getStaticVariables() returns string representations of statics, not the actual values
  • Fix BadMethodCallException for ReflectionClass::getExtensionName()
  • ReflectionClass::isAbstract() does not return true for traits
  • ReflectionParameter::__toString should include indicator whether passed by reference
  • ReflectionFunction does not have a public name member
  • ReflectionParameter::isDefaultValueConstant() is missing
  • ReflectionParameter::getDefaultValueConstantName() returns PHP code instead of constant name

There are still differences to the PHP API which I could not or did not address here (e.g. all extension related reflection - HipHop's concept seems to work differently than PHP's, I still haven't quite understood how this could be made to work) and cases in which PHP raises errors, where HipHop throws exceptions for self-consistency.

thekid added 23 commits January 13, 2014 02:38
. For integers, check if the offset exists, raise a ReflectionException otherwise
. For any other type, cast to string, search, raise a ReflectionException if not found
Fixes facebook#1572
Note: Behaves differently than PHP which fatals, using BadMethodCallException
here in alignment with "fatal error: call to a method of a non-object"
Set this inside ReflectionFunctionAbstract's constructor, and call into
it from both ReflectionFunction and ReflectionMethod
  when there is no extension, which is the case for userland classes
The name member is declared by ReflectionMethod's parent class,
ReflectionFunctionAbstract, and thus appears in a different place
in the output
These functions are implemented in a skeletal way and will always
return NULL (or FALSE - anyways, as if there were no extension).
This way, we at least no longer get fatal errors though...
Always returns FALSE at the moment
This way, we at least no longer get fatal errors though
This sucks: PHP returns false instead of throwing an exception, which would
be better, and we'd be able to distinguish here from the case where a class
constant carries the value FALSE. Nevertheless, be compliant
Still missing: Return by reference, api doc comment, closure handling
@@ -432,6 +463,11 @@ public function isCallable() {
return $this->getTypeText() === 'callable';
}

// Prevent cloning
public function __clone() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not private?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To not raise fatal errors but to be able to throw an exception, in the spirit of $null->method(); also not fatalling in HHVM.

@Maks3w
Copy link

Maks3w commented Jan 20, 2014

With the support of parent and self you are fixing #1499 too

Fixes facebook#1499
fpi.phpCode() will already contain resolved fully qualified
class names for constants such as `self::CONSTANT` or
`ClassName::CONSTANT`; and will contain `CONSTANT` for
global constants, both need to be evaluated in the global
namespace
We now habe a __toString() implementation in ReflectionFunction
Also fix up flaky tests asserting on hardcoded object ids
Indent correctly, at the same time, not like PHP (see thekid/behave@4b0850d)
thekid added 2 commits March 16, 2014 11:56
See facebook#1600 (comment)
This parameter is only used to detect whether too many arguments where
passed and has no other meaning AFAIS
@thekid
Copy link
Contributor Author

thekid commented Mar 16, 2014

...though no. 3 surely has the least impact:

-.function array_filter($arr = no_args, $func = start("""null"""), $res = start) {
+.function array_filter($arr = no_args, $func = start("""null"""), $res = start("""null""")) {
           .numiters 2;

-# if we get here, a value was supplied for $res
+# if we get here, a value was supplied for $res. NULL is OK.
+          IssetL $res
+          JmpZ start
+

...so I've implemented that for a starter.

$ find hphp/test/ -name 'array_filter*.php' | grep -v bad \|
  xargs ./hphp/test/run hphp/test/slow/reflection/hhas_defaults.php
Running 12 tests in 9 threads
............
All tests passed.

@thekid
Copy link
Contributor Author

thekid commented Mar 16, 2014

I'm seeing failures in default_value_with_self

$ ./hphp/test/run hphp/test/slow/reflection_classes/default_value_with_self.php
Running 1 tests in 1 threads
.
All tests passed.

@thekid
Copy link
Contributor Author

thekid commented Mar 16, 2014

I've found a workaround to the double-namespacing issue which aligns nicely along what was done in 3504e7a to fix #1449 and #1652 but I'm not sure this is the right place

@ptarjan
Copy link
Contributor

ptarjan commented Mar 17, 2014

@thekid I would like to see #1357 fixed anyways, so maybe this is the time. I tried to add your fix internally and @jdelong (correctly) pushed back saying that php totally allows you to have a param without a default value after a param with a default value.

@thekid
Copy link
Contributor Author

thekid commented Mar 17, 2014

Yes, PHP allows this, but reflection then doesn't regard these parameters as optional then, since in reality, you can't omit if from the call:)

As said, it's easy to change HHVM to behave differently, but this is not this pull request's intention:) Alternatively, there's option no. 2, where we change array_filter's signature and remove the third parameter, whose sole purpose is to detect excess arguments.

ptarjan added a commit that referenced this pull request Mar 18, 2014
In #1600 we are actually supporting printing of default args, which evals them. All this stuff uses c-strings all the way down so we need to escape nulls.

Reviewed By: @elgenie

Differential Revision: D1223776
@GrahamCampbell
Copy link
Contributor

I take it this will have to wait until 2.6 now?

@ptarjan
Copy link
Contributor

ptarjan commented Mar 19, 2014

@GrahamCampbell yes, there was just too many issues. I'm still fighting with some and there is a chance of it going into a point release, but the prospects of 2.5 are bad.

@GrahamCampbell
Copy link
Contributor

It's a shame. Still, it does fix a lot off issues as well as introducing some...

@ptarjan
Copy link
Contributor

ptarjan commented Mar 19, 2014

@GrahamCampbell right, but more importantly it breaks things that real consumers of HHVM are using already. That can't happen.

@GrahamCampbell
Copy link
Contributor

In that case, I'll be looking forward to 2.6 then. :)

@thekid
Copy link
Contributor Author

thekid commented Mar 20, 2014

@ptarjan - let me know if I can do anything (or if that would make things worse:))

@ptarjan
Copy link
Contributor

ptarjan commented Mar 20, 2014

@thekid next time make lots of small PRs that can stand on their own please :) It makes bisecting errors so much easier

@thekid
Copy link
Contributor Author

thekid commented Mar 20, 2014

You're right. This somehow escalated.

@GrahamCampbell
Copy link
Contributor

I see that the next release will be 3.0, not 2.5. Would it be possible to delay the 3.0 release a few days so we could get this into it?

@ptarjan
Copy link
Contributor

ptarjan commented Apr 8, 2014

I've been fighting through this and I think I have to declare bankruptcy. Untangling the various issues is very hard on something this large.

I need you (or someone else) to split this up into multiple directed PRs that are segmented and individually tested. There are 67 commits in here, many of which are not tested and break lots of things in subtle ways. I don't know good cut points to easily test. There are lots of new functions added without any tests calling them.

This is the diff I ended up with if you want to start at it and cut down instead: https://gist.github.com/10075701

@ptarjan ptarjan closed this Apr 8, 2014
@Ocramius
Copy link
Contributor

Ocramius commented Apr 8, 2014

@ptarjan all the issues referencing this one as "possible fix" should probably be reopened.

@ptarjan
Copy link
Contributor

ptarjan commented Apr 8, 2014

@Ocramius which ones? The ones referenced in the top are all open except for one which was independently fixed.

@Ocramius
Copy link
Contributor

Ocramius commented Apr 8, 2014

@ptarjan nvm - went through them, they are indeed all open.

@thekid thekid deleted the reflection-compliance branch April 9, 2014 06:53
@BenMorel
Copy link

@Ocramius @ptarjan There doesn't seem to be an open issue for the missing ReflectionParameter::isDefaultValueConstant() method, should I create a new one?

@Ocramius
Copy link
Contributor

@BenMorel go for it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants