Skip to content

Commit

Permalink
Merge branch 'refactor_collector_cor'
Browse files Browse the repository at this point in the history
  • Loading branch information
Trismegiste committed Sep 16, 2014
2 parents cb509e3 + 4d10a85 commit 8afaf6a
Show file tree
Hide file tree
Showing 51 changed files with 2,323 additions and 1,183 deletions.
8 changes: 4 additions & 4 deletions doc/language.dot
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ rankdir=TB;
{ rank=same;
owning3;
TraitImpl [fixedsize="1", width="2", height="2", shape="pentagon", style="filled", color="hotpink"];
traitDoSomething [fixedsize="1", width="2", height="2", shape="rectangle", style="filled", label="doSomething"];
"The trait TraitImpl is owning doSomething() method" [shape=plaintext];
traitDoSomething [fixedsize="1", width="2", height="2", shape="rectangle", style="filled", label="TraitImpl\ndoSomething"];
"The trait TraitImpl is owning TraitImpl::doSomething() method" [shape=plaintext];
TraitImpl -> traitDoSomething [label="owns"];
}

Expand Down Expand Up @@ -110,9 +110,9 @@ rankdir=TB;

{ rank=same;
depend4;
getSize [fixedsize="1", width="2", height="2", shape="rectangle", style="filled", label="getSize"];
getSize [fixedsize="1", width="2", height="2", shape="rectangle", style="filled", label="Image\ngetSize"];
Image [fixedsize="1", width="2", height="2", shape="pentagon", style="filled", color="hotpink"];
"The implementation getSize() \ndepends on Image trait" [shape=plaintext];
"The implementation Image::getSize() \ndepends on Image trait" [shape=plaintext];
getSize -> Image [label="depends"];
}

Expand Down
Binary file modified doc/language.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion phpunit.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="tests/bootstrap.php"
colors="true">
colors="false">

<testsuites>
<testsuite name="Mondrian unit and func tests">
Expand Down
10 changes: 5 additions & 5 deletions src/Analysis/HiddenCoupling.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
use Trismegiste\Mondrian\Transform\Vertex\MethodVertex;
use Trismegiste\Mondrian\Transform\Vertex\ClassVertex;
use Trismegiste\Mondrian\Transform\Vertex\InterfaceVertex;
use Trismegiste\Mondrian\Graph\Edge;
use Trismegiste\Mondrian\Transform\Vertex\TraitVertex;

