Issue #2151829 by dawehner, chx: Doctrine annotation parsing takes an unacceptable amount of time/memory on install.

8.0.x
webchick 2013-12-15 14:49:56 -08:00
parent a9f1dfe4b2
commit 5fc0ca8118
8 changed files with 124 additions and 73 deletions

View File

@ -3,6 +3,11 @@
"description": "Drupal is an open source content management platform powering millions of websites and applications.",
"type": "drupal-core",
"license": "GPL-2.0+",
"repositories": [{
"type": "vcs",
"url": "https://github.com/dawehner/common.git"
}
],
"require": {
"sdboyer/gliph": "0.1.*",
"symfony/class-loader": "2.3.*",
@ -15,7 +20,7 @@
"symfony/validator": "2.3.*",
"symfony/yaml": "2.3.*",
"twig/twig": "1.12.*",
"doctrine/common": "dev-master",
"doctrine/common": "dev-bmaster#99b44f52a1b844f9c4c34e618b160664d5c27daf",
"doctrine/annotations": "dev-master#463d926a8dcc49271cb7db5a08364a70ed6e3cd3",
"guzzle/http": "3.7.*",
"kriswallsmith/assetic": "1.1.*@alpha",

46
composer.lock generated
View File

@ -3,7 +3,7 @@
"This file locks the dependencies of your project to a known state",
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
],
"hash": "c0c7604f8c0ed6b60809dfe98015e8b8",
"hash": "06006c1512fb829fcdb498b7e515901d",
"packages": [
{
"name": "doctrine/annotations",
@ -207,18 +207,29 @@
},
{
"name": "doctrine/common",
"version": "dev-master",
"version": "dev-bmaster",
"source": {
"type": "git",
"url": "https://github.com/doctrine/common.git",
"reference": "ba2ad8a7db24adb37a33ff52ee64b02d59ccfee0"
"url": "https://github.com/dawehner/common.git",
"reference": "99b44f52a1b844f9c4c34e618b160664d5c27daf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/common/zipball/ba2ad8a7db24adb37a33ff52ee64b02d59ccfee0",
"reference": "ba2ad8a7db24adb37a33ff52ee64b02d59ccfee0",
"url": "https://api.github.com/repos/dawehner/common/zipball/99b44f52a1b844f9c4c34e618b160664d5c27daf",
"reference": "99b44f52a1b844f9c4c34e618b160664d5c27daf",
"shasum": ""
},
"archive": {
"exclude": [
"!vendor",
"tests",
"*phpunit.xml",
".travis.yml",
"build.xml",
"build.properties",
"composer.phar"
]
},
"require": {
"doctrine/annotations": "1.*",
"doctrine/cache": "1.*",
@ -238,21 +249,13 @@
"Doctrine\\Common\\": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com",
"homepage": "http://www.jwage.com/",
"role": "Creator"
},
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com",
"homepage": "http://www.instaclick.com"
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Roman Borschel",
@ -262,11 +265,13 @@
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com",
"homepage": "http://jmsyst.com",
"role": "Developer of wrapped JMSSerializerBundle"
"email": "schmittjoh@gmail.com"
}
],
"description": "Common Library for Doctrine projects",
@ -278,7 +283,10 @@
"persistence",
"spl"
],
"time": "2013-12-03 21:02:18"
"support": {
"source": "https://github.com/dawehner/common/tree/bmaster"
},
"time": "2013-12-12 18:37:37"
},
{
"name": "doctrine/inflector",

View File

@ -4,4 +4,4 @@
require_once __DIR__ . '/composer' . '/autoload_real.php';
return ComposerAutoloaderInit0fa08cab46efc8ac2870c28f0a4fd5aa::getLoader();
return ComposerAutoloaderInit50432d86c534be2ddddf85d27e021721::getLoader();

View File

@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit0fa08cab46efc8ac2870c28f0a4fd5aa
class ComposerAutoloaderInit50432d86c534be2ddddf85d27e021721
{
private static $loader;
@ -19,9 +19,9 @@ class ComposerAutoloaderInit0fa08cab46efc8ac2870c28f0a4fd5aa
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit0fa08cab46efc8ac2870c28f0a4fd5aa', 'loadClassLoader'), true, true);
spl_autoload_register(array('ComposerAutoloaderInit50432d86c534be2ddddf85d27e021721', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInit0fa08cab46efc8ac2870c28f0a4fd5aa', 'loadClassLoader'));
spl_autoload_unregister(array('ComposerAutoloaderInit50432d86c534be2ddddf85d27e021721', 'loadClassLoader'));
$vendorDir = dirname(__DIR__);
$baseDir = dirname(dirname($vendorDir));

View File

@ -2043,19 +2043,30 @@
},
{
"name": "doctrine/common",
"version": "dev-master",
"version_normalized": "9999999-dev",
"version": "dev-bmaster",
"version_normalized": "dev-bmaster",
"source": {
"type": "git",
"url": "https://github.com/doctrine/common.git",
"reference": "ba2ad8a7db24adb37a33ff52ee64b02d59ccfee0"
"url": "https://github.com/dawehner/common.git",
"reference": "99b44f52a1b844f9c4c34e618b160664d5c27daf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/common/zipball/ba2ad8a7db24adb37a33ff52ee64b02d59ccfee0",
"reference": "ba2ad8a7db24adb37a33ff52ee64b02d59ccfee0",
"url": "https://api.github.com/repos/dawehner/common/zipball/99b44f52a1b844f9c4c34e618b160664d5c27daf",
"reference": "99b44f52a1b844f9c4c34e618b160664d5c27daf",
"shasum": ""
},
"archive": {
"exclude": [
"!vendor",
"tests",
"*phpunit.xml",
".travis.yml",
"build.xml",
"build.properties",
"composer.phar"
]
},
"require": {
"doctrine/annotations": "1.*",
"doctrine/cache": "1.*",
@ -2064,7 +2075,7 @@
"doctrine/lexer": "1.*",
"php": ">=5.3.2"
},
"time": "2013-12-03 21:02:18",
"time": "2013-12-12 18:37:37",
"type": "library",
"extra": {
"branch-alias": {
@ -2077,21 +2088,13 @@
"Doctrine\\Common\\": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com",
"homepage": "http://www.jwage.com/",
"role": "Creator"
},
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com",
"homepage": "http://www.instaclick.com"
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Roman Borschel",
@ -2101,11 +2104,13 @@
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com",
"homepage": "http://jmsyst.com",
"role": "Developer of wrapped JMSSerializerBundle"
"email": "schmittjoh@gmail.com"
}
],
"description": "Common Library for Doctrine projects",
@ -2116,6 +2121,9 @@
"eventmanager",
"persistence",
"spl"
]
],
"support": {
"source": "https://github.com/dawehner/common/tree/bmaster"
}
}
]

