-
Notifications
You must be signed in to change notification settings - Fork 242
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
Initial idea for Intersection/Union types #569
base: master
Are you sure you want to change the base?
Conversation
Adding void return type fixture and test.
Removing naming normalization of types from node to ClassMirror.php.
Temp commit.
/** | ||
* @param NamedTypeNode ...$types | ||
*/ | ||
public function __construct(bool $allowsNull = false, NamedTypeNode ...$types) |
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 make it an array rather than a variadic argument. Otherwise, we have no way to add more parameters in the signature in the future.
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.
Sure
{ | ||
$string = ''; | ||
foreach ($this->types as $type) { | ||
$string .= $type . '|'; |
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 code would be much simpler by using return implode('|', $this->types)
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.
Sure.
/** | ||
* @see \ReflectionNamedType | ||
*/ | ||
class NamedTypeNode extends TypeNodeAbstract implements Type |
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.
extending TypeNodeAbstract without calling the parent constructor is a no-go to me, as it does not initialize the parent properties properly. To me, there is no reason to extend TypeNodeAbstract here
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.
Refactored some of the Type's. Now the TypeNodeAbstract does not have a __constrcut
.
class UnionTypeNode extends TypeNodeAbstract implements Type | ||
{ | ||
/** | ||
* @var NamedTypeNode[] |
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 should be Type[]
as PHP 8.2 supports putting intersections inside unions
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 was targeted for PHP81 intersection at the moment. The extra pull request for DNF is pretty easy and would include 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.
Well, I would work on both at the same time actually (otherwise, your PR needs to include a nice handling of DNF to fail with a good error message, which is not worth it IMO). Thus, as those classes are not marked as internal, you would still need to do the work in the same release to avoid having to introduce BC layers.
return ''; | ||
} | ||
|
||
// When we require PHP 8 we can stop generating ?foo nullables and remove this first block | ||
if ($typeNode->canUseNullShorthand()) { | ||
return sprintf( '?%s', $typeNode->getNonNullTypes()[0]); | ||
return sprintf( '?%s', $typeNode->getType()->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.
this is broken if $typeNode->getType()
is not a NamedTypeNode`
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 baked into $typeNode->canUseNullShorthand()
since only NamedType can be shorthand.
foreach ($this->types as $type) { | ||
$string .= $type . '&'; | ||
} | ||
return '(' . rtrim($string, '&') . ')'; |
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.
those braces will be broken in PHP 8.1, and will be useless in PHP 8.2+ when the intersection is not part of a union
if (isset($this->types['never']) && count($this->types) !== 1) { | ||
throw new DoubleException('never cannot be part of a union'); | ||
if ($this->type instanceof UnionTypeNode) { | ||
/** @var NamedTypeNode $type */ |
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.
Assuming this here will not support DNF types. Instead, you should have a check if (!$type instanceof NamedTypeNode) continue;
/** | ||
* @see \ReflectionIntersectionType | ||
*/ | ||
class IntersectionTypeNode extends TypeNodeAbstract implements Type |
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 remove Node
from the names of those classes representing types.
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.
Sure.
return $this->allowsNull; | ||
} | ||
|
||
public function getTypes(): 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 not add this method here. It makes no sense for NamedTypeNode to define it. And having it only in specific classes would force to check the type before using it, which is good because subtypes of a union or of an intersection should almost never be used the same.
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.
It's been removed during a refactor.
|
||
namespace Prophecy\Doubler\Generator\Node; | ||
|
||
interface Type |
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 interface needs to enforce types being stringable, as the code relies on it.
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.
Sure
Awesome, thanks for the feedback. Seems like you're ok with the BC breaks in signatures. |
|
||
public function __toString(): string | ||
{ | ||
return $this->name; |
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.
NamedTypeNode should not require passing the leading \
IMO. Otherwise, it makes it impossible to use it with Foo::class
, which would be a confusing API when building class patches.
@kschatzle it would be better if ArgumentTypeNode and ReturnTypeNode could have a BC layer for their |
@kschatzle Is this something still actively being worked on. Can I help out in any way? |
I need to get back to this eventually when I have time. Some IRL stuff. |
Doctrine has changed the return type from ObjectRepository to EntityRepository https://github.com/doctrine/DoctrineBundle/blob/2.12.x/src/Repository/RepositoryFactoryCompatibility.php (in ORM 3.x). This triggers now the following error in phpspec "doubling intersection types is not supported" |
@dannyvw how is this related ? There is no union type nor intersection type in this trait |
@stof The issue is related to the changes inside EntityRepository (https://github.com/doctrine/orm/blob/3.1.x/src/EntityRepository.php) and the return type change. If you have a test case like below then it triggers this error "doubling intersection types is not supported".
|
I doubt the code you linked is relevant then, as there is no intersection type anywhere in this file. Anyway, this PR is not ready to be merged. If you want this to move forward without waiting for the author to get back to it, an option is to take over the work to finish it. |
Not sure either but the EntityRepository was the class inside the error. This error "doubling intersection types is not supported" is only triggered when upgrading doctrine/orm from 2.19 to 3.x. |
Hey all, is this pull request still in progress? What's missing? |
none of the review comments have been taken into account for now. |
Not close to finishing, but what do you think about the direction before I get everything ironed out? (Not all unit tests pass yet).
#535