php-stubs-generator
php-stubs-generator copied to clipboard
Inverted operation
Hello!
@GiacoCorsiglia Is it possible to output only parts which have side-effects?
Definitely doable with PHP-Parser, but I'd say this is probably too different from generating stubs to belong in this tool. The implementation would have different considerations. For example, you'd have to recursively inspect every branch of every function starting with those called from the global scope (see below code sample). The NodeVisitor
for generating stubs currently avoids doing that.
I'm open to ideas if you feel otherwise.
function a() {
// Never called, should be discarded.
}
function b() {
// called by c(), must be included in "side effect stubs".
}
function c() {
return b();
}
$var = c();
Thank you for your guidance.
Would it be simpler if I want only non-classes? I would check huge codebases with this, looking for everything except classes thus making sure the code is clean.
Ah, I assumed you'd want the generated code to still function. If you want to output everything but declarations, a NodeVisitor
with this method would probably do the trick (ignoring constant declarations):
public function leaveNode(Node $node)
{
if ($node instanceof Function_
|| $node instanceof Class_
|| $node instanceof Interface_
|| $node instanceof Trait_
) {
return NodeTraverser::REMOVE_NODE;
}
}
So yes, that seems simpler. I imagine such a tool would be more useful if it also output file names and line numbers indicating where the code with side effects lives.
Thank you!
Adding this to NodeVisitor::leaveNode()
generated the code below.
// Inverted operation: only OOP code should remain
if ($node instanceof Class_
|| $node instanceof Interface_
|| $node instanceof Trait_
) {
return NodeTraverser::REMOVE_NODE;
}
<?php
/**
* index.php - A frontend program belépőpontja.
*/
namespace app\frontend\web {
/** @var \app\frontend\core\FrontendMain $main */
$main = \app\frontend\core\FrontendMain::getInstance();
}
/**
* index.php - Az API program belépőpontja.
*/
namespace app\api\web {
/** @var \app\api\core\ApiMain $main */
$main = \app\api\core\ApiMain::getInstance();
}
/**
* index.php - A backend program belépőpontja.
*/
namespace app\backend\web {
/** @var \app\backend\core\BackendMain $main */
$main = \app\backend\core\BackendMain::getInstance();
}
namespace {
// Cron program betöltése
/** @var \core\Cron $cron */
$cron = \core\Cron::getInstance();
}
So our code is clean!! These are the 3 entry points.
Would you add a command line option to do this?
Here it is
diff --git a/src/NodeVisitor.php b/src/NodeVisitor.php
index e299e6b..76b4a77 100644
--- a/src/NodeVisitor.php
+++ b/src/NodeVisitor.php
@@ -19,6 +19,7 @@ use PhpParser\Node\Stmt\Trait_;
use PhpParser\NodeTraverser;
use PhpParser\NodeVisitorAbstract;
use PhpParser\Node\Expr\ConstFetch;
+use PhpParser\Node\Stmt\Use_;
/**
* On node traversal, this visitor converts any AST to one just containing stub
@@ -174,6 +175,15 @@ class NodeVisitor extends NodeVisitorAbstract
}
$parent = $this->stack[count($this->stack) - 1] ?? null;
+ // Inverted operation: only OOP code should remain
+ if ($node instanceof Class_
+ || $node instanceof Interface_
+ || $node instanceof Trait_
+ || $node instanceof Use_
+ ) {
+ return NodeTraverser::REMOVE_NODE;
+ }
+
if ($node instanceof Assign
|| $node instanceof Function_
|| $node instanceof Class_
@@ -244,6 +254,7 @@ class NodeVisitor extends NodeVisitorAbstract
}
// Any other top level junk we are happy to remove.
+return;
return NodeTraverser::REMOVE_NODE;
}
This removes all but OOP.
Would it be possible to add a command line option? like --non-oop