Skip to content

Commit

Permalink
Organise generator into namespaces
Browse files Browse the repository at this point in the history
Trying to make this project as easy to contribute to as possible - smaller modules make it easier to focus on parts relevant to an issue
  • Loading branch information
shish committed Feb 3, 2025
1 parent 842f352 commit 97d0467
Show file tree
Hide file tree
Showing 22 changed files with 73 additions and 63 deletions.
23 changes: 9 additions & 14 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,15 @@ Safe-PHP code is generated automatically from the PHP doc.
### Generator

* `safe.php` is the CLI entry point, with a few utility commands, but the
most important one is `generate`, which generates the Safe-PHP code.
* `GenerateCommand` is the class that actually does the generation:
* Call `Scanner` to get a list of all the PHP XML documentation files
(returned in a `ScannerResponse`).
* Use `DocPage` to parse each XML file and extract the relevant
information.
* The "relevant information" is a list of `Method`s, which have
`Parameter`s, which have `Type`s.
* (As well as taking some information from the PHP XML docs, we also
take some type-hint information from PHPStan's type-hint database,
and merge these sources together to get a more complete picture.)
* Given a bunch of `Method` meta-data objects, `FileCreator` will create
files in `generated/` and use `WritePhpFunction` to write safe wrappers
for each function into those files.
most important one is `\Safe\Commands\GenerateCommand`, which does the
generation:
* Use `\Safe\XmlDocParser` to parse the PHP XML documentation
and pull out information about `Method`s, `Parameter`s, and
`Type`s - try to figure out which methods are unsafe.
* Use `\Safe\PhpStanFunctions` to get a bit of extra data from
PHPStan's typehint database, and merge that with the XML info.
* Given this list of unsafe functions, use `\Safe\Generator` to
write a bunch of safe wrappers.

### End-Users

Expand Down
6 changes: 3 additions & 3 deletions generator/safe.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

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

use Safe\GenerateCommand;
use Safe\ScanObjectsCommand;
use Safe\FunctionInfoCommand;
use Safe\Commands\FunctionInfoCommand;
use Safe\Commands\GenerateCommand;
use Safe\Commands\ScanObjectsCommand;
use Symfony\Component\Console\Application;

$application = new Application();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

declare(strict_types=1);

namespace Safe;
namespace Safe\Commands;

use Safe\XmlDocParser\Scanner;
use Safe\XmlDocParser\DocPage;
use Safe\Generator\WritePhpFunction;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@

declare(strict_types=1);

namespace Safe;
namespace Safe\Commands;

use Safe\XmlDocParser\Scanner;
use Safe\XmlDocParser\DocPage;
use Safe\Generator\FileCreator;
use Safe\Generator\ComposerJsonEditor;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
Expand Down Expand Up @@ -37,9 +42,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$output->writeln('These functions have been ignored and must be dealt with manually: '.\implode(', ', $overloadedFunctions));

$fileCreator = new FileCreator();
$fileCreator->generatePhpFile($functions, __DIR__ . '/../../generated/');
$fileCreator->generateFunctionsList($functions, __DIR__ . '/../../generated/functionsList.php');
$fileCreator->generateRectorFile($functions, __DIR__ . '/../../rector-migrate.php');
$fileCreator->generatePhpFile($functions, __DIR__ . '/../../../generated/');
$fileCreator->generateFunctionsList($functions, __DIR__ . '/../../../generated/functionsList.php');
$fileCreator->generateRectorFile($functions, __DIR__ . '/../../../rector-migrate.php');


$modules = [];
Expand All @@ -63,7 +68,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int

private function rmGenerated(): void
{
$exceptions = \glob(__DIR__.'/../../generated/Exceptions/*.php');
$exceptions = \glob(__DIR__.'/../../../generated/Exceptions/*.php');
if ($exceptions === false) {
throw new \RuntimeException('Failed to require the generated exception files');
}
Expand All @@ -72,7 +77,7 @@ private function rmGenerated(): void
\unlink($exception);
}

