Fix registering of PHP 7 aliases

The previous approach was causing issues, because "instanceof"
does not invoke the autoloader.
This commit is contained in:
Nikita Popov 2015-03-24 20:04:50 +01:00
parent dce19b074b
commit 617bf0aa41
2 changed files with 31 additions and 8 deletions

View File

@ -36,17 +36,23 @@ class Autoloader
*/
static public function autoload($class) {
if (0 === strpos($class, 'PhpParser\\')) {
if (isset(self::$php7CompatAliases[$class])) {
if (!self::$runningOnPhp7) {
// Register aliases only on PHP 5.x, otherwise this call will fatal
class_alias(self::$php7CompatAliases[$class], $class);
}
if (isset(self::$php7AliasesOldToNew[$class])) {
// Old class name was used, register alias to new one (which will
// be autoloaded, if it wasn't yet).
self::registerPhp7Alias(self::$php7AliasesOldToNew[$class], $class);
return;
}
$fileName = dirname(__DIR__) . '/' . strtr($class, '\\', '/') . '.php';
if (file_exists($fileName)) {
require $fileName;
}
if (isset(self::$php7AliasesNewToOld[$class])) {
// New class name was used, register alias for old one, otherwise
// it won't be usable in "instanceof" and other non-autoloading places.
self::registerPhp7Alias($class, self::$php7AliasesNewToOld[$class]);
}
} else if (0 === strpos($class, 'PHPParser_')) {
if (isset(self::$nonNamespacedAliases[$class])) {
// Register all aliases at once to avoid dependency issues
@ -55,13 +61,21 @@ class Autoloader
}
}
private static function registerPhp7Alias($old, $new) {
// Registering these aliases would throw a fatal error on PHP 7,
// we want to avoid that.
if (!self::$runningOnPhp7) {
class_alias($old, $new);
}
}
private static function registerNonNamespacedAliases() {
foreach (self::$nonNamespacedAliases as $old => $new) {
class_alias($new, $old);
}
}
private static $php7CompatAliases = array(
private static $php7AliasesOldToNew = array(
'PhpParser\Node\Expr\Cast\Bool' => 'PhpParser\Node\Expr\Cast\Bool_',
'PhpParser\Node\Expr\Cast\Int' => 'PhpParser\Node\Expr\Cast\Int_',
'PhpParser\Node\Expr\Cast\Object' => 'PhpParser\Node\Expr\Cast\Object_',
@ -69,6 +83,14 @@ class Autoloader
'PhpParser\Node\Scalar\String' => 'PhpParser\Node\Scalar\String_',
);
private static $php7AliasesNewToOld = array(
'PhpParser\Node\Expr\Cast\Bool_' => 'PhpParser\Node\Expr\Cast\Bool',
'PhpParser\Node\Expr\Cast\Int_' => 'PhpParser\Node\Expr\Cast\Int',
'PhpParser\Node\Expr\Cast\Object_' => 'PhpParser\Node\Expr\Cast\Object',
'PhpParser\Node\Expr\Cast\String_' => 'PhpParser\Node\Expr\Cast\String',
'PhpParser\Node\Scalar\String_' => 'PhpParser\Node\Scalar\String',
);
private static $nonNamespacedAliases = array(
'PHPParser_Builder' => 'PhpParser\Builder',
'PHPParser_BuilderAbstract' => 'PhpParser\BuilderAbstract',

View File

@ -23,8 +23,9 @@ class AutoloaderTest extends \PHPUnit_Framework_TestCase {
$this->markTestSkipped('Cannot create aliases to reserved names on PHP 7');
}
$this->assertInstanceof('PhpParser\Node\Expr\Cast\Bool_', new Expr\Cast\Bool(new Expr\Variable('foo')));
$this->assertInstanceof('PhpParser\Node\Expr\Cast\Int_', new Expr\Cast\Int(new Expr\Variable('foo')));
$this->assertTrue(new Expr\Cast\Bool_(new Expr\Variable('foo')) instanceof Expr\Cast\Bool);
$this->assertTrue(new Expr\Cast\Int_(new Expr\Variable('foo')) instanceof Expr\Cast\Int);
$this->assertInstanceof('PhpParser\Node\Expr\Cast\Object_', new Expr\Cast\Object(new Expr\Variable('foo')));
$this->assertInstanceof('PhpParser\Node\Expr\Cast\String_', new Expr\Cast\String(new Expr\Variable('foo')));
$this->assertInstanceof('PhpParser\Node\Scalar\String_', new Scalar\String('foobar'));