From 3831755714174d2f045320774f6a203a404d0b9b Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Wed, 26 Apr 2023 07:57:48 +0200 Subject: [PATCH] Replace output status table in places instead of clearing the screen --- etc/qa/phpcs.xml | 5 +- src/Gatherer/Schema.php | 11 +-- src/Generator.php | 47 ++++++++++--- src/Registry/ThrowableSchema.php | 4 +- src/StatusOutput.php | 46 ++++++------ src/StatusOutput/OverWritingOutPut.php | 97 ++++++++++++++++++++++++++ src/StatusOutput/Step.php | 2 + 7 files changed, 169 insertions(+), 43 deletions(-) create mode 100644 src/StatusOutput/OverWritingOutPut.php diff --git a/etc/qa/phpcs.xml b/etc/qa/phpcs.xml index b6fd651..f6c11d9 100644 --- a/etc/qa/phpcs.xml +++ b/etc/qa/phpcs.xml @@ -6,9 +6,8 @@ - ../../src/Generator/Client.php - - + ../../src + ../../tests diff --git a/src/Gatherer/Schema.php b/src/Gatherer/Schema.php index 0fd5076..0c0cae7 100644 --- a/src/Gatherer/Schema.php +++ b/src/Gatherer/Schema.php @@ -11,6 +11,7 @@ use function array_key_exists; use function in_array; use function is_array; +use function property_exists; final class Schema { @@ -19,8 +20,8 @@ public static function gather( baseSchema $schema, SchemaRegistry $schemaRegistry, ): \ApiClients\Tools\OpenApiClientGenerator\Representation\Schema { - $className = Utils::fixKeyword($className); - $isArray = $schema->type === 'array'; + $className = Utils::fixKeyword($className); + $isArray = $schema->type === 'array'; $properties = []; $example = []; @@ -43,9 +44,11 @@ public static function gather( break; } - if (property_exists($schema, $examplePropertyName) && is_array($schema->$examplePropertyName) && array_key_exists($gatheredProperty->sourceName, $schema->$examplePropertyName)) { - $example[$gatheredProperty->sourceName] = $schema->$examplePropertyName[$gatheredProperty->sourceName]; + if (! property_exists($schema, $examplePropertyName) || ! is_array($schema->$examplePropertyName) || ! array_key_exists($gatheredProperty->sourceName, $schema->$examplePropertyName)) { + continue; } + + $example[$gatheredProperty->sourceName] = $schema->$examplePropertyName[$gatheredProperty->sourceName]; } $example[$gatheredProperty->sourceName] = $gatheredProperty->exampleData; diff --git a/src/Generator.php b/src/Generator.php index 88e0c49..4cefe68 100644 --- a/src/Generator.php +++ b/src/Generator.php @@ -25,11 +25,9 @@ use ApiClients\Tools\OpenApiClientGenerator\StatusOutput\Step; use cebe\openapi\Reader; use cebe\openapi\spec\OpenApi; -use DivineOmega\CliProgressBar\ProgressBar; use EventSauce\ObjectHydrator\ObjectMapperUsingReflection; use PhpParser\Node; use PhpParser\PrettyPrinter\Standard; -use Psr\Log\LoggerInterface; use RuntimeException; use function array_filter; @@ -129,7 +127,7 @@ public function __construct( $this->state->specHash === $this->currentSpecHash && (static function (string $root, Files $files, string ...$additionalFiles): bool { foreach ($additionalFiles as $additionalFile) { - if ($files->has($additionalFile) && (!file_exists($root . $additionalFile) || $files->get($additionalFile)->hash !== md5(file_get_contents($root . $additionalFile)))) { + if ($files->has($additionalFile) && (! file_exists($root . $additionalFile) || $files->get($additionalFile)->hash !== md5(file_get_contents($root . $additionalFile)))) { echo $additionalFile, PHP_EOL; return false; @@ -255,6 +253,7 @@ private function all(string $namespace, string $namespaceTest, string $configura $this->statusOutput->advanceStep('gathering_schemas'); } } + $this->statusOutput->markStepDone('gathering_schemas'); $webHooks = []; @@ -266,9 +265,11 @@ private function all(string $namespace, string $namespaceTest, string $configura $webHooks[$webHookje->event] = []; } - $webHooks[$webHookje->event][] = $webHookje;$this->statusOutput->advanceStep('gathering_webhooks'); + $webHooks[$webHookje->event][] = $webHookje; + $this->statusOutput->advanceStep('gathering_webhooks'); } } + $this->statusOutput->markStepDone('gathering_webhooks'); $paths = []; @@ -285,10 +286,11 @@ private function all(string $namespace, string $namespaceTest, string $configura continue; } - $paths[] = \ApiClients\Tools\OpenApiClientGenerator\Gatherer\Path::gather($pathClassName, $path, $pathItem, $schemaRegistry, $this->configuration->voter); + $paths[] = \ApiClients\Tools\OpenApiClientGenerator\Gatherer\Path::gather($pathClassName, $path, $pathItem, $schemaRegistry, $this->configuration->voter); $webHooks[$webHookje->event][] = $webHookje; $this->statusOutput->advanceStep('gathering_paths'); } + $this->statusOutput->markStepDone('gathering_paths'); } @@ -316,8 +318,8 @@ private function all(string $namespace, string $namespaceTest, string $configura private function oneClient(string $namespace, string $namespaceTest, string $configurationLocation, SchemaRegistry $schemaRegistry, ThrowableSchema $throwableSchemaRegistry, array $schemas, array $paths, array $webHooks) { - $hydrators = []; - $operations = []; + $hydrators = []; + $operations = []; $this->statusOutput->itemForStep('generating_operations', count($paths)); foreach ($paths as $path) { $hydrators[] = $path->hydrator; @@ -345,6 +347,7 @@ private function oneClient(string $namespace, string $namespaceTest, string $con $this->statusOutput->advanceStep('generating_operations'); } + $this->statusOutput->markStepDone('generating_operations'); $unknownSchemaCount = 0; @@ -357,6 +360,7 @@ private function oneClient(string $namespace, string $namespaceTest, string $con $this->statusOutput->advanceStep('gathering_unknown_schemas'); } } + $this->statusOutput->markStepDone('gathering_unknown_schemas'); $this->statusOutput->itemForStep('generating_schemas', count($schemas)); @@ -375,13 +379,16 @@ private function oneClient(string $namespace, string $namespaceTest, string $con $schema, ); } + $this->statusOutput->advanceStep('generating_schemas'); } + $this->statusOutput->markStepDone('generating_schemas'); $client = \ApiClients\Tools\OpenApiClientGenerator\Gatherer\Client::gather($this->spec, ...$paths); $this->statusOutput->markStepDone('generating_clientinterface'); + yield from ClientInterface::generate( $this->configuration->destination->source . DIRECTORY_SEPARATOR, $namespace, @@ -389,6 +396,7 @@ private function oneClient(string $namespace, string $namespaceTest, string $con ); $this->statusOutput->markStepDone('generating_client'); + yield from Client::generate( $this->configuration->destination->source . DIRECTORY_SEPARATOR, $namespace, @@ -410,11 +418,14 @@ private function oneClient(string $namespace, string $namespaceTest, string $con $schemaRegistry, ...$webHook, ); + $this->statusOutput->advanceStep('generating_webhooks'); } + $this->statusOutput->markStepDone('generating_webhooks'); $this->statusOutput->markStepDone('generating_webhooks_entry_point'); + yield from WebHooks::generate($this->configuration->destination->source . DIRECTORY_SEPARATOR, $namespace, $webHooksHydrators, $webHooks); $this->statusOutput->itemForStep('generating_hydrators', count($hydrators)); @@ -423,9 +434,11 @@ private function oneClient(string $namespace, string $namespaceTest, string $con $this->statusOutput->advanceStep('generating_hydrators'); } + $this->statusOutput->markStepDone('generating_hydrators'); $this->statusOutput->markStepDone('generating_hydrators_entry_point'); + yield from Hydrators::generate($this->configuration->destination->source . DIRECTORY_SEPARATOR, $namespace, ...$hydrators); $this->statusOutput->markStepDone('generating_templated_files'); @@ -447,9 +460,9 @@ private function oneClient(string $namespace, string $namespaceTest, string $con */ private function subSplitClient(string $namespace, string $namespaceTest, string $configurationLocation, SchemaRegistry $schemaRegistry, ThrowableSchema $throwableSchemaRegistry, array $schemas, array $paths, array $webHooks) { - $splits = []; - $hydrators = []; - $operations = []; + $splits = []; + $hydrators = []; + $operations = []; $this->statusOutput->itemForStep('generating_operations', count($paths)); foreach ($paths as $path) { foreach ($this->configuration->subSplit->sectionGenerator as $generator) { @@ -482,8 +495,10 @@ private function subSplitClient(string $namespace, string $namespaceTest, string $this->configuration, ); } + $this->statusOutput->advanceStep('generating_operations'); } + $this->statusOutput->markStepDone('generating_operations'); $webHooksHydrators = []; @@ -512,6 +527,7 @@ private function subSplitClient(string $namespace, string $namespaceTest, string $this->statusOutput->advanceStep('gathering_unknown_schemas'); } } + $this->statusOutput->markStepDone('gathering_unknown_schemas'); $sortedSchemas = []; @@ -575,13 +591,16 @@ private function subSplitClient(string $namespace, string $namespaceTest, string $aliases, ); } + $this->statusOutput->advanceStep('generating_schemas'); } + $this->statusOutput->markStepDone('generating_schemas'); $client = \ApiClients\Tools\OpenApiClientGenerator\Gatherer\Client::gather($this->spec, ...$paths); $this->statusOutput->markStepDone('generating_clientinterface'); + yield from ClientInterface::generate( $this->configuration->subSplit->subSplitsDestination . DIRECTORY_SEPARATOR . $this->splitPathPrefix($this->configuration->subSplit->rootPackage, '') . $this->configuration->destination->source, $namespace, @@ -589,6 +608,7 @@ private function subSplitClient(string $namespace, string $namespaceTest, string ); $this->statusOutput->markStepDone('generating_client'); + yield from Client::generate( $this->configuration->subSplit->subSplitsDestination . DIRECTORY_SEPARATOR . $this->splitPathPrefix($this->configuration->subSplit->rootPackage, '') . $this->configuration->destination->source, $namespace, @@ -613,11 +633,14 @@ private function subSplitClient(string $namespace, string $namespaceTest, string $schemaRegistry, ...$webHook, ); + $this->statusOutput->advanceStep('generating_webhooks'); } + $this->statusOutput->markStepDone('generating_webhooks'); $this->statusOutput->markStepDone('generating_webhooks_entry_point'); + yield from WebHooks::generate( $this->configuration->subSplit->subSplitsDestination . DIRECTORY_SEPARATOR . $this->splitPathPrefix($this->configuration->subSplit->rootPackage, '') . $this->configuration->destination->source, $namespace, @@ -634,11 +657,14 @@ private function subSplitClient(string $namespace, string $namespaceTest, string $hydrator ); } + $this->statusOutput->advanceStep('generating_hydrators'); } + $this->statusOutput->markStepDone('generating_hydrators'); $this->statusOutput->markStepDone('generating_hydrators_entry_point'); + yield from Hydrators::generate( $this->configuration->subSplit->subSplitsDestination . DIRECTORY_SEPARATOR . $this->splitPathPrefix($this->configuration->subSplit->rootPackage, '') . $this->configuration->destination->source, $namespace, @@ -739,6 +765,7 @@ private function subSplitClient(string $namespace, string $namespaceTest, string ); $this->statusOutput->advanceStep('generating_templates_files_subsplit_package'); } + $this->statusOutput->markStepDone('generating_templates_files_subsplit_package'); $this->statusOutput->markStepDone('generating_subsplit_configuration'); diff --git a/src/Registry/ThrowableSchema.php b/src/Registry/ThrowableSchema.php index 7f0ce50..e6aa402 100644 --- a/src/Registry/ThrowableSchema.php +++ b/src/Registry/ThrowableSchema.php @@ -8,9 +8,7 @@ final class ThrowableSchema { - /** - * @var array - */ + /** @var array */ private array $throwables = []; public function add(string $class): void diff --git a/src/StatusOutput.php b/src/StatusOutput.php index 11e1f7b..5645f4a 100644 --- a/src/StatusOutput.php +++ b/src/StatusOutput.php @@ -1,54 +1,52 @@ - */ + /** @var array */ private readonly array $steps; - /** - * @var array - */ + /** @var array */ private array $stepsStatus = []; - /** - * @var array - */ + /** @var array */ private array $itemsCountForStep = []; - /** - * @var array - */ + /** @var array */ private array $stepProgress = []; - private readonly Terminal $terminal; - private int $lastPaint = 0; + public function __construct(Step ...$steps) { $this->steps = $steps; foreach ($this->steps as $step) { $this->stepsStatus[$step->key] = '🌀'; - if ($step->progressBer) { - $this->itemsCountForStep[$step->key] = 0; - $this->stepProgress[$step->key] = 0; + if (! $step->progressBer) { + continue; } + + $this->itemsCountForStep[$step->key] = 0; + $this->stepProgress[$step->key] = 0; } - $this->terminal = terminal(); + + renderUsing(new OverWritingOutPut(new ConsoleOutput())); } public function render(): void { - $html = ''; + $html = '
'; $html .= ''; $html .= ''; $html .= ''; @@ -61,15 +59,16 @@ public function render(): void if ($step->progressBer && $this->itemsCountForStep[$step->key] > 0) { $progress = $this->stepProgress[$step->key] . '/' . $this->itemsCountForStep[$step->key]; } + $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; } + $html .= '
Status
' . $this->stepsStatus[$step->key] . '' . $step->name . '' . $progress . '
'; - $this->terminal->clear(); render($html); $this->lastPaint = time(); } @@ -94,6 +93,7 @@ public function markStepWontDo(string ...$keys): void foreach ($keys as $key) { $this->stepsStatus[$key] = '🚫'; } + $this->render(); } @@ -106,7 +106,7 @@ public function itemForStep(string $key, int $count): void public function advanceStep(string $key): void { $this->stepProgress[$key]++; - $percentage = (100 / $this->itemsCountForStep[$key]) * $this->stepProgress[$key]; + $percentage = 100 / $this->itemsCountForStep[$key] * $this->stepProgress[$key]; switch (true) { case $percentage <= 12.5: $this->stepsStatus[$key] = '🌑'; diff --git a/src/StatusOutput/OverWritingOutPut.php b/src/StatusOutput/OverWritingOutPut.php new file mode 100644 index 0000000..ffe3c6f --- /dev/null +++ b/src/StatusOutput/OverWritingOutPut.php @@ -0,0 +1,97 @@ +output->write($messages, $newline, $options); + } + + public function writeln(iterable|string $messages, int $options = 0): void + { + if (! is_string($messages)) { + $messages = implode(PHP_EOL, $messages); + } + + if ($this->previousLinecount > 0) { + $this->output->write(sprintf("\x1b[%dA", $this->previousLinecount)); + $this->output->write("\x1b[0J"); + } + + $this->previousLinecount = count(explode(PHP_EOL, $messages)); + + $this->output->writeln($messages, $options); + } + + public function setVerbosity(int $level): void + { + $this->output->setVerbosity($level); + } + + public function getVerbosity(): int + { + return $this->output->getVerbosity(); + } + + public function isQuiet(): bool + { + return $this->output->isQuiet(); + } + + public function isVerbose(): bool + { + return $this->output->isVerbose(); + } + + public function isVeryVerbose(): bool + { + return $this->output->isVeryVerbose(); + } + + public function isDebug(): bool + { + return $this->output->isDebug(); + } + + public function setDecorated(bool $decorated): void + { + $this->output->setDecorated($decorated); + } + + public function isDecorated(): bool + { + return $this->output->isDecorated(); + } + + public function setFormatter(OutputFormatterInterface $formatter): void + { + $this->output->setFormatter($formatter); + } + + public function getFormatter(): OutputFormatterInterface + { + return $this->output->getFormatter(); + } +} diff --git a/src/StatusOutput/Step.php b/src/StatusOutput/Step.php index e7055b3..391edea 100644 --- a/src/StatusOutput/Step.php +++ b/src/StatusOutput/Step.php @@ -1,5 +1,7 @@