Skip to content

Commit

Permalink
Merge branch 'master' into issues/557
Browse files Browse the repository at this point in the history
  • Loading branch information
ciaranmcnulty authored Nov 29, 2022
2 parents 3f007e2 + c5281eb commit 8ed6049
Show file tree
Hide file tree
Showing 20 changed files with 194 additions and 154 deletions.
4 changes: 1 addition & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,13 @@ jobs:
strategy:
fail-fast: false
matrix:
php: [7.2, 7.3, 7.4, 8.0]
php: ["7.2", "7.3", "7.4", "8.0", "8.1", "8.2"]
composer-flags: [ "" ]
experimental: [false]
include:
- php: 7.2
composer-flags: "--prefer-lowest"
experimental: false
- php: 8.1
experimental: true

steps:
- uses: actions/checkout@v2
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
],

"require": {
"php": "^7.2 || ~8.0, <8.2",
"php": "^7.2 || 8.0.* || 8.1.* || 8.2.*",
"phpdocumentor/reflection-docblock": "^5.2",
"sebastian/comparator": "^3.0 || ^4.0",
"doctrine/instantiator": "^1.2",
Expand Down
11 changes: 11 additions & 0 deletions fixtures/DnfArgumentType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace Fixtures\Prophecy;

class DnfArgumentType
{
public function doSomething ((A&B)|C $foo)
{

}
}
11 changes: 11 additions & 0 deletions fixtures/DnfReturnType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace Fixtures\Prophecy;

class DnfReturnType
{
public function doSomething () : (A&B)|C
{

}
}
7 changes: 7 additions & 0 deletions fixtures/ReadOnlyClass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace Fixtures\Prophecy;

readonly class ReadOnlyClass
{
}
8 changes: 4 additions & 4 deletions spec/Prophecy/Argument/ArgumentsWildcardSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ function it_wraps_non_token_arguments_into_ExactValueToken(\stdClass $object)
$this->beConstructedWith(array(42, 'zet', $object));

$class = get_class($object->getWrappedObject());
$hash = spl_object_hash($object->getWrappedObject());
$id = spl_object_id($object->getWrappedObject());

$objHash = "exact(42), exact(\"zet\"), exact($class:$hash Object (\n 'objectProphecyClosure' => Closure:%s Object (\n 0 => Closure:%s Object\n )\n))";
$objHash = "exact(42), exact(\"zet\"), exact($class#$id Object (\n 'objectProphecyClosure' => Closure#%s Object (\n 0 => Closure#%s Object\n )\n))";

$hashRegexExpr = '[a-f0-9]{32}';
$this->__toString()->shouldMatch(sprintf('/^%s$/', sprintf(preg_quote("$objHash"), $hashRegexExpr, $hashRegexExpr)));
$idRegexExpr = '[0-9]+';
$this->__toString()->shouldMatch(sprintf('/^%s$/', sprintf(preg_quote("$objHash"), $idRegexExpr, $idRegexExpr)));
}

function it_generates_string_representation_from_all_tokens_imploded(
Expand Down
10 changes: 5 additions & 5 deletions spec/Prophecy/Argument/Token/ExactValueTokenSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -133,15 +133,15 @@ function it_generates_proper_string_representation_for_resource()

function it_generates_proper_string_representation_for_object(\stdClass $object)
{
$objHash = sprintf('exact(%s:%s',
$objHash = sprintf('exact(%s#%s',
get_class($object->getWrappedObject()),
spl_object_hash($object->getWrappedObject())
) . " Object (\n 'objectProphecyClosure' => Closure:%s Object (\n 0 => Closure:%s Object\n )\n))";
spl_object_id($object->getWrappedObject())
) . " Object (\n 'objectProphecyClosure' => Closure#%s Object (\n 0 => Closure#%s Object\n )\n))";

$this->beConstructedWith($object);

$hashRegexExpr = '[a-f0-9]{32}';
$this->__toString()->shouldMatch(sprintf('/^%s$/', sprintf(preg_quote("$objHash"), $hashRegexExpr, $hashRegexExpr)));
$idRegexExpr = '[0-9]+';
$this->__toString()->shouldMatch(sprintf('/^%s$/', sprintf(preg_quote("$objHash"), $idRegexExpr, $idRegexExpr)));
}
}

Expand Down
10 changes: 5 additions & 5 deletions spec/Prophecy/Argument/Token/IdenticalValueTokenSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -141,14 +141,14 @@ function it_generates_proper_string_representation_for_resource()

