fork icon indicating copy to clipboard operation
fork copied to clipboard

Allow to identify callable by either name or order

Open llaville opened this issue 1 year ago • 5 comments

Hello,

With this PR I will allow to identify list of callables, either by order (int: default behavior), but also by a name (string: new behavior).

Hope you will be agree with my proposal. I'm begin with Pest on this PR. So, if we can do better tests, I'll happy to hear you !

And now a use case to proove a real use case (at least for me). Based on https://github.com/composer-unused/symbol-parser project.

I want to retrieve all symbols (classes, interfaces, functions, constants) from a data source (file list get by the Symfony Finder). But rather to use task order to identify values in $results array, I wanted to have an array with each file name of the data source as task identifer.

WDYT about this proposal ?

My Use Case
<?php declare(strict_types=1);

use Bartlett\Sandbox\Service\Profiler;
use Bartlett\Sandbox\Service\SourceProvider;
use ComposerUnused\SymbolParser\Parser\PHP\ConsumedSymbolCollector;
use ComposerUnused\SymbolParser\Parser\PHP\Strategy\UsedExtensionSymbolStrategy;
use ComposerUnused\SymbolParser\Parser\PHP\SymbolNameParser;
use PhpParser\NodeVisitor\NameResolver;
use PhpParser\ParserFactory;
use Psr\Log\NullLogger;
use Spatie\Fork\Fork;
use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\Stopwatch\Stopwatch;

require __DIR__ . '/../../vendor/autoload.php';

$stopWatch = new Stopwatch();

$commandName = basename(__FILE__);

$out = new ConsoleOutput();
$section1 = $out->section();

$profiler = new Profiler($stopWatch, $section1);
$profiler->onConsoleCommand($commandName);

// --------------------------------------------------------------------------------------------------------------------
$section1->writeln("Begin Line >>>");

$dataSource = __DIR__ . '/../php-compatinfo/vendors/bartlett/php-compatinfo-db/src/Presentation';

$finder = SourceProvider::getFinder($dataSource, []);

$symbolParser = new SymbolNameParser(
    (new ParserFactory())->create(ParserFactory::ONLY_PHP7),
    new NameResolver(),
    new ConsumedSymbolCollector(
        [
            new UsedExtensionSymbolStrategy(
                get_loaded_extensions(),
                new NullLogger()
            ),
        ]
    )
);

$callables = [];

foreach ($finder as $fileInfo) {
    $taskId = $fileInfo->getRelativePathname();
    $callables[] = function () use($fileInfo, $symbolParser) {
        return iterator_to_array(
            $symbolParser->parseSymbolNames($fileInfo->getContents())
        );
    };
}

$results = Fork::new()
    ->before(null, fn($task) => $section1->writeln(sprintf('Task %s : %s', $task->order(), $task->name())))
    ->run(...$callables)
;

var_dump($results);

$section1->writeln("End line <<<");
// --------------------------------------------------------------------------------------------------------------------

