Skip to content
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

fix: Append alias class statement correct when the class/interface is within a statement #966

Merged
merged 4 commits into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/e2e-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ jobs:
- 'e2e_035'
- 'e2e_036'
- 'e2e_037'
- 'e2e_040'
php:
- '8.2'
- '8.3'
Expand Down
18 changes: 18 additions & 0 deletions .makefile/e2e.file
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,24 @@ e2e_039: $(PHP_SCOPER_PHAR_BIN)
> build/set039/output || true
diff fixtures/set039-min-php-version/expected-output build/set039/output

.PHONY: e2e_040
e2e_040: # Runs end-to-end tests for the fixture set e2e_040 — Codebase using a polyfill
e2e_040: $(PHP_SCOPER_PHAR_BIN)
rm -rf fixtures/set040-polyfills/vendor || true
composer --working-dir=fixtures/set040-polyfills dump-autoload

$(PHP_SCOPER_PHAR) add-prefix . \
--working-dir=fixtures/set040-polyfills \
--output-dir=../../build/set040 \
--force \
--no-interaction \
--stop-on-failure
composer --working-dir=build/set040 dump-autoload

php build/set040/index.php > build/set040/output || true

diff fixtures/set040-polyfills/expected-output build/set040/output


#
# Rules from files
Expand Down
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,8 @@ e2e: e2e_004 \
e2e_036 \
e2e_037 \
e2e_038 \
e2e_039
e2e_039 \
e2e_040

.PHONY: blackfire
blackfire: ## Runs Blackfire profiling
Expand Down
15 changes: 15 additions & 0 deletions fixtures/set040-polyfills/bootstrap.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php declare(strict_types=1);

use Set040\Php20;

if (PHP_VERSION_ID >= 200_000) {
return;
}

if (!defined('NEW_PHP20_CONSTANT')) {
define('NEW_PHP20_CONSTANT', 42);
}

if (!function_exists('new_php20_function')) {
function new_php20_function(bool $echo = false): void { Php20::new_php20_function($echo); }
}
11 changes: 11 additions & 0 deletions fixtures/set040-polyfills/composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"bin": "index.php",
"autoload": {
"files": ["bootstrap.php"],
"classmap": ["stubs"],
"psr-4": {
"Set040\\Polyfill\\": "src/",
"Set040\\": "src/"
}
}
}
18 changes: 18 additions & 0 deletions fixtures/set040-polyfills/composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions fixtures/set040-polyfills/expected-output
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
OK.
27 changes: 27 additions & 0 deletions fixtures/set040-polyfills/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php declare(strict_types=1);

namespace App;

use NewPhp20Interface;
use NewPhp20Class;
use function new_php20_function;
use const NEW_PHP20_CONSTANT;
use const PHP_EOL;

require file_exists(__DIR__.'/vendor/scoper-autoload.php')
? __DIR__.'/vendor/scoper-autoload.php'
: __DIR__.'/vendor/autoload.php';

// This file mimics the execution of an app relying on a polyfill.
//
// From PHP-Scoper point of view, marking a symbol as excluded is
// akin to say this is a PHP native symbol.

// Consume the polyfilled code.

class NewPhp20Child implements NewPhp20Interface {}
new NewPhp20Class();
new_php20_function();
$x = NEW_PHP20_CONSTANT;

echo "OK.".PHP_EOL;
14 changes: 14 additions & 0 deletions fixtures/set040-polyfills/scoper.inc.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php declare(strict_types=1);

return [
'exclude-classes' => [
'NewPhp20Interface',
'NewPhp20Class',
],
'exclude-functions' => [
'new_php20_function',
],
'exclude-constants' => [
'NEW_PHP20_CONSTANT',
],
];
17 changes: 17 additions & 0 deletions fixtures/set040-polyfills/src/Php20.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php declare(strict_types=1);

namespace Set040;

final class Php20
{
public static function new_php20_function(bool $echo = false): void
{
if ($echo) {
echo "Called `new_php20_function()`.";
}
}

private function __construct()
{
}
}
7 changes: 7 additions & 0 deletions fixtures/set040-polyfills/stubs/NewPhp20Class.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php declare(strict_types=1);

if (PHP_VERSION_ID < 200_000) {
final class NewPhp20Class
{
}
}
7 changes: 7 additions & 0 deletions fixtures/set040-polyfills/stubs/NewPhp20Interface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php declare(strict_types=1);

if (PHP_VERSION_ID < 200_000) {
interface NewPhp20Interface
{
}
}
2 changes: 2 additions & 0 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,5 @@ parameters:
path: 'tests/Console/Command/AddInspectCommandIntegrationTest.php'
- message: '#unserialize#'
path: 'src/Symbol/SymbolsRegistry.php'
- message: '#Stmt\:\:\$stmts#'
path: 'src/PhpParser/NodeVisitor/ClassAliasStmtAppender.php'
31 changes: 31 additions & 0 deletions specs/class/concrete.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,37 @@ public function a()
PHP,
],

'Declaration in the global namespace with global classes exposed within a condition' => [
'expose-global-classes' => true,
'expected-recorded-classes' => [
['A', 'Humbug\A'],
],
'payload' => <<<'PHP'
<?php

if ($condition) {
class A {
public function a() {}
}
}
----
<?php

namespace Humbug;

if ($condition) {
class A
{
public function a()
{
}
}
\class_alias('Humbug\\A', 'A', \false);
}

PHP,
],

'Declaration of an internal class' => [
'expected-recorded-classes' => [
['Normalizer', 'Humbug\Normalizer'],
Expand Down
2 changes: 2 additions & 0 deletions specs/class/conditional.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class A {}
class A
{
}
\class_alias('Humbug\\A', 'A', \false);
}

PHP,
Expand Down Expand Up @@ -122,6 +123,7 @@ class A {}
class A
{
}
\class_alias('Humbug\\Foo\\A', 'Foo\\A', \false);
}

PHP,
Expand Down
48 changes: 48 additions & 0 deletions specs/class/interface.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,54 @@ public function a();

PHP,

'Declaration of an internal interface' => [
'exclude-classes' => ['NewPhp20Interface'],
'expected-recorded-classes' => [
['NewPhp20Interface', 'Humbug\NewPhp20Interface'],
],
'payload' => <<<'PHP'
<?php

interface NewPhp20Interface {}
----
<?php

namespace Humbug;

interface NewPhp20Interface
{
}
\class_alias('Humbug\\NewPhp20Interface', 'NewPhp20Interface', \false);

PHP,
],

'Declaration of an internal interface within an if statement' => [
'exclude-classes' => ['NewPhp20Interface'],
'expected-recorded-classes' => [
['NewPhp20Interface', 'Humbug\NewPhp20Interface'],
],
'payload' => <<<'PHP'
<?php

if (PHP_VERSION_ID <= 200000) {
interface NewPhp20Interface {}
}
----
<?php

namespace Humbug;

if (\PHP_VERSION_ID <= 200000) {
interface NewPhp20Interface
{
}
\class_alias('Humbug\\NewPhp20Interface', 'NewPhp20Interface', \false);
}

PHP,
],

'Declaration in the global namespace with global classes exposed' => [
'expose-global-classes' => true,
'expected-recorded-classes' => [
Expand Down
Loading
Loading