public function fix(CSConfigInterface $config, $dryRun = false, $diff = false)
    {
        $changed = array();
        $fixers = $config->getFixers();

        $this->stopwatch->openSection();

        $fileCacheManager = new FileCacheManager(
            $config->usingCache(),
            $config->getCacheFile(),
            $config->getRules()
        );

        $checkers = [];
        $messageCacheManager = null;
        if ($config instanceof ConfigInterface) {
            $checkers = $config->getCheckers();
            $messageCacheManager = new FileMessageCacheManager(
                $config->usingCache(),
                $config->getCheckerCacheFile(),
                array_map('get_class', $config->getCheckers())
            );
        }

        /** @var \SplFileInfo $file */
        foreach ($config->getFinder() as $file) {
            if ($file->isDir() || $file->isLink()) {
                continue;
            }

            $this->stopwatch->start($this->getFileRelativePathname($file));

            $relativeFile = $this->getFileRelativePathname($file);
            if ($fixInfo = $this->fixFile($file, $fixers, $dryRun, $diff, $fileCacheManager, $checkers, $messageCacheManager)) {
                $changed[$relativeFile] = $fixInfo;
            } elseif ($messageCacheManager->hasMessage($this->getFileRelativePathname($file))) {
                $changed[$relativeFile] = array(
                    'checkMessages' => $messageCacheManager->getMessage($relativeFile),
                );
            }

            $this->stopwatch->stop($this->getFileRelativePathname($file));
        }

        $this->stopwatch->stopSection('fixFile');

        return $changed;
    }