$profiler->onConsoleTerminate($commandName);
Tasks identified by order : `$callables[]` syntax in PHP script
Begin Line >>>
Task 0 : 0
Task 1 : 1
Task 2 : 2
Task 3 : 3
Task 4 : 4
Task 5 : 5
Task 6 : 6
Task 7 : 7
Task 8 : 8
Task 9 : 9
Task 10 : 10
Task 11 : 11
Task 12 : 12
Task 13 : 13
Task 14 : 14
Task 15 : 15
Task 16 : 16
Task 17 : 17
Task 18 : 18
Task 19 : 19
Task 20 : 20
Task 21 : 21
/shared/backups/bartlett/sandbox/src/fork/consumed_symbols.php:63:
array(22) {
  [1] =>
  array(0) {
  }
  [4] =>
  array(2) {
    [0] =>
    string(6) "getenv"
    [1] =>
    string(11) "array_shift"
  }
  [10] =>
  array(3) {
    [0] =>
    string(4) "Phar"
    [1] =>
    string(8) "in_array"
    [2] =>
    string(9) "get_class"
  }
  [0] =>
  array(3) {
    [0] =>
    string(7) "sprintf"
    [1] =>
    string(11) "PHP_VERSION"
    [2] =>
    string(9) "php_uname"
  }
  [6] =>
  array(1) {
    [0] =>
    string(7) "sprintf"
  }
  [9] =>
  array(1) {
    [0] =>
    string(4) "trim"
  }
  [2] =>
  array(1) {
    [0] =>
    string(7) "sprintf"
  }
  [7] =>
  array(7) {
    [0] =>
    string(7) "sprintf"
    [1] =>
    string(6) "substr"
    [2] =>
    string(5) "ltrim"
    [3] =>
    string(5) "count"
    [4] =>
    string(15) "str_starts_with"
    [5] =>
    string(7) "stripos"
    [6] =>
    string(11) "str_replace"
  }
  [14] =>
  array(0) {
  }
  [3] =>
  array(10) {
    [0] =>
    string(3) "min"
    [1] =>
    string(19) "DIRECTORY_SEPARATOR"
    [2] =>
    string(13) "func_num_args"
    [3] =>
    string(12) "func_get_arg"
    [4] =>
    string(8) "is_array"
    [5] =>
    string(12) "array_values"
    [6] =>
    string(8) "wordwrap"
    [7] =>
    string(7) "sprintf"
    [8] =>
    string(9) "array_map"
    [9] =>
    string(8) "vsprintf"
  }
  [8] =>
  array(9) {
    [0] =>
    string(11) "json_encode"
    [1] =>
    string(17) "JSON_PRETTY_PRINT"
    [2] =>
    string(7) "sprintf"
    [3] =>
    string(5) "count"
    [4] =>
    string(7) "natsort"
    [5] =>
    string(12) "array_values"
    [6] =>
    string(6) "strpos"
    [7] =>
    string(4) "trim"
    [8] =>
    string(6) "substr"
  }
  [11] =>
  array(0) {
  }
  [12] =>
  array(3) {
    [0] =>
    string(4) "date"
    [1] =>
    string(4) "trim"
    [2] =>
    string(10) "strtolower"
  }
  [15] =>
  array(2) {
    [0] =>
    string(7) "sprintf"
    [1] =>
    string(5) "count"
  }
  [19] =>
  array(0) {
  }
  [5] =>
  array(6) {
    [0] =>
    string(9) "array_map"
    [1] =>
    string(10) "strcasecmp"
    [2] =>
    string(10) "phpversion"
    [3] =>
    string(15) "version_compare"
    [4] =>
    string(7) "sprintf"
    [5] =>
    string(5) "count"
  }
  [20] =>
  array(0) {
  }
  [13] =>
  array(2) {
    [0] =>
    string(4) "trim"
    [1] =>
    string(7) "sprintf"
  }
  [21] =>
  array(0) {
  }
  [16] =>
  array(2) {
    [0] =>
    string(6) "getenv"
    [1] =>
    string(11) "array_shift"
  }
  [18] =>
  array(3) {
    [0] =>
    string(6) "getenv"
    [1] =>
    string(4) "trim"
    [2] =>
    string(11) "array_shift"
  }
  [17] =>
  array(10) {
    [0] =>
    string(4) "trim"
    [1] =>
    string(7) "sprintf"
    [2] =>
    string(5) "count"
    [3] =>
    string(12) "array_unique"
    [4] =>
    string(7) "explode"
    [5] =>
    string(5) "ksort"
    [6] =>
    string(12) "SORT_NATURAL"
    [7] =>
    string(13) "method_exists"
    [8] =>
    string(7) "implode"
    [9] =>
    string(13) "array_unshift"
  }
}
End line <<<

