src/Context/Code/SourceCodeManager.php
public function yieldSourceFiles(string $fileNameRegex = NULL, array $searchPaths = NULL) {
        $loadSearchPathIfNeeded = function($path, $name) {
            if(!isset($this->sourceFiles[$name])) {
                $this->sourceFiles[$name] = [];

                $iterateOverDirectory = function(RecursiveDirectoryIterator $iterator) use (&$iterateOverDirectory) {
                    /** @var SplFileInfo $item */
                    foreach($iterator as $item) {
                        $file = new SourceFile($item);
                        if($this->shouldIncludeFilename($file)) {
                            if($item->isFile())
                                yield (string)$file => $file;
                            elseif($iterator->hasChildren(true)) {
                                yield from $iterateOverDirectory($iterator->getChildren());
                            }
                        } else {
                            $this->excludedFiles[ (string)$file ] = $file;
                        }
                    }
                };

                $iterator = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS | RecursiveDirectoryIterator::FOLLOW_SYMLINKS);

                foreach($iterateOverDirectory($iterator) as $fn => $file) {
                    $this->sourceFiles[$name][$fn] = $file;
                }
            }
        };

        $addSrcDir = function($dirsOrDir, $kind) use (&$sources, $loadSearchPathIfNeeded) {
            $notFound = function($value) {
                trigger_error("Search path $value not found", E_USER_WARNING);
            };

            if(is_array($dirsOrDir)) {
                foreach($dirsOrDir as $ss) {
                    if(is_dir($ss))
                        $loadSearchPathIfNeeded($ss, $kind);
                    else
                        $notFound($ss);
                }
            }
            elseif(is_dir($dirsOrDir))
               $loadSearchPathIfNeeded($dirsOrDir, $kind);
            else
                $notFound($dirsOrDir);
        };


        if(NULL === $searchPaths) {
            $searchPaths = [];

            foreach($this->getDefaultSearchPaths() as $name => $dirsOrDir) {
                if($dirsOrDir)
                    $addSrcDir($dirsOrDir, $name);
                $searchPaths[] = $name;
            }
        } else {
            $defaults = $this->getDefaultSearchPaths();

            foreach($searchPaths as $key => $value) {
                if(is_numeric($key))
                    $key = $value;

                if(isset($defaults[$value])) {
                    $value = $defaults[$value];
                }

                $addSrcDir($value, $key);
            }
        }


        foreach($this->sourceFiles as $bank => $files) {
            if(!in_array($bank, $searchPaths))
                continue;

            foreach($files as $fileName => $file) {
                if(NULL == $fileNameRegex || preg_match($fileNameRegex, basename($fileName)))
                    yield $fileName => $file;
            }
        }
    }
public function yieldSourceFiles(string $fileNameRegex = NULL, array $searchPaths = NULL) {
        $loadSearchPathIfNeeded = function($path, $name) {
            if(!isset($this->sourceFiles[$name])) {
                $this->sourceFiles[$name] = [];

                $iterateOverDirectory = function(RecursiveDirectoryIterator $iterator) use (&$iterateOverDirectory) {
                    /** @var SplFileInfo $item */
                    foreach($iterator as $item) {
                        $file = new SourceFile($item);
                        if($this->shouldIncludeFilename($file)) {
                            if($item->isFile())
                                yield (string)$file => $file;
                            elseif($iterator->hasChildren(true)) {
                                yield from $iterateOverDirectory($iterator->getChildren());
                            }
                        } else {
                            $this->excludedFiles[ (string)$file ] = $file;
                        }
                    }
                };

                $iterator = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS | RecursiveDirectoryIterator::FOLLOW_SYMLINKS);

                foreach($iterateOverDirectory($iterator) as $fn => $file) {
                    $this->sourceFiles[$name][$fn] = $file;
                }
            }
        };

        $addSrcDir = function($dirsOrDir, $kind) use (&$sources, $loadSearchPathIfNeeded) {
            $notFound = function($value) {
                trigger_error("Search path $value not found", E_USER_WARNING);
            };

            if(is_array($dirsOrDir)) {
                foreach($dirsOrDir as $ss) {
                    if(is_dir($ss))
                        $loadSearchPathIfNeeded($ss, $kind);
                    else
                        $notFound($ss);
                }
            }
            elseif(is_dir($dirsOrDir))
               $loadSearchPathIfNeeded($dirsOrDir, $kind);
            else
                $notFound($dirsOrDir);
        };


        if(NULL === $searchPaths) {
            $searchPaths = [];

            foreach($this->getDefaultSearchPaths() as $name => $dirsOrDir) {
                if($dirsOrDir)
                    $addSrcDir($dirsOrDir, $name);
                $searchPaths[] = $name;
            }
        } else {
            $defaults = $this->getDefaultSearchPaths();

            foreach($searchPaths as $key => $value) {
                if(is_numeric($key))
                    $key = $value;

                if(isset($defaults[$value])) {
                    $value = $defaults[$value];
                }

                $addSrcDir($value, $key);
            }
        }


        foreach($this->sourceFiles as $bank => $files) {
            if(!in_array($bank, $searchPaths))
                continue;

            foreach($files as $fileName => $file) {
                if(NULL == $fileNameRegex || preg_match($fileNameRegex, basename($fileName)))
                    yield $fileName => $file;
            }
        }
    }
Yields all source files found in declared directories that match the passed regex.
NOTE: The first call takes longer to iterate over all source directories collecting the source files.

@param string $fileNameRegex If null, yields all source files
@param array $searchPaths Define in which search paths to look for files
@return Generator