comparison vendor/psy/psysh/test/Psy/Test/CodeCleaner/ValidClassNamePassTest.php @ 0:4c8ae668cc8c

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