mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Initial PHP Parser implementation
This commit is contained in:
parent
f225b83e2b
commit
f8e3443c89
@ -27,6 +27,7 @@
|
||||
"symfony/config": "^2.8",
|
||||
"symfony/translation": "^2.8",
|
||||
"vlucas/phpdotenv": "^2.4",
|
||||
"nikic/php-parser": "^2.1",
|
||||
"silverstripe/config": "^1@dev"
|
||||
},
|
||||
"require-dev": {
|
||||
|
@ -3,6 +3,9 @@
|
||||
namespace SilverStripe\Core\Manifest;
|
||||
|
||||
use Exception;
|
||||
use PhpParser\NodeTraverser;
|
||||
use PhpParser\NodeVisitorAbstract;
|
||||
use PhpParser\ParserFactory;
|
||||
use SilverStripe\Control\Director;
|
||||
|
||||
/**
|
||||
@ -163,6 +166,10 @@ class ClassManifest
|
||||
));
|
||||
}
|
||||
|
||||
protected $parser;
|
||||
protected $traverser;
|
||||
protected $visitor;
|
||||
|
||||
/**
|
||||
* Constructs and initialises a new class manifest, either loading the data
|
||||
* from the cache or re-scanning for classes.
|
||||
@ -182,6 +189,11 @@ class ClassManifest
|
||||
$this->cache = new $cacheClass('classmanifest'.($includeTests ? '_tests' : ''));
|
||||
$this->cacheKey = 'manifest';
|
||||
|
||||
$this->parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP5, new PhpParser\Lexer);
|
||||
$this->traverser = new NodeTraverser;
|
||||
$this->traverser->addVisitor(new PhpParser\NodeVisitor\NameResolver);
|
||||
$this->traverser->addVisitor($this->visitor = new SilverStripeNodeVisitor);
|
||||
|
||||
if (!$forceRegen && $data = $this->cache->load($this->cacheKey)) {
|
||||
$this->classes = $data['classes'];
|
||||
$this->descendants = $data['descendants'];
|
||||
@ -593,22 +605,17 @@ class ClassManifest
|
||||
}
|
||||
|
||||
if (!$valid) {
|
||||
$tokens = token_get_all(file_get_contents($pathname));
|
||||
$this->visitor->reset();
|
||||
$stmts = $this->parser->parse(file_get_contents($pathname));
|
||||
$this->traverser->traverse($stmts);
|
||||
|
||||
$classes = self::get_namespaced_class_parser()->findAll($tokens);
|
||||
$traits = self::get_trait_parser()->findAll($tokens);
|
||||
$classes = $this->visitor->getClasses();
|
||||
$traits = $this->visitor->getTraits();
|
||||
$namespace = $this->visitor->getNamespace();
|
||||
|
||||
$namespace = self::get_namespace_parser()->findAll($tokens);
|
||||
$imports = [];//$this->getImportsFromTokens($tokens);
|
||||
|
||||
if ($namespace) {
|
||||
$namespace = implode('', $namespace[0]['namespaceName']);
|
||||
} else {
|
||||
$namespace = '';
|
||||
}
|
||||
|
||||
$imports = $this->getImportsFromTokens($tokens);
|
||||
|
||||
$interfaces = self::get_interface_parser()->findAll($tokens);
|
||||
$interfaces = $this->visitor->getInterfaces();
|
||||
|
||||
$cache = array(
|
||||
'classes' => $classes,
|
||||
@ -722,3 +729,78 @@ class ClassManifest
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SilverStripeNodeVisitor extends NodeVisitorAbstract
|
||||
{
|
||||
|
||||
private $classes = [];
|
||||
|
||||
private $traits = [];
|
||||
|
||||
private $namespace = '';
|
||||
|
||||
private $interfaces = [];
|
||||
|
||||
public function reset()
|
||||
{
|
||||
$this->classes = [];
|
||||
$this->traits = [];
|
||||
$this->namespace = '';
|
||||
$this->interfaces = [];
|
||||
}
|
||||
|
||||
public function enterNode(PhpParser\Node $node)
|
||||
{
|
||||
if ($node instanceof PhpParser\Node\Stmt\Class_) {
|
||||
$extends = [];
|
||||
$implements = [];
|
||||
|
||||
if ($node->extends) {
|
||||
$extends[] = (string)$node->extends;
|
||||
}
|
||||
|
||||
if ($node->implements) {
|
||||
foreach ($node->implements as $implement) {
|
||||
$implements[] = (string)$implement;
|
||||
}
|
||||
}
|
||||
|
||||
$this->classes[] = [
|
||||
'className' => $node->name,
|
||||
'extends' => $extends,
|
||||
'implements' => $implements
|
||||
];
|
||||
} else if ($node instanceof PhpParser\Node\Stmt\Trait_) {
|
||||
$this->traits[] = ['traitName' => (string)$node->name];
|
||||
} else if ($node instanceof PhpParser\Node\Stmt\Namespace_) {
|
||||
$this->namespace = (string)$node->name;
|
||||
} else if ($node instanceof PhpParser\Node\Stmt\Interface_) {
|
||||
$this->interfaces[] = ['interfaceName' => (string)$node->name];
|
||||
}
|
||||
|
||||
if (!$node instanceof PhpParser\Node\Stmt\Namespace_) {
|
||||
return NodeTraverser::DONT_TRAVERSE_CHILDREN;
|
||||
}
|
||||
}
|
||||
|
||||
public function getClasses()
|
||||
{
|
||||
return $this->classes;
|
||||
}
|
||||
|
||||
public function getTraits()
|
||||
{
|
||||
return $this->traits;
|
||||
}
|
||||
|
||||
public function getNamespace()
|
||||
{
|
||||
return $this->namespace;
|
||||
}
|
||||
|
||||
public function getInterfaces()
|
||||
{
|
||||
return $this->interfaces;
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user