Time: 235 ms, Memory: 14.00Mb
Tasks identified by name : `$callables[$taskId]` syntax in PHP script
Begin Line >>>
Task 0 : Console/Output/PrintDiagnose.php
Task 1 : Console/Output/Output.php
Task 2 : Console/Application.php
Task 3 : Console/Style.php
Task 4 : Console/Command/CreateCommand.php
Task 5 : Console/Command/ListCommand.php
Task 6 : Console/Command/AboutCommand.php
Task 7 : Console/Command/Debug/ContainerDebugCommand.php
Task 8 : Console/Command/DoctorCommand.php
Task 9 : Console/Command/BuildCommand.php
Task 10 : Console/Command/FactoryCommandLoader.php
Task 11 : Console/Command/AbstractCommand.php
Task 12 : Console/Command/ReleaseCommand.php
Task 13 : Console/Command/PolyfillCommand.php
Task 14 : Console/Command/CommandInterface.php
Task 15 : Console/Command/DiagnoseCommand.php
Task 16 : Console/Command/NewCommand.php
Task 17 : Console/Command/ShowCommand.php
Task 18 : Console/Command/InitCommand.php
Task 19 : Console/StyleInterface.php
Task 20 : Console/ApplicationInterface.php
Task 21 : Console/Input/Input.php
/shared/backups/bartlett/sandbox/src/fork/consumed_symbols.php:65:
array(22) {
  'Console/Output/Output.php' =>
  array(0) {
  }
  'Console/Command/FactoryCommandLoader.php' =>
  array(3) {
    [0] =>
    string(4) "Phar"
    [1] =>
    string(8) "in_array"
    [2] =>
    string(9) "get_class"
  }
  'Console/Application.php' =>
  array(1) {
    [0] =>
    string(7) "sprintf"
  }
  'Console/Output/PrintDiagnose.php' =>
  array(3) {
    [0] =>
    string(7) "sprintf"
    [1] =>
    string(11) "PHP_VERSION"
    [2] =>
    string(9) "php_uname"
  }
  'Console/Style.php' =>
  array(10) {
    [0] =>
    string(3) "min"
    [1] =>
    string(19) "DIRECTORY_SEPARATOR"
    [2] =>
    string(13) "func_num_args"
    [3] =>
    string(12) "func_get_arg"
    [4] =>
    string(8) "is_array"
    [5] =>
    string(12) "array_values"
    [6] =>
    string(8) "wordwrap"
    [7] =>
    string(7) "sprintf"
    [8] =>
    string(9) "array_map"
    [9] =>
    string(8) "vsprintf"
  }
  'Console/Command/AboutCommand.php' =>
  array(1) {
    [0] =>
    string(7) "sprintf"
  }
  'Console/Command/ListCommand.php' =>
  array(6) {
    [0] =>
    string(9) "array_map"
    [1] =>
    string(10) "strcasecmp"
    [2] =>
    string(10) "phpversion"
    [3] =>
    string(15) "version_compare"
    [4] =>
    string(7) "sprintf"
    [5] =>
    string(5) "count"
  }
  'Console/Command/CreateCommand.php' =>
  array(2) {
    [0] =>
    string(6) "getenv"
    [1] =>
    string(11) "array_shift"
  }
  'Console/Command/BuildCommand.php' =>
  array(1) {
    [0] =>
    string(4) "trim"
  }
  'Console/Command/CommandInterface.php' =>
  array(0) {
  }
  'Console/Command/ReleaseCommand.php' =>
  array(3) {
    [0] =>
    string(4) "date"
    [1] =>
    string(4) "trim"
    [2] =>
    string(10) "strtolower"
  }
  'Console/Command/AbstractCommand.php' =>
  array(0) {
  }
  'Console/Command/DoctorCommand.php' =>
  array(9) {
    [0] =>
    string(11) "json_encode"
    [1] =>
    string(17) "JSON_PRETTY_PRINT"
    [2] =>
    string(7) "sprintf"
    [3] =>
    string(5) "count"
    [4] =>
    string(7) "natsort"
    [5] =>
    string(12) "array_values"
    [6] =>
    string(6) "strpos"
    [7] =>
    string(4) "trim"
    [8] =>
    string(6) "substr"
  }
  'Console/Command/DiagnoseCommand.php' =>
  array(2) {
    [0] =>
    string(7) "sprintf"
    [1] =>
    string(5) "count"
  }
  'Console/ApplicationInterface.php' =>
  array(0) {
  }
  'Console/Input/Input.php' =>
  array(0) {
  }
  'Console/Command/Debug/ContainerDebugCommand.php' =>
  array(7) {
    [0] =>
    string(7) "sprintf"
    [1] =>
    string(6) "substr"
    [2] =>
    string(5) "ltrim"
    [3] =>
    string(5) "count"
    [4] =>
    string(15) "str_starts_with"
    [5] =>
    string(7) "stripos"
    [6] =>
    string(11) "str_replace"
  }
  'Console/Command/NewCommand.php' =>
  array(2) {
    [0] =>
    string(6) "getenv"
    [1] =>
    string(11) "array_shift"
  }
  'Console/StyleInterface.php' =>
  array(0) {
  }
  'Console/Command/PolyfillCommand.php' =>
  array(2) {
    [0] =>
    string(4) "trim"
    [1] =>
    string(7) "sprintf"
  }
  'Console/Command/InitCommand.php' =>
  array(3) {
    [0] =>
    string(6) "getenv"
    [1] =>
    string(4) "trim"
    [2] =>
    string(11) "array_shift"
  }
  'Console/Command/ShowCommand.php' =>
  array(10) {
    [0] =>
    string(4) "trim"
    [1] =>
    string(7) "sprintf"
    [2] =>
    string(5) "count"
    [3] =>
    string(12) "array_unique"
    [4] =>
    string(7) "explode"
    [5] =>
    string(5) "ksort"
    [6] =>
    string(12) "SORT_NATURAL"
    [7] =>
    string(13) "method_exists"
    [8] =>
    string(7) "implode"
    [9] =>
    string(13) "array_unshift"
  }
}
End line <<<

Time: 239 ms, Memory: 14.00Mb

llaville avatar Feb 20 '24 16:02 llaville

If you want to give it a try, source code is now available on my repo (https://github.com/llaville/sandbox/commit/44137f7c39d330f32db7d7d125dd761ec6214eb8)

Once all dependencies installed (with composer update), the console launcher bin/sandbox provides 2, 3 use cases :

  • play:fork:usage run the basic fork usage example
  • play:fork:symbol-parser:uc1 is the proof of concept that task naming identification works
  • play:fork:symbol-parser:uc2 is an alternative pretty equivalent to previous one

llaville avatar Feb 21 '24 09:02 llaville

Very nice! Could you also update the readme?

freekmurze avatar Feb 21 '24 13:02 freekmurze

Very nice! Could you also update the readme?

I prefer to let you do it.

llaville avatar Feb 21 '24 15:02 llaville

What's your status about this PR ?

llaville avatar Mar 11 '24 05:03 llaville

I prefer you update the readme, after that I'll do a review 👍

freekmurze avatar Mar 11 '24 07:03 freekmurze