Skip to content

Commit

Permalink
Better way to exclude unwanted Larastan extensions/rules.
Browse files Browse the repository at this point in the history
  • Loading branch information
LastDragon-ru committed Mar 23, 2024
1 parent f5e8c24 commit faaf225
Show file tree
Hide file tree
Showing 9 changed files with 963 additions and 116 deletions.
9 changes: 5 additions & 4 deletions packages/dev/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,17 @@
"require": {
"php": "^8.1|^8.2|^8.3",
"ext-mbstring": "*",
"phpstan/phpstan": "^1.10",
"illuminate/container": "^10.0.0"
"illuminate/container": "^10.0.0",
"lastdragon-ru/lara-asp-core": "self.version",
"nette/neon": "^3.4",
"phpstan/phpstan": "^1.10"
},
"require-dev": {
"phpunit/phpunit": "^10.1.0"
},
"autoload": {
"psr-4": {
"LastDragon_ru\\LaraASP\\Dev\\": "src/",
"Larastan\\Larastan\\": "larastan/"
"LastDragon_ru\\LaraASP\\Dev\\": "src/"
},
"exclude-from-classmap": [
"src/**Test.php"
Expand Down

This file was deleted.

This file was deleted.

142 changes: 125 additions & 17 deletions packages/dev/src/PhpStan/Container/Installer.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,144 @@

namespace LastDragon_ru\LaraASP\Dev\PhpStan\Container;

use Composer\InstalledVersions;
use Exception;
use Larastan\Larastan\ReturnTypes\ApplicationMakeDynamicReturnTypeExtension;
use Larastan\Larastan\ReturnTypes\AppMakeDynamicReturnTypeExtension;
use Larastan\Larastan\ReturnTypes\ContainerArrayAccessDynamicMethodReturnTypeExtension;
use Larastan\Larastan\ReturnTypes\ContainerMakeDynamicReturnTypeExtension;
use LastDragon_ru\LaraASP\Core\Utils\Path;
use Nette\Neon\Neon;

use function is_file;
use function str_replace;
use function unlink;
use function array_filter;
use function array_keys;
use function array_values;
use function file_get_contents;
use function file_put_contents;
use function implode;
use function is_array;
use function is_string;
use function realpath;
use function sprintf;

use const PHP_EOL;

class Installer {
public static function install(): void {
$path = 'vendor';
$root = 'larastan/larastan/src';
$classes = [
ContainerMakeDynamicReturnTypeExtension::class,
ContainerArrayAccessDynamicMethodReturnTypeExtension::class,
/**
* Removes unwanted/conflicting services from `larastan/extension.neon` and
* dump remaining into `larastan.neon` (that should be used instead of the
* original file).
*/
public static function dump(): void {
// Load
$origin = (string) file_get_contents(Path::join(self::getLarastanPath(), 'extension.neon'));
$extension = Neon::decode($origin);

if (!is_array($extension)) {
throw new Exception('The `$extension` expected to be an array.');
}

// Process
$extension = self::updateBootstrapFiles($extension);
$extension = self::updateServices($extension);

// Save
$target = __DIR__.'/larastan.neon';
$neon = Neon::encode($extension, true, ' ');

file_put_contents($target, $neon);

echo " Updated {$target}".PHP_EOL;
}

/**
* @param array<array-key, mixed> $extension
*
* @return array<array-key, mixed>
*/
private static function updateBootstrapFiles(array $extension): array {
// Valid?
if (!isset($extension['parameters']) || !is_array($extension['parameters'])) {
throw new Exception('The `$extension[\'parameters\']` expected to be an array.');
}

// Update
$source = self::getLarastanPath();
$files = (array) ($extension['parameters']['bootstrapFiles'] ?? []);
$root = self::getOwnPath();
$root = Path::join($root, Path::getRelativePath((string) realpath($root), __DIR__));

foreach ($files as $index => $file) {
if (!is_string($file)) {
throw new Exception(
sprintf(
'The `$extension[\'parameters\'][\'bootstrapFiles\'][%s]` expected to be a string.',
$index,
),
);
}

$file = Path::getPath($source, $file);
$extension['parameters']['bootstrapFiles'][$index] = Path::getRelativePath($root, $file);
}

// Return
return $extension;
}

/**
* @param array<array-key, mixed> $extension
*
* @return array<array-key, mixed>
*/
private static function updateServices(array $extension): array {
// Remove
$disabled = [
ApplicationMakeDynamicReturnTypeExtension::class => true,
AppMakeDynamicReturnTypeExtension::class => true,
ContainerArrayAccessDynamicMethodReturnTypeExtension::class => true,
ContainerMakeDynamicReturnTypeExtension::class => true,
];

foreach ($classes as $class) {
$file = $path.'/'.str_replace('\\', '/', str_replace('Larastan\\Larastan', $root, $class)).'.php';
foreach ($extension['services'] ?? [] as $index => $service) {
$class = $service['class'] ?? '';

echo " Removing {$file} ... ";
if (isset($disabled[$class])) {
unset($extension['services'][$index]);

if (is_file($file)) {
echo @unlink($file) ? 'ok' : 'failed';
} else {
echo 'not found';
$disabled[$class] = false;
}
}

echo PHP_EOL;
// Reindex
$extension['services'] = array_values($extension['services']);

// Unused?
$unused = array_keys(array_filter($disabled));

if ($unused) {
throw new Exception(
sprintf(
'The following services is unknown: `%s`',
implode('`, `', $unused),
),
);
}

// Return
return $extension;
}

private static function getOwnPath(): string {
return self::getPackagePath('lastdragon-ru/lara-asp-dev');
}

private static function getLarastanPath(): string {
return self::getPackagePath('larastan/larastan');
}

private static function getPackagePath(string $package): string {
return InstalledVersions::getInstallPath($package)
?? throw new Exception(sprintf('The `%s` package is not found/installed.', $package));
}
}
3 changes: 3 additions & 0 deletions packages/dev/src/PhpStan/Container/extension.neon
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ services:
class: LastDragon_ru\LaraASP\Dev\PhpStan\Container\Extension
tags:
- phpstan.broker.dynamicMethodReturnTypeExtension

includes:
- ./larastan.neon
Loading

0 comments on commit faaf225

Please sign in to comment.