View File

@ -131,8 +131,8 @@ class StaticReflectionParser implements ReflectionProviderInterface
$this->parsed = true;
$contents = file_get_contents($fileName);
if ($this->classAnnotationOptimize) {
if (preg_match("/(\A.*)^\s+(abstract|final)?\s+class\s+{$this->shortClassName}\s+{/sm", $contents, $matches)) {
$contents = $matches[1];
if (preg_match("/\A.*^\s*((abstract|final)\s+)?class\s+{$this->shortClassName}\s+/sm", $contents, $matches)) {
$contents = $matches[0];
}
}
$tokenParser = new TokenParser($contents);

View File

@ -2,6 +2,6 @@
namespace Doctrine\Tests\Common\Reflection;
class SameNamespaceParent extends Dummies\NoParent
class DeeperNamespaceParent extends Dummies\NoParent
{
}

View File

@ -9,45 +9,75 @@ use Doctrine\Common\Reflection\Psr0FindFile;
class StaticReflectionParserTest extends DoctrineTestCase
{
/**
* @dataProvider classAnnotationOptimize
* @dataProvider parentClassData
*
* @param bool $classAnnotationOptimize
* @param string $parsedClassName
* @param string $expectedClassName
*
* @return void
*/
public function testParentClass($classAnnotationOptimize)
public function testParentClass($classAnnotationOptimize, $parsedClassName, $expectedClassName)
{
// If classed annotation optimization is enabled the properties tested
// below cannot be found.
if ($classAnnotationOptimize) {
$this->setExpectedException('ReflectionException');
}
$testsRoot = substr(__DIR__, 0, -strlen(__NAMESPACE__) - 1);
$paths = array(
'Doctrine\\Tests' => array($testsRoot),
);
$staticReflectionParser = new StaticReflectionParser($parsedClassName, new Psr0FindFile($paths), $classAnnotationOptimize);
$declaringClassName = $staticReflectionParser->getStaticReflectionParserForDeclaringClass('property', 'test')->getClassName();
$this->assertEquals($expectedClassName, $declaringClassName);
}
/**
* @return array
*/
public function parentClassData()
{
$data = array();
$noParentClassName = 'Doctrine\\Tests\\Common\\Reflection\\NoParent';
$staticReflectionParser = new StaticReflectionParser($noParentClassName, new Psr0FindFile($paths), $classAnnotationOptimize);
$declaringClassName = $staticReflectionParser->getStaticReflectionParserForDeclaringClass('property', 'test')->getClassName();
$this->assertEquals($noParentClassName, $declaringClassName);
$className = 'Doctrine\\Tests\\Common\\Reflection\\FullyClassifiedParent';
$staticReflectionParser = new StaticReflectionParser($className, new Psr0FindFile($paths), $classAnnotationOptimize);
$declaringClassName = $staticReflectionParser->getStaticReflectionParserForDeclaringClass('property', 'test')->getClassName();
$this->assertEquals($noParentClassName, $declaringClassName);
$className = 'Doctrine\\Tests\\Common\\Reflection\\SameNamespaceParent';
$staticReflectionParser = new StaticReflectionParser($className, new Psr0FindFile($paths), $classAnnotationOptimize);
$declaringClassName = $staticReflectionParser->getStaticReflectionParserForDeclaringClass('property', 'test')->getClassName();
$this->assertEquals($noParentClassName, $declaringClassName);
$dummyParentClassName = 'Doctrine\\Tests\\Common\\Reflection\\Dummies\\NoParent';
foreach (array(false, true) as $classAnnotationOptimize) {
$data[] = array(
$classAnnotationOptimize, $noParentClassName, $noParentClassName,
);
$data[] = array(
$classAnnotationOptimize, 'Doctrine\\Tests\\Common\\Reflection\\FullyClassifiedParent', $noParentClassName,
);
$data[] = array(
$classAnnotationOptimize, 'Doctrine\\Tests\\Common\\Reflection\\SameNamespaceParent', $noParentClassName,
);
$data[] = array(
$classAnnotationOptimize, 'Doctrine\\Tests\\Common\\Reflection\\DeeperNamespaceParent', $dummyParentClassName,
);
$data[] = array(
$classAnnotationOptimize, 'Doctrine\\Tests\\Common\\Reflection\\UseParent', $dummyParentClassName,
);
}
return $data;
}
$className = 'Doctrine\\Tests\\Common\\Reflection\\DeeperNamespaceParent';
$staticReflectionParser = new StaticReflectionParser($className, new Psr0FindFile($paths), $classAnnotationOptimize);
$declaringClassName = $staticReflectionParser->getStaticReflectionParserForDeclaringClass('property', 'test')->getClassName();
$this->assertEquals($dummyParentClassName, $declaringClassName);
$className = 'Doctrine\\Tests\\Common\\Reflection\\UseParent';
$staticReflectionParser = new StaticReflectionParser($className, new Psr0FindFile($paths), $classAnnotationOptimize);
$declaringClassName = $staticReflectionParser->getStaticReflectionParserForDeclaringClass('property', 'test')->getClassName();
$this->assertEquals($dummyParentClassName, $declaringClassName);
/**
* @dataProvider classAnnotationOptimize
*/
public function testClassAnnotationOptimizedParsing($classAnnotationOptimize) {
$testsRoot = substr(__DIR__, 0, -strlen(__NAMESPACE__) - 1);
$paths = array(
'Doctrine\\Tests' => array($testsRoot),
);
$staticReflectionParser = new StaticReflectionParser('Doctrine\\Tests\\Common\\Reflection\\ExampleAnnotationClass', new Psr0FindFile($paths), $classAnnotationOptimize);
$expectedDocComment = '/**
* @Annotation(
* key = "value"
* )
*/';
$this->assertEquals($expectedDocComment, $staticReflectionParser->getDocComment('class'));
}
/**