$files = \glob(__DIR__.'/../../generated/*.php');
$files = \glob(__DIR__.'/../../../generated/*.php');
if ($files === false) {
throw new \RuntimeException('Failed to require the generated files');
}
Expand All @@ -88,7 +93,7 @@ private function rmGenerated(): void

private function runCsFix(OutputInterface $output): void
{
$process = new Process(['vendor/bin/phpcbf'], __DIR__.'/../..');
$process = new Process(['vendor/bin/phpcbf'], __DIR__.'/../../..');
$process->setTimeout(600);
$process->run(function ($type, $buffer) use ($output) {
if (Process::ERR === $type) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

declare(strict_types=1);

namespace Safe;
namespace Safe\Commands;

use Safe\XmlDocParser\Scanner;
use Safe\XmlDocParser\DocPage;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Safe;
namespace Safe\Generator;

/**
* This class will edit the main composer.json file to add the list of files generated from modules.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

declare(strict_types=1);

namespace Safe;
namespace Safe\Generator;

use Safe\XmlDocParser\Method;

use Rector\Config\RectorConfig;
use Rector\Renaming\Rector\FuncCall\RenameFunctionRector;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

declare(strict_types=1);

namespace Safe;
namespace Safe\Generator;

use Safe\XmlDocParser\Method;
use Safe\XmlDocParser\Parameter;

class WritePhpFunction
{
Expand Down
2 changes: 1 addition & 1 deletion generator/src/PhpStanFunctions/PhpStanParameter.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Safe\PhpStanFunctions;

use Safe\Type;
use Safe\XmlDocParser\Type;

class PhpStanParameter
{
Expand Down
4 changes: 2 additions & 2 deletions generator/src/PhpStanFunctions/PhpStanType.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

namespace Safe\PhpStanFunctions;

use Safe\Method;
use Safe\Type;
use Safe\XmlDocParser\Method;
use Safe\XmlDocParser\Type;

/**
* This class will parse the type from either parameters or return as given by phpstan and generate appropriate doc-block comments or typehints
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Safe;
namespace Safe\XmlDocParser;

use function explode;
use function strpos;
Expand All @@ -15,7 +15,7 @@ public function __construct(private readonly string $path)

public static function findDocDir(): string
{
return __DIR__ . '/../doc';
return __DIR__ . '/../../doc';
}

public static function findReferenceDir(): string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

declare(strict_types=1);

namespace Safe;
namespace Safe\XmlDocParser;

use Safe\PhpStanFunctions\PhpStanFunction;
use Safe\PhpStanFunctions\PhpStanFunctionMapReader;
use Safe\PhpStanFunctions\PhpStanType;
use Safe\Generator\FileCreator;

class Method
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Safe;
namespace Safe\XmlDocParser;

use Safe\PhpStanFunctions\PhpStanFunction;
use Safe\PhpStanFunctions\PhpStanParameter;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Safe;
namespace Safe\XmlDocParser;

use function array_merge;
use function iterator_to_array;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Safe;
namespace Safe\XmlDocParser;

class ScannerResponse
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Safe;
namespace Safe\XmlDocParser;

class Type
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Safe;
namespace Safe\Generator;

use PHPUnit\Framework\TestCase;

Expand Down
35 changes: 17 additions & 18 deletions generator/tests/PhpStanFunctions/PhpStanTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@

namespace Safe\PhpStanFunctions;


use PHPUnit\Framework\TestCase;
use Safe\Method;
use Safe\XmlDocParser\Method;

class PhpStanTypeTest extends TestCase
{
public function testMixedTypes(): void
public function testMixedTypes(): void
{
$param = new PhpStanType('array|string|int');
$this->assertEquals('array|string|int', $param->getDocBlockType());
Expand Down Expand Up @@ -54,8 +53,8 @@ public function testGenerics(): void
$this->assertEquals('array{0:float,1:float,2:float,3:float,4:float,5:float}', $param->getDocBlockType());
$this->assertEquals('array', $param->getSignatureType());
}
public function testNullable(): void

public function testNullable(): void
{
$param = new PhpStanType('array|null');
$this->assertEquals(true, $param->isNullable());
Expand All @@ -77,8 +76,8 @@ public function testNullable(): void
$this->assertEquals('\HashContext|null', $param->getDocBlockType());
$this->assertEquals('?\HashContext', $param->getSignatureType());
}
public function testParenthesisOutsideOfCallable(): void

public function testParenthesisOutsideOfCallable(): void
{
$param = new PhpStanType('(?int)|(?string)');
$this->assertEquals(true, $param->isNullable());
Expand All @@ -93,8 +92,8 @@ public function testFalsable(): void
$this->assertEquals('string|false', $param->getDocBlockType());
$this->assertEquals('string', $param->getSignatureType());
}
public function testResource(): void

public function testResource(): void
{
$param = new PhpStanType('resource');
$this->assertEquals('resource', $param->getDocBlockType());
Expand All @@ -107,8 +106,8 @@ public function testNamespace(): void
$this->assertEquals('\GMP', $param->getDocBlockType());
$this->assertEquals('\GMP', $param->getSignatureType());
}
public function testVoid(): void

public function testVoid(): void
{
$param = new PhpStanType('');
$this->assertEquals('', $param->getDocBlockType());
Expand All @@ -122,8 +121,8 @@ public function testVoid(): void
$this->assertEquals('void', $param->getDocBlockType());
$this->assertEquals('void', $param->getSignatureType());
}
public function testOciSpecialCases(): void

public function testOciSpecialCases(): void
{
$param = new PhpStanType('OCI-Collection');
$this->assertEquals('\OCI-Collection', $param->getDocBlockType());
Expand All @@ -133,14 +132,14 @@ public function testOciSpecialCases(): void
$this->assertEquals('\OCI-Lob', $param->getDocBlockType());
$this->assertEquals('', $param->getSignatureType());
}
public function testErrorTypeInteraction(): void

public function testErrorTypeInteraction(): void
{
//bool => void if the method is falsy
$param = new PhpStanType('bool');
$this->assertEquals('void', $param->getDocBlockType(Method::FALSY_TYPE));
$this->assertEquals('void', $param->getSignatureType(Method::FALSY_TYPE));

//int|false => int if the method is falsy
$param = new PhpStanType('int|false');
$this->assertEquals('int', $param->getDocBlockType(Method::FALSY_TYPE));
Expand All @@ -155,8 +154,8 @@ public function testErrorTypeInteraction(): void
$this->assertEquals('array|null', $param->getDocBlockType(Method::FALSY_TYPE));
$this->assertEquals('?array', $param->getSignatureType(Method::FALSY_TYPE));
}
public function testDuplicateType(): void

public function testDuplicateType(): void
{
$param = new PhpStanType('array<string,string>|array<string,false>|array<string,array<int,mixed>>');
$this->assertEquals('array<string,string>|array<string,false>|array<string,array<int,mixed>>', $param->getDocBlockType());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Safe;
namespace Safe\XmlDocParser;

use PHPUnit\Framework\TestCase;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Safe;
namespace Safe\XmlDocParser;

use PHPUnit\Framework\TestCase;
use Safe\PhpStanFunctions\PhpStanFunctionMapReader;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Safe;
namespace Safe\XmlDocParser;

use PHPUnit\Framework\TestCase;

Expand All @@ -20,7 +20,7 @@ public function testGetMethodsPaths(): void

public function testGetFunctionsPaths(): void
{
$scanner = new Scanner(DocPage::findReferenceDir());
$scanner = new Scanner(DocPage::findReferenceDir() . '/');
$paths = $scanner->getMethodsPaths();

$this->assertArrayNotHasKey(DocPage::findReferenceDir() . '/filesystem/functions/chmod.xml', $paths);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Safe;
namespace Safe\XmlDocParser;

use PHPUnit\Framework\TestCase;

Expand Down

0 comments on commit 97d0467

Please sign in to comment.