Skip to content

Commit 5e0f750

Browse files
committed
Add support for a custom node visitor to override the default.
1 parent c579642 commit 5e0f750

File tree

3 files changed

+28
-4
lines changed

3 files changed

+28
-4
lines changed

src/GenerateStubsCommand.php

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ public function configure(): void
5858
->addOption('out', null, InputOption::VALUE_REQUIRED, 'Path to a file to write pretty-printed stubs to. If unset, stubs will be written to stdout.')
5959
->addOption('force', null, InputOption::VALUE_NONE, 'Whether to force an overwrite.')
6060
->addOption('finder', null, InputOption::VALUE_REQUIRED, 'Path to a PHP file which returns a `Symfony\Finder` instance including the set of files that should be parsed. Can be used instead of, but not in addition to, passing sources directly.')
61+
->addOption('visitor', null, InputOption::VALUE_REQUIRED, 'Path to a PHP file which returns a `StubsGenerator\NodeVisitor` instance to replace the default node visitor.')
6162
->addOption('header', null, InputOption::VALUE_REQUIRED, 'A doc comment to prepend to the top of the generated stubs file. (Will be added below the opening `<?php` tag.)', '')
6263
->addOption('nullify-globals', null, InputOption::VALUE_NONE, 'Initialize all global variables with a value of `null`, instead of their assigned value.')
6364
->addOption('stats', null, InputOption::VALUE_NONE, 'Whether to print stats instead of outputting stubs. Stats will always be printed if --out is provided.');
@@ -94,13 +95,30 @@ protected function interact(InputInterface $input, OutputInterface $output): voi
9495
protected function execute(InputInterface $input, OutputInterface $output)
9596
{
9697
$io = new SymfonyStyle($input, $output);
98+
$visitor = null;
99+
$visitorPath = $input->getOption('visitor');
100+
101+
if ($visitorPath) {
102+
$visitorPath = $this->resolvePath($visitorPath);
103+
if (!$this->filesystem->exists($visitorPath) || is_dir($visitorPath)) {
104+
throw new InvalidArgumentException("Bad --visitor path: '$visitorPath' does not exist or is a directory.");
105+
}
106+
try {
107+
$visitor = @include $visitorPath;
108+
} catch (Exception $e) {
109+
throw new RuntimeException("Could not resolve a `StubsGenerator\NodeVisitor` from '$visitorPath'.", 0, $e);
110+
}
111+
if (!$visitor || !($visitor instanceof NodeVisitor)) {
112+
throw new RuntimeException("Could not resolve a `StubsGenerator\NodeVisitor` from '$visitorPath'.");
113+
}
114+
}
97115

98116
$finder = $this->parseSources($input);
99117
$generator = new StubsGenerator($this->parseSymbols($input), [
100118
'nullify_globals' => $input->getOption('nullify-globals'),
101119
]);
102120

103-
$result = $generator->generate($finder);
121+
$result = $generator->generate($finder, $visitor);
104122

105123
$printer = new Standard();
106124

src/NodeVisitor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ class NodeVisitor extends NodeVisitorAbstract
8484
/**
8585
* @param int $symbols Set of symbol types to include stubs for.
8686
*/
87-
public function __construct(int $symbols = StubsGenerator::DEFAULT, array $config = [])
87+
public function init(int $symbols = StubsGenerator::DEFAULT, array $config = [])
8888
{
8989
$this->needsFunctions = ($symbols & StubsGenerator::FUNCTIONS) !== 0;
9090
$this->needsClasses = ($symbols & StubsGenerator::CLASSES) !== 0;

src/StubsGenerator.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,15 +99,21 @@ public function __construct(int $symbols = self::DEFAULT, array $config = [])
9999
* pretty-printed stubs.
100100
*
101101
* @param Finder $finder The set of files to generate (merged) stubs for.
102+
* @param NodeVisitor $visitor The optional node visitor to override the default.
102103
*
103104
* @return Result
104105
*/
105-
public function generate(Finder $finder): Result
106+
public function generate(Finder $finder, NodeVisitor $visitor = null): Result
106107
{
107108
$parser = (new ParserFactory())->create(ParserFactory::PREFER_PHP7);
108109

110+
if (!($visitor instanceof NodeVisitor)) {
111+
$visitor = new NodeVisitor;
112+
}
113+
114+
$visitor->init($this->symbols, $this->config);
115+
109116
$traverser = new NodeTraverser();
110-
$visitor = new NodeVisitor($this->symbols, $this->config);
111117
$traverser->addVisitor(new NameResolver());
112118
$traverser->addVisitor($visitor);
113119

0 commit comments

Comments
 (0)