bug #19859 [ClassLoader] Fix ClassCollectionLoader inlining with declare(strict_types=1) (nicolas-grekas)
This PR was merged into the 2.7 branch.
Discussion
----------
[ClassLoader] Fix ClassCollectionLoader inlining with declare(strict_types=1)
| Q | A
| ------------- | ---
| Branch? | 2.7
| Bug fix? | yes
| Tests pass? | yes
| Fixed tickets | #19845
| License | MIT
See diff as https://github.com/symfony/symfony/pull/19859/files?w=1
Commits
-------
647b3d2
[ClassLoader] Fix ClassCollectionLoader inlining with declare(strict_types=1)
This commit is contained in:
commit
993b405492
@ -58,7 +58,12 @@ class ClassCollectionLoader
|
||||
|
||||
$classes = array_unique($classes);
|
||||
|
||||
$cache = $cacheDir.'/'.$name.$extension;
|
||||
// cache the core classes
|
||||
if (!is_dir($cacheDir) && !@mkdir($cacheDir, 0777, true) && !is_dir($cacheDir)) {
|
||||
throw new \RuntimeException(sprintf('Class Collection Loader was not able to create directory "%s"', $cacheDir));
|
||||
}
|
||||
$cacheDir = rtrim(realpath($cacheDir), '/'.DIRECTORY_SEPARATOR);
|
||||
$cache = $cacheDir.DIRECTORY_SEPARATOR.$name.$extension;
|
||||
|
||||
// auto-reload
|
||||
$reload = false;
|
||||
@ -99,6 +104,10 @@ class ClassCollectionLoader
|
||||
}
|
||||
}
|
||||
|
||||
$c = '(?:\s*+(?:(?:#|//)[^\n]*+\n|/\*(?:(?<!\*/).)++)?+)*+';
|
||||
$strictTypesRegex = str_replace('.', $c, "'^<\?php\s.declare.\(.strict_types.=.1.\).;'is");
|
||||
|
||||
$cacheDir = explode(DIRECTORY_SEPARATOR, $cacheDir);
|
||||
$files = array();
|
||||
$content = '';
|
||||
foreach (self::getOrderedClasses($classes) as $class) {
|
||||
@ -106,25 +115,40 @@ class ClassCollectionLoader
|
||||
continue;
|
||||
}
|
||||
|
||||
$files[] = $class->getFileName();
|
||||
$files[] = $file = $class->getFileName();
|
||||
$c = file_get_contents($file);
|
||||
|
||||
$c = preg_replace(array('/^\s*<\?php/', '/\?>\s*$/'), '', file_get_contents($class->getFileName()));
|
||||
if (preg_match($strictTypesRegex, $c)) {
|
||||
$file = explode(DIRECTORY_SEPARATOR, $file);
|
||||
|
||||
// fakes namespace declaration for global code
|
||||
if (!$class->inNamespace()) {
|
||||
$c = "\nnamespace\n{\n".$c."\n}\n";
|
||||
for ($i = 0; isset($file[$i], $cacheDir[$i]); ++$i) {
|
||||
if ($file[$i] !== $cacheDir[$i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (1 >= $i) {
|
||||
$file = var_export(implode(DIRECTORY_SEPARATOR, $file), true);
|
||||
} else {
|
||||
$file = array_slice($file, $i);
|
||||
$file = str_repeat('..'.DIRECTORY_SEPARATOR, count($cacheDir) - $i).implode(DIRECTORY_SEPARATOR, $file);
|
||||
$file = '__DIR__.'.var_export(DIRECTORY_SEPARATOR.$file, true);
|
||||
}
|
||||
|
||||
$c = "\nnamespace {require $file;}";
|
||||
} else {
|
||||
$c = preg_replace(array('/^\s*<\?php/', '/\?>\s*$/'), '', $c);
|
||||
|
||||
// fakes namespace declaration for global code
|
||||
if (!$class->inNamespace()) {
|
||||
$c = "\nnamespace\n{\n".$c."\n}\n";
|
||||
}
|
||||
|
||||
$c = self::fixNamespaceDeclarations('<?php '.$c);
|
||||
$c = preg_replace('/^\s*<\?php/', '', $c);
|
||||
}
|
||||
|
||||
$c = self::fixNamespaceDeclarations('<?php '.$c);
|
||||
$c = preg_replace('/^\s*<\?php/', '', $c);
|
||||
|
||||
$content .= $c;
|
||||
}
|
||||
|
||||
// cache the core classes
|
||||
if (!is_dir($cacheDir) && !@mkdir($cacheDir, 0777, true) && !is_dir($cacheDir)) {
|
||||
throw new \RuntimeException(sprintf('Class Collection Loader was not able to create directory "%s"', $cacheDir));
|
||||
}
|
||||
self::writeCacheFile($cache, '<?php '.$content);
|
||||
|
||||
if ($autoReload) {
|
||||
|
@ -223,18 +223,20 @@ class ClassCollectionLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testCommentStripping()
|
||||
{
|
||||
if (is_file($file = sys_get_temp_dir().'/bar.php')) {
|
||||
if (is_file($file = __DIR__.'/bar.php')) {
|
||||
unlink($file);
|
||||
}
|
||||
spl_autoload_register($r = function ($class) {
|
||||
if (0 === strpos($class, 'Namespaced') || 0 === strpos($class, 'Pearlike_')) {
|
||||
require_once __DIR__.'/Fixtures/'.str_replace(array('\\', '_'), '/', $class).'.php';
|
||||
@require_once __DIR__.'/Fixtures/'.str_replace(array('\\', '_'), '/', $class).'.php';
|
||||
}
|
||||
});
|
||||
|
||||
$strictTypes = defined('HHVM_VERSION') ? '' : "\nnamespace {require __DIR__.'/Fixtures/Namespaced/WithStrictTypes.php';}";
|
||||
|
||||
ClassCollectionLoader::load(
|
||||
array('Namespaced\\WithComments', 'Pearlike_WithComments'),
|
||||
sys_get_temp_dir(),
|
||||
array('Namespaced\\WithComments', 'Pearlike_WithComments', $strictTypes ? 'Namespaced\\WithStrictTypes' : 'Namespaced\\WithComments'),
|
||||
__DIR__,
|
||||
'bar',
|
||||
false
|
||||
);
|
||||
@ -274,7 +276,9 @@ public static $loaded = true;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
, str_replace("<?php \n", '', file_get_contents($file)));
|
||||
.$strictTypes,
|
||||
str_replace(array("<?php \n", '\\\\'), array('', '/'), file_get_contents($file))
|
||||
);
|
||||
|
||||
unlink($file);
|
||||
}
|
||||
|
@ -76,6 +76,7 @@ class ClassMapGeneratorTest extends \PHPUnit_Framework_TestCase
|
||||
'Namespaced\\Foo' => realpath(__DIR__).'/Fixtures/Namespaced/Foo.php',
|
||||
'Namespaced\\Baz' => realpath(__DIR__).'/Fixtures/Namespaced/Baz.php',
|
||||
'Namespaced\\WithComments' => realpath(__DIR__).'/Fixtures/Namespaced/WithComments.php',
|
||||
'Namespaced\WithStrictTypes' => realpath(__DIR__).'/Fixtures/Namespaced/WithStrictTypes.php',
|
||||
),
|
||||
),
|
||||
array(__DIR__.'/Fixtures/beta/NamespaceCollision', array(
|
||||
|
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* foo
|
||||
*/
|
||||
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace Namespaced;
|
||||
|
||||
class WithStrictTypes
|
||||
{
|
||||
}
|
Reference in New Issue
Block a user