Skip to content

Commit

Permalink
Ignore inaccessible class child nodes (#15)
Browse files Browse the repository at this point in the history
* Ignore inaccessible class child nodes

* Add config flag to include inaccessible class nodes

* Add test for include-inaccessible-class-nodes config
  • Loading branch information
herndlm authored Feb 8, 2023
1 parent dd405ec commit 9b9067b
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/GenerateStubsCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public function configure(): void
->addOption('visitor', null, InputOption::VALUE_REQUIRED, 'Path to a PHP file which returns a `StubsGenerator\NodeVisitor` instance to replace the default node visitor.')
->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.)', '')
->addOption('nullify-globals', null, InputOption::VALUE_NONE, 'Initialize all global variables with a value of `null`, instead of their assigned value.')
->addOption('include-inaccessible-class-nodes', null, InputOption::VALUE_NONE, 'Include inaccessible class nodes like private members.')
->addOption('stats', null, InputOption::VALUE_NONE, 'Whether to print stats instead of outputting stubs. Stats will always be printed if --out is provided.');

foreach (self::SYMBOL_OPTIONS as $opt) {
Expand Down Expand Up @@ -117,6 +118,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$finder = $this->parseSources($input);
$generator = new StubsGenerator($this->parseSymbols($input), [
'nullify_globals' => $input->getOption('nullify-globals'),
'include_inaccessible_class_nodes' => $input->getOption('include-inaccessible-class-nodes')
]);

$result = $generator->generate($finder, $visitor);
Expand Down
12 changes: 12 additions & 0 deletions src/NodeVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Stmt;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassConst;
use PhpParser\Node\Stmt\ClassLike;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Const_;
Expand All @@ -19,6 +20,7 @@
use PhpParser\Node\Stmt\If_;
use PhpParser\Node\Stmt\Interface_;
use PhpParser\Node\Stmt\Namespace_;
use PhpParser\Node\Stmt\Property;
use PhpParser\Node\Stmt\Trait_;
use PhpParser\NodeTraverser;
use PhpParser\NodeVisitorAbstract;
Expand Down Expand Up @@ -47,6 +49,8 @@ class NodeVisitor extends NodeVisitorAbstract
private $needsConstants;
/** @var bool */
private $nullifyGlobals;
/** @var bool */
private $includeInaccessibleClassNodes;

/**
* @psalm-suppress PropertyNotSetInConstructor
Expand Down Expand Up @@ -101,6 +105,7 @@ public function init(int $symbols = StubsGenerator::DEFAULT, array $config = [])
$this->needsConstants = ($symbols & StubsGenerator::CONSTANTS) !== 0;

$this->nullifyGlobals = !empty($config['nullify_globals']);
$this->includeInaccessibleClassNodes = ($config['include_inaccessible_class_nodes'] ?? false) === true;

$this->globalNamespace = new Namespace_();
}
Expand Down Expand Up @@ -238,6 +243,13 @@ public function leaveNode(Node $node, bool $preserveStack = false)
// Implies `$parent instanceof ClassLike`, which means $node is a
// either a method, property, or constant, or its part of the
// declaration itself (e.g., `extends`).

if (!$this->includeInaccessibleClassNodes && $parent instanceof Class_ && ($node instanceof ClassMethod || $node instanceof ClassConst || $node instanceof Property)) {
if ($node->isPrivate() || ($parent->isFinal() && $node->isProtected())) {
return NodeTraverser::REMOVE_NODE;
}
}

return;
}

Expand Down
1 change: 1 addition & 0 deletions test/NodeVisitorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public function inputOutputProvider(): array
{
$cases = [
'classes',
['classes', 'classes-include-inaccessible-class-nodes', null, ['include_inaccessible_class_nodes' => true]],
'classes-with-dependencies',
'circular-dependency',
'functions',
Expand Down
73 changes: 73 additions & 0 deletions test/files/classes-include-inaccessible-class-nodes.out.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php
/** doc */
abstract class A extends \B implements \C
{
/** doc */
protected const A = 'B';

/** doc */
private const B = 'C';

/** doc */
public static $a = 'a';

private static $b = 'b';

/** doc */
public static function b($a): void
{
}

/** doc */
abstract public function c($a): string;

/** doc */
protected function d($a) : void
{
}

/** doc */
protected abstract function e($a) : string;

/** doc */
private function f($a): void
{
}
}

class D
{
public function a(string $a): string
{
}
}

final class E
{
/** doc */
public $a = 'a';

/** doc */
protected $b = 'b';

/** doc */
public function a($a) : void
{
}

/** doc */
protected function b($a): void
{
}
}

trait F
{
/** doc */
private $a = 'a';

/** doc */
private function a($a) : void
{
}
}
53 changes: 53 additions & 0 deletions test/files/classes.in.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@ abstract class A extends B implements C
/** doc */
protected const A = 'B';

/** doc */
private const B = 'C';

/** doc */
public static $a = 'a';

private static $b = 'b';

/** doc */
public static function b($a): void
{
Expand All @@ -16,6 +21,21 @@ public static function b($a): void

/** doc */
abstract public function c($a): string;

/** doc */
protected function d($a): void
{
return;
}

/** doc */
abstract protected function e($a): string;

/** doc */
private function f($a): void
{
return;
}
}

if (!class_exists('D')) {
Expand All @@ -27,3 +47,36 @@ public function a(string $a): string
}
}
}

final class E
{
/** doc */
public $a = 'a';

/** doc */
protected $b = 'b';

/** doc */
public function a($a): void
{
return;
}

/** doc */
protected function b($a): void
{
return;
}
}

trait F
{
/** doc */
private $a = 'a';

/** doc */
private function a($a): void
{
return;
}
}
30 changes: 30 additions & 0 deletions test/files/classes.out.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ public static function b($a): void

/** doc */
abstract public function c($a): string;

/** doc */
protected function d($a) : void
{
}

/** doc */
protected abstract function e($a) : string;
}

class D
Expand All @@ -23,3 +31,25 @@ public function a(string $a): string
{
}
}

final class E
{
/** doc */
public $a = 'a';

/** doc */
public function a($a) : void
{
}
}

trait F
{
/** doc */
private $a = 'a';

/** doc */
private function a($a) : void
{
}
}

0 comments on commit 9b9067b

Please sign in to comment.