Passed
Push — master ( 4ba5d0...423aca )
by Valentin
02:37
created

ProxyPrinter   A

Complexity

Total Complexity 7

Size/Duplication

Total Lines 113
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 21

Importance

Changes 0
Metric Value
wmc 7
lcom 1
cbo 21
dl 0
loc 113
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 22 1
A make() 0 25 1
A propertyName() 0 4 1
A useStmts() 0 8 2
A propertyType() 0 4 1
A getNodesFromStub() 0 4 1
1
<?php
2
declare(strict_types=1);
3
4
namespace Cycle\ORM\Promise;
5
6
use Cycle\ORM\ORMInterface;
7
use Cycle\ORM\Promise\Declaration\Declaration;
8
use Cycle\ORM\Promise\Declaration\Extractor;
9
use Cycle\ORM\Promise\Declaration\Structure;
10
use PhpParser\Lexer;
11
use PhpParser\Node;
12
use PhpParser\Parser;
13
use PhpParser\PrettyPrinter\Standard;
14
use PhpParser\PrettyPrinterAbstract;
15
16
class ProxyPrinter
17
{
18
    private const PROPERTY = '__resolver';
19
20
    private const DEPENDENCIES = [
21
        'orm'   => ORMInterface::class,
22
        'role'  => 'string',
23
        'scope' => 'array'
24
    ];
25
26
    /** @var ConflictResolver */
27
    private $resolver;
28
29
    /** @var Traverser */
30
    private $traverser;
31
32
    /** @var Extractor */
33
    private $extractor;
34
35
    /** @var Lexer */
36
    private $lexer;
37
38
    /** @var Parser */
39
    private $parser;
40
41
    /** @var PrettyPrinterAbstract */
42
    private $printer;
43
44
    /** @var Stubs */
45
    private $stubs;
46
47
    public function __construct(ConflictResolver $resolver, Traverser $traverser, Extractor $extractor, Stubs $stubs)
48
    {
49
        $this->resolver = $resolver;
50
        $this->traverser = $traverser;
51
        $this->extractor = $extractor;
52
53
        $lexer = new Lexer\Emulative([
54
            'usedAttributes' => [
55
                'comments',
56
                'startLine',
57
                'endLine',
58
                'startTokenPos',
59
                'endTokenPos',
60
            ],
61
        ]);
62
63
        $this->lexer = $lexer;
64
        $this->parser = new Parser\Php7($this->lexer);
65
66
        $this->printer = new Standard();
67
        $this->stubs = $stubs;
68
    }
69
70
    /**
71
     *
72
     * @param Declaration $declaration
73
     *
74
     * @return string
75
     */
76
    public function make(Declaration $declaration): string
77
    {
78
        $structure = $this->extractor->extract($declaration->parent->getFullName());
79
80
        $property = $this->propertyName($structure);
81
82
        $visitors = [
83
            new Visitor\AddUseStmts($this->useStmts($declaration)),
84
            new Visitor\UpdateNamespace($declaration->class->getNamespaceName()),
85
            new Visitor\DeclareClass($declaration->class->getShortName(), $declaration->parent->getShortName()),
86
            new Visitor\AddResolverProperty($property, $this->propertyType(), $declaration->parent->getShortName()),
87
            new Visitor\UpdateConstructor($structure->hasConstructor, $property, $this->propertyType(), self::DEPENDENCIES),
88
            new Visitor\UpdatePromiseMethods($property),
89
            new Visitor\AddProxiedMethods($property, $structure->methods),
90
        ];
91
92
        $nodes = $this->getNodesFromStub();
93
        $output = $this->traverser->traverseClonedNodes($nodes, ...$visitors);
94
95
        return $this->printer->printFormatPreserving(
96
            $output,
97
            $nodes,
0 ignored issues
show
Bug introduced by
It seems like $nodes defined by $this->getNodesFromStub() on line 92 can also be of type null; however, PhpParser\PrettyPrinterA...printFormatPreserving() does only seem to accept array<integer,object<PhpParser\Node>>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
98
            $this->lexer->getTokens()
99
        );
100
    }
101
102
    private function propertyName(Structure $declaration): string
103
    {
104
        return $this->resolver->resolve($declaration->properties, self::PROPERTY);
105
    }
106
107
    private function useStmts(Declaration $schema): array
108
    {
109
        if ($schema->class->getNamespaceName() !== $schema->parent->getNamespaceName()) {
110
            return [$schema->parent->getFullName()];
111
        }
112
113
        return [];
114
    }
115
116
    private function propertyType(): string
117
    {
118
        return Utils::shortName(PromiseResolver::class);
119
    }
120
121
    /**
122
     * @return Node\Stmt[]|null
123
     */
124
    private function getNodesFromStub(): ?array
125
    {
126
        return $this->parser->parse($this->stubs->getContent());
127
    }
128
}