/**
* HiddenCoupling is an analyser which checks and finds hidden coupling
Expand Down Expand Up @@ -62,8 +62,8 @@ public function createReducedGraph()
$reducedGraph = new \Trismegiste\Mondrian\Graph\Digraph();
$dependency = $this->getEdgeSet();
foreach ($dependency as $edge) {
if (($edge->getSource() instanceof ImplVertex)
&& ($edge->getTarget() instanceof MethodVertex)) {
if (($edge->getSource() instanceof ImplVertex) &&
($edge->getTarget() instanceof MethodVertex)) {

$this->resetVisited();
$edge->visited = true;
Expand All @@ -88,8 +88,8 @@ protected function findOwningClassVertex(ImplVertex $impl)
{
list($className, $methodName) = explode('::', $impl->getName());
foreach ($this->graph->getSuccessor($impl) as $succ) {
if (($succ instanceof ClassVertex)
&& ($succ->getName() == $className)) {
if ((($succ instanceof ClassVertex) || ($succ instanceof TraitVertex)) &&
($succ->getName() == $className)) {

return $succ;
}
Expand Down
7 changes: 4 additions & 3 deletions src/Builder/Compiler/AbstractTraverser.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@

namespace Trismegiste\Mondrian\Builder\Compiler;

use Trismegiste\Mondrian\Visitor;
use PhpParser\NodeVisitor;
use PhpParser\NodeTraverser;

/**
* AbstractTraverser partly builds the compiler with a traverser
*/
abstract class AbstractTraverser implements BuilderInterface
{

public function buildTraverser(Visitor\FqcnHelper $collector)
public function buildTraverser(NodeVisitor $collector)
{
$traverser = new \PHPParser_NodeTraverser();
$traverser = new NodeTraverser();
$traverser->addVisitor($collector);

return $traverser;
Expand Down
4 changes: 2 additions & 2 deletions src/Builder/Compiler/BuilderInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Trismegiste\Mondrian\Builder\Compiler;

use Trismegiste\Mondrian\Visitor\FqcnHelper;
use PhpParser\NodeVisitor;

/**
* BuilderInterface is a contract to build a compiler
Expand All @@ -14,5 +14,5 @@ public function buildContext();

public function buildCollectors();

public function buildTraverser(FqcnHelper $collector);
public function buildTraverser(NodeVisitor $collector);
}
6 changes: 3 additions & 3 deletions src/Transform/GraphBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ public function buildContext()
public function buildCollectors()
{
return array(
new Visitor\SymbolMap($this->reflection),
new Visitor\VertexCollector($this->reflection, $this->vertexContext, $this->graphResult),
new Visitor\EdgeCollector($this->reflection, $this->vertexContext, $this->graphResult)
new Visitor\SymbolMap\Collector($this->reflection, $this->vertexContext, $this->graphResult),
new Visitor\Vertex\Collector($this->reflection, $this->vertexContext, $this->graphResult),
new Visitor\Edge\Collector($this->reflection, $this->vertexContext, $this->graphResult)
);
}

Expand Down
17 changes: 17 additions & 0 deletions src/Transform/ReflectionContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
*
* Responsible for maintaining a list of methods, traits, classes and interfaces used
* for building inheritance links in a digraph
*
* @todo this class lacks an interface
*/
class ReflectionContext
{
Expand Down Expand Up @@ -164,6 +166,21 @@ public function initSymbol($name, $symbolType)
}
}

public function initClass($name)
{
$this->initSymbol($name, self::SYMBOL_CLASS);
}

public function initInterface($name)
{
$this->initSymbol($name, self::SYMBOL_INTERFACE);
}

public function initTrait($name)
{
$this->initSymbol($name, self::SYMBOL_TRAIT);
}

/**
* Stacks a parent type for a type
*
Expand Down
86 changes: 86 additions & 0 deletions src/Visitor/Edge/ClassLevel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php

/*
* Mondrian
*/

namespace Trismegiste\Mondrian\Visitor\Edge;

use PhpParser\Node\Stmt;

/**
* ClassLevel is ...
*/
class ClassLevel extends TraitUserHelper
{

public function enter(\PhpParser\Node $node)
{
switch ($node->getType()) {

case 'Stmt_ClassMethod':
if ($node->isPublic()) {
$this->context->pushState('class-method', $node);
$this->enterPublicMethod($node);
}
break;

case 'Stmt_TraitUse':
$fqcn = $this->getCurrentFqcn();
$currentVertex = $this->findVertex('class', $fqcn);
$this->enterTraitUse($node, $currentVertex);
break;
}
}

public function getName()
{
return 'class';
}

protected function enterPublicMethod(Stmt\ClassMethod $node)
{
// NS
$methodName = $node->name;
$currentFqcn = $this->getCurrentFqcn();
$declaringFqcn = $this->getReflectionContext()->getDeclaringClass($currentFqcn, $methodName);
// Vertices
$signatureIndex = $declaringFqcn . '::' . $methodName;
$classVertex = $this->findVertex('class', $currentFqcn);
$signatureVertex = $this->findVertex('method', $signatureIndex);
$implVertex = $this->findVertex('impl', $currentFqcn . '::' . $methodName);

// if current class == declaring class, we add the edge
if ($declaringFqcn == $currentFqcn) {
$this->getGraph()->addEdge($classVertex, $signatureVertex); // C -> M
if (!$node->isAbstract()) {
$this->getGraph()->addEdge($signatureVertex, $implVertex); // M -> S
$this->getGraph()->addEdge($implVertex, $classVertex); // S -> C
}
} else {
if (!$node->isAbstract()) {
$this->getGraph()->addEdge($classVertex, $implVertex); // C -> S
$this->getGraph()->addEdge($implVertex, $classVertex); // S -> C
}
}

// in any case, we link the implementation to the params
foreach ($node->params as $idx => $param) {
// adding edge from signature to param :
$paramVertex = $this->findVertex('param', $signatureIndex . '/' . $idx);
// it is possible to not find the param because the signature
// is external to the source code :
if (!is_null($paramVertex)) {
if (!$node->isAbstract()) {
$this->getGraph()->addEdge($implVertex, $paramVertex); // S -> P
}
if ($currentFqcn === $declaringFqcn) {
$this->getGraph()->addEdge($signatureVertex, $paramVertex); // M -> P
// now the type of the param :
$this->typeHintParam($param, $paramVertex);
}
}
}
}

}
25 changes: 25 additions & 0 deletions src/Visitor/Edge/ClassMethodLevel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

/*
* Mondrian
*/

namespace Trismegiste\Mondrian\Visitor\Edge;

/**
* ClassMethodLevel is a visitor for method in a class
*/
class ClassMethodLevel extends MethodLevelHelper
{

public function getName()
{
return 'class-method';
}

protected function getParentName()
{
return 'class';
}

}
35 changes: 35 additions & 0 deletions src/Visitor/Edge/Collector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

/*
* Mondrian
*/

namespace Trismegiste\Mondrian\Visitor\Edge;

use Trismegiste\Mondrian\Visitor\VisitorGateway;
use Trismegiste\Mondrian\Transform\ReflectionContext;
use Trismegiste\Mondrian\Transform\GraphContext;
use Trismegiste\Mondrian\Graph\Graph;

/**
* Collector is the main visitor for creating edges between already-created vertices
*/
class Collector extends VisitorGateway
{

public function __construct(ReflectionContext $ref, GraphContext $grf, Graph $g)
{
$visitor = [
new \Trismegiste\Mondrian\Visitor\State\PackageLevel(),
new FileLevel(),
new ClassLevel(),
new InterfaceLevel(),
new TraitLevel(),
new ClassMethodLevel(),
new TraitMethodLevel()
];

parent::__construct($visitor, $ref, $grf, $g);
}

}
55 changes: 55 additions & 0 deletions src/Visitor/Edge/FileLevel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

/*
* Mondrian
*/

namespace Trismegiste\Mondrian\Visitor\Edge;

use Trismegiste\Mondrian\Visitor\State\FileLevelTemplate;
use PhpParser\Node\Stmt;

/**
* FileLevel is ...
*/
class FileLevel extends FileLevelTemplate
{

protected function enterClassNode(Stmt\Class_ $node)
{
$fqcn = $this->getNamespacedName($node);
$src = $this->findVertex('class', $fqcn);

// extends
if (!is_null($node->extends)) {
if (null !== $dst = $this->findVertex('class', (string) $this->resolveClassName($node->extends))) {
$this->getGraph()->addEdge($src, $dst);
}
}
// implements
foreach ($node->implements as $interf) {
if (null !== $dst = $this->findVertex('interface', (string) $this->resolveClassName($interf))) {
$this->getGraph()->addEdge($src, $dst);
}
}
}

protected function enterInterfaceNode(Stmt\Interface_ $node)
{
$fqcn = $this->getNamespacedName($node);
$src = $this->findVertex('interface', $fqcn);

// implements
foreach ($node->extends as $interf) {
if (null !== $dst = $this->findVertex('interface', (string) $this->resolveClassName($interf))) {
$this->getGraph()->addEdge($src, $dst);
}
}
}

protected function enterTraitNode(Stmt\Trait_ $node)
{
// no edge to create
}

}
Loading

0 comments on commit 8afaf6a

Please sign in to comment.