Completed
Pull Request — master (#124)
by Enrico
04:04
created

UnexpectedUseOfThis::pass()   B

Complexity

Conditions 7
Paths 7

Size

Total Lines 18
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 7.0178

Importance

Changes 7
Bugs 0 Features 0
Metric Value
cc 7
eloc 14
nc 7
nop 2
dl 0
loc 18
ccs 13
cts 14
cp 0.9286
crap 7.0178
rs 8.2222
c 7
b 0
f 0
1
<?php
2
/**
3
 * @author Kévin Gomez https://github.com/K-Phoen <[email protected]>
4
 */
5
6
namespace PHPSA\Analyzer\Pass\Statement;
7
8
use PhpParser\Node\Stmt;
9
use PhpParser\Node;
10
use PHPSA\Analyzer\Pass;
11
use PHPSA\Context;
12
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
13
14
class UnexpectedUseOfThis implements Pass\ConfigurablePassInterface, Pass\AnalyzerPassInterface
15
{
16
    /**
17
     * @param Node\Stmt $stmt
18
     * @param Context $context
19
     * @return bool
20
     */
21 23
    public function pass(Node\Stmt $stmt, Context $context)
22
    {
23 23
        if ($stmt instanceof Stmt\ClassMethod) {
24 23
            return $this->inspectClassMethodArguments($stmt, $context);
25 1
        } elseif ($stmt instanceof Stmt\TryCatch) {
26 1
            return $this->inspectTryCatch($stmt, $context);
27 1
        } elseif ($stmt instanceof Stmt\Foreach_) {
28 1
            return $this->inspectForeach($stmt, $context);
29 1
        } elseif ($stmt instanceof Stmt\Static_) {
30 1
            return $this->inspectStaticVar($stmt, $context);
31 1
        } elseif ($stmt instanceof Stmt\Global_) {
32 1
            return $this->inspectGlobalVar($stmt, $context);
33 1
        } elseif ($stmt instanceof Stmt\Unset_) {
34 1
            return $this->inspectUnset($stmt, $context);
35
        }
36
37
        return false;
38
    }
39
40
    /**
41
     * @return TreeBuilder
42
     */
43
    public function getConfiguration()
44
    {
45
        $treeBuilder = new TreeBuilder();
46
        $treeBuilder->root('unexpected_use.this')
47
            ->canBeDisabled()
48
        ;
49
50
        return $treeBuilder;
51
    }
52
53
    /**
54
     * @return array
55
     */
56 1
    public function getRegister()
57
    {
58
        return [
59 1
            Stmt\ClassMethod::class,
60 1
            Stmt\TryCatch::class,
61 1
            Stmt\Foreach_::class,
62 1
            Stmt\Static_::class,
63 1
            Stmt\Global_::class,
64 1
            Stmt\Unset_::class,
65 1
        ];
66
    }
67
68
    /**
69
     * @param Stmt\ClassMethod $methodStmt
70
     * @param Context $context
71
     * @return bool
72
     */
73 23
    private function inspectClassMethodArguments(Stmt\ClassMethod $methodStmt, Context $context)
74
    {
75
        /** @var \PhpParser\Node\Param $param */
76 23
        foreach ($methodStmt->getParams() as $param) {
77 3
            if ($param->name === 'this') {
78 1
                $context->notice(
79 1
                    'unexpected_use.this',
80 1
                    sprintf('Method %s can not have a parameter named "this".', $methodStmt->name),
81
                    $param
82 1
                );
83
84 1
                return true;
85
            }
86 23
        }
87
88 23
        return false;
89
    }
90
91
    /**
92
     * @param Stmt\TryCatch $tryCatchStmt
93
     * @param Context $context
94
     * @return bool
95
     */
96 1
    private function inspectTryCatch(Stmt\TryCatch $tryCatchStmt, Context $context)
97
    {
98 1
        $result = false;
99
100
        /** @var Stmt\Catch_ $catch */
101 1
        foreach ($tryCatchStmt->catches as $catch) {
102 1
            if ($catch->var === 'this') {
103 1
                $result = true;
104 1
                $context->notice(
105 1
                    'unexpected_use.this',
106 1
                    'Catch block can not have a catch variable named "this".',
107
                    $catch
108 1
                );
109 1
            }
110 1
        }
111
112 1
        return $result;
113
    }
114
115
    /**
116
     * @param Stmt\Foreach_ $foreachStmt
117
     * @param Context $context
118
     * @return bool
119
     */
120 1
    private function inspectForeach(Stmt\Foreach_ $foreachStmt, Context $context)
121
    {
122 1
        if ($foreachStmt->valueVar->name === 'this') {
0 ignored issues
show
Bug introduced by
The property name does not seem to exist in PhpParser\Node\Expr.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
123 1
            $context->notice(
124 1
                'unexpected_use.this',
125 1
                'Foreach loop can not use a value variable named "this".',
126 1
                $foreachStmt->valueVar
127 1
            );
128
129 1
            return true;
130
        }
131
132 1
        return false;
133
    }
134
135
    /**
136
     * @param Stmt\Static_ $staticStmt
137
     * @param Context $context
138
     * @return bool
139
     */
140 1
    private function inspectStaticVar(Stmt\Static_ $staticStmt, Context $context)
141
    {
142 1
        $result = false;
143
144
        /** @var Stmt\StaticVar $var */
145 1
        foreach ($staticStmt->vars as $var) {
146 1
            if ($var->name === 'this') {
147 1
                $result = true;
148
149 1
                $context->notice(
150 1
                    'unexpected_use.this',
151 1
                    'Can not declare a static variable named "this".',
152
                    $var
153 1
                );
154 1
            }
155 1
        }
156
157 1
        return $result;
158
    }
159
160
    /**
161
     * @param Stmt\Global_ $globalStmt
162
     * @param Context $context
163
     * @return bool
164
     */
165 1
    private function inspectGlobalVar(Stmt\Global_ $globalStmt, Context $context)
166
    {
167 1
        $result = false;
168
169 1
        foreach ($globalStmt->vars as $var) {
170 1
            if ($var->name === 'this') {
0 ignored issues
show
Bug introduced by
The property name does not seem to exist in PhpParser\Node\Expr.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
171 1
                $result = true;
172
173 1
                $context->notice(
174 1
                    'unexpected_use.this',
175 1
                    'Can not declare a global variable named "this".',
176
                    $var
177 1
                );
178 1
            }
179 1
        }
180
181 1
        return $result;
182
    }
183
184
    /**
185
     * @param Stmt\Unset_ $unsetStmt
186
     * @param Context $context
187
     * @return bool
188
     */
189 1
    private function inspectUnset(Stmt\Unset_ $unsetStmt, Context $context)
190
    {
191 1
        $result = false;
192
193 1
        foreach ($unsetStmt->vars as $var) {
194 1
            if ($var->name === 'this') {
0 ignored issues
show
Bug introduced by
The property name does not seem to exist in PhpParser\Node\Expr.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
195 1
                $result = true;
196
197 1
                $context->notice(
198 1
                    'unexpected_use.this',
199 1
                    'Can not unset $this.',
200
                    $var
201 1
                );
202 1
            }
203 1
        }
204
205 1
        return $result;
206
    }
207
}
208