Chris@13: setPass(new ValidClassNamePass()); Chris@13: } Chris@13: Chris@13: /** Chris@13: * @dataProvider getInvalid Chris@13: * @expectedException \Psy\Exception\FatalErrorException Chris@13: */ Chris@13: public function testProcessInvalid($code) Chris@13: { Chris@13: $this->parseAndTraverse($code); Chris@13: } Chris@13: Chris@13: public function getInvalid() Chris@13: { Chris@13: // class declarations Chris@13: return [ Chris@13: // core class Chris@13: ['class stdClass {}'], Chris@13: // capitalization Chris@13: ['class stdClass {}'], Chris@13: Chris@13: // collisions with interfaces and traits Chris@13: ['interface stdClass {}'], Chris@13: ['trait stdClass {}'], Chris@13: Chris@13: // collisions inside the same code snippet Chris@13: [' Chris@13: class Psy_Test_CodeCleaner_ValidClassNamePass_Alpha {} Chris@13: class Psy_Test_CodeCleaner_ValidClassNamePass_Alpha {} Chris@13: '], Chris@13: [' Chris@13: class Psy_Test_CodeCleaner_ValidClassNamePass_Alpha {} Chris@13: trait Psy_Test_CodeCleaner_ValidClassNamePass_Alpha {} Chris@13: '], Chris@13: [' Chris@13: trait Psy_Test_CodeCleaner_ValidClassNamePass_Alpha {} Chris@13: class Psy_Test_CodeCleaner_ValidClassNamePass_Alpha {} Chris@13: '], Chris@13: [' Chris@13: trait Psy_Test_CodeCleaner_ValidClassNamePass_Alpha {} Chris@13: interface Psy_Test_CodeCleaner_ValidClassNamePass_Alpha {} Chris@13: '], Chris@13: [' Chris@13: interface Psy_Test_CodeCleaner_ValidClassNamePass_Alpha {} Chris@13: trait Psy_Test_CodeCleaner_ValidClassNamePass_Alpha {} Chris@13: '], Chris@13: [' Chris@13: interface Psy_Test_CodeCleaner_ValidClassNamePass_Alpha {} Chris@13: class Psy_Test_CodeCleaner_ValidClassNamePass_Alpha {} Chris@13: '], Chris@13: [' Chris@13: class Psy_Test_CodeCleaner_ValidClassNamePass_Alpha {} Chris@13: interface Psy_Test_CodeCleaner_ValidClassNamePass_Alpha {} Chris@13: '], Chris@13: Chris@13: // namespaced collisions Chris@13: [' Chris@13: namespace Psy\\Test\\CodeCleaner { Chris@13: class ValidClassNamePassTest {} Chris@13: } Chris@13: '], Chris@13: [' Chris@13: namespace Psy\\Test\\CodeCleaner\\ValidClassNamePass { Chris@13: class Beta {} Chris@13: } Chris@13: namespace Psy\\Test\\CodeCleaner\\ValidClassNamePass { Chris@13: class Beta {} Chris@13: } Chris@13: '], Chris@13: Chris@13: // extends and implements Chris@13: ['class ValidClassNamePassTest extends NotAClass {}'], Chris@13: ['class ValidClassNamePassTest extends ArrayAccess {}'], Chris@13: ['class ValidClassNamePassTest implements stdClass {}'], Chris@13: ['class ValidClassNamePassTest implements ArrayAccess, stdClass {}'], Chris@13: ['interface ValidClassNamePassTest extends stdClass {}'], Chris@13: ['interface ValidClassNamePassTest extends ArrayAccess, stdClass {}'], Chris@13: Chris@13: // class instantiations Chris@13: ['new Psy_Test_CodeCleaner_ValidClassNamePass_Gamma();'], Chris@13: [' Chris@13: namespace Psy\\Test\\CodeCleaner\\ValidClassNamePass { Chris@13: new Psy_Test_CodeCleaner_ValidClassNamePass_Delta(); Chris@13: } Chris@13: '], Chris@13: Chris@13: // class constant fetch Chris@13: ['Psy\\Test\\CodeCleaner\\ValidClassNamePass\\NotAClass::FOO'], Chris@13: Chris@13: // static call Chris@13: ['Psy\\Test\\CodeCleaner\\ValidClassNamePass\\NotAClass::foo()'], Chris@13: ['Psy\\Test\\CodeCleaner\\ValidClassNamePass\\NotAClass::$foo()'], Chris@16: ['Psy\\Test\\CodeCleaner\\ValidClassNamePassTest::notAMethod()'], Chris@13: ]; Chris@13: } Chris@13: Chris@13: /** Chris@13: * @dataProvider getValid Chris@13: */ Chris@13: public function testProcessValid($code) Chris@13: { Chris@13: $this->parseAndTraverse($code); Chris@13: $this->assertTrue(true); Chris@13: } Chris@13: Chris@13: public function getValid() Chris@13: { Chris@13: $valid = [ Chris@13: // class declarations Chris@13: ['class Psy_Test_CodeCleaner_ValidClassNamePass_Epsilon {}'], Chris@13: ['namespace Psy\Test\CodeCleaner\ValidClassNamePass; class Zeta {}'], Chris@13: [' Chris@13: namespace { class Psy_Test_CodeCleaner_ValidClassNamePass_Eta {}; } Chris@13: namespace Psy\\Test\\CodeCleaner\\ValidClassNamePass { Chris@13: class Psy_Test_CodeCleaner_ValidClassNamePass_Eta {} Chris@13: } Chris@13: '], Chris@13: ['namespace Psy\Test\CodeCleaner\ValidClassNamePass { class stdClass {} }'], Chris@13: Chris@13: // class instantiations Chris@13: ['new stdClass();'], Chris@13: ['new stdClass();'], Chris@13: [' Chris@13: namespace Psy\\Test\\CodeCleaner\\ValidClassNamePass { Chris@13: class Theta {} Chris@13: } Chris@13: namespace Psy\\Test\\CodeCleaner\\ValidClassNamePass { Chris@13: new Theta(); Chris@13: } Chris@13: '], Chris@13: [' Chris@13: namespace Psy\\Test\\CodeCleaner\\ValidClassNamePass { Chris@13: class Iota {} Chris@13: new Iota(); Chris@13: } Chris@13: '], Chris@13: [' Chris@13: namespace Psy\\Test\\CodeCleaner\\ValidClassNamePass { Chris@13: class Kappa {} Chris@13: } Chris@13: namespace { Chris@13: new \\Psy\\Test\\CodeCleaner\\ValidClassNamePass\\Kappa(); Chris@13: } Chris@13: '], Chris@13: Chris@13: // Class constant fetch (ValidConstantPassTest validates the actual constant) Chris@13: ['class A {} A::FOO'], Chris@13: ['$a = new DateTime; $a::ATOM'], Chris@13: ['interface A { const B = 1; } A::B'], Chris@13: Chris@13: // static call Chris@13: ['DateTime::createFromFormat()'], Chris@13: ['DateTime::$someMethod()'], Chris@13: ['Psy\Test\CodeCleaner\Fixtures\ClassWithStatic::doStuff()'], Chris@13: ['Psy\Test\CodeCleaner\Fixtures\ClassWithCallStatic::doStuff()'], Chris@17: ['Psy\Test\CodeCleaner\Fixtures\TraitWithStatic::doStuff()'], Chris@13: Chris@13: // Allow `self` and `static` as class names. Chris@13: [' Chris@13: class Psy_Test_CodeCleaner_ValidClassNamePass_ClassWithStatic { Chris@13: public static function getInstance() { Chris@13: return new self(); Chris@13: } Chris@13: } Chris@13: '], Chris@13: [' Chris@13: class Psy_Test_CodeCleaner_ValidClassNamePass_ClassWithStatic { Chris@13: public static function getInstance() { Chris@13: return new SELF(); Chris@13: } Chris@13: } Chris@13: '], Chris@13: [' Chris@13: class Psy_Test_CodeCleaner_ValidClassNamePass_ClassWithStatic { Chris@13: public static function getInstance() { Chris@13: return new self; Chris@13: } Chris@13: } Chris@13: '], Chris@13: [' Chris@13: class Psy_Test_CodeCleaner_ValidClassNamePass_ClassWithStatic { Chris@13: public static function getInstance() { Chris@13: return new static(); Chris@13: } Chris@13: } Chris@13: '], Chris@13: [' Chris@13: class Psy_Test_CodeCleaner_ValidClassNamePass_ClassWithStatic { Chris@13: public static function getInstance() { Chris@13: return new Static(); Chris@13: } Chris@13: } Chris@13: '], Chris@13: [' Chris@13: class Psy_Test_CodeCleaner_ValidClassNamePass_ClassWithStatic { Chris@13: public static function getInstance() { Chris@13: return new static; Chris@13: } Chris@13: } Chris@13: '], Chris@13: [' Chris@13: class Psy_Test_CodeCleaner_ValidClassNamePass_ClassWithStatic { Chris@13: public static function foo() { Chris@13: return parent::bar(); Chris@13: } Chris@13: } Chris@13: '], Chris@13: [' Chris@13: class Psy_Test_CodeCleaner_ValidClassNamePass_ClassWithStatic { Chris@13: public static function foo() { Chris@13: return self::bar(); Chris@13: } Chris@13: } Chris@13: '], Chris@13: [' Chris@13: class Psy_Test_CodeCleaner_ValidClassNamePass_ClassWithStatic { Chris@13: public static function foo() { Chris@13: return static::bar(); Chris@13: } Chris@13: } Chris@13: '], Chris@13: Chris@13: ['class A { static function b() { return new A; } }'], Chris@13: [' Chris@13: class A { Chris@13: const B = 123; Chris@13: function c() { Chris@13: return A::B; Chris@13: } Chris@13: } Chris@13: '], Chris@13: ['class A {} class B { function c() { return new A; } }'], Chris@13: Chris@13: // recursion Chris@13: ['class A { function a() { A::a(); } }'], Chris@13: Chris@13: // conditionally defined classes Chris@13: [' Chris@13: class A {} Chris@13: if (false) { Chris@13: class A {} Chris@13: } Chris@13: '], Chris@13: [' Chris@13: class A {} Chris@13: if (true) { Chris@13: class A {} Chris@13: } else if (false) { Chris@13: class A {} Chris@13: } else { Chris@13: class A {} Chris@13: } Chris@13: '], Chris@13: // ewww Chris@13: [' Chris@13: class A {} Chris@13: if (true): Chris@13: class A {} Chris@13: elseif (false): Chris@13: class A {} Chris@13: else: Chris@13: class A {} Chris@13: endif; Chris@13: '], Chris@13: [' Chris@13: class A {} Chris@13: while (false) { class A {} } Chris@13: '], Chris@13: [' Chris@13: class A {} Chris@13: do { class A {} } while (false); Chris@13: '], Chris@13: [' Chris@13: class A {} Chris@13: switch (1) { Chris@13: case 0: Chris@13: class A {} Chris@13: break; Chris@13: case 1: Chris@13: class A {} Chris@13: break; Chris@13: case 2: Chris@13: class A {} Chris@13: break; Chris@13: } Chris@13: '], Chris@13: ]; Chris@13: Chris@13: // Ugh. There's gotta be a better way to test for this. Chris@17: if (\class_exists('PhpParser\ParserFactory')) { Chris@13: // PHP 7.0 anonymous classes, only supported by PHP Parser v2.x Chris@13: $valid[] = ['$obj = new class() {}']; Chris@13: } Chris@13: Chris@17: if (\version_compare(PHP_VERSION, '5.5', '>=')) { Chris@13: $valid[] = ['interface A {} A::class']; Chris@13: $valid[] = ['interface A {} A::CLASS']; Chris@13: $valid[] = ['class A {} A::class']; Chris@13: $valid[] = ['class A {} A::CLASS']; Chris@13: $valid[] = ['A::class']; Chris@13: $valid[] = ['A::CLASS']; Chris@13: } Chris@13: Chris@13: return $valid; Chris@13: } Chris@13: }