Skip to content

Commit

Permalink
[1.x] Fixes switch cases namespace resolution (#80)
Browse files Browse the repository at this point in the history
* Adds tests

* Apply fixes from StyleCI

* Fixes `instanceof` within switch cases

* Apply fixes from StyleCI

* Prefixes PHP version

* Apply fixes from StyleCI

* Adds PHP 8.0 tests

* Apply fixes from StyleCI

* Fixes existing tests

* Adds tests against namespaced class

* Adds reflection closure tests

* Apply fixes from StyleCI

* Fixes issue after style changes

* Fixes `:` namespace resolution

* Apply fixes from StyleCI

* Fixes test on PHP 7.4

* Apply fixes from StyleCI

* Space

* Another test

* More tests

---------

Co-authored-by: StyleCI Bot <[email protected]>
  • Loading branch information
nunomaduro and StyleCIBot authored Nov 8, 2023
1 parent ed9e590 commit 3dbf8a8
Show file tree
Hide file tree
Showing 6 changed files with 491 additions and 5 deletions.
3 changes: 1 addition & 2 deletions src/Support/ReflectionClosure.php
Original file line number Diff line number Diff line change
Expand Up @@ -508,8 +508,7 @@ public function getCode()
break;
case 'id_name':
switch ($token[0]) {
// named arguments...
case ':':
case $token[0] === ':' && $context !== 'instanceof':
if ($lastState === 'closure' && $context === 'root') {
$state = 'closure';
$code .= $id_start.$token;
Expand Down
87 changes: 87 additions & 0 deletions tests/ReflectionClosure1Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -297,3 +297,90 @@

expect($f1)->toBeCode($e1);
});

function reflection_closure_php_74_switch_statement_test_is_two($a)
{
return $a === 2;
}

class ReflectionClosurePhp74InstanceOfTest
{
}

class ReflectionClosurePhp74SwitchStatementTest
{
}

test('instanceof', function () {
$f1 = function ($a) {
$b = $a instanceof DateTime || $a instanceof ReflectionClosurePhp74InstanceOfTest || $a instanceof RegularClass;

return [
$b,
$a instanceof DateTime || $a instanceof ReflectionClosurePhp74InstanceOfTest || $a instanceof RegularClass,
(function ($a) {
return ($a instanceof DateTime || $a instanceof ReflectionClosurePhp74InstanceOfTest || $a instanceof RegularClass) === true;
})($a),
];
};

$e1 = 'function ($a) {
$b = $a instanceof \DateTime || $a instanceof \ReflectionClosurePhp74InstanceOfTest || $a instanceof \Tests\Fixtures\RegularClass;
return [
$b,
$a instanceof \DateTime || $a instanceof \ReflectionClosurePhp74InstanceOfTest || $a instanceof \Tests\Fixtures\RegularClass,
(function ($a) {
return ($a instanceof \DateTime || $a instanceof \ReflectionClosurePhp74InstanceOfTest || $a instanceof \Tests\Fixtures\RegularClass) === true;
})($a),
];
}';

expect($f1)->toBeCode($e1);
});

test('switch statement', function () {
$f1 = function ($a) {
switch (true) {
case $a === 1:
return 'one';
case reflection_closure_php_74_switch_statement_test_is_two($a):
return 'two';
case ReflectionClosurePhp74SwitchStatementTest::isThree($a):
return 'three';
case (new ReflectionClosurePhp74SwitchStatementTest)->isFour($a):
return 'four';
case $a instanceof ReflectionClosurePhp74SwitchStatementTest:
return 'five';
case $a instanceof DateTime:
return 'six';
case $a instanceof RegularClass:
return 'seven';
default:
return 'other';
}
};

$e1 = 'function ($a) {
switch (true) {
case $a === 1:
return \'one\';
case \reflection_closure_php_74_switch_statement_test_is_two($a):
return \'two\';
case \ReflectionClosurePhp74SwitchStatementTest::isThree($a):
return \'three\';
case (new \ReflectionClosurePhp74SwitchStatementTest)->isFour($a):
return \'four\';
case $a instanceof \ReflectionClosurePhp74SwitchStatementTest:
return \'five\';
case $a instanceof \DateTime:
return \'six\';
case $a instanceof \Tests\Fixtures\RegularClass:
return \'seven\';
default:
return \'other\';
}
}';

expect($f1)->toBeCode($e1);
});
164 changes: 161 additions & 3 deletions tests/ReflectionClosurePhp80Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

