From c67fec9a56b1247f3234c92dd970a7735f9e2c7a Mon Sep 17 00:00:00 2001 From: Enrico De Lazzari Date: Sun, 16 Jul 2023 17:39:36 +0200 Subject: [PATCH 01/14] wip --- src/Invader.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Invader.php b/src/Invader.php index 5def290..4cf6d7d 100755 --- a/src/Invader.php +++ b/src/Invader.php @@ -25,11 +25,13 @@ public function __construct(object $obj) public function __get(string $name): mixed { - $property = $this->reflected->getProperty($name); + /*$property = $this->reflected->getProperty($name); $property->setAccessible(true); - return $property->getValue($this->obj); + return $property->getValue($this->obj);*/ + + return (fn () $this->{$name})->call($this->obj); } public function __set(string $name, mixed $value): void From 95ebdbd27a3d332f86d5b3fd2b8cc6b8660faac1 Mon Sep 17 00:00:00 2001 From: Enrico De Lazzari Date: Sun, 16 Jul 2023 17:42:35 +0200 Subject: [PATCH 02/14] wip --- .github/workflows/run-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 4c9e69c..338c809 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -9,7 +9,7 @@ jobs: fail-fast: true matrix: os: [ubuntu-latest, windows-latest] - php: [8.0, 8.1] + php: [8.1] stability: [prefer-lowest, prefer-stable] name: P${{ matrix.php }} - ${{ matrix.stability }} - ${{ matrix.os }} From dc57e81ca633181e2ab4633264256197d2cf407a Mon Sep 17 00:00:00 2001 From: Enrico De Lazzari Date: Sun, 16 Jul 2023 17:45:08 +0200 Subject: [PATCH 03/14] wip --- .github/workflows/run-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 338c809..fff54ae 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -9,7 +9,7 @@ jobs: fail-fast: true matrix: os: [ubuntu-latest, windows-latest] - php: [8.1] + php: [8.2] stability: [prefer-lowest, prefer-stable] name: P${{ matrix.php }} - ${{ matrix.stability }} - ${{ matrix.os }} From c3a8daeaa9d427c413fe27a0be5980eff0936362 Mon Sep 17 00:00:00 2001 From: Enrico De Lazzari Date: Sun, 16 Jul 2023 17:51:30 +0200 Subject: [PATCH 04/14] wip --- src/Invader.php | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/Invader.php b/src/Invader.php index 4cf6d7d..8656f10 100755 --- a/src/Invader.php +++ b/src/Invader.php @@ -25,12 +25,6 @@ public function __construct(object $obj) public function __get(string $name): mixed { - /*$property = $this->reflected->getProperty($name); - - $property->setAccessible(true); - - return $property->getValue($this->obj);*/ - return (fn () $this->{$name})->call($this->obj); } @@ -45,10 +39,6 @@ public function __set(string $name, mixed $value): void public function __call(string $name, array $params = []): mixed { - $method = $this->reflected->getMethod($name); - - $method->setAccessible(true); - - return $method->invoke($this->obj, ...$params); + return (fn () $this->{$name}(...$params))->call($this->obj); } } From 9df012bbab4cd1489af91cd28f0381876448584b Mon Sep 17 00:00:00 2001 From: Enrico De Lazzari Date: Sun, 16 Jul 2023 17:52:57 +0200 Subject: [PATCH 05/14] wip --- src/Invader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Invader.php b/src/Invader.php index 8656f10..0139423 100755 --- a/src/Invader.php +++ b/src/Invader.php @@ -39,6 +39,6 @@ public function __set(string $name, mixed $value): void public function __call(string $name, array $params = []): mixed { - return (fn () $this->{$name}(...$params))->call($this->obj); + return (fn () => $this->{$name}(...$params))->call($this->obj); } } From 56638cd7d40e0958e3f4a5a653ec901ad21a3b88 Mon Sep 17 00:00:00 2001 From: Enrico De Lazzari Date: Sun, 16 Jul 2023 17:53:05 +0200 Subject: [PATCH 06/14] wip --- src/Invader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Invader.php b/src/Invader.php index 0139423..894fbb9 100755 --- a/src/Invader.php +++ b/src/Invader.php @@ -25,7 +25,7 @@ public function __construct(object $obj) public function __get(string $name): mixed { - return (fn () $this->{$name})->call($this->obj); + return (fn () => $this->{$name})->call($this->obj); } public function __set(string $name, mixed $value): void From c5b6cc4afc16896649e5a6dd12d4be6aee0d0d71 Mon Sep 17 00:00:00 2001 From: Enrico De Lazzari Date: Sun, 16 Jul 2023 17:54:58 +0200 Subject: [PATCH 07/14] wip --- src/Invader.php | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/Invader.php b/src/Invader.php index 894fbb9..ab10d02 100755 --- a/src/Invader.php +++ b/src/Invader.php @@ -12,7 +12,6 @@ class Invader { /** @var T */ public object $obj; - public ReflectionClass $reflected; /** * @param T $obj @@ -20,7 +19,6 @@ class Invader public function __construct(object $obj) { $this->obj = $obj; - $this->reflected = new ReflectionClass($obj); } public function __get(string $name): mixed @@ -30,11 +28,7 @@ public function __get(string $name): mixed public function __set(string $name, mixed $value): void { - $property = $this->reflected->getProperty($name); - - $property->setAccessible(true); - - $property->setValue($this->obj, $value); + (fn () => $this->{$name} = $value)->call($this->obj); } public function __call(string $name, array $params = []): mixed From b6839927f67133ee4a88325aac68adc325a29db6 Mon Sep 17 00:00:00 2001 From: Enrico De Lazzari Date: Sun, 16 Jul 2023 17:56:49 +0200 Subject: [PATCH 08/14] wip --- src/Invader.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Invader.php b/src/Invader.php index ab10d02..2d0a001 100755 --- a/src/Invader.php +++ b/src/Invader.php @@ -10,13 +10,10 @@ */ class Invader { - /** @var T */ - public object $obj; - /** * @param T $obj */ - public function __construct(object $obj) + public function __construct(public object $obj) { $this->obj = $obj; } From 828fcce3ae49ca0b66ce084a4a040fe1e8040d2c Mon Sep 17 00:00:00 2001 From: enricodelazzari Date: Sun, 16 Jul 2023 22:47:58 +0200 Subject: [PATCH 09/14] wip --- .github/workflows/phpstan.yml | 26 ++++++ composer.json | 11 +-- phpstan-baseline.neon | 0 phpstan-extension.neon | 8 -- phpstan.neon.dist | 9 ++ src/Invader.php | 2 - .../InvadeMethodsReflectionExtension.php | 35 -------- .../InvadePropertiesReflectionExtension.php | 35 -------- src/PHPStan/InvadedMethodReflection.php | 87 ------------------- src/PHPStan/InvadedPropertyReflection.php | 81 ----------------- 10 files changed, 38 insertions(+), 256 deletions(-) create mode 100644 .github/workflows/phpstan.yml create mode 100644 phpstan-baseline.neon delete mode 100644 phpstan-extension.neon create mode 100644 phpstan.neon.dist delete mode 100644 src/PHPStan/InvadeMethodsReflectionExtension.php delete mode 100644 src/PHPStan/InvadePropertiesReflectionExtension.php delete mode 100644 src/PHPStan/InvadedMethodReflection.php delete mode 100644 src/PHPStan/InvadedPropertyReflection.php diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml new file mode 100644 index 0000000..900f541 --- /dev/null +++ b/.github/workflows/phpstan.yml @@ -0,0 +1,26 @@ +name: PHPStan + +on: + push: + paths: + - '**.php' + - 'phpstan.neon.dist' + +jobs: + phpstan: + name: phpstan + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.2' + coverage: none + + - name: Install composer dependencies + uses: ramsey/composer-install@v2 + + - name: Run PHPStan + run: ./vendor/bin/phpstan --error-format=github diff --git a/composer.json b/composer.json index 28628cc..daa9eb2 100644 --- a/composer.json +++ b/composer.json @@ -15,9 +15,10 @@ } ], "require": { - "php": "^8.0" + "php": "^8.2" }, "require-dev": { + "friendsofphp/php-cs-fixer": "^3.21", "pestphp/pest": "^1.20", "phpstan/phpstan": "^1.4", "spatie/ray": "^1.28" @@ -36,6 +37,7 @@ } }, "scripts": { + "analyse": "vendor/bin/phpstan analyse", "test": "vendor/bin/pest", "test-coverage": "vendor/bin/pest --coverage", "format": "vendor/bin/php-cs-fixer fix --allow-risky=yes" @@ -46,13 +48,6 @@ "pestphp/pest-plugin": true } }, - "extra": { - "phpstan": { - "includes": [ - "phpstan-extension.neon" - ] - } - }, "minimum-stability": "dev", "prefer-stable": true } diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon new file mode 100644 index 0000000..e69de29 diff --git a/phpstan-extension.neon b/phpstan-extension.neon deleted file mode 100644 index 22f60cc..0000000 --- a/phpstan-extension.neon +++ /dev/null @@ -1,8 +0,0 @@ -services: - - class: Spatie\Invade\PHPStan\InvadePropertiesReflectionExtension - tags: - - phpstan.broker.propertiesClassReflectionExtension - - - class: Spatie\Invade\PHPStan\InvadeMethodsReflectionExtension - tags: - - phpstan.broker.methodsClassReflectionExtension diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 0000000..561972e --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,9 @@ +includes: + - phpstan-baseline.neon + +parameters: + level: 4 + paths: + - src + tmpDir: build/phpstan + checkMissingIterableValueType: false diff --git a/src/Invader.php b/src/Invader.php index 2d0a001..44d450e 100755 --- a/src/Invader.php +++ b/src/Invader.php @@ -2,8 +2,6 @@ namespace Spatie\Invade; -use ReflectionClass; - /** * @template T of object * @mixin T diff --git a/src/PHPStan/InvadeMethodsReflectionExtension.php b/src/PHPStan/InvadeMethodsReflectionExtension.php deleted file mode 100644 index 98a3ca7..0000000 --- a/src/PHPStan/InvadeMethodsReflectionExtension.php +++ /dev/null @@ -1,35 +0,0 @@ -is(Invader::class)) { - return false; - } - - $invaded = $classReflection->getActiveTemplateTypeMap()->getType('T') - ?? throw new ShouldNotHappenException(); - - return $invaded->hasMethod($methodName)->yes(); - } - - public function getMethod(ClassReflection $classReflection, string $methodName): MethodReflection - { - $invaded = $classReflection->getActiveTemplateTypeMap()->getType('T') - ?? throw new ShouldNotHappenException(); - - return new InvadedMethodReflection( - $invaded->getMethod($methodName, new OutOfClassScope()), - ); - } -} diff --git a/src/PHPStan/InvadePropertiesReflectionExtension.php b/src/PHPStan/InvadePropertiesReflectionExtension.php deleted file mode 100644 index c31b29d..0000000 --- a/src/PHPStan/InvadePropertiesReflectionExtension.php +++ /dev/null @@ -1,35 +0,0 @@ -is(Invader::class)) { - return false; - } - - $invaded = $classReflection->getActiveTemplateTypeMap()->getType('T') - ?? throw new ShouldNotHappenException(); - - return $invaded->hasProperty($propertyName)->yes(); - } - - public function getProperty(ClassReflection $classReflection, string $propertyName): PropertyReflection - { - $invaded = $classReflection->getActiveTemplateTypeMap()->getType('T') - ?? throw new ShouldNotHappenException(); - - return new InvadedPropertyReflection( - $invaded->getProperty($propertyName, new OutOfClassScope()), - ); - } -} diff --git a/src/PHPStan/InvadedMethodReflection.php b/src/PHPStan/InvadedMethodReflection.php deleted file mode 100644 index aa11105..0000000 --- a/src/PHPStan/InvadedMethodReflection.php +++ /dev/null @@ -1,87 +0,0 @@ -method->getDeclaringClass(); - } - - public function isStatic(): bool - { - return $this->method->isStatic(); - } - - public function isPrivate(): bool - { - return false; - } - - public function isPublic(): bool - { - return true; - } - - public function getDocComment(): ?string - { - return $this->method->getDocComment(); - } - - public function getName(): string - { - return $this->method->getName(); - } - - public function getPrototype(): ClassMemberReflection - { - return $this->method->getPrototype(); - } - - public function getVariants(): array - { - return $this->method->getVariants(); - } - - public function isDeprecated(): TrinaryLogic - { - return $this->method->isDeprecated(); - } - - public function getDeprecatedDescription(): ?string - { - return $this->method->getDeprecatedDescription(); - } - - public function isFinal(): TrinaryLogic - { - return $this->method->isFinal(); - } - - public function isInternal(): TrinaryLogic - { - return $this->method->isInternal(); - } - - public function getThrowType(): ?Type - { - return $this->method->getThrowType(); - } - - public function hasSideEffects(): TrinaryLogic - { - return $this->method->hasSideEffects(); - } -} diff --git a/src/PHPStan/InvadedPropertyReflection.php b/src/PHPStan/InvadedPropertyReflection.php deleted file mode 100644 index 94e46cb..0000000 --- a/src/PHPStan/InvadedPropertyReflection.php +++ /dev/null @@ -1,81 +0,0 @@ -property->getDeclaringClass(); - } - - public function isStatic(): bool - { - return $this->property->isStatic(); - } - - public function isPrivate(): bool - { - return false; - } - - public function isPublic(): bool - { - return true; - } - - public function getDocComment(): ?string - { - return $this->property->getDocComment(); - } - - public function getReadableType(): Type - { - return $this->property->getReadableType(); - } - - public function getWritableType(): Type - { - return $this->property->getWritableType(); - } - - public function canChangeTypeAfterAssignment(): bool - { - return $this->property->canChangeTypeAfterAssignment(); - } - - public function isReadable(): bool - { - return $this->property->isReadable(); - } - - public function isWritable(): bool - { - return $this->property->isWritable(); - } - - public function isDeprecated(): TrinaryLogic - { - return $this->property->isDeprecated(); - } - - public function getDeprecatedDescription(): ?string - { - return $this->property->getDeprecatedDescription(); - } - - public function isInternal(): TrinaryLogic - { - return $this->property->isInternal(); - } -} From a7b4ee53f2d0686d3faeb011605d1bf87303592e Mon Sep 17 00:00:00 2001 From: enricodelazzari Date: Sun, 16 Jul 2023 22:52:32 +0200 Subject: [PATCH 10/14] wip --- types/Example.php | 21 --------------------- types/phpstan.neon.dist | 20 -------------------- types/src/Invader.php | 21 --------------------- types/src/functions.php | 36 ------------------------------------ 4 files changed, 98 deletions(-) delete mode 100644 types/Example.php delete mode 100644 types/phpstan.neon.dist delete mode 100644 types/src/Invader.php delete mode 100644 types/src/functions.php diff --git a/types/Example.php b/types/Example.php deleted file mode 100644 index 2b41cfb..0000000 --- a/types/Example.php +++ /dev/null @@ -1,21 +0,0 @@ -mySecret . $this->internalMethod(); - } - - private function internalMethod(): int - { - return 2115; - } -} diff --git a/types/phpstan.neon.dist b/types/phpstan.neon.dist deleted file mode 100644 index 740bab6..0000000 --- a/types/phpstan.neon.dist +++ /dev/null @@ -1,20 +0,0 @@ -parameters: - paths: - - . - level: max - ignoreErrors: - - - message: '#^Parameter \#1 \$object of function invade expects object, mixed given\.$#' - count: 1 - path: src/functions.php - - - message: '#^Unable to resolve the template type T in call to function invade$#' - count: 1 - path: src/functions.php - - - message: '#Parameter \#1 \$obj of class Spatie\\Invade\\Invader constructor expects T of object, mixed given\.#' - count: 1 - path: src/Invader.php - -includes: - - ../phpstan-extension.neon diff --git a/types/src/Invader.php b/types/src/Invader.php deleted file mode 100644 index 0f04ff6..0000000 --- a/types/src/Invader.php +++ /dev/null @@ -1,21 +0,0 @@ -', $invaded); -assertType('string', $invaded->myExposed); -assertType('int', $invaded->myShared); -assertType('string', $invaded->mySecret); -assertType('int', $invaded->internalMethod()); - -assertType(Invader::class . '', new Invader(getMixed())); - -function getMixed(): mixed -{ - return null; -} - diff --git a/types/src/functions.php b/types/src/functions.php deleted file mode 100644 index 88f94c7..0000000 --- a/types/src/functions.php +++ /dev/null @@ -1,36 +0,0 @@ -', $invaded); -assertType('string', $invaded->myExposed); -assertType('int', $invaded->myShared); -assertType('string', $invaded->mySecret); -assertType('int', $invaded->internalMethod()); - -$invaded = getInvaded(); - -assertType(Invader::class . '<' . Example::class . '>', $invaded); -assertType('string', $invaded->myExposed); -assertType('int', $invaded->myShared); -assertType('string', $invaded->mySecret); -assertType('int', $invaded->internalMethod()); - -assertType(Invader::class . '', invade(getMixed())); - -function getMixed(): mixed -{ - return null; -} - -/** - * @return Invader - */ -function getInvaded(): Invader -{ - return invade(new Example("password", 42, "Pestival")); -} From 409efc62e0ddd2c25924ff82763667d08f6c5b31 Mon Sep 17 00:00:00 2001 From: enricodelazzari Date: Sun, 16 Jul 2023 23:20:03 +0200 Subject: [PATCH 11/14] wip --- src/Invader.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Invader.php b/src/Invader.php index 44d450e..1cbd402 100755 --- a/src/Invader.php +++ b/src/Invader.php @@ -11,9 +11,9 @@ class Invader /** * @param T $obj */ - public function __construct(public object $obj) - { - $this->obj = $obj; + public function __construct( + public object $obj + ) { } public function __get(string $name): mixed From 5e45dc33dcd0436886531e63d0275c6cf482411d Mon Sep 17 00:00:00 2001 From: enricodelazzari Date: Mon, 17 Jul 2023 21:08:21 +0200 Subject: [PATCH 12/14] wip --- README.md | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/README.md b/README.md index f101421..d793827 100644 --- a/README.md +++ b/README.md @@ -61,20 +61,10 @@ Using `invade` you can also call private functions. invade($myClass)->privateMethod(); // returns 'private return value' ``` -### Making PHPStan understand Invade - -PHPStan will report errors for every invaded private method and property as it is not aware that you can now access them. To remove these errors install the [PHPStan extension installer](https://github.com/phpstan/extension-installer) or add the invade PHPStan extension manually to your PHPStan configuration: - -```yaml -includes: - - ./vendor/spatie/invade/phpstan-extension.neon -``` - ## Testing ```bash composer test -vendor/bin/phpstan analyse -c types/phpstan.neon.dist ``` ## Changelog From 27fea8cd4aba0a8145c030c6e0e31067c1be2cc5 Mon Sep 17 00:00:00 2001 From: enricodelazzari Date: Mon, 17 Jul 2023 21:09:34 +0200 Subject: [PATCH 13/14] wip --- src/Invader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Invader.php b/src/Invader.php index 1cbd402..cfb7240 100755 --- a/src/Invader.php +++ b/src/Invader.php @@ -6,7 +6,7 @@ * @template T of object * @mixin T */ -class Invader +readonly class Invader { /** * @param T $obj From fcd85b053a8552c49a71080bb17a0c90b0254990 Mon Sep 17 00:00:00 2001 From: enricodelazzari Date: Mon, 17 Jul 2023 22:21:59 +0200 Subject: [PATCH 14/14] wip --- .github/workflows/phpstan.yml | 2 +- .github/workflows/run-tests.yml | 2 +- composer.json | 6 ++---- src/Invader.php | 2 +- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml index 900f541..980cb79 100644 --- a/.github/workflows/phpstan.yml +++ b/.github/workflows/phpstan.yml @@ -16,7 +16,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: '8.2' + php-version: '8.0' coverage: none - name: Install composer dependencies diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index fff54ae..1ab04d6 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -9,7 +9,7 @@ jobs: fail-fast: true matrix: os: [ubuntu-latest, windows-latest] - php: [8.2] + php: [8.0, 8.1, 8.2] stability: [prefer-lowest, prefer-stable] name: P${{ matrix.php }} - ${{ matrix.stability }} - ${{ matrix.os }} diff --git a/composer.json b/composer.json index daa9eb2..7f7ca69 100644 --- a/composer.json +++ b/composer.json @@ -15,10 +15,9 @@ } ], "require": { - "php": "^8.2" + "php": "^8.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.21", "pestphp/pest": "^1.20", "phpstan/phpstan": "^1.4", "spatie/ray": "^1.28" @@ -39,8 +38,7 @@ "scripts": { "analyse": "vendor/bin/phpstan analyse", "test": "vendor/bin/pest", - "test-coverage": "vendor/bin/pest --coverage", - "format": "vendor/bin/php-cs-fixer fix --allow-risky=yes" + "test-coverage": "vendor/bin/pest --coverage" }, "config": { "sort-packages": true, diff --git a/src/Invader.php b/src/Invader.php index cfb7240..1cbd402 100755 --- a/src/Invader.php +++ b/src/Invader.php @@ -6,7 +6,7 @@ * @template T of object * @mixin T */ -readonly class Invader +class Invader { /** * @param T $obj