From: Timo Tijhof Date: Tue, 18 Jun 2019 17:26:06 +0000 (+0100) Subject: AutoLoader: Skip tokenizing of irrelevant lines in ClassCollector X-Git-Tag: 1.34.0-rc.0~1338^2 X-Git-Url: http://git.cyclocoop.org/%7B%24www_url%7Dadmin/compta/pie.php?a=commitdiff_plain;h=8035a00e8cf2bd3db6e8dbe0710cd3816a00c97a;p=lhc%2Fweb%2Fwiklou.git AutoLoader: Skip tokenizing of irrelevant lines in ClassCollector This makes AutoLoaderStructureTest in PHPUnit and the generateLocalAutoload.php maintenance script much faster. On my machine, it made it 35X faster (or time spent reduced by 97%). Bug: T225730 Change-Id: Ife959bd17ce9c2ae952dfbd158ddb3d8475e8cb2 --- diff --git a/includes/utils/ClassCollector.php b/includes/utils/ClassCollector.php index c987354d37..12b8a707bd 100644 --- a/includes/utils/ClassCollector.php +++ b/includes/utils/ClassCollector.php @@ -59,6 +59,31 @@ class ClassCollector { $this->alias = null; $this->tokens = []; + // HACK: The PHP tokenizer is slow (T225730). + // Speed it up by reducing the input to the three kinds of statement we care about: + // - namespace X; + // - [final] [abstract] class X … {} + // - class_alias( … ); + $lines = []; + $matches = null; + preg_match_all( + // phpcs:ignore Generic.Files.LineLength.TooLong + '#^\t*(?:namespace |(final )?(abstract )?(class|interface|trait) |class_alias\()[^;{]+[;{]\s*\}?#m', + $code, + $matches + ); + if ( isset( $matches[0][0] ) ) { + foreach ( $matches[0] as $match ) { + $match = trim( $match ); + if ( substr( $match, -1 ) === '{' ) { + // Keep it balanced + $match .= '}'; + } + $lines[] = $match; + } + } + $code = 'startToken === null ) { $this->tryBeginExpect( $token ); diff --git a/tests/phpunit/includes/utils/ClassCollectorTest.php b/tests/phpunit/includes/utils/ClassCollectorTest.php index 9c7c50f0f6..6f8aa52720 100644 --- a/tests/phpunit/includes/utils/ClassCollectorTest.php +++ b/tests/phpunit/includes/utils/ClassCollectorTest.php @@ -29,10 +29,21 @@ class ClassCollectorTest extends PHPUnit\Framework\TestCase { "namespace Example;\nclass Foo {}\nclass_alias( 'Example\Foo', 'Bar' );", [ 'Example\Foo', 'Bar' ], ], + [ + // Support a multiline 'class' statement + "namespace Example;\nclass Foo extends\n\tFooBase {\n\t" + . "public function x() {}\n}\nclass_alias( 'Example\Foo', 'Bar' );", + [ 'Example\Foo', 'Bar' ], + ], [ "class_alias( Foo::class, 'Bar' );", [ 'Bar' ], ], + [ + // Support nested class_alias() calls + "if ( false ) {\n\tclass_alias( Foo::class, 'Bar' );\n}", + [ 'Bar' ], + ], [ // Namespaced class is not currently supported. Must use namespace declaration // earlier in the file. diff --git a/tests/phpunit/structure/AutoLoaderStructureTest.php b/tests/phpunit/structure/AutoLoaderStructureTest.php index 37babcef14..c20be5720e 100644 --- a/tests/phpunit/structure/AutoLoaderStructureTest.php +++ b/tests/phpunit/structure/AutoLoaderStructureTest.php @@ -198,7 +198,7 @@ class AutoLoaderStructureTest extends MediaWikiTestCase { } public function testAutoloadOrder() { - $path = realpath( __DIR__ . '/../../..' ); + $path = __DIR__ . '/../../..'; $oldAutoload = file_get_contents( $path . '/autoload.php' ); $generator = new AutoloadGenerator( $path, 'local' ); $generator->setPsr4Namespaces( AutoLoader::getAutoloadNamespaces() );