// Fake
use Some\ClassName as ClassAlias;
use Tests\Fixtures\RegularClass;

test('union types', function () {
$f1 = fn (): string|int|false|Bar|null => 1;
Expand Down Expand Up @@ -86,7 +87,7 @@
}";

expect($f1)->toBeCode($e1);
})->with('serializers');
});

test('single named argument within closures', function () {
$f1 = function () {
Expand All @@ -98,7 +99,7 @@
}";

expect($f1)->toBeCode($e1);
})->with('serializers');
});

test('multiple named arguments within closures', function () {
$f1 = function () {
Expand All @@ -110,7 +111,29 @@
}";

expect($f1)->toBeCode($e1);
})->with('serializers');
});

test('named arguments with switch cases and instanceof', function () {
$f1 = function ($a) {
switch (true) {
case (new RegularClass(a2: $a))->a2 instanceof RegularClass:
return (new RegularClass(a2: $a))->a2;
default:
return new RegularClass(a2: RegularClass::C);
}
};

$e1 = 'function ($a) {
switch (true) {
case (new \Tests\Fixtures\RegularClass(a2: $a))->a2 instanceof \Tests\Fixtures\RegularClass:
return (new \Tests\Fixtures\RegularClass(a2: $a))->a2;
default:
return new \Tests\Fixtures\RegularClass(a2: \Tests\Fixtures\RegularClass::C);
}
}';

expect($f1)->toBeCode($e1);
});

test('multiple named arguments within nested closures', function () {
$f1 = function () {
Expand Down Expand Up @@ -159,3 +182,138 @@ public function getPrivate(): string
return $this->private;
}
}

function reflection_closure_php_80_switch_statement_test_is_two($a)
{
return $a === 2;
}

class ReflectionClosurePhp80InstanceOfTest
{
};

class ReflectionClosurePhp80SwitchStatementTest
{
}

test('instanceof', function () {
$f1 = function (object $a): array {
$b = $a instanceof DateTime || $a instanceof ReflectionClosurePhp80InstanceOfTest || $a instanceof RegularClass;

return [
$b,
($a instanceof DateTime || $a instanceof ReflectionClosurePhp80InstanceOfTest || $a instanceof RegularClass),
(function (object $a): bool {
return ($a instanceof DateTime || $a instanceof ReflectionClosurePhp80InstanceOfTest || $a instanceof RegularClass) === true;
})(a: $a),
];
};

$e1 = 'function (object $a): array {
$b = $a instanceof \DateTime || $a instanceof \ReflectionClosurePhp80InstanceOfTest || $a instanceof \Tests\Fixtures\RegularClass;
return [
$b,
($a instanceof \DateTime || $a instanceof \ReflectionClosurePhp80InstanceOfTest || $a instanceof \Tests\Fixtures\RegularClass),
(function (object $a): bool {
return ($a instanceof \DateTime || $a instanceof \ReflectionClosurePhp80InstanceOfTest || $a instanceof \Tests\Fixtures\RegularClass) === true;
})(a: $a),
];
}';

expect($f1)->toBeCode($e1);
});

