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