jenkins-bot has submitted this change and it was merged. ( 
https://gerrit.wikimedia.org/r/338509 )

Change subject: AutoloadGenerator: Add support for class_alias()
......................................................................


AutoloadGenerator: Add support for class_alias()

Blob, Field, DatabaseBase are now auto-detected.

Change-Id: Ib8fae2ec3fbb3f5e4aca7965f81631c5f0485ea1
---
M includes/libs/rdbms/database/Database.php
M includes/libs/rdbms/encasing/Blob.php
M includes/libs/rdbms/field/Field.php
M includes/utils/AutoloadGenerator.php
A tests/phpunit/includes/utils/ClassCollectorTest.php
M tests/phpunit/structure/AutoLoaderTest.php
6 files changed, 122 insertions(+), 13 deletions(-)

Approvals:
  Aaron Schulz: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/includes/libs/rdbms/database/Database.php 
b/includes/libs/rdbms/database/Database.php
index 9d800a2..1c5c77e 100644
--- a/includes/libs/rdbms/database/Database.php
+++ b/includes/libs/rdbms/database/Database.php
@@ -3467,4 +3467,4 @@
        }
 }
 
-class_alias( 'Database', 'DatabaseBase' );
+class_alias( Database::class, 'DatabaseBase' );
diff --git a/includes/libs/rdbms/encasing/Blob.php 
b/includes/libs/rdbms/encasing/Blob.php
index d394692..db5b7e5 100644
--- a/includes/libs/rdbms/encasing/Blob.php
+++ b/includes/libs/rdbms/encasing/Blob.php
@@ -18,4 +18,4 @@
        }
 }
 
-class_alias( 'Wikimedia\Rdbms\Blob', 'Blob' );
+class_alias( Blob::class, 'Blob' );
diff --git a/includes/libs/rdbms/field/Field.php 
b/includes/libs/rdbms/field/Field.php
index 7a25f03..7918f36 100644
--- a/includes/libs/rdbms/field/Field.php
+++ b/includes/libs/rdbms/field/Field.php
@@ -32,4 +32,4 @@
        function isNullable();
 }
 
-class_alias( 'Wikimedia\Rdbms\Field', 'Field' );
+class_alias( Field::class, 'Field' );
diff --git a/includes/utils/AutoloadGenerator.php 
b/includes/utils/AutoloadGenerator.php
index 0bfd4a27..55e228a 100644
--- a/includes/utils/AutoloadGenerator.php
+++ b/includes/utils/AutoloadGenerator.php
@@ -291,15 +291,6 @@
                foreach ( glob( $this->basepath . '/*.php' ) as $file ) {
                        $this->readFile( $file );
                }
-
-               // Legacy aliases (1.28)
-               $this->forceClassPath( 'DatabaseBase',
-                       $this->basepath . 
'/includes/libs/rdbms/database/Database.php' );
-               // Legacy aliases (1.29)
-               $this->forceClassPath( 'Blob',
-                       $this->basepath . 
'/includes/libs/rdbms/encasing/Blob.php' );
-               $this->forceClassPath( 'Field',
-                       $this->basepath . 
'/includes/libs/rdbms/field/Field.php' );
        }
 }
 
@@ -329,6 +320,11 @@
        protected $tokens;
 
        /**
+        * @var array Class alias with target/name fields
+        */
+       protected $alias;
+
+       /**
         * @var string $code PHP code (including <?php) to detect class names 
from
         * @return array List of FQCN detected within the tokens
         */
@@ -336,6 +332,7 @@
                $this->namespace = '';
                $this->classes = [];
                $this->startToken = null;
+               $this->alias = null;
                $this->tokens = [];
 
                foreach ( token_get_all( $code ) as $token ) {
@@ -358,6 +355,8 @@
                if ( is_string( $token ) ) {
                        return;
                }
+               // Note: When changing class name discovery logic,
+               // AutoLoaderTest.php may also need to be updated.
                switch ( $token[0] ) {
                case T_NAMESPACE:
                case T_CLASS:
@@ -365,6 +364,12 @@
                case T_TRAIT:
                case T_DOUBLE_COLON:
                        $this->startToken = $token;
+                       break;
+               case T_STRING:
+                       if ( $token[1] === 'class_alias' ) {
+                               $this->startToken = $token;
+                               $this->alias = [];
+                       }
                }
        }
 
@@ -388,6 +393,49 @@
                        }
                        break;
 
+               case T_STRING:
+                       if ( $this->alias !== null ) {
+                               // Flow 1 - Two string literals:
+                               // - T_STRING  class_alias
+                               // - '('
+                               // - T_CONSTANT_ENCAPSED_STRING 'TargetClass'
+                               // - ','
+                               // - T_WHITESPACE
+                               // - T_CONSTANT_ENCAPSED_STRING 'AliasName'
+                               // - ')'
+                               // Flow 2 - Use of ::class syntax for first 
parameter
+                               // - T_STRING  class_alias
+                               // - '('
+                               // - T_STRING TargetClass
+                               // - T_DOUBLE_COLON ::
+                               // - T_CLASS class
+                               // - ','
+                               // - T_WHITESPACE
+                               // - T_CONSTANT_ENCAPSED_STRING 'AliasName'
+                               // - ')'
+                               if ( $token === '(' ) {
+                                       // Start of a function call to 
class_alias()
+                                       $this->alias = [ 'target' => false, 
'name' => false ];
+                               } elseif ( $token === ',' ) {
+                                       // Record that we're past the first 
parameter
+                                       if ( $this->alias['target'] === false ) 
{
+                                               $this->alias['target'] = true;
+                                       }
+                               } elseif ( is_array( $token ) && $token[0] === 
T_CONSTANT_ENCAPSED_STRING ) {
+                                       if ( $this->alias['target'] === true ) {
+                                               // We already saw a first 
argument, this must be the second.
+                                               // Strip quotes from the string 
literal.
+                                               $this->alias['name'] = substr( 
$token[1], 1, -1 );
+                                       }
+                               } elseif ( $token === ')' ) {
+                                       // End of function call
+                                       $this->classes[] = $this->alias['name'];
+                                       $this->alias = null;
+                                       $this->startToken = null;
+                               }
+                       }
+                       break;
+
                case T_CLASS:
                case T_INTERFACE:
                case T_TRAIT:
