Completed
Pull Request — master (#264)
by Enrico
11:14
created

ClosureDefinition::compile()   C

Complexity

Conditions 9
Paths 6

Size

Total Lines 46
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 90

Importance

Changes 0
Metric Value
cc 9
eloc 26
nc 6
nop 1
dl 0
loc 46
ccs 0
cts 33
cp 0
crap 90
rs 5.0942
c 0
b 0
f 0
1
<?php
2
/**
3
 * @author Patsura Dmitry https://github.com/ovr <[email protected]>
4
 */
5
6
namespace PHPSA\Definition;
7
8
use PHPSA\CompiledExpression;
9
use PHPSA\Compiler\SymbolTable;
10
use PHPSA\Context;
11
use PhpParser\Node;
12
use PHPSA\Compiler\Parameter;
13
use PHPSA\Compiler\Types;
14
15
/**
16
 * Class FunctionDefinition
17
 * @package PHPSA\Definition
18
 */
19
class ClosureDefinition extends ParentDefinition
20
{
21
    /**
22
     * @todo Use Finder
23
     *
24
     * @var string
25
     */
26
    protected $filepath;
27
28
    /**
29
     * @var Node\Expr\Closure
30
     */
31
    protected $statement;
32
33
    /**
34
     * @var int
35
     */
36
    protected $returnTypes = CompiledExpression::MIXED;
37
38
    /**
39
     * @var array
40
     */
41
    protected $possibleReturnTypes = [];
42
43
    /**
44
     * @var SymbolTable
45
     */
46
    protected $symbolTable;
47
48
    /**
49
     * @param Node\Expr\Closure $statement
50
     */
51
    public function __construct(Node\Expr\Closure $statement)
52
    {
53
        $this->symbolTable = new SymbolTable();
54
        $this->statement = $statement;
55
    }
56
57
    /**
58
     * @param Context $context
59
     */
60
    public function preCompile(Context $context)
61
    {
62
        if ($this->statement->uses) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->statement->uses of type PhpParser\Node\Expr\ClosureUse[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
63
            /**
64
             * Store variables from User to next restore Context
65
             */
66
            foreach ($this->statement->uses as $variable) {
67
                $variable = $context->getSymbol($variable->var);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $variable is correct as $context->getSymbol($variable->var) (which targets PHPSA\Context::getSymbol()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
68
                if ($variable) {
69
                    $variable->incGets();
70
71
                    $this->symbolTable->add(clone $variable);
72
                }
73
            }
74
        }
75
    }
76
77
    /**
78
     * Compile function to check it
79
     *
80
     * @param Context $context
81
     * @return bool
82
     */
83
    public function compile(Context $context)
84
    {
85
        if ($this->compiled) {
86
            return true;
87
        }
88
89
        $context->setFilepath($this->filepath);
90
        $this->compiled = true;
91
92
        $context->clearSymbols();
93
        $context->scopePointer = $this->getPointer();
94
        $context->setScope(null);
95
96
        if (count($this->statement->stmts) == 0) {
97
            return $context->notice(
98
                'not-implemented-function',
99
                sprintf('Closure %s() is not implemented', $this->name),
100
                $this->statement
101
            );
102
        }
103
104
        if (count($this->statement->params) > 0) {
105
            /** @var  Node\Param $parameter */
106
            foreach ($this->statement->params as $parameter) {
107
                $type = CompiledExpression::UNKNOWN;
108
109
                if ($parameter->type) {
110
                    if (is_string($parameter->type)) {
111
                        $type = Types::getType($parameter->type);
112
                    } elseif ($parameter->type instanceof Node\Name) {
113
                        $type = CompiledExpression::OBJECT;
114
                    }
115
                }
116
117
                $context->addVariable(
118
                    new Parameter($parameter->name, null, $type, $parameter->byRef)
119
                );
120
            }
121
        }
122
123
        foreach ($this->statement->stmts as $st) {
124
            \PHPSA\nodeVisitorFactory($st, $context);
125
        }
126
127
        return true;
128
    }
129
130
    /**
131
     * @param CompiledExpression[] $arguments
132
     * @param Context $context
133
     * @return CompiledExpression
134
     */
135
    public function run(array $arguments, Context $context)
0 ignored issues
show
Unused Code introduced by
The parameter $arguments is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $context is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
136
    {
137
        return new CompiledExpression();
138
    }
139
140
    /**
141
     * @return string
142
     */
143
    public function getFilepath()
144
    {
145
        return $this->filepath;
146
    }
147
148
    /**
149
     * @param string $filepath
150
     */
151
    public function setFilepath($filepath)
152
    {
153
        $this->filepath = $filepath;
154
    }
155
156
    /**
157
     * @return string
158
     */
159
    public function getNamespace()
160
    {
161
        return $this->namespace;
162
    }
163
}
164