test('switch statement', function () {
$f1 = function ($a) {
switch (true) {
case $a === 1:
return 'one';
case reflection_closure_php_80_switch_statement_test_is_two(a: $a):
return 'two';
case ReflectionClosurePhp80SwitchStatementTest::isThree(a: $a):
return 'three';
case (new ReflectionClosurePhp80SwitchStatementTest)->isFour(a: $a):
return 'four';
case ($a instanceof ReflectionClosurePhp80SwitchStatementTest):
return 'five';
case ($a instanceof DateTime):
return 'six';
case ($a instanceof RegularClass):
return 'seven';
default:
return 'other';
}
};

$e1 = 'function ($a) {
switch (true) {
case $a === 1:
return \'one\';
case \reflection_closure_php_80_switch_statement_test_is_two(a: $a):
return \'two\';
case \ReflectionClosurePhp80SwitchStatementTest::isThree(a: $a):
return \'three\';
case (new \ReflectionClosurePhp80SwitchStatementTest)->isFour(a: $a):
return \'four\';
case ($a instanceof \ReflectionClosurePhp80SwitchStatementTest):
return \'five\';
case ($a instanceof \DateTime):
return \'six\';
case ($a instanceof \Tests\Fixtures\RegularClass):
return \'seven\';
default:
return \'other\';
}
}';

expect($f1)->toBeCode($e1);
});

function reflection_closure_php_80_match_statement_test_is_two($a)
{
return $a === 2;
}

class ReflectionClosurePhp80MatchStatementTest
{
public static function isThree($a)
{
return $a === 3;
}

public function isFour($a)
{
return $a === 4;
}
}

test('match statement', function () {
$f1 = function ($a) {
return match (true) {
$a === 1 => 'one',
reflection_closure_php_80_match_statement_test_is_two($a) => 'two',
ReflectionClosurePhp80MatchStatementTest::isThree(a: $a) => 'three',
(new ReflectionClosurePhp80MatchStatementTest)->isFour($a) => 'four',
$a instanceof ReflectionClosurePhp80MatchStatementTest => 'five',
$a instanceof DateTime => 'six',
$a instanceof RegularClass => 'seven',
default => 'other',
};
};

$e1 = 'function ($a) {
return match (true) {
$a === 1 => \'one\',
\reflection_closure_php_80_match_statement_test_is_two($a) => \'two\',
\ReflectionClosurePhp80MatchStatementTest::isThree(a: $a) => \'three\',
(new \ReflectionClosurePhp80MatchStatementTest)->isFour($a) => \'four\',
$a instanceof \ReflectionClosurePhp80MatchStatementTest => \'five\',
$a instanceof \DateTime => \'six\',
$a instanceof \Tests\Fixtures\RegularClass => \'seven\',
default => \'other\',
};
}';

expect($f1)->toBeCode($e1);
});
10 changes: 10 additions & 0 deletions tests/ReflectionClosurePhp81Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@ enum GlobalEnum {
a18: reflection_closure_my_function(),
a19: reflection_closure_my_function(ReflectionClosureGlobalEnum::Guest),
a20: reflection_closure_my_function(enum: ReflectionClosureGlobalEnum::Guest),
a21: match (true) {
true => new RegularClass(),
false => (new RegularClass()) instanceof RegularClass,
default => reflection_closure_my_function(enum: ReflectionClosureGlobalEnum::Guest),
},
);
};

Expand Down Expand Up @@ -276,6 +281,11 @@ enum GlobalEnum {
a18: \\reflection_closure_my_function(),
a19: \\reflection_closure_my_function(\ReflectionClosureGlobalEnum::Guest),
a20: \\reflection_closure_my_function(enum: \ReflectionClosureGlobalEnum::Guest),
a21: match (true) {
true => new \Tests\Fixtures\RegularClass(),
false => (new \Tests\Fixtures\RegularClass()) instanceof \Tests\Fixtures\RegularClass,
default => \\reflection_closure_my_function(enum: \ReflectionClosureGlobalEnum::Guest),
},
);
}";

Expand Down
Loading

0 comments on commit 3dbf8a8

Please sign in to comment.