Skip to content

Commit

Permalink
more refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
smoench committed Feb 14, 2020
1 parent 3e2b334 commit ac73896
Show file tree
Hide file tree
Showing 22 changed files with 144 additions and 151 deletions.
1 change: 1 addition & 0 deletions config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
<service id="SensioLabs\Deptrac\AstRunner\AstParser\NikicPhpParser\NikicPhpParser">
<argument type="service" id="SensioLabs\Deptrac\AstRunner\AstParser\NikicPhpParser\FileParser"/>
<argument type="service" id="SensioLabs\Deptrac\AstRunner\AstParser\AstFileReferenceCache"/>
<argument type="service" id="SensioLabs\Deptrac\AstRunner\Resolver\TypeResolver"/>
<argument type="service" id="SensioLabs\Deptrac\AstRunner\Resolver\AnnotationDependencyResolver"/>
<argument type="service" id="SensioLabs\Deptrac\AstRunner\Resolver\AnonymousClassResolver"/>
<argument type="service" id="SensioLabs\Deptrac\AstRunner\Resolver\ClassConstantResolver"/>
Expand Down
5 changes: 2 additions & 3 deletions src/AstRunner/AstParser/AstParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@
namespace SensioLabs\Deptrac\AstRunner\AstParser;

use SensioLabs\Deptrac\AstRunner\AstMap\AstFileReference;
use SplFileInfo;