function it_generates_proper_string_representation_for_object($object)
{
$objHash = sprintf('identical(%s:%s',
$objHash = sprintf('identical(%s#%s',
get_class($object->getWrappedObject()),
spl_object_hash($object->getWrappedObject())
) . " Object (\n 'objectProphecyClosure' => Closure:%s Object (\n 0 => Closure:%s Object\n )\n))";
spl_object_id($object->getWrappedObject())
) . " Object (\n 'objectProphecyClosure' => Closure#%s Object (\n 0 => Closure#%s Object\n )\n))";

$this->beConstructedWith($object);

$hashRegexExpr = '[a-f0-9]{32}';
$this->__toString()->shouldMatch(sprintf('/^%s$/', sprintf(preg_quote("$objHash"), $hashRegexExpr, $hashRegexExpr)));
$idRegexExpr = '[0-9]+';
$this->__toString()->shouldMatch(sprintf('/^%s$/', sprintf(preg_quote("$objHash"), $idRegexExpr, $idRegexExpr)));
}
}
34 changes: 0 additions & 34 deletions spec/Prophecy/Doubler/ClassPatch/HhvmExceptionPatchSpec.php

This file was deleted.

28 changes: 28 additions & 0 deletions spec/Prophecy/Doubler/Generator/ClassCodeGeneratorSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ function it_generates_proper_php_code_for_specific_ClassNode(
));
$class->getProperties()->willReturn(array('name' => 'public', 'email' => 'private'));
$class->getMethods()->willReturn(array($method1, $method2, $method3, $method4, $method5));
$class->isReadOnly()->willReturn(false);

$method1->getName()->willReturn('getName');
$method1->getVisibility()->willReturn('public');
Expand Down Expand Up @@ -156,6 +157,7 @@ function it_generates_proper_php_code_for_variadics(
$class->getMethods()->willReturn(array(
$method1, $method2, $method3, $method4
));
$class->isReadOnly()->willReturn(false);

$method1->getName()->willReturn('variadic');
$method1->getVisibility()->willReturn('public');
Expand Down Expand Up @@ -248,6 +250,7 @@ function it_overrides_properly_methods_with_args_passed_by_reference(
$class->getInterfaces()->willReturn(array('Prophecy\Doubler\Generator\MirroredInterface'));
$class->getProperties()->willReturn(array());
$class->getMethods()->willReturn(array($method));
$class->isReadOnly()->willReturn(false);

$method->getName()->willReturn('getName');
$method->getVisibility()->willReturn('public');
Expand Down Expand Up @@ -290,6 +293,7 @@ function it_generates_proper_code_for_union_return_types
$class->getInterfaces()->willReturn([]);
$class->getProperties()->willReturn([]);
$class->getMethods()->willReturn(array($method));
$class->isReadOnly()->willReturn(false);

$method->getName()->willReturn('foo');
$method->getVisibility()->willReturn('public');
Expand Down Expand Up @@ -328,6 +332,7 @@ function it_generates_proper_code_for_union_argument_types
$class->getInterfaces()->willReturn([]);
$class->getProperties()->willReturn([]);
$class->getMethods()->willReturn(array($method));
$class->isReadOnly()->willReturn(false);

$method->getName()->willReturn('foo');
$method->getVisibility()->willReturn('public');
Expand Down Expand Up @@ -367,6 +372,7 @@ function it_generates_empty_class_for_empty_ClassNode(ClassNode $class)
$class->getInterfaces()->willReturn(array('Prophecy\Doubler\Generator\MirroredInterface'));
$class->getProperties()->willReturn(array());
$class->getMethods()->willReturn(array());
$class->isReadOnly()->willReturn(false);

$code = $this->generate('CustomClass', $class);
$expected =<<<'PHP'
Expand All @@ -387,13 +393,35 @@ function it_wraps_class_in_namespace_if_it_is_namespaced(ClassNode $class)
$class->getInterfaces()->willReturn(array('Prophecy\Doubler\Generator\MirroredInterface'));
$class->getProperties()->willReturn(array());
$class->getMethods()->willReturn(array());
$class->isReadOnly()->willReturn(false);

$code = $this->generate('My\Awesome\CustomClass', $class);
$expected =<<<'PHP'
namespace My\Awesome {
class CustomClass extends \stdClass implements \Prophecy\Doubler\Generator\MirroredInterface {
}
}
PHP;
$expected = strtr($expected, array("\r\n" => "\n", "\r" => "\n"));
$code->shouldBe($expected);
}

function it_generates_read_only_class_if_parent_class_is_read_only(ClassNode $class)
{
$class->getParentClass()->willReturn('ReadOnlyClass');
$class->getInterfaces()->willReturn(array('Prophecy\Doubler\Generator\MirroredInterface'));
$class->getProperties()->willReturn(array());
$class->getMethods()->willReturn(array());
$class->isReadOnly()->willReturn(true);

$code = $this->generate('CustomClass', $class);
$expected =<<<'PHP'
namespace {
readonly class CustomClass extends \ReadOnlyClass implements \Prophecy\Doubler\Generator\MirroredInterface {
}
}
PHP;
Expand Down
12 changes: 12 additions & 0 deletions spec/Prophecy/Doubler/Generator/Node/ClassNodeSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -182,4 +182,16 @@ function it_throws_an_exception_when_adding_a_method_that_isnt_extendable(Method
);
$this->shouldThrow($expectedException)->duringAddMethod($method);
}

function it_is_non_read_only_by_default()
{
$this->isReadOnly()->shouldReturn(false);
}

function its_read_only_is_mutable()
{
$this->setReadOnly(true);

$this->isReadOnly()->shouldReturn(true);
}
}
14 changes: 7 additions & 7 deletions spec/Prophecy/Util/StringUtilSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,20 +71,20 @@ function it_generates_proper_string_representation_for_resource()

