private function createClassmapIterator(
        iterable $classmap,
        iterable $exclude = []
    ): Iterator {
        $files = new AppendIterator();

        foreach ($classmap as $directory) {
            if (!is_dir($directory)) {
                continue;
            }

            $files->append(
                new RecursiveIteratorIterator(
                    new RecursiveDirectoryIterator($directory)
                )
            );
        }

        return new class ($files, $this->preparePattern(...$exclude)) extends FilterIterator {
            /** @var string|null */
            private $excludePattern;

            /**
             * Constructor.
             *
             * @param Iterator    $iterator
             * @param string|null $excludePattern
             */
            public function __construct(
                Iterator $iterator,
                ?string $excludePattern
            ) {
                $this->excludePattern = $excludePattern;

                parent::__construct($iterator);
            }

            /**
             * Check whether the current element of the iterator is acceptable.
             *
             * @return bool
             */
            public function accept(): bool
            {
                /** @var SplFileInfo $file */
                $file = $this->getInnerIterator()->current();

                return (
                    $file->isFile()
                    && (
                        $this->excludePattern === null
                        ?: !preg_match(
                            $this->excludePattern,
                            str_replace('\\', '/', $file->getRealPath())
                        )
                    )
                );
            }
        };
    }