framework
framework copied to clipboard
SelfValueVisitor throws exception on parsing class without namespace
Error message:
Call to a member function toString() on null in vendor/goaop/framework/src/Instrument/Transformer/SelfValueVisitor.php:72
public function enterNode(Node $node)
{
if ($node instanceof Stmt\Namespace_) {
$this->namespace = $node->name->toString();
$node->name
is null in a class without namespace.
Could you please report your framework version, PHP version and steps to reproduce this isssue.
Yeah, the goaop/framework version is 2.3.1 and the PHP version is 7.1.23.
More details about the exception stack trace:
Stack trace:
#0 vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(200): Go\Instrument\Transformer\SelfValueVisitor->enterNode(Object(PhpParser\Node\Stmt\Namespace_))
#1 vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(91): PhpParser\NodeTraverser->traverseArray(Array)
#2 vendor/goaop/framework/src/Instrument/Transformer/SelfValueTransformer.php(32): PhpParser\NodeTraverser->traverse(Array)
#3 vendor/goaop/framework/src/Instrument/Transformer/CachingTransformer.php(121): Go\Instrument\Transformer\SelfValueTransformer->transform(Object(Go\Instrument\Transformer\StreamMetaData))
I simplify my project as below:
annotation/test.php
<?php
namespace AopTest;
use Doctrine\Common\Annotations\Annotation;
/**
* Pointcut annotation.
* @Annotation
* @Target("METHOD")
*/
class Test extends Annotation {
}
aspect/test.php
<?php
use Go\Aop\Intercept\MethodInvocation;
use Go\Lang\Annotation\Around;
/**
* Test Aspect
*/
class AspectTest implements \Go\Aop\Aspect {
/**
* @Around("@execution(AopTest\Test)")
*/
public function aroundTest(MethodInvocation $invocation) {
echo "Before around<br/>";
$res = $invocation->proceed();
echo "After around<br/>";
return $res;
}
}
service/profit/test.php
<?php
use AopTest\Test;
/**
* Example class to test aspects
*/
class ServiceProfitTest {
/**
* @Test
*/
public function test()
{
echo "Test Result<br/>";
}
}
aop_kernel.php
<?php
require_once (DIR_APPLICATION."aspect/test.php");
use Go\Core\AspectKernel;
use Go\Core\AspectContainer;
/**
* Application Aspect Kernel
*/
class AopKernel extends AspectKernel {
protected function configureAop(AspectContainer $container) {
$container->registerAspect(new AspectTest());
}
}
index.php
// codes about initing the aspect kernel
$aop_kernel = AopKernel::getInstance();
$aop_kernel->init(array(
'debug' => true,
// Cache directory
'cacheDir' => DIR_CACHE,
'includePaths' => array(
DIR_APPLICATION . 'service/'
),
'excludePaths' => array(
DIR_ROOT . 'vendor/',
DIR_APPLICATION . 'aspect/',
),
));
And then I load and invoke the ServiceProfitTest::test
method in a controller method.
public function someControllerMethod() {
$this->load->service("profit/test");
$this->service_profit_test->test();
}
The $this->load->service
above is the loader in my project which maintains the mapping of file name and class name. More detail is as below:
public function service($service, $data = array()) {
$file = DIR_APPLICATION . 'service/' . $service . '.php';
$class = 'Service' . preg_replace('/[^a-zA-Z0-9]/', '', $service);
if (file_exists($file)) {
// $this->classloader is the Composer\Autoload\ClassLoader instance
if(empty($this->classloader)) {
// regular route
include_once($file);
} else {
// hack to make goaop work
$this->classloader->addClassMap(array(
$class => $file,
));
}
$this->registry->set('service_' . str_replace('/', '_', $service), new $class($this->registry));
} else {
trigger_error('Error: Could not load service ' . $file . '!');
exit();
}
}
It would throws an exception if the class ServiceProfitTest
dose not has a namespace. And it would be OK if I add a namespace for the ServiceProfitTest
.
It is OK if I do some check in the SelfValueVisitor::enterNode method as below:
public function enterNode(Node $node)
{
if ($node instanceof Stmt\Namespace_) {
$this->namespace = $node->name->toString();
if(!empty($node->name)) {
$this->namespace = $node->name->toString();
}
Hi @lisachenko, is there any update here? I'd really appreciate the suggested fix for the v2.x - I'd be able to provide a PR if it helps?!