interface AstParser
{
public function parse($data): AstFileReference;

public function supports($data): bool;
public function parse(SplFileInfo $data): AstFileReference;
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,32 +12,37 @@
use SensioLabs\Deptrac\AstRunner\AstMap\ClassReferenceBuilder;
use SensioLabs\Deptrac\AstRunner\AstMap\FileOccurrence;
use SensioLabs\Deptrac\AstRunner\Resolver\ClassDependencyResolver;
use SensioLabs\Deptrac\AstRunner\Resolver\NameScope;
use SensioLabs\Deptrac\AstRunner\Resolver\TypeResolver;
use SensioLabs\Deptrac\AstRunner\Resolver\TypeScope;

class AstClassReferenceResolver extends NodeVisitorAbstract
class ClassReferenceVisitor extends NodeVisitorAbstract
{
private $fileReference;

/** @var ClassDependencyResolver[] */
private $classDependencyResolvers;

/** @var NameScope */
private $currentTypeContext;
/** @var TypeScope */
private $currentTypeScope;

/** @var ClassReferenceBuilder */
private $currentClassReferenceBuilder;

public function __construct(AstFileReference $fileReference, ClassDependencyResolver ...$classDependencyResolvers)
/** @var TypeResolver */
private $typeResolver;

public function __construct(AstFileReference $fileReference, TypeResolver $typeResolver, ClassDependencyResolver ...$classDependencyResolvers)
{
$this->currentTypeContext = new NameScope('global');
$this->currentTypeScope = new TypeScope('');
$this->fileReference = $fileReference;
$this->classDependencyResolvers = $classDependencyResolvers;
$this->typeResolver = $typeResolver;
}

public function enterNode(Node $node)
{
if ($node instanceof Node\Stmt\Namespace_) {
$this->currentTypeContext = new NameScope($node->name ? $node->name->toCodeString() : 'global');
$this->currentTypeScope = new TypeScope($node->name ? $node->name->toCodeString() : '');
}

if (!$node instanceof Node\Stmt\ClassLike) {
Expand All @@ -47,7 +52,7 @@ public function enterNode(Node $node)
if (isset($node->namespacedName) && $node->namespacedName instanceof Node\Name) {
$className = $node->namespacedName->toCodeString();
} elseif ($node->name instanceof Node\Identifier) {
$className = $node->name->toCodeString();
$className = $node->name->toString();
} else {
return null; // map anonymous classes on current class
}
Expand Down Expand Up @@ -79,7 +84,7 @@ public function enterNode(Node $node)
public function leaveNode(Node $node)
{
if ($node instanceof Node\Stmt\UseUse) {
$this->currentTypeContext->addUse($node->name->toCodeString(), $node->getAlias()->toString());
$this->currentTypeScope->addUse($node->name->toCodeString(), $node->getAlias()->toString());
$this->fileReference->addDependency(
AstDependency::useStmt(
ClassLikeName::fromFQCN($node->name->toCodeString()),
Expand All @@ -93,47 +98,55 @@ public function leaveNode(Node $node)
}

if ($node instanceof Node\Stmt\TraitUse) {
foreach ($node->traits as $trait) {
$this->currentClassReferenceBuilder->trait($trait->toCodeString(), $trait->getLine());
foreach ($this->typeResolver->resolvePHPParserTypes($this->currentTypeScope, ...$node->traits) as $classLikeName) {
$this->currentClassReferenceBuilder->trait($classLikeName, $node->getLine());
}
}

if ($node instanceof Node\Expr\Instanceof_ && $this->isQualifiedType($node->class)) {
$this->currentClassReferenceBuilder->instanceof($node->class->toCodeString(), $node->class->getLine());
if ($node instanceof Node\Expr\Instanceof_ && $node->class instanceof Node\Name) {
foreach ($this->typeResolver->resolvePHPParserTypes($this->currentTypeScope, $node->class) as $classLikeName) {
$this->currentClassReferenceBuilder->instanceof($classLikeName, $node->class->getLine());
}
}

if ($node instanceof Node\Param && $this->isQualifiedType($node->type)) {
$this->currentClassReferenceBuilder->parameter($node->type->toCodeString(), $node->type->getLine());
if ($node instanceof Node\Param && null !== $node->type) {
foreach ($this->typeResolver->resolvePHPParserTypes($this->currentTypeScope, $node->type) as $classLikeName) {
$this->currentClassReferenceBuilder->parameter($classLikeName, $node->type->getLine());
}
}

if ($node instanceof Node\Expr\New_ && $this->isQualifiedType($node->class)) {
$this->currentClassReferenceBuilder->newStatement($node->class->toCodeString(), $node->class->getLine());
if ($node instanceof Node\Expr\New_ && $node->class instanceof Node\Name) {
foreach ($this->typeResolver->resolvePHPParserTypes($this->currentTypeScope, $node->class) as $classLikeName) {
$this->currentClassReferenceBuilder->newStatement($classLikeName, $node->class->getLine());
}
}

if ($node instanceof Node\Expr\StaticPropertyFetch && $this->isQualifiedType($node->class)) {
$this->currentClassReferenceBuilder->staticProperty($node->class->toCodeString(), $node->class->getLine());
if ($node instanceof Node\Expr\StaticPropertyFetch && $node->class instanceof Node\Name) {
foreach ($this->typeResolver->resolvePHPParserTypes($this->currentTypeScope, $node->class) as $classLikeName) {
$this->currentClassReferenceBuilder->staticProperty($classLikeName, $node->class->getLine());
}
}

if ($node instanceof Node\Expr\StaticCall && $this->isQualifiedType($node->class)) {
$this->currentClassReferenceBuilder->staticMethod($node->class->toCodeString(), $node->class->getLine());
if ($node instanceof Node\Expr\StaticCall && $node->class instanceof Node\Name) {
foreach ($this->typeResolver->resolvePHPParserTypes($this->currentTypeScope, $node->class) as $classLikeName) {
$this->currentClassReferenceBuilder->staticMethod($classLikeName, $node->class->getLine());
}
}

if ($node instanceof Node\Stmt\ClassMethod || $node instanceof Node\Expr\Closure) {
if ($this->isQualifiedType($node->returnType)) {
$this->currentClassReferenceBuilder->returnType($node->returnType->toCodeString(), $node->returnType->getLine());
} elseif ($node->returnType instanceof Node\NullableType && $this->isQualifiedType($node->returnType->type)) {
$this->currentClassReferenceBuilder->returnType($node->returnType->type->toCodeString(), $node->returnType->getLine());
if (($node instanceof Node\Stmt\ClassMethod || $node instanceof Node\Expr\Closure) && null !== $node->returnType) {
foreach ($this->typeResolver->resolvePHPParserTypes($this->currentTypeScope, $node->returnType) as $classLikeName) {
$this->currentClassReferenceBuilder->returnType($classLikeName, $node->returnType->getLine());
}
}

if ($node instanceof Node\Stmt\Catch_) {
foreach ($node->types as $type) {
$this->currentClassReferenceBuilder->catchStmt($type->toCodeString(), $type->getLine());
foreach ($this->typeResolver->resolvePHPParserTypes($this->currentTypeScope, ...$node->types) as $classLikeName) {
$this->currentClassReferenceBuilder->catchStmt($classLikeName, $node->getLine());
}
}

foreach ($this->classDependencyResolvers as $resolver) {
$resolver->processNode($node, $this->currentClassReferenceBuilder, $this->currentTypeContext);
$resolver->processNode($node, $this->currentClassReferenceBuilder, $this->currentTypeScope);
}

return null;
Expand All @@ -147,17 +160,4 @@ public function afterTraverse(array $nodes)

return null;
}

private function isQualifiedType($type): bool
{
if (null === $type) {
return false;
}

if ($type instanceof Node\Name) {
return !$type->isSpecialClassName();
}

return false;
}
}
54 changes: 28 additions & 26 deletions src/AstRunner/AstParser/NikicPhpParser/NikicPhpParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use SensioLabs\Deptrac\AstRunner\AstParser\AstFileReferenceCache;
use SensioLabs\Deptrac\AstRunner\AstParser\AstParser;
use SensioLabs\Deptrac\AstRunner\Resolver\ClassDependencyResolver;
use SensioLabs\Deptrac\AstRunner\Resolver\TypeResolver;

class NikicPhpParser implements AstParser
{
Expand All @@ -31,48 +32,50 @@ class NikicPhpParser implements AstParser
*/
private $cache;

/**
* @var TypeResolver
*/
private $typeResolver;

/**
* @var ClassDependencyResolver[]
*/
private $classDependencyResolvers;

/**
* @var NodeTraverser
*/
private $traverser;

public function __construct(
FileParser $fileParser,
AstFileReferenceCache $cache,
TypeResolver $typeResolver,
ClassDependencyResolver ...$classDependencyResolvers
) {
$this->fileParser = $fileParser;
$this->cache = $cache;
$this->typeResolver = $typeResolver;
$this->classDependencyResolvers = $classDependencyResolvers;
}

public function supports($data): bool
{
if (!$data instanceof \SplFileInfo) {
return false;
}

return 'php' === strtolower($data->getExtension());
$this->traverser = new NodeTraverser();
$this->traverser->addVisitor(new NameResolver());
}

public function parse($data): AstFileReference
public function parse(\SplFileInfo $data): AstFileReference
{
/** @var \SplFileInfo $data */
if (!$this->supports($data)) {
throw new \LogicException('data not supported');
}
$filepath = (string) $data->getRealPath();

if (null !== $fileReference = $this->cache->get($data->getRealPath())) {
if (null !== $fileReference = $this->cache->get($filepath)) {
return $fileReference;
}

$fileReference = new AstFileReference($data->getRealPath());

$traverser = new NodeTraverser();
$traverser->addVisitor(new NameResolver());
$traverser->addVisitor(new AstClassReferenceResolver($fileReference, ...$this->classDependencyResolvers));
$fileReference = new AstFileReference($filepath);
$visitor = new ClassReferenceVisitor($fileReference, $this->typeResolver, ...$this->classDependencyResolvers);

$traverser->traverse($this->fileParser->parse($data));
$this->traverser->addVisitor($visitor);
$this->traverser->traverse($this->fileParser->parse($data));
$this->traverser->removeVisitor($visitor);

$this->cache->set($fileReference);

Expand All @@ -91,21 +94,20 @@ public function getAstForClassReference(AstClassReference $classReference): ?Nod
return null;
}

$finding = new FindingVisitor(
$findingVisitor = new FindingVisitor(
static function (Node $node): bool {
return $node instanceof Node\Stmt\ClassLike;
}
);

$traverser = new NodeTraverser();
$traverser->addVisitor(new NameResolver());
$traverser->addVisitor($finding);
$traverser->traverse(
$this->traverser->addVisitor($findingVisitor);
$this->traverser->traverse(
$this->fileParser->parse(new \SplFileInfo($classReference->getFileReference()->getFilepath()))
);
$this->traverser->removeVisitor($findingVisitor);

/** @var Node\Stmt\ClassLike[] $classLikeNodes */
$classLikeNodes = $finding->getFoundNodes();
$classLikeNodes = $findingVisitor->getFoundNodes();

foreach ($classLikeNodes as $classLikeNode) {
if (isset($classLikeNode->namespacedName) && $classLikeNode->namespacedName instanceof Node\Name) {
Expand Down
4 changes: 0 additions & 4 deletions src/AstRunner/AstRunner.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,6 @@ public function createAstMapByFiles(array $files): AstMap
$this->dispatcher->dispatch(new PreCreateAstMapEvent(count($files)));

foreach ($files as $file) {
if (!$this->astParser->supports($file)) {
continue;
}

try {
$references[] = $this->astParser->parse($file);

Expand Down
10 changes: 5 additions & 5 deletions src/AstRunner/Resolver/AnnotationDependencyResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public function __construct(TypeResolver $typeResolver)
$this->typeResolver = $typeResolver;
}

public function processNode(Node $node, ClassReferenceBuilder $classReferenceBuilder, NameScope $nameScope): void
public function processNode(Node $node, ClassReferenceBuilder $classReferenceBuilder, TypeScope $typeScope): void
{
if (!$node instanceof Node\Stmt\Property
&& !$node instanceof Node\Expr\Variable
Expand All @@ -48,31 +48,31 @@ public function processNode(Node $node, ClassReferenceBuilder $classReferenceBui
$docNode = $this->docParser->parse($tokens);

foreach ($docNode->getParamTagValues() as $tag) {
$types = $this->typeResolver->resolveType($tag->type, $nameScope);
$types = $this->typeResolver->resolvePHPStanDocParserType($tag->type, $typeScope);

foreach ($types as $type) {
$classReferenceBuilder->parameter($type, $docComment->getLine());
}
}

foreach ($docNode->getVarTagValues() as $tag) {
$types = $this->typeResolver->resolveType($tag->type, $nameScope);
$types = $this->typeResolver->resolvePHPStanDocParserType($tag->type, $typeScope);

foreach ($types as $type) {
$classReferenceBuilder->variable($type, $docComment->getLine());
}
}

foreach ($docNode->getReturnTagValues() as $tag) {
$types = $this->typeResolver->resolveType($tag->type, $nameScope);
$types = $this->typeResolver->resolvePHPStanDocParserType($tag->type, $typeScope);

foreach ($types as $type) {
$classReferenceBuilder->returnType($type, $docComment->getLine());
}
}

foreach ($docNode->getThrowsTagValues() as $tag) {
$types = $this->typeResolver->resolveType($tag->type, $nameScope);
$types = $this->typeResolver->resolvePHPStanDocParserType($tag->type, $typeScope);

foreach ($types as $type) {
$classReferenceBuilder->throwStatement($type, $docComment->getLine());
Expand Down
2 changes: 1 addition & 1 deletion src/AstRunner/Resolver/AnonymousClassResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

class AnonymousClassResolver implements ClassDependencyResolver
{
public function processNode(Node $node, ClassReferenceBuilder $classReferenceBuilder, NameScope $nameScope): void
public function processNode(Node $node, ClassReferenceBuilder $classReferenceBuilder, TypeScope $typeScope): void
{
if (!$node instanceof Node\Stmt\Class_ || null !== $node->name) {
return;
Expand Down
2 changes: 1 addition & 1 deletion src/AstRunner/Resolver/ClassConstantResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

class ClassConstantResolver implements ClassDependencyResolver
{
public function processNode(Node $node, ClassReferenceBuilder $classReferenceBuilder, NameScope $nameScope): void
public function processNode(Node $node, ClassReferenceBuilder $classReferenceBuilder, TypeScope $typeScope): void
{
if (!$node instanceof ClassConstFetch || !$node->class instanceof Node\Name || $node->class->isSpecialClassName()) {
return;
Expand Down
2 changes: 1 addition & 1 deletion src/AstRunner/Resolver/ClassDependencyResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@

interface ClassDependencyResolver
{
public function processNode(Node $node, ClassReferenceBuilder $classReferenceBuilder, NameScope $nameScope): void;
public function processNode(Node $node, ClassReferenceBuilder $classReferenceBuilder, TypeScope $typeScope): void;
}
Loading

0 comments on commit ac73896

Please sign in to comment.