Skip to content

Commit b5254c7

Browse files
committed
Add cli test runner
1 parent 5dc34a9 commit b5254c7

File tree

9 files changed

+211
-65
lines changed

9 files changed

+211
-65
lines changed

.php-cs-fixer.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
->name('.php_cs')
1212
->exclude('vendor')
1313
->exclude('.git')
14+
->exclude('coverage')
1415
->in(__DIR__);
1516

1617
return (new PhpCsFixer\Config())

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,11 @@ To dump the graph, simply use the built-in dumper:
3737
$dumper = new PHPCfg\Printer\Text();
3838
echo $dumper->printScript($script);
3939
```
40+
41+
## CLI
42+
43+
You can leverage the CLI binary to generate debug traces of the CFG for any file, or for printing GraphViz visualizations.
44+
45+
```shell
46+
bin/php-cfg dot -o output.dot path/to/file.php
47+
```

bin/php-cfg

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/usr/bin/env php
2+
<?php
3+
require_once(__DIR__ . '/../vendor/autoload.php');
4+
5+
// Init App with name and version
6+
$app = new Ahc\Cli\Application('PHP-CFG', 'v0.0.1');
7+
8+
$app->add(new PHPCfg\Cli\PrintCommand, 'p');
9+
$app->add(new PHPCfg\Cli\DotCommand, 'd');
10+
11+
$app->add(new PHPCfg\Cli\RunTestCommand);
12+
13+
$app->handle($_SERVER['argv']); // if argv[1] is `i` or `init` it executes InitCommand

composer.json

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,20 @@
1111
"require": {
1212
"php": ">=8.1",
1313
"nikic/php-parser": "^5.0",
14-
"phpdocumentor/graphviz": "^1.0.4"
14+
"phpdocumentor/graphviz": "^1.0.4",
15+
"adhocore/cli": "^v1.0.0"
1516
},
1617
"require-dev": {
1718
"phpunit/phpunit": ">=10.0",
1819
"friendsofphp/php-cs-fixer": ">=3.86"
1920
},
2021
"autoload": {
2122
"psr-4": {
22-
"PHPCfg\\": "lib/PHPCfg/"
23+
"PHPCfg\\": "lib/PHPCfg/",
24+
"PHPCfg\\Cli\\": "src/Cli"
2325
}
24-
}
26+
},
27+
"bin": [
28+
"bin/php-cfg"
29+
]
2530
}

demo.php

Lines changed: 0 additions & 62 deletions
This file was deleted.

src/Cli/BaseCommand.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
/**
4+
* This file is part of PHP-CFG, a Control flow graph implementation for PHP
5+
*
6+
* @copyright 2015 Anthony Ferrara. All rights reserved
7+
* @license MIT See LICENSE at the root of the project for more info
8+
*/
9+
10+
namespace PHPCfg\Cli;
11+
12+
use Ahc\Cli\Input\Command;
13+
use PHPCfg\Parser;
14+
use PHPCfg\Script;
15+
use PHPCfg\Traverser;
16+
use PHPCfg\Visitor;
17+
use PhpParser\ParserFactory;
18+
19+
abstract class BaseCommand extends Command
20+
{
21+
protected function exec(string $file, string $code, bool $optimize): Script
22+
{
23+
$parser = new Parser((new ParserFactory())->createForNewestSupportedVersion());
24+
25+
$traverser = new Traverser();
26+
27+
if ($optimize) {
28+
$traverser->addVisitor(new Visitor\Simplifier());
29+
}
30+
31+
$script = $parser->parse($code, $file);
32+
$traverser->traverse($script);
33+
return $script;
34+
}
35+
}

src/Cli/DotCommand.php

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
/**
4+
* This file is part of PHP-CFG, a Control flow graph implementation for PHP
5+
*
6+
* @copyright 2015 Anthony Ferrara. All rights reserved
7+
* @license MIT See LICENSE at the root of the project for more info
8+
*/
9+
10+
namespace PHPCfg\Cli;
11+
12+
use Ahc\Cli\Output\Color;
13+
use PHPCfg\Printer;
14+
15+
class DotCommand extends BaseCommand
16+
{
17+
public function __construct()
18+
{
19+
parent::__construct('dot', 'Print GraphViz DOT Representation');
20+
21+
$help = "Todo";
22+
23+
$this
24+
->argument('<file>', 'File to process')
25+
->option('-n|--no-optimize', 'Disable Optimizers')
26+
->option('-o|--output', 'Output File', null, '-')
27+
;
28+
}
29+
30+
public function execute($file, $optimize, $output)
31+
{
32+
$io = $this->app()->io();
33+
$color = new Color();
34+
35+
if (file_exists($file)) {
36+
$code = file_get_contents($file);
37+
} else {
38+
$io->write($color->error("Unknown file $file"));
39+
return 1;
40+
}
41+
42+
$script = $this->exec($file, $code, $optimize);
43+
44+
$dumper = new Printer\GraphViz();
45+
$result = $dumper->printScript($script);
46+
if ($output === '-') {
47+
$io->write($result);
48+
} else {
49+
file_put_contents($output, $result);
50+
$io->write("Saved to {$output}", true);
51+
}
52+
}
53+
}

src/Cli/PrintCommand.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
/**
4+
* This file is part of PHP-CFG, a Control flow graph implementation for PHP
5+
*
6+
* @copyright 2015 Anthony Ferrara. All rights reserved
7+
* @license MIT See LICENSE at the root of the project for more info
8+
*/
9+
10+
namespace PHPCfg\Cli;
11+
12+
use Ahc\Cli\Output\Color;
13+
use PHPCfg\Printer;
14+
15+
class PrintCommand extends BaseCommand
16+
{
17+
public function __construct()
18+
{
19+
parent::__construct('print', 'Print CFG Representation');
20+
21+
22+
$this
23+
->argument('<file>', 'File to process')
24+
->option('-n|--no-optimize', 'Disable Optimizers', 'boolval', false)
25+
->option('-a|--attributes', 'Render Attributes', 'boolval', false)
26+
;
27+
}
28+
29+
public function execute($file, $optimize, $attributes)
30+
{
31+
$io = $this->app()->io();
32+
$color = new Color();
33+
34+
if (file_exists($file)) {
35+
$code = file_get_contents($file);
36+
} else {
37+
$io->write($color->error("Unknown file $file"));
38+
return 1;
39+
}
40+
41+
$script = $this->exec($file, $code, $optimize);
42+
43+
$dumper = new Printer\Text($attributes);
44+
$io->write($dumper->printScript($script), true);
45+
}
46+
}

src/Cli/RunTestCommand.php

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
/**
4+
* This file is part of PHP-CFG, a Control flow graph implementation for PHP
5+
*
6+
* @copyright 2015 Anthony Ferrara. All rights reserved
7+
* @license MIT See LICENSE at the root of the project for more info
8+
*/
9+
10+
namespace PHPCfg\Cli;
11+
12+
use Ahc\Cli\Output\Color;
13+
use PHPCfg\Printer;
14+
15+
class RunTestCommand extends BaseCommand
16+
{
17+
public function __construct()
18+
{
19+
parent::__construct('run-test', 'Run test name - Used for generating results when writing code tests');
20+
21+
$help = "Todo";
22+
23+
$this
24+
->argument('<test>', 'Name of test to run (without .test suffix)')
25+
;
26+
}
27+
28+
public function execute($test)
29+
{
30+
$io = $this->app()->io();
31+
$color = new Color();
32+
33+
$file = __DIR__ . '/../../test/code/' . $test . '.test';
34+
35+
if (file_exists($file)) {
36+
[$code] = explode('-----', file_get_contents($file), 2);
37+
} else {
38+
$io->write($color->error("Unknown file $file"));
39+
return 1;
40+
}
41+
42+
$script = $this->exec($file, $code, true);
43+
44+
$dumper = new Printer\Text();
45+
$io->write($dumper->printScript($script), true);
46+
}
47+
}

0 commit comments

Comments
 (0)