function it_generates_proper_string_representation_for_object(\stdClass $object)
{
$objHash = sprintf('%s:%s',
$objHash = sprintf('%s#%s',
get_class($object->getWrappedObject()),
spl_object_hash($object->getWrappedObject())
) . " Object (\n 'objectProphecyClosure' => Closure:%s Object (\n 0 => Closure:%s Object\n )\n)";
spl_object_id($object->getWrappedObject())
) . " Object (\n 'objectProphecyClosure' => Closure#%s Object (\n 0 => Closure#%s Object\n )\n)";

$hashRegexExpr = '[a-f0-9]{32}';
$this->stringify($object)->shouldMatch(sprintf('/^%s$/', sprintf(preg_quote("$objHash"), $hashRegexExpr, $hashRegexExpr)));
$idRegexExpr = '[0-9]+';
$this->stringify($object)->shouldMatch(sprintf('/^%s$/', sprintf(preg_quote("$objHash"), $idRegexExpr, $idRegexExpr)));
}

function it_generates_proper_string_representation_for_object_without_exporting(\stdClass $object)
{
$objHash = sprintf('%s:%s',
$objHash = sprintf('%s#%s',
get_class($object->getWrappedObject()),
spl_object_hash($object->getWrappedObject())
spl_object_id($object->getWrappedObject())
);

$this->stringify($object, false)->shouldReturn("$objHash");
Expand Down
63 changes: 0 additions & 63 deletions src/Prophecy/Doubler/ClassPatch/HhvmExceptionPatch.php

This file was deleted.

7 changes: 5 additions & 2 deletions src/Prophecy/Doubler/Generator/ClassCodeGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,11 @@ public function generate($classname, Node\ClassNode $class)
$classname = array_pop($parts);
$namespace = implode('\\', $parts);

$code = sprintf("class %s extends \%s implements %s {\n",
$classname, $class->getParentClass(), implode(', ',
$code = sprintf("%sclass %s extends \%s implements %s {\n",
$class->isReadOnly() ? 'readonly ': '',
$classname,
$class->getParentClass(),
implode(', ',
array_map(function ($interface) {return '\\'.$interface;}, $class->getInterfaces())
)
);
Expand Down
11 changes: 11 additions & 0 deletions src/Prophecy/Doubler/Generator/ClassMirror.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ private function reflectClassToNode(ReflectionClass $class, Node\ClassNode $node
), $class);
}

if (method_exists(ReflectionClass::class, 'isReadOnly')) {
$node->setReadOnly($class->isReadOnly());
}

$node->setParentClass($class->getName());

foreach ($class->getMethods(ReflectionMethod::IS_ABSTRACT) as $method) {
Expand Down Expand Up @@ -223,6 +227,13 @@ private function getTypeHints(?ReflectionType $type, ?ReflectionClass $class, bo
}
elseif ($type instanceof ReflectionUnionType) {
$types = $type->getTypes();
if (\PHP_VERSION_ID >= 80200) {
foreach ($types as $reflectionType) {
if ($reflectionType instanceof ReflectionIntersectionType) {
throw new ClassMirrorException('Doubling intersection types is not supported', $class);
}
}
}
}
elseif ($type instanceof ReflectionIntersectionType) {
throw new ClassMirrorException('Doubling intersection types is not supported', $class);
Expand Down
Loading

0 comments on commit 8ed6049

Please # to comment.