1
0
Fork 0

Filter out exclude-from-classmap rules to avoid generating very long regexes, fixes #9487

pull/9695/head
Jordi Boggiano 2021-01-27 15:02:19 +01:00
parent bab210777e
commit 92313447d6
No known key found for this signature in database
GPG Key ID: 7BBD42C429EC80BC
3 changed files with 34 additions and 5 deletions

View File

@ -231,7 +231,7 @@ EOF;
$excluded = null;
if (!empty($autoloads['exclude-from-classmap'])) {
$excluded = '{(' . implode('|', $autoloads['exclude-from-classmap']) . ')}';
$excluded = $autoloads['exclude-from-classmap'];
}
$classMap = array();
@ -350,8 +350,31 @@ EOF;
return $classMap;
}
/**
* @param ?array $excluded
*/
private function generateClassMap($dir, $excluded, $namespaceFilter, $autoloadType, $showAmbiguousWarning, array &$scannedFiles)
{
if ($excluded) {
// filter excluded patterns here to only use those matching $dir
// exclude-from-classmap patterns are all realpath'd so we can only filter them if $dir exists so that realpath($dir) will work
// if $dir does not exist, it should anyway not find anything there so no trouble
if (file_exists($dir)) {
// transform $dir in the same way that exclude-from-classmap patterns are transformed so we can match them against each other
$dirMatch = preg_quote(strtr(realpath($dir), '\\', '/'));
foreach ($excluded as $index => $pattern) {
// extract the constant string prefix of the pattern here, until we reach a non-escaped regex special character
$pattern = preg_replace('{^(([^.+*?\[^\]$(){}=!<>|:\\\\#-]+|\\\\[.+*?\[^\]$(){}=!<>|:#-])*).*}', '$1', $pattern);
// if the pattern is not a subset or superset of $dir, it is unrelated and we skip it
if (0 !== strpos($pattern, $dirMatch) && 0 !== strpos($dirMatch, $pattern)) {
unset($excluded[$index]);
}
}
}
$excluded = $excluded ? '{(' . implode('|', $excluded) . ')}' : null;
}
return ClassMapGenerator::createMap($dir, $excluded, $showAmbiguousWarning ? $this->io : null, $namespaceFilter, $autoloadType, $scannedFiles);
}
@ -458,7 +481,7 @@ EOF;
if (isset($autoloads['classmap'])) {
$excluded = null;
if (!empty($autoloads['exclude-from-classmap'])) {
$excluded = '{(' . implode('|', $autoloads['exclude-from-classmap']) . ')}';
$excluded = $autoloads['exclude-from-classmap'];
}
$scannedFiles = array();

View File

@ -51,7 +51,7 @@ class ClassMapGenerator
* Iterate over all files in the given directory searching for classes
*
* @param \Iterator|string $path The path to search in or an iterator
* @param string $excluded Regex that matches against the file path that exclude from the classmap.
* @param string $excluded Regex that matches file paths to be excluded from the classmap
* @param IOInterface $io IO object
* @param string $namespace Optional namespace prefix to filter by
* @param string $autoloadType psr-0|psr-4 Optional autoload standard to use mapping rules

View File

@ -1377,9 +1377,9 @@ EOF;
$package->setAutoload(array(
'psr-0' => array('Foo' => '../path/../src'),
'psr-4' => array('Acme\Foo\\' => '../path/../src-psr4'),
'classmap' => array('../classmap'),
'classmap' => array('../classmap', '../classmap2/subdir', 'classmap3', 'classmap4'),
'files' => array('../test.php'),
'exclude-from-classmap' => array('./../classmap/excluded'),
'exclude-from-classmap' => array('./../classmap/excluded', '../classmap2', 'classmap3/classes.php', 'classmap4/*/classes.php'),
));
$this->repository->expects($this->once())
@ -1388,9 +1388,15 @@ EOF;
$this->fs->ensureDirectoryExists($this->workingDir.'/src/Foo');
$this->fs->ensureDirectoryExists($this->workingDir.'/classmap/excluded');
$this->fs->ensureDirectoryExists($this->workingDir.'/classmap2/subdir');
$this->fs->ensureDirectoryExists($this->workingDir.'/working-dir/classmap3');
$this->fs->ensureDirectoryExists($this->workingDir.'/working-dir/classmap4/foo/');
file_put_contents($this->workingDir.'/src/Foo/Bar.php', '<?php namespace Foo; class Bar {}');
file_put_contents($this->workingDir.'/classmap/classes.php', '<?php namespace Foo; class Foo {}');
file_put_contents($this->workingDir.'/classmap/excluded/classes.php', '<?php namespace Foo; class Boo {}');
file_put_contents($this->workingDir.'/classmap2/subdir/classes.php', '<?php namespace Foo; class Boo2 {}');
file_put_contents($this->workingDir.'/working-dir/classmap3/classes.php', '<?php namespace Foo; class Boo3 {}');
file_put_contents($this->workingDir.'/working-dir/classmap4/foo/classes.php', '<?php namespace Foo; class Boo4 {}');
file_put_contents($this->workingDir.'/test.php', '<?php class Foo {}');
$this->generator->dump($this->config, $this->repository, $package, $this->im, 'composer', true, '_14');