diff --git a/tests/phpunit/includes/utils/ClassCollectorTest.php 
b/tests/phpunit/includes/utils/ClassCollectorTest.php
new file mode 100644
index 0000000..e8a228e
--- /dev/null
+++ b/tests/phpunit/includes/utils/ClassCollectorTest.php
@@ -0,0 +1,48 @@
+<?php
+
+/**
+ * @covers ClassCollector
+ */
+class ClassCollectorTest extends PHPUnit_Framework_TestCase {
+
+       public static function provideCases() {
+               return [
+                       [
+                               "class Foo {}",
+                               [ 'Foo' ],
+                       ],
+                       [
+                               "namespace Example;\nclass Foo {}\nclass Bar 
{}",
+                               [ 'Example\Foo', 'Example\Bar' ],
+                       ],
+                       [
+                               "class_alias( 'Foo', 'Bar' );",
+                               [ 'Bar' ],
+                       ],
+                       [
+                               "namespace Example;\nclass Foo {}\nclass_alias( 
'Example\Foo', 'Foo' );",
+                               [ 'Example\Foo', 'Foo' ],
+                       ],
+                       [
+                               "namespace Example;\nclass Foo {}\nclass_alias( 
'Example\Foo', 'Bar' );",
+                               [ 'Example\Foo', 'Bar' ],
+                       ],
+                       [
+                               "class_alias( Foo::class, 'Bar' );",
+                               [ 'Bar' ],
+                       ],
+                       [
+                               "namespace Example;\nclass Foo {}\nclass_alias( 
Foo::class, 'Bar' );",
+                               [ 'Example\Foo', 'Bar' ],
+                       ],
+               ];
+       }
+
+       /**
+        * @dataProvider provideCases
+        */
+       public function testGetClasses( $code, array $classes, $message = null 
) {
+               $cc = new ClassCollector();
+               $this->assertEquals( $classes, $cc->getClasses( "<?php\n$code" 
), $message );
+       }
+}
diff --git a/tests/phpunit/structure/AutoLoaderTest.php 
b/tests/phpunit/structure/AutoLoaderTest.php
index f36b51a..d81e8c6 100644
--- a/tests/phpunit/structure/AutoLoaderTest.php
+++ b/tests/phpunit/structure/AutoLoaderTest.php
@@ -68,6 +68,7 @@
                        }
 
                        // We could use token_get_all() here, but this is faster
+                       // Note: Keep in sync with ClassCollector
                        $matches = [];
                        preg_match_all( '/
                                ^ [\t ]* (?:
@@ -77,6 +78,11 @@
                                        class_alias \s* \( \s*
                                                ([\'"]) (?P<original> [^\'"]+) 
\g{-2} \s* , \s*
                                                ([\'"]) (?P<alias> [^\'"]+ ) 
\g{-2} \s*
+                                       \) \s* ;
+                               |
+                                       class_alias \s* \( \s*
+                                               (?P<originalStatic> 
[a-zA-Z0-9_]+)::class \s* , \s*
+                                               ([\'"]) (?P<aliasString> 
[^\'"]+ ) \g{-2} \s*
                                        \) \s* ;
                                )
                        /imx', $contents, $matches, PREG_SET_ORDER );
@@ -95,11 +101,18 @@
 
                        foreach ( $matches as $match ) {
                                if ( !empty( $match['class'] ) ) {
+                                       // 'class Foo {}'
                                        $class = $fileNamespace . 
$match['class'];
                                        $actual[$class] = $file;
                                        $classesInFile[$class] = true;
                                } else {
-                                       $aliasesInFile[$match['alias']] = 
$match['original'];
+                                       if ( !empty( $match['original'] ) ) {
+                                               // 'class_alias( "Foo", "Bar" 
);'
+                                               $aliasesInFile[$match['alias']] 
= $match['original'];
+                                       } else {
+                                               // 'class_alias( Foo::class, 
"Bar" );'
+                                               
$aliasesInFile[$match['aliasString']] = $fileNamespace . 
$match['originalStatic'];
+                                       }
                                }
                        }
 

-- 
To view, visit https://gerrit.wikimedia.org/r/338509
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Ib8fae2ec3fbb3f5e4aca7965f81631c5f0485ea1
Gerrit-PatchSet: 11
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Krinkle <krinklem...@gmail.com>
Gerrit-Reviewer: Aaron Schulz <asch...@wikimedia.org>
Gerrit-Reviewer: Anomie <bjor...@wikimedia.org>
Gerrit-Reviewer: Florianschmidtwelzow <florian.schmidt.stargatewis...@gmail.com>
Gerrit-Reviewer: Jforrester <jforres...@wikimedia.org>
Gerrit-Reviewer: Krinkle <krinklem...@gmail.com>
Gerrit-Reviewer: Legoktm <lego...@member.fsf.org>
Gerrit-Reviewer: Reedy <re...@wikimedia.org>
Gerrit-Reviewer: Thiemo Mättig (WMDE) <thiemo.maet...@wikimedia.de>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to