Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 /*
|
Chris@0
|
4 * This file is part of Psy Shell.
|
Chris@0
|
5 *
|
Chris@0
|
6 * (c) 2012-2017 Justin Hileman
|
Chris@0
|
7 *
|
Chris@0
|
8 * For the full copyright and license information, please view the LICENSE
|
Chris@0
|
9 * file that was distributed with this source code.
|
Chris@0
|
10 */
|
Chris@0
|
11
|
Chris@0
|
12 namespace Psy\Test\CodeCleaner;
|
Chris@0
|
13
|
Chris@0
|
14 use Psy\CodeCleaner\ValidClassNamePass;
|
Chris@0
|
15 use Psy\Exception\Exception;
|
Chris@0
|
16
|
Chris@0
|
17 class ValidClassNamePassTest extends CodeCleanerTestCase
|
Chris@0
|
18 {
|
Chris@0
|
19 public function setUp()
|
Chris@0
|
20 {
|
Chris@0
|
21 $this->setPass(new ValidClassNamePass());
|
Chris@0
|
22 }
|
Chris@0
|
23
|
Chris@0
|
24 /**
|
Chris@0
|
25 * @dataProvider getInvalid
|
Chris@0
|
26 */
|
Chris@0
|
27 public function testProcessInvalid($code, $php54 = false)
|
Chris@0
|
28 {
|
Chris@0
|
29 try {
|
Chris@0
|
30 $stmts = $this->parse($code);
|
Chris@0
|
31 $this->traverse($stmts);
|
Chris@0
|
32 $this->fail();
|
Chris@0
|
33 } catch (Exception $e) {
|
Chris@0
|
34 if ($php54 && version_compare(PHP_VERSION, '5.4', '<')) {
|
Chris@0
|
35 $this->assertInstanceOf('Psy\Exception\ParseErrorException', $e);
|
Chris@0
|
36 } else {
|
Chris@0
|
37 $this->assertInstanceOf('Psy\Exception\FatalErrorException', $e);
|
Chris@0
|
38 }
|
Chris@0
|
39 }
|
Chris@0
|
40 }
|
Chris@0
|
41
|
Chris@0
|
42 public function getInvalid()
|
Chris@0
|
43 {
|
Chris@0
|
44 // class declarations
|
Chris@0
|
45 return array(
|
Chris@0
|
46 // core class
|
Chris@0
|
47 array('class stdClass {}'),
|
Chris@0
|
48 // capitalization
|
Chris@0
|
49 array('class stdClass {}'),
|
Chris@0
|
50
|
Chris@0
|
51 // collisions with interfaces and traits
|
Chris@0
|
52 array('interface stdClass {}'),
|
Chris@0
|
53 array('trait stdClass {}', true),
|
Chris@0
|
54
|
Chris@0
|
55 // collisions inside the same code snippet
|
Chris@0
|
56 array('
|
Chris@0
|
57 class Psy_Test_CodeCleaner_ValidClassNamePass_Alpha {}
|
Chris@0
|
58 class Psy_Test_CodeCleaner_ValidClassNamePass_Alpha {}
|
Chris@0
|
59 '),
|
Chris@0
|
60 array('
|
Chris@0
|
61 class Psy_Test_CodeCleaner_ValidClassNamePass_Alpha {}
|
Chris@0
|
62 trait Psy_Test_CodeCleaner_ValidClassNamePass_Alpha {}
|
Chris@0
|
63 ', true),
|
Chris@0
|
64 array('
|
Chris@0
|
65 trait Psy_Test_CodeCleaner_ValidClassNamePass_Alpha {}
|
Chris@0
|
66 class Psy_Test_CodeCleaner_ValidClassNamePass_Alpha {}
|
Chris@0
|
67 ', true),
|
Chris@0
|
68 array('
|
Chris@0
|
69 trait Psy_Test_CodeCleaner_ValidClassNamePass_Alpha {}
|
Chris@0
|
70 interface Psy_Test_CodeCleaner_ValidClassNamePass_Alpha {}
|
Chris@0
|
71 ', true),
|
Chris@0
|
72 array('
|
Chris@0
|
73 interface Psy_Test_CodeCleaner_ValidClassNamePass_Alpha {}
|
Chris@0
|
74 trait Psy_Test_CodeCleaner_ValidClassNamePass_Alpha {}
|
Chris@0
|
75 ', true),
|
Chris@0
|
76 array('
|
Chris@0
|
77 interface Psy_Test_CodeCleaner_ValidClassNamePass_Alpha {}
|
Chris@0
|
78 class Psy_Test_CodeCleaner_ValidClassNamePass_Alpha {}
|
Chris@0
|
79 '),
|
Chris@0
|
80 array('
|
Chris@0
|
81 class Psy_Test_CodeCleaner_ValidClassNamePass_Alpha {}
|
Chris@0
|
82 interface Psy_Test_CodeCleaner_ValidClassNamePass_Alpha {}
|
Chris@0
|
83 '),
|
Chris@0
|
84
|
Chris@0
|
85 // namespaced collisions
|
Chris@0
|
86 array('
|
Chris@0
|
87 namespace Psy\\Test\\CodeCleaner {
|
Chris@0
|
88 class ValidClassNamePassTest {}
|
Chris@0
|
89 }
|
Chris@0
|
90 '),
|
Chris@0
|
91 array('
|
Chris@0
|
92 namespace Psy\\Test\\CodeCleaner\\ValidClassNamePass {
|
Chris@0
|
93 class Beta {}
|
Chris@0
|
94 }
|
Chris@0
|
95 namespace Psy\\Test\\CodeCleaner\\ValidClassNamePass {
|
Chris@0
|
96 class Beta {}
|
Chris@0
|
97 }
|
Chris@0
|
98 '),
|
Chris@0
|
99
|
Chris@0
|
100 // extends and implements
|
Chris@0
|
101 array('class ValidClassNamePassTest extends NotAClass {}'),
|
Chris@0
|
102 array('class ValidClassNamePassTest extends ArrayAccess {}'),
|
Chris@0
|
103 array('class ValidClassNamePassTest implements stdClass {}'),
|
Chris@0
|
104 array('class ValidClassNamePassTest implements ArrayAccess, stdClass {}'),
|
Chris@0
|
105 array('interface ValidClassNamePassTest extends stdClass {}'),
|
Chris@0
|
106 array('interface ValidClassNamePassTest extends ArrayAccess, stdClass {}'),
|
Chris@0
|
107
|
Chris@0
|
108 // class instantiations
|
Chris@0
|
109 array('new Psy_Test_CodeCleaner_ValidClassNamePass_Gamma();'),
|
Chris@0
|
110 array('
|
Chris@0
|
111 namespace Psy\\Test\\CodeCleaner\\ValidClassNamePass {
|
Chris@0
|
112 new Psy_Test_CodeCleaner_ValidClassNamePass_Delta();
|
Chris@0
|
113 }
|
Chris@0
|
114 '),
|
Chris@0
|
115
|
Chris@0
|
116 // class constant fetch
|
Chris@0
|
117 array('Psy\\Test\\CodeCleaner\\ValidClassNamePass\\NotAClass::FOO'),
|
Chris@0
|
118
|
Chris@0
|
119 // static call
|
Chris@0
|
120 array('Psy\\Test\\CodeCleaner\\ValidClassNamePass\\NotAClass::foo()'),
|
Chris@0
|
121 array('Psy\\Test\\CodeCleaner\\ValidClassNamePass\\NotAClass::$foo()'),
|
Chris@0
|
122 );
|
Chris@0
|
123 }
|
Chris@0
|
124
|
Chris@0
|
125 /**
|
Chris@0
|
126 * @dataProvider getValid
|
Chris@0
|
127 */
|
Chris@0
|
128 public function testProcessValid($code)
|
Chris@0
|
129 {
|
Chris@0
|
130 $stmts = $this->parse($code);
|
Chris@0
|
131 $this->traverse($stmts);
|
Chris@0
|
132 }
|
Chris@0
|
133
|
Chris@0
|
134 public function getValid()
|
Chris@0
|
135 {
|
Chris@0
|
136 $valid = array(
|
Chris@0
|
137 // class declarations
|
Chris@0
|
138 array('class Psy_Test_CodeCleaner_ValidClassNamePass_Epsilon {}'),
|
Chris@0
|
139 array('namespace Psy\Test\CodeCleaner\ValidClassNamePass; class Zeta {}'),
|
Chris@0
|
140 array('
|
Chris@0
|
141 namespace { class Psy_Test_CodeCleaner_ValidClassNamePass_Eta {}; }
|
Chris@0
|
142 namespace Psy\\Test\\CodeCleaner\\ValidClassNamePass {
|
Chris@0
|
143 class Psy_Test_CodeCleaner_ValidClassNamePass_Eta {}
|
Chris@0
|
144 }
|
Chris@0
|
145 '),
|
Chris@0
|
146 array('namespace Psy\Test\CodeCleaner\ValidClassNamePass { class stdClass {} }'),
|
Chris@0
|
147
|
Chris@0
|
148 // class instantiations
|
Chris@0
|
149 array('new stdClass();'),
|
Chris@0
|
150 array('new stdClass();'),
|
Chris@0
|
151 array('
|
Chris@0
|
152 namespace Psy\\Test\\CodeCleaner\\ValidClassNamePass {
|
Chris@0
|
153 class Theta {}
|
Chris@0
|
154 }
|
Chris@0
|
155 namespace Psy\\Test\\CodeCleaner\\ValidClassNamePass {
|
Chris@0
|
156 new Theta();
|
Chris@0
|
157 }
|
Chris@0
|
158 '),
|
Chris@0
|
159 array('
|
Chris@0
|
160 namespace Psy\\Test\\CodeCleaner\\ValidClassNamePass {
|
Chris@0
|
161 class Iota {}
|
Chris@0
|
162 new Iota();
|
Chris@0
|
163 }
|
Chris@0
|
164 '),
|
Chris@0
|
165 array('
|
Chris@0
|
166 namespace Psy\\Test\\CodeCleaner\\ValidClassNamePass {
|
Chris@0
|
167 class Kappa {}
|
Chris@0
|
168 }
|
Chris@0
|
169 namespace {
|
Chris@0
|
170 new \\Psy\\Test\\CodeCleaner\\ValidClassNamePass\\Kappa();
|
Chris@0
|
171 }
|
Chris@0
|
172 '),
|
Chris@0
|
173
|
Chris@0
|
174 // Class constant fetch (ValidConstantPassTest validates the actual constant)
|
Chris@0
|
175 array('class A {} A::FOO'),
|
Chris@0
|
176 array('$a = new DateTime; $a::ATOM'),
|
Chris@0
|
177 array('interface A { const B = 1; } A::B'),
|
Chris@0
|
178
|
Chris@0
|
179 // static call
|
Chris@0
|
180 array('DateTime::createFromFormat()'),
|
Chris@0
|
181 array('DateTime::$someMethod()'),
|
Chris@0
|
182 array('Psy\Test\CodeCleaner\Fixtures\ClassWithStatic::doStuff()'),
|
Chris@0
|
183 array('Psy\Test\CodeCleaner\Fixtures\ClassWithCallStatic::doStuff()'),
|
Chris@0
|
184
|
Chris@0
|
185 // Allow `self` and `static` as class names.
|
Chris@0
|
186 array('
|
Chris@0
|
187 class Psy_Test_CodeCleaner_ValidClassNamePass_ClassWithStatic {
|
Chris@0
|
188 public static function getInstance() {
|
Chris@0
|
189 return new self();
|
Chris@0
|
190 }
|
Chris@0
|
191 }
|
Chris@0
|
192 '),
|
Chris@0
|
193 array('
|
Chris@0
|
194 class Psy_Test_CodeCleaner_ValidClassNamePass_ClassWithStatic {
|
Chris@0
|
195 public static function getInstance() {
|
Chris@0
|
196 return new SELF();
|
Chris@0
|
197 }
|
Chris@0
|
198 }
|
Chris@0
|
199 '),
|
Chris@0
|
200 array('
|
Chris@0
|
201 class Psy_Test_CodeCleaner_ValidClassNamePass_ClassWithStatic {
|
Chris@0
|
202 public static function getInstance() {
|
Chris@0
|
203 return new self;
|
Chris@0
|
204 }
|
Chris@0
|
205 }
|
Chris@0
|
206 '),
|
Chris@0
|
207 array('
|
Chris@0
|
208 class Psy_Test_CodeCleaner_ValidClassNamePass_ClassWithStatic {
|
Chris@0
|
209 public static function getInstance() {
|
Chris@0
|
210 return new static();
|
Chris@0
|
211 }
|
Chris@0
|
212 }
|
Chris@0
|
213 '),
|
Chris@0
|
214 array('
|
Chris@0
|
215 class Psy_Test_CodeCleaner_ValidClassNamePass_ClassWithStatic {
|
Chris@0
|
216 public static function getInstance() {
|
Chris@0
|
217 return new Static();
|
Chris@0
|
218 }
|
Chris@0
|
219 }
|
Chris@0
|
220 '),
|
Chris@0
|
221 array('
|
Chris@0
|
222 class Psy_Test_CodeCleaner_ValidClassNamePass_ClassWithStatic {
|
Chris@0
|
223 public static function getInstance() {
|
Chris@0
|
224 return new static;
|
Chris@0
|
225 }
|
Chris@0
|
226 }
|
Chris@0
|
227 '),
|
Chris@0
|
228 array('
|
Chris@0
|
229 class Psy_Test_CodeCleaner_ValidClassNamePass_ClassWithStatic {
|
Chris@0
|
230 public static function foo() {
|
Chris@0
|
231 return parent::bar();
|
Chris@0
|
232 }
|
Chris@0
|
233 }
|
Chris@0
|
234 '),
|
Chris@0
|
235 array('
|
Chris@0
|
236 class Psy_Test_CodeCleaner_ValidClassNamePass_ClassWithStatic {
|
Chris@0
|
237 public static function foo() {
|
Chris@0
|
238 return self::bar();
|
Chris@0
|
239 }
|
Chris@0
|
240 }
|
Chris@0
|
241 '),
|
Chris@0
|
242 array('
|
Chris@0
|
243 class Psy_Test_CodeCleaner_ValidClassNamePass_ClassWithStatic {
|
Chris@0
|
244 public static function foo() {
|
Chris@0
|
245 return static::bar();
|
Chris@0
|
246 }
|
Chris@0
|
247 }
|
Chris@0
|
248 '),
|
Chris@0
|
249
|
Chris@0
|
250 array('class A { static function b() { return new A; } }'),
|
Chris@0
|
251 array('
|
Chris@0
|
252 class A {
|
Chris@0
|
253 const B = 123;
|
Chris@0
|
254 function c() {
|
Chris@0
|
255 return A::B;
|
Chris@0
|
256 }
|
Chris@0
|
257 }
|
Chris@0
|
258 '),
|
Chris@0
|
259 array('class A {} class B { function c() { return new A; } }'),
|
Chris@0
|
260
|
Chris@0
|
261 // recursion
|
Chris@0
|
262 array('class A { function a() { A::a(); } }'),
|
Chris@0
|
263
|
Chris@0
|
264 // conditionally defined classes
|
Chris@0
|
265 array('
|
Chris@0
|
266 class A {}
|
Chris@0
|
267 if (false) {
|
Chris@0
|
268 class A {}
|
Chris@0
|
269 }
|
Chris@0
|
270 '),
|
Chris@0
|
271 array('
|
Chris@0
|
272 class A {}
|
Chris@0
|
273 if (true) {
|
Chris@0
|
274 class A {}
|
Chris@0
|
275 } else if (false) {
|
Chris@0
|
276 class A {}
|
Chris@0
|
277 } else {
|
Chris@0
|
278 class A {}
|
Chris@0
|
279 }
|
Chris@0
|
280 '),
|
Chris@0
|
281 // ewww
|
Chris@0
|
282 array('
|
Chris@0
|
283 class A {}
|
Chris@0
|
284 if (true):
|
Chris@0
|
285 class A {}
|
Chris@0
|
286 elseif (false):
|
Chris@0
|
287 class A {}
|
Chris@0
|
288 else:
|
Chris@0
|
289 class A {}
|
Chris@0
|
290 endif;
|
Chris@0
|
291 '),
|
Chris@0
|
292 array('
|
Chris@0
|
293 class A {}
|
Chris@0
|
294 while (false) { class A {} }
|
Chris@0
|
295 '),
|
Chris@0
|
296 array('
|
Chris@0
|
297 class A {}
|
Chris@0
|
298 do { class A {} } while (false);
|
Chris@0
|
299 '),
|
Chris@0
|
300 array('
|
Chris@0
|
301 class A {}
|
Chris@0
|
302 switch (1) {
|
Chris@0
|
303 case 0:
|
Chris@0
|
304 class A {}
|
Chris@0
|
305 break;
|
Chris@0
|
306 case 1:
|
Chris@0
|
307 class A {}
|
Chris@0
|
308 break;
|
Chris@0
|
309 case 2:
|
Chris@0
|
310 class A {}
|
Chris@0
|
311 break;
|
Chris@0
|
312 }
|
Chris@0
|
313 '),
|
Chris@0
|
314 );
|
Chris@0
|
315
|
Chris@0
|
316 // Ugh. There's gotta be a better way to test for this.
|
Chris@0
|
317 if (class_exists('PhpParser\ParserFactory')) {
|
Chris@0
|
318 // PHP 7.0 anonymous classes, only supported by PHP Parser v2.x
|
Chris@0
|
319 $valid[] = array('$obj = new class() {}');
|
Chris@0
|
320 }
|
Chris@0
|
321
|
Chris@0
|
322 if (version_compare(PHP_VERSION, '5.5', '>=')) {
|
Chris@0
|
323 $valid[] = array('interface A {} A::class');
|
Chris@0
|
324 $valid[] = array('interface A {} A::CLASS');
|
Chris@0
|
325 $valid[] = array('class A {} A::class');
|
Chris@0
|
326 $valid[] = array('class A {} A::CLASS');
|
Chris@0
|
327 $valid[] = array('A::class');
|
Chris@0
|
328 $valid[] = array('A::CLASS');
|
Chris@0
|
329 }
|
Chris@0
|
330
|
Chris@0
|
331 return $valid;
|
Chris@0
|
332 }
|
Chris@0
|
333 }
|