diff --git a/src/Symfony/Component/ExpressionLanguage/ExpressionFunction.php b/src/Symfony/Component/ExpressionLanguage/ExpressionFunction.php index 7408ff2fcf..18f7296d3e 100644 --- a/src/Symfony/Component/ExpressionLanguage/ExpressionFunction.php +++ b/src/Symfony/Component/ExpressionLanguage/ExpressionFunction.php @@ -84,12 +84,12 @@ class ExpressionFunction throw new \InvalidArgumentException(sprintf('An expression function name must be defined when PHP function "%s" is namespaced.', $phpFunctionName)); } - $compiler = function () use ($phpFunctionName) { - return sprintf('\%s(%s)', $phpFunctionName, implode(', ', \func_get_args())); + $compiler = function (...$args) use ($phpFunctionName) { + return sprintf('\%s(%s)', $phpFunctionName, implode(', ', $args)); }; - $evaluator = function () use ($phpFunctionName) { - return $phpFunctionName(...\array_slice(\func_get_args(), 1)); + $evaluator = function ($p, ...$args) use ($phpFunctionName) { + return $phpFunctionName(...$args); }; return new self($expressionFunctionName ?: end($parts), $compiler, $evaluator); diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php index 49c6f70d62..35c568e71e 100644 --- a/src/Symfony/Component/Filesystem/Filesystem.php +++ b/src/Symfony/Component/Filesystem/Filesystem.php @@ -717,14 +717,16 @@ class Filesystem } /** + * @param mixed ...$args + * * @return mixed */ - private static function box(callable $func) + private static function box(callable $func, ...$args) { self::$lastError = null; set_error_handler(__CLASS__.'::handleError'); try { - $result = $func(...\array_slice(\func_get_args(), 1)); + $result = $func(...$args); restore_error_handler(); return $result; diff --git a/src/Symfony/Component/Finder/Finder.php b/src/Symfony/Component/Finder/Finder.php index 65154ef2f2..b5a3b964db 100644 --- a/src/Symfony/Component/Finder/Finder.php +++ b/src/Symfony/Component/Finder/Finder.php @@ -20,6 +20,7 @@ use Symfony\Component\Finder\Iterator\DepthRangeFilterIterator; use Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator; use Symfony\Component\Finder\Iterator\FilecontentFilterIterator; use Symfony\Component\Finder\Iterator\FilenameFilterIterator; +use Symfony\Component\Finder\Iterator\LazyIterator; use Symfony\Component\Finder\Iterator\SizeRangeFilterIterator; use Symfony\Component\Finder\Iterator\SortableIterator; @@ -622,7 +623,9 @@ class Finder implements \IteratorAggregate, \Countable $iterator = new \AppendIterator(); foreach ($this->dirs as $dir) { - $iterator->append($this->searchInDirectory($dir)); + $iterator->append(new \IteratorIterator(new LazyIterator(function () use ($dir) { + return $this->searchInDirectory($dir); + }))); } foreach ($this->iterators as $it) { diff --git a/src/Symfony/Component/Finder/Iterator/LazyIterator.php b/src/Symfony/Component/Finder/Iterator/LazyIterator.php new file mode 100644 index 0000000000..9028facf7f --- /dev/null +++ b/src/Symfony/Component/Finder/Iterator/LazyIterator.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder\Iterator; + +/** + * @author Jérémy Derussé + */ +class LazyIterator implements \IteratorAggregate +{ + private $iteratorFactory; + + public function __construct(callable $iteratorFactory) + { + $this->iteratorFactory = $iteratorFactory; + } + + public function getIterator(): \Traversable + { + yield from ($this->iteratorFactory)(); + } +} diff --git a/src/Symfony/Component/Finder/Tests/Iterator/LazyIteratorTest.php b/src/Symfony/Component/Finder/Tests/Iterator/LazyIteratorTest.php new file mode 100644 index 0000000000..1a96c32d0b --- /dev/null +++ b/src/Symfony/Component/Finder/Tests/Iterator/LazyIteratorTest.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder\Tests\Iterator; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Finder\Iterator\LazyIterator; + +class LazyIteratorTest extends TestCase +{ + public function testLazy() + { + new LazyIterator(function () { + $this->markTestFailed('lazyIterator should not be called'); + }); + + $this->expectNotToPerformAssertions(); + } + + public function testDelegate() + { + $iterator = new LazyIterator(function () { + return new Iterator(['foo', 'bar']); + }); + + $this->assertCount(2, $iterator); + } + + public function testInnerDestructedAtTheEnd() + { + $count = 0; + $iterator = new LazyIterator(function () use (&$count) { + ++$count; + + return new Iterator(['foo', 'bar']); + }); + + foreach ($iterator as $x) { + } + $this->assertSame(1, $count); + foreach ($iterator as $x) { + } + $this->assertSame(2, $count); + } +} diff --git a/src/Symfony/Component/Intl/Tests/Locale/AbstractLocaleTest.php b/src/Symfony/Component/Intl/Tests/Locale/AbstractLocaleTest.php index cf991c9bcc..a3daecb59e 100644 --- a/src/Symfony/Component/Intl/Tests/Locale/AbstractLocaleTest.php +++ b/src/Symfony/Component/Intl/Tests/Locale/AbstractLocaleTest.php @@ -27,5 +27,10 @@ abstract class AbstractLocaleTest extends TestCase $this->assertSame('en_GB', $this->call('getDefault')); } - abstract protected function call($methodName); + /** + * @param mixed ...$args + * + * @return mixed + */ + abstract protected function call(string $methodName, ...$args); } diff --git a/src/Symfony/Component/Intl/Tests/Locale/LocaleTest.php b/src/Symfony/Component/Intl/Tests/Locale/LocaleTest.php index 80b3352e21..05ba7106eb 100644 --- a/src/Symfony/Component/Intl/Tests/Locale/LocaleTest.php +++ b/src/Symfony/Component/Intl/Tests/Locale/LocaleTest.php @@ -139,10 +139,8 @@ class LocaleTest extends AbstractLocaleTest $this->assertSame('en', $this->call('getDefault')); } - protected function call($methodName) + protected function call(string $methodName, ...$args) { - $args = \array_slice(\func_get_args(), 1); - return Locale::{$methodName}(...$args); } } diff --git a/src/Symfony/Component/Intl/Tests/Locale/Verification/LocaleTest.php b/src/Symfony/Component/Intl/Tests/Locale/Verification/LocaleTest.php index 45c90f6c0f..c0b1b26b62 100644 --- a/src/Symfony/Component/Intl/Tests/Locale/Verification/LocaleTest.php +++ b/src/Symfony/Component/Intl/Tests/Locale/Verification/LocaleTest.php @@ -29,10 +29,8 @@ class LocaleTest extends AbstractLocaleTest parent::setUp(); } - protected function call($methodName) + protected function call(string $methodName, ...$args) { - $args = \array_slice(\func_get_args(), 1); - return \Locale::{$methodName}(...$args); } }